Building a simple instrumentation file with channels

As seen in the last section, instrumentation are usually referred to with $ref from a network / station information file. This is a best practice, but it is not mandatory. It does allow for easier reuse.

The file starts as usual:

---
format_version: "0.1101"
revision:
   date: "2019-12-19"
   authors:
       - {$ref: "persons/Wayne_Crawford.person.yaml#person"}
       - {$ref: "person/Romuald_Daniel.person.yaml#person"}

Observe that we have added an author to the list of authors, and that lists are separated by dashes.

Equipment

The main part of the file is the instrumentation section. First, we have the equipment section, which details the manufacturer, model and serial number of the instrumentation.

instrumentation:

   equipment:
       model: "BBOBS1"
       type: "Broadband Ocean Bottom Seismometer"
       description: "LCHEAPO 2000 BBOBS 2012-present"
       manufacturer: "Scripps Inst. Oceanography - INSU"
       vendor: "Scripps Inst. Oceanography - UNSU"

As most OBS are assembled with parts from different manufacturers, the only required fields of the equipment section are the type (a free-form text field) and the description.

channels and channel default

Next, we have channels. A channel is the combination of an instrument (sensor + optional preamplifier + datalogger) and an orientation. Orientation codes are explained here in the Geographic orientation subsource codes section. They are dictated by FDSN standards.

The channels are the actual channels in the instrumentation. They all have string labels, which are usually numbers giving their sequence/code within the data acquistion system (not the FDSN channel name). These must be in quotes as they are not keys in the obsinfo syntax.

To minimize duplication, a default channel declares common elements to all channels. This is not an actual channel, it’s just a place to specify default attributes. If an attribute is not specified in an actual channel but exists in the default channel then it will be added to the final configuration of the channel.

Let’s see an example:

channels:
    default:
        sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
        preamplifier:
            base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}
        datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
     "1": {orientation: {"2": {azimuth.deg: {value: 90},  dip.deg: {value: 0}}}}
     "2":
          orientation:
                  "1":
                      azimuth.deg: {value: 0, uncertainty: 9}
                      dip.deg: {value: 0}

