Skip to content

Commit

Permalink
Merge pull request #80 from IceCubeOpenSource/mc_inj_fix
Browse files Browse the repository at this point in the history
Monte Carlo injections fix
  • Loading branch information
tomaskontrimas authored Oct 26, 2020
2 parents 0330111 + 10d26e4 commit c286b9a
Showing 1 changed file with 20 additions and 73 deletions.
93 changes: 20 additions & 73 deletions skyllh/core/background_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ class MCDataSamplingBkgGenMethod(BackgroundGenerationMethod):
def __init__(
self, get_event_prob_func, get_mean_func=None, unique_events=False,
data_scrambler=None, mc_inplace_scrambling=False,
keep_mc_data_fields=None, pre_event_selection_method=None,
event_selection_method=None):
keep_mc_data_fields=None, pre_event_selection_method=None):
"""Creates a new instance of the MCDataSamplingBkgGenMethod class.
Parameters
Expand Down Expand Up @@ -140,10 +139,6 @@ def __init__(
pre-select the MC events that will be used for later background
event generation. Using this pre-selection a large portion of the
MC data can be reduced prior to background event generation.
event_selection_method : instance of EventSelectionMethod | None
If set to an instance of EventSelectionMethod, background
events will get selected from the MC only for events that pass the
event selection method.
"""
super(MCDataSamplingBkgGenMethod, self).__init__()

Expand All @@ -154,11 +149,10 @@ def __init__(
self.mc_inplace_scrambling = mc_inplace_scrambling
self.keep_mc_data_field_names = keep_mc_data_fields
self.pre_event_selection_method = pre_event_selection_method
self.event_selection_method = event_selection_method

if((event_selection_method is not None) and (get_mean_func is None)):
raise ValueError('If an event selection method is provided, a '
'get_mean_func needs to be provided as well!')
if((pre_event_selection_method is not None) and (get_mean_func is None)):
raise ValueError('If an event pre-selection method is provided, a '
'get_mean_func needs to be provided as well!')

# Define cache members to cache the background probabilities for each
# monte-carlo event. The probabilities change only if the data changes.
Expand Down Expand Up @@ -282,34 +276,10 @@ def pre_event_selection_method(self, method):
method = None
self._pre_event_selection_method = method

@property
def event_selection_method(self):
"""The instance of EventSelectionMethod that selects events, which have
potential to be signal. Since all non-selected events will be treated as
pure background events, background events for the analysis have to be
drawn only for the spatial region where events are evaluated with the
likelihood ratio function for the analysis.
This property can be ``None`` if set to ``None``, or set to the
``AllEventSelectionMethod`` method.
"""
return self._event_selection_method
@event_selection_method.setter
def event_selection_method(self, method):
if(method is not None):
if(not isinstance(method, EventSelectionMethod)):
raise TypeError('The event_selection_method property must be '
'None, or an instance of EventSelectionMethod!')
# If the event selection method selects all events, it's equivalent
# to have it set to None, because then no operation has to be
# performed.
if(isinstance(method, AllEventSelectionMethod)):
method = None
self._event_selection_method = method

def change_source_hypo_group_manager(self, src_hypo_group_manager):
"""Changes the SourceHypoGroupManager instance of the
pre-event-selection and event-selection method. Also it invalides the
data cache of this background generation method.
pre-event-selection method. Also it invalides the data cache of this
background generation method.
Parameters
----------
Expand All @@ -319,9 +289,6 @@ def change_source_hypo_group_manager(self, src_hypo_group_manager):
if(self._pre_event_selection_method is not None):
self._pre_event_selection_method.change_source_hypo_group_manager(
src_hypo_group_manager)
if(self._event_selection_method is not None):
self._event_selection_method.change_source_hypo_group_manager(
src_hypo_group_manager)

# Invalidate the data cache.
self._cache_data_id = None
Expand Down Expand Up @@ -369,7 +336,6 @@ def generate_events(

# Create aliases to avoid dot-lookup.
self__pre_event_selection_method = self._pre_event_selection_method
self__event_selection_method = self._event_selection_method

# Check if the data set has changed. In that case need to get new
# background probabilities for each monte-carlo event and a new mean
Expand Down Expand Up @@ -429,31 +395,12 @@ def generate_events(
n_bkg = (int(rss.random.poisson(mean)) if poisson else
int(np.round(mean, 0)))

data_mc_pre_selected = self._cache_mc_pre_selected
# Apply only event pre-selection before choosing events.
data_mc_selected = self._cache_mc_pre_selected

# Scramble the pre-selected MC events if requested.
if(self._data_scrambler is not None):
with TaskTimer(tl, 'Scramble MC background data.'):
data_mc_pre_selected = self._data_scrambler.scramble_data(
rss, data_mc_pre_selected, copy=False)

# Select the significant events from the pre-selection.
if(self__event_selection_method is None):
data_mc_selected = data_mc_pre_selected
else:
with TaskTimer(tl, 'Select the significant background events.'):
(data_mc_selected, mask_idxs) = self__event_selection_method.select_events(
data_mc_pre_selected, retidxs=True, tl=tl)

# Determine if there is an event selection at all.
no_selection = (
(self__pre_event_selection_method is None) and
(self__event_selection_method is None)
)

# Calculate the mean number of background events for the selected
# MC events (including pre-selection and selection).
if(no_selection):
# Calculate the mean number of background events for the pre-selected
# MC events.
if(self__pre_event_selection_method is None):
# No selection at all, use the total mean.
mean_selected = mean
else:
Expand All @@ -465,17 +412,11 @@ def generate_events(
# events.
p_binomial = mean_selected / mean
with TaskTimer(tl, 'Get p array.'):
if(no_selection):
if(self__pre_event_selection_method is None):
p = self._cache_mc_event_bkg_prob
elif(self__event_selection_method is None):
# Only pre-selection.
p = self._cache_mc_event_bkg_prob_pre_selected / p_binomial
elif(self__pre_event_selection_method is None):
# Only normal selection.
p = self._cache_mc_event_bkg_prob[mask_idxs] / p_binomial
else:
# Pre-selection and normal selection.
p = self._cache_mc_event_bkg_prob_pre_selected[mask_idxs] / p_binomial
# Pre-selection.
p = self._cache_mc_event_bkg_prob_pre_selected / p_binomial
n_bkg_selected = int(np.around(n_bkg * p_binomial, 0))

# Draw the actual background events from the selected events of the
Expand All @@ -489,6 +430,12 @@ def generate_events(
with TaskTimer(tl, 'Select MC background events from indices.'):
bkg_events = data_mc_selected[bkg_event_indices]

# Scramble the drawn MC events if requested.
if(self._data_scrambler is not None):
with TaskTimer(tl, 'Scramble MC background data.'):
bkg_events = self._data_scrambler.scramble_data(
rss, bkg_events, copy=False)

# Remove MC specific data fields from the background events record
# array. So the result contains only experimental data fields. The list
# of experimental data fields is defined as the unique set of the
Expand Down

0 comments on commit c286b9a

Please sign in to comment.