def eccentricity(z_array = None, z_object = None, pt_array= None, pt_object = None): if z_array is not None: pt_obj = MTpt.PhaseTensor(z_array = z_array) elif z_object is not None: if not isinstance(z_object, MTz.Z): raise MTex.MTpyError_Z('Input argument is not an instance of the Z class') pt_obj = MTpt.PhaseTensor(z_object = z_object) elif pt_array is not None: pt_obj = MTpt.PhaseTensor(pt_array= pt_array) elif pt_object is not None: if not isinstance(pt_object, MTpt.PhaseTensor): raise MTex.MTpyError_PT('Input argument is not an instance of the PhaseTensor class') pt_obj = pt_object lo_ecc = [] lo_eccerr = [] if not isinstance(pt_obj, MTpt.PhaseTensor): raise MTex.MTpyError_PT('Input argument is not an instance of the PhaseTensor class') for idx_f in range(len(pt_obj.pt)): lo_ecc.append( pt_obj._pi1()[0][idx_f] / pt_obj._pi2()[0][idx_f] ) ecc_err = None if (pt_obj._pi1()[1] is not None) and (pt_obj._pi2()[1] is not None): ecc_err = np.sqrt( (pt_obj._pi1()[1][idx_f] /pt_obj._pi1()[0][idx_f] )**2 + (pt_obj._pi2()[1][idx_f] /pt_obj._pi2()[0][idx_f])**2) lo_eccerr.append(ecc_err) return np.array(lo_ecc), np.array(lo_eccerr)
def strike_angle(z_array=None, z_object=None, pt_array=None, pt_object=None, beta_threshold=5, eccentricity_threshold=0.1): if z_array is not None: pt_obj = MTpt.PhaseTensor(z_array=z_array) elif z_object is not None: if not isinstance(z_object, MTz.Z): raise MTex.MTpyError_Z( 'Input argument is not an instance of the Z class') pt_obj = MTpt.PhaseTensor(z_object=z_object) elif pt_array is not None: pt_obj = MTpt.PhaseTensor(pt_array=pt_array) elif pt_object is not None: if not isinstance(pt_object, MTpt.PhaseTensor): raise MTex.MTpyError_PT( 'Input argument is not an instance of the PhaseTensor class') pt_obj = pt_object lo_dims = dimensionality(pt_object=pt_obj, beta_threshold=beta_threshold, eccentricity_threshold=eccentricity_threshold) lo_strikes = [] for idx, dim in enumerate(lo_dims): if dim == 1: lo_strikes.append((np.nan, np.nan)) continue a = pt_obj.alpha[0][idx] b = pt_obj.beta[0][idx] strike1 = (a - b) % 90 if 0 < strike1 < 45: strike2 = strike1 + 90 else: strike2 = strike1 - 90 s1 = min(strike1, strike2) s2 = max(strike1, strike2) lo_strikes.append((s1, s2)) return np.array(lo_strikes)
def _read_edi_file(self): """ read in edi file and set attributes accordingly """ self.edi_object = MTedi.Edi(self.fn, datatype=self._data_type) self.lat = self.edi_object.lat self.lon = self.edi_object.lon self.elev = self.edi_object.elev self.Z = self.edi_object.Z self.Tipper = self.edi_object.Tipper self.station = self.edi_object.station #--> get utm coordinates from lat and lon self._get_utm() #--> make sure things are ordered from high frequency to low self._check_freq_order() #--> compute phase tensor self.pt = MTpt.PhaseTensor(z_object=self.Z, freq=self.Z.freq) #--> compute invariants self.zinv = MTinv.Zinvariants(z_object=self.Z)
def dimensionality(z_array=None, z_object=None, pt_array=None, pt_object=None, beta_threshold=5, eccentricity_threshold=0.1): """ beta_threshold: angle in degrees - if beta is smaller than this, it's 2d eccentricity_threshold: fraction of eccentricity (0: circle - 1: line) - if eccentricity (ellipticity) is small than this, it's a 1D geometry. """ lo_dimensionality = [] if z_array is not None: pt_obj = MTpt.PhaseTensor(z_array=z_array) elif z_object is not None: if not isinstance(z_object, MTz.Z): raise MTex.MTpyError_Z( 'Input argument is not an instance of the Z class') pt_obj = MTpt.PhaseTensor(z_object=z_object) elif pt_array is not None: pt_obj = MTpt.PhaseTensor(pt_array=pt_array) elif pt_object is not None: if not isinstance(pt_object, MTpt.PhaseTensor): raise MTex.MTpyError_PT( 'Input argument is not an instance of the PhaseTensor class') pt_obj = pt_object #use criteria from Bibby et al. 2005 for determining the dimensionality for each frequency of the pt/z array: for idx_f in range(len(pt_obj.pt)): #1. determine beta value... beta = pt_obj.beta[0][idx_f] #compare with threshold for 3D if beta > beta_threshold: lo_dimensionality.append(3) else: #2.check for eccentricity: ecc = pt_obj._pi1()[0][idx_f] / pt_obj._pi2()[0][idx_f] if ecc > eccentricity_threshold: lo_dimensionality.append(2) else: lo_dimensionality.append(1) return np.array(lo_dimensionality)
def _set_Z(self, z_object): """ set z_object recalculate phase tensor and invariants, which shouldn't change except for strike angle """ self._Z = z_object self._Z._compute_res_phase() #--> compute phase tensor self.pt = MTpt.PhaseTensor(z_object=self._Z, freq=self._Z.freq) #--> compute invariants self.zinv = MTinv.Zinvariants(z_object=self._Z)
# z1det=.2*period*abs(np.array([np.sqrt(np.linalg.det(zz)) for zz in z1]))**2 # z2det=.2*period*abs(np.array([np.sqrt(np.linalg.det(zz)) for zz in z2]))**2 z1det = np.array([np.sqrt(abs(np.linalg.det(zz))) for zz in z1]) z2det = np.array([np.sqrt(abs(np.linalg.det(zz))) for zz in z2]) zdet = (abs(z1det - z2det) / z1det) * 100 replst.append((abs(z1det - z2det) / z1det) * 100) # dr1,dp1,zd1=implst[0].getResPhaseDet() # dr2,dp2,zd2=implst[1].getResPhaseDet() # # preplst.append((abs(dp1[0]-dp2[0])/dp1[0])*100) # ---Phase tensor determinant--- ptdict1 = mtpt.PhaseTensor(z_object=implst[0].Z) ptdict2 = mtpt.PhaseTensor(z_object=implst[1].Z) ptd1 = np.array([ np.sqrt(np.linalg.det(pt1)) * (180 / np.pi) for pt1 in ptdict1.pt ]) ptd2 = np.array([ np.sqrt(np.linalg.det(pt2)) * (180 / np.pi) for pt2 in ptdict2.pt ]) ptlst.append((abs(ptd1 - ptd2) / ptd1) * 100) ptdet = (abs(ptd1 - ptd2) / ptd1) * 100 for freq, zz, pp in zip(1.0 / period, zdet, ptdet): lines.append("{0:<12}{1:>12.2f}{2:>12.2f}\n".format(freq, zz, pp))
def generate_ptcrossdata_file(edi_object, n_iterations, sigma_scaling, outdir, outfn=None): freqs = edi_object.freq station = edi_object.station #no spaces in file names: if len(station.split()) > 1: station = '_'.join(station.split()) #Define and check validity of output file if outfn is None: fn = '{0}_PTcrossdata'.format(station) outfn = op.join(outdir, fn) outfn = op.realpath(outfn) try: Fout = open(outfn, 'w') except: print '\n\tERROR - Cannot generate output file!\n' raise if n_iterations == 0: Fout.write('# {0} {1:+010.6f} {2:+011.6f}\n'.format( station, edi_object.lat, edi_object.lon)) else: Fout.write( '# {0} {1:+010.6f} {2:+011.6f} \t\t statistical evaluation of {3} realisations\n' .format(station, edi_object.lat, edi_object.lon, abs(int(n_iterations)))) headerstring = '# lat \t\t lon \t\t freq \t\t Pmin sigma \t Pmax sigma \t alpha '\ 'sigma \t beta sigma \t ellipticity \n' Fout.write(headerstring) if n_iterations == 0: pt = MTpt.PhaseTensor(z_object=edi_object.Z, freq=freqs) a = pt.alpha b = pt.beta phimin = pt.phimin[0] phiminerr = pt.phimin[1] phimax = pt.phimax[0] phimaxerr = pt.phimax[1] #e = pt.ellipticity #e = (pmax-pmin)/(pmax+pmin) for i, freq in enumerate(edi_object.freq): try: e = (phimax[i] - phimin[i]) / (phimax[i] + phimin[i]) vals = '{10:.4f}\t{11:.4f}\t{0:.4e}\t{1: 3.2f}\t{2:3.2f}\t{3: 3.2f}\t{4:3.2f}\t{5: 3.2f}\t{6:3.2f}'\ '\t{7: 3.2f}\t{8:3.2f}\t{9:.3f}\n'.format( freq,phimin[i],phiminerr[i],phimax[i], phimaxerr[i],a[0][i]%90,a[1][i]%90, b[0][i],b[1][i],e,edi_object.lat,edi_object.lon) Fout.write(vals) except: raise continue Fout.close() print '\n\t Done - Written data to file: {0}\n'.format(outfn) return # for all values n_iterations !=0 loop over abs(n_iterations) # # loops individual per frequency for idx, f in enumerate(freqs): z = edi_object.Z.z zerr = edi_object.Z.zerr lo_pts = [] lo_ptserr = [] cur_z = z[idx] cur_zerr = zerr[idx] #crude check for 'bad' values in zerr: for i in np.arange(4): a = cur_zerr[i / 2, i % 2] val = cur_z[i / 2, i % 2] try: dummy = float(a) if np.isnan(a) or np.isinf(a): raise except: #correct by nearest neighbour value print f, '\ncorrecting error value', a, '...', rel_errs = [] if idx + 1 != len(freqs): next_z = z[idx + 1][i / 2, i % 2] next_zerr = zerr[idx + 1][i / 2, i % 2] rel_err = next_zerr / abs(next_z) rel_errs.append(rel_err) if idx != 0: last_z = z[idx - 1][i / 2, i % 2] last_zerr = zerr[idx - 1][i / 2, i % 2] rel_err = last_zerr / abs(last_z) rel_errs.append(rel_err) rel_err_final = np.mean(rel_errs) err = rel_err_final * abs(val) cur_zerr[i / 2, i % 2] = err #print err #calculate random numbers: lo_rands = [] for k in np.arange(4): randnums = sigma_scaling * cur_zerr[k / 2, k % 2] * np.random.randn( 2 * abs(int(n_iterations))) lo_rands.append(randnums) #Loop over |n_iterations| random realisations: lo_pmin = [] lo_pmax = [] lo_alphas = [] lo_betas = [] #lo_ellipticities = [] #print 'running {0} iterations for {1} Hz'.format(n_iterations,f) for run in np.arange(abs(int(n_iterations))): tmp_z = np.array( [[ complex( np.real(cur_z[0, 0]) + lo_rands[0][run], np.imag(cur_z[0, 0]) + lo_rands[0][-run - 1]), complex( np.real(cur_z[0, 1]) + lo_rands[1][run], np.imag(cur_z[0, 1]) + lo_rands[1][-run - 1]) ], [ complex( np.real(cur_z[1, 0]) + lo_rands[2][run], np.imag(cur_z[1, 0]) + lo_rands[2][-run - 1]), complex( np.real(cur_z[1, 1]) + lo_rands[3][run], np.imag(cur_z[1, 1]) + lo_rands[3][-run - 1]) ]]) tmp_pt = MTpt.PhaseTensor(z_array=tmp_z.reshape(1, 2, 2), freq=f.reshape(1)) pi1 = tmp_pt._pi1()[0] pi2 = tmp_pt._pi2()[0] lo_pmin.append(pi2 - pi1) lo_pmax.append(pi2 + pi1) alpha = tmp_pt.alpha[0][0] if alpha < 0 and alpha % 90 < 10: lo_alphas.append(alpha % 90 + 90) else: lo_alphas.append(alpha % 90) # if idx%10==0: # print alpha,lo_alphas[-1] lo_betas.append(tmp_pt.beta[0][0]) #in percent: #lo_ellipticities.append(100*tmp_pt.ellipticity[0][0]) lo_alphas = np.array(lo_alphas) a = np.median(lo_alphas) aerr = np.median(np.abs(lo_alphas - a)) #aerr = np.std(lo_alphas) # if idx%10==0: # print '\t',a,aerr # print b = np.mean(lo_betas) berr = np.std(lo_betas) #ipdb.set_trace() #convert to angles: phimin = np.mean([np.degrees(np.arctan(i)) for i in lo_pmin]) phiminerr = np.std([np.degrees(np.arctan(i)) for i in lo_pmin]) phimax = np.mean([np.degrees(np.arctan(i)) for i in lo_pmax]) phimaxerr = np.std([np.degrees(np.arctan(i)) for i in lo_pmax]) #e = np.mean(lo_ellipticities) #eerr = np.std(lo_ellipticities) e = (phimax - phimin) / (phimax + phimin) try: vals = '{10:.4f}\t{11:.4f}\t{0:.4e}\t{1: 3.2f}\t{2:3.2f}\t{3: 3.2f}\t{4:3.2f}\t{5: 3.2f}\t{6:3.2f}'\ '\t{7: 3.2f}\t{8:3.2f}\t{9:.3f}\n'.format( f,phimin,phiminerr,phimax, phimaxerr,a,aerr, b,berr,e,edi_object.lat,edi_object.lon) Fout.write(vals) except: raise continue Fout.close() print '\n\t Done - Written data to file: {0}\n'.format(outfn) return
def _compute_residual_pt(self): """ compute residual phase tensor so the result is something useful to plot """ log_path = os.path.dirname(os.path.dirname(self.fn_list1[0])) log_fn = os.path.join(log_path, 'Residual_PT.log') logfid = file(log_fn, 'w') self._get_freq_list() freq_dict = dict([(np.round(key, 5), value) for value, key in enumerate(self.freq_list)]) num_freq = self.freq_list.shape[0] num_station = len(self.mt_list1) #make a structured array to put stuff into for easier manipulation self.rpt_array = np.zeros(num_station, dtype=[('station', '|S10'), ('freq', (np.float, num_freq)), ('lat', np.float), ('lon', np.float), ('elev', np.float), ('offset', np.float), ('phimin', (np.float, num_freq)), ('phimax', (np.float, num_freq)), ('skew', (np.float, num_freq)), ('azimuth', (np.float, num_freq)), ('geometric_mean', (np.float, num_freq))]) self.residual_pt_list = [] for mm, mt1 in enumerate(self.mt_list1): station_find = False fdict1 = dict([(np.round(ff, 5), ii) for ii, ff in enumerate(mt1.freq)]) for mt2 in self.mt_list2: if mt2.station == mt1.station: logfid.write('{0}{1}{0}\n'.format('=' * 30, mt1.station)) fdict2 = dict([(np.round(ff, 5), ii) for ii, ff in enumerate(mt2.freq)]) #need to make sure only matched frequencies are compared index_1 = [] index_2 = [] for key1 in sorted(fdict1.keys()): try: index_2.append(fdict2[key1]) index_1.append(fdict1[key1]) logfid.write('-' * 20 + '\n') logfid.write('found {0} in both\n'.format(key1)) logfid.write('Index 1={0}, Index 2={1}\n'.format( fdict1[key1], fdict2[key1])) except KeyError: 'Did not find {0:.4e} Hz in {1}'.format( key1, mt2.fn) #need to sort the index list, otherwise weird things happen index_1.sort() index_2.sort() #create new Z objects that have similar frequencies new_z1 = mtpl.mtz.Z(z_array=mt1.z[index_1], zerr_array=mt1.z_err[index_1], freq=mt1.freq[index_1]) new_z2 = mtpl.mtz.Z(z_array=mt2.z[index_2], zerr_array=mt2.z_err[index_2], freq=mt2.freq[index_2]) #make new phase tensor objects pt1 = mtpt.PhaseTensor(z_object=new_z1) pt2 = mtpt.PhaseTensor(z_object=new_z2) #compute residual phase tensor rpt = mtpt.ResidualPhaseTensor(pt1, pt2) rpt.compute_residual_pt(pt1, pt2) #add some attributes to residual phase tensor object rpt.station = mt1.station rpt.lat = mt1.lat rpt.lon = mt1.lon #append to list for manipulating later self.residual_pt_list.append(rpt) #be sure to tell the program you found the station station_find = True #put stuff into an array because we cannot set values of #rpt, need this for filtering. st_1, st_2 = self.station_id self.rpt_array[mm]['station'] = mt1.station[st_1:st_2] self.rpt_array[mm]['lat'] = mt1.lat self.rpt_array[mm]['lon'] = mt1.lon self.rpt_array[mm]['elev'] = mt1.elev self.rpt_array[mm]['freq'][:] = self.freq_list rpt_fdict = dict([(np.round(key, 5), value) for value, key in enumerate(rpt.freq)]) for f_index, freq in enumerate(rpt.freq): aa = freq_dict[np.round(freq, 5)] try: rr = rpt_fdict[np.round(freq, 5)] try: self.rpt_array[mm]['phimin'][aa] = \ rpt.residual_pt.phimin[0][rr] self.rpt_array[mm]['phimax'][aa] = \ rpt.residual_pt.phimax[0][rr] self.rpt_array[mm]['skew'][aa] = \ rpt.residual_pt.beta[0][rr] self.rpt_array[mm]['azimuth'][aa] = \ rpt.residual_pt.azimuth[0][rr] self.rpt_array[mm]['geometric_mean'][aa] = \ np.sqrt(abs(rpt.residual_pt.phimin[0][rr]* rpt.residual_pt.phimax[0][rr])) logfid.write('Freq={0:.5f} '.format(freq)) logfid.write('Freq_list_index={0} '.format( np.where(self.freq_list == freq)[0][0])) logfid.write('rpt_array_index={0} '.format(aa)) logfid.write('rpt_dict={0} '.format(rr)) logfid.write('rpt.freq_index={0} '.format( np.where(rpt.freq == freq)[0][0])) logfid.write('Phi_max={0:2f} '.format( rpt.residual_pt.phimax[0][rr])) logfid.write('Phi_min={0:2f} '.format( rpt.residual_pt.phimin[0][rr])) logfid.write('Skew={0:2f} '.format( rpt.residual_pt.beta[0][rr])) logfid.write('Azimuth={0:2f}\n'.format( rpt.residual_pt.azimuth[0][rr])) except IndexError: print '-' * 50 print mt1.station print 'freq_index for 1: {0}'.format(f_index) print 'freq looking for: {0}'.format(freq) print 'index in big : {0}'.format(aa) print 'index in 1 : {0} '.format(rr) print 'len_1 = {0}, len_2 = {1}'.format( len(mt2.freq), len(mt1.freq)) print 'len rpt_freq = {0}'.format(len( rpt.freq)) except KeyError: print 'Station {0} does not have {1:.5f}Hz'.format( mt1.station, freq) break else: pass if station_find == False: print 'Did not find {0} from list 1 in list 2'.format( mt1.station) # from the data get the relative offsets and sort the data by them self._get_offsets() logfid.close()
#write Marina's format rp_lines_base = [] rp_lines_base.append( ''.join(['{0:^12}'.format(hh) for hh in header_line] + ['\n'])) rp_lines_inj = [] rp_lines_inj.append( ''.join(['{0:^12}'.format(hh) for hh in header_line] + ['\n'])) pt_lines_base = [] pt_lines_base.append( ''.join(['{0:^12}'.format(hh) for hh in header_line_pt] + ['\n'])) pt_lines_inj = [] pt_lines_inj.append( ''.join(['{0:^12}'.format(hh) for hh in header_line_pt] + ['\n'])) pt_base = mtpt.PhaseTensor(z_object=edi_base.Z) pt_inj = mtpt.PhaseTensor(z_object=edi_inj.Z) for ii, freq in enumerate(edi_base.Z.freq): rp_lines_base.append(''.join([ '{0:>12}'.format(nn) for nn in [ '{0:+.4e}'.format(mm) for mm in [ 1. / freq, edi_base.Z.resistivity[ii, 0, 1], edi_base. Z.resistivity_err[ii, 0, 1], edi_base.Z.resistivity[ii, 1, 0], edi_base.Z.resistivity_err[ii, 1, 0], edi_base.Z.phase[ ii, 0, 1], edi_base.Z.phase_err[ii, 0, 1], edi_base .Z.phase[ii, 1, 0], edi_base.Z.phase_err[ii, 1, 0] ] ] ] + ['\n']))
def create_measurement_csv(self, dest_dir, period_list=None, interpolate=True): """ create csv file from the data of EDI files: IMPEDANCE, APPARENT RESISTIVITIES AND PHASES see also utils/shapefiles_creator.py :param dest_dir: output directory :param period_list: list of periods; default=None, in which data for all available frequencies are output :param interpolate: Boolean to indicate whether to interpolate data onto given period_list :return: csvfname """ if dest_dir is None: dest_dir = self.outdir else: self._logger.info("result will be in the dir %s", dest_dir) if not os.path.exists(dest_dir): os.mkdir(dest_dir) # summary csv file csv_basename = "edi_measurement" csvfname = os.path.join(dest_dir, "%s.csv" % csv_basename) pt_dict = {} csv_header = [ 'FREQ', 'STATION', 'LAT', 'LON', 'ZXXre', 'ZXXim', 'ZXYre', 'ZXYim', 'ZYXre', 'ZYXim', 'ZYYre', 'ZYYim', 'TXre', 'TXim', 'TYre', 'TYim', 'RHOxx', 'RHOxy', 'RHOyx', 'RHOyy', 'PHSxx', 'PHSxy', 'PHSyx', 'PHSyy' ] freq_list = None if (period_list is None): freq_list = self.all_frequencies else: freq_list = 1. / np.array(period_list) # end if with open(csvfname, "wb") as csvf: writer = csv.writer(csvf) writer.writerow(csv_header) for freq in freq_list: mtlist = [] for mt_obj in self.mt_obj_list: f_index_list = None pt = None ti = None zobj = None if (interpolate): f_index_list = [0] newZ = None newTipper = None newZ, newTipper = mt_obj.interpolate([freq], bounds_error=False) pt = MTpt.PhaseTensor(z_object=newZ) ti = newTipper zobj = newZ else: freq_max = freq * (1 + self.ptol) freq_min = freq * (1 - self.ptol) f_index_list = np.where((mt_obj.Z.freq < freq_max) & (mt_obj.Z.freq > freq_min)) pt = mt_obj.pt ti = mt_obj.Tipper zobj = mt_obj.Z # end if if len(f_index_list) > 1: self._logger.warn("more than one freq found %s", f_index_list) if len(f_index_list) >= 1: p_index = f_index_list[0] self._logger.debug("The freqs index %s", f_index_list) # geographic coord lat long and elevation # long, lat, elev = (mt_obj.lon, mt_obj.lat, 0) station, lat, lon = (mt_obj.station, mt_obj.lat, mt_obj.lon) resist_phase = mtplottools.ResPhase(z_object=zobj) # resist_phase.compute_res_phase() mt_stat = [ freq, station, lat, lon, zobj.z[p_index, 0, 0].real, zobj.z[p_index, 0, 0].imag, zobj.z[p_index, 0, 1].real, zobj.z[p_index, 0, 1].imag, zobj.z[p_index, 1, 0].real, zobj.z[p_index, 1, 0].imag, zobj.z[p_index, 1, 1].real, zobj.z[p_index, 1, 1].imag, ti.tipper[p_index, 0, 0].real, ti.tipper[p_index, 0, 0].imag, ti.tipper[p_index, 0, 1].real, ti.tipper[p_index, 0, 1].imag, resist_phase.resxx[p_index], resist_phase.resxy[p_index], resist_phase.resyx[p_index], resist_phase.resyy[p_index], resist_phase.phasexx[p_index], resist_phase.phasexy[p_index], resist_phase.phaseyx[p_index], resist_phase.phaseyy[p_index] ] mtlist.append(mt_stat) else: self._logger.warn('Freq %s NOT found for this station %s', freq, mt_obj.station) with open(csvfname, "ab") as csvf: # summary csv for all freqs writer = csv.writer(csvf) writer.writerows(mtlist) csv_basename2 = "%s_%sHz.csv" % (csv_basename, str(freq)) csvfile2 = os.path.join(dest_dir, csv_basename2) with open(csvfile2, "wb") as csvf: # individual csvfile for each freq writer = csv.writer(csvf) writer.writerow(csv_header) writer.writerows(mtlist) pt_dict[freq] = mtlist return csvfname
def create_phase_tensor_csv(self, dest_dir, period_list=None, interpolate=True, file_name="phase_tensor.csv"): """ create phase tensor ellipse and tipper properties. Implementation based on mtpy.utils.shapefiles_creator.ShapeFilesCreator.create_csv_files :param dest_dir: output directory :param period_list: list of periods; default=None, in which data for all available frequencies are output :param interpolate: Boolean to indicate whether to interpolate data onto given period_list :param file_name: output file name :return: pt_dict """ csvfname = os.path.join(dest_dir, file_name) pt_dict = {} csv_header = [ 'station', 'freq', 'lon', 'lat', 'phi_min', 'phi_max', 'azimuth', 'skew', 'n_skew', 'elliptic', 'tip_mag_re', 'tip_mag_im', 'tip_ang_re', 'tip_ang_im' ] freq_list = None if (period_list is None): freq_list = self.all_frequencies else: freq_list = 1. / np.array(period_list) # end if with open(csvfname, "wb") as csvf: writer = csv.writer(csvf) writer.writerow(csv_header) for freq in freq_list: ptlist = [] for mt_obj in self.mt_obj_list: f_index_list = None pt = None ti = None if (interpolate): f_index_list = [0] newZ = None newTipper = None newZ, newTipper = mt_obj.interpolate( [freq], bounds_error=False) pt = MTpt.PhaseTensor(z_object=newZ) ti = newTipper else: freq_min = freq * (1 - self.ptol) freq_max = freq * (1 + self.ptol) f_index_list = [ ff for ff, f2 in enumerate(mt_obj.Z.freq) if (f2 > freq_min) and (f2 < freq_max) ] pt = mt_obj.pt ti = mt_obj.Tipper #end if if len(f_index_list) > 1: self._logger.warn("more than one freq found %s", f_index_list) if len(f_index_list) >= 1: p_index = f_index_list[0] # geographic coord lat long and elevation # long, lat, elev = (mt_obj.lon, mt_obj.lat, 0) station, lon, lat = (mt_obj.station, mt_obj.lon, mt_obj.lat) pt_stat = [ station, freq, lon, lat, pt.phimin[p_index], pt.phimax[p_index], pt.azimuth[p_index], pt.beta[p_index], 2 * pt.beta[p_index], pt.ellipticity[ p_index], # FZ: get ellipticity begin here ti.mag_real[p_index], ti.mag_imag[p_index], ti.angle_real[p_index], ti.angle_imag[p_index] ] ptlist.append(pt_stat) else: self._logger.warn( "Freq %s NOT found for this station %s", freq, mt_obj.station) csv_freq_file = os.path.join( dest_dir, '{name[0]}_{freq}Hz{name[1]}'.format( freq=str(freq), name=os.path.splitext(file_name))) with open(csv_freq_file, "wb") as freq_csvf: writer_freq = csv.writer(freq_csvf) writer_freq.writerow(csv_header) writer_freq.writerows(ptlist) writer.writerows(ptlist) pt_dict[freq] = ptlist return pt_dict
def get_phase_tensor_tippers(self, period, interpolate=True): """ For a given MT period (s) value, compute the phase tensor and tippers etc. :param period: MT_period (s) :param interpolate: Boolean to indicate whether to interpolate on to the given period :return: dictionary pt_dict_list pt_dict keys ['station', 'freq', 'lon', 'lat', 'phi_min', 'phi_max', 'azimuth', 'skew', 'n_skew', 'elliptic', 'tip_mag_re', 'tip_mag_im', 'tip_ang_re', 'tip_ang_im'] """ pt_dict_list = [] plot_per = period #plot_per = self.all_unique_periods[1] # test first print("The plot period is ", plot_per) for mt_obj in self.mt_obj_list: pt_dict = {} pt = None ti = None if (interpolate == False): p_index = [ ff for ff, f2 in enumerate(1.0 / mt_obj.Z.freq) if (f2 > plot_per * (1 - self.ptol)) and (f2 < plot_per * (1 + self.ptol)) ] pt = mt_obj.pt ti = mt_obj.Tipper else: p_index = [0] newZ, newTipper = mt_obj.interpolate([1. / plot_per], bounds_error=False) pt = MTpt.PhaseTensor(z_object=newZ) ti = newTipper # end if if len(p_index) >= 1: p_index = p_index[0] pt_dict['station'] = mt_obj.station pt_dict['period'] = plot_per pt_dict['lon'] = mt_obj.lon pt_dict['lat'] = mt_obj.lat pt_dict['phi_min'] = pt.phimin[p_index] pt_dict['phi_max'] = pt.phimax[p_index] pt_dict['azimuth'] = pt.azimuth[p_index] pt_dict['skew'] = pt.beta[p_index] pt_dict['n_skew'] = 2 * pt.beta[p_index] pt_dict['elliptic'] = pt.ellipticity[p_index] pt_dict['tip_mag_re'] = ti.mag_real[p_index] pt_dict['tip_mag_im'] = ti.mag_imag[p_index] pt_dict['tip_ang_re'] = ti.angle_real[p_index] pt_dict['tip_ang_im'] = ti.angle_imag[p_index] pt_dict_list.append(pt_dict) else: self._logger.warn( " the period %s is NOT found for this station %s. Skipping!!!" % (plot_per, mt_obj.station)) return pt_dict_list
phimaxarr = np.zeros((nf, ns)) phiminarr = np.zeros((nf, ns)) betaarr = np.zeros((nf, ns)) colorarr = np.zeros((nf, ns)) latlst = np.zeros(ns) lonlst = np.zeros(ns) stationlst = [] for ss, station in enumerate(edilst): #make a data type Z edi1 = mtedi.Edi(station[0]) edi2 = mtedi.Edi(station[1]) pt1 = mtpt.PhaseTensor(z_object=edi1.Z) pt2 = mtpt.PhaseTensor(z_object=edi2.Z) stationlst.append(edi1.station) sz, se, sn = utm2ll.LLtoUTM(refe, edi1.lat, edi1.lon) latlst[ss] = (sn - bhn) / 1000. lonlst[ss] = (se - bhe) / 1000. #calculate the difference between the two phase tensor ellipses for ii in range(nf): phi = np.eye(2) - (np.dot(np.linalg.inv(pt1.pt[ii]), pt2.pt[ii])) #compute the trace tr = phi[0, 0] + phi[1, 1] #Calculate skew of phi and the cooresponding error
def dimensionality(z_array=None, z_object=None, pt_array=None, pt_object=None, skew_threshold=5, eccentricity_threshold=0.1): """ Esitmate dimensionality of an impedance tensor, frequency by frequency. Dimensionality is estimated from the phase tensor given the threshold criteria on the skew angle and eccentricity following Bibby et al., 2005 and Booker, 2014. Arguments ------------ **z_array** : np.ndarray(nf, 2, 2) numpy array of impedance elements *default* is None **z_object** : mtpy.core.z.Z z_object *default* is None **pt_array** : np.ndarray(nf, 2, 2) numpy array of phase tensor elements *default* is None **pt_object** : mtpy.analysis.pt.PT phase tensor object *default* is None **skew_threshold** : float threshold on the skew angle in degrees, anything above this value is 3-D or azimuthally anisotropic *default* is 5 degrees **eccentricity_threshold** : float threshold on eccentricty in dimensionaless units, anything below this value is 1-D *default* is 0.1 Returns ---------- **dimensions** : np.ndarray(nf, dtype=int) an array of dimesions for each frequency the values are [ 1 | 2 | 3 ] Examples ---------- :Estimate Dimesions: :: >>> import mtpy.analysis.geometry as geometry >>> dim = geometry.dimensionality(z_object=z_obj, >>> skew_threshold=3) """ lo_dimensionality = [] if z_array is not None: pt_obj = MTpt.PhaseTensor(z_array=z_array) elif z_object is not None: if not isinstance(z_object, MTz.Z): raise MTex.MTpyError_Z( 'Input argument is not an instance of the Z class') pt_obj = MTpt.PhaseTensor(z_object=z_object) elif pt_array is not None: pt_obj = MTpt.PhaseTensor(pt_array=pt_array) elif pt_object is not None: if not isinstance(pt_object, MTpt.PhaseTensor): raise MTex.MTpyError_PT( 'Input argument is not an instance of the PhaseTensor class') pt_obj = pt_object # use criteria from Bibby et al. 2005 for determining the dimensionality # for each frequency of the pt/z array: for idx_f in range(len(pt_obj.pt)): #1. determine skew value... skew = pt_obj.beta[idx_f] #compare with threshold for 3D if np.abs(skew) > skew_threshold: lo_dimensionality.append(3) else: # 2.check for eccentricity: ecc = pt_obj._pi1()[0][idx_f] / pt_obj._pi2()[0][idx_f] if ecc > eccentricity_threshold: lo_dimensionality.append(2) else: lo_dimensionality.append(1) return np.array(lo_dimensionality)
def eccentricity(z_array=None, z_object=None, pt_array=None, pt_object=None): """ Estimate eccentricy of a given impedance or phase tensor object Arguments ------------ **z_array** : np.ndarray(nf, 2, 2) numpy array of impedance elements *default* is None **z_object** : mtpy.core.z.Z z_object *default* is None **pt_array** : np.ndarray(nf, 2, 2) numpy array of phase tensor elements *default* is None **pt_object** : mtpy.analysis.pt.PT phase tensor object *default* is None Returns ---------- **eccentricity** : np.ndarray(nf) **eccentricity_err** : np.ndarray(nf) Examples ---------- :Estimate Dimesions: :: >>> import mtpy.analysis.geometry as geometry >>> ec, ec_err= geometry.eccentricity(z_object=z_obj) """ if z_array is not None: pt_obj = MTpt.PhaseTensor(z_array=z_array) elif z_object is not None: if not isinstance(z_object, MTz.Z): raise MTex.MTpyError_Z( 'Input argument is not an instance of the Z class') pt_obj = MTpt.PhaseTensor(z_object=z_object) elif pt_array is not None: pt_obj = MTpt.PhaseTensor(pt_array=pt_array) elif pt_object is not None: if not isinstance(pt_object, MTpt.PhaseTensor): raise MTex.MTpyError_PT( 'Input argument is not an instance of the PhaseTensor class') pt_obj = pt_object lo_ecc = [] lo_eccerr = [] if not isinstance(pt_obj, MTpt.PhaseTensor): raise MTex.MTpyError_PT( 'Input argument is not an instance of the PhaseTensor class') for idx_f in range(len(pt_obj.pt)): lo_ecc.append(pt_obj._pi1()[0][idx_f] / pt_obj._pi2()[0][idx_f]) ecc_err = None if (pt_obj._pi1()[1] is not None) and (pt_obj._pi2()[1] is not None): ecc_err = np.sqrt((pt_obj._pi1()[1][idx_f] / pt_obj._pi1()[0][idx_f]) ** 2 +\ (pt_obj._pi2()[1][idx_f] / pt_obj._pi2()[0][idx_f]) ** 2) lo_eccerr.append(ecc_err) return np.array(lo_ecc), np.array(lo_eccerr) * np.array(lo_ecc)
def strike_angle(z_array=None, z_object=None, pt_array=None, pt_object=None, skew_threshold=5, eccentricity_threshold=0.1): """ Estimate strike angle from 2D parts of the phase tensor given the skew and eccentricity thresholds Arguments ------------ **z_array** : np.ndarray(nf, 2, 2) numpy array of impedance elements *default* is None **z_object** : mtpy.core.z.Z z_object *default* is None **pt_array** : np.ndarray(nf, 2, 2) numpy array of phase tensor elements *default* is None **pt_object** : mtpy.analysis.pt.PT phase tensor object *default* is None **skew_threshold** : float threshold on the skew angle in degrees, anything above this value is 3-D or azimuthally anisotropic *default* is 5 degrees **eccentricity_threshold** : float threshold on eccentricty in dimensionaless units, anything below this value is 1-D *default* is 0.1 Returns ---------- **strike** : np.ndarray(nf) an array of strike angles in degrees for each frequency assuming 0 is north, and e is 90. There is a 90 degree ambiguity in the angle. Examples ---------- :Estimate Dimesions: :: >>> import mtpy.analysis.geometry as geometry >>> strike = geometry.strike_angle(z_object=z_obj, >>> skew_threshold=3) """ if z_array is not None: pt_obj = MTpt.PhaseTensor(z_array=z_array) elif z_object is not None: if not isinstance(z_object, MTz.Z): raise MTex.MTpyError_Z( 'Input argument is not an instance of the Z class') pt_obj = MTpt.PhaseTensor(z_object=z_object) elif pt_array is not None: pt_obj = MTpt.PhaseTensor(pt_array=pt_array) elif pt_object is not None: if not isinstance(pt_object, MTpt.PhaseTensor): raise MTex.MTpyError_PT( 'Input argument is not an instance of the PhaseTensor class') pt_obj = pt_object lo_dims = dimensionality(pt_object=pt_obj, skew_threshold=skew_threshold, eccentricity_threshold=eccentricity_threshold) lo_strikes = [] for idx, dim in enumerate(lo_dims): if dim == 1: lo_strikes.append((np.nan, np.nan)) # continue elif dim == 3: lo_strikes.append((np.nan, np.nan)) else: a = pt_obj.alpha[idx] b = pt_obj.beta[idx] strike1 = (a - b) % 180 # change so that values range from -90 to +90 # add alternative strikes to account for ambiguity if strike1 > 90: strike1 -= 180 strike2 = strike1 + 90 else: strike2 = strike1 - 90 lo_strikes.append((strike1, strike2)) return np.array(lo_strikes)