obspy中文教程(八)

 

Handling custom defined tags in QuakeML and the ObsPy Catalog/Event framework (在QuakeML和ObsPy的目录/事件框架中处理自定义标记)

除了QuakeML标准定义的“usual”信息之外,QuakeML还允许使用自定义元素。它允许:

  1. a自定义命名空间属性到QuakeML命名空间标记
  2. b自定义命名空间子标签到QuakeML命名空间元素

ObsPy可以在输入/输出QuakeML的过程中处理事件类型对象中的基本自定义标记和自定义属性。

以下基本示例说明如何使用自定义xml标记/属性输出有效的QuakeML文件:

from obspy import Catalog, UTCDateTime



extra = {'my_tag': {'value': True,

                    'namespace': 'http://some-page.de/xmlns/1.0',

                    'attrib': {'{http://some-page.de/xmlns/1.0}my_attrib1': '123.4',

                               '{http://some-page.de/xmlns/1.0}my_attrib2': '567'}},

         'my_tag_2': {'value': u'True',

                      'namespace': 'http://some-page.de/xmlns/1.0'},

         'my_tag_3': {'value': 1,

                      'namespace': 'http://some-page.de/xmlns/1.0'},

         'my_tag_4': {'value': UTCDateTime('2013-01-02T13:12:14.600000Z'),

                      'namespace': 'http://test.org/xmlns/0.1'},

         'my_attribute': {'value': 'my_attribute_value',

                          'type': 'attribute',

                          'namespace': 'http://test.org/xmlns/0.1'}}



cat = Catalog()

cat.extra = extra

cat.write('my_catalog.xml', format='QUAKEML',

          nsmap={'my_ns': 'http://test.org/xmlns/0.1'})

所有储存在自定义QuakeML中的信息必须存为带有自定义信息(如Catalog, Event, Pick)的extra属性的dictAttribDict对象。关键字用作xml标记的名称,xml标记的内容在一个字典中定义:'value'定义标记的内容(对象的字符串表示形式存储在文本xml输出中)。 'namespace'必须为标记指定自定义命名空间。 'type'可用于指定额外信息是应存储为子元素('element',default)还是存储为属性('attribute')。 自定义子元素的属性可以以字典的形式提供为'attrib'。如果需要更好的可读性,输出xml中的命名空间缩写可以在输出期间指定为QuakeML,方法是将命名空间缩写映射字典作为nsmap参数提供给Catalog.write()。上例的xml输出如下所示:

<?xml version='1.0' encoding='utf-8'?>

<q:quakeml xmlns:q='http://quakeml.org/xmlns/quakeml/1.2'

           xmlns:ns0='http://some-page.de/xmlns/1.0'

           xmlns:my_ns='http://test.org/xmlns/0.1'

           xmlns='http://quakeml.org/xmlns/bed/1.2'>

  <eventParameters publicID='smi:local/b425518c-9445-40c7-8284-d1f299ed2eac'

                   my_ns:my_attribute='my_attribute_value'>

    <ns0:my_tag ns0:my_attrib1='123.4' ns0:my_attrib2='567'>true</ns0:my_tag>

    <my_ns:my_tag_4>2013-01-02T13:12:14.600000Z</my_ns:my_tag_4>

    <ns0:my_tag_2>True</ns0:my_tag_2>

    <ns0:my_tag_3>1</ns0:my_tag_3>

  </eventParameters>

</q:quakeml>

再次使用read_events()读取上述xml时,自定义标记被解析并附加到相应的事件类型对象(在此示例中为Catalog对象)为“.extra”。 请注意,所有值都作为文本字符串读取:

from obspy import read_events



cat = read_events('my_catalog.xml')

print(cat.extra)

 

AttribDict({u'my_tag': {u'attrib': {'{http://some-page.de/xmlns/1.0}my_attrib2': '567',

                                    '{http://some-page.de/xmlns/1.0}my_attrib1': '123.4'},

                        u'namespace': u'http://some-page.de/xmlns/1.0',

                        u'value': 'true'},

            u'my_tag_4': {u'namespace': u'http://test.org/xmlns/0.1',

                          u'value': '2013-01-02T13:12:14.600000Z'},

            u'my_attribute': {u'type': u'attribute',

                              u'namespace': u'http://test.org/xmlns/0.1',

                              u'value': 'my_attribute_value'},

            u'my_tag_2': {u'namespace': u'http://some-page.de/xmlns/1.0',

                          u'value': 'True'},

            u'my_tag_3': {u'namespace': u'http://some-page.de/xmlns/1.0',

                          u'value': '1'}})

自定义标签可以嵌套:

from obspy import Catalog

from obspy.core import AttribDict



