Skip to content
This repository was archived by the owner on May 6, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions include/SimCore/ReSimulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ class ReSimulator : public SimulatorBase {
public:
ReSimulator(const std::string& name, framework::Process& process)
: SimulatorBase{name, process} {}
/*
/**
* Callback for the processor to configure itself from the given set
* of parameters.
*
* @param parameters ParameterSet for configuration.
*/
void configure(framework::config::Parameters& parameters) final override;
/*
/**
* Run resimulation if the event is part of the requested sets of events to
* resimulate
*
Expand All @@ -26,26 +26,41 @@ class ReSimulator : public SimulatorBase {
void produce(framework::Event& event) override;

private:
/*
* List of event numbers in the input files that should be resimulated if
/**
* Check if an event should be skipped during resimulation
*
* @param[in] event handle to the current event being processed
*/
bool skip(framework::Event& event) const;

/**
* List of events in the input files that should be resimulated if
* `resimulate_all_events` is false.
*
* @note: If an event number in `events_to_resimulate_` is not part of the
* Each event is identified uniquely by its run number and event number.
*
* @note: If an event in `events_to_resimulate_` is not part of the
* input file, it will be ignored.
*/
std::vector<int> events_to_resimulate_;
std::vector<std::pair<int, int>> events_to_resimulate_;

/**
* Whether to resimulate all events in the input files
*/
bool resimulate_all_events;
bool resimulate_all_events_;

/**
* Whether or not we should check the run number when seeing
* if a specific event should be resimulated
*/
bool care_about_run_;

/*
* How many events have already been resimulated. This determines the event
* number in the output file, since more than one input file can be used.
*
*/
int events_resimulated = 0;
int events_resimulated_ = 0;
};
} // namespace simcore

Expand Down
54 changes: 50 additions & 4 deletions python/simulator.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ with several helpful member functions.

from @PYTHON_PACKAGE_NAME@.Framework.ldmxcfg import Producer

class _EventToReSim:
"""A class to hold the information identifying a specific event we wish to re-simulate

This is an internal class used by simulator.resimulate in order to pass the event
identification to the ReSimulator class

Attributes
----------
run: int
run number of the event to re-sim, -1 if we don't care about the run
event: int
event number to re-sim, required
"""

def __init__(self, event, run = -1):
self.event = event
self.run = run


class simulator(Producer):
"""A instance of the simulation configuration

Expand Down Expand Up @@ -135,7 +154,7 @@ class simulator(Producer):
sds.ScoringPlaneSD.magnet()
])

def resimulate(self, which_events = None):
def resimulate(self, which_events = None, which_runs = None):
"""Create a resimulator based on the simulator configuration.

This is intended to ensure that a resimulator has the same configuration
Expand All @@ -147,27 +166,54 @@ class simulator(Producer):

Parameters
----------
which_events : list of event numbers, optional
which_events : list of event numbers, optional
Which events from the input files to resimulate. If None,
resimulate all events.

Events that are not present in any of the input files will be
ignored.

For multiple input files, if an event number is present within more
than one input file all versions will be resimulated.
than one input file all versions will be resimulated unless the which_runs
parameters is used to distinguish them.

which_runs : list of run numbers, optional
Which runs from the input files to resimulate, ignored if no
events are listed. Runs not present in the input files will be
ignored.

If not provided, all runs will be resimulated (i.e. the run number
check is ignored). If only one value is provided, all events requested
are also required to have that value for their run number to be resimulated.
If more than one value is provided, it must be the same length as the
number of events requested so that the event/run number pair can be required.

