def test_xpathWithNamespace(self): """ Tests for XMLParser.xpath """ # xml + iris # XXX xml_etree is now C extension, skipping #xml_doc = xml_etree.parse(self.iris_xml) #p = XMLParser(xml_doc) #ns = p._getFirstChildNamespace() #result = p.xpath('*/event', namespace=ns) #self.assertEqual(len(result), 2) #self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') #result = p.xpath('eventParameters/event', namespace=ns) #self.assertEqual(len(result), 2) #self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') # lxml + iris xml_doc = lxml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) ns = p._getFirstChildNamespace() result = p.xpath('*/event', namespace=ns) self.assertEqual(len(result), 2) self.assertTrue(isinstance(result[0], lxml_etree._Element)) result = p.xpath('eventParameters/event', namespace=ns) self.assertEqual(len(result), 2) self.assertTrue(isinstance(result[0], lxml_etree._Element)) # xml + neries # XXX xml_etree is now C extension, skipping #xml_doc = xml_etree.parse(self.neries_xml) #p = XMLParser(xml_doc) #ns = p._getFirstChildNamespace() #result = p.xpath('*/event', namespace=ns) #self.assertEqual(len(result), 3) #self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') #result = p.xpath('eventParameters/event', namespace=ns) #self.assertEqual(len(result), 3) #self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') # lxml + neries xml_doc = lxml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) ns = p._getFirstChildNamespace() result = p.xpath('*/event', namespace=ns) self.assertEqual(len(result), 3) self.assertTrue(isinstance(result[0], lxml_etree._Element)) result = p.xpath('eventParameters/event', namespace=ns) self.assertEqual(len(result), 3) self.assertTrue(isinstance(result[0], lxml_etree._Element))
def isSeishubEventFile(filename): """ Checks whether a file is a Seishub Event file. This is a very rough test as the format is not very well defined and has no unique features. :type filename: str :param filename: Name of the Seishub event file to be checked. :rtype: bool :return: ``True`` if Seishub event file. .. rubric:: Example """ try: parser = XMLParser(filename) except: return False # Simply check to paths that should always exist. if parser.xpath('event_id/value') and parser.xpath('event_type/value'): return True return False
def test_xpathWithNamespace(self): """ Tests for XMLParser.xpath """ # xml + iris # XXX xml_etree is now C extension, skipping # xml_doc = xml_etree.parse(self.iris_xml) # p = XMLParser(xml_doc) # ns = p._getFirstChildNamespace() # result = p.xpath('*/event', namespace=ns) # self.assertEqual(len(result), 2) # self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') # result = p.xpath('eventParameters/event', namespace=ns) # self.assertEqual(len(result), 2) # self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') # lxml + iris xml_doc = lxml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) ns = p._getFirstChildNamespace() result = p.xpath('*/event', namespace=ns) self.assertEqual(len(result), 2) self.assertTrue(isinstance(result[0], lxml_etree._Element)) result = p.xpath('eventParameters/event', namespace=ns) self.assertEqual(len(result), 2) self.assertTrue(isinstance(result[0], lxml_etree._Element)) # xml + neries # XXX xml_etree is now C extension, skipping # xml_doc = xml_etree.parse(self.neries_xml) # p = XMLParser(xml_doc) # ns = p._getFirstChildNamespace() # result = p.xpath('*/event', namespace=ns) # self.assertEqual(len(result), 3) # self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') # result = p.xpath('eventParameters/event', namespace=ns) # self.assertEqual(len(result), 3) # self.assertEqual(result[0].__module__, 'xml.etree.ElementTree') # lxml + neries xml_doc = lxml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) ns = p._getFirstChildNamespace() result = p.xpath('*/event', namespace=ns) self.assertEqual(len(result), 3) self.assertTrue(isinstance(result[0], lxml_etree._Element)) result = p.xpath('eventParameters/event', namespace=ns) self.assertEqual(len(result), 3) self.assertTrue(isinstance(result[0], lxml_etree._Element))
def test_getRootNamespace(self): """ Tests for XMLParser._getRootNamespace """ # xml + iris xml_doc = xml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) self.assertEqual(p._getRootNamespace(), "http://quakeml.org/xmlns/quakeml/1.2") # xml + neries xml_doc = xml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) self.assertEqual(p._getRootNamespace(), "http://quakeml.org/xmlns/quakeml/1.0") # lxml + iris xml_doc = lxml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) self.assertEqual(p._getRootNamespace(), "http://quakeml.org/xmlns/quakeml/1.2") # lxml + neries xml_doc = lxml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) self.assertEqual(p._getRootNamespace(), "http://quakeml.org/xmlns/quakeml/1.0")
def test_init(self): """ Tests the __init__ method of the XMLParser object. """ # parser accepts # 1 - filenames XMLParser(self.iris_xml) # 2 - XML strings data = XML_DOC XMLParser(data) # 3 - file like objects fh = open(self.iris_xml, 'rt') XMLParser(fh) fh.close() # 4 - StringIO data = StringIO.StringIO(XML_DOC) XMLParser(data) # 5 - with xml parsed XML documents xml_doc = xml_etree.parse(self.iris_xml) XMLParser(xml_doc) # 6 - with lxml parsed XML documents xml_doc = lxml_etree.parse(self.iris_xml) XMLParser(xml_doc)
def test_xpath(self): """ Tests the xpath method of the XMLParser object. """ parser = XMLParser(XML_DOC) # 1st level q = parser.xpath('notexisting') self.assertEqual([e.tag for e in q], []) q = parser.xpath('request') self.assertEqual([e.tag for e in q], ['request', 'request']) q = parser.xpath('/request') self.assertEqual([e.tag for e in q], ['request', 'request']) q = parser.xpath('*') self.assertEqual([e.tag for e in q], ['request', 'request']) q = parser.xpath('/*') self.assertEqual([e.tag for e in q], ['request', 'request']) # 2nd level q = parser.xpath('*/*') self.assertEqual([e.tag for e in q], ['volume', 'test']) q = parser.xpath('/*/*') self.assertEqual([e.tag for e in q], ['volume', 'test']) q = parser.xpath('*/volume') self.assertEqual([e.tag for e in q], ['volume']) q = parser.xpath('request/*') self.assertEqual([e.tag for e in q], ['volume', 'test']) q = parser.xpath('request/volume') self.assertEqual([e.tag for e in q], ['volume']) q = parser.xpath('/request/volume') self.assertEqual([e.tag for e in q], ['volume']) # 3rd level q = parser.xpath('*/*/*') self.assertEqual([e.tag for e in q], ['line', 'line']) q = parser.xpath('/request/test/doesnotexist') self.assertEqual([e.tag for e in q], []) # element selector (first element starts with 1) q = parser.xpath('/*/*/*[2]') self.assertEqual([e.tag for e in q], ['line']) q = parser.xpath('/*/*/*[100]') self.assertEqual([e.tag for e in q], [])
def test_getElementNamespace(self): """ Tests for XMLParser._getElementNamespace """ # xml + iris xml_doc = xml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) eventParameters = p.xml_root[0] self.assertEqual(p._getElementNamespace(eventParameters), "http://quakeml.org/xmlns/bed/1.2") # xml + neries xml_doc = xml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) eventParameters = p.xml_root[0] self.assertEqual(p._getElementNamespace(eventParameters), "http://quakeml.org/xmlns/quakeml/1.0") # lxml + iris xml_doc = lxml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) eventParameters = p.xml_root[0] self.assertEqual(p._getElementNamespace(eventParameters), "http://quakeml.org/xmlns/bed/1.2") # lxml + neries xml_doc = lxml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) eventParameters = p.xml_root[0] self.assertEqual(p._getElementNamespace(eventParameters), "http://quakeml.org/xmlns/quakeml/1.0") # checking sub elements # xml + iris xml_doc = xml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) event = p.xml_root[0][0] self.assertEqual(p._getElementNamespace(event), "http://quakeml.org/xmlns/bed/1.2") # xml + neries xml_doc = xml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) event = p.xml_root[0][0] self.assertEqual(p._getElementNamespace(event), "http://quakeml.org/xmlns/quakeml/1.0") # lxml + iris xml_doc = lxml_etree.parse(self.iris_xml) p = XMLParser(xml_doc) event = p.xml_root[0][0] self.assertEqual(p._getElementNamespace(event), "http://quakeml.org/xmlns/bed/1.2") # lxml + neries xml_doc = lxml_etree.parse(self.neries_xml) p = XMLParser(xml_doc) event = p.xml_root[0][0] self.assertEqual(p._getElementNamespace(event), "http://quakeml.org/xmlns/quakeml/1.0")
def readSeishubEventFile(filename): """ Reads a Seishub event file and returns a ObsPy Catalog object. .. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.event.readEvents` function, call this instead. :type filename: str :param filename: Seishub event file to be read. :rtype: :class:`~obspy.core.event.Catalog` :return: A ObsPy Catalog object. .. rubric:: Example """ # Just init the parser, the SeisHub event file format has no namespaces. parser = XMLParser(filename) # A Seishub event just specifies a single event so Catalog information is # not really given. catalog = Catalog() # Create new Event object. public_id = parser.xpath('event_id/value')[0].text # Read the event_type tag. pick_method = parser.xpath2obj('event_type/account', parser, str) user = parser.xpath2obj('event_type/user', parser, str) global_evaluation_mode = parser.xpath2obj('event_type/value', parser, str) # The author will be stored in the CreationInfo object. This will be the # creation info of the event as well as on all picks. creation_info = {"author": user} # Create the event object. event = Event(resource_id=public_id, creation_info=creation_info) # Parse the origins. for origin_el in parser.xpath("origin"): origin = __toOrigin(parser, origin_el) event.origins.append(origin) # There should always be only one origin. assert(len(event.origins) == 1) # Parse the magnitudes. for magnitude_el in parser.xpath("magnitude"): magnitude = __toMagnitude(parser, magnitude_el) event.magnitudes.append(magnitude) # Parse the station magnitudes. for stat_magnitude_el in parser.xpath("stationMagnitude"): stat_magnitude = __toStationMagnitude(parser, stat_magnitude_el) event.station_magnitudes.append(stat_magnitude) # Parse the picks. Pass the global evaluation mode (automatic, manual) for pick_el in parser.xpath("pick"): pick = __toPick(parser, pick_el, global_evaluation_mode) event.picks.append(pick) # Append the creation info to all picks. And also add the pick_method, e.g. # the event_type/account value as the method_id to the picks. for pick in event.picks: pick.creation_info = creation_info pick.method_id = pick_method # In QuakeML a StationMagnitude object has to be associated with an Origin. # This in turn means that the origin needs to have a resource_id. event.origins[0].resource_id = "smi:local/origins/%s" % \ event.resource_id.resource_id for mag in event.station_magnitudes: mag.origin_id = event.origins[0].resource_id # Add the event to the catalog catalog.append(event) return catalog
def readSeishubEventFile(filename): """ Reads a Seishub event file and returns a ObsPy Catalog object. .. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.event.readEvents` function, call this instead. :type filename: str :param filename: Seishub event file to be read. :rtype: :class:`~obspy.core.event.Catalog` :return: A ObsPy Catalog object. .. rubric:: Example """ global CURRENT_TYPE base_name = os.path.basename(filename) if base_name.lower().startswith("baynet"): CURRENT_TYPE = "baynet" elif base_name.lower().startswith("earthworm"): CURRENT_TYPE = "earthworm" elif base_name.lower().startswith("gof"): CURRENT_TYPE = "seiscomp3" elif base_name.lower().startswith("obspyck") or base_name == "5622": CURRENT_TYPE = "obspyck" elif base_name.lower().startswith("toni"): CURRENT_TYPE = "toni" else: print "AAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHH" raise Exception # Just init the parser, the SeisHub event file format has no namespaces. parser = XMLParser(filename) # Create new Event object. public_id = parser.xpath('event_id/value')[0].text # A Seishub event just specifies a single event so Catalog information is # not really given. catalog = Catalog() catalog.resource_id = "/".join([RESOURCE_ROOT, "catalog", public_id]) # Read the event_type tag. account = parser.xpath2obj('event_type/account', parser, str) user = parser.xpath2obj('event_type/user', parser, str) global_evaluation_mode = parser.xpath2obj('event_type/value', parser, str) public = parser.xpath2obj('event_type/public', parser, str) public = {"True": True, "False": False}.get(public, None) if account is not None and account.lower() != "sysop": public = False # The author will be stored in the CreationInfo object. This will be the # creation info of the event as well as on all picks. author = user if CURRENT_TYPE in ["seiscomp3", "earthworm"]: author = CURRENT_TYPE creation_info = {"author": author, "agency_id": "Erdbebendienst Bayern", "agency_uri": "%s/agency" % RESOURCE_ROOT, "creation_time": NOW} # Create the event object. event = Event(resource_id="/".join([RESOURCE_ROOT, "event", public_id]), creation_info=creation_info) # If account is None or 'sysop' and public is true, write 'public in the # comment, 'private' otherwise. event.extra = AttribDict() event.extra.public = {'value': public, 'namespace': NAMESPACE} event.extra.evaluationMode = {'value': global_evaluation_mode, 'namespace': NAMESPACE} event_type = parser.xpath2obj('type', parser, str) if event_type is not None: if event_type == "induced earthquake": event_type = "induced or triggered event" if event_type != "null": event.event_type = event_type # Parse the origins. origins = parser.xpath("origin") if len(origins) > 1: msg = "Only files with a single origin are currently supported" raise Exception(msg) for origin_el in parser.xpath("origin"): origin = __toOrigin(parser, origin_el) event.origins.append(origin) # Parse the magnitudes. for magnitude_el in parser.xpath("magnitude"): magnitude = __toMagnitude(parser, magnitude_el, origin) if magnitude.mag is None: continue event.magnitudes.append(magnitude) # Parse the picks. Pass the global evaluation mode (automatic, manual) for pick_el in parser.xpath("pick"): pick = __toPick(parser, pick_el, global_evaluation_mode) if pick is None: continue event.picks.append(pick) # The arrival object gets the following things from the Seishub.pick # objects # arrival.time_weight = pick.phase_weight # arrival.time_residual = pick.phase_res # arrival.azimuth = pick.azimuth # arrival.take_off_angle = pick.incident # arrival.distance = hyp_dist arrival = __toArrival(parser, pick_el, global_evaluation_mode, pick) if event.origins: event.origins[0].arrivals.append(arrival) for mag in event.station_magnitudes: mag.origin_id = event.origins[0].resource_id # Parse the station magnitudes. for stat_magnitude_el in parser.xpath("stationMagnitude"): stat_magnitude = __toStationMagnitude(parser, stat_magnitude_el) event.station_magnitudes.append(stat_magnitude) # Parse the amplitudes # we don't reference their id in the corresponding station magnitude, # because we use one amplitude measurement for each component for el in parser.xpath("stationMagnitude/amplitude"): event.amplitudes.append(__toAmplitude(parser, el)) for mag in event.station_magnitudes: mag.origin_id = event.origins[0].resource_id for _i, stat_mag in enumerate(event.station_magnitudes): contrib = StationMagnitudeContribution() weight = None # The order of station magnitude objects is the same as in the xml # file. weight = parser.xpath2obj("weight", parser.xpath("stationMagnitude")[_i], float) if weight is not None: contrib.weight = weight contrib.station_magnitude_id = stat_mag.resource_id event.magnitudes[0].station_magnitude_contributions.append(contrib) for foc_mec_el in parser.xpath("focalMechanism"): foc_mec = __toFocalMechanism(parser, foc_mec_el) if foc_mec is not None: event.focal_mechanisms.append(foc_mec) # Set the origin id for the focal mechanisms. There is only one origin per # SeisHub event file. for focmec in event.focal_mechanisms: focmec.triggering_origin_id = event.origins[0].resource_id # Add the event to the catalog catalog.append(event) return catalog
def readSeishubEventFile(filename): """ Reads a Seishub event file and returns a ObsPy Catalog object. .. warning:: This function should NOT be called directly, it registers via the ObsPy :func:`~obspy.core.event.readEvents` function, call this instead. :type filename: str :param filename: Seishub event file to be read. :rtype: :class:`~obspy.core.event.Catalog` :return: A ObsPy Catalog object. .. rubric:: Example """ global CURRENT_TYPE base_name = os.path.basename(filename) if base_name.lower().startswith("baynet"): CURRENT_TYPE = "baynet" elif base_name.lower().startswith("earthworm"): CURRENT_TYPE = "earthworm" elif base_name.lower().startswith("gof"): CURRENT_TYPE = "seiscomp3" elif base_name.lower().startswith("obspyck") or base_name == "5622": CURRENT_TYPE = "obspyck" elif base_name.lower().startswith("toni"): CURRENT_TYPE = "toni" else: print "AAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHH" raise Exception # Just init the parser, the SeisHub event file format has no namespaces. parser = XMLParser(filename) # Create new Event object. public_id = parser.xpath('event_id/value')[0].text # A Seishub event just specifies a single event so Catalog information is # not really given. catalog = Catalog() catalog.resource_id = "/".join([RESOURCE_ROOT, "catalog", public_id]) # Read the event_type tag. account = parser.xpath2obj('event_type/account', parser, str) user = parser.xpath2obj('event_type/user', parser, str) global_evaluation_mode = parser.xpath2obj('event_type/value', parser, str) public = parser.xpath2obj('event_type/public', parser, str) public = { "True": True, "False": False, "true": True, "false": False }.get(public, None) if account is not None and account.lower() != "sysop": public = False # The author will be stored in the CreationInfo object. This will be the # creation info of the event as well as on all picks. author = user if CURRENT_TYPE in ["seiscomp3", "earthworm"]: public = False author = CURRENT_TYPE global_evaluation_mode = "automatic" elif CURRENT_TYPE in ["baynet", "toni"]: public = True author = CURRENT_TYPE global_evaluation_mode = "manual" creation_info = { "author": author, "agency_id": "Erdbebendienst Bayern", "agency_uri": "%s/agency" % RESOURCE_ROOT, "creation_time": NOW } # Create the event object. event = Event(resource_id="/".join([RESOURCE_ROOT, "event", public_id]), creation_info=creation_info) # If account is None or 'sysop' and public is true, write 'public in the # comment, 'private' otherwise. event.extra = AttribDict() event.extra.public = {'value': public, 'namespace': NAMESPACE} event.extra.evaluationMode = { 'value': global_evaluation_mode, 'namespace': NAMESPACE } event_type = parser.xpath2obj('type', parser, str) if event_type is not None: if event_type == "induced earthquake": event_type = "induced or triggered event" if event_type != "null": event.event_type = event_type # Parse the origins. origins = parser.xpath("origin") if len(origins) > 1: msg = "Only files with a single origin are currently supported" raise Exception(msg) for origin_el in parser.xpath("origin"): origin = __toOrigin(parser, origin_el) event.origins.append(origin) # Parse the magnitudes. for magnitude_el in parser.xpath("magnitude"): magnitude = __toMagnitude(parser, magnitude_el, origin) if magnitude.mag is None: continue event.magnitudes.append(magnitude) # Parse the picks. Pass the global evaluation mode (automatic, manual) for pick_el in parser.xpath("pick"): pick = __toPick(parser, pick_el, global_evaluation_mode) if pick is None: continue event.picks.append(pick) # The arrival object gets the following things from the Seishub.pick # objects # arrival.time_weight = pick.phase_weight # arrival.time_residual = pick.phase_res # arrival.azimuth = pick.azimuth # arrival.take_off_angle = pick.incident # arrival.distance = hyp_dist arrival = __toArrival(parser, pick_el, global_evaluation_mode, pick) if event.origins: event.origins[0].arrivals.append(arrival) for mag in event.station_magnitudes: mag.origin_id = event.origins[0].resource_id # Parse the station magnitudes. for stat_magnitude_el in parser.xpath("stationMagnitude"): stat_magnitude = __toStationMagnitude(parser, stat_magnitude_el) event.station_magnitudes.append(stat_magnitude) # Parse the amplitudes # we don't reference their id in the corresponding station magnitude, # because we use one amplitude measurement for each component for el in parser.xpath("stationMagnitude/amplitude"): event.amplitudes.append(__toAmplitude(parser, el)) for mag in event.station_magnitudes: mag.origin_id = event.origins[0].resource_id for _i, stat_mag in enumerate(event.station_magnitudes): contrib = StationMagnitudeContribution() weight = None # The order of station magnitude objects is the same as in the xml # file. weight = parser.xpath2obj("weight", parser.xpath("stationMagnitude")[_i], float) if weight is not None: contrib.weight = weight contrib.station_magnitude_id = stat_mag.resource_id event.magnitudes[0].station_magnitude_contributions.append(contrib) for foc_mec_el in parser.xpath("focalMechanism"): foc_mec = __toFocalMechanism(parser, foc_mec_el) if foc_mec is not None: event.focal_mechanisms.append(foc_mec) # Set the origin id for the focal mechanisms. There is only one origin per # SeisHub event file. for focmec in event.focal_mechanisms: focmec.triggering_origin_id = event.origins[0].resource_id # Add the event to the catalog catalog.append(event) return catalog