ns = 'http://some-page.de/xmlns/1.0'



my_tag = AttribDict()

my_tag.namespace = ns

my_tag.value = AttribDict()



my_tag.value.my_nested_tag1 = AttribDict()

my_tag.value.my_nested_tag1.namespace = ns

my_tag.value.my_nested_tag1.value = 1.23E+10



my_tag.value.my_nested_tag2 = AttribDict()

my_tag.value.my_nested_tag2.namespace = ns

my_tag.value.my_nested_tag2.value = True



cat = Catalog()

cat.extra = AttribDict()

cat.extra.my_tag = my_tag

cat.write('my_catalog.xml', 'QUAKEML')

这将产生类似于以下内容的xml输出:

<?xml version='1.0' encoding='utf-8'?>

<q:quakeml xmlns:q='http://quakeml.org/xmlns/quakeml/1.2'

           xmlns:ns0='http://some-page.de/xmlns/1.0'

           xmlns='http://quakeml.org/xmlns/bed/1.2'>

  <eventParameters publicID='smi:local/97d2b338-0701-41a4-9b6b-5903048bc341'>

    <ns0:my_tag>

      <ns0:my_nested_tag1>12300000000.0</ns0:my_nested_tag1>

      <ns0:my_nested_tag2>true</ns0:my_nested_tag2>

    </ns0:my_tag>

  </eventParameters>

</q:quakeml>

输出的XML可以再次使用read_events()读取,嵌套标签可使用下面的方法检索:

from obspy import read_events



cat = read_events('my_catalog.xml')

print(cat.extra.my_tag.value.my_nested_tag1.value)

print(cat.extra.my_tag.value.my_nested_tag2.value)

结果:

12300000000.0

true

可以使用OrderedDict为额外属性控制额外标签的顺序:

from collections import OrderedDict

from obspy.core.event import Catalog, Event



ns = 'http://some-page.de/xmlns/1.0'



my_tag1 = {'namespace': ns, 'value': 'some value 1'}

my_tag2 = {'namespace': ns, 'value': 'some value 2'}



event = Event()

cat = Catalog(events=[event])

event.extra = OrderedDict()

event.extra['myFirstExtraTag'] = my_tag2

event.extra['mySecondExtraTag'] = my_tag1

cat.write('my_catalog.xml', 'QUAKEML')

 

Handling custom defined tags in StationXML with the Obspy Inventory(使用Obspy Inventory处理StationXML中的自定义标签)

以下基本示例说明如何输出包含其他xml标记/属性的StationXML文件:

from obspy import Inventory, UTCDateTime

from obspy.core.inventory import Network

from obspy.core.util import AttribDict



extra = AttribDict({

           'my_tag': {

                'value': True,

                'namespace': 'http://some-page.de/xmlns/1.0',

                'attrib': {

                  '{http://some-page.de/xmlns/1.0}my_attrib1': '123.4',

                  '{http://some-page.de/xmlns/1.0}my_attrib2': '567'

                }

            },

           'my_tag_2': {

                'value': u'True',

                'namespace': 'http://some-page.de/xmlns/1.0'

            },

           'my_tag_3': {

                'value': 1,

                'namespace': 'http://some-page.de/xmlns/1.0'

            },

           'my_tag_4': {

                'value': UTCDateTime('2013-01-02T13:12:14.600000Z'),

                'namespace': 'http://test.org/xmlns/0.1'

            },

           'my_attribute': {

                'value': 'my_attribute_value',

                'type': 'attribute',

                'namespace': 'http://test.org/xmlns/0.1'

            }

        })



inv = Inventory([Network('XX')], 'XX')

inv[0].extra = extra

inv.write('my_inventory.xml', format='STATIONXML',

          nsmap={'my_ns': 'http://test.org/xmlns/0.1',

                 'somepage_ns': 'http://some-page.de/xmlns/1.0'})

要存储在定制的StationXML中的所有自定义信息必须以dictAttribDict对象的形式存储,作为应携带附加自定义信息的对象的.extra属性(例如,Network, Station, Channel)。关键字作xml标记的名称,xml标记的内容在简单字典中定义:'value'定义标记的内容(对象的字符串表示形式存储在文本xml输出中)。 'namespace'必须为标记指定自定义命名空间。 'type'可用于指定额外信息是应存储为子元素('element',default)还是存储为属性('attribute')。 自定义子元素的属性可以以字典的形式提供为“attrib”。

如果需要更好可读性,输出xml中的命名空间缩写可以在输出期间指定为StationXML,方法是将名称空间缩写映射字典作为nsmap参数提供给Inventory.write()。xml输出如下所示:

<?xml version='1.0' encoding='UTF-8'?>

