예제 #1
0
    def test_read_nlloc_with_pick_seed_id_lookup(self):
        # create some bogus metadata for lookup
        cha = Channel('HHZ', '00', 0, 0, 0, 0)
        sta = Station('HM02', 0, 0, 0, channels=[cha])
        cha = Channel('HHZ', '10', 0, 0, 0, 0)
        sta2 = Station('YYYY', 0, 0, 0, channels=[cha])
        net = Network('XX', stations=[sta, sta2])
        # second network with non matching data
        cha = Channel('HHZ', '00', 0, 0, 0, 0)
        sta = Station('ABCD', 0, 0, 0, channels=[cha])
        cha = Channel('HHZ', '10', 0, 0, 0, 0)
        sta2 = Station('EFGH', 0, 0, 0, channels=[cha])
        net2 = Network('YY', stations=[sta, sta2])

        inv = Inventory(networks=[net, net2], source='')

        filename = get_example_file("nlloc_custom.hyp")
        # we get some warnings since we only provide sufficient metadata for
        # one pick
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            cat = read_events(filename, format="NLLOC_HYP", inventory=inv)
        self.assertEqual(len(cat), 1)
        for pick in cat[0].picks:
            wid = pick.waveform_id
            if wid.station_code == 'HM02':
                self.assertEqual(wid.network_code, 'XX')
                self.assertEqual(wid.location_code, '')
            else:
                self.assertEqual(wid.network_code, '')
                self.assertEqual(wid.location_code, None)
예제 #2
0
    def test_get_response(self):
        response_n1_s1 = Response('RESPN1S1')
        response_n1_s2 = Response('RESPN1S2')
        response_n2_s1 = Response('RESPN2S1')
        channels_n1_s1 = [
            Channel(code='BHZ',
                    location_code='',
                    latitude=0.0,
                    longitude=0.0,
                    elevation=0.0,
                    depth=0.0,
                    response=response_n1_s1)
        ]
        channels_n1_s2 = [
            Channel(code='BHZ',
                    location_code='',
                    latitude=0.0,
                    longitude=0.0,
                    elevation=0.0,
                    depth=0.0,
                    response=response_n1_s2)
        ]
        channels_n2_s1 = [
            Channel(code='BHZ',
                    location_code='',
                    latitude=0.0,
                    longitude=0.0,
                    elevation=0.0,
                    depth=0.0,
                    response=response_n2_s1)
        ]
        stations_1 = [
            Station(code='N1S1',
                    latitude=0.0,
                    longitude=0.0,
                    elevation=0.0,
                    channels=channels_n1_s1),
            Station(code='N1S2',
                    latitude=0.0,
                    longitude=0.0,
                    elevation=0.0,
                    channels=channels_n1_s2),
            Station(code='N2S1',
                    latitude=0.0,
                    longitude=0.0,
                    elevation=0.0,
                    channels=channels_n2_s1)
        ]
        network = Network('N1', stations=stations_1)

        response = network.get_response('N1.N1S1..BHZ',
                                        UTCDateTime('2010-01-01T12:00'))
        self.assertEqual(response, response_n1_s1)
        response = network.get_response('N1.N1S2..BHZ',
                                        UTCDateTime('2010-01-01T12:00'))
        self.assertEqual(response, response_n1_s2)
        response = network.get_response('N1.N2S1..BHZ',
                                        UTCDateTime('2010-01-01T12:00'))
        self.assertEqual(response, response_n2_s1)
def get_inventory(stations,
                  depths,
                  lat=50.45031,
                  long=-112.12087,
                  elevation=779.0,
                  dip1=0,
                  azi1=0,
                  dip2=0,
                  azi2=90,
                  dip3=90,
                  azi3=0):
    inv = Inventory(networks=[], source="Genevieve")
    net = Network(code="BH",
                  stations=[],
                  description=" ",
                  start_date=UTCDateTime(2019, 1, 1))
    for i, station in enumerate(stations):
        dep = depths[i]
        sta = Station(code=station,
                      latitude=lat,
                      longitude=long,
                      elevation=elevation,
                      creation_date=UTCDateTime(2019, 1, 1),
                      site=Site(name="borehole"))
        chaz = Channel(code="DPZ",
                       location_code="",
                       latitude=lat,
                       longitude=long,
                       elevation=elevation,
                       azimuth=azi3,
                       dip=dip3,
                       depth=dep,
                       sample_rate=500)
        cha1 = Channel(code="DPN",
                       location_code="",
                       latitude=lat,
                       longitude=long,
                       elevation=elevation,
                       azimuth=azi1,
                       dip=dip1,
                       depth=dep,
                       sample_rate=500)
        cha2 = Channel(code="DPE",
                       location_code="",
                       latitude=lat,
                       longitude=long,
                       elevation=elevation,
                       azimuth=azi2,
                       dip=dip2,
                       depth=dep,
                       sample_rate=500)
        sta.channels.append(chaz)
        sta.channels.append(cha1)
        sta.channels.append(cha2)
        net.stations.append(sta)
    inv.networks.append(net)
    return inv
예제 #4
0
    def test_get_response(self):
        response_n1_s1 = Response('RESPN1S1')
        response_n1_s2 = Response('RESPN1S2')
        response_n2_s1 = Response('RESPN2S1')
        channels_n1_s1 = [Channel(code='BHZ',
                                  location_code='',
                                  latitude=0.0,
                                  longitude=0.0,
                                  elevation=0.0,
                                  depth=0.0,
                                  response=response_n1_s1)]
        channels_n1_s2 = [Channel(code='BHZ',
                                  location_code='',
                                  latitude=0.0,
                                  longitude=0.0,
                                  elevation=0.0,
                                  depth=0.0,
                                  response=response_n1_s2)]
        channels_n2_s1 = [Channel(code='BHZ',
                                  location_code='',
                                  latitude=0.0,
                                  longitude=0.0,
                                  elevation=0.0,
                                  depth=0.0,
                                  response=response_n2_s1)]
        stations_1 = [Station(code='N1S1',
                              latitude=0.0,
                              longitude=0.0,
                              elevation=0.0,
                              channels=channels_n1_s1),
                      Station(code='N1S2',
                              latitude=0.0,
                              longitude=0.0,
                              elevation=0.0,
                              channels=channels_n1_s2)]
        stations_2 = [Station(code='N2S1',
                              latitude=0.0,
                              longitude=0.0,
                              elevation=0.0,
                              channels=channels_n2_s1)]
        networks = [Network('N1', stations=stations_1),
                    Network('N2', stations=stations_2)]
        inv = Inventory(networks=networks, source='TEST')

        response = inv.get_response('N1.N1S1..BHZ',
                                    UTCDateTime('2010-01-01T12:00'))
        assert response == response_n1_s1
        response = inv.get_response('N1.N1S2..BHZ',
                                    UTCDateTime('2010-01-01T12:00'))
        assert response == response_n1_s2
        response = inv.get_response('N2.N2S1..BHZ',
                                    UTCDateTime('2010-01-01T12:00'))
        assert response == response_n2_s1
예제 #5
0
def do_xml():
    nrl = NRL('http://ds.iris.edu/NRL/')
    datalogger_keys = ['REF TEK', 'RT 130 & 130-SMA', '1', '40']
    sensor_keys = ['Streckeisen', 'STS-2', '1500', '3 - installed 04/97 to present']

    response = nrl.get_response(sensor_keys=sensor_keys, datalogger_keys=datalogger_keys)

    channel = Channel(code='BHZ',
                      location_code='10',      # required
                      latitude=0,      # required
                      longitude=0,   # required
                      elevation=0.0,        # required
                      depth=0.,                # required
                      )

    channel.response = response
    station = Station(code='ABCD',
                      latitude=0,
                      longitude=0,
                      elevation=0.0,
                      creation_date=UTCDateTime(1970, 1, 1),          # required
                      site=Site(name='Fake Site'),  # required
                      channels=[channel],
                      )

    network = Network(code='XX',
                     stations=[station])
    inventory = Inventory(networks=[network], source="demo")

    inventory.write("Test.xml", format="stationxml", validate=True)
def create_inv(network_code, station_code, location_code, channel_code, isr,
               sf, u):
    writethisinv = Inventory(
        networks=[
            Network(code=network_code,
                    start_date=obspy.UTCDateTime('2007-01-01'),
                    stations=[
                        Station(
                            code=station_code,
                            latitude=1,
                            longitude=2,
                            elevation=3,
                            creation_date=obspy.UTCDateTime('2007-01-01'),
                            site=Site(name='site'),
                            channels=[
                                Channel(
                                    code=channel_code,
                                    location_code=location_code,
                                    start_date=obspy.UTCDateTime('2007-01-01'),
                                    latitude=1,
                                    longitude=2,
                                    elevation=3,
                                    depth=4,
                                    response=create_response(
                                        inputsamplerate=isr,
                                        scaling_factor=sf,
                                        units=u))
                            ])
                    ])
        ],
        source=
        'Joseph Farrugia, Ocean Networks Canada',  # The source should be the id whoever create the file.
        created=obspy.UTCDateTime(datetime.today()))
    return writethisinv
