Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging Wenjie's edits from years ago #20

Open
wants to merge 42 commits into
base: master
Choose a base branch
from

Conversation

lsawade
Copy link

@lsawade lsawade commented Sep 14, 2023

Hi @bch0w !

I'm reorganizing some of my packages, one of which depends on some of the edits Wenjie made years ago. I have merged them in a hopefully non-conflicting way. They work with my workflows, and tests are passing, but I think it would be good if you double check this with your workflows.

Cheers,

Lucas

wjlei1990 and others added 30 commits January 27, 2015 13:39
Two tests are still not passed:
1) code formatting: going to rebase to fix this problem
2) figure for tests should be replaced in the future
Conflicts:
	src/pyflex/tests/test_pyflex.py
	src/pyflex/window_selector.py
…tion

1) modify `calculate_preliminary` to check the signal region instead
2) add `reject_on_noise_region`, split from `reject_on_selection_mode`
3) add selection_mode=`custom` for user customization
@bch0w
Copy link
Member

bch0w commented Sep 14, 2023

Thanks @lsawade! Good to have those changes merged back into the repo, I appreciate you making the effort!
I'll review the changes when I get a chance and try this out with my workflow codes.

@bch0w
Copy link
Member

bch0w commented Nov 30, 2023

Hey @lsawade, just wanted to let you know this is still on my to-do list! Apologies for the long wait

@lsawade
Copy link
Author

lsawade commented Nov 30, 2023

All good! I found a bug that was introduced by the merged anyways!

@lsawade
Copy link
Author

lsawade commented Jan 29, 2024

Accidentally clicked resolve...

@lsawade
Copy link
Author

lsawade commented Jan 29, 2024

Have to do it tonight, traveling rn

@bch0w
Copy link
Member

bch0w commented Jan 29, 2024

Woops, sorry if you're getting emails for all these comments, I'm just going through the PR now, will leave a longer message when I finish looking through. And no rush!

edit: that was my bad, I was leaving single comments and not putting all into one review, hopefully you do not get inundated by future stuff!

Copy link
Member

@bch0w bch0w left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @lsawade, thanks again for pushing these through and sorry again for how long it's taken me to get to it! Also sorry for harassing you with notifications when I first started the review :D

I've just gone through the diffs and looks great, I've left code change suggestions on some things, but otherwise this looks like this is a pretty useful and non-intrusive PR. After those changes I am happy to merge through and version push to 0.3.0.

Just summarizing the changes I saw so I can copy paste this into the release notes:

  • Adds new Config parameters: s2n_limit_energy, max_surface_wave_velocity, max_time_after_last_arrival, selection_mode, window_signal_to_noise_type
  • Adds ability to reject windows based on signal to noise energy ratio (original code based on amplitudes)
  • Feature: force window selection to certain phase arrivals with selection_mode
  • Adds new Window parameters: channel_id_2, snr_amplitude, snr_amplitude_threshold, distance_in_deg
  • WindowSelector.write_text provides a simple plaintext file write function
  • Adds a new rejection function to reject peaks and troughs not within the desired signal region which is determined by selection_mode and expected arrival times
  • Adds new debug log message to list out chosen windows
  • Adds a new rejection criteria for windows in pre-defined noise regions

Let me know what you think, and no rush on this. Thanks again!

:type min_surface_wave_velocity: float

:param max_surface_wave_velocity: The maxium surface wave velocity
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:param max_surface_wave_velocity: The maxium surface wave velocity
:param max_surface_wave_velocity: The maximum surface wave velocity

"6) custom; 7) phase_list;".format(selection_mode))

self.selection_mode = selection_mode

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Comment on lines +84 to +85

Returns the list of surface wave arrivals in time order.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Returns the list of surface wave arrivals in time order.
:type dist_in_deg: float
:param dist_in_deg: great circle source-receiver distance in units of degrees
:type min_vel: float
:param min_vel: minimum expected surface wave velocity to get latest arrival, units of km/s
:type max_vel: float
:param max_vel: maximum expected surface wave velocity to get earliest arrival, units of km/s
:type ncircles: int
:param ncircles: number of global orbits to calculate, defaults to 1
Returns the list of surface wave arrivals in time order.

Calculate the arrival time of surface waves, based on the distance
and velocity range (min_vel, max_vel).
This function will calculate both minor-arc and major-arc surface
waves. It further calcualte the surface orbit multiple times
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
waves. It further calcualte the surface orbit multiple times
waves. It further calculates the surface orbit multiple times