<FDSNStationXML xmlns:my_ns="http://test.org/xmlns/0.1" xmlns:somepage_ns="http://some-page.de/xmlns/1.0" xmlns="http://www.fdsn.org/xml/station/1" schemaVersion="1.0">

  <Source>XX</Source>

  <Module>ObsPy 1.0.2</Module>

  <ModuleURI>https://www.obspy.org</ModuleURI>

  <Created>2016-10-17T18:32:28.696287+00:00</Created>

  <Network code="XX">

    <somepage_ns:my_tag somepage_ns:my_attrib1="123.4" somepage_ns:my_attrib2="567">True</somepage_ns:my_tag>

    <my_ns:my_tag_4>2013-01-02T13:12:14.600000Z</my_ns:my_tag_4>

    <my_ns:my_attribute>my_attribute_value</my_ns:my_attribute>

    <somepage_ns:my_tag_2>True</somepage_ns:my_tag_2>

    <somepage_ns:my_tag_3>1</somepage_ns:my_tag_3>

  </Network>

</FDSNStationXML>

再次读取上面的XML时,使用read_inventory(),自定义标记被解析并作为为'.extra'附加到相应的网络类型对象(在此示例中为Inventory对象)。请注意,所有值都作为文本字符串读取:

from obspy import read_inventory



inv = read_inventory('my_inventory.xml')

print(inv[0].extra)

 

AttribDict({

    u'my_tag': AttribDict({

        'attrib': {

          '{http://some-page.de/xmlns/1.0}my_attrib2': '567',

          '{http://some-page.de/xmlns/1.0}my_attrib1': '123.4'

        },

        'namespace': 'http://some-page.de/xmlns/1.0',

        'value': 'True'

    }),

    u'my_tag_4': AttribDict({

        'namespace': 'http://test.org/xmlns/0.1',

        'value': '2013-01-02T13:12:14.600000Z'

    }),

    u'my_attribute': AttribDict({

        'namespace': 'http://test.org/xmlns/0.1',

        'value': 'my_attribute_value'

    }),

    u'my_tag_2': AttribDict({

        'namespace': 'http://some-page.de/xmlns/1.0',

        'value': 'True'

    }),

    u'my_tag_3': AttribDict({

        'namespace': 'http://some-page.de/xmlns/1.0',

        'value': '1'

    })

})

 

自定义标签可以嵌套:

from obspy import Inventory

from obspy.core.inventory import Network

from obspy.core.util import AttribDict



ns = 'http://some-page.de/xmlns/1.0'



my_tag = AttribDict()

my_tag.namespace = ns

my_tag.value = AttribDict()



my_tag.value.my_nested_tag1 = AttribDict()

my_tag.value.my_nested_tag1.namespace = ns

my_tag.value.my_nested_tag1.value = 1.23E+10



my_tag.value.my_nested_tag2 = AttribDict()

my_tag.value.my_nested_tag2.namespace = ns

my_tag.value.my_nested_tag2.value = True



inv = Inventory([Network('XX')], 'XX')

inv[0].extra = AttribDict()

inv[0].extra.my_tag = my_tag

inv.write('my_inventory.xml', format='STATIONXML',

          nsmap={'somepage_ns': 'http://some-page.de/xmlns/1.0'})

这将产生类似于以下内容的xml输出:

<?xml version='1.0' encoding='UTF-8'?>

<FDSNStationXML xmlns:somepage_ns="http://some-page.de/xmlns/1.0" xmlns="http://www.fdsn.org/xml/station/1" schemaVersion="1.0">

  <Source>XX</Source>

  <Module>ObsPy 1.0.2</Module>

  <ModuleURI>https://www.obspy.org</ModuleURI>

  <Created>2016-10-17T18:45:14.302265+00:00</Created>

  <Network code="XX">

    <somepage_ns:my_tag>

      <somepage_ns:my_nested_tag1>12300000000.0</somepage_ns:my_nested_tag1>

      <somepage_ns:my_nested_tag2>True</somepage_ns:my_nested_tag2>

    </somepage_ns:my_tag>

  </Network>

</FDSNStationXML>

输出XML可以使用read_inventory()再次读取,嵌套标签使用下面的方法检索:

from obspy import read_inventory



inv = read_inventory('my_inventory.xml')

print(inv[0].extra.my_tag.value.my_nested_tag1.value)

print(inv[0].extra.my_tag.value.my_nested_tag2.value)

结果:

12300000000.0

True

 

Creating a StationXML file from Scratch(从Scratch创建StationXML文件)

在地震学中有时需要创建自定义StationXML文件。本节演示如何使用ObsPy完成这样的任务请注意,这不一定比直接编辑XML文件更容易或更容易观察,但它确实提供了一种与ObsPy的其余部分更紧密结合的方法,并且可以保证最终结果有效。

