-
Notifications
You must be signed in to change notification settings - Fork 35
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
Trigger Readout Window #763
Open
cg-laser
wants to merge
32
commits into
develop
Choose a base branch
from
refactor-triggertimeadjuster
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+292
−249
Open
Changes from 4 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
e2a65ea
include the readout time delays in the trace start time
cg-laser 58d2393
commit modules
cg-laser 60964b8
fix
cg-laser 1efa01a
address comments
cg-laser 309bc22
properly initialize propagator
cg-laser 97bb68e
Scrap everything from deprecated module and only keep warning and error
fschlueter c1c8b2c
Merge branch 'develop' into refactor-triggertimeadjuster-fs
fschlueter eb176b6
Let the channelReadoutWindowCutter make use of the new function
fschlueter a159034
Fix channel trace_start_time for non-triggered channels
fschlueter 6f6deca
Fix channelReadoutWindowCutter.py
fschlueter 27f9ccf
Fix import of channel
fschlueter 9afabee
Fix module
fschlueter 56ca4a2
Add logger and raise value error
fschlueter 33a86c3
Merge branch 'develop' into refactor-triggertimeadjuster
fschlueter 9e9fef7
Fixed bug in BaseTrace.add_to_trace
MartinRavn c943db0
Merge branch 'refactor-triggertimeadjuster' into refactor-triggertime…
fschlueter 2232cd0
Only run if dt is not 0.
fschlueter d6efa3f
Attempt to fix base_trace.add_to_trace
fschlueter 93ecdeb
Fix simulations.py
fschlueter 08fefc1
Add better doc-strings/comments [skip-ci] [ci-skip]
fschlueter c59a908
Update documentation
fschlueter caf5499
Update documentation
fschlueter 7b04bfe
Change implementation of channelReadoutWindowCutter back to what is d…
fschlueter 02dec51
Remove print [skip ci]
fschlueter 460d7ae
Merge pull request #820 from nu-radio/refactor-triggertimeadjuster-fs
fschlueter 75e3f32
Fix doc-string syntax in readLOFARData.py
fschlueter 3b5550d
Remove reference for deprecated (private) module which are not refere…
fschlueter 9f99ed2
Added min_residual_time_offset argument to add_to_trace
MartinRavn 2ab4fbd
By default raise an error if for trace.add_to_trace(channel), the cha…
fschlueter d4eed16
Fix docu
fschlueter 56cf2e3
Disable error for non-trigger channels
fschlueter 2a5acc4
test for equality of trace_start_times in SingleEvent test
sjoerd-bouma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from _deprecated import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
from NuRadioReco.modules.base.module import register_run | ||
import numpy as np | ||
import logging | ||
from NuRadioReco.utilities import units | ||
|
||
logger = logging.getLogger('NuRadioReco.channelReadoutWindowCutter') | ||
|
||
|
||
class channelReadoutWindowCutter: | ||
""" | ||
Modifies channel traces to simulate the effects of the trigger | ||
|
||
The trace is cut to the length defined in the detector description relative to the trigger time. | ||
If no trigger exists, nothing is done. | ||
""" | ||
|
||
def __init__(self, log_level=logging.NOTSET): | ||
logger.setLevel(log_level) | ||
self.__sampling_rate_warning_issued = False | ||
self.begin() | ||
|
||
def begin(self): | ||
pass | ||
|
||
@register_run() | ||
def run(self, event, station, detector): | ||
""" | ||
Cuts the traces to the readout window defined in the trigger. | ||
|
||
If multiple triggers exist, the primary trigger is used. If multiple | ||
primary triggers exist, an error is raised. | ||
If no primary trigger exists, the trigger with the earliest trigger time | ||
is defined as the primary trigger and used to set the readout windows. | ||
|
||
Parameters | ||
---------- | ||
event: `NuRadioReco.framework.event.Event` | ||
|
||
station: `NuRadioReco.framework.base_station.Station` | ||
|
||
detector: `NuRadioReco.detector.detector.Detector` | ||
""" | ||
counter = 0 | ||
for i, (name, instance, kwargs) in enumerate(event.iter_modules(station.get_id())): | ||
if name == 'channelReadoutWindowCutter': | ||
counter += 1 | ||
if counter > 1: | ||
logger.warning('channelReadoutWindowCutter was called twice. ' | ||
'This is likely a mistake. The module will not be applied again.') | ||
return 0 | ||
|
||
|
||
# determine which trigger to use | ||
# if no primary trigger exists, use the trigger with the earliest trigger time | ||
trigger = station.get_primary_trigger() | ||
if trigger is None: # no primary trigger found | ||
logger.debug('No primary trigger found. Using the trigger with the earliest trigger time.') | ||
trigger = station.get_first_trigger() | ||
if trigger is not None: | ||
logger.info(f"setting trigger {trigger.get_name()} primary because it triggered first") | ||
trigger.set_primary(True) | ||
|
||
if trigger is None: | ||
logger.info('No trigger found! Channel timings will not be changed.') | ||
return | ||
|
||
if trigger.has_triggered(): | ||
trigger_time = trigger.get_trigger_time() | ||
for channel in station.iter_channels(): | ||
trigger_time_channel = trigger_time - channel.get_trace_start_time() | ||
# if trigger_time_channel == 0: | ||
# logger.warning(f"the trigger time is equal to the trace start time for channel {channel.get_id()}. This is likely because this module was already run on this station. The trace will not be changed.") | ||
# continue | ||
|
||
trace = channel.get_trace() | ||
trace_length = len(trace) | ||
detector_sampling_rate = detector.get_sampling_frequency(station.get_id(), channel.get_id()) | ||
sampling_rate = channel.get_sampling_rate() | ||
self.__check_sampling_rates(detector_sampling_rate, sampling_rate) | ||
|
||
# this should ensure that 1) the number of samples is even and | ||
# 2) resampling to the detector sampling rate results in the correct number of samples | ||
# (note that 2) can only be guaranteed if the detector sampling rate is lower than the | ||
# current sampling rate) | ||
number_of_samples = int( | ||
2 * np.ceil( | ||
detector.get_number_of_samples(station.get_id(), channel.get_id()) / 2 | ||
* sampling_rate / detector_sampling_rate | ||
)) | ||
|
||
if number_of_samples > trace.shape[0]: | ||
logger.error("Input has fewer samples than desired output. Channels has only {} samples but {} samples are requested.".format( | ||
trace.shape[0], number_of_samples)) | ||
raise AttributeError | ||
else: | ||
trigger_time_sample = int(np.round(trigger_time_channel * sampling_rate)) | ||
# logger.debug(f"channel {channel.get_id()}: trace_start_time = {channel.get_trace_start_time():.1f}ns, trigger time channel {trigger_time_channel/units.ns:.1f}ns, trigger time sample = {trigger_time_sample}") | ||
channel_id = channel.get_id() | ||
pre_trigger_time = trigger.get_pre_trigger_time_channel(channel_id) | ||
samples_before_trigger = int(pre_trigger_time * sampling_rate) | ||
cut_samples_beginning = 0 | ||
if(samples_before_trigger <= trigger_time_sample): | ||
cut_samples_beginning = trigger_time_sample - samples_before_trigger | ||
roll_by = 0 | ||
if(cut_samples_beginning + number_of_samples > trace_length): | ||
logger.warning("trigger time is sample {} but total trace length is only {} samples (requested trace length is {} with an offest of {} before trigger). To achieve desired configuration, trace will be rolled".format( | ||
trigger_time_sample, trace_length, number_of_samples, samples_before_trigger)) | ||
roll_by = cut_samples_beginning + number_of_samples - trace_length # roll_by is positive | ||
trace = np.roll(trace, -1 * roll_by) | ||
cut_samples_beginning -= roll_by | ||
rel_station_time_samples = cut_samples_beginning + roll_by | ||
elif(samples_before_trigger > trigger_time_sample): | ||
roll_by = -trigger_time_sample + samples_before_trigger | ||
logger.warning(f"trigger time is before 'trigger offset window' (requested samples before trigger = {samples_before_trigger}," \ | ||
f"trigger time sample = {trigger_time_sample}), the trace needs to be rolled by {roll_by} samples first" \ | ||
f" = {roll_by / sampling_rate/units.ns:.2f}ns") | ||
trace = np.roll(trace, roll_by) | ||
|
||
# shift trace to be in the correct location for cutting | ||
trace = trace[cut_samples_beginning:(number_of_samples + cut_samples_beginning)] | ||
channel.set_trace(trace, channel.get_sampling_rate()) | ||
channel.set_trace_start_time(trigger_time - pre_trigger_time) | ||
# channel.set_trace_start_time(channel.get_trace_start_time() + rel_station_time_samples / channel.get_sampling_rate()) | ||
# logger.debug(f"setting trace start time to {channel.get_trace_start_time() + rel_station_time_samples / channel.get_sampling_rate():.0f} = {channel.get_trace_start_time():.0f} + {rel_station_time_samples / channel.get_sampling_rate():.0f}") | ||
|
||
|
||
|
||
def __check_sampling_rates(self, detector_sampling_rate, channel_sampling_rate): | ||
if not self.__sampling_rate_warning_issued: # we only issue this warning once | ||
if not np.isclose(detector_sampling_rate, channel_sampling_rate): | ||
logger.warning( | ||
'triggerTimeAdjuster was called, but the channel sampling rate ' | ||
f'({channel_sampling_rate/units.GHz:.3f} GHz) is not equal to ' | ||
f'the target detector sampling rate ({detector_sampling_rate/units.GHz:.3f} GHz). ' | ||
'Traces may not have the correct trace length after resampling.' | ||
) | ||
self.__sampling_rate_warning_issued = True | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this warning at all? We ensure that we have the correct number of samples with:
Maybe we can only check that
detector_sampling_rate <= channel_sampling_rate
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think when I implemented this I thought about it sufficiently to realize that if
sampling_rate < detector_sampling_rate
we cannot guarantee the correct number of samples (with the way resampling is currently implemented); I am not actually sure if the correct number of samples is guaranteed in all cases ifsampling_rate > detector_sampling_rate
; my feeling was that this is only true in most cases which is why I left the warning as it is. If you can work out the maths and figure out that this is wrong and we don't need the warning we can change this : )