コード例 #1
0
ファイル: quakeplot.py プロジェクト: syzeng999/QuakeMigrate
    def coalescence_video(self, file_str):
        """
        Generate a video over the marginal window showing the coalescence map
        and expected arrival times overlain on the station traces.

        Parameters
        ----------
        file_str : str
            String {run_name}_{event_name}

        """

        # Find index of start and end of marginal window
        idx0 = np.where(self.times == self.event_mw_data["DT"].iloc[0])[0][0]
        idx1 = np.where(self.times == self.event_mw_data["DT"].iloc[-1])[0][0]

        Writer = animation.writers["ffmpeg"]
        writer = Writer(fps=4, metadata=dict(artist="Ulvetanna"), bitrate=1800)

        fig = self._coalescence_frame(idx0)
        ani = animation.FuncAnimation(fig,
                                      self._video_update,
                                      frames=np.linspace(idx0 + 1, idx1, 200),
                                      blit=False,
                                      repeat=False)

        subdir = "videos"
        util.make_directories(self.run_path, subdir=subdir)
        out_str = self.run_path / subdir / file_str
        ani.save("{}_CoalescenceVideo.mp4".format(out_str), writer=writer)
コード例 #2
0
    def __init__(self, path, name=None, log=False):
        """
        Class initialisation method.

        Parameters
        ----------
        path : str
            Path to input / output directory

        name: str, optional
            Name of run

        """

        path = pathlib.Path(path)
        if name is None:
            name = datetime.now().strftime("RUN_%Y%m%d_%H%M%S")
        self.path = path
        self.name = name
        self.run = path / name

        self.log_ = log

        # Make run output directory
        util.make_directories(self.run)
コード例 #3
0
    def write_event(self, event, event_name):
        """
        Create a new .event file

        Parameters
        ----------
        event : pandas DataFrame
            Final event location information.
            Columns = ["DT", "COA", "X", "Y", "Z",
                       "LocalGaussian_X", "LocalGaussian_Y", "LocalGaussian_Z",
                       "LocalGaussian_ErrX", "LocalGaussian_ErrY",
                       "LocalGaussian_ErrZ", "GlobalCovariance_X",
                       "GlobalCovariance_Y", "GlobalCovariance_Z",
                       "GlobalCovariance_ErrX", "GlobalCovariance_ErrY",
                       "GlobalCovariance_ErrZ"]
            All X / Y as lon / lat; Z and X / Y / Z uncertainties in metres

        event_name : str
            event_uid for file naming

        """

        subdir = "events"
        util.make_directories(self.run, subdir=subdir)
        fname = self.run / subdir / "{}".format(event_name)
        fname = str(fname.with_suffix(".event"))
        event.to_csv(fname, index=False)
コード例 #4
0
    def write_coal4D(self, map_4d, event_name, start_time, end_time):
        """
        Writes 4-D coalescence grid to a binary numpy file.

        Parameters
        ----------
        map_4d : array-like
            4-D coalescence grid output by _compute()

        event_name : str
            event_id for file naming

        start_time : UTCDateTime
            start time of 4-D coalescence map

        end_time : UTCDateTime
            end time of 4-D coalescence map

        """

        start_time = UTCDateTime(start_time)
        end_time = UTCDateTime(end_time)

        subdir = "4d_coal_grids"
        util.make_directories(self.run, subdir=subdir)
        filestr = "{}_{}_{}_{}".format(self.name, event_name, start_time,
                                       end_time)
        fname = self.run / subdir / filestr
        fname = fname.with_suffix(".coal4D")

        np.save(str(fname), map_4d)
コード例 #5
0
    def write_picks(self, stations, event_name):
        """
        Write phase picks to a new .picks file

        Parameters
        ----------
        stations : pandas DataFrame object

        event_name : str
            event_id for file naming

        """

        subdir = "picks"
        util.make_directories(self.run, subdir=subdir)
        fname = self.run / subdir / "{}".format(event_name)
        fname = str(fname.with_suffix(".picks"))
        stations.to_csv(fname, index=False)
コード例 #6
0
    def log(self, message, log):
        """
        Write a log file to track the progress of a scanning run through time.

        Parameters
        ----------
        message : str
            Information to be saved to the log file

        """

        print(message)

        if log:
            subdir = "logs"
            util.make_directories(self.run, subdir=subdir)
            fname = (self.run / subdir / self.name).with_suffix(".log")
            with fname.open(mode="a") as f:
                f.write(message + "\n")