예제 #7
0
 def test_get_orientation(self):
     """
     Test extracting orientation
     """
     expected = {u'azimuth': 90.0, u'dip': 0.0}
     channels = [
         Channel(code='EHZ',
                 location_code='',
                 start_date=UTCDateTime('2007-01-01'),
                 latitude=47.737166999999999,
                 longitude=12.795714,
                 elevation=860.0,
                 depth=0.0,
                 azimuth=90.0,
                 dip=0.0)
     ]
     stations = [
         Station(code='RJOB',
                 latitude=0.0,
                 longitude=0.0,
                 elevation=0.0,
                 channels=channels)
     ]
     networks = [Network('BW', stations=stations)]
     inv = Inventory(networks=networks, source='TEST')
     # 1
     orientation = inv.get_orientation('BW.RJOB..EHZ',
                                       UTCDateTime('2010-01-01T12:00'))
     self.assertEqual(sorted(orientation.items()), sorted(expected.items()))
     # 2 - without datetime
     orientation = inv.get_orientation('BW.RJOB..EHZ')
     self.assertEqual(sorted(orientation.items()), sorted(expected.items()))
     # 3 - unknown SEED ID should raise exception
     self.assertRaises(Exception, inv.get_orientation, 'BW.RJOB..XXX')
예제 #8
0
    def set_channel(self):
        self.channels = []
        self.channels_raw = self.get_channels()
        p_datalogger = ()
        p_sensor = ()
        for channel in self.channels_raw:
            temp_channel = Channel(code=channel["code"],
                                   location_code=channel["location_code"],
                                   latitude=channel["latitude"],
                                   longitude=channel["longitude"],
                                   elevation=channel["elevation"],
                                   depth=channel["depth"],
                                   azimuth=channel["azimuth"],
                                   dip=channel["dip"],
                                   sample_rate=channel["sample_rate"])

            temp_list = []
            for value in channel["datalogger"].values():
                if not value is None:
                    temp_list.append(value)
            p_datalogger = tuple(temp_list)
            temp_list.clear()
            for value in channel["sensor"].values():
                if not value is None:
                    temp_list.append(value)
            p_sensor = tuple(temp_list)
            temp_channel.response = self.my_nrl.get_response(
                datalogger_keys=p_datalogger, sensor_keys=p_sensor)
            self.station.channels.append(temp_channel)
예제 #9
0
 def test_get_coordinates(self):
     """
     Test extracting coordinates
     """
     expected = {u'latitude': 47.737166999999999,
                 u'longitude': 12.795714,
                 u'elevation': 860.0,
                 u'local_depth': 0.0}
     channels = [Channel(code='EHZ',
                         location_code='',
                         start_date=UTCDateTime('2007-01-01'),
                         latitude=47.737166999999999,
                         longitude=12.795714,
                         elevation=860.0,
                         depth=0.0)]
     stations = [Station(code='RJOB',
                         latitude=0.0,
                         longitude=0.0,
                         elevation=0.0,
                         channels=channels)]
     network = Network('BW', stations=stations)
     # 1
     coordinates = network.get_coordinates('BW.RJOB..EHZ',
                                           UTCDateTime('2010-01-01T12:00'))
     assert sorted(coordinates.items()) == sorted(expected.items())
     # 2 - without datetime
     coordinates = network.get_coordinates('BW.RJOB..EHZ')
     assert sorted(coordinates.items()) == sorted(expected.items())
     # 3 - unknown SEED ID should raise exception
     with pytest.raises(Exception):
         network.get_coordinates('BW.RJOB..XXX')
예제 #10
0
파일: io.py 프로젝트: weijias-fork/SeisNN
def write_channel_coordinates(pkl_list,
                              pkl_output_dir,
                              inventory,
                              kml_output_dir=None,
                              remove_pkl_dir=False):
    if remove_pkl_dir:
        shutil.rmtree(pkl_output_dir, ignore_errors=True)
    os.makedirs(pkl_output_dir, exist_ok=True)

    for i, file in enumerate(pkl_list):
        trace = read(file).traces[0]
        network = trace.stats.network
        station = trace.stats.station
        channel = trace.stats.channel
        location = trace.stats.location

        for net in inventory:
            if not fnmatch.fnmatch(net.code, network):
                continue

            for sta in net:
                if not fnmatch.fnmatch(sta.code, station):
                    continue

                lat = sta.latitude
                lon = sta.longitude
                elev = sta.elevation
                depth = Distance(0)

                trace.stats.coordinates = ({'latitude': lat, 'longitude': lon})
                trace.stats.elevation = elev
                trace.stats.depth = depth

                time_stamp = trace.stats.starttime.isoformat()
                trace.write(pkl_output_dir + '/' + time_stamp +
                            trace.get_id() + ".pkl",
                            format="PICKLE")
                print(trace.get_id() + " latitude: " + str(lat)[0:5] +
                      " longitude: " + str(lon)[0:6])

                ch_name = []
                for ch in sta.channels:
                    ch_name.append(ch.code)

                if channel not in ch_name:
                    chan = Channel(code=channel,
                                   location_code=location,
                                   latitude=lat,
                                   longitude=lon,
                                   elevation=elev,
                                   depth=depth)
                    sta.channels.append(chan)

    if kml_output_dir:
        os.makedirs(kml_output_dir, exist_ok=True)
        inventory.write(kml_output_dir + "/" + inventory.networks[0].code +
                        ".kml",
                        format="KML")
예제 #11
0
def _channel_from_stats(stats):
    if stats.standard.units in UNITS:
        units = UNITS[stats.standard.units]
    else:
        units = ''
    instrument = stats.standard.instrument
    serialnum = stats.standard.sensor_serial_number
    if len(instrument) or len(serialnum):
        equipment = Equipment(type=instrument,
                              serial_number=serialnum)
    else:
        equipment = None
    depth = 0.0
    azimuth = None
    c1 = 'horizontal_orientation' in stats.standard
    c2 = c1 and not np.isnan(stats.standard.horizontal_orientation)
    if c2:
        azimuth = stats.standard.horizontal_orientation
    else:
        azimuth = 0

    if not (azimuth >= 0 and azimuth <= 360):
        azimuth = 0

    response = None
    if 'response' in stats:
        response = stats['response']
    else:
        # we may have instrument sensitivity...
        frequency = 1 / stats['standard']['instrument_period']
        units = stats.standard.units
        if not np.isnan(stats['standard']['instrument_sensitivity']):
            sens = stats['standard']['instrument_sensitivity']
        else:
            sens = 1.0
        sensitivity = InstrumentSensitivity(sens,
                                            frequency=frequency,
                                            input_units=units,
                                            output_units='COUNTS')
        response = Response(instrument_sensitivity=sensitivity)

    comments = Comment(stats.standard.comments)
    logging.debug('channel: %s' % stats.channel)
    channel = Channel(stats.channel,
                      stats.location,
                      stats.coordinates['latitude'],
                      stats.coordinates['longitude'],
                      stats.coordinates['elevation'],
                      depth,
                      azimuth=azimuth,
                      sample_rate=stats.sampling_rate,
                      storage_format=stats.standard.source_format,
                      calibration_units=units,
                      comments=[comments],
                      response=response,
                      sensor=equipment)
    return channel
예제 #12
0
def _channel_from_stats(stats):
    if stats.standard.units in UNITS:
        units = UNITS[stats.standard.units]
    else:
        units = ""
    instrument = stats.standard.instrument
    serialnum = stats.standard.sensor_serial_number
    if len(instrument) or len(serialnum):
        equipment = Equipment(type=instrument, serial_number=serialnum)
    else:
        equipment = None
    depth = 0.0
    azimuth = None
    c1 = "horizontal_orientation" in stats.standard
    c2 = c1 and not np.isnan(stats.standard.horizontal_orientation)
    if c2:
        azimuth = stats.standard.horizontal_orientation
    else:
        azimuth = 0

    if not (azimuth >= 0 and azimuth <= 360):
        azimuth = 0

    response = None
    if "response" in stats:
        response = stats["response"]
    else:
        # we may have instrument sensitivity...
        frequency = 1 / stats["standard"]["instrument_period"]
        units = stats.standard.units
        if not np.isnan(stats["standard"]["instrument_sensitivity"]):
            sens = stats["standard"]["instrument_sensitivity"]
        else:
            sens = 1.0
        sensitivity = InstrumentSensitivity(sens,
                                            frequency=frequency,
                                            input_units=units,
                                            output_units="COUNTS")
        response = Response(instrument_sensitivity=sensitivity)

    comments = Comment(stats.standard.comments)
    logging.debug(f"channel: {stats.channel}")
    channel = Channel(
        stats.channel,
        stats.location,
        stats.coordinates["latitude"],
        stats.coordinates["longitude"],
        stats.coordinates["elevation"],
        depth,
        azimuth=azimuth,
        sample_rate=stats.sampling_rate,
        calibration_units=units,
        comments=[comments],
        response=response,
        sensor=equipment,
    )
    return channel
