def clip_modem_model(model_fn, clip):
    """
    Read in ModEM model and clip to a smaller box
    """
    m_obj = modem.Model()
    m_obj.read_model_file(model_fn)

    ### --> need to convert model coordinates into lat and lon
    utm_center = gis_tools.project_point_ll2utm(model_center[1],
                                                model_center[0])

    lat = np.zeros_like(m_obj.grid_north[clip:-(clip + 1)])
    lon = np.zeros_like(m_obj.grid_east[clip:-(clip + 1)])
    depth = m_obj.grid_z[:-1] / 1000.0

    for ii, north in enumerate(m_obj.grid_north[clip:-(clip + 1)]):
        m_lat, m_lon = gis_tools.project_point_utm2ll(utm_center[0],
                                                      utm_center[1] + north,
                                                      utm_center[2])
        lat[ii] = m_lat

    for ii, east in enumerate(m_obj.grid_east[clip:-(clip + 1)]):
        m_lat, m_lon = gis_tools.project_point_utm2ll(utm_center[0] + east,
                                                      utm_center[1],
                                                      utm_center[2])
        lon[ii] = m_lon

    res = np.log10(m_obj.res_model[clip:-clip, clip:-clip, :])

    return lat, lon, depth, res
Example #2
0
    def interpolate_grid(self, pad_east=None, pad_north=None, cell_size=None):
        """
        interpolate the irregular model grid onto a regular grid.
        
        """

        model_obj = modem.Model()
        model_obj.model_fn = self.model_fn
        model_obj.read_model_file()

        self.grid_z = model_obj.grid_z.copy()

        if cell_size is not None:
            self.cell_size_east = cell_size
            self.cell_size_north = cell_size
        else:
            self.cell_size_east = np.median(model_obj.nodes_east)
            self.cell_size_north = np.median(model_obj.nodes_north)

        if pad_east is not None:
            self.pad_east = pad_east

        if self.pad_east is None:
            self.pad_east = np.where(
                model_obj.nodes_east[0:25] > self.cell_size_east * 1.1)[0][-1]
        if pad_north is not None:
            self.pad_north = pad_north
        if self.pad_north is None:
            self.pad_north = np.where(
                model_obj.nodes_north[0:25] > self.cell_size_north *
                1.1)[0][-1]

        print 'Pad north = {0}'.format(self.pad_north)
        print 'Pad east  = {0}'.format(self.pad_east)

        new_east = np.arange(model_obj.grid_east[self.pad_east],
                             model_obj.grid_east[-self.pad_east - 2],
                             self.cell_size_east)
        new_north = np.arange(model_obj.grid_north[self.pad_north],
                              model_obj.grid_north[-self.pad_north - 2],
                              self.cell_size_north)

        # needs to be -1 because the grid is n+1 as it is the edges of the
        # the nodes.  Might need to change this in the future
        model_n, model_e = np.broadcast_arrays(model_obj.grid_north[:-1, None],
                                               model_obj.grid_east[None, :-1])

        new_res_arr = np.zeros(
            (new_north.size, new_east.size, model_obj.nodes_z.size))

        for z_index in range(model_obj.grid_z.shape[0] - 1):
            res = model_obj.res_model[:, :, z_index]
            new_res_arr[:, :, z_index] = interpolate.griddata(
                (model_n.ravel(), model_e.ravel()), res.ravel(),
                (new_north[:, None], new_east[None, :]))

        self.res_array = new_res_arr
Example #3
0
 def __init__(self):
     super(MeshWidget, self).__init__()
     self.model_obj = modem.Model()
     self.mpl_widget = MeshPlot()
     
     #sys.stdout = MyStream()
     
     
     self.setup_ui()
Example #4
0
    def get_model_fn(self):
        """ 
        read in an existing model file
        """

        fn_dialog = QtGui.QFileDialog() 
        fn = str(fn_dialog.getOpenFileName(caption='Choose ModEM model file',
                                       filter='*.rho'))
                                       
        self.model_obj = modem.Model()
        self.model_obj.read_model_file(fn)

        self.dir_path = os.path.dirname(fn)
Example #5
0
 def load_edi_files(self):
     fn_list = QtGui.QFileDialog().getOpenFileNames(
                                                 caption='Choose EDI Files',
                                                 filter='*.edi')
     self.edi_list = []                                    
     for fn in fn_list:
         self.edi_list.append(str(fn))
     
     self.model_obj = modem.Model(edi_list=self.edi_list)
     
     self.model_obj.get_station_locations()
     
     self.mpl_widget.plot_mesh(self.model_obj)
