14 from ROOT
import Belle2
25 import trackfindingcdc.harvest.cdc_peelers
as cdc_peelers
31 return logging.getLogger(__name__)
34 CONTACT =
"oliver.frost@desy.de"
38 """Harvester to generate, postprocess and inspect MC events for track-segment-pair fit validation"""
42 generator_module =
"simple_gun"
47 segment_orientation =
"outwards"
50 fit_method_name =
"fuse-sz"
54 """Get the output ROOT filename"""
66 """Harvest and post-process the MC events"""
69 path.add_module(harvesting_module)
70 return harvesting_module
73 """Convert command-line arguments to basf2 argument list"""
76 argument_parser.add_argument(
79 choices=[
"no",
"medium",
"full"],
82 help=
'Amount of monte carlo information to be used in the segment generation.',
85 argument_parser.add_argument(
87 choices=[
"zreco",
"fuse-pre",
"fuse-sz",
"fuse-sz-re"],
89 dest=
"fit_method_name",
90 help=(
"Choose which fit positional information of the segment should be used. \n"
91 "* 'zreco' means the z coordinate is reconstructed and a linear sz fit is made. "
92 "No covariance between the circle and the linear sz part can be made.\n"
93 "* 'fuse-sz' means the Kalmanesk fuse of the two trajectory fits.\n"
94 "* 'fuse-sz-re' means the Kalmanesk fuse of the two trajectory fits but reestimate the drift length."
98 return argument_parser
101 """Determine which track-segment-pair fitter to use"""
104 if fit_method_name ==
'zreco':
107 def z_reconstruction_fit(pair):
108 return sz_fitter.update(pair)
109 return z_reconstruction_fit
111 elif fit_method_name.startswith(
'fuse-pre'):
114 fusionFit = CDCAxialStereoFusion()
116 def sz_segment_pair_preliminary_fit(pair):
117 fusionFit.fusePreliminary(pair)
118 return sz_segment_pair_preliminary_fit
120 elif fit_method_name.startswith(
'fuse-sz'):
123 reestimateDriftLength = fit_method_name.endswith(
"re")
124 fusionFit = CDCAxialStereoFusion(reestimateDriftLength)
126 def sz_segment_pair_fusion_fit(pair):
127 fusionFit.reconstructFuseTrajectories(pair)
130 trajectory3D = pair.getTrajectory3D()
131 revFromSegment = pair.getFromSegment().reversed()
132 revToSegment = pair.getToSegment().reversed()
133 revPair = CDCSegmentPair(revToSegment, revFromSegment)
135 CDCAxialStereoFusion.reconstructFuseTrajectories(revPair)
136 revTrajectory3D = revPair.getTrajectory3D().reversed()
146 print(
"One parameters", [trajectory3D.getLocalHelix().parameters()[i]
for i
in range(5)])
147 print(
"Rev parameters", [revTrajectory3D.getLocalHelix().parameters()[i]
for i
in range(5)])
149 print(
"One covariance")
151 print([trajectory3D.getLocalHelix().helixCovariance()(i, j)
for i
in range(5)])
153 print(
"Rev covariance")
155 print([revTrajectory3D.getLocalHelix().helixCovariance()(i, j)
for i
in range(5)])
160 return sz_segment_pair_fusion_fit
163 raise ValueError(
"Unexpected fit_positions %s" % fit_method_name)
167 Sets up a path that plays back pregenerated events or generates events
168 based on the properties in the base class.
172 path.add_module(
"TFCDC_WireHitPreparer",
173 flightTimeEstimation=
"outwards",
177 path.add_module(
"TFCDC_ClusterPreparer")
182 path.add_module(
"TFCDC_SegmentFinderFacetAutomaton",
183 SegmentOrientation=
"outwards"
186 path.add_module(
"TFCDC_SegmentFitter",
187 inputSegments=
"CDCSegment2DVector",
188 updateDriftLength=
True,
189 useAlphaInDriftLength=
True,
194 path.add_module(
"TFCDC_SegmentFinderFacetAutomaton",
196 FacetRelationFilter=
"truth",
197 SegmentOrientation=
"outwards"
200 path.add_module(
"TFCDC_SegmentFitter",
201 inputSegments=
"CDCSegment2DVector",
202 updateDriftLength=
True,
203 useAlphaInDriftLength=
True,
209 path.add_module(
"TFCDC_SegmentCreatorMCTruth",
210 reconstructedDriftLength=
False,
211 reconstructedPositions=
True,
215 path.add_module(
"TFCDC_SegmentFitter",
216 inputSegments=
"CDCSegment2DVector",
217 updateDriftLength=
False,
222 raise ValueError(
"Invalid degree of Monte Carlo information")
224 path.add_module(
"TFCDC_SegmentOrienter",
225 SegmentOrientation=
"outwards",
227 inputSegments=
"CDCSegment2DVector",
228 segments=
"CDCSegment2DVectorOriented"
231 path.add_module(
"TFCDC_TrackFinderSegmentPairAutomaton",
232 inputSegments=
"CDCSegment2DVectorOriented",
233 WriteSegmentPairs=
True,
234 SegmentPairFilter=
"truth",
235 SegmentPairFilterParameters={
"allowReverse":
True},
236 SegmentPairRelationFilter=
"none"
245 """Module to collect information about the generated segment pairs and
246 compose validation plots on terminate."""
250 super(SegmentPairFitValidationModule, self).
__init__(
251 output_file_name=output_file_name,
252 foreach=
"CDCSegmentPairVector"
259 """Receive signal at the start of event processing"""
261 super(SegmentPairFitValidationModule, self).
initialize()
264 """Initialize the MC-hit lookup method"""
268 """Select segment pairs with 4 or more hits per segment and a matching primary MC particle"""
270 from_segment = segment_pair.getFromSegment()
271 to_segment = segment_pair.getToSegment()
272 mc_particle = mc_segment_lookup.getMCParticle(from_segment)
273 return (mc_particle
and
274 is_primary(mc_particle)
and
275 from_segment.size() > 3
and
276 to_segment.size() > 3)
279 """Aggregate the track and MC information for track-segment analysis"""
283 to_segment = segment_pair.getToSegment()
288 fit3d_truth = mc_segment_lookup.getTrajectory3D(to_segment)
290 fb_info = 1
if segment_pair.getAutomatonCell().getCellWeight() > 0
else -1
292 curvature_truth=fb_info * fit3d_truth.getCurvatureXY(),
293 tan_lambda_truth=fb_info * fit3d_truth.getTanLambda(),
297 segment_pair_crops.update(truth_crops)
298 return segment_pair_crops
302 save_histograms = refiners.save_histograms(outlier_z_score=5.0, allow_discrete=
True)
304 save_tree = refiners.save_tree()
307 save_curvature_pull_aux = refiners.save_pull_analysis(
308 part_name=
"curvature",
312 aux_names=[
"superlayer_id_pair",
"tan_lambda_truth"],
317 save_curvature_pull = refiners.save_pull_analysis(
318 part_name=
"curvature",
321 groupby=[
None,
"superlayer_id_pair"],
325 save_absolute_curvature_pull = refiners.save_pull_analysis(
326 part_name=
"curvature",
329 groupby=[
None,
"superlayer_id_pair"],
333 save_tan_lambda_pull = refiners.save_pull_analysis(
334 part_name=
"tan_lambda",
335 quantity_name=
"tan #lambda",
337 groupby=[
None,
"superlayer_id_pair"],
341 save_fit_quality_histograms = refiners.save_histograms(
343 select={
"ndf":
"ndf",
345 "p_value":
"p-value",
347 groupby=[
None,
"superlayer_id_pair"],
348 description=
"Distribution of {part_name} in the segment fits",
352 save_fit_quality_by_tan_lambda_profiles = refiners.save_profiles(
354 "p_value":
"fit p-value",
355 "tan_lambda_truth":
"true tan #lambda",
357 groupby=[
None,
"superlayer_id_pair"],
358 x=
"true tan #lambda",
360 check=(
"The {y_part_name} should be essentially the same over"
361 "the whole range of the tan lambda spectrum"),
362 description=(
"Investigating the reconstruction quality for different "
363 "tan lambda regions of the CDC. Most notably is the superlayer dependency."
364 "For stereo superlayers the curve is not flat but has distinct slope."),
370 """Fit axial and stereo track segment pairs"""
374 """Default method to fit the generated segment pairs."""
377 CDCAxialStereoFusion.reconstructFuseTrajectories(segmentPair,
391 super(AxialStereoPairFitterModule, self).
__init__()
394 """Called by basf2 for each event"""
398 """Fits all pairs in the StoreArray with designated fit method."""
403 wrapped_segment_pair_relations = stored_segment_pair_relations.obj()
404 segment_pair_relations = wrapped_segment_pair_relations.get()
406 for segment_pair_relation
in segment_pair_relations:
412 run.configure_and_execute_from_commandline()
415 if __name__ ==
"__main__":
416 logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=
'%(levelname)s:%(message)s')
def peel_segment_pair(segment_pair, key="{part_name}")
a (simplified) python wrapper for StoreObjPtr.
Utility class implementing the Kalmanesk combination of to two dimensional trajectories to one three ...
static const CDCMCHitLookUp & getInstance()
Getter for the singletone instance.
static const CDCMCSegment2DLookUp & getInstance()
Getter for the singletone instance.
static const CDCSZFitter & getFitter()
Getter for a standard sz line fitter instance.
Class representing a pair of one reconstructed axial segement and one stereo segment in adjacent supe...
def default_fit_method(segmentPair)
def __init__(self, fit_method=None)
fit_method
fit_method : function A function called on each stored segment pair as its only argument to update it...
mc_segment_lookup
by default, there is no method to find matching MC track segments
def peel(self, segment_pair)
def pick(self, segment_pair)
def __init__(self, output_file_name)
def create_argument_parser(self, **kwds)
monte_carlo
Degree of refinement of the segment generation.
string fit_method_name
use the Kalmanesk fuse of the two trajectory fits
string monte_carlo
do not generate new events
def harvesting_module(self, path=None)
def output_file_name(self)
output_file_name
Disable the writing of an output ROOT file.
root_input_file
generating events, so there is no ROOT input file
root_input_file
By default, there is no input ROOT TFile.
output_file_name
There is no default for the name of the output TFile.
int main(int argc, char **argv)
Run all tests.