예제 #13
0
def sac2asdf_hinet(sac_directory, cmt_path, output_path):
    with pyasdf.ASDFDataSet(output_path, mode="w", compression=None,
                            mpi=False) as ds:
        # read in eventxml
        event_xml = obspy.read_events(cmt_path)
        # add eventxml to ds
        ds.add_quakeml(event_xml)
        event = ds.events[0]
        # read in waves
        files = sorted(glob(join(sac_directory, "*")))
        inv = Inventory()  # pylint: disable=no-value-for-parameter
        net_inv = Network(code="N", stations=[])
        # * we should sort files based on the station names
        sta_collection = {}
        # * here we add the waveforms along with the process of building the inventory
        for each_file in files:
            tr = obspy.read(each_file)[0]
            # here we need to modify some stats' values
            net_sta = tr.stats.station
            net, sta = net_sta.split(".")
            tr.stats.network = net
            tr.stats.station = sta
            # we change the channel names U->HHZ N->HHN E->HHE
            channel_mapper = {"U": "HHZ", "N": "HHN", "E": "HHE"}
            try:
                tr.stats.channel = channel_mapper[tr.stats.channel]
            except KeyError:
                continue
            # we have to consider the time difference in Japan
            tr.stats.starttime = tr.stats.starttime - 9 * 60 * 60
            # * add the waveforms
            tr.data = np.require(tr.data, dtype="float32")
            ds.add_waveforms(tr, tag="raw", event_id=event)
            # * handle the stationxml
            cha = Channel(code=tr.stats.channel,
                          location_code="",
                          latitude=tr.stats.sac.stla,
                          longitude=tr.stats.sac.stlo,
                          elevation=tr.stats.sac.stel,
                          depth=0.0,
                          sample_rate=tr.stats.sampling_rate)
            if (sta in sta_collection):
                sta_collection[sta].channels.append(cha)
            else:
                sta_collection[sta] = Station(code=sta,
                                              latitude=tr.stats.sac.stla,
                                              longitude=tr.stats.sac.stlo,
                                              elevation=tr.stats.sac.stel)
                sta_collection[sta].channels.append(cha)
        # * now we can add all the sta to net
        for sta in sta_collection:
            if (len(sta_collection[sta].channels) == 3):
                net_inv.stations.append(sta_collection[sta])
        # * we can add net to station_xml
        inv.networks.append(net_inv)
        # * now we can add inv to asdf
        ds.add_stationxml(inv)
예제 #14
0
def _dataframe_to_station(statcode, station_df, instrument_register=None):
    """
    Convert Pandas dataframe with unique station code to obspy Station object.

    :param statcode: Station code
    :type statcode: str
    :param station_df: Dataframe containing records for a single station code.
    :type station_df: pandas.DataFrame conforming to table_format.TABLE_SCHEMA
    :param instrument_register: Dictionary of nominal instrument responses indexed by channel code, defaults to None
    :param instrument_register: dict of {str, Instrument(obspy.core.inventory.util.Equipment,
        obspy.core.inventory.response.Response)}, optional
    :return: Station object containing the station information from the dataframe
    :rtype: obspy.core.inventory.station.Station
    """
    station_data = station_df.iloc[0]
    st_start = station_data['StationStart']
    assert pd.notnull(st_start)
    st_start = utcdatetime.UTCDateTime(st_start)
    st_end = station_data['StationEnd']
    assert pd.notnull(st_end)
    st_end = utcdatetime.UTCDateTime(st_end)
    station = Station(statcode,
                      station_data['Latitude'],
                      station_data['Longitude'],
                      station_data['Elevation'],
                      start_date=st_start, creation_date=st_start,
                      end_date=st_end, termination_date=st_end,
                      site=Site(name=' '))
    for _, d in station_df.iterrows():
        ch_start = d['ChannelStart']
        ch_start = utcdatetime.UTCDateTime(ch_start) if not pd.isnull(ch_start) else None
        ch_end = d['ChannelEnd']
        ch_end = utcdatetime.UTCDateTime(ch_end) if not pd.isnull(ch_end) else None
        ch_code = d['ChannelCode']
        instrument = instrument_register[ch_code]
        if instrument is not None:
            sensor = instrument.sensor
            response = instrument.response
        elif 'LAST_RESORT' in instrument_register:
            last_resort = instrument_register['LAST_RESORT']
            sensor = last_resort.sensor
            response = last_resort.response
        else:
            sensor = None
            response = None
        cha = Channel(ch_code, '', float(d['Latitude']), float(d['Longitude']), float(d['Elevation']),
                      depth=0.0, azimuth=0.0, dip=-90.0, sample_rate=0.0, clock_drift_in_seconds_per_sample=0.0,
                      start_date=ch_start, end_date=ch_end, sensor=sensor, response=response)
        station.channels.append(cha)
    return station
예제 #15
0
def clone_inv(inv, net_name, sta_name):

    net = Network(
        # This is the network code according to the SEED standard.
        code=net_name,
        # A list of stations. We'll add one later.
        stations=[],
        #        description="A test stations.",
        # Start-and end dates are optional.
        #        start_date=obspy.UTCDateTime(2016, 1, 2))
    )

    sta = Station(
        # This is the station code according to the SEED standard.
        code=sta_name,
        latitude=inv[0][0].latitude,
        longitude=inv[0][0].longitude,
        elevation=inv[0][0].elevation,
        creation_date=obspy.UTCDateTime(2016, 1, 2),
        site=Site(name="station with cloned inv"))

    cha = Channel(
        # This is the channel code according to the SEED standard.
        code="HHZ",
        # This is the location code according to the SEED standard.
        location_code="",
        # Note that these coordinates can differ from the station coordinates.
        start_date=inv[0][0][0].start_date,
        latitude=inv[0][0][0].latitude,
        longitude=inv[0][0][0].longitude,
        elevation=inv[0][0][0].elevation,
        depth=inv[0][0][0].depth,
        #        azimuth=0.0,
        #        dip=-90.0,
        sample_rate=inv[0][0][0].sample_rate)

    # Now tie it all together.
    cha.response = inv[0][0][0].response  #response
    sta.channels.append(cha)
    net.stations.append(sta)
    inv.networks.append(net)

    return inv
예제 #16
0
    def set_channel(self,
                    p_code="",
                    p_location_code="",
                    p_latitude=0,
                    p_longitude=0,
                    p_elevation=0,
                    p_depth=0,
                    p_azimuth=0,
                    p_dip=0,
                    p_sample_rate=0,
                    p_sensor=None,
                    p_datalogger=None):
        self.channels_raw = {
            "code": p_code,
            "location_code": p_location_code,
            "latitude": p_latitude,
            "longitude": p_longitude,
            "elevation": p_elevation,
            "depth": p_depth,
            "azimuth": p_azimuth,
            "dip": p_dip,
            "sample_rate": p_sample_rate,
            "sensor": p_sensor,
            "datalogger": p_datalogger
        }

        temp_channel = Channel(
            code=self.channels_raw["code"],
            location_code=self.channels_raw["location_code"],
            latitude=self.channels_raw["latitude"],
            longitude=self.channels_raw["longitude"],
            elevation=self.channels_raw["elevation"],
            depth=self.channels_raw["depth"],
            azimuth=self.channels_raw["azimuth"],
            dip=self.channels_raw["dip"],
            sample_rate=self.channels_raw["sample_rate"])
        temp_channel.response = self.my_nrl.get_response(
            datalogger_keys=p_datalogger, sensor_keys=p_sensor)
        self.channels.append(temp_channel)
예제 #17
0
def _channel_from_stats(stats):
    if stats.standard.units in UNITS:
        units = UNITS[stats.standard.units]
    else:
        units = ''
    instrument = stats.standard.instrument
    serialnum = stats.standard.sensor_serial_number
    if len(instrument) or len(serialnum):
        equipment = Equipment(type=instrument, serial_number=serialnum)
    else:
        equipment = None
    depth = 0.0
    azimuth = None
    c1 = 'horizontal_orientation' in stats.standard
    c2 = c1 and not np.isnan(stats.standard.horizontal_orientation)
    if c2:
        azimuth = stats.standard.horizontal_orientation
    else:
        azimuth = 0

    response = None
    if 'response' in stats:
        response = stats['response']
    comments = Comment(stats.standard.comments)
    logging.debug('channel: %s' % stats.channel)
    channel = Channel(stats.channel,
                      stats.location,
                      stats.coordinates['latitude'],
                      stats.coordinates['longitude'],
                      stats.coordinates['elevation'],
                      depth,
                      azimuth=azimuth,
                      sample_rate=stats.sampling_rate,
                      storage_format=stats.standard.source_format,
                      calibration_units=units,
                      comments=[comments],
                      response=response,
                      sensor=equipment)
    return channel