Example #6
0
    def __init__(self, model_fn, data_fn):
        '''
        Class for extracting field values at arbitrary locations from a 3D MODEM model.
        The model-mesh is centered on the centre-point of station-locations.

        :param model_fn: name of model file
        :param data_fn: name of data file
        '''

        # Read data and model files
        self._model_fn = model_fn
        self._data_fn = data_fn
        try:
            self._d = modem.Data()
            self._d.read_data_file(data_fn=self._data_fn)
        except Exception as err:
            print 'Failed to read %s' % (self._data_fn)
            logging.error(traceback.format_exc())
            exit(-1)

        try:
            self._m = modem.Model(model_fn=self._model_fn,
                                  station_object=self._d.station_locations)
            self._m.read_model_file()
        except Exception as err:
            print 'Failed to read %s' % (self._model_fn)
            logging.error(traceback.format_exc())
            exit(-1)

        # Re-orient model coordinates based on the centre of data locations
        self._mx = self._m.grid_east + self._d.center_point['east']
        self._my = self._m.grid_north + self._d.center_point['north']
        self._mz = self._m.grid_z

        # Compute cell-centre coordinates
        self._mcx = (self._mx[1:] + self._mx[:-1]) / 2.
        self._mcy = (self._my[1:] + self._my[:-1]) / 2.
        self._mcz = (self._mz[1:] + self._mz[:-1]) / 2.

        # Create mesh-grid based on cell-centre coordinates
        self._mgx, self._mgy, self._mgz = np.meshgrid(self._mcx, self._mcy,
                                                      self._mcz)

        # List of xyz coodinates of mesh-grid
        self._mgxyz = np.vstack(
            [self._mgx.flatten(),
             self._mgy.flatten(),
             self._mgz.flatten()]).T

        # Create Kd-Tree based on mesh-grid coordinates
        self._tree = cKDTree(self._mgxyz)
Example #7
0
    def make_vtk_files(self):
        if self.model_type == 'ModEM':
            m_obj = modem.Model()
            m_obj.read_model_file(os.path.join(self.cwd, self.model_fn))
            m_obj.write_vtk_file(vtk_save_path=self.cwd,
                                 vtk_fn_basename=self.vtk_model_fn)

            d_obj = modem.Data()
            d_obj.read_data_file(self.resp_fn)
            d_obj.write_vtk_station_file(vtk_save_path=self.cwd,
                                         vtk_fn_basename=self.vtk_station_fn)
            program = 'modem2vtk'
        elif self.model_type == 'WS':
            program = 'ws2vtk'

            subprocess.call([
                program, self.model_fn, self.resp_fn, self.vtk_model_fn,
                self.vtk_station_fn
            ])
Example #8
0
    def _get_model(self):
        """
        get model to put into array
        """

        model_obj = modem.Model()
        model_obj.model_fn = self.model_fn
        model_obj.read_model_file()

        self.cell_size_east = np.median(model_obj.nodes_east)
        self.cell_size_north = np.median(model_obj.nodes_north)

        self.pad_east = np.where(
            model_obj.nodes_east[0:10] > self.cell_size_east * 1.1)[0][-1]
        self.pad_north = np.where(
            model_obj.nodes_north[0:10] > self.cell_size_north * 1.1)[0][-1]
        self.grid_z = model_obj.grid_z.copy()
        self.res_array = model_obj.res_model[self.pad_north:-self.pad_north,
                                             self.pad_east:-self.pad_east, :]
Example #9
0
    def get_model_lower_left_coord(self,
                                   model_fn=None,
                                   model_center=None,
                                   pad_east=0,
                                   pad_north=0):
        """
        Find the models lower left hand corner in (lon, lat) decimal degrees
        """
        if model_fn is not None:
            self.model_fn = model_fn

        if self.model_fn is None:
            raise IOError('Need to input a ModEM model file name to read in')

        self.pad_east = pad_east
        self.pad_north = pad_north

        model_obj = modem.Model()
        model_obj.model_fn = self.model_fn
        model_obj.read_model_file()

        if model_center:
            center_zone, center_east, center_north = gis_tools.project_point_ll2utm(
                model_center[1], model_center[0])


            lower_left_east = center_east+model_obj.grid_center[1]+\
                                model_obj.nodes_east[0:pad_east].sum()-\
                                model_obj.nodes_east[pad_east]/2
            lower_left_north = center_north+model_obj.grid_center[1]+\
                                model_obj.nodes_north[0:pad_north].sum()+\
                                model_obj.nodes_north[pad_north]/2

            ll_lat, ll_lon = gis_tools.project_point_utm2ll(
                lower_left_north, lower_left_east, center_zone)

            print 'Lower Left Coordinates should be ({0:.5f}, {1:.5f})'.format(
                ll_lon, ll_lat)
            return (ll_lon, ll_lat)
        else:
            raise IOError('Need to input model center (lon, lat)')
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
data_obj.error_value_tipper = .02

#--> here is where you can rotate the data
data_obj.write_data_file(
    save_path=save_path,
    fn_basename="shz_modem_data_err{0:02.0f}_tip{1:02.0f}.dat".format(
        data_obj.error_value_z, data_obj.error_value_tipper))

#==============================================================================
# First make the mesh
#==============================================================================
mod_obj = modem.Model(station_object=data_obj.station_locations)
mod_obj.cell_size_east = 400
mod_obj.cell_size_north = 400
mod_obj.pad_east = 8
mod_obj.pad_north = 8
mod_obj.pad_method = 'extent1'
mod_obj.pad_stretch_h = 1.8
mod_obj.pad_z = 5
mod_obj.n_layers = 50
mod_obj.z1_layer = 10
mod_obj.z_target_depth = 30000.

#--> here is where you can rotate the mesh
mod_obj.mesh_rotation_angle = 0

mod_obj.make_mesh()
#mont_model_center = (583337., 1849383.+1400.)

pad = 5
dem_cell_size = 200.
bathym_cell_size = 900
res_air = 1e12
elev_cell = 30

#starting model resistivity
sm_res = 100

##==============================================================================
##  Do all the work
##==============================================================================

m_obj = modem.Model()
m_obj.read_model_file(model_fn)

d_obj = modem.Data()
d_obj.read_data_file(data_fn)
mont_model_center = (d_obj.center_point.east + 1200,
                     d_obj.center_point.north + 2900)

m_obj.add_topography_to_model(dem_fn,
                              model_center=mont_model_center,
                              cell_size=dem_cell_size,
                              elev_cell=30)

#### 1.) read in the dem and center it onto the resistivity model
#e_east, e_north, elevation = modem.read_dem_ascii(dem_fn, cell_size=dem_cell_size,
#                                        model_center=mont_model_center,
Example #12
0
#--> here is where you can rotate the data
data_obj.write_data_file(save_path=save_path, 
                         fn_basename="{1}_modem_data_err{0:02.0f}_tip{2:02.0f}.dat".format(data_obj.error_value_z,
                                        fn_stem, 
                                        data_obj.error_value_tipper*100),
                        elevation=True,
                        fill=True,
                        compute_error=True)
                                        
                                        
                                    

#==============================================================================
# Write model file
#==============================================================================
mod_obj = modem.Model(data_obj.station_locations)
mod_obj.cell_size_east = 150
mod_obj.cell_size_north = 150
mod_obj.ew_ext = 300000
mod_obj.ns_ext = 300000
mod_obj.pad_east = 10
mod_obj.pad_north = 10
mod_obj.z1_layer = 30
mod_obj.z_target_depth = 25000
mod_obj.z_bottom = 300000
mod_obj.n_layers = 40

mod_obj.make_mesh()
mod_obj.plot_mesh()

mod_obj.write_model_file(save_path=save_path, 
def interpolate_model_grid(old_model_fn,
                           new_model_fn,
                           save_path=None,
                           new_fn_basename=None,
                           pad=3,
                           nan_rho=100,
                           shift_east=0,
                           shift_north=0):
    """
    interpolate an old model onto a new model
    
    Arguments
    ------------------
        **old_model_fn** : string
                           full path to the old model file, or the file
                           that contains the original model that will be
                           interpolated onto a new grid, new_model_fn
        
        **new_model_fn** : string
                           full path to the new model file to interpolate
                           old_model_fn on to.
        
        **save_path** : string
                        directory path to save new interpolated model file
                        *default* is os.path.dirname(new_model_fn)
        
        **new_fn_basename** : string
                              filename given to the new interpolated model
                              *default* is
                              os.path.basename(new_model_fn+'interp')
                           
        **pad** : int
                  number of cells which to pad outer values of the grid.
                  Say new_model_fn is larger than old_model_fn, then there
                  will be Nan where the model don't match up, pad will 
                  extend values from the given number of cells from the edge
                  of new_model_fn.
                  
        **nan_rho** : float
                      if there are Nan in the new_model, they will be given
                      this value. *default* is 100 Ohm-m
        
        **shift_east** : float
                         shift east of new_model grid relative to the old
                         model grid in meters. *Default* is 0
        
        **shift_north** : float
                         shift north of new_model grid relative to the old
                         model grid in meters. *Default* is 0
                         
            
    """
    print 'Interpolating {0} into {1}'.format(old_model_fn, new_model_fn)
    # check to see if the old model is modem or ws
    if old_model_fn[-4:] == '.rho':
        old_mod = modem.Model()
        old_mod.read_model_file(old_model_fn)

    else:
        old_mod = ws.WSModel(old_model_fn)
        old_mod.read_model_file()

    # check to see if the new model is modem or ws
    if new_model_fn[-4:] == '.rho':
        new_mod = modem.Model()
        new_mod.read_model_file(new_model_fn)
        new_ext = '.rho'
        new_fn_type = 'modem'

    else:
        try:
            new_mod = ws.WSModel(new_model_fn)
            new_mod.read_model_file()
        except ValueError:
            new_mod = ws.WSMesh()
            new_mod.read_initial_file(new_model_fn)
        new_ext = ''
        new_fn_type = 'ws'

    if save_path is None:
        save_path = os.path.dirname(new_model_fn)

    if new_fn_basename is None:
        fn = os.path.basename(new_model_fn)
        ext_find = fn.find('.')
        if ext_find == -1:
            ext_find = len(fn) - 1

        new_fn_basename = '{0}_interp{1}'.format(fn[0:ext_find], new_ext)

    print 'Start Time = {0}'.format(time.ctime())

    # make a grid of old model
    old_north, old_east = np.broadcast_arrays(old_mod.grid_north[:-1, None],
                                              old_mod.grid_east[None, :-1])

    #2) do a 2D interpolation for each layer, much faster
    # make a new array of zeros to put values with shape of new model
    new_res = np.zeros((new_mod.nodes_north.shape[0],
                        new_mod.nodes_east.shape[0], new_mod.nodes_z.shape[0]))

    for zz in range(new_mod.nodes_z.shape[0]):
        try:
            old_zz = np.where(old_mod.grid_z >= new_mod.grid_z[zz])[0][0]
            if old_zz >= old_mod.nodes_z.size - 1:
                old_zz = old_mod.nodes_z.size - 1
        except IndexError:
            old_zz = -1

        print 'New depth={0:.2f}; old depth={1:.2f}'.format(
            new_mod.grid_z[zz], old_mod.grid_z[old_zz])

        new_res[:, :, zz] = spi.griddata(
            (old_north.ravel(), old_east.ravel()),
            old_mod.res_model[:, :, old_zz].ravel(),
            (new_mod.grid_north[:-1, None] + shift_north,
             new_mod.grid_east[None, :-1] + shift_east),
            method='linear')

        new_res[0:pad, pad:-pad, zz] = new_res[pad, pad:-pad, zz]
        new_res[-pad:, pad:-pad, zz] = new_res[-pad - 1, pad:-pad, zz]
        new_res[:, 0:pad,
                zz] = new_res[:, pad,
                              zz].repeat(pad).reshape(new_res[:, 0:pad,
                                                              zz].shape)
        new_res[:, -pad:,
                zz] = new_res[:, -pad - 1,
                              zz].repeat(pad).reshape(new_res[:, -pad:,
                                                              zz].shape)

    #
    new_res[np.where(np.nan_to_num(new_res) == 0.0)] = 100.0

    if new_fn_type == 'modem':
        new_mod.write_model_file(save_path=save_path,
                                 model_fn_basename=new_fn_basename,
                                 res_model=new_res)
    else:
        nfid = file(os.path.join(save_path, new_fn_basename), 'w')
        nfid.write('# interpolated starting model for ws written by mtpy\n')
        nfid.write('{0} {1} {2} {3}\n'.format(new_mod.nodes_north.shape[0],
                                              new_mod.nodes_east.shape[0],
                                              new_mod.nodes_z.shape[0], 0))
        # write S--> N block
        for ii, n_node in enumerate(new_mod.nodes_north):
            nfid.write('{0:>12.1f}'.format(abs(n_node)))
            if ii != 0 and np.remainder(ii + 1, 5) == 0:
                nfid.write('\n')
            elif ii == new_mod.nodes_north.shape[0] - 1:
                nfid.write('\n')
        # write W--> E block
        for jj, e_node in enumerate(new_mod.nodes_east):
            nfid.write('{0:>12.1f}'.format(abs(e_node)))
            if jj != 0 and np.remainder(jj + 1, 5) == 0:
                nfid.write('\n')
            elif jj == new_mod.nodes_east.shape[0] - 1:
                nfid.write('\n')
        # write top--> bottom block
        for kk, z_node in enumerate(new_mod.nodes_z):
            nfid.write('{0:>12.1f}'.format(abs(z_node)))
            if kk != 0 and np.remainder(kk + 1, 5) == 0:
                nfid.write('\n')
            elif kk == new_mod.nodes_z.shape[0] - 1:
                nfid.write('\n')

        for kk in range(new_mod.nodes_z.shape[0]):
            for jj in range(new_mod.nodes_east.shape[0]):
                for ii in range(new_mod.nodes_north.shape[0]):
                    nfid.write('{0:.4e}\n'.format(
                        new_res[(new_mod.nodes_north.shape[0] - 1) - ii, jj,
                                kk]))
        nfid.close()
        print 'Wrote file to {0}'.format(
            os.path.join(save_path, new_fn_basename))

#        new_mesh = ws.WSMesh()
#        new_mesh.write_initial_file(nodes_north=new_mod.nodes_north,
#                                    nodes_east=new_mod.nodes_east,
#                                    nodes_z=new_mod.nodes_z,/home/jpeacock/Documents/ModEM/LV/geo_err12/lv_geo_err03_cov5_NLCG_065.res
#                                    res_model=new_res,
#                                    save_path=save_path)

    print 'End Time = {0}'.format(time.ctime())
    return os.path.join(save_path, new_fn_basename)
Example #14
0
# mfn = r"c:\Users\jpeacock\OneDrive - DOI\Geothermal\GreatBasin\modem_inv\canv_01\canv_t03_c04_084.rho"
mfn = r"c:\Users\jpeacock\OneDrive - DOI\Geothermal\GreatBasin\modem_inv\canv_01\canv_z10_c06_150.rho"
# mfn = r"c:\Users\jpeacock\OneDrive - DOI\Geothermal\Umatilla\modem_inv\inv_06\um_z05_c03_083.rho"
# model_center = (-118.704435 + .03, 45.597757000000001 + .02)

model_center = (-119.015192, 38.615252)
lower_left = (-124.2937861, 32.5799747)

z_dict = {
    "surface": np.array((0, 5000)),
    "middle_crust": np.array((12000, 17000)),
    "lower_crust": np.array((17000, 35000)),
}
pad = 10

m = modem.Model()
m.read_model_file(mfn)
gx, gy = np.meshgrid(m.grid_east, m.grid_north)

fig = plt.figure(1)
fig.clf()

for ii, key in enumerate(["surface", "middle_crust", "lower_crust"]):
    z = z_dict[key]
    index_min = np.where(m.grid_z <= z.min())[0][-1]
    index_max = np.where(m.grid_z >= z.max())[0][0]

    conductance = (1.0 / m.res_model[:, :, index_min:index_max]) * abs(
        m.grid_z[index_min:index_max])
    conductance = np.log10(conductance.sum(axis=2))
Example #15
0
#mb_model_fn = r"/home/jpeacock/Documents/ModEM/MB_MT/WS_StartingModel_03_tipper/cov3_mb_tipper_NLCG_028.rho"
#mb_model_fn = r"c:\Users\jpeacock\Documents\MonoBasin\cov3_mb_tipper_NLCG_028.rho"

#grid already made, use it to combine the models
comb_model_fn = r"c:\Users\jpeacock\Documents\MonoBasin\modem_inv\inv_02\ml_sm02_lake.rho"

#locate model centers (E, N)
#mb_center = (327150., 4194900.)
# lv_center old lv_center = (336800, 4167525)
lv_center = (331534., 4179614.)
#comb_center = (331515+5285, 4179690) # big center
comb_center = (328520., 4201968.)

#--> read in the model files
lv_mod = modem.Model()
lv_mod.read_model_file(lv_model_fn)

#mb_mod = modem.Model()
#mb_mod.read_model_file(mb_model_fn)

comb_mod = modem.Model()
comb_mod.read_model_file(comb_model_fn)

#--> interpolate each grid onto the combined grid
#mb_res = interp_grid(mb_mod,
#                     comb_mod,
#                     shift_east=-comb_center[0]+mb_center[0],
#                     shift_north=-comb_center[1]+mb_center[1],
#                     pad=1,
#                     dim='2d',
        #2) next interpolate ont the new mesh (3D interpolation, slow)
        new_res = spi.griddata((north.ravel(), east.ravel(), vert.ravel()),
                                old_model_obj.res_model.ravel(),
                                (new_model_obj.plot_north[:, None, None], 
                                 new_model_obj.plot_east[None, :, None], 
                                 new_model_obj.plot_z[None, None, :]),
                                 method='linear')
         
    print 'Shape of new res = {0}'.format(new_res.shape)                        
    return new_res

# =============================================================================
# Shift modem grid
# =============================================================================
mfn = r"c:\Users\jpeacock\Documents\Geysers\gz_sm50_topo_ocean.rho"
m1_obj = modem.Model()
m1_obj.read_model_file(mfn)

m2_obj = modem.Model()
m2_obj.read_model_file(mfn)

m2_obj.res_model = interp_grid(m1_obj, m2_obj, shift_east=600)
m2_obj.res_model[np.where(m1_obj.res_model < 49)] = m1_obj.res_model[np.where(m1_obj.res_model < 49)]
m2_obj.write_model_file(model_fn_basename=r"gz_sm50_topo_ocean_shifted.rho")
m2_obj.write_vtk_file(vtk_fn_basename='gz_sm_shifted_res')

### write new covariance file
cov = modem.Covariance(grid_dimensions=m2_obj.res_model.shape)
cov.write_covariance_file(save_path=m2_obj.save_path, model_fn=m2_obj.model_fn)
 
# ==============================================================================
#  interpolate all models onto the same grid
# ==============================================================================
dfn = r"/home/jpeacock/Documents/ModEM/LV/hs1000_no_tipper/lv_dp_23p_no_tipper.dat"
mfn_no_tipper = (
    r"/home/jpeacock/Documents/ModEM/LV/hs1000_no_tipper/hs1000_no_tipper_NLCG_070.rho"
)
mfn_tipper = (
    r"/home/jpeacock/Documents/ModEM/LV/hs1000_tipper/hs1000_tipper_NLCG_042.rho"
)

modem_data = modem.Data()
modem_data.read_data_file(dfn)

modem_nt = modem.Model()
modem_nt.read_model_file(mfn_no_tipper)

modem_tip = modem.Model()
modem_tip.read_model_file(mfn_tipper)

# --> average all as a geometric mean
avg_res = (modem_nt.res_model * modem_tip.res_model)**(1.0 / 2)
# avg_res = (nr_ws_hs1*nr_ws_sm1*nr_ws_sm2*nr_nt*nr_tip)**(1./5)

x, y = np.meshgrid(modem_tip.grid_east, modem_tip.grid_north)
kk = 30
kwargs = {"cmap": "jet_r", "vmin": -1, "vmax": 4}

fig = plt.figure(4)
ax1 = fig.add_subplot(1, 3, 1, aspect="equal")
Example #18
0
    print "Shape of new res = {0}".format(new_res.shape)
    return new_res


# ==============================================================================
#  interpolate all models onto the same grid
# ==============================================================================
dfn = r"C:\Users\jpeacock\Documents\iMush\modem_inv\shz_inv_02\shz_modem_data_err03_tip02_edit.dat"
mfn_imush = r"c:\Users\jpeacock\Documents\iMush\modem_inv\paul_final_model\Z4T3_cov0p2x2_L1E2_NLCG_061.rho"
mfn_shz = r"c:\Users\jpeacock\Documents\iMush\modem_inv\shz_inv_02\shz_smt_z04_t03_c02_NLCG_070.rho"

modem_data = modem.Data()
modem_data.read_data_file(dfn)

modem_imush = modem.Model()
modem_imush.read_model_file(mfn_imush)

modem_shz = modem.Model()
modem_shz.read_model_file(mfn_shz)

imush_center = (46.450149, -122.032858)
shz_center = (46.310461, -122.194629)

imush_east, imush_north, zone = gis_tools.project_point_ll2utm(
    imush_center[0], imush_center[1]
)
shz_east, shz_north, zone = gis_tools.project_point_ll2utm(shz_center[0], shz_center[1])

d_east = imush_east - shz_east + 8500
d_north = imush_north - shz_north + 8000