コード例 #7
0
ファイル: quakeplot.py プロジェクト: syzeng999/QuakeMigrate
    def event_summary(self, file_str=None):
        """
        Create summary plot for an event.

        Shows the coalescence map sliced through the maximum coalescence
        showing calculated locations and uncdrtainties, the coalescence value
        over the course of the marginal time window and a gather of the station
        traces.

        Parameters
        ----------
        file_str : str, optional
            String {run_name}_{event_name} (figure displayed by default)

        """

        # Event is only in first line of earthquake, reduces chars later on
        if self.event is not None:
            eq = self.event.iloc[0]
        else:
            msg = "\t\tError: no event specified!"
            print(msg)
            return

        dt_max = (self.event_mw_data["DT"].iloc[np.argmax(
            np.array(self.event_mw_data["COA"]))]).to_pydatetime()

        # Determining the marginal window value from the coalescence function
        coa_map = np.ma.masked_invalid(self.coa_map)
        loc = np.where(coa_map == np.nanmax(coa_map))
        point = np.array([[loc[0][0], loc[1][0], loc[2][0]]])
        crd = self.lut.coord2loc(point, inverse=True)

        # Defining the plots to be represented
        fig = plt.figure(figsize=(25, 15))
        fig.patch.set_facecolor("white")
        xy_slice = plt.subplot2grid((3, 5), (0, 0), colspan=2, rowspan=2)
        xz_slice = plt.subplot2grid((3, 5), (2, 0), colspan=2)
        yz_slice = plt.subplot2grid((3, 5), (0, 2), rowspan=2)
        trace = plt.subplot2grid((3, 5), (0, 3), colspan=2, rowspan=2)
        logo = plt.subplot2grid((3, 5), (2, 2))
        coal_val = plt.subplot2grid((3, 5), (2, 3), colspan=2)

        # --- Ordering by distance to event ---
        if self.range_order:
            ttp = self.lut.get_value_at("TIME_P", point[0])[0]
            sidx = abs(
                np.argsort(np.argsort(ttp)) -
                np.max(np.argsort(np.argsort(ttp))))
        else:
            sidx = np.argsort(self.data.stations)[::-1]

        for i in range(self.data.signal.shape[1]):
            if not self.filtered_signal:
                self._plot_signal_trace(trace,
                                        self.times,
                                        self.data.signal[0, i, :],
                                        sidx[i],
                                        color="r")
                self._plot_signal_trace(trace,
                                        self.times,
                                        self.data.signal[1, i, :],
                                        sidx[i],
                                        color="b")
                self._plot_signal_trace(trace,
                                        self.times,
                                        self.data.signal[2, i, :],
                                        sidx[i],
                                        color="g")
            else:
                self._plot_signal_trace(trace,
                                        self.times,
                                        self.data.filtered_signal[0, i, :],
                                        sidx[i],
                                        color="r")
                self._plot_signal_trace(trace,
                                        self.times,
                                        self.data.filtered_signal[1, i, :],
                                        sidx[i],
                                        color="b")
                self._plot_signal_trace(trace,
                                        self.times,
                                        self.data.filtered_signal[2, i, :],
                                        sidx[i],
                                        color="g")

        # --- Plotting the Station Travel Times ---
        ttime_range = self.lut.get_value_at("TIME_P", point[0])[0].shape[0]
        tps = []
        tss = []
        dt_max = UTCDateTime(dt_max)
        tmp_p = self.lut.get_value_at("TIME_P", point[0])
        tmp_s = self.lut.get_value_at("TIME_S", point[0])
        for i in range(ttime_range):
            tps.append((dt_max + tmp_p[0][i]).datetime)
            tss.append((dt_max + tmp_s[0][i]).datetime)

        del tmp_p, tmp_s

        self.tp_arrival = trace.scatter(tps, (sidx + 1),
                                        50,
                                        "pink",
                                        marker="v",
                                        zorder=4,
                                        linewidth=0.1,
                                        edgecolors="black")
        self.ts_arrival = trace.scatter(tss, (sidx + 1),
                                        50,
                                        "purple",
                                        marker="v",
                                        zorder=5,
                                        linewidth=0.1,
                                        edgecolors="black")

        # Set signal trace limits
        trace.set_xlim([(dt_max - 0.1).datetime,
                        (self.data.end_time - 0.8).datetime])
        trace.yaxis.tick_right()
        trace.yaxis.set_ticks(sidx + 1)
        trace.yaxis.set_ticklabels(self.data.stations)
        self.station_trace_vline = trace.axvline(dt_max.datetime,
                                                 0,
                                                 1000,
                                                 linestyle="--",
                                                 linewidth=2,
                                                 color="r")

        # --- Plotting the Coalescence Function ---
        self._plot_coalescence_value(coal_val, dt_max.datetime)

        # --- Determining Error ellipse for Covariance ---
        cov_x = eq["GlobalCovariance_ErrX"] / self.lut.cell_size[0]
        cov_y = eq["GlobalCovariance_ErrY"] / self.lut.cell_size[1]
        cov_z = eq["GlobalCovariance_ErrZ"] / self.lut.cell_size[2]

        cov_crd = np.array([[
            eq["GlobalCovariance_X"], eq["GlobalCovariance_Y"],
            eq["GlobalCovariance_Z"]
        ]])
        cov_loc = self.lut.coord2loc(cov_crd)
        dCo = abs(cov_crd - self.lut.coord2loc(np.array([[
            cov_loc[0][0] + cov_x, cov_loc[0][1] + cov_y, cov_loc[0][2] + cov_z
        ]]),
                                               inverse=True))

        ellipse_XY = Ellipse(
            (eq["GlobalCovariance_X"], eq["GlobalCovariance_Y"]),
            2 * dCo[0][0],
            2 * dCo[0][1],
            angle=0,
            linewidth=2,
            edgecolor="k",
            fill=False,
            label="Global Covariance Error Ellipse")
        ellipse_YZ = Ellipse(
            (eq["GlobalCovariance_Z"], eq["GlobalCovariance_Y"]),
            2 * dCo[0][2],
            2 * dCo[0][1],
            angle=0,
            linewidth=2,
            edgecolor="k",
            fill=False)
        ellipse_XZ = Ellipse(
            (eq["GlobalCovariance_X"], eq["GlobalCovariance_Z"]),
            2 * dCo[0][0],
            2 * dCo[0][2],
            angle=0,
            linewidth=2,
            edgecolor="k",
            fill=False)

        # --- Determining Error ellipse for Gaussian ---
        gau_x = eq["LocalGaussian_ErrX"] / self.lut.cell_size[0]
        gau_y = eq["LocalGaussian_ErrY"] / self.lut.cell_size[1]
        gau_z = eq["LocalGaussian_ErrZ"] / self.lut.cell_size[2]

        gau_crd = np.array([[
            eq["LocalGaussian_X"], eq["LocalGaussian_Y"], eq["LocalGaussian_Z"]
        ]])
        gau_loc = self.lut.coord2loc(gau_crd)
        dGa = abs(gau_crd - self.lut.coord2loc(np.array([[
            gau_loc[0][0] + gau_x, gau_loc[0][1] + gau_y, gau_loc[0][2] + gau_z
        ]]),
                                               inverse=True))

        gellipse_XY = Ellipse((eq["LocalGaussian_X"], eq["LocalGaussian_Y"]),
                              2 * dGa[0][0],
                              2 * dGa[0][1],
                              angle=0,
                              linewidth=2,
                              edgecolor="b",
                              fill=False,
                              label="Local Gaussian Error Ellipse")
        gellipse_YZ = Ellipse((eq["LocalGaussian_Z"], eq["LocalGaussian_Y"]),
                              2 * dGa[0][2],
                              2 * dGa[0][1],
                              angle=0,
                              linewidth=2,
                              edgecolor="b",
                              fill=False)
        gellipse_XZ = Ellipse((eq["LocalGaussian_X"], eq["LocalGaussian_Z"]),
                              2 * dGa[0][0],
                              2 * dGa[0][2],
                              angle=0,
                              linewidth=2,
                              edgecolor="b",
                              fill=False)

        # --- Plot slices through coalescence map ---
        self._plot_map_slice(xy_slice, eq, coa_map[:, :, int(loc[2][0])], crd,
                             "X", "Y", ellipse_XY, gellipse_XY)
        xy_slice.legend()

        self._plot_map_slice(xz_slice, eq, coa_map[:, int(loc[1][0]), :], crd,
                             "X", "Z", ellipse_XZ, gellipse_XZ)
        xz_slice.invert_yaxis()

        self._plot_map_slice(yz_slice, eq,
                             np.transpose(coa_map[int(loc[0][0]), :, :]), crd,
                             "Y", "Z", ellipse_YZ, gellipse_YZ)

        # --- Plotting the station locations ---
        xy_slice.scatter(self.lut.station_data["Longitude"],
                         self.lut.station_data["Latitude"],
                         15,
                         marker="^",
                         color=self.line_station_color)
        xz_slice.scatter(self.lut.station_data["Longitude"],
                         self.lut.station_data["Elevation"],
                         15,
                         marker="^",
                         color=self.line_station_color)
        yz_slice.scatter(self.lut.station_data["Elevation"],
                         self.lut.station_data["Latitude"],
                         15,
                         marker="<",
                         color=self.line_station_color)
        for i, txt in enumerate(self.lut.station_data["Name"]):
            xy_slice.annotate(txt, [
                self.lut.station_data["Longitude"][i],
                self.lut.station_data["Latitude"][i]
            ],
                              color=self.line_station_color)

        # --- Plotting the xy_files ---
        self._plot_xy_files(xy_slice)

        # --- Plotting the logo ---
        self._plot_logo(logo, r"Earthquake Location Error", 10)

        if file_str is None:
            plt.show()
        else:
            fig.suptitle("Event Origin Time = {}".format(dt_max.datetime))
            subdir = "summaries"
            util.make_directories(self.run_path, subdir=subdir)
            out_str = self.run_path / subdir / file_str
            plt.savefig("{}_EventSummary.pdf".format(out_str), dpi=400)
            plt.close("all")