예제 #18
0
파일: utils.py 프로젝트: wjlei1990/pytomo3d
def create_simple_inventory(network, station, latitude=None, longitude=None,
                            elevation=None, depth=None, start_date=None,
                            end_date=None, location_code="S3",
                            channel_code="MX"):
    """
    Create simple inventory with only location information,
    for ZNE component, especially usefull for synthetic data
    """
    azi_dict = {"MXZ": 0.0,  "MXN": 0.0, "MXE": 90.0}
    dip_dict = {"MXZ": 90.0, "MXN": 0.0, "MXE": 0.0}
    channel_list = []

    if start_date is None:
        start_date = UTCDateTime(0)

    # specfem default channel code is MX
    for _comp in ["Z", "E", "N"]:
        _chan_code = "%s%s" % (channel_code, _comp)
        chan = Channel(_chan_code, location_code, latitude=latitude,
                       longitude=longitude, elevation=elevation,
                       depth=depth, azimuth=azi_dict[_chan_code],
                       dip=dip_dict[_chan_code], start_date=start_date,
                       end_date=end_date)
        channel_list.append(chan)

    site = Site("N/A")
    sta = Station(station, latitude=latitude, longitude=longitude,
                  elevation=elevation, channels=channel_list, site=site,
                  creation_date=start_date, total_number_of_channels=3,
                  selected_number_of_channels=3)

    nw = Network(network, stations=[sta, ], total_number_of_stations=1,
                 selected_number_of_stations=1)

    inv = Inventory([nw, ], source="SPECFEM3D_GLOBE", sender="Princeton",
                    created=UTCDateTime.now())

    return inv
예제 #19
0
    def _make_inventory(self, df: pd.DataFrame):
        """
        Loopy logic for creating the inventory form a dataframe.
        """
        # get dataframe with correct columns/conditioning from input
        df = obsplus.stations_to_df(df).copy()
        # add responses (if requested) and drop response cols
        df["response"] = self._get_responses(df)
        df = df.drop(columns=self._drop_cols, errors="ignore")
        # warn if any unexpected columns are found in df
        self._maybe_warn_on_unexpected_columns(df)
        # Iterate networks and create stations
        networks = []
        for net_code, net_df in self._groupby_if_exists(df, "network"):
            stations = []
            for st_code, sta_df in self._groupby_if_exists(net_df, "station"):
                if not st_code[0]:
                    continue
                channels = []
                for ch_code, ch_df in self._groupby_if_exists(sta_df, "channel"):
                    if not ch_code[0]:  # skip empty channel lines
                        continue
                    chan_series = ch_df.iloc[0]
                    kwargs = self._get_kwargs(chan_series, self.cha_map)
                    # try to add the inventory
                    channels.append(Channel(**kwargs))
                kwargs = self._get_kwargs(sta_df.iloc[0], self.sta_map)
                self._add_dates(kwargs, channels)
                stations.append(Station(channels=channels, **kwargs))
            kwargs = self._get_kwargs(net_df.iloc[0], self.net_map)
            self._add_dates(kwargs, stations)
            networks.append(Network(stations=stations, **kwargs))

        return obspy.Inventory(
            networks=networks, source=f"ObsPlus_v{obsplus.__version__}"
        )
예제 #20
0
def read_fdsn_station_text_file(path_or_file_object):
    """
    Function reading a FDSN station text file to an inventory object.

    :param path_or_file_object: File name or file like object.
    """
    def _read(obj):
        r = unicode_csv_reader(obj, delimiter=native_str("|"))
        header = next(r)
        header[0] = header[0].lstrip("#")
        header = [_i.strip().lower() for _i in header]
        # IRIS currently has a wrong header name. Just map it.
        header = [
            _i.replace("instrument", "sensordescription") for _i in header
        ]

        all_lines = []
        for line in r:
            # Skip comment lines.
            if line[0].startswith("#"):
                continue
            all_lines.append([_i.strip() for _i in line])
        return {"header": tuple(header), "content": all_lines}

    # Enable reading from files and buffers opened in binary mode.
    if (hasattr(path_or_file_object, "mode") and
            "b" in path_or_file_object.mode) or \
            isinstance(path_or_file_object, io.BytesIO):
        buf = io.StringIO(path_or_file_object.read().decode("utf-8"))
        buf.seek(0, 0)
        path_or_file_object = buf

    if hasattr(path_or_file_object, "read"):
        content = _read(path_or_file_object)
    else:
        with open(path_or_file_object, "rt", newline="",
                  encoding="utf8") as fh:
            content = _read(fh)

    # Figure out the type.
    if content["header"] == network_components:
        level = "network"
        filetypes = network_types
    elif content["header"] == station_components:
        level = "station"
        filetypes = station_types
    elif content["header"] == channel_components:
        level = "channel"
        filetypes = channel_types
    else:
        raise ValueError("Unknown type of header.")

    content = content["content"]
    converted_content = []
    # Convert all types.
    for line in content:
        converted_content.append(
            [v_type(value) for value, v_type in zip(line, filetypes)])

    # Now convert to an inventory object.
    inv = Inventory(networks=[], source=None)

    if level == "network":
        for net in converted_content:
            network = Network(code=net[0],
                              description=net[1],
                              start_date=net[2],
                              end_date=net[3],
                              total_number_of_stations=net[4])
            inv.networks.append(network)
    elif level == "station":
        networks = collections.OrderedDict()
        for sta in converted_content:
            site = Site(name=sta[5])
            station = Station(code=sta[1],
                              latitude=sta[2],
                              longitude=sta[3],
                              elevation=sta[4],
                              site=site,
                              start_date=sta[6],
                              end_date=sta[7])
            if sta[0] not in networks:
                networks[sta[0]] = []
            networks[sta[0]].append(station)
        for network_code, stations in networks.items():
            net = Network(code=network_code, stations=stations)
            inv.networks.append(net)
    elif level == "channel":
        networks = collections.OrderedDict()
        stations = collections.OrderedDict()

        for channel in converted_content:
            net, sta, loc, chan, lat, lng, ele, dep, azi, dip, inst, scale, \
                scale_freq, scale_units, s_r, st, et = channel

            if net not in networks:
                networks[net] = Network(code=net)

            if (net, sta) not in stations:
                station = Station(code=sta,
                                  latitude=lat,
                                  longitude=lng,
                                  elevation=ele)
                networks[net].stations.append(station)
                stations[(net, sta)] = station

            sensor = Equipment(type=inst)
            if scale is not None and scale_freq is not None:
                resp = Response(instrument_sensitivity=InstrumentSensitivity(
                    value=scale,
                    frequency=scale_freq,
                    input_units=scale_units,
                    output_units=None))
            else:
                resp = None
            try:
                channel = Channel(code=chan,
                                  location_code=loc,
                                  latitude=lat,
                                  longitude=lng,
                                  elevation=ele,
                                  depth=dep,
                                  azimuth=azi,
                                  dip=dip,
                                  sensor=sensor,
                                  sample_rate=s_r,
                                  start_date=st,
                                  end_date=et,
                                  response=resp)
            except Exception as e:
                warnings.warn(
                    "Failed to parse channel %s.%s.%s.%s due to: %s" %
                    (net, sta, loc, chan, str(e)), UserWarning)
                continue
            stations[(net, sta)].channels.append(channel)
        inv.networks.extend(list(networks.values()))
    else:
        # Cannot really happen - just a safety measure.
        raise NotImplementedError("Unknown level: %s" % str(level))
    return inv
예제 #21
0
def main(argv):
    '''@package isc2stnxml
       It gathers station information from all STN files provided in ISC and Engdahl catalogues assigning correct network code.
       When proper network code can not be identified the program just guess it, sorry...
    '''
    inv = read_inventory("IRIS-ALL.xml")

    # unknown stations in Indonesia are usually installed by Potsdam and we assume they have network name GE
    default_net = 'GE'
    ehb1 = read_eng('BMG.STN')
    ehb2 = read_eng('ISC.STN')
    ehb = np.unique(np.vstack((ehb1, ehb2)), axis=0)

    isc1 = read_isc('ehb.stn')
    isc2 = read_isc('iscehb.stn')
    isc = np.unique(np.vstack((isc1, isc2)), axis=0)

    catalogue = []
    our_xml = Inventory(networks=[], source='EHB')

    for i in xrange(ehb.shape[0]):
        filed = False
        xml = False
        stn_found = isc[isc[:, 0] == ehb[i, 0], :]
        min_dist = 10e10
        if stn_found.shape[0] > 0:
            if stn_found.shape[0] > 1:
                for j in xrange(stn_found.shape[0]):
                    dist = locations2degrees(np.float(stn_found[j, 2]),
                                             np.float(stn_found[j, 3]),
                                             np.float(ehb[i, 1]),
                                             np.float(ehb[i, 2]))
                    if dist < min_dist:
                        min_dist = dist
                        record = stn_found[j, :]
            else:
                min_dist = locations2degrees(np.float(stn_found[0, 2]),
                                             np.float(stn_found[0, 3]),
                                             np.float(ehb[i, 1]),
                                             np.float(ehb[i, 2]))
                record = stn_found[0, :]

#                Now we try to find the same station in XML file
#                if min_dist > 1. or stn_found.shape[0]==0:

        xstn_found = inv.select(station=ehb[i, 0], channel="*HZ")

        if len(stn_found) == 0 and len(xstn_found) == 0:
            # we filed to find station anywhere and assign dummy values
            record = [
                ehb[i, 0], default_net, ehb[i, 1], ehb[i, 2], ehb[i, 3], 'Z',
                '1964-1-1 00:00:00', '2599-12-31 23:59:59'
            ]
            min_dist = 0.
            filed = True
        else:
            # if station is found somehwere we try to iterate and see if XML has data giving it preference through adding extra value to min_dist found in ISC
            if len(xstn_found) > 0:
                #                        print "----------",len(xstn_found)
                #                        print xstn_found[0][0].latitude
                min_dist = min_dist + 0.1
                for j in xrange(len(xstn_found)):
                    dist = locations2degrees(xstn_found[j][0].latitude,
                                             xstn_found[j][0].longitude,
                                             np.float(ehb[i, 1]),
                                             np.float(ehb[i, 2]))
                    if min_dist > dist:
                        min_dist = dist
                        record = xstn_found[j]
                        #                                print record
                        xml = True