This code specifies two channels as a dictionary. Each channel specifies the two or three instrument components and the orientation_code. The orientation key will become the third character in the SEED code identification (see SeedCodes, and thus must follow FDSN standards.

Again, these are real, physical channels. default` specifies three instrument components: sensor, preamplifier and datalogger These will be applied to all channels that do not specify these values themselves All three files reference an information file in separate directory, which, in the example, are just under the DATAPATH directory. So the above could also be typed:

channels:
       "1":
           sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
           preamplifier: {base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}}
           datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
           orientation: {"2": {azimuth.deg: {value: 90},  dip.deg: {value: 0}}}
       "2":
           sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
           preamplifier: {base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}}
           datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
           orientation:
                    "1":
                        azimuth.deg: {value: 0, uncertainty: 9}
                        dip.deg: {value: 0}

Observe that in this case we have used curly parentheses to specify elements in a dictionary. They can be left out, letting simple indentation do the job of determining the items.

If a channel specifies any field that is also in the default, it will override that field. Let’s assume we have a 4th channel 4 with a hydrophone:

"4":
    sensor: {base: {$ref: "sensors/SIO_DPG.sensor.yaml#sensor"}}
    preamplifier: {base: {$ref: "preamplifiers/LCHEAPO_DPG.preamplifier.yaml#preamplifier"}}
    orientation: {"H": {{azimuth.deg: {value: 0},  dip.deg: {value: 90}}}

Then, assuming the same default` field as above, the result of channel 4 would be:

"4":
    sensor: {base: {$ref: "sensors/SIO_DPG.sensor.yaml#sensor"}}
    preamplifier: {base: {$ref: "preamplifiers/LCHEAPO_DPG.preamplifier.yaml#preamplifier"}}
    datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
    orientation: {"H": {azimuth.deg: [0, 0],  dip.deg: [90, 0]}}

Only datalogger retaints the default value. The other components are overriden with the values specified in channel 4.

Orientation Codes

Orientation codes are a FDSN standard. By convention, if the orientation code is N, E or Z, these represent the regular coordinates in space , within five degrees of the actual directions. So N corresponds to an azimuth of 0º and a dip of 0º, E corresponds to an azimuth of 90º and a dip of 0º, and Z corresponds to an azimuth of 0º and a dip of -90º (the positive Z direction is upwards). However, if 1, 2 or 3 are specified, these represent three orthogonal directions but not necessarily coincidental with the regular coordinates, so an azimuth and a dip must be specified, depending on the type of code. The same is true of the H (hydrophone) code. See reference above for details.

Note also how we freely mix the two syntactic ways of specifying a dictionary in YAML, either with curly parentheses or with indentation. You can use whatever syntax you prefer.

The order that you enter the keys sensor. preamplifier and datalogger is arbitrary, but their stages will always be processed from input (physical) to the output (stored): that is, first sensor, then preamplifier, then datalogger. You should specify stages within each of these instrument components in the same order, from top to bottom. For example, a sensor with an internal amplifier should have the sensor as the top stage and the amplifier below. obsinfo will check that the output_units of each stage match the input_units of the stage below.

Configurations

We have learned how to specify default components through the default and how to override them. This is pretty flexible, but we can get more flexible still. This is done through configurations. Every element that specifies a base element (instrumentation, location_base, instrument_components and stage) can also specify configurations that modify this base element. configuration` definitions can take any field at the base level and either overriding it or add to it. This is by selecting a configuration at the channel level. A configuration selection field can specify a configuration for each of the three instrument components in a channel: sensor, preamplifier and datalogger. The configuration must be defined. Below, we add two things to the previous example: a default preamplifier configuration and a channel 3 that overrides this configuration.

channels:
     default:
         sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
         preamplifier:
             base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}
             configuration: "0.225x"
         datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
     "1": {orientation: {"2": {azimuth.deg: {value: 90},  dip.deg: {value: 0}}}}
     "2":
          orientation:
                  "1":
                      azimuth.deg: {value: 0, uncertainty: 9}
                      dip.deg: {value: 0}
     "3":
         orientation: {"Z": {azimuth.deg: 0, dip.deg: -90}}
         preamplifier: {configuration: "1x"}
     "4":
         sensor: {base: {$ref: "sensors/SIO_DPG.sensor.yaml#sensor"}}
         preamplifier: {base: {$ref: "preamplifiers/LCHEAPO_DPG.preamplifier.yaml#preamplifier"}}
         orientation: {"H": {{azimuth.deg: {value: 0},  dip.deg: {value: 90}}}

This code specifies configurations, which can be for sensor, preamplifier or datalogger; in this case, simply for the preamplifier. The configuration selected is called “0.225x” and is a gain multiplier, as will be seen shortly. This value will be used in all channels, except channel 3, where it will be changed to “1x”. In the end, the four channels specified above will be the same as typing this:

channels:
    "1":
        sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
        preamplifier:
            base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}
            configuration: "0.225x"
        datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
        orientation: {"2": {azimuth.deg: {value: 90},  dip.deg: {value: 0}}}
    "2":
        sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
        preamplifier:
            base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}
            configuration: "0.225x"
        datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
        orientation:
             "1":
                 azimuth.deg: {value: 0, uncertainty: 9}
                 dip.deg: {value: 0}
    "3":
        sensor: {base: {$ref: "sensors/NANOMETRICS_T240_SINGLESIDED.sensor.yaml#sensor"}}
        preamplifier:
            base: {$ref: "preamplifiers/LCHEAPO_BBOBS.preamplifier.yaml#preamplifier"}
            configuration: "1x"
        datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
        orientation: {"Z": {azimuth.deg: 0, dip.deg: -90}}
    "4":
        sensor: {base: {$ref: "sensors/SIO_DPG.sensor.yaml#sensor"}}
        preamplifier: {base: {$ref: "preamplifiers/LCHEAPO_DPG.preamplifier.yaml#preamplifier"}}
        datalogger: {base: {$ref: "dataloggers/LC2000.datalogger.yaml#datalogger"}}
        orientation_code: {"H": {azimuth.deg: [0, 0],  dip.deg: [90, 0]}}

Channel modifications

As seen in the last chapter, channel configurations can also be modified. The rationale behind this feature is that the user has a stable database of instruments which may occasionally undergo last-minute or one-time modifications, for example, when a malfunctioning sensor is replaced by another. obsinfo is conceived to reflect this malleability. Channel modifications are indicated at the station level but can potentially change any field from instrumentation level down. This is a more complex topic that falls outside of this beginner’s tutorial. It will be treated in the Advanced Topics documentation.

Notes and extras

This file is complex, so it’s a good place to talk about notes and extras. These are optional fields. Notes can occur in any information file. They are documentation that can be used to remind users of the specifics of the information file. They will not be put into the StationXML to avoid clutter.

Extras are key:value pairs that document attributes that do not exist in the information file specification. They are put into StationXML comments. For this reason and to avoid clutter, they are only available at three levels: network, station and channel.

As an example, let’s assume we have an “octopus” sensor where the serial number of the sensor is not specified. This is because we have actually several sensors with different serial numbers, enclosed in spheres. How do we convey that information? There are two ways. One is in a list of notes at the end of the sensor file:

notes:
   - "INSU-IPGP OBS park sphere sensor pairs are: Sphere01-133, Sphere02-132,"
   - "Sphere03-134, Sphere04-138, Sphere05-137, Sphere06-830, Sphere07-136,"
   - "Sphere08-829, Sphere09-826"

The other YAML syntax for lists is possible too:


notes: [“INSU-IPGP OBS park sphere sensor pairs are: Sphere01-133, Sphere02-132,”,

“Sphere03-134, Sphere04-138, Sphere05-137, Sphere06-830, Sphere07-136,”, “Sphere08-829, Sphere09-826”]

This associates serial numbers to the spheres. However, this will not be reflected in the StationXML file. Alternatively, we can use the extras dictionary, not in the sensor file but in the instrumentation one:

extras:
   "Description": "Serial numbers for sensors"
   "Sphere03": "134"
   "Sphere04": "138"
   "Sphere05": "137"
   "Sphere06": "830"
   "Sphere07": "136"
   "Sphere08": "829"
   "Sphere09": "826"

Complete example

This is a real file. The order of the fields may be different than the examples above. As previoiusly mentioned, this is immaterial.


— format_version: “0.111” revision:

authors:
  • {$ref: “persons/Wayne_Crawford.person.yaml#person”}

date: “2019-12-19”

subnetwork:
operators:
  • {$ref: “operators/INSU-IPGP.operator.yaml#operator”}

network:

$ref: “networks/EMSO-AZORES.network.yaml#network”

stations:
“BB_1”:

site: “My favorite site” start_date: “2011-04-23T10:00:00” end_date: “2011-05-28T15:37:00” location_code: “00” locations:

“00”:

base: {$ref: ‘location_bases/INSU-IPGP.location_base.yaml#location_base’} configuration: “BUC_DROP” position: {lon: -32.234, lat: 37.2806, elev: -1950}

instrumentation:

base: {$ref: “instrumentations/BBOBS1_pre2012.instrumentation_base.yaml#instrumentation_base”} configuration: “SN07” modifications:

datalogger: {configuration: “62.5sps”}

processing:
  • clock_correction_linear:

    base: {$ref: “timing_bases/Seascan_GNSS.timing_base.yaml#timing_base”} start_sync_reference: “2015-04-23T11:20:00” end_sync_reference: “2016-05-27T14:00:00.2450” end_sync_instrument: “2016-05-27T14:00:00”

“BB_2”:

site: “My other favorite site” start_date: “2015-04-23T10:00:00Z” end_date: “2016-05-28T15:37:00Z” location_code: “00” notes: [“example of deploying with a different sphere”] instrumentation:

base: {$ref: “instrumentations/BBOBS1_2012+.instrumentation_base.yaml#instrumentation_base”} serial_number: “06” modifications:

datalogger: {configuration: “62.5sps”, equipment: {serial_number: “26”}} preamplifier: {equipment: {serial_number: “26”}}

channel_modifications:

“1-”: {sensor: {configuration: “Sphere08”}} “2-”: {sensor: {configuration: “Sphere08”}} “Z-”: {sensor: {configuration: “Sphere08”}} “H-”: {sensor: {configuration: “5004”}}

locations:
“00”:

base: {$ref: ‘location_bases/INSU-IPGP.location_base.yaml#location_base’} configuration: “BUC_DROP” position: {lon: -32.29756, lat: 37.26049, elev: -1887}

processing:
  • clock_correction_linear:

    base: {$ref: “timing_bases/Seascan_GNSS.timing_base.yaml#timing_base”} start_sync_reference: “2015-04-22T12:24:00” end_sync_reference: “2016-05-28T15:35:00.3660” end_sync_instrument: “2016-05-28T15:35:02”