コード例 #8
0
ファイル: quakeplot.py プロジェクト: syzeng999/QuakeMigrate
    def station_traces(self, file_str=None, event_name=None):
        """
        Plot figures showing the filtered traces for each data component
        and the characteristic functions calculated from them (P and S) for
        each station. The search window to make a phase pick is displayed,
        along with the dynamic pick threshold (defined as a percentile of the
        background noise level), the phase pick time and its uncertainty (if
        made) and the gaussian fit to the characteristic function.

        Parameters
        ----------
        file_str : str, optional
            String {run_name}_{evt_id} (figure displayed by default)

        event_name : str, optional
            Earthquake UID string; for subdirectory naming within directory
            {run_path}/traces/

        """

        # This function currently doesn't work due to a float/int issue
        # point = np.round(self.lut.coord2loc(np.array([[event["X"],
        #                                                event["Y"],
        #                                                event["Z"]]]))).astype(int)

        loc = np.where(self.coa_map == np.nanmax(self.coa_map))
        point = np.array([[loc[0][0], loc[1][0], loc[2][0]]])

        # Get P- and S-traveltimes at this location
        ptt = self.lut.get_value_at("TIME_P", point)[0]
        stt = self.lut.get_value_at("TIME_S", point)[0]

        # Make output dir for this event outside of loop
        if file_str:
            subdir = "traces"
            util.make_directories(self.run_path, subdir=subdir)
            out_dir = self.run_path / subdir / event_name
            util.make_directories(out_dir)

        # Looping through all stations
        for i in range(self.data.signal.shape[1]):
            station = self.lut.station_data["Name"][i]
            gau_p = self.phase_picks["GAU_P"][i]
            gau_s = self.phase_picks["GAU_S"][i]
            fig = plt.figure(figsize=(30, 15))

            # Defining the plot
            fig.patch.set_facecolor("white")
            x_trace = plt.subplot(322)
            y_trace = plt.subplot(324)
            z_trace = plt.subplot(321)
            p_onset = plt.subplot(323)
            s_onset = plt.subplot(326)

            # Plotting the traces
            self._plot_signal_trace(x_trace, self.times,
                                    self.data.filtered_signal[0,
                                                              i, :], -1, "r")
            self._plot_signal_trace(y_trace, self.times,
                                    self.data.filtered_signal[1,
                                                              i, :], -1, "b")
            self._plot_signal_trace(z_trace, self.times,
                                    self.data.filtered_signal[2,
                                                              i, :], -1, "g")
            p_onset.plot(self.times,
                         self.data.p_onset[i, :],
                         "r",
                         linewidth=0.5)
            s_onset.plot(self.times,
                         self.data.s_onset[i, :],
                         "b",
                         linewidth=0.5)

            # Defining Pick and Error
            picks = self.phase_picks["Pick"]
            phase_picks = picks[picks["Name"] == station].replace(-1, np.nan)
            phase_picks = phase_picks.reset_index(drop=True)

            for j, pick in phase_picks.iterrows():
                if np.isnan(pick["PickError"]):
                    continue

                pick_time = pick["PickTime"]
                pick_err = pick["PickError"]

                if pick["Phase"] == "P":
                    self._pick_vlines(z_trace, pick_time, pick_err)

                    yy = util.gaussian_1d(gau_p["xdata"], gau_p["popt"][0],
                                          gau_p["popt"][1], gau_p["popt"][2])
                    gau_dts = [x.datetime for x in gau_p["xdata_dt"]]
                    p_onset.plot(gau_dts, yy)
                    self._pick_vlines(p_onset, pick_time, pick_err)
                else:
                    self._pick_vlines(y_trace, pick_time, pick_err)
                    self._pick_vlines(x_trace, pick_time, pick_err)

                    yy = util.gaussian_1d(gau_s["xdata"], gau_s["popt"][0],
                                          gau_s["popt"][1], gau_s["popt"][2])
                    gau_dts = [x.datetime for x in gau_s["xdata_dt"]]
                    s_onset.plot(gau_dts, yy)
                    self._pick_vlines(s_onset, pick_time, pick_err)

            dt_max = self.event_mw_data["DT"].iloc[np.argmax(
                np.array(self.event_mw_data["COA"]))]
            dt_max = UTCDateTime(dt_max)
            self._ttime_vlines(z_trace, dt_max, ptt[i])
            self._ttime_vlines(p_onset, dt_max, ptt[i])
            self._ttime_vlines(y_trace, dt_max, stt[i])
            self._ttime_vlines(x_trace, dt_max, stt[i])
            self._ttime_vlines(s_onset, dt_max, stt[i])

            p_onset.axhline(gau_p["PickThreshold"])
            s_onset.axhline(gau_s["PickThreshold"])

            # Refining the window as around the pick time
            min_t = (dt_max + 0.5 * ptt[i]).datetime
            max_t = (dt_max + 1.5 * stt[i]).datetime

            x_trace.set_xlim([min_t, max_t])
            y_trace.set_xlim([min_t, max_t])
            z_trace.set_xlim([min_t, max_t])
            p_onset.set_xlim([min_t, max_t])
            s_onset.set_xlim([min_t, max_t])

            suptitle = "Trace for Station {} - PPick = {}, SPick = {}"
            suptitle = suptitle.format(station, gau_p["PickValue"],
                                       gau_s["PickValue"])

            fig.suptitle(suptitle)

            if file_str is None:
                plt.show()
            else:
                out_str = out_dir / file_str
                fname = "{}_{}.pdf"
                fname = fname.format(out_str, station)
                plt.savefig(fname)
                plt.close("all")