# last defence if stations have been done but distance between declared and found locations are more than 1 degree
        if min_dist > 1:
            record = [
                ehb[i, 0], default_net, ehb[i, 1], ehb[i, 2], ehb[i, 3], 'Z',
                '1964-1-1 00:00:00', '2599-12-31 23:59:59'
            ]
            filed = True
        if xml:
            #our_xml.networks.append(record)
            xml = False

        else:
            if filed:

                if len(record[7]) < 5:
                    record[7] = '2599-12-31 23:59:59'
                catalogue.append(record)

            else:

                stn_found = isc[(isc[:, 0] == record[0]) &
                                (isc[:, 1] == record[1]), :]

                for k in xrange(stn_found.shape[0]):
                    net = Network(code=stn_found[k, 1],
                                  stations=[],
                                  description=' ')
                    if len(stn_found[k, 7]) < 5:
                        stn_found[k, 7] = '2599-12-31 23:59:59'
                    catalogue.append(stn_found[k, :])

    stn_found = np.unique(np.array(catalogue), axis=0)
    if len(stn_found[stn_found == '']) > 0 or len(
            stn_found[stn_found == ' ']) > 0:
        print "Some elements are empty, check the list"

    # we composed our inventory. However some stations from ISC list can be left behind. We check if some stations in ISC are forgotten
    lost = []
    for j in xrange(isc.shape[0]):
        # is there any common station name?
        common_st = stn_found[isc[j, 0] == stn_found[:, 0]]
        if common_st.shape[0] > 0:
            # is network code the same?
            common_net = common_st[common_st[:, 1] == isc[j, 1]]
            if common_net.shape[0] < 1:
                # ok we found forgotten one, check the XML
                if len(inv.select(station=isc[j, 0], network=isc[j, 1])) <= 0:
                    # Bingo...
                    lost.append(isc[j, :])
        else:
            if len(inv.select(station=isc[j, 0], network=isc[j, 1])) <= 0:
                # Bingo...
                lost.append(isc[j, :])

    stn_found = np.vstack((stn_found, np.array(lost)))

    for k in xrange(stn_found.shape[0]):

        net = Network(code=stn_found[k, 1], stations=[], description=' ')
        if len(stn_found[k, 7]) < 5:
            stn_found[k, 7] = '2599-12-31 23:59:59'
        catalogue.append(stn_found[k, :])
        sta=Station(code=stn_found[k,0],creation_date=utcdatetime.UTCDateTime(stn_found[k,6]), \
        termination_date=utcdatetime.UTCDateTime(stn_found[k,7]), \
        site=Site(name=' '), \
        latitude=np.float(stn_found[k,2]), \
        longitude=np.float(stn_found[k,3]), \
        elevation=np.float(stn_found[k,4]))

        cha=Channel(code=stn_found[k,5], \
        depth=0., \
        azimuth=0., \
        dip=-90., \
        location_code='', \
        latitude=np.float(stn_found[k,2]), \
        longitude=np.float(stn_found[k,3]), \
        elevation=np.float(stn_found[k,4]))

        sta.channels.append(cha)
        net.stations.append(sta)
        our_xml.networks.append(net)


#             print 'np',stn_found[k,:]

    our_xml.write("station.xml", format="stationxml", validate=True)
    our_xml.write("station.txt", format="stationtxt")
예제 #22
0
    def test_channel_str(self):
        """
        Tests the __str__ method of the channel object.
        """
        c = Channel(code="BHE",
                    location_code="10",
                    latitude=1,
                    longitude=2,
                    elevation=3,
                    depth=4,
                    azimuth=5,
                    dip=6)
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n")

        # Adding channel types.
        c.types = ["A", "B"]
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n")

        # Adding channel types.
        c.sample_rate = 10.0
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n"
            "\tSampling Rate: 10.00 Hz\n")

        # "Adding" response
        c.response = True
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n"
            "\tSampling Rate: 10.00 Hz\n"
            "\tResponse information available")

        # Adding an empty sensor.
        c.sensor = Equipment(type=None)
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n"
            "\tSampling Rate: 10.00 Hz\n"
            "\tSensor (Description): None (None)\n"
            "\tResponse information available")

        # Adding a sensor with only a type.
        c.sensor = Equipment(type="random")
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n"
            "\tSampling Rate: 10.00 Hz\n"
            "\tSensor (Description): random (None)\n"
            "\tResponse information available")

        # Adding a sensor with only a description
        c.sensor = Equipment(description="some description")
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n"
            "\tSampling Rate: 10.00 Hz\n"
            "\tSensor (Description): None (some description)\n"
            "\tResponse information available")

        # Adding a sensor with type and description
        c.sensor = Equipment(type="random", description="some description")
        assert str(c) == (
            "Channel 'BHE', Location '10' \n"
            "\tTime range: -- - --\n"
            "\tLatitude: 1.00, Longitude: 2.00, Elevation: 3.0 m, "
            "Local Depth: 4.0 m\n"
            "\tAzimuth: 5.00 degrees from north, clockwise\n"
            "\tDip: 6.00 degrees down from horizontal\n"
            "\tChannel types: A, B\n"
            "\tSampling Rate: 10.00 Hz\n"
            "\tSensor (Description): random (some description)\n"
            "\tResponse information available")
예제 #23
0
def MMF_calibration_to_response(directory, plot=False):
    """
    Take directory of MMF calibration spreadsheets and convert to Obspy
    inventory object
    """
    inv = Inventory(networks=[Network(code='MMF')])
    lat = Latitude(0.)
    lon = Longitude(0.)
    chan_map = {
        'Tabellenblatt3': 'X',
        'Tabellenblatt4': 'Y',
        'Tabellenblatt5': 'Z'
    }
    calibs = glob('{}/*.xls'.format(directory))
    avg_amp = {'XNZ': [], 'XNY': [], 'XNX': []}
    avg_phase = {'XNZ': [], 'XNY': [], 'XNX': []}
    avg_sensitivity = {'XNZ': [], 'XNY': [], 'XNX': []}
    avg_freq = []
    for c in calibs:
        serial = c.split()[-2]
        sta = Station(code=serial[1:],
                      latitude=lat,
                      longitude=lon,
                      elevation=0.)
        # Tables slightly shifted for each channel due to comments
        dict_xyz = pd.read_excel(c,
                                 sheet_name=['Tabellenblatt3'],
                                 header=14,
                                 usecols=list(np.arange(4, 14)),
                                 nrows=37)
        dict_xyz.update(
            pd.read_excel(c,
                          sheet_name=['Tabellenblatt4'],
                          header=14,
                          usecols=list(np.arange(5, 15)),
                          nrows=37))
        dict_xyz.update(
            pd.read_excel(c,
                          sheet_name=['Tabellenblatt5'],
                          header=13,
                          usecols=list(np.arange(9, 20)),
                          nrows=37))
        # Get array of sensitivities at 80 Hz for X, Y, Z
        sens = pd.read_excel(c,
                             sheet_name=['Tabellenblatt2'],
                             header=84,
                             usecols=[27],
                             nrows=3)['Tabellenblatt2'].values.squeeze()
        # mV/m/s**2 to V/m/s**2
        sens_dict = {
            'Tabellenblatt3': float(sens[0].replace(',', '.')) * 1e-3,
            'Tabellenblatt4': float(sens[1].replace(',', '.')) * 1e-3,
            'Tabellenblatt5': float(sens[2].replace(',', '.')) * 1e-3
        }
        # Resp for each channel
        for nm, df in dict_xyz.items():
            # Dummy channel
            chan_code = 'XN{}'.format(chan_map[nm])
            # Set samp_rate to 40 kHz so that Nyquist is below max shake freq
            chan = Channel(code=chan_code,
                           location_code='',
                           latitude=lat,
                           longitude=lon,
                           elevation=0.,
                           depth=0.,
                           sample_rate=40000.,
                           sensor=Equipment(
                               type='IEPE Accelerometer',
                               description='Piezoelectric accelerometer',
                               manufacturer='MMF',
                               model='KS943B.100',
                               serial_number=serial))
            values = df[['[Hz]', '[m/s²]', '[°]']].values
            # Add to dict for average channel estimate later
            avg_amp[chan_code].append(values[:, 1])
            avg_phase[chan_code].append(values[:, 2])
            avg_sensitivity[chan_code].append(float(sens_dict[nm]))
            avg_freq = values[:, 0]
            response_elements = [
                ResponseListElement(frequency=values[i][0],
                                    amplitude=values[i][1],
                                    phase=values[i][2])
                for i in range(values.shape[0])
            ]
            # Add a value at zero to avoid deconvolution errors
            response_elements.insert(
                0,
                ResponseListElement(frequency=0.,
                                    amplitude=values[0][1],
                                    phase=values[0][2]))
            resp_stage = ResponseListResponseStage(
                response_list_elements=response_elements,
                stage_gain=1,
                stage_gain_frequency=80.,
                input_units='M/S**2',
                output_units='V',
                stage_sequence_number=1)
            sensitivity = InstrumentSensitivity(value=float(sens_dict[nm]),
                                                frequency=80.,
                                                input_units='M/S**2',
                                                output_units='V',
                                                frequency_range_start=5,
                                                frequency_range_end=15850,
                                                frequency_range_db_variation=3)
            response = Response(instrument_sensitivity=sensitivity,
                                response_stages=[resp_stage])
            chan.response = response
            sta.channels.append(chan)
            # chan.response.plot(min_freq=2.4, sampling_rate=40000.)
        inv[0].stations.append(sta)
    # Now make an 'average' channel for the other sensors
    avg_sta = Station(code='AVG', latitude=lat, longitude=lon, elevation=0.)
    for c in ['XNX', 'XNY', 'XNZ']:
        chan = Channel(code=c,
                       location_code='',
                       latitude=lat,
                       longitude=lon,
                       elevation=0.,
                       depth=0.,
                       sample_rate=40000.,
                       sensor=Equipment(
                           type='IEPE Accelerometer',
                           description='Piezoelectric accelerometer',
                           manufacturer='MMF',
                           model='KS943B.100',
                           serial_number='9999'))
        amp = np.array(avg_amp[c]).mean(axis=0)
        pha = np.array(avg_phase[c]).mean(axis=0)
        response_elements = [
            ResponseListElement(frequency=avg_freq[i],
                                amplitude=amp[i],
                                phase=pha[i]) for i in range(avg_freq.size)
        ]
        # Add a value at zero to avoid deconvolution errors
        response_elements.insert(
            0, ResponseListElement(frequency=0.,
                                   amplitude=amp[0],
                                   phase=pha[0]))
        resp_stage = ResponseListResponseStage(
            response_list_elements=response_elements,
            stage_gain=1,
            stage_gain_frequency=80.,
            input_units='M/S**2',
            output_units='V',
            stage_sequence_number=1)
        sensitivity = InstrumentSensitivity(value=np.array(
            avg_sensitivity[c]).mean(),
                                            frequency=80.,
                                            input_units='M/S**2',
                                            output_units='V',
                                            frequency_range_start=5,
                                            frequency_range_end=15850,
                                            frequency_range_db_variation=3)
        response = Response(instrument_sensitivity=sensitivity,
                            response_stages=[resp_stage])
        chan.response = response
        avg_sta.channels.append(chan)
    inv[0].stations.append(avg_sta)
    if plot:
        inv.plot_response(min_freq=2.4, plot_degrees=True)
    return inv