"""
resimulator = self
resimulator.className = 'simcore::ReSimulator'
if which_events is None:
resimulator.resimulate_all_events = True
resimulator.care_about_run = False
resimulator.events_to_resimulate = [ ]
elif isinstance(which_events, list):
resimulator.resimulate_all_events = False
resimulator.events_to_resimulate = which_events
if len(which_events) == 0:
raise ValueError('which_events must contain at least one element if provided')
if which_runs is None:
resimulator.care_about_run = False
resimulator.events_to_resimulate = [ _EventToReSim(event) for event in which_events ]
elif isinstance(which_runs, int):
resimulator.care_about_run = True
resimulator.events_to_resimulate = [ _EventToReSim(event, which_runs) for event in which_events ]
elif isinstance(which_runs, list):
if len(which_runs) == 0:
raise ValueError('which_runs must have at least one value if provided as a list')
if len(which_runs) != len(which_events):
raise ValueError('which_runs must have the same number of entries as which_events if more than one run is provided')
resimulator.care_about_run = True
resimulator.runs_to_resimulate = [ _EventToReSim(event, run) for event, run in zip(which_events, which_runs) ]
else:
raise ValueError('which_runs must be an int or a list of ints if provided')
else:
raise ValueError('which_events must be a list if provided')
return resimulator
60 changes: 43 additions & 17 deletions src/SimCore/ReSimulator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,39 @@ namespace simcore {

void ReSimulator::configure(framework::config::Parameters& parameters) {
SimulatorBase::configure(parameters);
resimulate_all_events =
resimulate_all_events_ =
parameters.getParameter<bool>("resimulate_all_events");
if (!resimulate_all_events) {
events_to_resimulate_ =
parameters.getParameter<std::vector<int>>("events_to_resimulate", {});
if (events_to_resimulate_.size() == 0) {
if (!resimulate_all_events_) {
care_about_run_ = parameters.getParameter<bool>("care_about_run");
auto configured_events{
parameters.getParameter<std::vector<framework::config::Parameters>>(
"events_to_resimulate", {})};
if (configured_events.size() == 0) {
EXCEPTION_RAISE(
"ReSimNoEvents",
"ReSim was configured with resimulate_all_events marked false but "
"no event numbers were requested.\n\nDid you forget to configure "
"the events_to_resimulate parameter?\n");
}
for (const auto& run_event : configured_events) {
events_to_resimulate_.emplace_back(run_event.getParameter<int>("run"),
run_event.getParameter<int>("event"));
}
}
}

void ReSimulator::produce(framework::Event& event) {
/* numEventsBegan_++; */
auto& eventHeader{event.getEventHeader()};
const auto eventNumber{eventHeader.getEventNumber()};
if (!resimulate_all_events) {
auto found = std::find(std::begin(events_to_resimulate_),
std::end(events_to_resimulate_), eventNumber);
if (found == std::end(events_to_resimulate_)) {
if (verbosity_ > 1) {
std::cout << "Skipping event: " << eventNumber
<< " since it wasn't part of the requested events..."
<< std::endl;
}
this->abortEvent(); // get out of processors loop
return;
if (skip(event)) {
if (verbosity_ > 1) {
std::cout << "Skipping event: " << eventNumber
<< " since it wasn't part of the requested events..."
<< std::endl;
}
this->abortEvent(); // get out of processors loop
return;
}
if (verbosity_ > 0) {
std::cout << "Resimulating " << eventNumber << std::endl;
Expand All @@ -56,7 +59,7 @@ void ReSimulator::produce(framework::Event& event) {
std::to_string(eventNumber));
}

eventHeader.setEventNumber(++events_resimulated);
eventHeader.setEventNumber(++events_resimulated_);
updateEventHeader(eventHeader);
saveTracks(event);

Expand All @@ -65,5 +68,28 @@ void ReSimulator::produce(framework::Event& event) {
runManager_->TerminateOneEvent();
}

bool ReSimulator::skip(framework::Event& event) const {
/**
* If we are configured to simply resimulate all events, this
* function always returns false.
*/
if (resimulate_all_events_) return false;
/**
* Otherwise, we check the event number
* (and also its run number if we care_about_run_)
* against the list of run/event pairs that we are
* interested in re-simulating.
*/
auto found_event_to_resim = std::find_if(
std::begin(events_to_resimulate_), std::end(events_to_resimulate_),
[&](const std::pair<int, int>& run_event) -> bool {
bool runs_match = true;
if (care_about_run_)
runs_match = (event.getEventHeader().getRun() == run_event.first);
return event.getEventNumber() == run_event.second and runs_match;
});
return (found_event_to_resim == std::end(events_to_resimulate_));
}

} // namespace simcore
DECLARE_PRODUCER_NS(simcore, ReSimulator)