コード例 #9
0
    def write_cut_waveforms(self,
                            data,
                            event,
                            event_name,
                            data_format="MSEED",
                            pre_cut=None,
                            post_cut=None):
        """
        Output raw cut waveform data as a waveform file -- defaults to mSEED.

        Parameters
        ----------
        data : Archive object
            Contains read_waveform_data() method and stores read data in raw
            and processed state

        event : pandas DataFrame
            Final event location information.
            Columns = ["DT", "COA", "X", "Y", "Z",
                       "LocalGaussian_X", "LocalGaussian_Y", "LocalGaussian_Z",
                       "LocalGaussian_ErrX", "LocalGaussian_ErrY",
                       "LocalGaussian_ErrZ", "GlobalCovariance_X",
                       "GlobalCovariance_Y", "GlobalCovariance_Z",
                       "GlobalCovariance_ErrX", "GlobalCovariance_ErrY",
                       "GlobalCovariance_ErrZ"]
            All X / Y as lon / lat; Z and X / Y / Z uncertainties in metres

        event_name : str
            event_uid for file naming

        format : str, optional
            File format to write waveform data to. Options are all file formats
            supported by obspy, including: "MSEED" (default), "SAC", "SEGY",
            "GSE2"

        pre_cut : float, optional
            Specify how long before the event origin time to cut the waveform
            data from

        post_cut : float, optional
            Specify how long after the event origin time to cut the waveform
            data to

        """

        st = data.raw_waveforms

        otime = UTCDateTime(event["DT"])
        if pre_cut:
            for tr in st.traces:
                tr.trim(starttime=otime - pre_cut)
        if post_cut:
            for tr in st.traces:
                tr.trim(endtime=otime + post_cut)

        subdir = "cut_waveforms"
        util.make_directories(self.run, subdir=subdir)
        fname = self.run / subdir / "{}".format(event_name)

        if data_format == "MSEED":
            suffix = ".m"
        elif data_format == "SAC":
            suffix = ".sac"
        elif data_format == "SEGY":
            suffix = ".segy"
        elif data_format == "GSE2":
            suffix = ".gse2"
        else:
            suffix = ".waveforms"

        fname = str(fname.with_suffix(suffix))
        st.write(str(fname), format=data_format)  # , encoding="STEIM1")