예제 #24
0
def fsb_to_inv(path, orientations=False, debug=0):
    """
    Take excel file of sensor locations and build an Inventory

    :param path: Path to excel spreadsheet
    :param orientations: False or dict of orientation info
    :param debug:
    :return:
    """
    inventory = Inventory()
    inventory.networks = [Network(code='FS')]
    converter = FSB_converter()
    sens_dict = read_fsb_asbuilt(path)
    # Assemble dictionary of {station: {channel: infoz}}
    # Create dict before, then build inventory from channel level upwards
    sta_dict = {}
    extra_dict = {}
    for sta, loc in sens_dict.items():
        # Station location
        # Convert from SURF coords to lat lon, but keep local for actual use
        lon, lat, elev = converter.to_lonlat((loc[0], loc[1], loc[2]))
        depth = 0.0  # Until we do any orientations?
        # Save HMC coords to custom attributes of Station and Channel
        extra = AttribDict({
            'ch1903_east': {
                'value': loc[0],
                'namespace': 'smi:local/hmc'
            },
            'ch1903_north': {
                'value': loc[1],
                'namespace': 'smi:local/hmc'
            },
            'ch1903_elev': {
                'value': loc[2],  # extra will preserve absolute elev
                'namespace': 'smi:local/hmc'
            }
        })
        # Not yet implemented; Pass orientations dict when we do
        if orientations:
            # TODO Something is real effed here. Answers are right though.
            dip_rad = np.arcsin(-orientations[sta]['Sz'])
            az_rad = np.arcsin(orientations[sta]['Sx'] / np.cos(dip_rad))
            dip = np.rad2deg(dip_rad)
            az = np.rad2deg(az_rad)
            # Force positive
            if az < 0:
                az += 360.
            # Correct
            if orientations[sta]['Sx'] < 0 and orientations[sta]['Sy'] < 0:
                az -= 270.
                az = 270. - az
            elif orientations[sta]['Sy'] < 0:
                az = 180 - az
            if debug > 0:
                print(
                    np.array((orientations[sta]['Sx'], orientations[sta]['Sy'],
                              orientations[sta]['Sz'])))
                print(az, dip)
        try:
            if orientations[sta]['Sensor'].endswith(('Z', 'X', 'Y')):
                chan = 'XN{}'.format(orientations[sta]['Sensor'][-1])
                # Geophones
                if orientations[sta]['Sensor'].startswith('G'):
                    no = orientations[sta]['Sensor'][-3]
                # Accelerometers
                else:
                    no = orientations[sta]['Sensor'].split('_')[1]
                sta_name = '{}{}'.format(orientations[sta]['Desc'], no)
                channel = Channel(code=chan,
                                  location_code='',
                                  latitude=lat,
                                  longitude=lon,
                                  elevation=elev,
                                  depth=depth,
                                  azimuth=az,
                                  dip=dip,
                                  response=Response())
                # channel.extra = extra
            elif orientations[sta]['Sensor'].startswith('Hydro'):
                chan = 'XN1'
                sta_name = '{}{}'.format(
                    orientations[sta]['Desc'],
                    orientations[sta]['Sensor'].split('-')[-1].zfill(2))
                channel = Channel(code=chan,
                                  location_code='',
                                  latitude=lat,
                                  longitude=lon,
                                  elevation=elev,
                                  depth=depth,
                                  response=Response())
        except TypeError as e:
            sta_name = sta
            if sta in fsb_accelerometers:
                channels = []
                for chan in ['XNZ', 'XNX', 'XNY']:
                    channels.append(
                        Channel(code=chan,
                                location_code='',
                                latitude=lat,
                                longitude=lon,
                                elevation=elev,
                                depth=depth,
                                response=Response()))
            else:
                channel = Channel(code='XN1',
                                  location_code='',
                                  latitude=lat,
                                  longitude=lon,
                                  elevation=elev,
                                  depth=depth,
                                  response=Response())
                channels = [channel]
        extra_dict[sta_name] = extra
        sta_dict[sta_name] = channels
    for nm, chans in sta_dict.items():
        station = Station(code=nm,
                          latitude=chans[0].latitude,
                          longitude=chans[0].longitude,
                          elevation=chans[0].elevation,
                          channels=chans)
        station.extra = extra_dict[nm]
        inventory[0].stations.append(station)
    return inventory
예제 #25
0
def get_inventory():
    # We'll first create all the various objects. These strongly follow the
    # hierarchy of StationXML files.
    inv = Inventory(
        # We'll add networks later.
        networks=[],
        # The source should be the id whoever create the file.
        source="ObsPy-Tutorial")

    net = Network(
        # This is the network code according to the SEED standard.
        code="US",
        # A list of stations. We'll add one later.
        stations=[],
        description="A test stations.",
        # Start-and end dates are optional.
        start_date=UTCDateTime(2016, 1, 2))

    sta = Station(
        # This is the station code according to the SEED standard.
        code="ABCD",
        latitude=1.0,
        longitude=2.0,
        elevation=345.0,
        creation_date=UTCDateTime(2016, 1, 2),
        site=Site(name="First station"))

    cha1 = Channel(
        # This is the channel code according to the SEED standard.
        code="HN1",
        # This is the location code according to the SEED standard.
        location_code="11",
        # Note that these coordinates can differ from the station coordinates.
        latitude=1.0,
        longitude=2.0,
        elevation=345.0,
        depth=10.0,
        azimuth=0.0,
        dip=-90.0,
        sample_rate=1)
    cha2 = Channel(
        # This is the channel code according to the SEED standard.
        code="HN2",
        # This is the location code according to the SEED standard.
        location_code="11",
        # Note that these coordinates can differ from the station coordinates.
        latitude=1.0,
        longitude=2.0,
        elevation=345.0,
        depth=10.0,
        azimuth=90.0,
        dip=-90.0,
        sample_rate=1)
    cha3 = Channel(
        # This is the channel code according to the SEED standard.
        code="HNZ",
        # This is the location code according to the SEED standard.
        location_code="11",
        # Note that these coordinates can differ from the station coordinates.
        latitude=1.0,
        longitude=2.0,
        elevation=345.0,
        depth=10.0,
        azimuth=0.0,
        dip=-90.0,
        sample_rate=1)

    # Now tie it all together.
    sta.channels.append(cha1)
    sta.channels.append(cha2)
    sta.channels.append(cha3)
    net.stations.append(sta)
    inv.networks.append(net)

    return inv