Returns the list of surface wave arrivals in time order.
"""
if min_vel > max_vel:
min_vel, max_vel = max_vel, min_vel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should add a logger warning message to let the User know they mixed these up?

Comment on lines +765 to +849
def _prepare_min_max_timebox(self, min_time, max_time, srate):
logger.debug("selection_timebox min/max time: {:.2f} {:.2f}"
"".format(min_time, max_time))

timebox = np.zeros(self.observed.stats.npts, dtype=bool)
il = int(min_time * srate)
ir = int(max_time * srate)
timebox[il:(ir+1)] = 1

logger.debug("selection_timebox index range: {} - {} / {}".format(
il, ir, len(timebox)))

self.selection_timebox = timebox
return timebox

def _prepare_exclude_surface_wave_timebox(self, min_time, max_time,
srate, offset):
logger.debug("selection_timebox exclude surface waves")

# get the surface windows first
self._prepare_surface_wave_timebox(srate, offset)

# flip the sign to reject surface windoes
timebox = self.selection_timebox
timebox = ~timebox

# set the min_time and max_time range to non-selectable
i1 = int(min_time * srate)
timebox[:i1] = False

i2 = int(max_time * srate)
timebox[i2:] = False

logger.debug("Selectable region coverage percentage: {}/{}".format(
timebox.sum(), len(timebox)))
self.selection_timebox = timebox
return timebox

def _prepare_surface_wave_timebox(self, srate, offset):
logger.debug("selection_timebox using surface waves")

max_vel = self.config.max_surface_wave_velocity
min_vel = self.config.min_surface_wave_velocity
arrivals = get_surface_wave_arrivals(
self.dist_in_deg, min_vel, max_vel, ncircles=2)
logger.debug("Number of surface wave arrivals: {}".format(
len(arrivals)))

timebox = np.zeros(self.observed.stats.npts, dtype=bool)

for _i, arr in enumerate(arrivals):
il = int((arr[0] + offset - self.config.min_period) * srate)
ir = int((arr[1] + offset + 2.5 * self.config.min_period) * srate)
logger.debug(f"Arrival {_i} (min, max): ({il}, {ir})")
timebox[il:(ir+1)] = 1
logger.debug("Selectable region coverage percentage: {}/{}".format(
timebox.sum(), len(timebox)))
self.selection_timebox = timebox
return timebox

def _prepare_phase_timebox(self, phase_list, srate, buffer_time, offset):
logger.debug("Selection_timebox using phases: {}".format(phase_list))

source_depth = self.event.depth_in_m / 1000.0
logger.debug("event depth: {:.2f} km".format(source_depth))
logger.debug("distance in deg: {:.2f}".format(self.dist_in_deg))
tts = self.taupy_model.get_travel_times(
source_depth_in_km=source_depth,
distance_in_degree=self.dist_in_deg,
phase_list=phase_list
)

timebox = np.zeros(self.observed.stats.npts, dtype=bool)
for t in tts:
t_left = t.time - buffer_time + offset
il = int(t_left * srate)
t_right = t.time + buffer_time + offset
ir = int(t_right * srate)
timebox[il:(ir+1)] = 1

logger.debug("Selectable region percentage: {}/{}".format(
timebox.sum(), len(timebox)))
self.selection_timebox = timebox

return timebox
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be condensed, alongside reject_on_selection_criteria. I think it's fine for now but in the future I/we might want to try and find a cleaner way to write this.

Comment on lines +877 to +881
Reject based on selection mode.
This function will reject windows outside of the
wave category specified. For example, if config.selection_mode
== "body_waves", only body wave windows will be selected(after
first arrival and before surface wave arrival).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    Reject windows outside a pre-defined phase window (e.g., body waves,
    surface waves, mantle waves) using the User-defined `selection_mode`.

    Availalable values for `selection_mode` are:
    - all_waves: all phases after first arrival
    - body_waves: all phases after first arrival and before first surface 
    - surface_waves: all phases inside surface wave train
    - mantle_waves: all phases after final surface wave arrival
    - body_and_mantle_waves: exclude surface waves
    - body_and_surface_waves: all phases before final surface wave arrival

Comment on lines +260 to +261
* ``"body_and_surface_waves"``: windows inside body and surface
wave regions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* ``"body_and_surface_waves"``: windows inside body and surface
wave regions.
* ``"body_and_surface_waves"``: windows inside body and surface
wave regions.
* ``"body_and_mantle_waves"``: exclude surface waves

win.cc_shift)
if not (tshift_min <= win.cc_shift_in_seconds <= tshift_max):
logger.debug("Window [%.1f - %.1f] rejected due to time "
"shift does not satisfy: %.1f < %.1f < %.1f"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, I've been meaning to change that log message because it's getting annoying having to manually convert samples to time every inversion!

@@ -870,7 +1294,7 @@ def _sanity_checks(self):

ptp = sorted([self.observed.data.ptp(), self.synthetic.data.ptp()])
if ptp[1] / ptp[0] >= 5:
warnings.warn("The amplitude difference between data and "
warnings.warn("The amplitude difference between data and"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
warnings.warn("The amplitude difference between data and"
warnings.warn("The amplitude difference between data and "

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants