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()
Пример #2
0
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
Пример #3
0
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()
Пример #4
0
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
Пример #5
0
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
Пример #6
0
 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
Пример #7
0
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
Пример #8
0
    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
Пример #9
0
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
Пример #10
0
 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)))
Пример #11
0
 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))
Пример #12
0
    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
Пример #13
0
    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])
Пример #14
0
    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:]))
Пример #15
0
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()
Пример #16
0
    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)
Пример #17
0
    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
Пример #18
0
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
Пример #19
0
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
Пример #21
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)))
Пример #23
0
#    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)
Пример #24
0
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
Пример #25
0
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
Пример #26
0
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()
Пример #27
0
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)
Пример #28
0
# -*- 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
Пример #30
0
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