def make_gis_station_location_file(edi_path, save_path=None, fn_basename=None): edi_list = [ os.path.join(edi_path, edi) for edi in os.listdir(edi_path) if edi.find('.edi') > 0 ] if fn_basename is None: fn_basename = 'Station_locations.csv' if save_path is None: sv_fn = os.path.join(edi_path, fn_basename) else: sv_fn = os.path.join(save_path, fn_basename) #--> write csv file sfid = file(sv_fn, 'w') header_line = '{0:},{1:},{2:},{3:}\n'.format('lon', 'lat', 'elevation', 'Object-ID') lines = [] lines.append(header_line) for ii, edi in enumerate(edi_list): mt_obj = mt.MT(fn=edi) line = '{1:.3f},{2:.3f},{3:.3f},{0:}\n'.format(mt_obj.station, mt_obj.lon, mt_obj.lat, mt_obj.elev) lines.append(line) sfid.writelines(lines) sfid.close()
def get_penetration_depth(mt_obj_list, per_index, whichrho='det'): """ compute the penetration depth of mt_obj at the given period_index, and using whichrho option :param per_index: the index of periods 0, 1, ... :param mt_obj_list: list of edi file paths or mt objects :param whichrho: det, zxy, or zyx :return: """ scale_param = np.sqrt(1.0 / (2.0 * np.pi * 4 * np.pi * 10**(-7))) # per_index=0,1,2,.... periods = [] pen_depth = [] stations = [] latlons = [] for mt_obj in mt_obj_list: if isinstance(mt_obj, str) and os.path.isfile(mt_obj): mt_obj = mt.MT(mt_obj) elif not isinstance(mt_obj, mt.MT): raise Exception("Unsupported list of objects %s" % type(mt_obj)) # station id stations.append(mt_obj.station) # latlons latlons.append((mt_obj.lat, mt_obj.lon)) # the attribute Z zeta = mt_obj.Z if per_index >= len(zeta.freq): _logger.debug("Number of frequecies (Max per_index)= %s", len(zeta.freq)) raise Exception( "Index out_of_range Error: period index must be less than number of periods in zeta.freq" ) per = 1.0 / zeta.freq[per_index] periods.append(per) if whichrho == 'zxy': penetration_depth = - scale_param * \ np.sqrt(zeta.resistivity[per_index, 0, 1] * per) elif whichrho == 'zyx': penetration_depth = - scale_param * \ np.sqrt(zeta.resistivity[per_index, 1, 0] * per) elif whichrho == 'det': # the 2X2 complex Z-matrix's determinant abs value # determinant value at the given period index det2 = np.abs(zeta.det[per_index]) penetration_depth = -scale_param * np.sqrt(0.2 * per * det2 * per) else: _logger.critical( "unsupported method to compute penetration depth: %s", whichrho) # sys.exit(100) raise Exception( "unsupported method to compute penetratoin depth: %s" % whichrho) pen_depth.append(penetration_depth) return stations, periods, pen_depth, latlons
def make_gis_station_location_file(edi_path, save_path=None, fn_basename=None): edi_list = [ os.path.join(edi_path, edi) for edi in os.listdir(edi_path) if edi.find(".edi") > 0 ] if fn_basename is None: fn_basename = "Station_locations.csv" if save_path is None: sv_fn = os.path.join(edi_path, fn_basename) else: sv_fn = os.path.join(save_path, fn_basename) # --> write csv file sfid = file(sv_fn, "w") header_line = "{0:},{1:},{2:},{3:}\n".format("lon", "lat", "elevation", "Object-ID") lines = [] lines.append(header_line) for ii, edi in enumerate(edi_list): mt_obj = mt.MT(fn=edi) line = "{1:.3f},{2:.3f},{3:.3f},{0:}\n".format( mt_obj.station, mt_obj.lon, mt_obj.lat, mt_obj.elev ) lines.append(line) sfid.writelines(lines) sfid.close()
def load_edi_files(edi_path): edi_list = [] if edi_path is not None: edi_list = [ mt.MT(os.path.join(edi_path, edi)) for edi in os.listdir(edi_path) if edi.endswith("edi") ] return edi_list
def load_edi_files(edi_path, file_list=None): if file_list is None: file_list = [ff for ff in os.listdir(edi_path) if ff.endswith("edi")] if edi_path is not None: edi_list = [mt.MT(os.path.join(edi_path, edi)) for edi in file_list] return edi_list
def get_mt_file(self): fn_dialog = QtWidgets.QFileDialog() fn = str(fn_dialog.getOpenFileName(caption='Choose MT file', directory=self.plot_widget.dir_path, filter='*.edi;*.xml;*.j')[0]) self.mt_obj = mt.MT() self.mt_obj.read_mt_file(fn) self.tab_widget.mt_obj = self.mt_obj
def make_mt_dict_keys(edi_list): keys = [k.stem for k in edi_list] d = {} d.fromkeys(keys) for edi in edi_list: mt_obj = mt.MT(edi) d[mt_obj.station] = mt_obj return d
def __init__(self, edilist=None, mt_objs=None, outdir=None, ptol=0.05): """ constructor :param edilist: a list of edifiles with full path, for read-only :param outdir: computed result to be stored in outdir :param ptol: period tolerance considered as equal, default 0.05 means 5 percent this param controls what freqs/periods are grouped together: 10pct may result more double counting of freq/period data than 5pct. eg: E:/Data/MT_Datasets/WenPingJiang_EDI 18528 rows vs 14654 rows """ #self._logger = MtPyLog.get_mtpy_logger(self.__class__.__name__) # will be EdiCollection self._logger = MtPyLog.get_mtpy_logger( __name__) # __name__ will be path.to.module OR __main__ self._logger.setLevel(INFO) if edilist is not None: self.edifiles = edilist self._logger.info("number of edi files in this collection: %s", len(self.edifiles)) elif mt_objs is not None: self.edifiles = [mt_obj.fn for mt_obj in mt_objs] assert len(self.edifiles) > 0 self.num_of_edifiles = len(self.edifiles) # number of stations print("number of stations/edifiles = %s" % self.num_of_edifiles) self.ptol = ptol if edilist is not None: # if edilist is provided, always create MT objects from the list self._logger.debug("constructing MT objects from edi files") self.mt_obj_list = [mt.MT(edi) for edi in self.edifiles] elif mt_objs is not None: # use the supplied mt_objs self.mt_obj_list = list(mt_objs) else: self._logger.error("None Edi file set") # get all frequencies from all edi files self.all_frequencies = None self.mt_periods = None self.all_unique_periods = self._get_all_periods() self.geopdf = self.create_mt_station_gdf() self.bound_box_dict = self.get_bounding_box() # in orginal projection # ensure that outdir is created if not exists. if outdir is None: #raise Exception("Error: OutputDir is not specified!!!") pass elif not os.path.exists(outdir): os.mkdir(outdir) self.outdir = outdir return
def iterate_mt_list(n): dt = [] for edi in n: st = datetime.now() m = mt.MT(edi) et = datetime.now() diff = (et - st).total_seconds() m.logger.info(f"Took {diff}") dt.append(diff) return dt
def rotate_edi_files(self): if not os.path.exists(self.save_dir): os.mkdir(self.save_dir) print 'Made directory {0}'.format(self.save_dir) for edi in self.edi_list: print '='*40 edi_fn = os.path.join(self.cwd, '{0}.edi'.format(edi)) mt_obj = mt.MT(fn=edi_fn) mt_obj.rotation_angle = self.rotation_angle mt_obj.write_edi_file(new_fn=os.path.join(self.save_dir, '{0}.edi'.format(edi)))
def default(self): edi_file_list = glob.glob(os.path.join(edi_path, '*.edi')) for edi_file in edi_file_list: plt.clf() mt_obj = mt.MT(edi_file) pt_obj = mt_obj.plot_mt_response(plot_yn='n') pt_obj.plot() plt.pause(.5) save_figure_name = "{}.png".format(default.__name__) save_figure_path = os.path.join(self._temp_dir, save_figure_name) pt_obj.save_plot(save_figure_path) assert (os.path.isfile(save_figure_path))
def __init__(self, edilist=None, mt_objs=None, outdir=None, ptol=0.05): """ constructor """ #self._logger = MtPyLog.get_mtpy_logger(self.__class__.__name__) # will be EdiCollection self._logger = MtPyLog.get_mtpy_logger( __name__) # __name__ will be path.to.module OR __main__ self._logger.setLevel(INFO) if edilist is not None: self.edifiles = edilist self._logger.info("number of edi files in this collection: %s", len(self.edifiles)) elif mt_objs is not None: self.edifiles = [mt_obj.fn for mt_obj in mt_objs] assert len(self.edifiles) > 0 self.num_of_edifiles = len(self.edifiles) # number of stations print("number of stations/edifiles = %s" % self.num_of_edifiles) self.ptol = ptol if edilist is not None: # if edilist is provided, always create MT objects from the list self._logger.debug("constructing MT objects from edi files") self.mt_obj_list = [mt.MT(edi) for edi in self.edifiles] elif mt_objs is not None: # use the supplied mt_objs self.mt_obj_list = list(mt_objs) else: self._logger.error("None Edi file set") # get all frequencies from all edi files self.all_frequencies = None self.mt_periods = None self.all_unique_periods = self._get_all_periods() self.geopdf = self.create_mt_station_gdf() self.bound_box_dict = self.get_bounding_box() # in orginal projection # ensure that outdir is created if not exists. if outdir is None: #raise Exception("Error: OutputDir is not specified!!!") pass elif not os.path.exists(outdir): os.mkdir(outdir) self.outdir = outdir return
def __init__(self, **kwargs): self.birrp_dir = None self.birrp_config_fn = None self.birrp_dict = None self.survey_config_fn = None self.survey_config_dict = None self.station = None self.j_fn = None self.mt_obj = mt.MT() for key in list(kwargs.keys()): setattr(self, key, kwargs[key])
def _get_mt_objs_from_list(self, input_list): """ get mt_objects from a list of files or mt_objects """ if type(input_list) not in [list, np.ndarray]: raise ValueError('Input list needs to be type list, not {0}'.format(type(input_list))) if type(input_list[0]) is mt.MT: return input_list if type(input_list[0]) is str: if input_list[0].endswith('.edi'): return [mt.MT(fn) for fn in input_list] else: raise ModEMError('file {0} not supported yet'.format(input_list[0][-4:]))
def plot_edi_file(edifile, rholist=['zxy', 'zyx', 'det'], savefile=None): """ Plot the input edi_file Args: edi_file: path2edifile rholist: a list of the rho to be used. savefile: path2savefig, not save if None Returns: """ import mtpy.core.mt as mt mt_obj = mt.MT(edifile) image = Depth1D(mt_obj, rholist) image.plot() if savefile: image.export_image(savefile) image.show()
def add_file(self, file_name, group_id=None): """ :param file_name: :param group_id: :type file_name: str :type group_id: str :return: """ file_ref = mt_obj = None if isinstance(file_name, str): if os.path.isfile(file_name): if file_name in self._file_dict and self._file_dict[ file_name] is not None: self._logger.warning("File %s already loaded." % file_name) file_ref = file_name mt_obj = self.get_MT_obj(file_name) else: file_ref = file_name self._logger.info("loading %s" % file_name) mt_obj = mt.MT(file_name) elif isinstance(file_name, mt.MT): mt_obj = file_name file_ref = mt_obj.fn else: raise FileHandlingException("Unsupported input type %s" % type(file_name)) # add file in to container self._logger.info("referencing %s to %s" % (file_ref, mt_obj.station)) if file_ref not in self._file_dict: self._file_dict[file_ref] = mt_obj if mt_obj.station in self._station_dict: raise FileHandlingException( "Station %s already loaded from %s, you could try to unload this first" % (mt_obj.station, self.station2ref(mt_obj.station))) else: self._station_dict[mt_obj.station] = (file_ref) self._file_to_groups[file_ref] = set() # add file to group return self.add_to_group(group_id, file_ref)
def get_freq(self): """ get a list of frequencies, if not all stations have the same frequencies get a common group to interpolate on to. """ if self.edi_list is None: self.get_edi_list() self.mt_obj_list = [] freq_list = [] nf_list = np.zeros(self.ns) for ii, edi in enumerate(self.edi_list): mt_obj = mt.MT(edi) self.mt_obj_list.append(mt_obj) freq_list.extend(list(mt_obj.Z.freq)) nf_list[ii] = mt_obj.Z.freq.size frequencies = np.array(sorted(list(set(freq_list)), reverse=True)) if nf_list.mean() != frequencies.size: interp_frequencies = np.logspace( np.log10(frequencies.min()), np.log10(frequencies.max()), num=nf_list.mean(), ) print "interpolating data" for mt_obj in self.mt_obj_list: new_z, new_t = mt_obj.interpolate(interp_frequencies) mt_obj.Z = new_z mt_obj.Tipper = new_t self.freq = interp_frequencies else: self.freq = frequencies self.num_freq = self.freq.size
def get_resistivity_from_edi_file(edifile, rholist=['det']): """Compute the resistivity values of an edi file :param edifile: input edifile :param rholist: flag the method to compute penetration depth: det zxy zyx :return: a tuple:(station_lat, statoin_lon, periods_list, pendepth_list) """ _logger.debug("processing the edi file %s", edifile) mt_obj = mt.MT(edifile) zeta = mt_obj.Z # the attribute Z represent the impedance tensor 2X2 matrix freqs = zeta.freq # frequencies scale_param = np.sqrt(1.0 / (2.0 * np.pi * 4 * np.pi * 10**(-7))) _logger.debug("the scale parameter should be 355.88127 =?= %s", scale_param) # The periods array periods = 1.0 / freqs if 'zxy' in rholist: # One of the 4-components: XY penetration_depth = scale_param * \ np.sqrt(zeta.resistivity[:, 0, 1] * periods) if 'zyx' in rholist: penetration_depth = scale_param * \ np.sqrt(zeta.resistivity[:, 1, 0] * periods) if 'det' in rholist: # determinant is |Zeta|**2 det2 = np.abs(zeta.det[0]) penetration_depth = scale_param * \ np.sqrt(0.2 * periods * det2 * periods) latlong_d = (mt_obj.lat, mt_obj.lon, periods, penetration_depth) return latlong_d
def plot_edi_file(edi_file): """ Plot the input edi_file Args: edi_file: path2edifile Returns: """ # plt.style.use('dark_background') plt.style.use('seaborn-deep') plt.style.use('classic') _logger.info("Plotting the edi file %s", edi_file) mt_obj = mt.MT(edi_file) pt_obj = mt_obj.plot_mt_response(plot_yn='n') pt_obj.plot() # pt_obj = mt_obj.plot_mt_response(plot_yn='n',plot_num=2, res_limits=(1, 10000), phase_limits=(0, 90)) # pt_obj.plot() return
if not os.path.exists(save_path): os.mkdir(save_path) edi_list_fn = os.path.join(save_path, 'msh_shz_edi_files_big.pkl') if os.path.exists(edi_list_fn): inv_edi_list = pickle.load(open(edi_list_fn, 'r')) else: s_edi_list = [ os.path.join(edi_path, ss) for ss in os.listdir(edi_path) if ss.endswith('.edi') ] inv_edi_list = [] for edi in s_edi_list: mt_obj = mt.MT(edi) if mt_obj.lon >= inv_box[0].min() and mt_obj.lon <= inv_box[0].max(): if mt_obj.lat >= inv_box[1].min() and mt_obj.lat <= inv_box[1].max( ): inv_edi_list.append(edi) pickle.dump(inv_edi_list, open(edi_list_fn, 'w')) #============================================================================== # Make the data file #============================================================================== inv_period_list = np.logspace(-np.log10(300), np.log10(1024), num=23) data_obj = modem.Data(edi_list=inv_edi_list, period_list=inv_period_list) data_obj.error_type_z = 'eigen_floor' data_obj.error_type_tipper = 'absolute_floor' data_obj.error_value_z = 3.0
("rel_north", np.float), ("east", np.float), ("north", np.float), ("zone", "|S4"), ("phimin", (np.float, (nf))), ("phimax", (np.float, (nf))), ("azimuth", (np.float, (nf))), ("skew", (np.float, (nf))), ], ) # ('z', (np.complex, (nf, 2, 2))), # ('z_err', (np.complex, (nf, 2, 2))), # ('tip', (np.complex, (nf, 1, 2))), # ('tip_err', (np.complex, (nf, 1, 2)))] for ii, base_edi in enumerate(edi_base_list): mt_obj = mt.MT(base_edi) base_arr[ii]["station"] = mt_obj.station base_arr[ii]["lat"] = mt_obj.lat base_arr[ii]["lon"] = mt_obj.lon base_arr[ii]["elev"] = mt_obj.elev base_arr[ii]["north"] = mt_obj.north base_arr[ii]["east"] = mt_obj.east base_arr[ii]["zone"] = mt_obj.utm_zone base_arr[ii]["phimin"][:] = sps.medfilt(mt_obj.pt.phimin[0], kernel_size=ks) base_arr[ii]["phimax"][:] = sps.medfilt(mt_obj.pt.phimax[0], kernel_size=ks) base_arr[ii]["azimuth"][:] = sps.medfilt(mt_obj.pt.azimuth[0], kernel_size=ks) base_arr[ii]["skew"][:] = sps.medfilt(mt_obj.pt.beta[0], kernel_size=ks)
Created on Mon Apr 03 17:42:06 2017 @author: jpeacock """ import os import mtpy.core.mt as mt edi_path = r"c:\Users\jpeacock\Documents\SaudiArabia\EDI_Files\Edited_01" edi_list = [ os.path.join(edi_path, ss) for ss in os.listdir(edi_path) if ss.endswith(".edi") ] sv_path = os.path.join(edi_path, "geomag_north") if not os.path.exists(sv_path): os.mkdir(sv_path) print "Made directory {0}".format(sv_path) for edi in edi_list: mt_obj = mt.MT(fn=edi) if mt_obj.Z.rotation_angle.mean() == -34.0: mt_obj.rotation_angle = 34 elif mt_obj.Z.rotation_angle.mean() == -30: mt_obj.rotation_angle = 30 elif mt_obj.Z.rotation_angle.mean() == 0.0: mt_obj.rotation_angle = -30 mt_obj.rotation_angle = 0.0 mt_obj.write_edi_file(new_fn=os.path.join(sv_path, os.path.basename(edi)))
# os.mkdir(sv_path) # ab_list = [chr(i) for i in range(ord('A'),ord('Z')+1)] # char_dict = dict([(index, alpha) for index, alpha in enumerate(ab_list, 1)]) # ============================================================================= # Rename EDI files and rename station # ============================================================================= edi_list = [ os.path.join(edi_path, edi) for edi in os.listdir(edi_path) if edi.endswith(".edi") ] lines = ["station,lat,lon,nm_elev"] for edi_fn in edi_list: mt_obj = mt.MT(edi_fn) nm_elev = archive.get_nm_elev(mt_obj.lat, mt_obj.lon) lines.append("{0},{1:.5f},{2:.5f},{3:.2f}".format(mt_obj.station, mt_obj.lat, mt_obj.lon, nm_elev)) with open(os.path.join(edi_path, "imush_station_locations_nm.csv"), "w") as fid: fid.write("\n".join(lines)) # print(mt_obj.station) # new_station = '{0}{1:03}'.format(char_dict[int(mt_obj.station[0:2])], # int(mt_obj.station[2:])) # mt_obj.station = new_station # print(mt_obj.station) # mt_obj.write_mt_file(save_dir=sv_path)
def estimate_static_spatial_median(edi_fn, radius=1000., num_freq=20, freq_skip=4, shift_tol=.15): """ Remove static shift from a station using a spatial median filter. This will look at all the edi files in the same directory as edi_fn and find those station within the given radius (meters). Then it will find the medain static shift for the x and y modes and remove it, given that it is larger than the shift tolerance away from 1. A new edi file will be written in a new folder called SS. Arguments ----------------- **edi_fn** : string full path to edi file to have static shift removed **radius** : float radius to look for nearby stations, in meters. *default* is 1000 m **num_freq** : int number of frequencies calculate the median static shift. This is assuming the first frequency is the highest frequency. Cause usually highest frequencies are sampling a 1D earth. *default* is 20 **freq_skip** : int number of frequencies to skip from the highest frequency. Sometimes the highest frequencies are not reliable due to noise or low signal in the AMT deadband. This allows you to skip those frequencies. *default* is 4 **shift_tol** : float Tolerance on the median static shift correction. If the data is noisy the correction factor can be biased away from 1. Therefore the shift_tol is used to stop that bias. If 1-tol < correction < 1+tol then the correction factor is set to 1. *default* is 0.15 Returns ---------------- **shift_corrections** : (float, float) static shift corrections for x and y modes """ # convert meters to decimal degrees so we don't have to deal with zone # changes meter_to_deg_factor = 8.994423457456377e-06 dm_deg = radius * meter_to_deg_factor # make a list of edi files in the directory edi_path = os.path.dirname(edi_fn) edi_list = [os.path.abspath(os.path.join(edi_path, edi)) for edi in os.listdir(edi_path) if edi.endswith('.edi')] edi_list.remove(os.path.abspath(edi_fn)) # read the edi file mt_obj = mt.MT(edi_fn) mt_obj.Z.compute_resistivity_phase() interp_freq = mt_obj.Z.freq[freq_skip:num_freq + freq_skip] # Find stations near by and store them in a list mt_obj_list = [] for kk, kk_edi in enumerate(edi_list): mt_obj_2 = mt.MT(kk_edi) delta_d = np.sqrt((mt_obj.lat - mt_obj_2.lat) ** 2 + (mt_obj.lon - mt_obj_2.lon) ** 2) if delta_d <= dm_deg: mt_obj_2.delta_d = float(delta_d) / meter_to_deg_factor mt_obj_list.append(mt_obj_2) if len(mt_obj_list) == 0: print('No stations found within given radius {0:.2f} m'.format(radius)) return 1.0, 1.0 # extract the resistivity values from the near by stations res_array = np.zeros((len(mt_obj_list), num_freq, 2, 2)) print('These stations are within the given {0} m radius:'.format(radius)) for kk, mt_obj_kk in enumerate(mt_obj_list): print('\t{0} --> {1:.1f} m'.format(mt_obj_kk.station, mt_obj_kk.delta_d)) interp_idx = np.where((interp_freq >= mt_obj_kk.Z.freq.min()) & (interp_freq <= mt_obj_kk.Z.freq.max())) interp_freq_kk = interp_freq[interp_idx] Z_interp, Tip_interp = mt_obj_kk.interpolate(interp_freq_kk) Z_interp.compute_resistivity_phase() res_array[ kk, interp_idx, :, :] = Z_interp.resistivity[ 0:len(interp_freq_kk), :, :] # compute the static shift of x-components static_shift_x = mt_obj.Z.resistivity[freq_skip:num_freq + freq_skip, 0, 1] / \ np.median(res_array[:, :, 0, 1], axis=0) static_shift_x = np.median(static_shift_x) # check to see if the estimated static shift is within given tolerance if 1 - shift_tol < static_shift_x and static_shift_x < 1 + shift_tol: static_shift_x = 1.0 # compute the static shift of y-components static_shift_y = mt_obj.Z.resistivity[freq_skip:num_freq + freq_skip, 1, 0] / \ np.median(res_array[:, :, 1, 0], axis=0) static_shift_y = np.median(static_shift_y) # check to see if the estimated static shift is within given tolerance if 1 - shift_tol < static_shift_y and static_shift_y < 1 + shift_tol: static_shift_y = 1.0 return static_shift_x, static_shift_y
def remove_static_shift_spatial_filter(edi_fn, radius=1000, num_freq=20, freq_skip=4, shift_tol=.15, plot=False): """ Remove static shift from a station using a spatial median filter. This will look at all the edi files in the same directory as edi_fn and find those station within the given radius (meters). Then it will find the medain static shift for the x and y modes and remove it, given that it is larger than the shift tolerance away from 1. A new edi file will be written in a new folder called SS. Arguments ----------------- **edi_fn** : string full path to edi file to have static shift removed **radius** : float radius to look for nearby stations, in meters. *default* is 1000 m **num_freq** : int number of frequencies calculate the median static shift. This is assuming the first frequency is the highest frequency. Cause usually highest frequencies are sampling a 1D earth. *default* is 20 **freq_skip** : int number of frequencies to skip from the highest frequency. Sometimes the highest frequencies are not reliable due to noise or low signal in the AMT deadband. This allows you to skip those frequencies. *default* is 4 **shift_tol** : float Tolerance on the median static shift correction. If the data is noisy the correction factor can be biased away from 1. Therefore the shift_tol is used to stop that bias. If 1-tol < correction < 1+tol then the correction factor is set to 1. *default* is 0.15 **plot** : [ True | False ] Boolean to plot the corrected response against the non-corrected response. *default* is False Returns ---------------- **new_edi_fn_ss** : string new path to the edi file with static shift removed **shift_corrections** : (float, float) static shift corrections for x and y modes **plot_obj** : mtplot.plot_multiple_mt_responses object If plot is True a plot_obj is returned If plot is False None is returned """ ss_x, ss_y = estimate_static_spatial_median(edi_fn, radius=radius, num_freq=num_freq, freq_skip=freq_skip, shift_tol=.15) mt_obj = mt.MT(edi_fn) s, z_ss = mt_obj.Z.no_ss(reduce_res_factor_x=ss_x, reduce_res_factor_y=ss_y) edi_path = os.path.dirname(edi_fn) mt_obj.Z.z = z_ss new_edi_fn = os.path.join( edi_path, 'SS', '{0}_ss.edi'.format( mt_obj.station)) if not os.path.exists(os.path.dirname(new_edi_fn)): os.mkdir(os.path.dirname(new_edi_fn)) mt_obj.write_edi_file(new_fn=new_edi_fn) if plot == True: rpm = mtplot.plot_multiple_mt_responses(fn_list=[edi_fn, new_edi_fn], plot_style='compare') return new_edi_fn, s[0], rpm else: return new_edi_fn, s[0], None
def plot_bar3d_depth(edifiles, per_index, whichrho='det'): """ plot 3D bar of penetration depths For a given freq/period index of a set of edifiles/dir, the station,periods, pendepth,(lat, lon) are extracted the geo-bounding box calculated, and the mapping from stations to grids is constructed and plotted. :param whichrho: z component either 'det', 'zxy' or 'zyx' :param edifiles: an edi_dir or list of edi_files :param per_index: period index number 0,1,2 :return: """ if os.path.isdir(edifiles): edi_dir = edifiles # "E:/Githubz/mtpy2/tests/data/edifiles/" edifiles = glob.glob(os.path.join(edi_dir, '*.edi')) _logger.debug(edifiles) else: # Assume edifiles is [a list of files] pass scale_param = np.sqrt(1.0 / (2.0 * np.pi * 4 * np.pi * 10**(-7))) _logger.debug("The scaling parameter=%.6f" % scale_param) # per_index=0,1,2,.... periods = [] pen_depth = [] stations = [] latlons = [] for afile in edifiles: mt_obj = mt.MT(afile) latlons.append((mt_obj.lat, mt_obj.lon)) # the attribute Z zeta = mt_obj.Z if per_index >= len(zeta.freq): raise Exception( "Error: input period index must be less than the number of freqs in zeta.freq=%s", len(zeta.freq)) per = 1.0 / zeta.freq[per_index] periods.append(per) if whichrho == 'det': # the 2X2 complex Z-matrix's determinant abs value # determinant value at the given period index det2 = np.abs(zeta.det[0][per_index]) penetration_depth = -scale_param * np.sqrt(0.2 * per * det2 * per) elif whichrho == 'zxy': penetration_depth = - scale_param * \ np.sqrt(zeta.resistivity[per_index, 0, 1] * per) elif whichrho == 'zyx': penetration_depth = - scale_param * \ np.sqrt(zeta.resistivity[per_index, 1, 0] * per) pen_depth.append(penetration_depth) stations.append(mt_obj.station) # return (stations, periods, pen_depth, latlons) lats = [tup[0] for tup in latlons] lons = [tup[1] for tup in latlons] minlat = min(lats) maxlat = max(lats) minlon = min(lons) maxlon = max(lons) pixelsize = 0.002 # degree 0.001 = 100meters shift = 3 ref_lat = minlat - shift * pixelsize ref_lon = minlon - shift * pixelsize xgrids = maxlon - minlon ygrids = maxlat - minlat # nx = xgrids / pixelsize # ny = ygrids / pixelsize # import matplotlib.pyplot as plt # import numpy as np fig = plt.figure() ax1 = fig.add_subplot(111, projection='3d') xpos = [] # a seq (1,2,3,4,5,6,7,8,9,10) ypos = [] # a seq [2,3,4,5,1,6,2,1,7,2] dz = [] for iter, pair in enumerate(latlons): xpos.append( get_index(pair[0], pair[1], ref_lat, ref_lon, pixelsize)[0]) ypos.append( get_index(pair[0], pair[1], ref_lat, ref_lon, pixelsize)[1]) dz.append(np.abs(pen_depth[iter])) # dz.append(-np.abs(pen_depth[iter])) num_elements = len(xpos) zpos = np.zeros(num_elements) # zpos = [0,0,0,0,0,0,0,0,0,0] dx = np.ones(num_elements) dy = np.ones(num_elements) # dz = [1,2,3,4,5,6,7,8,9,10] # print(xpos) # print(ypos) # print(zpos) # # print(dx) # print(dy) # print(dz) ax1.bar3d(xpos, ypos, zpos, dx, dy, dz, color='r') # ax1 plt.title( 'Penetration Depth (Meter) Across Stations for period= %6.3f Seconds' % periods[0], fontsize=16) plt.xlabel('Longitude(deg-grid)', fontsize=16) plt.ylabel('Latitude(deg-grid)', fontsize=16) # plt.zlabel('Penetration Depth (m)') # bar_width = 0.4 # plt.xticks(index + bar_width / 2, stations, rotation='horizontal', fontsize=16) # plt.legend() # # # plt.tight_layout() # plt.gca().xaxis.tick_top() # plt.show() plt.show()
def barplot_multi_station_penentration_depth(edifiles_dir, per_index=0, zcomponent='det'): """ A simple bar chart plot of the penetration depth across multiple edi files (stations), at the given (frequency) per_index. No profile-projection is done in this funciton. :param edifiles_dir: a list of edi files, or a dir of edi :param per_index: an integer smaller than the number of MT frequencies in the edi files. :return: """ if os.path.isdir(edifiles_dir): edi_dir = edifiles_dir # "E:/Githubz/mtpy2/tests/data/edifiles/" edifiles_dir = glob.glob(os.path.join(edi_dir, '*.edi')) _logger.debug(edifiles_dir) else: # Assume edifiles_dir is [a list of edi files] pass scale_param = np.sqrt(1.0 / (2.0 * np.pi * 4 * np.pi * 10**(-7))) # per_index=0,1,2,.... periods = [] depths = [] stations = [] mt_obj_list = [mt.MT(afile) for afile in edifiles_dir] (stations, periods, depths, _) = get_penetration_depth_by_index(mt_obj_list, int(per_index), whichrho=zcomponent) # the attribute Z # zeta = mt_obj.Z # # if per_index >= len(zeta.freq): # raise Exception("Error: input period index must be less than number of freqs in zeta.freq=%s",len(zeta.freq)) # # per = 1.0 / zeta.freq[per_index] # periods.append(per) # penetration_depth = -scale_param * np.sqrt(zeta.resistivity[per_index, 0, 1] * per) # # depths.append(penetration_depth) # stations.append(mt_obj.station) #plt.plot(app_resis, color='b', marker='o') index = np.arange(len(depths)) plt.bar(index, depths, color='#000000') # plt.xaxis.tick_top() # plt.set_xlabel('X LABEL') # plt.xaxis.set_label_position('top') plt.xlabel( 'Penetration Depth Across Stations, for MT period= %6.5f Seconds' % periods[0], fontsize=16) plt.ylabel('Penetration Depth (m)', fontsize=16) # plt.title('Penetration Depth profile for T=??') bar_width = 0.4 plt.xticks(index + bar_width / 2, stations, rotation='horizontal', fontsize=14) plt.legend() # plt.tight_layout() plt.gca().xaxis.tick_top() plt.show() # Check that the periods are the same value for all stations return (stations, depths, periods)
# -*- coding: utf-8 -*- """ plots edi files as resistivity and phase vs period CreatedOn: Wed Sep 18 15:35:39 2013 CreatedBy: Alison Kirkby LastUpdated: 2017-01-24 UpdatedBy: [email protected] LastUpdated: 2018-03-22 AK updated to use as script rather than command line """ from mtpy.core import mt edi_file = r'C:\mtpywin\mtpy\examples\data\edi_files_2\Synth06.edi' mt_obj = mt.MT(edi_file) pt_obj = mt_obj.plot_mt_response(plot_yn='n') pt_obj.plot()
def remove_static_shift_spatial_filter(edi_fn, radius=1000, num_freq=20, freq_skip=4, shift_tol=.15, plot=False): """ Remove static shift from a station using a spatial median filter. This will look at all the edi files in the same directory as edi_fn and find those station within the given radius (meters). Then it will find the medain static shift for the x and y modes and remove it, given that it is larger than the shift tolerance away from 1. A new edi file will be written in a new folder called SS. Arguments ----------------- **edi_fn** : string full path to edi file to have static shift removed **radius** : float radius to look for nearby stations, in meters. *default* is 1000 m **num_freq** : int number of frequencies calculate the median static shift. This is assuming the first frequency is the highest frequency. Cause usually highest frequencies are sampling a 1D earth. *default* is 20 **freq_skip** : int number of frequencies to skip from the highest frequency. Sometimes the highest frequencies are not reliable due to noise or low signal in the AMT deadband. This allows you to skip those frequencies. *default* is 4 **shift_tol** : float Tolerance on the median static shift correction. If the data is noisy the correction factor can be biased away from 1. Therefore the shift_tol is used to stop that bias. If 1-tol < correction < 1+tol then the correction factor is set to 1. *default* is 0.15 **plot** : [ True | False ] Boolean to plot the corrected response against the non-corrected response. *default* is False Returns ---------------- **new_edi_fn_ss** : string new path to the edi file with static shift removed **shift_corrections** : (float, float) static shift corrections for x and y modes **plot_obj** : mtplot.plot_multiple_mt_responses object If plot is True a plot_obj is returned If plot is False None is returned """ # convert meters to decimal degrees so we don't have to deal with zone # changes meter_to_deg_factor = 8.994423457456377e-06 dm_deg = radius * meter_to_deg_factor # make a list of edi files in the directory edi_path = os.path.dirname(edi_fn) edi_list = [ os.path.join(edi_path, edi) for edi in os.listdir(edi_path) if edi.find('.edi') > 0 ] edi_list.remove(edi_fn) # read the edi file mt_obj = mt.MT(edi_fn) mt_obj.Z._compute_res_phase() # Find stations near by and store them in a list mt_obj_list = [] for kk, kk_edi in enumerate(edi_list): mt_obj_2 = mt.MT(kk_edi) delta_d = np.sqrt((mt_obj.lat-mt_obj_2.lat)**2+\ (mt_obj.lon-mt_obj_2.lon)**2) if delta_d <= dm_deg: mt_obj_2.delta_d = float(delta_d) / meter_to_deg_factor mt_obj_list.append(mt_obj_2) # extract the resistivity values from the near by stations res_array = np.zeros((len(mt_obj_list), num_freq, 2, 2)) print 'These stations are within the given {0} m radius:'.format(radius) for kk, mt_obj_kk in enumerate(mt_obj_list): print '\t{0} --> {1:.1f} m'.format(mt_obj_kk.station, mt_obj_kk.delta_d) interp_freq = mt_obj.Z.freq[freq_skip:num_freq + freq_skip] Z_interp, Tip_interp = mt_obj_kk.interpolate(interp_freq) Z_interp._compute_res_phase() res_array[kk, :, :, :] = Z_interp.resistivity[0:num_freq, :, :] #compute the static shift of x-components static_shift_x = mt_obj.Z.resistivity[freq_skip:num_freq+freq_skip, 0, 1]/\ np.median(res_array[:, :, 0, 1], axis=0) static_shift_x = np.median(static_shift_x) ##check to see if the estimated static shift is within given tolerance if 1 - shift_tol < static_shift_x and static_shift_x < 1 + shift_tol: static_shift_x = 1.0 #compute the static shift of y-components static_shift_y = mt_obj.Z.resistivity[freq_skip:num_freq+freq_skip, 1, 0]/\ np.median(res_array[:, :, 1, 0], axis=0) static_shift_y = np.median(static_shift_y) ##check to see if the estimated static shift is within given tolerance if 1 - shift_tol < static_shift_y and static_shift_y < 1 + shift_tol: static_shift_y = 1.0 print 'x static shift is {0:.3f}'.format(static_shift_x) print 'y static shift is {0:.3f}'.format(static_shift_y) s, z_ss = mt_obj.Z.no_ss(reduce_res_factor_x=static_shift_x, reduce_res_factor_y=static_shift_y) mt_obj.Z.z = z_ss new_edi_fn = os.path.join(edi_path, 'SS', '{0}_ss.edi'.format(mt_obj.station)) mt_obj.write_edi_file(new_fn=new_edi_fn) if plot == True: rpm = mtplot.plot_multiple_mt_responses(fn_list=[edi_fn, new_edi_fn], plot_style='compare') return new_edi_fn, s[0], rpm else: return new_edi_fn, s[0], None
def get_penetration_depth_generic(edi_file_list, period_sec, whichrho='det', ptol=0.1): """ This is a more generic and useful function to compute the penetration depths of a list of edi files at given period_sec (seconds). No assumption is made about the edi files period list. A tolerance of 10% is used to identify the relevant edi files which contain the period of interest. :param ptol: freq error/tolerance, need to be consistent with phase_tensor_map.py, default is 0.1 :param edi_file_list: edi file list of mt object list :param period_sec: the float number value of the period in second: 0.1, ...20.0 :param whichrho: :return: tuple of (stations, periods, penetrationdepth, lat-lons-pairs) """ scale_param = np.sqrt(1.0 / (2.0 * np.pi * 4 * np.pi * 10**(-7))) _logger.debug("The scaling parameter=%.6f" % scale_param) # per_index=0,1,2,.... periods = [] pendep = [] stations = [] latlons = [] all_freqs = [] # gather all freqs for afile in edi_file_list: if isinstance(afile, str) and os.path.isfile(afile): mt_obj = mt.MT(afile) elif isinstance(afile, mt.MT): mt_obj = afile else: raise Exception("Unsupported list of objects %s" % type(afile)) all_freqs.extend(list(mt_obj.Z.freq)) # all stations positions included # stations.append((mt_obj.lat, mt_obj.lon)) stations.append(mt_obj.station) p_index = [ ff for ff, f2 in enumerate(1.0 / mt_obj.Z.freq) if (f2 > period_sec * (1 - ptol)) and (f2 < period_sec * (1 + ptol)) ] _logger.debug("Period index found: %s", p_index) if len(p_index) >= 1: # this edi can be included per_index = p_index[0] # stations.append(mt_obj.station) latlons.append((mt_obj.lat, mt_obj.lon)) # the attribute Z zeta = mt_obj.Z if per_index >= len(zeta.freq): _logger.debug("Number of frequecies (Max per_index)= %s", len(zeta.freq)) raise Exception( "Index out_of_range Error: period index must be less than number of periods in zeta.freq" ) per = 1.0 / zeta.freq[per_index] periods.append(per) if whichrho == 'det': # the 2X2 complex Z-matrix's determinant abs value # determinant value at the given period index det2 = np.abs(zeta.det[per_index]) penetration_depth = -scale_param * np.sqrt( 0.2 * per * det2 * per) elif whichrho == 'zxy': penetration_depth = -scale_param * np.sqrt( zeta.resistivity[per_index, 0, 1] * per) elif whichrho == 'zyx': penetration_depth = -scale_param * np.sqrt( zeta.resistivity[per_index, 1, 0] * per) else: _logger.critical( "un-supported method to compute penetration depth: %s", whichrho) sys.exit(100) pendep.append(penetration_depth) else: _logger.warn( '%s was not used in the 3d profile, because it has no required period.', afile) pass # sort all frequencies so that they are in descending order, # use set to remove repeats and make an array. all_periods = 1.0 / np.array(sorted(list(set(all_freqs)), reverse=True)) print("Here is a list of ALL the periods in your edi files:\t ", all_periods) return stations, periods, pendep, latlons