这里假定您对FDSN StationXML standard.有一定的了解。我们将创建一个相当简单的StationXML文件,并且许多参数是可选的。 ObsPy将在写入时根据其模式验证生成的StationXML文件,以确保最终文件对StationXML模式有效。下图显示了ObsPy内部表示的基本结构。

每个大框都是一个对象,所有对象都必须分层链接以形成一个Inventory对象。Inventory可以包含任意数量的网络对象,这些对象又可以包含任意数量的工作站对象,这些工具又可以包含任意数量的信道对象。对于每个信道,仪器响应可以存储为response属性。

使用ObsPy的NRL客户端,可以从IRIS DMC Library of Nominal Responses(NRL)中查找仪器响应并将其附加到每个信道。

import obspy

from obspy.core.inventory import Inventory, Network, Station, Channel, Site

from obspy.clients.nrl import NRL





# 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="XX",

    # 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="ABC",

    latitude=1.0,

    longitude=2.0,

    elevation=345.0,

    creation_date=obspy.UTCDateTime(2016, 1, 2),

    site=Site(name="First station"))



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.

    latitude=1.0,

    longitude=2.0,

    elevation=345.0,

    depth=10.0,

    azimuth=0.0,

    dip=-90.0,

    sample_rate=200)



# 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.

inv.write("station.xml", format="stationxml", validate=True)

 

Connecting to a SeedLink Server(连接到SeedLink服务器)

obspy.clients.seedlink模块提供了Python实现的SeedLink客户端协议。obspy.clients.seedlink.easyseedlink子模块包含SeedLink实现的高级接口,有助于创建SeedLink客户端。

create_client函数

使用create_client()函数创建一个新的EasySeedLinkClient类是连接到SeedLink服务器的最简单方法。它接受一个从SeedLink服务器接收的新数据的函数作为参数,例如:

def handle_data(trace):

    print('Received the following trace:')

    print(trace)

    print()

此函数随后可以与SeedLink服务器URL一同传递给create_client()创建一个客户端:

client = create_client('geofon.gfz-potsdam.de', on_data=handle_data)

客户端在创建时立即连接到服务器。

 

发送INFO请求到服务器

客户端可以发送INFO请求到服务器:

# Send the INFO:ID request

client.get_info('ID')



# Returns:

# <?xml version="1.0"?>\n<seedlink software="SeedLink v3.2 (2014.071)" organization="GEOFON" started="2014/09/01 14:08:37.4192"/>\n

INFO请求的响应是XML格式的。客户端提供了检索和解析服务器功能的快捷方式(经由一个INFO:CAPABILITIES请求。)

>>> client.capabilities

['dialup', 'multistation', 'window-extraction', 'info:id', 'info:capabilities', 'info:stations', 'info:streams']

首次访问属性时会提取和解析这些功能,并在此之后进行缓存。

从服务器传输数据流

为了开始接受波形数据,需要先通过select_stream()函数选择至少一个stream。

client.select_stream('BW', 'MANZ', 'EHZ')

多个stream也可以被选择,也支持SeedLink通配符:

client.select_stream('BW', 'ROTZ', 'EH?')

选择stream后,客户端就准备好进入streaming模式了:

client.run()

这将从服务器开始流式传输数据。 在从服务器接收的每个完整跟踪时,使用跟踪对象调用上面定义的函数:

Received new data:

BW.MANZ..EHZ | 2014-09-04T19:47:25.625000Z - 2014-09-04T19:47:26.770000Z | 200.0 Hz, 230 samples



Received new data:

BW.ROTZ..EHZ | 2014-09-04T19:47:22.685000Z - 2014-09-04T19:47:24.740000Z | 200.0 Hz, 412 samples



Received new data:

BW.ROTZ..EHZ | 2014-09-04T19:47:24.745000Z - 2014-09-04T19:47:26.800000Z | 200.0 Hz, 412 samples



Received new data:

BW.ROTZ..EHN | 2014-09-04T19:47:20.870000Z - 2014-09-04T19:47:22.925000Z | 200.0 Hz, 412 samples



Received new data:

BW.ROTZ..EHN | 2014-09-04T19:47:22.930000Z - 2014-09-04T19:47:24.985000Z | 200.0 Hz, 412 samples

高级用法:子类化客户端

对于高级用法,继承EasySeedLinkClient类可以更好地控制。下列代码实现与上面相同的客户端:

class DemoClient(EasySeedLinkClient):

    """

    A custom SeedLink client

    """

    def on_data(self, trace):

        """

        Override the on_data callback

        """

        print('Received trace:')

        print(trace)

        print()

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值