def _parse_component_data(self, wfid, proc_data): """ Parses the information for each component """ filter_params = { 'Type': proc_data['comp_ordered.filter_type'], 'Order': proc_data['comp_ordered.filter_order'], 'Passes': get_int( proc_data['comp_ordered.filter_number_of_passes']), 'NRoll': get_int(proc_data['comp_ordered.nroll']), 'High-Cut': get_float(proc_data['comp_ordered.high_cut_freq']), 'Low-Cut': get_float(proc_data['comp_ordered.low_cut_freq'])} intensity_measures = { # All m - convert to cm 'PGA': get_float(proc_data['comp_ordered.pga']), 'PGV': get_float(proc_data['comp_ordered.pgv']), 'PGD': get_float(proc_data['comp_ordered.pgd']) } for imkey in intensity_measures.keys(): if intensity_measures[imkey]: intensity_measures[imkey] = 100.0 * intensity_measures[imkey] comp = Component(wfid, proc_data['comp_ordered.orientation'], ims=intensity_measures, longest_period=None, waveform_filter=filter_params, baseline=proc_data['comp_ordered.baseline_correction']) return comp
def _parse_site_data(self, metadata): """ Parses the site metadata. Coordinates in western hemisphere are returned as negative values. """ try: altitude = get_float(metadata["ALTITUD (msnm)"]) except: altitude = 0 site = RecordSite( "|".join([metadata["INSTITUCION RESPONSABLE"], metadata["CLAVE DE LA ESTACION"]]), metadata["CLAVE DE LA ESTACION"], metadata["NOMBRE DE LA ESTACION"], -get_float(metadata["COORDENADAS DE LA ESTACION"].split(" ")[3]), get_float(metadata["COORDENADAS DE LA ESTACION"].split(" ")[0]), altitude) if "UNAM" in metadata["INSTITUCION RESPONSABLE"]: site.network_code = "UNAM" elif "CICESE" in metadata["INSTITUCION RESPONSABLE"]: site.network_code = "CICESE" else: site.network_code = "unknown" try: site.morphology = metadata["TIPO DE SUELO"] except: site.morphology = None site.instrument_type = metadata["MODELO DEL ACELEROGRAFO"] return site
def _parse_record(self, metadata): """ Parses the record information and returns an instance of the :class: smtk.sm_database.GroundMotionRecord """ # Waveform ID wfid = metadata["Record Sequence Number"] # Event information event = self._parse_event_data(metadata) # Site information site = self._parse_site_data(metadata) # Distance Information distances = self._parse_distance_data(event, site, metadata) # Components x_comp, y_comp, vertical = self._parse_processing_data(wfid, metadata) # Return record metadata lup = get_float(metadata["Lowest Usable Freq - Ave. Component (Hz)"]) if lup: lup = 1. / lup sup = get_float(metadata["Maximum Usable Freq - Ave. Component (Hz)"]) if sup: sup = 1. / sup return GroundMotionRecord(wfid, [metadata["File Name (Horizontal 1)"], metadata["File Name (Horizontal 2)"], metadata["File Name (Vertical)"]], event, distances, site, x_comp, y_comp, longest_period=lup, shortest_period=sup)
def _parse_focal_mechanism(self, eq_id, eq_name, metadata): """ Parses the focal mechanism returning an instance of FocalMechanism """ nodal_planes = GCMTNodalPlanes() nodal_planes.nodal_plane_1 = { 'strike': get_float(metadata['event.strike1']), 'dip': get_float(metadata['event.dip1']), 'rake': get_float(metadata['event.slip1']) } nodal_planes.nodal_plane_2 = { 'strike': get_float(metadata['event.strike2']), 'dip': get_float(metadata['event.dip2']), 'rake': get_float(metadata['event.slip2']) } principal_axes = GCMTPrincipalAxes() principal_axes.t_axes = { 'eigenvalue': None, 'plunge': get_float(metadata['event.t_axes_plg']), 'azimuth': get_float(metadata['event.t_axes_az'])} principal_axes.p_axes = { 'eigenvalue': None, 'plunge': get_float(metadata['event.p_axes_plg']), 'azimuth': get_float(metadata['event.p_axes_az'])} principal_axes.b_axes = { 'eigenvalue': None, 'plunge': None, 'azimuth': None} return FocalMechanism(eq_id, eq_name, nodal_planes, principal_axes, mechanism_type=metadata['event.fault_mechanism.name'])
def _parse_site_data(self, metadata): """ Parses the site metadata """ try: altitude = get_float(metadata["ALTITUD (msnm)"]) except: altitude = 0 site = RecordSite( "|".join([ metadata["INSTITUCION RESPONSABLE"], metadata["CLAVE DE LA ESTACION"] ]), metadata["CLAVE DE LA ESTACION"], metadata["NOMBRE DE LA ESTACION"], get_float(metadata["COORDENADAS DE LA ESTACION"].split(" ")[3]), get_float(metadata["COORDENADAS DE LA ESTACION"].split(" ")[0]), altitude) if "UNAM" in metadata["INSTITUCION RESPONSABLE"]: site.network_code = "UNAM" elif "CICESE" in metadata["INSTITUCION RESPONSABLE"]: site.network_code = "CICESE" else: site.network_code = "unknown" try: site.morphology = metadata["TIPO DE SUELO"] except: site.morphology = None site.instrument_type = metadata["MODELO DEL ACELEROGRAFO"] return site
def _parse_distance_data(self, metadata, file_str, eqk): """ Parses the event metadata to return an instance of the :class: smtk.sm_database.RecordDistance """ epi_lon = get_float( metadata["COORDENADAS DEL EPICENTRO"].split(" ")[3]) epi_lat = get_float( metadata["COORDENADAS DEL EPICENTRO"].split(" ")[0]) sta_lon = get_float( metadata["COORDENADAS DE LA ESTACION"].split(" ")[3]) sta_lat = get_float( metadata["COORDENADAS DE LA ESTACION"].split(" ")[0]) p = Point(longitude=epi_lon, latitude=epi_lat) repi = p.distance(Point(longitude=sta_lon, latitude=sta_lat)) # No hypocentral distance in file - calculate from event rhypo = sqrt(repi**2. + eqk.depth**2.) azimuth = Point(epi_lon, epi_lat, eqk.depth).azimuth(Point(sta_lon, sta_lat)) dists = RecordDistance(repi, rhypo) dists.azimuth = azimuth return dists
def _get_focal_mechanism(self, eq_id, eq_name, metadata): """ Returns the focal mechanism information as an instance of the :class: smtk.sigma_database.FocalMechanism """ nodal_planes = GCMTNodalPlanes() strike = get_float(metadata["Strike (deg)"]) if strike is None: strike = 0.0 dip = get_float(metadata["Dip (deg)"]) if dip is None: dip = 90.0 nodal_planes.nodal_plane_1 = { "strike": strike, "dip": dip, "rake": get_float(metadata["Rake Angle (deg)"]) } nodal_planes.nodal_plane2 = {"strike": None, "dip": None, "rake": None} principal_axes = GCMTPrincipalAxes() return FocalMechanism( eq_id, eq_name, nodal_planes, principal_axes, mechanism_type=metadata["Mechanism Based on Rake Angle"])
def _parse_distance_data(self, metadata, file_str, eqk): """ Parses the event metadata to return an instance of the :class: smtk.sm_database.RecordDistance. Coordinates in western hemisphere are converted to negative values. """ epi_lon = -get_float( metadata["COORDENADAS DEL EPICENTRO"].split(" ")[3]) epi_lat = get_float( metadata["COORDENADAS DEL EPICENTRO"].split(" ")[0]) sta_lon = -get_float( metadata["COORDENADAS DE LA ESTACION"].split(" ")[3]) sta_lat = get_float( metadata["COORDENADAS DE LA ESTACION"].split(" ")[0]) p = Point(longitude=epi_lon, latitude=epi_lat) repi = p.distance(Point(longitude=sta_lon, latitude=sta_lat)) # No hypocentral distance in file - calculate from event rhypo = sqrt(repi ** 2. + eqk.depth ** 2.) azimuth = Point(epi_lon, epi_lat, eqk.depth).azimuth( Point(sta_lon, sta_lat)) dists = RecordDistance(repi, rhypo) dists.azimuth = azimuth return dists
def _parse_rupture(self, eq_id, eq_name, magnitude, metadata): """ """ return Rupture(eq_id, eq_name, magnitude, get_float(metadata['event.fault_rupture_length']), get_float(metadata['event.fault_rupture_width']), get_float(metadata['event.fault_rupture_depth']))
def _parse_rupture(self, eq_id, metadata): """ """ return Rupture(eq_id, get_float(metadata['event.fault_rupture_length']), get_float(metadata['event.fault_rupture_width']), get_float(metadata['event.fault_rupture_depth']))
def _parse_distance_data(self, metadata): """ Parses the distance data """ return RecordDistance(get_float(metadata['distance_repi']), get_float(metadata['distance_rhyp']), rjb = get_float(metadata['distance_rjb']), rrup = get_float(metadata['distance_rrup']), r_x = None, flag = get_int(metadata['distance_flag']))
def _parse_event_data(self, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.Earthquake """ metadata["MODY"] = metadata["MODY"].zfill(4) metadata["HRMN"] = metadata["HRMN"].zfill(4) # Date and Time year = get_int(metadata["YEAR"]) month = get_int(metadata["MODY"][:2]) day = get_int(metadata["MODY"][2:]) hour = get_int(metadata["HRMN"][:2]) minute = get_int(metadata["HRMN"][2:]) eq_datetime = datetime(year, month, day, hour, minute) # Event ID and Name eq_id = metadata["EQID"] eq_name = metadata["Earthquake Name"] # Focal Mechanism focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata) focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\ 1E-7 # Read magnitude pref_mag = Magnitude(get_float(metadata["Earthquake Magnitude"]), metadata["Magnitude Type"], sigma=get_float(metadata["Uncertainty"])) # Create Earthquake Class eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata["Hypocenter Longitude (deg)"]), get_float(metadata["Hypocenter Latitude (deg)"]), get_float(metadata["Hypocenter Depth (km)"]), pref_mag, focal_mechanism, metadata["Country"]) hypo_loc = (0.5, 0.7) # Hypocentre Location msr = WC1994() # Warning rake set to 0.0 in scaling relationship area = msr.get_median_area(pref_mag.value, 0.0) aspect_ratio = 1.5 # Assumed Fixed width_model = np.sqrt(area / aspect_ratio) length_model = aspect_ratio * width_model ztor_model = eqk.depth - width_model / 2. if ztor_model < 0: ztor_model = 0.0 length = get_float(metadata["Fault Rupture Length (km)"]) if length is None: length = length_model width = get_float(metadata["Fault Rupture Width (km)"]) if width is None: width = width_model ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"]) if ztor is None: ztor = ztor_model # Rupture eqk.rupture = Rupture(eq_id, eq_name, pref_mag, length, width, ztor) # get_float(metadata["Fault Rupture Length (km)"]), # get_float(metadata["Fault Rupture Width (km)"]), # get_float(metadata["Depth to Top Of Fault Rupture Model"])) eqk.rupture.get_area() return eqk
def _build_spectra_hdf5_from_row(self, output_file, row, periods, scalar_fields, spectra_fields, component, damping, units): """ """ fle = h5py.File(output_file, "w-") ts_grp = fle.create_group("Time Series") ims_grp = fle.create_group("IMS") h_grp = ims_grp.create_group("H") scalar_grp = h_grp.create_group("Scalar") # Create Scalar values for f_attr, imt in scalar_fields: dset = scalar_grp.create_dataset(imt, (1,), dtype="f") dset.attrs["Component"] = component input_units = re.search('\((.*?)\)', f_attr).group(1) if imt == "PGA": # Convert acceleration from reported units to cm/s/s dset.attrs["Units"] = "cm/s/s" dset[:] = utils.convert_accel_units(get_float(row[f_attr]), input_units) else: # For other values take direct from spreadsheet # Units should be given in parenthesis from fieldname dset.attrs["Units"] = input_units dset[:] = get_float(row[f_attr]) spectra_grp = h_grp.create_group("Spectra") rsp_grp = spectra_grp.create_group("Response") # Setup periods dataset per_dset = rsp_grp.create_dataset("Periods", (len(periods),), dtype="f") per_dset.attrs["High Period"] = np.max(periods) per_dset.attrs["Low Period"] = np.min(periods) per_dset.attrs["Number Periods"] = len(periods) per_dset[:] = periods # Get response spectra spectra = np.array([get_float(row[f_attr]) for f_attr in spectra_fields]) acc_grp = rsp_grp.create_group("Acceleration") comp_grp = acc_grp.create_group(component) spectra_dset = comp_grp.create_dataset("damping_{:s}".format(damping), (len(spectra),), dtype="f") spectra_dset.attrs["Units"] = "cm/s/s" spectra_dset[:] = utils.convert_accel_units(spectra, units) fle.close()
def parse_metadata(self, metadata, file_str): """ Parses the metadata dictionary """ # Waveform id wfid = metadata['waveform_sourceid'] # Get event information event = self._parse_event_data(metadata) # Get distance information distances = self._parse_distance_data(metadata) # Get site data site = self._parse_site_data(metadata) # Get processing data x_comp, y_comp, z_comp = self._parse_processing_data(wfid, metadata) # Create and return record rec_file = os.path.join(file_str + "/" + file_str) return GroundMotionRecord(wfid, [rec_file + self.XCOMP_STR, rec_file + self.YCOMP_STR, rec_file + self.ZCOMP_STR], event, distances, site, x_comp, y_comp, vertical=z_comp, ims=None, longest_period=get_float(metadata['up4horiz_components']), spectra_file=[rec_file + self.XSPEC_STR, rec_file + self.YSPEC_STR, rec_file + self.ZSPEC_STR])
def _build_spectra_hdf5_from_row(self, output_file, row, periods, scalar_fields, spectra_fields, component, damping, units): """ """ fle = h5py.File(output_file, "w-") ts_grp = fle.create_group("Time Series") ims_grp = fle.create_group("IMS") h_grp = ims_grp.create_group("H") scalar_grp = h_grp.create_group("Scalar") # Create Scalar values for f_attr, imt in scalar_fields: dset = scalar_grp.create_dataset(imt, (1, ), dtype="f") dset.attrs["Component"] = component input_units = re.search('\((.*?)\)', f_attr).group(1) if imt == "PGA": # Convert acceleration from reported units to cm/s/s dset.attrs["Units"] = "cm/s/s" dset[:] = utils.convert_accel_units(get_float(row[f_attr]), input_units) else: # For other values take direct from spreadsheet # Units should be given in parenthesis from fieldname dset.attrs["Units"] = input_units dset[:] = get_float(row[f_attr]) spectra_grp = h_grp.create_group("Spectra") rsp_grp = spectra_grp.create_group("Response") # Setup periods dataset per_dset = rsp_grp.create_dataset("Periods", (len(periods), ), dtype="f") per_dset.attrs["High Period"] = np.max(periods) per_dset.attrs["Low Period"] = np.min(periods) per_dset.attrs["Number Periods"] = len(periods) per_dset[:] = periods # Get response spectra spectra = np.array( [get_float(row[f_attr]) for f_attr in spectra_fields]) acc_grp = rsp_grp.create_group("Acceleration") comp_grp = acc_grp.create_group(component) spectra_dset = comp_grp.create_dataset("damping_{:s}".format(damping), (len(spectra), ), dtype="f") spectra_dset.attrs["Units"] = "cm/s/s" spectra_dset[:] = utils.convert_accel_units(spectra, units) fle.close()
def _parse_site_data(self, metadata): """ Returns the site data as an instance of the :class: smtk.sm_database.RecordSite """ site = RecordSite(metadata["Station Sequence Number"], metadata["Station ID No."], metadata["Station ID No."], get_float(metadata["Station Longitude"]), get_float(metadata["Station Latitude"]), 0.0, # Elevation data not given get_float(metadata["Preferred Vs30 (m/s)"]), network_code=metadata["Owner"]) site.nehrp = metadata["Preferred NEHRP Based on Vs30"] site.vs30_measured_type = metadata["Measured/Inferred Class"] if site.vs30_measured_type in ["0", "5"]: site.vs30_measured = True else: site.vs30_measured = False site.vs30_uncertainty = get_float( metadata["Sigma of Vs30 (in natural log Units)"]) site.z1pt0 = get_float(metadata["Z1 (m)"]) site.z1pt5 = get_float(metadata["Z1.5 (m)"]) site.z2pt5 = get_float(metadata["Z2.5 (m)"]) # Implement default values for z1pt0 and z2pt5 if site.z1pt0 is None: site.z1pt0 = rcfg.vs30_to_z1pt0_as08(site.vs30) if site.z2pt5 is None: site.z2pt5 = rcfg.z1pt0_to_z2pt5(site.z1pt0) site.arc_location = metadata["Forearc/Backarc for subduction events"] site.instrument_type = metadata["Type of Recording"] return site
def _parse_event_data(self, metadata): """ """ # Get datetime if len(metadata['event.datetime']) > 20: eq_datetime = datetime.strptime(metadata['event.datetime'], "%Y-%m-%d %H:%M:%S.%f") else: eq_datetime = datetime.strptime(metadata['event.datetime'], "%Y-%m-%d %H:%M:%S") # Event ID and Name if metadata['event.unid']: eq_id = metadata['event.unid'] else: eq_id = eq_datetime.isoformat() eq_name = metadata['event.name'] # Get focal mechanism focal_mech = self._parse_focal_mechanism(eq_id, eq_name, metadata) # Get preferred magnitude pref_mag = Magnitude(get_float(metadata['event.pref_mag']), metadata['event.pref_mag_type']) # Get magnitude list mag_list = [] for kstr in ['0', '1', '2', '3', '4']: mag_list.append(Magnitude( get_float(metadata['event.magnitudes/' + kstr + '.value']), metadata['event.magnitudes/' + kstr + '.magtype'])) eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata['event.longitude']), get_float(metadata['event.latitude']), get_float(metadata['event.focaldepth']), pref_mag, focal_mech, metadata['event.country.name']) eqk.magnitude_list = mag_list # Get Rupture data eqk.rupture = self._parse_rupture(eq_id, eq_name, pref_mag, metadata) return eqk
def _get_focal_mechanism(self, eq_id, eq_name, metadata): """ Returns the focal mechanism information as an instance of the :class: smtk.sigma_database.FocalMechanism """ nodal_planes = GCMTNodalPlanes() strike = get_float(metadata["Strike (deg)"]) if strike is None: strike = 0.0 dip = get_float(metadata["Dip (deg)"]) if dip is None: dip = 90.0 nodal_planes.nodal_plane_1 = { "strike": strike, "dip": dip, "rake": get_float(metadata["Rake Angle (deg)"])} nodal_planes.nodal_plane2 = {"strike": None, "dip": None, "rake": None} principal_axes = GCMTPrincipalAxes() return FocalMechanism(eq_id, eq_name, nodal_planes, principal_axes, mechanism_type=metadata["Mechanism Based on Rake Angle"])
def _parse_site_data(self, metadata): """ Parse the site data """ site = RecordSite( metadata['station.oid'], metadata['station.name'], metadata['station.code'], get_float(metadata['station.longitude']), get_float(metadata['station.latitude']), get_float(metadata['station.altitude']), vs30=get_float(metadata['station.vs30']), vs30_measured=get_int(metadata['station.vs30_measured']), network_code=metadata['station.agency.name'], country=metadata['station.country.name']) site.vs30_measured_type = metadata['station.vs30_measured_type'] site.instrument_type = metadata['recording_type'] site.digitiser = metadata['digitalizer'] site.building_structure = metadata['station.building_struct.name'] site.number_floors = get_int(metadata['station.number_of_floor']) site.floor = metadata['station.installed_on_floor'] site.ec8 = metadata['station.ec8'] return site
def _parse_distance_data(self, event, site, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.RecordDistance """ # Compute various distance metrics # Add calculation of Repi, Rhypo from event and station localizations (latitudes, longitudes, depth, elevation)? target_site = Mesh(np.array([site.longitude]), np.array([site.latitude]), np.array([0.0])) # Warning ratio fixed to 1.5 ratio = 1.5 surface_modeled = rcfg.create_planar_surface( Point(event.longitude, event.latitude, event.depth), event.mechanism.nodal_planes.nodal_plane_1['strike'], event.mechanism.nodal_planes.nodal_plane_1['dip'], event.rupture.area, ratio) hypocenter = rcfg.get_hypocentre_on_planar_surface( surface_modeled, event.rupture.hypo_loc) # Rhypo Rhypo = get_float(metadata["HypD (km)"]) if Rhypo is None: Rhypo = hypocenter.distance_to_mesh(target_site) # Repi Repi = get_float(metadata["EpiD (km)"]) if Repi is None: Repi = hypocenter.distance_to_mesh(target_site, with_depths=False) # Rrup Rrup = get_float(metadata["Campbell R Dist. (km)"]) if Rrup is None: Rrup = surface_modeled.get_min_distance(target_site) # Rjb Rjb = get_float(metadata["Joyner-Boore Dist. (km)"]) if Rjb is None: Rjb = surface_modeled.get_joyner_boore_distance(target_site) # Need to check if Rx and Ry0 are consistant with the other metrics # when those are coming from the flatfile? # Rx Rx = surface_modeled.get_rx_distance(target_site) # Ry0 Ry0 = surface_modeled.get_ry0_distance(target_site) distance = RecordDistance(repi=float(Repi), rhypo=float(Rhypo), rjb=float(Rjb), rrup=float(Rrup), r_x=float(Rx), ry0=float(Ry0)) distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) # distance = RecordDistance( # get_float(metadata["EpiD (km)"]), # get_float(metadata["HypD (km)"]), # get_float(metadata["Joyner-Boore Dist. (km)"]), # get_float(metadata["Campbell R Dist. (km)"])) # distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) # distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) return distance
def _parse_distance_data(self, event, site, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.RecordDistance """ # Compute various distance metrics # Add calculation of Repi, Rhypo from event and station localizations # (latitudes, longitudes, depth, elevation)? target_site = Mesh(np.array([site.longitude]), np.array([site.latitude]), np.array([-site.altitude / 1000.0])) # Warning ratio fixed to 1.5 ratio=1.5 surface_modeled = rcfg.create_planar_surface( Point(event.longitude, event.latitude, event.depth), event.mechanism.nodal_planes.nodal_plane_1['strike'], event.mechanism.nodal_planes.nodal_plane_1['dip'], event.rupture.area, ratio) hypocenter = rcfg.get_hypocentre_on_planar_surface( surface_modeled, event.rupture.hypo_loc) # Rhypo Rhypo = get_float(metadata["Hypocentral Distance (km)"]) if Rhypo is None: Rhypo = hypocenter.distance_to_mesh(target_site) # Repi Repi = get_float(metadata["Epicentral Distance (km)"]) if Repi is None: Repi= hypocenter.distance_to_mesh(target_site, with_depths=False) # Rrup Rrup = get_float(metadata["Rupture Distance (km)"]) if Rrup is None: Rrup = surface_modeled.get_min_distance(target_site) # Rjb Rjb = get_float(metadata["Joyner-Boore Distance (km)"]) if Rjb is None: Rjb = surface_modeled.get_joyner_boore_distance(target_site) # Need to check if Rx and Ry0 are consistant with the other metrics # when those are coming from the flatfile? # Rx Rx = surface_modeled.get_rx_distance(target_site) # Ry0 Ry0 = surface_modeled.get_ry0_distance(target_site) distance = RecordDistance( repi = float(Repi), rhypo = float(Rhypo), rjb = float(Rjb), rrup = float(Rrup), r_x = float(Rx), ry0 = float(Ry0)) distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) return distance
def _sanitise(self, row, reader): """ If all of the strong motion values are negative the record is null and should be removed """ iml_vals = [] for fname in reader.fieldnames: if fname.startswith("SA(") or fname in SCALAR_LIST: # Ground motion value iml = get_float(row[fname]) if iml: iml_vals.append(iml) else: iml_vals.append(-999.0) # If all ground motion values are negative then the record is null # return false if np.all(np.array(iml_vals) < 0.0): return False else: return True
def _parse_site_data(self, metadata): """ Returns the site data as an instance of the :class: smtk.sm_database.RecordSite """ site = RecordSite( self._get_site_id(metadata["Station ID"]), metadata["Station ID"], metadata["Station Code"], get_float(metadata["Station Longitude (deg positive E)"]), get_float(metadata["Station Latitude (deg positive N)"]), get_float(metadata["Station Elevation (m)"]), get_float(metadata["Preferred Vs30 (m/s)"]), site_class=metadata[ 'Site Class (Hard Rock; Rock; Stiff Soil; Soft Soil)'], network_code=None, # not provided ) # network_code=metadata["Owner"]) site.nehrp = metadata["Preferred NEHRP Based on Vs30"] site.vs30_measured_type = metadata["Measured(1)/Inferred(2) Class"] if metadata["Measured(1)/Inferred(2) Class"] == "1": site.vs30_measured = True else: site.vs30_measured = False site.vs30_uncertainty = get_float( metadata["Sigma of Vs30 (in natural log Units)"]) site.z1pt0 = get_float(metadata["Z1 (m)"]) site.z1pt5 = None # site.z1pt5 = get_float(metadata["Z1.5 (m)"]) site.z2pt5 = get_float(metadata["Z2.5 (m)"]) # Implement default values for z1pt0 and z2pt5 if site.z1pt0 is None: site.z1pt0 = rcfg.vs30_to_z1pt0_as08(site.vs30) if site.z2pt5 is None: site.z2pt5 = rcfg.z1pt0_to_z2pt5(site.z1pt0) else: # Need to convert z2pt5 from m to km site.z2pt5 = site.z2pt5 / 1000.0 if "Backarc" in metadata["Forearc/Backarc for subduction events"]: site.backarc = True site.instrument_type = metadata["Digital (D)/Analog (A) Recording"] return site
def _parse_site_data(self, metadata): """ Returns the site data as an instance of the :class: smtk.sm_database.RecordSite """ site = RecordSite( self._get_site_id(metadata["Station ID"]), metadata["Station ID"], metadata["Station Code"], get_float(metadata["Station Longitude (deg positive E)"]), get_float(metadata["Station Latitude (deg positive N)"]), get_float(metadata["Station Elevation (m)"]), get_float(metadata["Preferred Vs30 (m/s)"]), site_class=metadata['Site Class (Hard Rock; Rock; Stiff Soil; Soft Soil)'], network_code=None, # not provided ) # network_code=metadata["Owner"]) site.nehrp = metadata["Preferred NEHRP Based on Vs30"] site.vs30_measured_type = metadata["Measured(1)/Inferred(2) Class"] if metadata["Measured(1)/Inferred(2) Class"] == "1": site.vs30_measured = True else: site.vs30_measured = False site.vs30_uncertainty = get_float( metadata["Sigma of Vs30 (in natural log Units)"]) site.z1pt0 = get_float(metadata["Z1 (m)"]) site.z1pt5 = None # site.z1pt5 = get_float(metadata["Z1.5 (m)"]) site.z2pt5 = get_float(metadata["Z2.5 (m)"]) # Implement default values for z1pt0 and z2pt5 if site.z1pt0 is None: site.z1pt0 = rcfg.vs30_to_z1pt0_as08(site.vs30) if site.z2pt5 is None: site.z2pt5 = rcfg.z1pt0_to_z2pt5(site.z1pt0) else: # Need to convert z2pt5 from m to km site.z2pt5 = site.z2pt5/1000.0 if "Backarc" in metadata["Forearc/Backarc for subduction events"]: site.backarc = True site.instrument_type = metadata["Digital (D)/Analog (A) Recording"] return site
def _parse_processing_data(self, wfid, metadata): """ Parses the information for each component """ filter_params1 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]], 'Order': None, 'Passes': get_int(metadata['npass']), 'NRoll': get_int(metadata['nroll']), 'High-Cut': get_float(metadata["LP-H1 (Hz)"]), 'Low-Cut': get_float(metadata["HP-H1 (Hz)"]) } filter_params2 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]], 'Order': None, 'Passes': get_int(metadata['npass']), 'NRoll': get_int(metadata['nroll']), 'High-Cut': get_float(metadata["LP-H2 (Hz)"]), 'Low-Cut': get_float(metadata["HP-H2 (Hz)"]) } intensity_measures = { # All m - convert to cm 'PGA': None, 'PGV': None, 'PGD': None } lup1 = 1. / get_float(metadata["Lowest Usable Freq - H1 (Hz)"]) lup2 = 1. / get_float(metadata["Lowest Usable Freq - H2 (Hz)"]) xcomp = Component(wfid, "1", ims=intensity_measures, longest_period=lup1, waveform_filter=filter_params1, units=metadata["Unit"]) ycomp = Component(wfid, "2", ims=intensity_measures, longest_period=lup2, waveform_filter=filter_params2, units=metadata["Unit"]) return xcomp, ycomp, None
def _parse_processing_data(self, wfid, metadata): """ Parses the information for each component """ filter_params1 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]] , 'Order': None, 'Passes': get_int(metadata['npass']), 'NRoll': get_int(metadata['nroll']), 'High-Cut': get_float(metadata["LP-H1 (Hz)"]), 'Low-Cut': get_float(metadata["HP-H1 (Hz)"])} filter_params2 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]] , 'Order': None, 'Passes': get_int(metadata['npass']), 'NRoll': get_int(metadata['nroll']), 'High-Cut': get_float(metadata["LP-H2 (Hz)"]), 'Low-Cut': get_float(metadata["HP-H2 (Hz)"])} intensity_measures = { # All m - convert to cm 'PGA': None, 'PGV': None, 'PGD': None } lup1 = 1. / get_float(metadata["Lowest Usable Freq - H1 (Hz)"]) lup2 = 1. / get_float(metadata["Lowest Usable Freq - H2 (Hz)"]) xcomp = Component(wfid, "1", ims=intensity_measures, longest_period=lup1, waveform_filter=filter_params1, units=metadata["Unit"]) ycomp = Component(wfid, "2", ims=intensity_measures, longest_period=lup2, waveform_filter=filter_params2, units=metadata["Unit"]) return xcomp, ycomp, None
def _parse_distance_data(self, event, site, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.RecordDistance """ # Compute various distance metrics # Add calculation of Repi, Rhypo from event and station localizations # (latitudes, longitudes, depth, elevation)? target_site = Mesh(np.array([site.longitude]), np.array([site.latitude]), np.array([-site.altitude / 1000.0])) # Warning ratio fixed to 1.5 ratio = 1.5 if not event.rupture.area: event.rupture.area = WC1994().get_median_area( event.magnitude.value, None) surface_modeled = rcfg.create_planar_surface( Point(event.longitude, event.latitude, event.depth), event.mechanism.nodal_planes.nodal_plane_1['strike'], event.mechanism.nodal_planes.nodal_plane_1['dip'], event.rupture.area, ratio) hypocenter = rcfg.get_hypocentre_on_planar_surface( surface_modeled, event.rupture.hypo_loc) try: surface_modeled._create_mesh() except: dip = surface_modeled.get_dip() dip_dir = (surface_modeled.get_strike() - 90.) % 360. ztor = surface_modeled.top_left.depth d_x = ztor * np.tan(np.radians(90.0 - dip)) top_left_surface = surface_modeled.top_left.point_at( d_x, -ztor, dip_dir) top_left_surface.depth = 0. top_right_surface = surface_modeled.top_right.point_at( d_x, -ztor, dip_dir) top_right_surface.depth = 0. surface_modeled = SimpleFaultSurface.from_fault_data( Line([top_left_surface, top_right_surface]), surface_modeled.top_left.depth, surface_modeled.bottom_left.depth, surface_modeled.get_dip(), 1.0) # Rhypo Rhypo, Repi, Rrup, Rjb, Ry0 = tuple( map(get_positive_float, [ metadata[key] for key in [ "Hypocentral Distance (km)", "Epicentral Distance (km)", "Rupture Distance (km)", "Joyner-Boore Distance (km)", "Ry0 (km)" ] ])) Rx = get_float(metadata["Rx (km)"]) # Rx can be negative #Rhypo = get_float(metadata["Hypocentral Distance (km)"]) if Rhypo is None or Rhypo < 0.0: Rhypo = hypocenter.distance_to_mesh(target_site) # Repi #Repi = get_float(metadata["Epicentral Distance (km)"]) if Repi is None or Repi < 0.0: Repi = hypocenter.distance_to_mesh(target_site, with_depths=False) # Rrup #Rrup = get_float(metadata["Rupture Distance (km)"]) if Rrup is None or Rrup < 0.0: Rrup = surface_modeled.get_min_distance(target_site)[0] # Rjb #Rjb = get_float(metadata["Joyner-Boore Distance (km)"]) if Rjb is None or Rjb < 0.0: Rjb = surface_modeled.get_joyner_boore_distance(target_site)[0] # Need to check if Rx and Ry0 are consistant with the other metrics # when those are coming from the flatfile? # Rx #Rx = get_float(metadata["Rx (km)"]) if Rx is None or Rx < 0.0: Rx = surface_modeled.get_rx_distance(target_site)[0] # Ry0 Ry0 = get_float(metadata["Ry0 (km)"]) if Ry0 is None or Ry0 < 0.0: Ry0 = surface_modeled.get_ry0_distance(target_site)[0] distance = RecordDistance(repi=Repi, rhypo=Rhypo, rjb=Rjb, rrup=Rrup, r_x=Rx, ry0=Ry0) distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) #distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) if metadata["FW/HW Indicator"] == "HW": distance.hanging_wall = True elif metadata["FW/HW Indicator"] == "FW": distance.hanging_wall = False else: pass return distance return
def _parse_time_history(self, ifile, component2parse): """ Parses the time history and returns the time history of the specified component. All 3 components are provided in every ASA file. Note that components are defined with various names, and are not always given in the same order """ # The components are definied using the following names comp_names = {'X': ['ENE', 'N90E', 'N90E;', 'N90W', 'N90W;', 'S90E', 'S90W', 'E--W', 'S9OE'], 'Y': ['ENN', 'N00E', 'N00E;', 'NOOE;', 'N00W', 'NOOW;', 'S00E', 'S00W', 'N--S', 'NOOE'], 'V': ['ENZ', 'V', 'V;+', '+V', 'Z', 'VERT']} # Read component names, which are given on line 107 o = open(ifile, "r", encoding='iso-8859-1') r = o.readlines() components = list(r[107].split()) # Check if any component names are repeated if any(components.count(x) > 1 for x in components): raise ValueError( "Some components %s in record %s have the same name" % (components, ifile)) # Check if more than 3 components are given if len(components) > 3: raise ValueError( "More than 3 components %s in record %s" % (components, ifile)) # Get acceleration data from correct column column = None for i in comp_names[component2parse]: if i == components[0]: column = 0 try: accel = np.genfromtxt(ifile, skip_header=109, usecols=column, delimiter='', encoding='iso-8859-1') except: raise ValueError( "Check %s has 3 equal length time-series columns" % ifile) break elif i == components[1]: column = 1 try: accel = np.genfromtxt(ifile, skip_header=109, usecols=column, delimiter='', encoding='iso-8859-1') except: raise ValueError( "Check %s has 3 equal length time-series columns" % ifile) break elif i == components[2]: column = 2 try: accel = np.genfromtxt(ifile, skip_header=109, usecols=column, delimiter='', encoding='iso-8859-1') except: raise ValueError( "Check %s has 3 equal length time-series columns" % ifile) break if column is None: raise ValueError( "None of the components %s were found to be \n\ the %s component of file %s" % (components, component2parse, ifile)) # Build the metadata dictionary again metadata = _get_metadata_from_file(ifile) # Get units units_provided = metadata["UNIDADES DE LOS DATOS"] units = units_provided[units_provided.find("(") + 1: units_provided.find(")")] # Get time step, naming is not consistent so allow for variation for i in metadata: if 'INTERVALO DE MUESTREO, C1' in i: self.time_step = get_float(metadata[i].split("/")[1]) # Get number of time steps, use len(accel) because # sometimes "NUM. TOTAL DE MUESTRAS, C1-C6" is wrong self.number_steps = len(accel) output = { "Acceleration": convert_accel_units(accel, self.units), "Time": get_time_vector(self.time_step, self.number_steps), "Time-step": self.time_step, "Number Steps": self.number_steps, "Units": self.units, "PGA": max(abs(accel)), "PGD": None } return output
def _parse_time_history(self, ifile, component2parse): """ Parses the time history and returns the time history of the specified component. All 3 components are provided in every ASA file. Note that components are defined with various names, and are not always given in the same order """ # The components are definied using the following names comp_names = { 'X': ['N90E', 'N90E;', 'N90W', 'N90W;', 'S90E', 'S90W', 'E--W', 'S9OE'], 'Y': ['N00E', 'N00E;', 'N00W', 'N00W;', 'S00E', 'S00W', 'N--S', 'NOOE'], 'V': ['V', 'V;+', '+V', 'Z', 'VERT'] } # Read component names, which are given on line 107 o = open(ifile, "r") r = o.readlines() components = list(r[107].split()) # Check if any component names are repeated if any(components.count(x) > 1 for x in components): raise ValueError( "Some components %s in record %s have the same name" % (components, ifile)) # Check if more than 3 components are given if len(components) > 3: raise ValueError("More than 3 components %s in record %s" % (components, ifile)) # Get acceleration data from correct column column = None for i in comp_names[component2parse]: if i == components[0]: column = 0 try: accel = np.genfromtxt(ifile, skip_header=109, usecols=column, delimiter='') except: raise ValueError( "Check %s has 3 equal length time-series columns" % ifile) break elif i == components[1]: column = 1 try: accel = np.genfromtxt(ifile, skip_header=109, usecols=column, delimiter='') except: raise ValueError( "Check %s has 3 equal length time-series columns" % ifile) break elif i == components[2]: column = 2 try: accel = np.genfromtxt(ifile, skip_header=109, usecols=column, delimiter='') except: raise ValueError( "Check %s has 3 equal length time-series columns" % ifile) break if column is None: raise ValueError("None of the components %s were found to be \n\ the %s component of file %s" % (components, component2parse, ifile)) # Build the metadata dictionary again metadata = _get_metadata_from_file(ifile) # Get units units_provided = metadata["UNIDADES DE LOS DATOS"] units = units_provided[units_provided.find("(") + 1:units_provided.find(")")] # Get time step, naming is not consistent so allow for variation for i in metadata: if 'INTERVALO DE MUESTREO, C1' in i: self.time_step = get_float(metadata[i].split("/")[1]) # Get number of time steps, use len(accel) because # sometimes "NUM. TOTAL DE MUESTRAS, C1-C6" is wrong self.number_steps = len(accel) output = { "Acceleration": convert_accel_units(accel, self.units), "Time": get_time_vector(self.time_step, self.number_steps), "Time-step": self.time_step, "Number Steps": self.number_steps, "Units": self.units, "PGA": max(abs(accel)), "PGD": None } return output
def _parse_processing_data(self, wfid, metadata): """ Parses the information for each component """ if metadata["Type of Filter"]: filter_params1 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]], 'Order': None, 'Passes': get_positive_int(metadata['npass']), 'NRoll': get_positive_int(metadata['nroll']), 'High-Cut': get_positive_float(metadata["LP-H1 (Hz)"]), 'Low-Cut': get_positive_float(metadata["HP-H1 (Hz)"])} filter_params2 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]], 'Order': None, 'Passes': get_positive_int(metadata['npass']), 'NRoll': get_positive_int(metadata['nroll']), 'High-Cut': get_positive_float(metadata["LP-H2 (Hz)"]), 'Low-Cut': get_positive_float(metadata["HP-H2 (Hz)"])} else: filter_params1, filter_params2 = None, None intensity_measures = { # All m - convert to cm 'PGA': None, 'PGV': None, 'PGD': None } luf1 = get_float(metadata["Lowest Usable Freq - H1 (Hz)"]) if luf1 and luf1 > 0.0: lup1 = 1. / luf1 else: lup1 = None luf2 = get_float(metadata["Lowest Usable Freq - H2 (Hz)"]) if luf2 and luf2 > 0.0: lup2 = 1. / luf2 else: lup2 = None xcomp = Component(wfid, "1", ims=intensity_measures, longest_period=lup1, waveform_filter=filter_params1, units=metadata["Unit (cm/s/s; m/s/s; g)"]) ycomp = Component(wfid, "2", ims=intensity_measures, longest_period=lup2, waveform_filter=filter_params2, units=metadata["Unit (cm/s/s; m/s/s; g)"]) luf3 = get_float(metadata["Lowest Usable Freq - V (Hz)"]) if luf3 and luf3 > 0.0: filter_params3 = { 'Type': FILTER_TYPE[metadata["Type of Filter"]], 'Order': None, 'Passes': get_int(metadata['npass']), 'NRoll': get_int(metadata['nroll']), 'High-Cut': get_float(metadata["LP-V (Hz)"]), 'Low-Cut': get_float(metadata["HP-V (Hz)"])} lup3 = 1. / luf3 zcomp = Component(wfid, "V", ims=intensity_measures, longest_period=lup3, waveform_filter=filter_params3, units=metadata["Unit (cm/s/s; m/s/s; g)"]) return xcomp, ycomp, zcomp else: return xcomp, ycomp, None
def _parse_event(self, metadata, file_str): """ Parses the event metadata to return an instance of the :class: smtk.sm_database.Earthquake """ months = { 'ENERO': 1, 'FEBRERO': 2, 'MARZO': 3, 'ABRIL': 4, 'MAYO': 5, 'JUNIO': 6, 'JULIO': 7, 'AGOSTO': 8, 'SEPTIEMBRE': 9, 'OCTUBURE': 10, 'NOVIEMBRE': 11, 'DICIEMBRE': 12 } # Date and time try: # UNAM DATES year, month, day = ( get_int(metadata["FECHA DEL SISMO [GMT]"].split("/")[0]), get_int(metadata["FECHA DEL SISMO [GMT]"].split("/")[1]), get_int(metadata["FECHA DEL SISMO [GMT]"].split("/")[2])) except: # CICESE DATES year, month, day = ( get_int(metadata["FECHA DEL SISMO (GMT)"][-4:]), months[metadata["FECHA DEL SISMO (GMT)"].split()[2]], get_int(metadata["FECHA DEL SISMO (GMT)"][:2])) # Get event time, naming is not consistent (e.g. 07.1, 00, 17,1) for i in metadata: if 'HORA EPICENTRO (GMT)' in i: hour, minute, second = ( get_int(metadata[i].split(":")[0]), get_int(metadata[i].split(":")[1]), int( float(metadata[i].split(":")[2].replace( "0", "", 1).replace(",", ".")))) try: eq_datetime = datetime(year, month, day, hour, minute, second) except: raise ValueError("Record %s is missing event time" % file_str) # Event ID - No EVID, so use the date and time of the event eq_id = str(eq_datetime).replace(" ", "_") # Event Name eq_name = None # Get magnitudes, below are the different types given in ASA files moment_mag = None surface_mag = None body_mag = None c_mag = None l_mag = None e_mag = None a_mag = None m_mag = None mag_list = [] mag = metadata["MAGNITUD(ES)"].split("/") for i in range(0, len(mag)): if mag[i][0:2] == "": continue if mag[i][0:2] == "Mw": m_w = get_float(mag[i][3:]) moment_mag = Magnitude(m_w, "Mw") mag_list.append(moment_mag) if mag[i][0:2] == "Ms": m_s = get_float(mag[i][3:]) surface_mag = Magnitude(m_s, "Ms") mag_list.append(surface_mag) if mag[i][0:2] == "Mb": m_b = get_float(mag[i][3:]) body_mag = Magnitude(m_b, "Mb") mag_list.append(body_mag) if mag[i][0:2] == "Mc": m = get_float(mag[i][3:]) c_mag = Magnitude(m, "Mc") mag_list.append(c_mag) if mag[i][0:2] == "Ml": m = get_float(mag[i][3:]) l_mag = Magnitude(m, "Ml") mag_list.append(l_mag) if mag[i][0:2] == "Me" or mag[i][0:2] == "ME": m = get_float(mag[i][3:]) e_mag = Magnitude(m, "Me") mag_list.append(e_mag) if mag[i][0:2] == "Ma": m = get_float(mag[i][3:]) a_mag = Magnitude(m, "Ma") mag_list.append(a_mag) if mag[i][0:2] == "M=": m = get_float(mag[i][2:]) m_mag = Magnitude(m, "M") mag_list.append(m_mag) # magnitude hierarchy for defining pref_mag if moment_mag is not None: pref_mag = moment_mag elif surface_mag is not None: pref_mag = surface_mag elif body_mag is not None: pref_mag = body_mag elif c_mag is not None: pref_mag = c_mag elif l_mag is not None: pref_mag = l_mag elif e_mag is not None: pref_mag = e_mag elif a_mag is not None: pref_mag = a_mag elif m_mag is not None: pref_mag = m_mag else: raise ValueError("Record %s has no magnitude!" % file_str) # Get focal mechanism data (not given in ASA file) foc_mech = FocalMechanism(eq_id, eq_name, None, None, mechanism_type=None) # Get depths, naming is not consistent so allow for variation for i in metadata: if 'PROFUNDIDAD ' in i: # assume <5km = 5km evtdepth = get_float(re.sub('[ <>]', '', metadata[i])) if evtdepth is None: raise ValueError("Record %s is missing event depth" % file_str) # Build event eqk = Earthquake( eq_id, eq_name, eq_datetime, get_float(metadata["COORDENADAS DEL EPICENTRO"].split(" ")[3]), get_float(metadata["COORDENADAS DEL EPICENTRO"].split(" ")[0]), evtdepth, pref_mag, foc_mech) eqk.magnitude_list = mag_list return eqk
def _parse_distance_data(self, event, site, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.RecordDistance """ # Compute various distance metrics # Add calculation of Repi, Rhypo from event and station localizations # (latitudes, longitudes, depth, elevation)? target_site = Mesh(np.array([site.longitude]), np.array([site.latitude]), np.array([-site.altitude / 1000.0])) # Warning ratio fixed to 1.5 ratio=1.5 if not event.rupture.area: event.rupture.area = WC1994().get_median_area(event.magnitude.value, None) surface_modeled = rcfg.create_planar_surface( Point(event.longitude, event.latitude, event.depth), event.mechanism.nodal_planes.nodal_plane_1['strike'], event.mechanism.nodal_planes.nodal_plane_1['dip'], event.rupture.area, ratio) hypocenter = rcfg.get_hypocentre_on_planar_surface( surface_modeled, event.rupture.hypo_loc) try: surface_modeled._create_mesh() except: dip = surface_modeled.get_dip() dip_dir = (surface_modeled.get_strike() - 90.) % 360. ztor = surface_modeled.top_left.depth d_x = ztor * np.tan(np.radians(90.0 - dip)) top_left_surface = surface_modeled.top_left.point_at(d_x, -ztor, dip_dir) top_left_surface.depth = 0. top_right_surface = surface_modeled.top_right.point_at(d_x, -ztor, dip_dir) top_right_surface.depth = 0. surface_modeled = SimpleFaultSurface.from_fault_data( Line([top_left_surface, top_right_surface]), surface_modeled.top_left.depth, surface_modeled.bottom_left.depth, surface_modeled.get_dip(), 1.0) # Rhypo Rhypo, Repi, Rrup, Rjb, Ry0 = tuple(map( get_positive_float, [metadata[key] for key in [ "Hypocentral Distance (km)", "Epicentral Distance (km)", "Rupture Distance (km)", "Joyner-Boore Distance (km)", "Ry0 (km)"]])) Rx = get_float(metadata["Rx (km)"]) # Rx can be negative #Rhypo = get_float(metadata["Hypocentral Distance (km)"]) if Rhypo is None or Rhypo < 0.0: Rhypo = hypocenter.distance_to_mesh(target_site) # Repi #Repi = get_float(metadata["Epicentral Distance (km)"]) if Repi is None or Repi < 0.0: Repi= hypocenter.distance_to_mesh(target_site, with_depths=False) # Rrup #Rrup = get_float(metadata["Rupture Distance (km)"]) if Rrup is None or Rrup < 0.0: Rrup = surface_modeled.get_min_distance(target_site)[0] # Rjb #Rjb = get_float(metadata["Joyner-Boore Distance (km)"]) if Rjb is None or Rjb < 0.0: Rjb = surface_modeled.get_joyner_boore_distance( target_site)[0] # Need to check if Rx and Ry0 are consistant with the other metrics # when those are coming from the flatfile? # Rx #Rx = get_float(metadata["Rx (km)"]) if Rx is None or Rx < 0.0: Rx = surface_modeled.get_rx_distance(target_site)[0] # Ry0 Ry0 = get_float(metadata["Ry0 (km)"]) if Ry0 is None or Ry0 < 0.0: Ry0 = surface_modeled.get_ry0_distance(target_site)[0] distance = RecordDistance( repi = Repi, rhypo = Rhypo, rjb = Rjb, rrup = Rrup, r_x = Rx, ry0 = Ry0) distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) #distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) if metadata["FW/HW Indicator"] == "HW": distance.hanging_wall = True elif metadata["FW/HW Indicator"] == "FW": distance.hanging_wall = False else: pass return distance return
def _parse_distance_data(self, event, site, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.RecordDistance """ # Compute various distance metrics # Add calculation of Repi, Rhypo from event and station localizations # (latitudes, longitudes, depth, elevation)? target_site = Mesh(np.array([site.longitude]), np.array([site.latitude]), np.array([-site.altitude / 1000.0])) # Warning ratio fixed to 1.5 ratio=1.5 surface_modeled = rcfg.create_planar_surface( Point(event.longitude, event.latitude, event.depth), event.mechanism.nodal_planes.nodal_plane_1['strike'], event.mechanism.nodal_planes.nodal_plane_1['dip'], event.rupture.area, ratio) hypocenter = rcfg.get_hypocentre_on_planar_surface( surface_modeled, event.rupture.hypo_loc) try: surface_modeled._create_mesh() except: dip = surface_modeled.get_dip() dip_dir = (surface_modeled.get_strike() - 90.) % 360. ztor = surface_modeled.top_left.depth d_x = ztor * np.tan(np.radians(90.0 - dip)) top_left_surface = surface_modeled.top_left.point_at(d_x, -ztor, dip_dir) top_left_surface.depth = 0. top_right_surface = surface_modeled.top_right.point_at(d_x, -ztor, dip_dir) top_right_surface.depth = 0. surface_modeled = SimpleFaultSurface.from_fault_data( Line([top_left_surface, top_right_surface]), surface_modeled.top_left.depth, surface_modeled.bottom_left.depth, surface_modeled.get_dip(), 1.0) # Rhypo Rhypo = get_float(metadata["Hypocentral Distance (km)"]) if Rhypo is None: Rhypo = hypocenter.distance_to_mesh(target_site) # Repi Repi = get_float(metadata["Epicentral Distance (km)"]) if Repi is None: Repi= hypocenter.distance_to_mesh(target_site, with_depths=False) # Rrup Rrup = get_float(metadata["Rupture Distance (km)"]) if Rrup is None: Rrup = surface_modeled.get_min_distance(target_site) # Rjb Rjb = get_float(metadata["Joyner-Boore Distance (km)"]) if Rjb is None: Rjb = surface_modeled.get_joyner_boore_distance(target_site) # Rcdpp Rcdpp = get_float(metadata["Rcdpp"]) if Rcdpp is None: Rcdpp = surface_modeled.get_cdppvalue(target_site) # Need to check if Rx and Ry0 are consistant with the other metrics # when those are coming from the flatfile? # Rx Rx = surface_modeled.get_rx_distance(target_site) # Ry0 Ry0 = surface_modeled.get_ry0_distance(target_site) distance = RecordDistance( repi = float(Repi), rhypo = float(Rhypo), rjb = float(Rjb), rrup = float(Rrup), r_x = float(Rx), ry0 = float(Ry0), rcdpp = float(Rcdpp) ) distance.azimuth = get_float(metadata["Source to Site Azimuth (deg)"]) #distance.hanging_wall = get_float(metadata["FW/HW Indicator"]) if metadata["FW/HW Indicator"] == "HW": distance.hanging_wall = True elif metadata["FW/HW Indicator"] == "FW": distance.hanging_wall = False else: pass return distance
def _get_focal_mechanism(self, eq_id, eq_name, metadata): """ Returns the focal mechanism information as an instance of the :class: smtk.sigma_database.FocalMechanism """ nodal_planes = GCMTNodalPlanes() # By default nodal plane 1 is assumed to be the fault plane in smtk. # Depending on parameter fault_plane import correct angles in nodal # planes 1 and 2 (1 being the fault plane) if metadata['Fault Plane (1; 2; X)'] == '1': nodal_planes.nodal_plane_1 = { "strike": get_float(metadata['Nodal Plane 1 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 1 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 1 Rake Angle (deg)'])} nodal_planes.nodal_plane_2 = { "strike": get_float(metadata['Nodal Plane 2 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 2 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 2 Rake Angle (deg)'])} elif metadata['Fault Plane (1; 2; X)'] == '2': nodal_planes.nodal_plane_1 = { "strike": get_float(metadata['Nodal Plane 2 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 2 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 2 Rake Angle (deg)'])} nodal_planes.nodal_plane_2 = { "strike": get_float(metadata['Nodal Plane 1 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 1 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 1 Rake Angle (deg)'])} elif metadata['Fault Plane (1; 2; X)'] == 'X': # Check if values for strike or dip are given otherwise set # strike=0 and dip=90 and fill strike and dip for fault plane 1 # What can we do for rake? strike = get_float(metadata['Nodal Plane 1 Strike (deg)']) if strike is None: strike = get_float(metadata['Nodal Plane 2 Strike (deg)']) if strike is None: strike = 0.0 dip = get_float(metadata['Nodal Plane 1 Dip (deg)']) if dip is None: dip = get_float(metadata['Nodal Plane 2 Dip (deg)']) if dip is None: dip = 90.0 nodal_planes.nodal_plane_1 = {"strike": strike, "dip": dip, "rake": None} nodal_planes.nodal_plane_2 = {"strike": None, "dip": None, "rake": None} nodal_planes = self._check_mechanism(nodal_planes) principal_axes = GCMTPrincipalAxes() mech_type =\ NEW_MECHANISM_TYPE[metadata["Style-of-Faulting (S; R; N; U)"]] return FocalMechanism(eq_id, eq_name, nodal_planes, principal_axes, mechanism_type=mech_type)
def _parse_event_data(self, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.Earthquake """ data_fields = ['Month', 'Day', 'Hour', 'Minute', 'Second'] for f in data_fields: metadata[f] = metadata[f].zfill(2) # Date and Time year, month, day, hour, minute, second = self._validate_datetime( metadata) #year = get_int(metadata["Year"]) #month = get_int(metadata["Month"]) #day = get_int(metadata["Day"]) #hour = get_int(metadata["Hour"]) #minute = get_int(metadata["Minute"]) #second = get_int(metadata["Second"]) eq_datetime = datetime(year, month, day, hour, minute, second) # Event ID and Name eq_id = metadata["EQID"] eq_name = metadata["Earthquake Name"] # Focal Mechanism focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata) focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\ 1E-7 # Read magnitude pref_mag = Magnitude(get_float(metadata["Magnitude"]), metadata["Magnitude type"], sigma=get_float(metadata["Magnitude uncertainty"])) # Create Earthquake Class eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata["Epicenter Longitude (deg; positive E)"]), get_float(metadata["Epicenter Latitude (deg; positive N)"]), get_float(metadata["Hypocenter Depth (km)"]), pref_mag, focal_mechanism, metadata["Country"]) # hypocenter location f1 = get_float(metadata[ "Along-strike Hypocenter location " + "on the fault (fraction between 0 and 1)"]) f2 = get_float(metadata[ "Along-width Hypocenter location " + "on the fault (fraction between 0 and 1)"]) if f1 is None or f2 is None: hypo_loc = (0.5, 0.7) else: hypo_loc = (f1, f2) eqk.tectonic_region = metadata["Tectonic environment (Crustal; Inslab; Interface; Stable; Geothermal; Volcanic; Oceanic_crust)"] if (eqk.tectonic_region == "Stable" or eqk.tectonic_region == "Crustal" or eqk.tectonic_region == "Oceanic_crust"): msr=WC1994() elif eqk.tectonic_region == "Inslab": msr=StrasserIntraslab() elif eqk.tectonic_region == "Interface": msr=StrasserInterface() # Warning rake set to 0.0 in scaling relationship - applies only # to WC1994 area = msr.get_median_area(pref_mag.value, 0.0) aspect_ratio = 1.5 width_model = np.sqrt(area / aspect_ratio) length_model = aspect_ratio * width_model ztor_model = eqk.depth - width_model / 2. if ztor_model < 0: ztor_model = 0.0 length = get_positive_float(metadata["Fault Rupture Length (km)"]) if length is None: length = length_model width = get_positive_float(metadata["Fault Rupture Width (km)"]) if width is None: width = width_model ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"]) if ztor is None: ztor=ztor_model # Rupture eqk.rupture = Rupture(eq_id, eq_name, pref_mag, length, width, ztor, hypo_loc=hypo_loc) # get_float(metadata["Fault Rupture Length (km)"]), # get_float(metadata["Fault Rupture Width (km)"]), # get_float(metadata["Depth to Top Of Fault Rupture Model"]), # hypo_loc=hypo_loc) eqk.rupture.get_area() return eqk
def _parse_event_data(self, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.Earthquake """ data_fields = ['Month', 'Day', 'Hour', 'Minute', 'Second'] for f in data_fields: metadata[f] = metadata[f].zfill(2) # Date and Time year = get_int(metadata["Year"]) month = get_int(metadata["Month"]) day = get_int(metadata["Day"]) hour = get_int(metadata["Hour"]) minute = get_int(metadata["Minute"]) second = get_int(metadata["Second"]) eq_datetime = datetime(year, month, day, hour, minute, second) # Event ID and Name eq_id = metadata["EQID"] eq_name = metadata["Earthquake Name"] # Focal Mechanism focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata) focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\ 1E-7 # Read magnitude pref_mag = Magnitude(get_float(metadata["Magnitude"]), metadata["Magnitude type"], sigma=get_float(metadata["Magnitude uncertainty"])) # Create Earthquake Class eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata["Epicenter Longitude (deg; positive E)"]), get_float(metadata["Epicenter Latitude (deg; positive N)"]), get_float(metadata["Hypocenter Depth (km)"]), pref_mag, focal_mechanism, metadata["Country"]) # hypocenter location f1 = get_float(metadata[ "Along-strike Hypocenter location " + "on the fault (fraction between 0 and 1)"]) f2 = get_float(metadata[ "Along-width Hypocenter location " + "on the fault (fraction between 0 and 1)"]) if f1 is None or f2 is None: hypo_loc = (0.5, 0.7) else: hypo_loc = (f1, f2) evt_tectonic_region = metadata["Tectonic environment (Crustal; Inslab; Interface; Stable; Geothermal; Volcanic; Oceanic_crust)"] if evt_tectonic_region == "Stable" or evt_tectonic_region == "Crustal": msr=WC1994() elif evt_tectonic_region == "Inslab": msr=StrasserIntraslab() elif evt_tectonic_region == "Interface": msr=StrasserInterface() # Warning rake set to 0.0 in scaling relationship - applies only # to WC1994 area = msr.get_median_area(pref_mag.value, 0.0) aspect_ratio = 1.5 width_model = np.sqrt(area / aspect_ratio) length_model = aspect_ratio * width_model ztor_model = eqk.depth - width_model / 2. if ztor_model < 0: ztor_model = 0.0 length = get_float(metadata["Fault Rupture Length (km)"]) if length is None: length = length_model width = get_float(metadata["Fault Rupture Width (km)"]) if width is None: width = width_model ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"]) if ztor is None: ztor=ztor_model # Rupture eqk.rupture = Rupture(eq_id, length, width, ztor, hypo_loc=hypo_loc) # get_float(metadata["Fault Rupture Length (km)"]), # get_float(metadata["Fault Rupture Width (km)"]), # get_float(metadata["Depth to Top Of Fault Rupture Model"]), # hypo_loc=hypo_loc) eqk.rupture.get_area() return eqk
def _get_focal_mechanism(self, eq_id, eq_name, metadata): """ Returns the focal mechanism information as an instance of the :class: smtk.sigma_database.FocalMechanism """ nodal_planes = GCMTNodalPlanes() # By default nodal plane 1 is assumed to be the fault plane in smtk. # Depending on parameter fault_plane import correct angles in nodal # planes 1 and 2 (1 being the fault plane) if metadata['Fault Plane (1; 2; X)'] == '1': nodal_planes.nodal_plane_1 = { "strike": get_float(metadata['Nodal Plane 1 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 1 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 1 Rake Angle (deg)'])} nodal_planes.nodal_plane_2 = { "strike": get_float(metadata['Nodal Plane 2 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 2 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 2 Rake Angle (deg)'])} elif metadata['Fault Plane (1; 2; X)'] == '2': nodal_planes.nodal_plane_1 = { "strike": get_float(metadata['Nodal Plane 2 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 2 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 2 Rake Angle (deg)'])} nodal_planes.nodal_plane_2 = { "strike": get_float(metadata['Nodal Plane 1 Strike (deg)']), "dip": get_float(metadata['Nodal Plane 1 Dip (deg)']), "rake": get_float(metadata['Nodal Plane 1 Rake Angle (deg)'])} elif metadata['Fault Plane (1; 2; X)'] == 'X': # Check if values for strike or dip are given otherwise set # strike=0 and dip=90 and fill strike and dip for fault plane 1 # What can we do for rake? strike = get_float(metadata['Nodal Plane 1 Strike (deg)']) if strike is None: strike = get_float(metadata['Nodal Plane 2 Strike (deg)']) if strike is None: strike = 0.0 dip = get_float(metadata['Nodal Plane 1 Dip (deg)']) if dip is None: dip = get_float(metadata['Nodal Plane 2 Dip (deg)']) if dip is None: dip = 90.0 nodal_planes.nodal_plane_1 = {"strike": strike, "dip": dip, "rake": None} nodal_planes.nodal_plane_2 = {"strike": None, "dip": None, "rake": None} principal_axes = GCMTPrincipalAxes() mech_type =\ NEW_MECHANISM_TYPE[metadata["Style-of-Faulting (S; R; N; U)"]] return FocalMechanism(eq_id, eq_name, nodal_planes, principal_axes, mechanism_type=mech_type)
def _parse_event(self, metadata, file_str): """ Parses the event metadata to return an instance of the :class: smtk.sm_database.Earthquake. Coordinates in western hemisphere are returned as negative values. """ months = {'ENERO': 1, 'FEBRERO': 2, 'MARZO': 3, 'ABRIL': 4, 'MAYO': 5, 'JUNIO': 6, 'JULIO': 7, 'AGOSTO': 8, 'SEPTIEMBRE': 9, 'OCTUBURE': 10, 'NOVIEMBRE': 11, 'DICIEMBRE': 12} months_abrev = {'ENE': 1, 'FEB': 2, 'MAR': 3, 'ABR': 4, 'MAY': 5, 'JUN': 6, 'JUL': 7, 'AGO': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DIC': 12} # Date and time if 'CICESE' in metadata["INSTITUCION RESPONSABLE"]: year, month, day = ( get_int(metadata["FECHA DEL SISMO (GMT)"][-4:]), months[metadata["FECHA DEL SISMO (GMT)"].split()[2]], get_int(metadata["FECHA DEL SISMO (GMT)"][:2])) elif 'CIRES' in metadata["INSTITUCION RESPONSABLE"]: year, month, day = ( get_int('20'+metadata["FECHA DEL SISMO (GMT)"][-2:]), months_abrev[metadata["FECHA DEL SISMO (GMT)"].split('/')[1]], get_int(metadata["FECHA DEL SISMO (GMT)"][:2])) # UNAM data, which is not always indicated in "INSTITUCION RESPONSABLE" else: year, month, day = ( get_int(metadata["FECHA DEL SISMO [GMT]"].split("/")[0]), get_int(metadata["FECHA DEL SISMO [GMT]"].split("/")[1]), get_int(metadata["FECHA DEL SISMO [GMT]"].split("/")[2])) # Get event time, naming is not consistent (e.g. 07.1, 00, 17,1) for i in metadata: if 'HORA EPICENTRO (GMT)' in i: hour, minute, second = (get_int(metadata[i].split(":")[0]), get_int(metadata[i].split(":")[1]), int(float(metadata[i].split(":")[2]. replace("0", "", 1). replace(",", ".")))) try: eq_datetime = datetime(year, month, day, hour, minute, second) except: raise ValueError("Record %s is missing event time" % file_str) # Event ID - No EVID, so use the date and time of the event eq_id = str(eq_datetime).replace(" ", "_") # Event Name eq_name = None # Get magnitudes, below are the different types given in ASA files moment_mag = None surface_mag = None body_mag = None c_mag = None l_mag = None e_mag = None a_mag = None m_mag = None mag_list = [] mag = metadata["MAGNITUD(ES)"].split("/") for i in range(0, len(mag)): if mag[i][0:2] == "": continue if mag[i][0:2] == "Mw": m_w = get_float(mag[i][3:]) moment_mag = Magnitude(m_w, "Mw") mag_list.append(moment_mag) if mag[i][0:2] == "Ms": m_s = get_float(mag[i][3:]) surface_mag = Magnitude(m_s, "Ms") mag_list.append(surface_mag) if mag[i][0:2] == "Mb": m_b = get_float(mag[i][3:]) body_mag = Magnitude(m_b, "Mb") mag_list.append(body_mag) if mag[i][0:2] == "Mc": m = get_float(mag[i][3:]) c_mag = Magnitude(m, "Mc") mag_list.append(c_mag) if mag[i][0:2] == "Ml": m = get_float(mag[i][3:]) l_mag = Magnitude(m, "Ml") mag_list.append(l_mag) if mag[i][0:2] == "Me" or mag[i][0:2] == "ME": m = get_float(mag[i][3:]) e_mag = Magnitude(m, "Me") mag_list.append(e_mag) if mag[i][0:2] == "Ma": m = get_float(mag[i][3:]) a_mag = Magnitude(m, "Ma") mag_list.append(a_mag) if mag[i][0:2] == "M=": m = get_float(mag[i][2:]) m_mag = Magnitude(m, "M") mag_list.append(m_mag) # magnitude hierarchy for defining pref_mag if moment_mag is not None: pref_mag = moment_mag elif surface_mag is not None: pref_mag = surface_mag elif body_mag is not None: pref_mag = body_mag elif c_mag is not None: pref_mag = c_mag elif l_mag is not None: pref_mag = l_mag elif e_mag is not None: pref_mag = e_mag elif a_mag is not None: pref_mag = a_mag elif m_mag is not None: pref_mag = m_mag else: raise ValueError("Record %s has no magnitude!" % file_str) # Get focal mechanism data (not given in ASA file) foc_mech = FocalMechanism(eq_id, eq_name, None, None, mechanism_type=None) # Get depths, naming is not consistent so allow for variation for i in metadata: if 'PROFUNDIDAD ' in i: # assume <5km = 5km evtdepth = get_float(re.sub('[ <>]', '', metadata[i])) if evtdepth is None: raise ValueError("Record %s is missing event depth" % file_str) # Build event eqk = Earthquake( eq_id, eq_name, eq_datetime, -get_float(metadata["COORDENADAS DEL EPICENTRO"].split(" ")[3]), get_float(metadata["COORDENADAS DEL EPICENTRO"].split(" ")[0]), evtdepth, pref_mag, foc_mech) eqk.magnitude_list = mag_list return eqk
def _parse_event_data(self, metadata): """ Read in the distance related metadata and return an instance of the :class: smtk.sm_database.Earthquake """ metadata["MODY"] = metadata["MODY"].zfill(4) metadata["HRMN"] = metadata["HRMN"].zfill(4) # Date and Time year = get_int(metadata["YEAR"]) month = get_int(metadata["MODY"][:2]) day = get_int(metadata["MODY"][2:]) hour = get_int(metadata["HRMN"][:2]) minute = get_int(metadata["HRMN"][2:]) eq_datetime = datetime(year, month, day, hour, minute) # Event ID and Name eq_id = metadata["EQID"] eq_name = metadata["Earthquake Name"] # Focal Mechanism focal_mechanism = self._get_focal_mechanism(eq_id, eq_name, metadata) focal_mechanism.scalar_moment = get_float(metadata["Mo (dyne.cm)"]) *\ 1E-7 # Read magnitude pref_mag = Magnitude(get_float(metadata["Earthquake Magnitude"]), metadata["Magnitude Type"], sigma=get_float(metadata["Uncertainty"])) # Create Earthquake Class eqk = Earthquake(eq_id, eq_name, eq_datetime, get_float(metadata["Hypocenter Longitude (deg)"]), get_float(metadata["Hypocenter Latitude (deg)"]), get_float(metadata["Hypocenter Depth (km)"]), pref_mag, focal_mechanism, metadata["Country"]) hypo_loc = (0.5, 0.7) # Hypocentre Location msr=WC1994() # Warning rake set to 0.0 in scaling relationship area = msr.get_median_area(pref_mag.value,0.0) aspect_ratio = 1.5 # Assumed Fixed width_model = np.sqrt(area / aspect_ratio) length_model = aspect_ratio * width_model ztor_model = eqk.depth - width_model / 2. if ztor_model < 0: ztor_model = 0.0 length = get_float(metadata["Fault Rupture Length (km)"]) if length is None: length = length_model width = get_float(metadata["Fault Rupture Width (km)"]) if width is None: width = width_model ztor = get_float(metadata["Depth to Top Of Fault Rupture Model"]) if ztor is None: ztor=ztor_model # Rupture eqk.rupture = Rupture(eq_id, eq_name, pref_mag, length, width, ztor) # get_float(metadata["Fault Rupture Length (km)"]), # get_float(metadata["Fault Rupture Width (km)"]), # get_float(metadata["Depth to Top Of Fault Rupture Model"])) eqk.rupture.get_area() return eqk