def resampleNSEMdataAtFreq(NSEMdata, freqs): """ Function to resample NSEMdata at set of frequencies """ # Make a rec array NSEMrec = NSEMdata.toRecArray().data # Find unique locations uniLoc = np.unique(NSEMrec[['x','y','z']]) uniFreq = NSEMdata.survey.freqs # Get the comps dNames = NSEMrec.dtype # Loop over all the locations and interpolate for loc in uniLoc: # Find the index of the station ind = np.sqrt(np.sum((rec_to_ndarr(NSEMrec[['x','y','z']]) - rec_to_ndarr(loc))**2,axis=1)) < 1. # Find dist of 1 m accuracy # Make a temporary recArray and interpolate all the components tArrRec = np.concatenate((simpeg.mkvc(freqs,2),np.ones((len(freqs),1))*rec_to_ndarr(loc),np.nan*np.ones((len(freqs),12))),axis=1).view(dNames) for comp in ['zxxr','zxxi','zxyr','zxyi','zyxr','zyxi','zyyr','zyyi','tzxr','tzxi','tzyr','tzyi']: int1d = sciint.interp1d(NSEMrec[ind]['freq'],NSEMrec[ind][comp],bounds_error=False) tArrRec[comp] = simpeg.mkvc(int1d(freqs),2) # Join together try: outRecArr = recFunc.stack_arrays((outRecArr,tArrRec)) except NameError: outRecArr = tArrRec # Make the NSEMdata and return return Data.fromRecArray(outRecArr)
def rotateData(NSEMdata, rotAngle): ''' Function that rotates clockwist by rotAngle (- negative for a counter-clockwise rotation) ''' recData = NSEMdata.toRecArray('Complex') impData = rec_to_ndarr(recData[['zxx', 'zxy', 'zyx', 'zyy']], complex) # Make the rotation matrix # c,s,zxx,zxy,zyx,zyy = sympy.symbols('c,s,zxx,zxy,zyx,zyy') # rotM = sympy.Matrix([[c,-s],[s, c]]) # zM = sympy.Matrix([[zxx,zxy],[zyx,zyy]]) # rotM*zM*rotM.T # [c*(c*zxx - s*zyx) - s*(c*zxy - s*zyy), c*(c*zxy - s*zyy) + s*(c*zxx - s*zyx)], # [c*(c*zyx + s*zxx) - s*(c*zyy + s*zxy), c*(c*zyy + s*zxy) + s*(c*zyx + s*zxx)]]) s = np.sin(-np.deg2rad(rotAngle)) c = np.cos(-np.deg2rad(rotAngle)) rotMat = np.array([[c, -s], [s, c]]) rotData = (rotMat.dot(impData.reshape(-1, 2, 2).dot(rotMat.T))).transpose( 1, 0, 2).reshape(-1, 4) outRec = recData.copy() for nr, comp in enumerate(['zxx', 'zxy', 'zyx', 'zyy']): outRec[comp] = rotData[:, nr] return Data.fromRecArray(outRec)
def rotateData(NSEMdata, rotAngle): ''' Function that rotates clockwist by rotAngle (- negative for a counter-clockwise rotation) ''' recData = NSEMdata.toRecArray('Complex') impData = rec_to_ndarr(recData[['zxx','zxy','zyx','zyy']],complex) # Make the rotation matrix # c,s,zxx,zxy,zyx,zyy = sympy.symbols('c,s,zxx,zxy,zyx,zyy') # rotM = sympy.Matrix([[c,-s],[s, c]]) # zM = sympy.Matrix([[zxx,zxy],[zyx,zyy]]) # rotM*zM*rotM.T # [c*(c*zxx - s*zyx) - s*(c*zxy - s*zyy), c*(c*zxy - s*zyy) + s*(c*zxx - s*zyx)], # [c*(c*zyx + s*zxx) - s*(c*zyy + s*zxy), c*(c*zyy + s*zxy) + s*(c*zyx + s*zxx)]]) s = np.sin(-np.deg2rad(rotAngle)) c = np.cos(-np.deg2rad(rotAngle)) rotMat = np.array([[c,-s],[s,c]]) rotData = (rotMat.dot(impData.reshape(-1,2,2).dot(rotMat.T))).transpose(1,0,2).reshape(-1,4) outRec = recData.copy() for nr,comp in enumerate(['zxx','zxy','zyx','zyy']): outRec[comp] = rotData[:,nr] return Data.fromRecArray(outRec)
def resample_data(NSEMdata, locs='All', freqs='All', rxs='All', verbose=False): """ Function that selects locations from all the receivers in the survey (uses the numerator location as a reference). Also gives the option of selecting frequencies and receiver. **Required** :param SimPEG.EM.NSEM.Data NSEMdata: NSEM data object to process **Optional** :param numpy.ndarray locs: receiver locations to use (default is 'All' locations) :param numpy.ndarray freqs: frequencies to use (default is 'All' frequencies)) :param string rxs: list of receiver sting types to use (default is 'All' types) Can be any componation of ['zxx','zxy','zyx','zyy','tzx','tzy'] """ # Initiate new objects new_srcList = [] data_list = [] std_list = [] floor_list = [] # Sort out input frequencies if locs is 'All': locations = NSEMdata._unique_locations() elif isinstance(locs, np.ndarray): locations = locs else: raise IOError('Incorrect input type for locs. \n' + 'Can be \'All\' or ndarray ') # Sort out input frequencies if freqs is 'All': frequencies = NSEMdata.survey.freqs elif isinstance(freqs, np.ndarray): frequencies = freqs elif isinstance(freqs, list): frequencies = np.array(freqs) else: raise IOError('Incorrect input type for freqs. \n' + 'Can be \'All\'; ndarray or a list') # Sort out input rxs if rxs is 'All': rx_comp = True elif isinstance(rxs, list): rx_comp = [] for rxT in rxs: if 'z' in rxT[0]: rxtype = Point_impedance3D elif 't' in rxT[0]: rxtype = Point_tipper3D else: raise IOError('Unknown rx type string') orient = rxT[1:3] rx_comp.append((rxtype, orient)) else: raise IOError('Incorrect input type for rxs. \n' + 'Can be \'All\' or a list') # Filter the data for src in NSEMdata.survey.srcList: if src.freq in frequencies: new_rxList = [] for rx in src.rxList: if rx_comp is True or np.any([(isinstance(rx, ct) and rx.orientation in co) for (ct, co) in rx_comp]): if len(rx.locs.shape) == 3: ind_loc = np.sum(np.concatenate( [(np.sqrt( np.sum((rx.locs[:, :, 0] - location)**2, axis=1)) < 0.1).reshape(-1, 1) for location in locations], axis=1), axis=1, dtype=bool) new_locs = rx.locs[ind_loc, :, :] else: ind_loc = np.sum(np.concatenate( [(np.sqrt( np.sum((rx.locs[:, :] - location)**2, axis=1)) < 0.1).reshape(-1, 1) for location in locations], axis=1), axis=1, dtype=bool) new_locs = rx.locs[ind_loc, :] new_rx = type(rx) new_rxList.append( new_rx(new_locs, rx.orientation, rx.component)) data_list.append(NSEMdata[src, rx][ind_loc]) try: std_list.append( NSEMdata.standard_deviation[src, rx][ind_loc]) floor_list.append(NSEMdata.floor[src, rx][ind_loc]) except Exception as e: if verbose: print('No standard deviation or floor assigned') new_src = type(src) new_srcList.append(new_src(new_rxList, src.freq)) survey = Survey(new_srcList) if std_list or floor_list: return Data(survey, np.concatenate(data_list), np.concatenate(std_list), np.concatenate(floor_list)) else: return Data(survey, np.concatenate(data_list))
def convert3Dto1Dobject(NSEMdata, rxType3D='yx'): """ Function that converts a 3D NSEMdata of a list of 1D NSEMdata objects for running 1D inversions for. **Required** :param SimPEG.EM.NSEM.Data NSEMdata: NSEM data object to process **Optional** :param string rxType3D: component of the NSEMdata to use Can be 'xy', 'yx' or 'det' """ # Find the unique locations # Need to find the locations recDataTemp = NSEMdata.toRecArray().data.flatten() # Check if survey.std has been assigned. ## NEED TO: write this... # Calculte and add the DET of the tensor to the recArray if 'det' in rxType3D: Zon = ((recDataTemp['zxxr'] + 1j * recDataTemp['zxxi']) * (recDataTemp['zyyr'] + 1j * recDataTemp['zyyi'])) Zoff = ((recDataTemp['zxyr'] + 1j * recDataTemp['zxyi']) * (recDataTemp['zyxr'] + 1j * recDataTemp['zyxi'])) det = np.sqrt(Zon - Zoff) recData = recFunc.append_fields(recDataTemp, ['zdetr', 'zdeti'], [det.real, det.imag]) else: recData = recDataTemp uniLocs = rec_to_ndarr(np.unique(recData[['x', 'y', 'z']].copy())) mtData1DList = [] if 'xy' in rxType3D: corr = -1 # Shift the data to comply with the quadtrature of the 1d problem else: corr = 1 for loc in uniLocs: # Make the receiver list rx1DList = [] rx1DList.append(Point_impedance1D(simpeg.mkvc(loc, 2).T, 'real')) rx1DList.append(Point_impedance1D(simpeg.mkvc(loc, 2).T, 'imag')) # Source list locrecData = recData[np.sqrt( np.sum((rec_to_ndarr(recData[['x', 'y', 'z']].copy()) - loc)**2, axis=1)) < 1e-5] dat1DList = [] src1DList = [] for freq in locrecData['freq']: src1DList.append(Planewave_xy_1Dprimary(rx1DList, freq)) for comp in ['r', 'i']: dat1DList.append( corr * locrecData[rxType3D + comp][locrecData['freq'] == freq]) # Make the survey sur1D = Survey(src1DList) # Make the data dataVec = np.hstack(dat1DList) dat1D = Data(sur1D, dataVec) sur1D.dobs = dataVec # Need to take NSEMdata.survey.std and split it as well. std = 0.05 sur1D.std = np.abs(sur1D.dobs * std) mtData1DList.append(dat1D) # Return the the list of data. return mtData1DList