예제 #26
0
def surf_stations_to_inv(excel_file, debug=0):
    """
    Take Petrs orientation excel file for the hydrophones/accelerometers
    and build an inventory for later use.
    :param excel_file: path to Petr's excel file (formatting hard-coded)
    :return: obspy.core.Inventory
    """
    # Call coordinate converter
    converter = SURF_converter()
    sta_df = pd.read_excel(excel_file,
                           skiprows=[0, 1, 2, 3],
                           header=1,
                           nrows=90)
    # Assemble dictionary of {station: {channel: infoz}}
    # Create dict before, then build inventory from channel level upwards
    sta_dict = {}
    extra_dict = {}
    for i, row in sta_df.iterrows():
        # Station location
        # Convert from SURF coords to lat lon, but keep local for actual use
        lon, lat, elev = converter.to_lonlat(
            (row['Easting(m)'], row['Northing(m)'], row['Elev(m)']))
        # Correct for arbitrary zero 'depth' of 130m
        elev -= 130
        # Already accounted for in the elevation but will include here as its
        # ...a required arg for Channel()
        depth = row['Depth (m)']
        # Save HMC coords to custom attributes of Station and Channel
        extra = AttribDict({
            'hmc_east': {
                'value': row['Easting(m)'],
                'namespace': 'smi:local/hmc'
            },
            'hmc_north': {
                'value': row['Northing(m)'],
                'namespace': 'smi:local/hmc'
            },
            'hmc_elev': {
                'value': row['Elev(m)'],  # extra will preserve absolute elev
                'namespace': 'smi:local/hmc'
            }
        })
        # Sort out azimuth and dip for this channel (if it exists)
        if not np.isnan(row['Sx']):
            # TODO Something is real effed here. Answers are right though.
            dip_rad = np.arcsin(-row['Sz'])
            az_rad = np.arcsin(row['Sx'] / np.cos(dip_rad))
            dip = np.rad2deg(dip_rad)
            az = np.rad2deg(az_rad)
            # Force positive
            if az < 0:
                az += 360.
            # Correct
            if row['Sx'] < 0 and row['Sy'] < 0:
                az -= 270.
                az = 270. - az
            elif row['Sy'] < 0:
                az = 180 - az
            if debug > 0:
                print(np.array((row['Sx'], row['Sy'], row['Sz'])))
                print(az, dip)
        if row['Sensor'].endswith(('Z', 'X', 'Y')):
            chan = 'XN{}'.format(row['Sensor'][-1])
            # Geophones
            if row['Sensor'].startswith('G'):
                continue
            # Accelerometers
            else:
                no = row['Sensor'].split('_')[1]
            sta_name = '{}{}'.format(row['Desc'], no)
            if sta_name in ['OB14', 'OT17', 'PDT2', 'PDT5', 'PSB8', 'PST11']:
                # These are geode stations only, skip
                continue
            channel = Channel(code=chan,
                              location_code='',
                              latitude=lat,
                              longitude=lon,
                              elevation=elev,
                              depth=depth,
                              azimuth=az,
                              dip=dip,
                              response=Response())
            # channel.extra = extra
        elif row['Sensor'].startswith('Hydro'):
            chan = 'XN1'
            sta_name = '{}{}'.format(row['Desc'],
                                     row['Sensor'].split('-')[-1].zfill(2))
            channel = Channel(code=chan,
                              location_code='',
                              latitude=lat,
                              longitude=lon,
                              elevation=elev,
                              depth=depth,
                              response=Response())
        extra_dict[sta_name] = extra
        # channel.extra = extra
        if sta_name in sta_dict.keys():
            sta_dict[sta_name].append(channel)
        else:
            sta_dict[sta_name] = [channel]
    # Now loop station dict to create inventory
    stas = []
    for nm, chans in sta_dict.items():
        station = Station(code=nm,
                          latitude=chans[0].latitude,
                          longitude=chans[0].longitude,
                          elevation=chans[0].elevation,
                          channels=chans)
        station.extra = extra_dict[nm]
        stas.append(station)
    # Build inventory
    inventory = Inventory(networks=[Network(code='SV', stations=stas)],
                          source='SURF')
    return inventory
예제 #27
0
def stats2inv(stats, resp=None, filexml=None, locs=None):

    # We'll first create all the various objects. These strongly follow the
    # hierarchy of StationXML files.
    inv = Inventory(networks=[], source="japan_from_resp")

    if locs is None:
        net = Network(
            # This is the network code according to the SEED standard.
            code=stats.network,
            # A list of stations. We'll add one later.
            stations=[],
            description="Marine created from SAC and resp files",
            # Start-and end dates are optional.
            start_date=stats.starttime)

        sta = Station(
            # This is the station code according to the SEED standard.
            code=stats.station,
            latitude=stats.sac["stla"],
            longitude=stats.sac["stlo"],
            elevation=stats.sac["stel"],
            creation_date=stats.starttime,
            site=Site(name="First station"))

        cha = Channel(
            # This is the channel code according to the SEED standard.
            code=stats.channel,
            # This is the location code according to the SEED standard.
            location_code=stats.location,
            # Note that these coordinates can differ from the station coordinates.
            latitude=stats.sac["stla"],
            longitude=stats.sac["stlo"],
            elevation=stats.sac["stel"],
            depth=-stats.sac["stel"],
            azimuth=stats.sac["cmpaz"],
            dip=stats.sac["cmpinc"],
            sample_rate=stats.sampling_rate)

    else:
        ista = locs[locs['station'] == stats.station].index.values.astype(
            'int64')[0]

        net = Network(
            # This is the network code according to the SEED standard.
            code=locs.iloc[ista]["network"],
            # A list of stations. We'll add one later.
            stations=[],
            description="Marine created from SAC and resp files",
            # Start-and end dates are optional.
            start_date=stats.starttime)

        sta = Station(
            # This is the station code according to the SEED standard.
            code=locs.iloc[ista]["station"],
            latitude=locs.iloc[ista]["latitude"],
            longitude=locs.iloc[ista]["longitude"],
            elevation=locs.iloc[ista]["elevation"],
            creation_date=stats.starttime,
            site=Site(name="First station"))
        cha = Channel(
            # This is the channel code according to the SEED standard.
            code=stats.channel,
            # This is the location code according to the SEED standard.
            location_code=stats.location,
            # Note that these coordinates can differ from the station coordinates.
            latitude=locs.iloc[ista]["latitude"],
            longitude=locs.iloc[ista]["longitude"],
            elevation=locs.iloc[ista]["elevation"],
            depth=-locs.iloc[ista]["elevation"],
            azimuth=0,
            dip=0,
            sample_rate=stats.sampling_rate)

    response = obspy.core.inventory.response.Response()
    if resp is not None:
        print('i dont have the response')
    # By default this accesses the NRL online. Offline copies of the NRL can
    # also be used instead
    # nrl = NRL()
    # The contents of the NRL can be explored interactively in a Python prompt,
    # see API documentation of NRL submodule:
    # http://docs.obspy.org/packages/obspy.clients.nrl.html
    # Here we assume that the end point of data logger and sensor are already
    # known:
    #response = nrl.get_response( # doctest: +SKIP
    #    sensor_keys=['Streckeisen', 'STS-1', '360 seconds'],
    #    datalogger_keys=['REF TEK', 'RT 130 & 130-SMA', '1', '200'])

    # Now tie it all together.
    cha.response = response
    sta.channels.append(cha)
    net.stations.append(sta)
    inv.networks.append(net)

    # And finally write it to a StationXML file. We also force a validation against
    # the StationXML schema to ensure it produces a valid StationXML file.
    #
    # Note that it is also possible to serialize to any of the other inventory
    # output formats ObsPy supports.
    if filexml is not None:
        inv.write(filexml, format="stationxml", validate=True)

    return inv
