diff --git a/docs/README b/docs/README index 732d3375c..5e1130515 100644 --- a/docs/README +++ b/docs/README @@ -14,7 +14,7 @@ HOW TO UPDATE DOCS >> ./build.bash -3. If build fails with "Encountered unknown tag 'do', then try the following: +3. If build fails with "Encountered unknown tag 'do'", try the following: Modify the sphinx autosummary source code by adding 'jinja2.ext.do' to the jinja Environment() extensions list diff --git a/docs/install/issues.rst b/docs/install/issues.rst index 14fc4664e..5ac380216 100644 --- a/docs/install/issues.rst +++ b/docs/install/issues.rst @@ -31,13 +31,13 @@ We note that some versions of GMT and ObsPy do not plot `full moment tensors `_ dependency solver, which was `adopted `_ in the 23.10 release. +For reference, the largest potential speed up comes from the new `mamba `_ dependency solver, which was `adopted `_ in the 23.10 release. diff --git a/docs/user_guide/03.rst b/docs/user_guide/03.rst index d66655088..90b119556 100644 --- a/docs/user_guide/03.rst +++ b/docs/user_guide/03.rst @@ -2,7 +2,7 @@ Acquiring Green's functions =========================== -The response of a medium to an impulsive source is called a Green's function. This page describes the role of Green's functions in source inversions, the types of Green's functions supported by MTUQ, and how these types can be obtained. +The response of a medium to an impulsive source is called a Green's function. This page describes the role of Green's functions in source inversions, the types of Green's functions supported by MTUQ, and how these different types can each be obtained. Role of Green's functions @@ -10,15 +10,21 @@ Role of Green's functions By combining Green's functions, it is possible to obtain synthetics from any moment tensor or force source. Generating synthetics in this way is useful because it provides cost savings compared with on-the-fly wavefield simulations. Synthetics can then be compared with data to determine a best-fitting source. - - `GreensTensor` objects ---------------------- -`GreensTensor `_ objects provide access to a set of Green's functions describing the medium response between a given station and origin. +`GreensTensor `_ objects provide access to a set of Green's functions describing the medium response between a given hypocenter and station. + +Methods built into the `GreensTensor` class allow data processing and synthetics generation. In particular, the `get_synthetics `_ method accepts a `MomentTensor` or `Force` and returns corresponding synthetics. + + -Methods built into the `GreensTensor` class allow data processing and synthetics generation. In particular, the `get_synthetics `_ method accepts a `MomentTensor` or `Force` and returns corresponding synthetics for the given station. +Green's function conventions +---------------------------- + +A major goal of MTUQ is to avoid exposing users to unnecessary complexity. For Green's functions, MTUQ tries to accomplish this by understanding external conventions and converting to a common internal format. Specifically, MTUQ uses an `up-south-east` `convention `_ for internally storing impulse responses corresponding to individual force couples. (Moment tensors and forces are internally represented using the same `up-south-east` basis.) +Under the hood, MTUQ deals with a variety of external conventions related to (1) the symmetry of the medium (for example, 1D media require fewer independent Green's functions than 3D media); (2) the choice of local Cartesian basis convention (for example, some authors employ `up-south-east`, others `north-east-down`). A sense of what's involved can be obtained by browsing the `source code `_ and references therein. @@ -34,7 +40,7 @@ To download AK135 Green's functions and generate MTUQ `GreensTensor` objects: from mtuq import download_greens_functions greens_tensors = download_greens_functions(stations, origins, model="ak135f_2s") -A limitation of syngine is that Green's functions can be downloaded only on a station-by-station basis, not over an entire subset of Earth. An alternative that avoids this limitation is to compute your own Green's functions. +A limitation of syngine is that Green's functions can be downloaded only on a station-by-station basis, not over an entire area or volume. An alternative that avoids this limitation is to compute your own Green's functions. @@ -44,7 +50,9 @@ Computing Green's functions from 1D Earth models MTUQ supports the following 1D Green's functions formats: AxiSEM (preferred) and FK. -`AxiSEM `_ performs spectral element wave simulations in radially-symmetric Earth models. To generate synthetics in a format MTUQ natively supports, follow the instructions for in the `AxiSEM user manual `_ under "Output wavefields in NetCDF formated needed by instaseis." AxiSEM NetCDF files can be used to retrieve vertical, radial, and transverse displacement in units of m*(N-m)^-1. +`AxiSEM `_ performs spectral element wave simulations in radially-symmetric Earth models. AxiSEM NetCDF files can be used to retrieve vertical, radial, and transverse displacement in units of m*(N-m)^-1. + +To generate AxiSEM synthetics in a format MTUQ supports, follow the instructions in the `AxiSEM user manual `_ under "Output wavefields in NetCDF format needed by instaseis." To open an AxiSEM database client in MTUQ: @@ -81,60 +89,50 @@ Computing Green's functions from 3D Earth models MTUQ currently supports 3D Green's functions from SPECFEM3D/3D_GLOBE. -To generate a complete Green's function database for a given hypocenter and depth, six SPECFEM3D wavefield simulations are required. Output must be saved as/converted to SAC files at individual stations using the following filename convention, which comes from `GRD_CMT3D `_. Place all SAC files corresponding to a single hypocenter and depth in the same directory as follows: +To generate a full set of Green's functions for a given hypocenter and depth, six SPECFEM3D/3D_GLOBE wavefield simulations are required. Output must be saved as/converted to SAC files at individual stations using the following filename convention, which comes from `GRD_CMT3D `_. Place all SAC files corresponding to a single hypocenter and depth in the same directory as follows: .. code :: - {basedir}/{event_id}/ - {net}.{sta}.{loc}.Z.Mrr.sac - {net}.{sta}.{loc}.Z.Mtt.sac - {net}.{sta}.{loc}.Z.Mpp.sac - {net}.{sta}.{loc}.Z.Mrt.sac - {net}.{sta}.{loc}.Z.Mrp.sac - {net}.{sta}.{loc}.Z.Mtp.sac - {net}.{sta}.{loc}.R.Mrr.sac - {net}.{sta}.{loc}.R.Mtt.sac - {net}.{sta}.{loc}.R.Mpp.sac - {net}.{sta}.{loc}.R.Mrt.sac - {net}.{sta}.{loc}.R.Mrp.sac - {net}.{sta}.{loc}.R.Mtp.sac - {net}.{sta}.{loc}.T.Mrr.sac - {net}.{sta}.{loc}.T.Mtt.sac - {net}.{sta}.{loc}.T.Mpp.sac - {net}.{sta}.{loc}.T.Mrt.sac - {net}.{sta}.{loc}.T.Mrp.sac - {net}.{sta}.{loc}.T.Mtp.sac - - -To open an SPECFEM3D database client in MTUQ: + {event_id}/ + {depth_in_m}/ + {net}.{sta}.{loc}.Z.Mrr.sac + {net}.{sta}.{loc}.Z.Mtt.sac + {net}.{sta}.{loc}.Z.Mpp.sac + {net}.{sta}.{loc}.Z.Mrt.sac + {net}.{sta}.{loc}.Z.Mrp.sac + {net}.{sta}.{loc}.Z.Mtp.sac + {net}.{sta}.{loc}.R.Mrr.sac + {net}.{sta}.{loc}.R.Mtt.sac + {net}.{sta}.{loc}.R.Mpp.sac + {net}.{sta}.{loc}.R.Mrt.sac + {net}.{sta}.{loc}.R.Mrp.sac + {net}.{sta}.{loc}.R.Mtp.sac + {net}.{sta}.{loc}.T.Mrr.sac + {net}.{sta}.{loc}.T.Mtt.sac + {net}.{sta}.{loc}.T.Mpp.sac + {net}.{sta}.{loc}.T.Mrt.sac + {net}.{sta}.{loc}.T.Mrp.sac + {net}.{sta}.{loc}.T.Mtp.sac + + +To open a SPECFEM3D/3D_GLOBE database client: -.. code :: +.. code:: from mtuq import open_db db = open_db(path_SPECFEM3D_output_directory, format="SPECFEM3D") -Once opened, a SPECFEM3D database client can be used to generate `GreensTensor `_ objects as follows: +Once opened, the database client can be used to generate `GreensTensor `_ objects as follows: .. code:: greens_tensors = db.get_greens_tensors(stations, origin) +For more information, see also: -Green's function conventions ----------------------------- - -A variety of Green's function conventions exist. Figuring out which are used in a particular application can be challenging because it depends on - -- the type of medium under consideration (for example, acoustic media require fewer independent Green's functions than elastic media) - -- the symmetry of the medium (for example, 1D media require fewer independent Green's functions than 3D media) - -- the choice of local Cartesian basis conventions (for example, some authors employ `up-south-east`, others `north-east-down`; see `ObsPy documentation `_ for more information) - -A major goal is to avoid exposing users to unnecessary basis complexity. MTUQ accomplishes this by understanding external formats and converting to a common internal format that works for both 1D and 3D media. - -For internally storing moment tensors, forces, and Green's functions, MTUQ consistently uses an `up-south-east` Cartesian convention. +`Source-side Green's function details (under construction) `_ +`Receiver-side Green's function details (under construction) `_ diff --git a/docs/user_guide/03/receiver_side.rst b/docs/user_guide/03/receiver_side.rst new file mode 100644 index 000000000..c13fdc2c6 --- /dev/null +++ b/docs/user_guide/03/receiver_side.rst @@ -0,0 +1,14 @@ + +.. warning:: + + This page is still under construction. To help improve the + documentation, feel free to submit a pull request. + + +Receiver-side 3D Green's functions +================================== + +A working of example using receiver-side 3D Green's functions from SPECFEM3D in a moment tensor inversion: + +`test_greens_SPECFEM3D_SGT.py `_ + diff --git a/docs/user_guide/03/source_side.rst b/docs/user_guide/03/source_side.rst new file mode 100644 index 000000000..b43c17f12 --- /dev/null +++ b/docs/user_guide/03/source_side.rst @@ -0,0 +1,186 @@ + +.. warning:: + + This page is still under construction. To help improve the + documentation, feel free to submit a pull request. + +Source-side 3D Green's functions +================================ + +Generating source-side 3D Green's functions using SPECFEM3D/3D_GLOBE +-------------------------------------------------------------------- + +In principle, any 3D solver can be used to generate Green's functions, as long as the `requirements `_ below are satisfied. + +So far, however, the source-side Green's function machinery has been tested using only SPECFEM3D/3D_GLOBE. To convert SPECFEM3D/3D_GLOBE output to MTUQ-compliant Green's functions, the following steps are necessary. + + +**Generate SAC binary files** + +SAC binary output format is natively supported by SPECFEM3D_GLOBE (in the parameter file, set `OUTPUT_SEISMOS_SAC_BINARY = .true.`). + +Unfortunately, SAC binary output format is not natively supported by SPECFEM3D, so it becomes necessary to manually convert SPECFEM3D output to SAC binary format. + + +**Convert to SI units** + +MTUQ uses the fully SI convention described below. In contrast, SPECFEM3D/3D_GLOBE use a mixed SI and CGS convention, in which moment tensor elements are input in terms of dynes and centimeters, and seismograms are output in meters. As a result, it is necessary to scale SPECFEM3D/3D_GLOBE seismograms by 10^7 prior to using them as MTUQ Green's functions. + + +**Additional amplitude scaling** + +In addition to converting to SI units, it is also necessary to account for any scaling factors in the SPECFEM3D/3D_GLOBE input files. Such scaling factors can enter, for example, through the `M_rr,M_tt,M_pp,M_rt,M_rp,M_tp` values in the moment tensor input file or through the `scaling factor `_ in the force input file. + + +**Rotate to vertical, radial, transverse components** + +Conveniently, SPECFEM3D_GLOBE can be made to automatically rotate output seismograms into vertical, radial and transverse components (set `ROTATE_SEISMOGRAMS_RT = .true.` in the parameter file). + +No modifications are necessary on account of moment tensor basis convention, since MTUQ's `up-south-east` convention matches SPECFEM3D/3D_GLOBE's. + + + + +Requirements for MTUQ source-side 3D Green's functions +------------------------------------------------------ + +**File format** + +Individual Green's functions must be written to SAC binary files. + +A total 18 SAC binary files are required to represent the response between a given hypocenter and station (corresponding to 6 moment tensor elements times 3 directions of motion). + + + +**Units convention** + +For a moment tensor inversion, each SAC binary file must give the response in meters to a 1 Newton-meter force couple. + +For a force inversion, each SAC binary file must give the response in meters to a 1 Newton force. + +In both cases, MTUQ uses a fully SI units convention (compare with SPECFEM3D/3D_GLOBE notes, above). + + + +**Basis convention** + +MTUQ uses an `up-south-east` basis convention in which `r` denotes up, `t` denotes south, and `p` denotes east. + +Green's functions must be rotated into into vertical `Z`, radial `R` and transverse `T` components relative to the source-receiver backazimuth. + +Place all seismograms for the same hypocenter in a single directory as follows: + +.. code :: + + {event_id}/ + {depth_in_km}/ + {net}.{sta}.{loc}.Z.Mrr.sac + {net}.{sta}.{loc}.Z.Mtt.sac + {net}.{sta}.{loc}.Z.Mpp.sac + {net}.{sta}.{loc}.Z.Mrt.sac + {net}.{sta}.{loc}.Z.Mrp.sac + {net}.{sta}.{loc}.Z.Mtp.sac + {net}.{sta}.{loc}.R.Mrr.sac + {net}.{sta}.{loc}.R.Mtt.sac + {net}.{sta}.{loc}.R.Mpp.sac + {net}.{sta}.{loc}.R.Mrt.sac + {net}.{sta}.{loc}.R.Mrp.sac + {net}.{sta}.{loc}.R.Mtp.sac + {net}.{sta}.{loc}.T.Mrr.sac + {net}.{sta}.{loc}.T.Mtt.sac + {net}.{sta}.{loc}.T.Mpp.sac + {net}.{sta}.{loc}.T.Mrt.sac + {net}.{sta}.{loc}.T.Mrp.sac + {net}.{sta}.{loc}.T.Mtp.sac + ... + +The corresponding convention for force responses is: + +.. code :: + + {event_id}/ + {depth_in_km}/ + {net}.{sta}.{loc}.Z.Fr.sac + {net}.{sta}.{loc}.Z.Ft.sac + {net}.{sta}.{loc}.Z.Fp.sac + {net}.{sta}.{loc}.R.Fr.sac + {net}.{sta}.{loc}.R.Ft.sac + {net}.{sta}.{loc}.R.Fp.sac + {net}.{sta}.{loc}.T.Fr.sac + {net}.{sta}.{loc}.T.Fp.sac + {net}.{sta}.{loc}.T.Fp.sac + ... + + +**Origin time convention** + +For origin time, MTUQ uses a centroid convention (`more details `_), so that `t=0` in the `GreensTensor` time discretization corresponds to mean source excitation time. + +MTUQ uses the begin time (`B`) and end time (`E`) headers from the SAC binary files to align the Green's functions relative to centroid origin time. + +Currently, these are the only SAC headers used in reading Green's functions. + +(Note that different `SAC headers `_ are required in reading `observed data `_.) + + + +Hypocenter searches (experimental) +---------------------------------- + +Currently, only searches over source depth are possible with source-side 3D Green's functions (no other hypocenter parameters). + +The current `depth search `_ implementation is especially crude and experimental (consider local modifications to suit your needs). + +To allow depth searches, create subdirectories for each centroid depth as follows: + +.. code :: + + {event_id}/ + {depth_in_km}/ + {net}.{sta}.{loc}.Z.Mrr.sac + {net}.{sta}.{loc}.Z.Mtt.sac + {net}.{sta}.{loc}.Z.Mpp.sac + {net}.{sta}.{loc}.Z.Mrt.sac + {net}.{sta}.{loc}.Z.Mrp.sac + {net}.{sta}.{loc}.Z.Mtp.sac + {net}.{sta}.{loc}.R.Mrr.sac + {net}.{sta}.{loc}.R.Mtt.sac + {net}.{sta}.{loc}.R.Mpp.sac + {net}.{sta}.{loc}.R.Mrt.sac + {net}.{sta}.{loc}.R.Mrp.sac + {net}.{sta}.{loc}.R.Mtp.sac + {net}.{sta}.{loc}.T.Mrr.sac + {net}.{sta}.{loc}.T.Mtt.sac + {net}.{sta}.{loc}.T.Mpp.sac + {net}.{sta}.{loc}.T.Mrt.sac + {net}.{sta}.{loc}.T.Mrp.sac + {net}.{sta}.{loc}.T.Mtp.sac + {depth_in_km}/ + {net}.{sta}.{loc}.Z.Mrr.sac + {net}.{sta}.{loc}.Z.Mtt.sac + {net}.{sta}.{loc}.Z.Mpp.sac + {net}.{sta}.{loc}.Z.Mrt.sac + {net}.{sta}.{loc}.Z.Mrp.sac + {net}.{sta}.{loc}.Z.Mtp.sac + {net}.{sta}.{loc}.R.Mrr.sac + {net}.{sta}.{loc}.R.Mtt.sac + {net}.{sta}.{loc}.R.Mpp.sac + {net}.{sta}.{loc}.R.Mrt.sac + {net}.{sta}.{loc}.R.Mrp.sac + {net}.{sta}.{loc}.R.Mtp.sac + {net}.{sta}.{loc}.T.Mrr.sac + {net}.{sta}.{loc}.T.Mtt.sac + {net}.{sta}.{loc}.T.Mpp.sac + {net}.{sta}.{loc}.T.Mrt.sac + {net}.{sta}.{loc}.T.Mrp.sac + {net}.{sta}.{loc}.T.Mtp.sac + ... + + +Working example +--------------- + +A working of example using source-side 3D Green's functions from SPECFEM3D_GLOBE in a moment tensor inversion: + +`test_greens_SPECFEM3D_SAC.py `_ + diff --git a/docs/user_guide/05/gallery_force.rst b/docs/user_guide/05/gallery_force.rst index deaa33576..1383e0757 100644 --- a/docs/user_guide/05/gallery_force.rst +++ b/docs/user_guide/05/gallery_force.rst @@ -33,6 +33,10 @@ For a grid of regulary-spaced forces, `ds` may look something like: * origin_idx (origin_idx) int64 0 +.. note:: + + Force grids are implemented using parameters `F0, phi, h`, which are related to `r, phi, theta` spherical coordinates (`physics convention `_) by `F0 = r`, `phi = phi`, `h = cos(theta)`. In addition, `F0, phi, h` are related to geographic directions by these `formulas `_. + Misfit values """"""""""""" diff --git a/docs/user_guide/05/gallery_mt.rst b/docs/user_guide/05/gallery_mt.rst index 8b57c8d84..ff9880e58 100644 --- a/docs/user_guide/05/gallery_mt.rst +++ b/docs/user_guide/05/gallery_mt.rst @@ -37,6 +37,12 @@ For a grid of regulary-spaced moment tensors, `ds` may look something like: +.. note:: + + Moment tensor grids are implemented using the `rho, v, w, kappa, sigma, h` parameterization of `Tape2012 `_ and `Tape2015 `_, from which `formulas `_ converting to parameterizations can be derived. + + + Misfit values """"""""""""" diff --git a/docs/user_guide/06/trace_attributes.rst b/docs/user_guide/06/trace_attributes.rst index 41014330e..5e267d2f9 100644 --- a/docs/user_guide/06/trace_attributes.rst +++ b/docs/user_guide/06/trace_attributes.rst @@ -2,7 +2,7 @@ Trace attributes ================ -At various points during an inversion, waveform differences, phase shifts, and other values are calculated from observed and synthetic seismic traces. Such `trace attribute` quantities provide important information about how data misfit varies by geographic location and seismic component. +Waveform differences, time-shift corrections, and other values are calculated during an inversion on a trace-by-trace basis. Such `trace attributes` provide important information about how data misfit varies by geographic location and seismic component. Collecting trace attributes diff --git a/mtuq/greens_tensor/CPS.py b/mtuq/greens_tensor/CPS.py new file mode 100644 index 000000000..ba229c6e0 --- /dev/null +++ b/mtuq/greens_tensor/CPS.py @@ -0,0 +1,109 @@ + +import obspy +import numpy as np + +from mtuq.greens_tensor.base import GreensTensor as GreensTensorBase + + + +print('WARNING: CPS Greens functions are not fully tested yet') + + + +class GreensTensor(GreensTensorBase): + """ + FK Green's tensor object + + Overloads base class with machinery for working with CPS-style + Green's functions + + """ + def __init__(self, *args, **kwargs): + super(GreensTensor, self).__init__(*args, **kwargs) + + if 'type:greens' not in self.tags: + self.tags += ['type:greens'] + + if 'type:velocity' not in self.tags: + self.tags += ['type:velocity'] + + if 'units:m' not in self.tags: + self.tags += ['units:m'] + + def _precompute(self): + """ Computes NumPy arrays used by get_synthetics + """ + if self.include_mt: + self._precompute_mt() + + if self.include_force: + self._precompute_force() + + + def _precompute_mt(self): + """ Recombines CPS time series so they can be used in straightforward + linear combination with Mrr,Mtt,Mpp,Mrt,Mrp,Mtp + """ + + array = self._array + phi = np.deg2rad(self.azimuth) + _j = 0 + + # The formulas below were obtained by reverse engineering FK + + for _i, component in enumerate(self.components): + if component=='Z': + ZSS = self.select(channel="ZSS")[0].data + ZDS = self.select(channel="ZDS")[0].data + ZDD = self.select(channel="ZDD")[0].data + ZEP = self.select(channel="ZEP")[0].data + array[_i, _j+0, :] = ZSS/2. * np.cos(2*phi) - ZDD/6. + ZEP/3. + array[_i, _j+1, :] = -ZSS/2. * np.cos(2*phi) - ZDD/6. + ZEP/3. + array[_i, _j+2, :] = ZDD/3. + ZEP/3. + array[_i, _j+3, :] = ZSS * np.sin(2*phi) + array[_i, _j+4, :] = ZDS * np.cos(phi) + array[_i, _j+5, :] = ZDS * np.sin(phi) + + elif component=='R': + RSS = self.select(channel="RSS")[0].data + RDS = self.select(channel="RDS")[0].data + RDD = self.select(channel="RDD")[0].data + REP = self.select(channel="REP")[0].data + array[_i, _j+0, :] = RSS/2. * np.cos(2*phi) - RDD/6. + REP/3. + array[_i, _j+1, :] = -RSS/2. * np.cos(2*phi) - RDD/6. + REP/3. + array[_i, _j+2, :] = RDD/3. + REP/3. + array[_i, _j+3, :] = RSS * np.sin(2*phi) + array[_i, _j+4, :] = RDS * np.cos(phi) + array[_i, _j+5, :] = RDS * np.sin(phi) + + elif component=='T': + TSS = self.select(channel="TSS")[0].data + TDS = self.select(channel="TDS")[0].data + array[_i, _j+0, :] = TSS/2. * np.sin(2*phi) + array[_i, _j+1, :] = -TSS/2. * np.sin(2*phi) + array[_i, _j+2, :] = 0. + array[_i, _j+3, :] = -TSS * np.cos(2*phi) + array[_i, _j+4, :] = TDS * np.sin(phi) + array[_i, _j+5, :] = -TDS * np.cos(phi) + + else: + raise ValueError + + # + # CPS uses a north-east-down basis convention, while mtuq uses an + # up-south-east basis convention, so a permutation is necessary + # + array_copy = array.copy() + array[:, 0, :] = array_copy[:, 2, :] + array[:, 1, :] = array_copy[:, 0, :] + array[:, 2, :] = array_copy[:, 1, :] + array[:, 3, :] = array_copy[:, 4, :] + array[:, 4, :] = -array_copy[:, 5, :] + array[:, 5, :] = -array_copy[:, 3, :] + + + def _precompute_force(self): + raise NotImplementedError() + + + diff --git a/mtuq/greens_tensor/base.py b/mtuq/greens_tensor/base.py index 34c5cfea1..3ec868d4a 100644 --- a/mtuq/greens_tensor/base.py +++ b/mtuq/greens_tensor/base.py @@ -471,7 +471,7 @@ def sort_by_azimuth(self, reverse=False): def sort_by_function(self, function, reverse=False): - """ Sorts in-place using the python built-in `sort` + """ Sorts in-place by user-supplied function """ self.sort(key=function, reverse=reverse) diff --git a/mtuq/misfit/polarity.py b/mtuq/misfit/polarity.py index 401284de3..08021f4ed 100644 --- a/mtuq/misfit/polarity.py +++ b/mtuq/misfit/polarity.py @@ -58,9 +58,9 @@ class PolarityMisfit(object): .. rubric:: Other input arguments that may be required, depending on the above ``taup_model`` (`str`): Name of built-in ObsPy TauP model or path to custom - ObsPy TauP model, required for `type=taup` + ObsPy TauP model, required for `method=taup` - ``FK_database`` (`str`): Path to FK database, required for for `type=FK_metadata`. + ``FK_database`` (`str`): Path to FK database, required for for `method=FK_metadata`. .. note:: diff --git a/tests/check_urls.bash b/tests/check_urls.bash index 9053377f3..f712d96b5 100755 --- a/tests/check_urls.bash +++ b/tests/check_urls.bash @@ -10,8 +10,9 @@ URLS="\ https://www.eas.slu.edu/People/LZhu/home.html\ https://github.com/geodynamics/axisem\ https://github.com/Liang-Ding/seisgen\ - http://ds.iris.edu/ds/products/syngine\ - http://ds.iris.edu/ds/products/syngine/#models\ + https://ds.iris.edu/ds/products/syngine\ + https://ds.iris.edu/ds/products/syngine/#models\ + https://ds.iris.edu/files/sac-manual/manual/file_format.html\ https://instaseis.net\ https://docs.obspy.org/tutorial/index.html\ https://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.html\ @@ -20,6 +21,8 @@ URLS="\ https://docs.xarray.dev/en/stable/generated/xarray.DataArray.html\ https://github.com/uafgeotools/mtuq/blob/master/docs/user_guide/05/code/gallery_mt.py https://github.com/uafgeotools/mtuq/blob/master/docs/user_guide/05/code/gallery_force.py + https://conda.org/blog/2023-11-06-conda-23-10-0-release\ + https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community\ " diff --git a/tests/test_time_shifts.py b/tests/test_time_shifts.py index 0a6b31374..2c5db6a25 100644 --- a/tests/test_time_shifts.py +++ b/tests/test_time_shifts.py @@ -161,13 +161,16 @@ def __call__(self, traces): return super(ProcessData, self).__call__( traces, station=station, origin=origin) + + # + # plotting functions + # def _plot_dat(axis, t, data, attrs, pathspec='-k'): stream = data[0] trace = data[0][0] stats = trace.stats axis.plot(t, trace.data, pathspec) - def _plot_syn(axis, t, data, attrs, pathspec='-r'): stream = data[0] trace = data[0][0] @@ -176,7 +179,6 @@ def _plot_syn(axis, t, data, attrs, pathspec='-r'): idx2 = attrs.idx_stop axis.plot(t, trace.data[idx1:idx2], pathspec) - def _annotate(axis, attrs): text = 'static_shift: %.1f' % attrs.static_shift pyplot.text(0.02, 0.85, text, transform=axis.transAxes) @@ -187,15 +189,12 @@ def _annotate(axis, attrs): text = 'total_shift: %.1f' % attrs.total_shift pyplot.text(0.02, 0.55, text, transform=axis.transAxes) - def _get_synthetics(greens, mt): return greens.get_synthetics(mt, components=['Z']) - def _get_attrs(data, greens, misfit): return misfit.collect_attributes(data, greens, mt)[0]['Z'] - def _get_time_sampling(data): stream = data[0] t1 = float(stream[0].stats.starttime)