def toTensor(a): t = Tensor(m_rr=a[0, 0], m_tt=a[1, 1], m_pp=a[2, 2], m_rt=a[0, 1], m_rp=a[0, 2], m_tp=a[1, 2]) return t
def _parseRecordDt(self, line, focal_mechanism): """ Parses the 'source parameter data - tensor' record Dt """ tensor = Tensor() exponent = self._intZero(line[3:5]) scale = math.pow(10, exponent) for i in xrange(6, 51 + 1, 9): code = line[i:i + 2] value = self._floatWithFormat(line[i + 2:i + 6], '4.2', scale) error = self._floatWithFormat(line[i + 6:i + 9], '3.2', scale) self._tensorStore(tensor, code, value, error) focal_mechanism.moment_tensor.tensor = tensor
def event_to_quakeml(event, filename): """ Write one of those events to QuakeML. """ # Create all objects. cat = Catalog() ev = Event() org = Origin() mag = Magnitude() fm = FocalMechanism() mt = MomentTensor() t = Tensor() # Link them together. cat.append(ev) ev.origins.append(org) ev.magnitudes.append(mag) ev.focal_mechanisms.append(fm) fm.moment_tensor = mt mt.tensor = t # Fill values ev.resource_id = "smi:inversion/%s" % str(event["identifier"]) org.time = event["time"] org.longitude = event["longitude"] org.latitude = event["latitude"] org.depth = event["depth_in_km"] * 1000 mag.mag = event["Mw"] mag.magnitude_type = "Mw" t.m_rr = event["Mrr"] t.m_tt = event["Mpp"] t.m_pp = event["Mtt"] t.m_rt = event["Mrt"] t.m_rp = event["Mrp"] t.m_tp = event["Mtp"] cat.write(filename, format="quakeml")
def test_creating_minimal_quakeml_with_mt(self): """ Tests the creation of a minimal QuakeML containing origin, magnitude and moment tensor. """ # Rotate into physical domain lat, lon, depth, org_time = 10.0, -20.0, 12000, UTCDateTime(2012, 1, 1) mrr, mtt, mpp, mtr, mpr, mtp = 1E18, 2E18, 3E18, 3E18, 2E18, 1E18 scalar_moment = math.sqrt( mrr ** 2 + mtt ** 2 + mpp ** 2 + mtr ** 2 + mpr ** 2 + mtp ** 2) moment_magnitude = 0.667 * (math.log10(scalar_moment) - 9.1) # Initialise event ev = Event(event_type="earthquake") ev_origin = Origin(time=org_time, latitude=lat, longitude=lon, depth=depth, resource_id=ResourceIdentifier()) ev.origins.append(ev_origin) # populate event moment tensor ev_tensor = Tensor(m_rr=mrr, m_tt=mtt, m_pp=mpp, m_rt=mtr, m_rp=mpr, m_tp=mtp) ev_momenttensor = MomentTensor(tensor=ev_tensor) ev_momenttensor.scalar_moment = scalar_moment ev_momenttensor.derived_origin_id = ev_origin.resource_id ev_focalmechanism = FocalMechanism(moment_tensor=ev_momenttensor) ev.focal_mechanisms.append(ev_focalmechanism) # populate event magnitude ev_magnitude = Magnitude() ev_magnitude.mag = moment_magnitude ev_magnitude.magnitude_type = 'Mw' ev_magnitude.evaluation_mode = 'automatic' ev.magnitudes.append(ev_magnitude) # write QuakeML file cat = Catalog(events=[ev]) memfile = io.BytesIO() cat.write(memfile, format="quakeml", validate=IS_RECENT_LXML) memfile.seek(0, 0) new_cat = _read_quakeml(memfile) self.assertEqual(len(new_cat), 1) event = new_cat[0] self.assertEqual(len(event.origins), 1) self.assertEqual(len(event.magnitudes), 1) self.assertEqual(len(event.focal_mechanisms), 1) org = event.origins[0] mag = event.magnitudes[0] fm = event.focal_mechanisms[0] self.assertEqual(org.latitude, lat) self.assertEqual(org.longitude, lon) self.assertEqual(org.depth, depth) self.assertEqual(org.time, org_time) # Moment tensor. mt = fm.moment_tensor.tensor self.assertTrue((fm.moment_tensor.scalar_moment - scalar_moment) / scalar_moment < scalar_moment * 1E-10) self.assertEqual(mt.m_rr, mrr) self.assertEqual(mt.m_pp, mpp) self.assertEqual(mt.m_tt, mtt) self.assertEqual(mt.m_rt, mtr) self.assertEqual(mt.m_rp, mpr) self.assertEqual(mt.m_tp, mtp) # Mag self.assertAlmostEqual(mag.mag, moment_magnitude) self.assertEqual(mag.magnitude_type, "Mw") self.assertEqual(mag.evaluation_mode, "automatic")
def _read_ndk(filename, *args, **kwargs): # @UnusedVariable """ Reads an NDK file to a :class:`~obspy.core.event.Catalog` object. :param filename: File or file-like object in text mode. """ # Read the whole file at once. While an iterator would be more efficient # the largest NDK file out in the wild is 13.7 MB so it does not matter # much. if not hasattr(filename, "read"): # Check if it exists, otherwise assume its a string. try: with open(filename, "rt") as fh: data = fh.read() except Exception: try: data = filename.decode() except Exception: data = str(filename) data = data.strip() else: data = filename.read() if hasattr(data, "decode"): data = data.decode() # Create iterator that yields lines. def lines_iter(): prev_line = -1 while True: next_line = data.find("\n", prev_line + 1) if next_line < 0: break yield data[prev_line + 1:next_line] prev_line = next_line if len(data) > prev_line + 1: yield data[prev_line + 1:] # Use one Flinn Engdahl object for all region determinations. fe = FlinnEngdahl() cat = Catalog(resource_id=_get_resource_id("catalog", str(uuid.uuid4()))) # Loop over 5 lines at once. for _i, lines in enumerate(zip_longest(*[lines_iter()] * 5)): if None in lines: msg = "Skipped last %i lines. Not a multiple of 5 lines." % ( lines.count(None)) warnings.warn(msg, ObsPyNDKWarning) continue # Parse the lines to a human readable dictionary. try: record = _read_lines(*lines) except (ValueError, ObsPyNDKException): exc = traceback.format_exc() msg = ("Could not parse event %i (faulty file?). Will be " "skipped. Lines of the event:\n" "\t%s\n" "%s") % (_i + 1, "\n\t".join(lines), exc) warnings.warn(msg, ObsPyNDKWarning) continue # Use one creation info for essentially every item. creation_info = CreationInfo(agency_id="GCMT", version=record["version_code"]) # Use the ObsPy Flinn Engdahl region determiner as the region in the # NDK files is oftentimes trimmed. region = fe.get_region(record["centroid_longitude"], record["centroid_latitude"]) # Create an event object. event = Event(force_resource_id=False, event_type="earthquake", event_type_certainty="known", event_descriptions=[ EventDescription(text=region, type="Flinn-Engdahl region"), EventDescription(text=record["cmt_event_name"], type="earthquake name") ]) # Assemble the time for the reference origin. try: time = _parse_date_time(record["date"], record["time"]) except ObsPyNDKException: msg = ("Invalid time in event %i. '%s' and '%s' cannot be " "assembled to a valid time. Event will be skipped.") % \ (_i + 1, record["date"], record["time"]) warnings.warn(msg, ObsPyNDKWarning) continue # Create two origins, one with the reference latitude/longitude and # one with the centroidal values. ref_origin = Origin( force_resource_id=False, time=time, longitude=record["hypo_lng"], latitude=record["hypo_lat"], # Convert to m. depth=record["hypo_depth_in_km"] * 1000.0, origin_type="hypocenter", comments=[ Comment(text="Hypocenter catalog: %s" % record["hypocenter_reference_catalog"], force_resource_id=False) ]) ref_origin.comments[0].resource_id = _get_resource_id( record["cmt_event_name"], "comment", tag="ref_origin") ref_origin.resource_id = _get_resource_id(record["cmt_event_name"], "origin", tag="reforigin") cmt_origin = Origin( force_resource_id=False, longitude=record["centroid_longitude"], longitude_errors={ "uncertainty": record["centroid_longitude_error"] }, latitude=record["centroid_latitude"], latitude_errors={"uncertainty": record["centroid_latitude_error"]}, # Convert to m. depth=record["centroid_depth_in_km"] * 1000.0, depth_errors={ "uncertainty": record["centroid_depth_in_km_error"] * 1000 }, time=ref_origin["time"] + record["centroid_time"], time_errors={"uncertainty": record["centroid_time_error"]}, depth_type=record["type_of_centroid_depth"], origin_type="centroid", time_fixed=False, epicenter_fixed=False, creation_info=creation_info.copy()) cmt_origin.resource_id = _get_resource_id(record["cmt_event_name"], "origin", tag="cmtorigin") event.origins = [ref_origin, cmt_origin] event.preferred_origin_id = cmt_origin.resource_id.id # Create the magnitude object. mag = Magnitude(force_resource_id=False, mag=round(record["Mw"], 2), magnitude_type="Mwc", origin_id=cmt_origin.resource_id, creation_info=creation_info.copy()) mag.resource_id = _get_resource_id(record["cmt_event_name"], "magnitude", tag="moment_mag") event.magnitudes = [mag] event.preferred_magnitude_id = mag.resource_id.id # Add the reported mb, MS magnitudes as additional magnitude objects. event.magnitudes.append( Magnitude( force_resource_id=False, mag=record["mb"], magnitude_type="mb", comments=[ Comment( force_resource_id=False, text="Reported magnitude in NDK file. Most likely 'mb'." ) ])) event.magnitudes[-1].comments[-1].resource_id = _get_resource_id( record["cmt_event_name"], "comment", tag="mb_magnitude") event.magnitudes[-1].resource_id = _get_resource_id( record["cmt_event_name"], "magnitude", tag="mb") event.magnitudes.append( Magnitude( force_resource_id=False, mag=record["MS"], magnitude_type="MS", comments=[ Comment( force_resource_id=False, text="Reported magnitude in NDK file. Most likely 'MS'." ) ])) event.magnitudes[-1].comments[-1].resource_id = _get_resource_id( record["cmt_event_name"], "comment", tag="MS_magnitude") event.magnitudes[-1].resource_id = _get_resource_id( record["cmt_event_name"], "magnitude", tag="MS") # Take care of the moment tensor. tensor = Tensor(m_rr=record["m_rr"], m_rr_errors={"uncertainty": record["m_rr_error"]}, m_pp=record["m_pp"], m_pp_errors={"uncertainty": record["m_pp_error"]}, m_tt=record["m_tt"], m_tt_errors={"uncertainty": record["m_tt_error"]}, m_rt=record["m_rt"], m_rt_errors={"uncertainty": record["m_rt_error"]}, m_rp=record["m_rp"], m_rp_errors={"uncertainty": record["m_rp_error"]}, m_tp=record["m_tp"], m_tp_errors={"uncertainty": record["m_tp_error"]}, creation_info=creation_info.copy()) mt = MomentTensor( force_resource_id=False, scalar_moment=record["scalar_moment"], tensor=tensor, data_used=[DataUsed(**i) for i in record["data_used"]], inversion_type=record["source_type"], source_time_function=SourceTimeFunction( type=record["moment_rate_type"], duration=record["moment_rate_duration"]), derived_origin_id=cmt_origin.resource_id, creation_info=creation_info.copy()) mt.resource_id = _get_resource_id(record["cmt_event_name"], "momenttensor") axis = [Axis(**i) for i in record["principal_axis"]] focmec = FocalMechanism( force_resource_id=False, moment_tensor=mt, principal_axes=PrincipalAxes( # The ordering is the same as for the IRIS SPUD service and # from a website of the Saint Louis University Earthquake # center so it should be correct. t_axis=axis[0], p_axis=axis[2], n_axis=axis[1]), nodal_planes=NodalPlanes( nodal_plane_1=NodalPlane(**record["nodal_plane_1"]), nodal_plane_2=NodalPlane(**record["nodal_plane_2"])), comments=[ Comment(force_resource_id=False, text="CMT Analysis Type: %s" % record["cmt_type"].capitalize()), Comment(force_resource_id=False, text="CMT Timestamp: %s" % record["cmt_timestamp"]) ], creation_info=creation_info.copy()) focmec.comments[0].resource_id = _get_resource_id( record["cmt_event_name"], "comment", tag="cmt_type") focmec.comments[1].resource_id = _get_resource_id( record["cmt_event_name"], "comment", tag="cmt_timestamp") focmec.resource_id = _get_resource_id(record["cmt_event_name"], "focal_mechanism") event.focal_mechanisms = [focmec] event.preferred_focal_mechanism_id = focmec.resource_id.id # Set at end to avoid duplicate resource id warning. event.resource_id = _get_resource_id(record["cmt_event_name"], "event") cat.append(event) if len(cat) == 0: msg = "No valid events found in NDK file." raise ObsPyNDKException(msg) return cat
def makeCatalog(StazList, mt, scale, args): epi = args.epi.rsplit() model = args.model.split(os.sep) NrSt = len(StazList) NrCo = NrSt * 3 (Fmin, Fmax) = getFreq(args) Tmin = ('%.0f' % (1 / Fmax)) Tmax = ('%.0f' % (1 / Fmin)) mo = ('%.3e' % (mt[0])) mw = ('%.2f' % (mt[1])) Pdc = ('%.2f' % (float(mt[2]) / 100)) Pclvd = ('%.2f' % (float(mt[3]) / 100)) Tval = ('%10.3e' % (mt[22])) Tplg = ('%4.1f' % (mt[23])) Tazi = ('%5.1f' % (mt[24])) Nval = ('%10.3e' % (mt[25])) Nplg = ('%4.1f' % (mt[26])) Nazi = ('%5.1f' % (mt[27])) Pval = ('%10.3e' % (mt[28])) Pplg = ('%4.1f' % (mt[29])) Pazi = ('%5.1f' % (mt[30])) STp1 = ('%5.1f' % (mt[31])) DPp1 = ('%4.1f' % (mt[32])) RAp1 = ('%6.1f' % (mt[33])) STp2 = ('%5.1f' % (mt[34])) DPp2 = ('%4.1f' % (mt[35])) RAp2 = ('%6.1f' % (mt[36])) var = ('%.2f' % (mt[37])) qua = ('%d' % (mt[38])) mij = [mt[4], mt[5], mt[6], mt[7], mt[8], mt[9]] mm0 = str('%10.3e' % (mij[0])) mm1 = str('%10.3e' % (mij[1])) mm2 = str('%10.3e' % (mij[2])) mm3 = str('%10.3e' % (mij[3])) mm4 = str('%10.3e' % (mij[4])) mm5 = str('%10.3e' % (mij[5])) # Aki konvention Mrr = mm5 Mtt = mm0 Mff = mm1 Mrt = mm3 Mrf = mm4 Mtf = mm2 # stress regime A1 = PrincipalAxis(val=mt[22], dip=mt[23], strike=mt[24]) A2 = PrincipalAxis(val=mt[25], dip=mt[26], strike=mt[27]) A3 = PrincipalAxis(val=mt[28], dip=mt[29], strike=mt[30]) (regime, sh) = stressRegime(A1, A2, A3) sh = ('%5.1f' % (sh)) #### Build classes ################################# # #Resource Id is the event origin time for definition res_id = ResourceIdentifier(args.ori) nowUTC = datetime.datetime.utcnow() info = CreationInfo(author="pytdmt", version="2.4", creation_time=nowUTC) evOrigin = Origin(resource_id=res_id, time=args.ori, latitude=epi[0], longitude=epi[1], depth=epi[2], earth_model_id=model[-1], creation_info=info) # Magnitudes magnitude = Magnitude(mag=mw, magnitude_type="Mw") # Nodal Planes np1 = NodalPlane(strike=STp1, dip=DPp1, rake=RAp1) np2 = NodalPlane(strike=STp2, dip=DPp2, rake=RAp2) planes = NodalPlanes(nodal_plane_1=np1, nodal_plane_2=np2) # Principal axes Taxe = Axis(azimuth=Tazi, plunge=Tplg, length=Tval) Naxe = Axis(azimuth=Nazi, plunge=Nplg, length=Nval) Paxe = Axis(azimuth=Pazi, plunge=Pplg, length=Pval) axes = PrincipalAxes(t_axis=Taxe, p_axis=Paxe, n_axis=Naxe) # MT elements MT = Tensor(m_rr=Mrr, m_tt=Mtt, m_pp=Mff, m_rt=Mrt, m_rp=Mrf, m_tp=Mtf) # Stress regime regStr = 'Stress regime: ' + regime + ' - SH = ' + sh strDes = EventDescription(regStr) # MT dataset dataInfo = DataUsed(wave_type="combined", station_count=NrSt, component_count=NrCo, shortest_period=Tmin, longest_period=Tmax) source = MomentTensor(data_used=dataInfo, scalar_moment=mo, tensor=MT, variance_reduction=var, double_couple=Pdc, clvd=Pclvd, iso=0) focMec = FocalMechanism(moment_tensor=source, nodal_planes=planes, principal_axes=axes, azimuthal_gap=-1) #Initialize Event Catalog mtSolution = Event(creation_info=info) mtSolution.origins.append(evOrigin) mtSolution.magnitudes.append(magnitude) mtSolution.focal_mechanisms.append(focMec) mtSolution.event_descriptions.append(strDes) cat = Catalog() cat.append(mtSolution) return cat
def _internal_read_single_cmtsolution(buf): """ Reads a single CMTSOLUTION file to a :class:`~obspy.core.event.Catalog` object. :param buf: File to read. :type buf: open file or file-like object """ # The first line encodes the preliminary epicenter. line = buf.readline() hypocenter_catalog = line[:5].strip().decode() origin_time = line[5:].strip().split()[:6] values = list(map(int, origin_time[:-1])) + \ [float(origin_time[-1])] try: origin_time = UTCDateTime(*values) except (TypeError, ValueError): warnings.warn("Could not determine origin time from line: %s. Will " "be set to zero." % line) origin_time = UTCDateTime(0) line = line[28:].split() latitude, longitude, depth, body_wave_mag, surface_wave_mag = \ map(float, line[:5]) # The rest encodes the centroid solution. event_name = buf.readline().strip().split()[-1].decode() preliminary_origin = Origin( resource_id=_get_resource_id(event_name, "origin", tag="prelim"), time=origin_time, longitude=longitude, latitude=latitude, # Depth is in meters. depth=depth * 1000.0, origin_type="hypocenter", region=_fe.get_region(longitude=longitude, latitude=latitude), evaluation_status="preliminary") preliminary_bw_magnitude = Magnitude( resource_id=_get_resource_id(event_name, "magnitude", tag="prelim_bw"), mag=body_wave_mag, magnitude_type="Mb", evaluation_status="preliminary", origin_id=preliminary_origin.resource_id) preliminary_sw_magnitude = Magnitude( resource_id=_get_resource_id(event_name, "magnitude", tag="prelim_sw"), mag=surface_wave_mag, magnitude_type="MS", evaluation_status="preliminary", origin_id=preliminary_origin.resource_id) values = [ "time_shift", "half_duration", "latitude", "longitude", "depth", "m_rr", "m_tt", "m_pp", "m_rt", "m_rp", "m_tp" ] cmt_values = { _i: float(buf.readline().strip().split()[-1]) for _i in values } # Moment magnitude calculation in dyne * cm. m_0 = 1.0 / math.sqrt(2.0) * math.sqrt( cmt_values["m_rr"]**2 + cmt_values["m_tt"]**2 + cmt_values["m_pp"]**2 + 2.0 * cmt_values["m_rt"]**2 + 2.0 * cmt_values["m_rp"]**2 + 2.0 * cmt_values["m_tp"]**2) m_w = 2.0 / 3.0 * (math.log10(m_0) - 16.1) # Convert to meters. cmt_values["depth"] *= 1000.0 # Convert to Newton meter. values = ["m_rr", "m_tt", "m_pp", "m_rt", "m_rp", "m_tp"] for value in values: cmt_values[value] /= 1E7 cmt_origin = Origin( resource_id=_get_resource_id(event_name, "origin", tag="cmt"), time=origin_time + cmt_values["time_shift"], longitude=cmt_values["longitude"], latitude=cmt_values["latitude"], depth=cmt_values["depth"], origin_type="centroid", # Could rarely be different than the epicentral region. region=_fe.get_region(longitude=cmt_values["longitude"], latitude=cmt_values["latitude"]) # No evaluation status as it could be any of several and the file # format does not provide that information. ) cmt_mag = Magnitude( resource_id=_get_resource_id(event_name, "magnitude", tag="mw"), # Round to 2 digits. mag=round(m_w, 2), magnitude_type="mw", origin_id=cmt_origin.resource_id) foc_mec = FocalMechanism( resource_id=_get_resource_id(event_name, "focal_mechanism"), # The preliminary origin most likely triggered the focal mechanism # determination. triggering_origin_id=preliminary_origin.resource_id) tensor = Tensor(m_rr=cmt_values["m_rr"], m_pp=cmt_values["m_pp"], m_tt=cmt_values["m_tt"], m_rt=cmt_values["m_rt"], m_rp=cmt_values["m_rp"], m_tp=cmt_values["m_tp"]) # Source time function is a triangle, according to the SPECFEM manual. stf = SourceTimeFunction( type="triangle", # The duration is twice the half duration. duration=2.0 * cmt_values["half_duration"]) mt = MomentTensor( resource_id=_get_resource_id(event_name, "moment_tensor"), derived_origin_id=cmt_origin.resource_id, moment_magnitude_id=cmt_mag.resource_id, # Convert to Nm. scalar_moment=m_0 / 1E7, tensor=tensor, source_time_function=stf) # Assemble everything. foc_mec.moment_tensor = mt ev = Event(resource_id=_get_resource_id(event_name, "event"), event_type="earthquake") ev.event_descriptions.append( EventDescription(text=event_name, type="earthquake name")) ev.comments.append( Comment(text="Hypocenter catalog: %s" % hypocenter_catalog, force_resource_id=False)) ev.origins.append(cmt_origin) ev.origins.append(preliminary_origin) ev.magnitudes.append(cmt_mag) ev.magnitudes.append(preliminary_bw_magnitude) ev.magnitudes.append(preliminary_sw_magnitude) ev.focal_mechanisms.append(foc_mec) # Set the preferred items. ev.preferred_origin_id = cmt_origin.resource_id.id ev.preferred_magnitude_id = cmt_mag.resource_id.id ev.preferred_focal_mechanism_id = foc_mec.resource_id.id ev.scope_resource_ids() return ev
def __read_single_fnetmt_entry(line, **kwargs): """ Reads a single F-net moment tensor solution to a :class:`~obspy.core.event.Event` object. :param line: String containing moment tensor information. :type line: str. """ a = line.split() try: ot = UTCDateTime().strptime(a[0], '%Y/%m/%d,%H:%M:%S.%f') except ValueError: ot = UTCDateTime().strptime(a[0], '%Y/%m/%d,%H:%M:%S') lat, lon, depjma, magjma = map(float, a[1:5]) depjma *= 1000 region = a[5] strike = tuple(map(int, a[6].split(';'))) dip = tuple(map(int, a[7].split(';'))) rake = tuple(map(int, a[8].split(';'))) mo = float(a[9]) depmt = float(a[10]) * 1000 magmt = float(a[11]) var_red = float(a[12]) mxx, mxy, mxz, myy, myz, mzz, unit = map(float, a[13:20]) event_name = util.gen_sc3_id(ot) e = Event(event_type="earthquake") e.resource_id = _get_resource_id(event_name, 'event') # Standard JMA solution o_jma = Origin(time=ot, latitude=lat, longitude=lon, depth=depjma, depth_type="from location", region=region) o_jma.resource_id = _get_resource_id(event_name, 'origin', 'JMA') m_jma = Magnitude(mag=magjma, magnitude_type='ML', origin_id=o_jma.resource_id) m_jma.resource_id = _get_resource_id(event_name, 'magnitude', 'JMA') # MT solution o_mt = Origin(time=ot, latitude=lat, longitude=lon, depth=depmt, region=region, depth_type="from moment tensor inversion") o_mt.resource_id = _get_resource_id(event_name, 'origin', 'MT') m_mt = Magnitude(mag=magmt, magnitude_type='Mw', origin_id=o_mt.resource_id) m_mt.resource_id = _get_resource_id(event_name, 'magnitude', 'MT') foc_mec = FocalMechanism(triggering_origin_id=o_jma.resource_id) foc_mec.resource_id = _get_resource_id(event_name, "focal_mechanism") nod1 = NodalPlane(strike=strike[0], dip=dip[0], rake=rake[0]) nod2 = NodalPlane(strike=strike[1], dip=dip[1], rake=rake[1]) nod = NodalPlanes(nodal_plane_1=nod1, nodal_plane_2=nod2) foc_mec.nodal_planes = nod tensor = Tensor(m_rr=mxx, m_tt=myy, m_pp=mzz, m_rt=mxy, m_rp=mxz, m_tp=myz) cm = Comment(text="Basis system: North,East,Down (Jost and \ Herrmann 1989") cm.resource_id = _get_resource_id(event_name, 'comment', 'mt') mt = MomentTensor(derived_origin_id=o_mt.resource_id, moment_magnitude_id=m_mt.resource_id, scalar_moment=mo, comments=[cm], tensor=tensor, variance_reduction=var_red) mt.resource_id = _get_resource_id(event_name, 'moment_tensor') foc_mec.moment_tensor = mt e.origins = [o_jma, o_mt] e.magnitudes = [m_jma, m_mt] e.focal_mechanisms = [foc_mec] e.preferred_magnitude_id = m_mt.resource_id.id e.preferred_origin_id = o_mt.resource_id.id e.preferred_focal_mechanism_id = foc_mec.resource_id.id return e
def par2quakeml(Par_filename, QuakeML_filename, rotation_axis=[0.0, 1.0, 0.0], rotation_angle=-57.5, origin_time="2000-01-01 00:00:00.0", event_type="other event"): # initialise event ev = Event() # open and read Par file fid = open(Par_filename, 'r') fid.readline() fid.readline() fid.readline() fid.readline() lat_old = 90.0 - float(fid.readline().strip().split()[0]) lon_old = float(fid.readline().strip().split()[0]) depth = float(fid.readline().strip().split()[0]) fid.readline() Mtt_old = float(fid.readline().strip().split()[0]) Mpp_old = float(fid.readline().strip().split()[0]) Mrr_old = float(fid.readline().strip().split()[0]) Mtp_old = float(fid.readline().strip().split()[0]) Mtr_old = float(fid.readline().strip().split()[0]) Mpr_old = float(fid.readline().strip().split()[0]) # rotate event into physical domain lat, lon = rot.rotate_lat_lon(lat_old, lon_old, rotation_axis, rotation_angle) Mrr, Mtt, Mpp, Mtr, Mpr, Mtp = rot.rotate_moment_tensor( Mrr_old, Mtt_old, Mpp_old, Mtr_old, Mpr_old, Mtp_old, lat_old, lon_old, rotation_axis, rotation_angle) # populate event origin data ev.event_type = event_type ev_origin = Origin() ev_origin.time = UTCDateTime(origin_time) ev_origin.latitude = lat ev_origin.longitude = lon ev_origin.depth = depth ev.origins.append(ev_origin) # populte event moment tensor ev_tensor = Tensor() ev_tensor.m_rr = Mrr ev_tensor.m_tt = Mtt ev_tensor.m_pp = Mpp ev_tensor.m_rt = Mtr ev_tensor.m_rp = Mpr ev_tensor.m_tp = Mtp ev_momenttensor = MomentTensor() ev_momenttensor.tensor = ev_tensor ev_momenttensor.scalar_moment = np.sqrt(Mrr**2 + Mtt**2 + Mpp**2 + Mtr**2 + Mpr**2 + Mtp**2) ev_focalmechanism = FocalMechanism() ev_focalmechanism.moment_tensor = ev_momenttensor ev_focalmechanism.nodal_planes = NodalPlanes().setdefault(0, 0) ev.focal_mechanisms.append(ev_focalmechanism) # populate event magnitude ev_magnitude = Magnitude() ev_magnitude.mag = 0.667 * (np.log10(ev_momenttensor.scalar_moment) - 9.1) ev_magnitude.magnitude_type = 'Mw' ev.magnitudes.append(ev_magnitude) # write QuakeML file cat = Catalog() cat.append(ev) cat.write(QuakeML_filename, format="quakeml") # clean up fid.close()
def full_test_event(): """ Function to generate a basic, full test event """ test_event = Event() test_event.origins.append( Origin(time=UTCDateTime("2012-03-26") + 1.2, latitude=45.0, longitude=25.0, depth=15000)) test_event.event_descriptions.append(EventDescription()) test_event.event_descriptions[0].text = 'LE' test_event.creation_info = CreationInfo(agency_id='TES') test_event.magnitudes.append( Magnitude(mag=0.1, magnitude_type='ML', creation_info=CreationInfo('TES'), origin_id=test_event.origins[0].resource_id)) test_event.magnitudes.append( Magnitude(mag=0.5, magnitude_type='Mc', creation_info=CreationInfo('TES'), origin_id=test_event.origins[0].resource_id)) test_event.magnitudes.append( Magnitude(mag=1.3, magnitude_type='Ms', creation_info=CreationInfo('TES'), origin_id=test_event.origins[0].resource_id)) # Define the test pick _waveform_id_1 = WaveformStreamID(station_code='FOZ', channel_code='SHZ', network_code='NZ') _waveform_id_2 = WaveformStreamID(station_code='WTSZ', channel_code='BH1', network_code=' ') # Pick to associate with amplitude test_event.picks.append( Pick(waveform_id=_waveform_id_1, phase_hint='IAML', polarity='undecidable', time=UTCDateTime("2012-03-26") + 1.68, evaluation_mode="manual")) # Need a second pick for coda test_event.picks.append( Pick(waveform_id=_waveform_id_1, onset='impulsive', phase_hint='PN', polarity='positive', time=UTCDateTime("2012-03-26") + 1.68, evaluation_mode="manual")) # Unassociated pick test_event.picks.append( Pick(waveform_id=_waveform_id_2, onset='impulsive', phase_hint='SG', polarity='undecidable', time=UTCDateTime("2012-03-26") + 1.72, evaluation_mode="manual")) # Unassociated pick test_event.picks.append( Pick(waveform_id=_waveform_id_2, onset='impulsive', phase_hint='PN', polarity='undecidable', time=UTCDateTime("2012-03-26") + 1.62, evaluation_mode="automatic")) # Test a generic local magnitude amplitude pick test_event.amplitudes.append( Amplitude(generic_amplitude=2.0, period=0.4, pick_id=test_event.picks[0].resource_id, waveform_id=test_event.picks[0].waveform_id, unit='m', magnitude_hint='ML', category='point', type='AML')) # Test a coda magnitude pick test_event.amplitudes.append( Amplitude(generic_amplitude=10, pick_id=test_event.picks[1].resource_id, waveform_id=test_event.picks[1].waveform_id, type='END', category='duration', unit='s', magnitude_hint='Mc', snr=2.3)) test_event.origins[0].arrivals.append( Arrival(time_weight=0, phase=test_event.picks[1].phase_hint, pick_id=test_event.picks[1].resource_id)) test_event.origins[0].arrivals.append( Arrival(time_weight=2, phase=test_event.picks[2].phase_hint, pick_id=test_event.picks[2].resource_id, backazimuth_residual=5, time_residual=0.2, distance=15, azimuth=25)) test_event.origins[0].arrivals.append( Arrival(time_weight=2, phase=test_event.picks[3].phase_hint, pick_id=test_event.picks[3].resource_id, backazimuth_residual=5, time_residual=0.2, distance=15, azimuth=25)) # Add in error info (line E) test_event.origins[0].quality = OriginQuality(standard_error=0.01, azimuthal_gap=36) # Origin uncertainty in Seisan is output as long-lat-depth, quakeML has # semi-major and semi-minor test_event.origins[0].origin_uncertainty = OriginUncertainty( confidence_ellipsoid=ConfidenceEllipsoid( semi_major_axis_length=3000, semi_minor_axis_length=1000, semi_intermediate_axis_length=2000, major_axis_plunge=20, major_axis_azimuth=100, major_axis_rotation=4)) test_event.origins[0].time_errors = QuantityError(uncertainty=0.5) # Add in fault-plane solution info (line F) - Note have to check program # used to determine which fields are filled.... test_event.focal_mechanisms.append( FocalMechanism(nodal_planes=NodalPlanes( nodal_plane_1=NodalPlane(strike=180, dip=20, rake=30, strike_errors=QuantityError(10), dip_errors=QuantityError(10), rake_errors=QuantityError(20))), method_id=ResourceIdentifier( "smi:nc.anss.org/focalMechanism/FPFIT"), creation_info=CreationInfo(agency_id="NC"), misfit=0.5, station_distribution_ratio=0.8)) # Need to test high-precision origin and that it is preferred origin. # Moment tensor includes another origin test_event.origins.append( Origin(time=UTCDateTime("2012-03-26") + 1.2, latitude=45.1, longitude=25.2, depth=14500)) test_event.magnitudes.append( Magnitude(mag=0.1, magnitude_type='MW', creation_info=CreationInfo('TES'), origin_id=test_event.origins[-1].resource_id)) # Moment tensors go with focal-mechanisms test_event.focal_mechanisms.append( FocalMechanism(moment_tensor=MomentTensor( derived_origin_id=test_event.origins[-1].resource_id, moment_magnitude_id=test_event.magnitudes[-1].resource_id, scalar_moment=100, tensor=Tensor( m_rr=100, m_tt=100, m_pp=10, m_rt=1, m_rp=20, m_tp=15), method_id=ResourceIdentifier( 'smi:nc.anss.org/momentTensor/BLAH')))) return test_event
def par2quakeml(Par_filename, QuakeML_filename, rotation_axis=[0.0, 1.0, 0.0], rotation_angle=-57.5, origin_time="2000-01-01 00:00:00.0", event_type="other event"): # initialise event ev = Event() # open and read Par file fid = open(Par_filename, 'r') fid.readline() fid.readline() fid.readline() fid.readline() lat_old = 90.0 - float(fid.readline().strip().split()[0]) lon_old = float(fid.readline().strip().split()[0]) depth = float(fid.readline().strip().split()[0]) fid.readline() Mtt_old = float(fid.readline().strip().split()[0]) Mpp_old = float(fid.readline().strip().split()[0]) Mrr_old = float(fid.readline().strip().split()[0]) Mtp_old = float(fid.readline().strip().split()[0]) Mtr_old = float(fid.readline().strip().split()[0]) Mpr_old = float(fid.readline().strip().split()[0]) # rotate event into physical domain lat, lon = rot.rotate_lat_lon(lat_old, lon_old, rotation_axis, rotation_angle) Mrr, Mtt, Mpp, Mtr, Mpr, Mtp = rot.rotate_moment_tensor( Mrr_old, Mtt_old, Mpp_old, Mtr_old, Mpr_old, Mtp_old, lat_old, lon_old, rotation_axis, rotation_angle) # populate event origin data ev.event_type = event_type ev_origin = Origin() ev_origin.time = UTCDateTime(origin_time) ev_origin.latitude = lat ev_origin.longitude = lon ev_origin.depth = depth ev.origins.append(ev_origin) # populte event moment tensor ev_tensor = Tensor() ev_tensor.m_rr = Mrr ev_tensor.m_tt = Mtt ev_tensor.m_pp = Mpp ev_tensor.m_rt = Mtr ev_tensor.m_rp = Mpr ev_tensor.m_tp = Mtp ev_momenttensor = MomentTensor() ev_momenttensor.tensor = ev_tensor ev_momenttensor.scalar_moment = np.sqrt(Mrr ** 2 + Mtt ** 2 + Mpp ** 2 + Mtr ** 2 + Mpr ** 2 + Mtp ** 2) ev_focalmechanism = FocalMechanism() ev_focalmechanism.moment_tensor = ev_momenttensor ev_focalmechanism.nodal_planes = NodalPlanes().setdefault(0, 0) ev.focal_mechanisms.append(ev_focalmechanism) # populate event magnitude ev_magnitude = Magnitude() ev_magnitude.mag = 0.667 * (np.log10(ev_momenttensor.scalar_moment) - 9.1) ev_magnitude.magnitude_type = 'Mw' ev.magnitudes.append(ev_magnitude) # write QuakeML file cat = Catalog() cat.append(ev) cat.write(QuakeML_filename, format="quakeml") # clean up fid.close()
def _internal_read_single_scardec(buf): """ Reads a single SCARDEC file to a :class:`~obspy.core.event.Catalog` object. :param buf: File to read. :type buf: open file or file-like object """ # The first line encodes the origin time and epicenter line = buf.readline() origin_time = line.strip().split()[:6] values = list(map(int, origin_time[:-1])) + \ [float(origin_time[-1])] try: origin_time = UTCDateTime(*values) except (TypeError, ValueError): warnings.warn("Could not determine origin time from line: %s. Will " "be set to zero." % line) origin_time = UTCDateTime(0) line = line.split()[6:] latitude, longitude = map(float, line[:2]) # The second line encodes depth and the two focal mechanisms line = buf.readline() line = line.split() # First three values are depth, scalar moment (in Nm) and moment magnitude depth, scalar_moment, moment_mag = map(float, line[0:3]) # depth is in km in SCARDEC files depth *= 1e3 # Next six values are strike, dip, rake for both planes strike1, dip1, rake1 = map(float, line[3:6]) strike2, dip2, rake2 = map(float, line[6:9]) # The rest of the file is the moment rate function # In each line: time (sec), moment rate (Nm/sec) stf_time = [] stf_mr = [] for line in buf: stf_time.append(float(line.split()[0])) stf_mr.append(float(line.split()[1])) # Normalize the source time function stf_mr = np.array(stf_mr) stf_mr /= scalar_moment # Calculate the time step dt = np.mean(np.diff(stf_time)) # Calculate the stf offset (time of first sample wrt to origin time) offset = stf_time[0] # event name is set to generic value for now event_name = 'SCARDEC_event' cmt_origin = Origin(resource_id=_get_resource_id(event_name, "origin", tag="cmt"), time=origin_time, longitude=longitude, latitude=latitude, depth=depth, origin_type="centroid", region=_fe.get_region(longitude=longitude, latitude=latitude)) cmt_mag = Magnitude(resource_id=_get_resource_id(event_name, "magnitude", tag="mw"), mag=moment_mag, magnitude_type="mw", origin_id=cmt_origin.resource_id) nod1 = NodalPlane(strike=strike1, dip=dip1, rake=rake1) nod2 = NodalPlane(strike=strike2, dip=dip2, rake=rake2) nod = NodalPlanes(nodal_plane_1=nod1, nodal_plane_2=nod2) foc_mec = FocalMechanism(resource_id=_get_resource_id( event_name, "focal_mechanism"), nodal_planes=nod) dip1 *= np.pi / 180. rake1 *= np.pi / 180. strike1 *= np.pi / 180. mxx = -scalar_moment * ( (np.sin(dip1) * np.cos(rake1) * np.sin(2 * strike1)) + (np.sin(2 * dip1) * np.sin(rake1) * np.sin(2 * strike1))) mxy = scalar_moment * ( (np.sin(dip1) * np.cos(rake1) * np.cos(2 * strike1)) + (np.sin(2 * dip1) * np.sin(rake1) * np.sin(2 * strike1) * 0.5)) myy = scalar_moment * ( (np.sin(dip1) * np.cos(rake1) * np.sin(2 * strike1)) - (np.sin(2 * dip1) * np.sin(rake1) * np.cos(2 * strike1))) mxz = -scalar_moment * ( (np.cos(dip1) * np.cos(rake1) * np.cos(strike1)) + (np.cos(2 * dip1) * np.sin(rake1) * np.sin(strike1))) myz = -scalar_moment * ( (np.cos(dip1) * np.cos(rake1) * np.sin(strike1)) - (np.cos(2 * dip1) * np.sin(rake1) * np.cos(strike1))) mzz = scalar_moment * (np.sin(2 * dip1) * np.sin(rake1)) tensor = Tensor(m_rr=mxx, m_tt=myy, m_pp=mzz, m_rt=mxy, m_rp=mxz, m_tp=myz) cm = [ Comment(text="Basis system: North,East,Down \ (Jost and Herrmann 1989)") ] cm[0].resource_id = _get_resource_id(event_name, 'comment', 'mt') cm.append( Comment(text="MT derived from focal mechanism, therefore \ constrained to pure double couple.", force_resource_id=False)) # Write moment rate function extra = { 'moment_rate': { 'value': stf_mr, 'namespace': r"http://test.org/xmlns/0.1" }, 'dt': { 'value': dt, 'namespace': r"http://test.org/xmlns/0.1" }, 'offset': { 'value': offset, 'namespace': r"http://test.org/xmlns/0.1" } } # Source time function stf = SourceTimeFunction(type="unknown") stf.extra = extra mt = MomentTensor(resource_id=_get_resource_id(event_name, "moment_tensor"), derived_origin_id=cmt_origin.resource_id, moment_magnitude_id=cmt_mag.resource_id, scalar_moment=scalar_moment, tensor=tensor, source_time_function=stf, comments=cm) # Assemble everything. foc_mec.moment_tensor = mt ev = Event(resource_id=_get_resource_id(event_name, "event"), event_type="earthquake") ev.event_descriptions.append( EventDescription(text=event_name, type="earthquake name")) ev.comments.append( Comment(text="Hypocenter catalog: SCARDEC", force_resource_id=False)) ev.origins.append(cmt_origin) ev.magnitudes.append(cmt_mag) ev.focal_mechanisms.append(foc_mec) # Set the preferred items. ev.preferred_origin_id = cmt_origin.resource_id.id ev.preferred_magnitude_id = cmt_mag.resource_id.id ev.preferred_focal_mechanism_id = foc_mec.resource_id.id ev.scope_resource_ids() return ev