예제 #28
0
def getStation(stationBlock, units, transFuncs):
    ## Should probably do a check up here to see that the order given in block is consistent ##
    for entry in stationBlock:
        if entry.name == 'Station Identifier':
            #            print 'NewStation!',entry.station_call_letters
            staDict = {
                'code': entry.station_call_letters,
                'latitude': entry.latitude,
                'longitude': entry.longitude,
                'elevation': entry.elevation,
                'channels': [],
                'site': Site(entry.site_name),
                'creation_date':
                UTCDateTime(entry.start_effective_date),  # Allows for save
                'start_date': UTCDateTime(entry.start_effective_date),
                'end_date': UTCDateTime(entry.end_effective_date)
            }
            staNetCode = entry.network_code
        # If found a new channel, reset the stages
        elif entry.name == 'Channel Identifier':
            #            print 'NewChannel!',entry.channel_identifier
            stages = []
            chaDict = {
                'code': entry.channel_identifier,
                'location_code': entry.location_identifier,
                'latitude': entry.latitude,
                'longitude': entry.longitude,
                'elevation': entry.elevation,
                'depth': entry.local_depth,
                'sample_rate': entry.sample_rate,
                'start_date': UTCDateTime(entry.start_date),
                'end_date': UTCDateTime(entry.end_date),
                'azimuth': entry.azimuth,
                'dip': entry.dip
            }
        #code, location_code, latitude, longitude, elevation, depth
        # If on a new stage, set up the dictionary again
        # ...paz stage
        elif entry.name == 'Response Poles and Zeros':
            # Get units
            stageReqs = {}
            #            print entry.name,entry.stage_sequence_number
            #            print entry
            #            quit()
            stageReqs['input_units'] = units[entry.stage_signal_input_units]
            stageReqs['output_units'] = units[entry.stage_signal_output_units]
            # Collect the poles and zeros
            lastType = 'paz'
            if entry.number_of_complex_zeros == 0:
                zeros = np.array([], dtype=float)
            else:
                zeros = np.array(entry.real_zero, dtype=float) + np.array(
                    entry.imaginary_zero, dtype=float) * 1j
            if entry.number_of_complex_poles == 0:
                poles = np.array([], dtype=float)
            else:
                poles = np.array(entry.real_pole, dtype=float) + np.array(
                    entry.imaginary_pole, dtype=float) * 1j
            # Form the paz response dictionary (also ensure arrays are 1D)
            pazDict = {
                'pz_transfer_function_type':
                transFuncs[entry.transfer_function_types],
                'normalization_factor':
                entry.A0_normalization_factor,
                'normalization_frequency':
                entry.normalization_frequency,
                'zeros':
                setArrDim(zeros),
                'poles':
                setArrDim(poles)
            }
        # ...coeff stage
        elif entry.name == 'Response Coefficients':
            # Get units
            stageReqs = {}
            #            print entry.name,entry.stage_sequence_number
            stageReqs['input_units'] = units[entry.signal_input_units]
            stageReqs['output_units'] = units[entry.signal_output_units]
            # Collect the coefficients
            lastType = 'coef'
            if entry.number_of_denominators == 0:
                denom = np.array([], dtype=float)
                denomErr = np.array([], dtype=float)
            else:
                denom = np.array(entry.denominator_coefficient, dtype=float)
                denomErr = np.array(entry.denominator_error, dtype=float)
            if entry.number_of_numerators == 0:
                numer = np.array([], dtype=float)
                numerErr = np.array([], dtype=float)
            else:
                numer = np.array(entry.numerator_coefficient, dtype=float)
                numerErr = np.array(entry.numerator_error, dtype=float)
            # Convert these arrays into lists of numbers which have uncertainty (also ensure arrays are 1D)
            denomArr = genArrWithUncertainty(setArrDim(denom),
                                             setArrDim(denomErr))
            numerArr = genArrWithUncertainty(setArrDim(numer),
                                             setArrDim(numerErr))
            # Form the coeefficient response dictionary
            coefDict = {
                'cf_transfer_function_type': transFuncs[entry.response_type],
                'numerator': numerArr,
                'denominator': denomArr
            }
        # Get the decimation sampling info
        elif entry.name == 'Decimation':
            #            print entry.name,entry.stage_sequence_number
            stageReqs['decimation_input_sample_rate'] = Frequency(
                entry.input_sample_rate)
            stageReqs['decimation_factor'] = entry.decimation_factor
            stageReqs['decimation_offset'] = entry.decimation_offset
            stageReqs['decimation_delay'] = FloatWithUncertaintiesAndUnit(
                entry.estimated_delay)
            stageReqs['decimation_correction'] = FloatWithUncertaintiesAndUnit(
                entry.correction_applied)
        # Get the stage sensitivity
        elif entry.name == 'Channel Sensitivity Gain':
            #            print entry.name,entry.stage_sequence_number
            if entry.stage_sequence_number != 0:
                stageReqs[
                    'stage_sequence_number'] = entry.stage_sequence_number
                stageReqs['stage_gain'] = entry.sensitivity_gain
                stageReqs['stage_gain_frequency'] = entry.frequency
                # See what type of stage this was
                if lastType == 'paz':
                    pazDict.update(stageReqs)
                    stages.append(PolesZerosResponseStage(**pazDict))
                else:
                    coefDict.update(stageReqs)
                    stages.append(CoefficientsTypeResponseStage(**coefDict))
            # If on the last stage, send off the collected stage info
            else:
                if len(stages) > 0:
                    instrSens = InstrumentSensitivity(entry.sensitivity_gain,
                                                      entry.frequency,
                                                      stages[0].input_units,
                                                      stages[-1].output_units)
                    # Finalize the channel dictionary, and append this channel to the station dictionary
                    chaResp = Response(response_stages=stages,
                                       instrument_sensitivity=instrSens)
                    chaDict['response'] = chaResp
                staDict['channels'].append(Channel(**chaDict))
    # Return the stations to the list of stations (also track the network code)
    return Station(**staDict), staNetCode
예제 #29
0
def surf_4100_to_inv(location_file, response_inv, plot=False):
    """
    Combine the xyz Homestake locations and MMF calibration responses into
    an Inventory object for the 4100L
    """
    converter = SURF_converter()
    sta_df = pd.read_csv(location_file)
    inv = Inventory()
    serial_map = {'GMF1': '21010', 'GMF2': '21015', 'GMF3': '21027'}
    inv.networks = [Network(code='CB')]
    for _, row in sta_df.iterrows():
        print(row)
        sta_code = row['Sensor name']
        # Station location
        # Convert from SURF coords to lat lon, but keep local for actual use
        lon, lat, elev = converter.to_lonlat(
            (row['x_ft'] * 0.3048, row['y_ft'] * 0.3048, row['z_ft'] * 0.3048))
        print(lon, lat, elev)
        # Just leave as zero here and convert HMC feet elevation to m
        depth = 0.0
        # Save HMC coords to custom attributes of Station and Channel
        extra = AttribDict({
            'hmc_east': {
                'value': row['x_ft'],
                'namespace': 'smi:local/hmc'
            },
            'hmc_north': {
                'value': row['y_ft'],
                'namespace': 'smi:local/hmc'
            },
            'hmc_elev': {
                'value': row['z_ft'] * 0.3048,
                'namespace': 'smi:local/hmc'
            }
        })
        if sta_code.startswith('TS'):
            # Hydrophone or CASSM, wet well
            if 'SS' in sta_code:
                # Cassm (Y for unspecified instrument)
                chan_code = 'XY1'
                chans = [
                    Channel(code=chan_code,
                            location_code='',
                            latitude=lat,
                            longitude=lon,
                            elevation=elev,
                            depth=depth,
                            response=Response())
                ]
            else:
                # Hydrophone (D), Downhole (H) per SEED manual
                chan_code = 'XDH'
                chans = [
                    Channel(code=chan_code,
                            location_code='',
                            latitude=lat,
                            longitude=lon,
                            elevation=elev,
                            depth=depth,
                            response=Response())
                ]
        elif 'S' in sta_code:
            # Grouted CASSM
            chan_code = 'XY1'
            chans = [
                Channel(code=chan_code,
                        location_code='',
                        latitude=lat,
                        longitude=lon,
                        elevation=elev,
                        depth=depth,
                        response=Response())
            ]
        else:
            # Grouted accelerometer
            chans = []
            try:
                serial = serial_map[sta_code]
            except KeyError:
                serial = '9999'
            for chan_code in ['XNX', 'XNY', 'XNZ']:
                # Set samp_rate to 40 kHz so that Nyquist is below max shake f
                chan = Channel(code=chan_code,
                               location_code='',
                               latitude=lat,
                               longitude=lon,
                               elevation=elev,
                               depth=0.,
                               sample_rate=40000.,
                               sensor=Equipment(
                                   type='IEPE Accelerometer',
                                   description='Piezoelectric accelerometer',
                                   manufacturer='MMF',
                                   model='KS943B.100',
                                   serial_number=serial))
                # Apply exact response for the three tested sensors,
                # ...otherwise use the average
                avg_resp = response_inv.select(
                    station='AVG', channel=chan_code)[0][0][0].response
                chan.response = avg_resp
                chans.append(chan)
        sta = Station(code=sta_code,
                      latitude=chans[0].latitude,
                      longitude=chans[0].longitude,
                      elevation=chans[0].elevation,
                      channels=chans)
        sta.extra = extra
        inv[0].stations.append(sta)
    return inv
예제 #30
0
for row, station_df in survey_df.iterrows():
    sta = Station(code=station_df['siteID'],
                  latitude=station_df['lat'],
                  longitude=station_df['lon'],
                  elevation=station_df['nm_elev'],
                  creation_date=obspy.UTCDateTime(2016, 1, 2),
                  site=Site(name=station_df['siteID']))

    for comp in ['ex', 'ey', 'hx', 'hy', 'hz']:
        if station_df['{0}_azm'.format(comp)] is not None:
            if 'h' in comp:
                cha = Channel(code=comp.upper(),
                              location_code="",
                              latitude=station_df['lat'],
                              longitude=station_df['lon'],
                              elevation=station_df['nm_elev'],
                              depth=0,
                              azimuth=station_df['{0}_azm'.format(comp)],
                              dip=0,
                              sample_rate=station_df['sampling_rate'])
                cha.channel_number = station_df['{0}_num'.format(comp)]
                cha.sensor = Equipment(
                    serial_number=station_df['{0}_id'.format(comp)])
            elif 'e' in comp:
                cha = Channel(code=comp.upper(),
                              location_code="",
                              latitude=station_df['lat'],
                              longitude=station_df['lon'],
                              elevation=station_df['nm_elev'],
                              depth=0,
                              azimuth=station_df['{0}_azm'.format(comp)],