Belle II Software  release-08-01-10
refiners.py
1 
8 
9 import functools
10 import numpy as np
11 import collections
12 import copy
13 
14 from tracking.validation.plot import ValidationPlot, compose_axis_label
15 from tracking.validation.fom import ValidationFiguresOfMerit
16 from tracking.validation.classification import ClassificationAnalysis
17 from tracking.validation.pull import PullAnalysis
18 from tracking.validation.tolerate_missing_key_formatter import TolerateMissingKeyFormatter
19 from tracking.root_utils import root_cd, root_save_name
20 
21 import ROOT
22 
23 import logging
24 
25 
26 def get_logger():
27  return logging.getLogger(__name__)
28 
29 
30 
31 formatter = TolerateMissingKeyFormatter()
32 
33 
34 class Refiner(object):
35  """Python module to refine a peeled dictionary"""
36 
37  def __init__(self, refiner_function=None):
38  """Constructor of the Refiner instance"""
39 
40  self.refiner_functionrefiner_function = refiner_function
41 
42  def __get__(self, harvesting_module, cls=None):
43  """Getter of the Refiner instance"""
44  if harvesting_module is None:
45  # Class access
46  return self
47  else:
48  # Instance access
49  refine = self.refinerefine
50 
51  def bound_call(*args, **kwds):
52  return refine(harvesting_module, *args, **kwds)
53  return bound_call
54 
55  def __call__(self, harvesting_module, crops=None, *args, **kwds):
56  """implementation of the function-call of the Refiner instance
57  r = Refiner()
58  r(harvester) # decoration
59  r(harvester, crops, args, keywords) # refinement
60  """
61  if crops is None:
62  # Decoration mode
63  harvesting_module.refiners.append(self)
64  return harvesting_module
65  else:
66  # Refining mode
67  return self.refinerefine(harvesting_module, crops, *args, **kwds)
68 
69  def refine(self, harvesting_module, *args, **kwds):
70  """Apply the instance's refiner function"""
71  self.refiner_functionrefiner_function(harvesting_module, *args, **kwds)
72 
73 
75  """Refiner for figures of merit"""
76 
77  default_name = "{module.id}_figures_of_merit{groupby_key}"
78 
79  default_title = "Figures of merit in {module.title}"
80 
81  default_contact = "{module.contact}"
82 
83  default_description = "Figures of merit are the {aggregation.__name__} of {keys}"
84 
85  default_check = "Check for reasonable values"
86 
87  default_key = "{aggregation.__name__}_{part_name}"
88 
89 
90  @staticmethod
91  def mean(xs):
92  return np.nanmean(xs)
93 
94 
95  default_aggregation = mean
96 
97  def __init__(self,
98  name=None,
99  title=None,
100  contact=None,
101  description=None,
102  check=None,
103  key=None,
104  aggregation=None,
105  ):
106  """Constructor for this refiner"""
107 
108  super(SaveFiguresOfMeritRefiner, self).__init__()
109 
110 
111  self.namename = name
112 
113  self.titletitle = title
114 
115 
116  self.descriptiondescription = description
117 
118  self.checkcheck = check
119 
120  self.contactcontact = contact
121 
122 
123  self.keykey = key
124 
125  self.aggregationaggregation = aggregation
126 
127  def refine(self,
128  harvesting_module,
129  crops,
130  tdirectory=None,
131  groupby_part_name=None,
132  groupby_value=None,
133  **kwds):
134  """Process the figures of merit"""
135 
136  name = self.namename or self.default_namedefault_name
137  title = self.titletitle or self.default_titledefault_title
138  contact = self.contactcontact or self.default_contactdefault_contact
139  description = self.descriptiondescription or self.default_descriptiondefault_description
140  check = self.checkcheck or self.default_checkdefault_check
141 
142  aggregation = self.aggregationaggregation or self.default_aggregationdefault_aggregation
143 
144  replacement_dict = dict(
145  refiner=self,
146  module=harvesting_module,
147  aggregation=aggregation,
148  groupby_key='_' + groupby_part_name + groupby_value if groupby_part_name else "",
149  groupby=groupby_part_name, # deprecated
150  groupby_value=groupby_value, # deprecated
151  )
152 
153  name = formatter.format(name, **replacement_dict)
154  title = formatter.format(title, **replacement_dict)
155  contact = formatter.format(contact, **replacement_dict)
156 
157  figures_of_merit = ValidationFiguresOfMerit(name,
158  contact=contact,
159  title=title)
160 
161  for part_name, parts in iter_items_sorted_for_key(crops):
162  key = self.keykey or self.default_keydefault_key
163  key = formatter.format(key, part_name=part_name, **replacement_dict)
164  figures_of_merit[key] = aggregation(parts)
165 
166  keys = list(figures_of_merit.keys())
167 
168  description = formatter.format(description, keys=keys, **replacement_dict)
169  check = formatter.format(check, keys=keys, **replacement_dict)
170 
171  figures_of_merit.description = description
172  figures_of_merit.check = check
173 
174  if tdirectory:
175  figures_of_merit.write(tdirectory)
176 
177  print(figures_of_merit)
178 
179 
181  """Refiner for histograms"""
182 
183  default_name = "{module.id}_{part_name}_histogram{groupby_key}{stackby_key}"
184 
185  default_title = "Histogram of {part_name}{groupby_key}{stackby_key} from {module.title}"
186 
187  default_contact = "{module.contact}"
188 
189  default_description = "This is a histogram of {part_name}{groupby_key}{stackby_key}."
190 
191  default_check = "Check if the distribution is reasonable"
192 
193  def __init__(self,
194  name=None,
195  title=None,
196  contact=None,
197  description=None,
198  check=None,
199  lower_bound=None,
200  upper_bound=None,
201  bins=None,
202  outlier_z_score=None,
203  allow_discrete=False,
204  stackby="",
205  fit=None,
206  fit_z_score=None):
207  """Constructor for this refiner"""
208 
209  super(SaveHistogramsRefiner, self).__init__()
210 
211 
212  self.namename = name
213 
214  self.titletitle = title
215 
216 
217  self.descriptiondescription = description
218 
219  self.checkcheck = check
220 
221  self.contactcontact = contact
222 
223 
224  self.lower_boundlower_bound = lower_bound
225 
226  self.upper_boundupper_bound = upper_bound
227 
228  self.binsbins = bins
229 
230 
231  self.outlier_z_scoreoutlier_z_score = outlier_z_score
232 
233  self.allow_discreteallow_discrete = allow_discrete
234 
235  self.stackbystackby = stackby
236 
237 
238  self.fitfit = fit
239 
240  self.fit_z_scorefit_z_score = fit_z_score
241 
242  def refine(self,
243  harvesting_module,
244  crops,
245  tdirectory=None,
246  groupby_part_name=None,
247  groupby_value=None,
248  **kwds):
249  """Process the histogram"""
250 
251  stackby = self.stackbystackby
252  if stackby:
253  stackby_parts = crops[stackby]
254  else:
255  stackby_parts = None
256 
257  replacement_dict = dict(
258  refiner=self,
259  module=harvesting_module,
260  stackby_key=' stacked by ' + stackby if stackby else "",
261  groupby_key=' in group ' + groupby_part_name + groupby_value if groupby_part_name else "",
262  )
263 
264  contact = self.contactcontact or self.default_contactdefault_contact
265  contact = formatter.format(contact, **replacement_dict)
266 
267  for part_name, parts in iter_items_sorted_for_key(crops):
268  name = self.namename or self.default_namedefault_name
269  title = self.titletitle or self.default_titledefault_title
270  description = self.descriptiondescription or self.default_descriptiondefault_description
271  check = self.checkcheck or self.default_checkdefault_check
272 
273  name = formatter.format(name, part_name=part_name, **replacement_dict)
274  title = formatter.format(title, part_name=part_name, **replacement_dict)
275  description = formatter.format(description, part_name=part_name, **replacement_dict)
276  check = formatter.format(check, part_name=part_name, **replacement_dict)
277 
278  histogram = ValidationPlot(name)
279  histogram.hist(parts,
280  lower_bound=self.lower_boundlower_bound,
281  upper_bound=self.upper_boundupper_bound,
282  bins=self.binsbins,
283  outlier_z_score=self.outlier_z_scoreoutlier_z_score,
284  allow_discrete=self.allow_discreteallow_discrete,
285  stackby=stackby_parts)
286 
287  histogram.title = title
288  histogram.contact = contact
289  histogram.description = description
290  histogram.check = check
291 
292  histogram.xlabel = compose_axis_label(part_name)
293 
294  if self.fitfit:
295  if self.fit_z_scorefit_z_score is None:
296  kwds = dict()
297  else:
298  kwds = dict(z_score=self.fit_z_scorefit_z_score)
299 
300  fit_method_name = 'fit_' + str(self.fitfit)
301  try:
302  fit_method = getattr(histogram, fit_method_name)
303  except AttributeError:
304  histogram.fit(str(self.fitfit), **kwds)
305  else:
306  fit_method(**kwds)
307 
308  if tdirectory:
309  histogram.write(tdirectory)
310 
311 
313  """Refiner for profile histograms and 2D scatterplots"""
314 
315  plot_kind = "profile"
316 
317  def __init__(self,
318  y,
319  x=None,
320  name=None,
321  title=None,
322  contact=None,
323  description=None,
324  check=None,
325  stackby=None,
326  y_unit=None,
327  y_binary=None,
328  y_log=None,
329  lower_bound=None,
330  upper_bound=None,
331  bins=None,
332  outlier_z_score=None,
333  fit=None,
334  fit_z_score=None,
335  skip_single_valued=False,
336  allow_discrete=False):
337  """Constructor for this refiner"""
338 
339  super().__init__()
340 
341 
342  self.namename = name
343 
344  self.titletitle = title
345 
346 
347  self.descriptiondescription = description
348 
349  self.checkcheck = check
350 
351  self.contactcontact = contact
352 
353 
354  self.xx = x
355 
356  self.yy = y
357 
358  self.stackbystackby = stackby
359 
360  self.y_unity_unit = y_unit
361 
362 
363  self.lower_boundlower_bound = lower_bound
364 
365  self.upper_boundupper_bound = upper_bound
366 
367  self.binsbins = bins
368 
369  self.y_binaryy_binary = y_binary
370 
371  self.y_logy_log = y_log
372 
373 
374  self.outlier_z_scoreoutlier_z_score = outlier_z_score
375 
376  self.allow_discreteallow_discrete = allow_discrete
377 
378 
379  self.fitfit = fit
380 
381  self.fit_z_scorefit_z_score = fit_z_score
382 
383 
384  self.skip_single_valuedskip_single_valued = skip_single_valued
385 
386  def refine(self,
387  harvesting_module,
388  crops,
389  tdirectory=None,
390  groupby_part_name=None,
391  groupby_value=None,
392  **kwds):
393  """Process the profile histogram / scatterplot"""
394 
395  stackby = self.stackbystackby
396  if stackby:
397  stackby_parts = crops[stackby]
398  else:
399  stackby_parts = None
400 
401  replacement_dict = dict(
402  refiner=self,
403  module=harvesting_module,
404  stackby_key=' stacked by ' + stackby if stackby else "",
405  groupby_key=' in group ' + groupby_part_name + groupby_value if groupby_part_name else "",
406  )
407 
408  contact = self.contactcontact or self.default_contact
409  contact = formatter.format(contact, **replacement_dict)
410 
411  y_crops = select_crop_parts(crops, select=self.yy)
412  x_crops = select_crop_parts(crops, select=self.xx, exclude=self.yy)
413 
414  for y_part_name, y_parts in iter_items_sorted_for_key(y_crops):
415  for x_part_name, x_parts in iter_items_sorted_for_key(x_crops):
416 
417  if self.skip_single_valuedskip_single_valued and not self.has_more_than_one_valuehas_more_than_one_value(x_parts):
418  get_logger().info('Skipping "%s" by "%s" profile because x has only a single value "%s"',
419  y_part_name,
420  x_part_name,
421  x_parts[0])
422  continue
423 
424  if self.skip_single_valuedskip_single_valued and not self.has_more_than_one_valuehas_more_than_one_value(y_parts):
425  get_logger().info('Skipping "%s" by "%s" profile because y has only a single value "%s"',
426  y_part_name,
427  x_part_name,
428  y_parts[0])
429  continue
430 
431  name = self.namename or self.default_name
432  title = self.titletitle or self.default_title
433  description = self.descriptiondescription or self.default_description
434  check = self.checkcheck or self.default_check
435 
436  name = formatter.format(name,
437  x_part_name=x_part_name,
438  y_part_name=y_part_name,
439  **replacement_dict)
440 
441  title = formatter.format(title,
442  x_part_name=x_part_name,
443  y_part_name=y_part_name,
444  **replacement_dict)
445 
446  description = formatter.format(description,
447  x_part_name=x_part_name,
448  y_part_name=y_part_name,
449  **replacement_dict)
450 
451  check = formatter.format(check,
452  x_part_name=x_part_name,
453  y_part_name=y_part_name,
454  **replacement_dict)
455 
456  profile_plot = ValidationPlot(name)
457 
458  plot_kind = self.plot_kindplot_kind
459  if plot_kind == "profile":
460  profile_plot.profile(x_parts,
461  y_parts,
462  lower_bound=self.lower_boundlower_bound,
463  upper_bound=self.upper_boundupper_bound,
464  bins=self.binsbins,
465  y_binary=self.y_binaryy_binary,
466  y_log=self.y_logy_log,
467  outlier_z_score=self.outlier_z_scoreoutlier_z_score,
468  allow_discrete=self.allow_discreteallow_discrete,
469  stackby=stackby_parts)
470 
471  if self.fitfit:
472  if self.fit_z_scorefit_z_score is None:
473  kwds = dict()
474  else:
475  kwds = dict(z_score=self.fit_z_scorefit_z_score)
476 
477  fit_method_name = 'fit_' + str(self.fitfit)
478  try:
479  fit_method = getattr(profile_plot, fit_method_name)
480  except BaseException:
481  profile_plot.fit(str(self.fitfit), **kwds)
482  else:
483  fit_method(**kwds)
484 
485  elif plot_kind == "scatter":
486  profile_plot.scatter(x_parts,
487  y_parts,
488  lower_bound=self.lower_boundlower_bound,
489  upper_bound=self.upper_boundupper_bound,
490  outlier_z_score=self.outlier_z_scoreoutlier_z_score,
491  stackby=stackby_parts)
492 
493  profile_plot.title = title
494  profile_plot.contact = contact
495  profile_plot.description = description
496  profile_plot.check = check
497 
498  profile_plot.xlabel = compose_axis_label(x_part_name)
499  profile_plot.ylabel = compose_axis_label(y_part_name, self.y_unity_unit)
500 
501  if tdirectory:
502  profile_plot.write(tdirectory)
503 
504  @staticmethod
506  """check if a list has at least two unique values"""
507  first_x = xs[0]
508  for x in xs:
509  if x != first_x:
510  return True
511  else:
512  return False
513 
514 
516  """Refiner for profile histograms"""
517 
518  default_name = "{module.id}_{y_part_name}_by_{x_part_name}_profile{groupby_key}{stackby_key}"
519 
520  default_title = "Profile of {y_part_name} by {x_part_name} from {module.title}"
521 
522  default_contact = "{module.contact}"
523 
524  default_description = "This is a profile of {y_part_name} over {x_part_name}."
525 
526  default_check = "Check if the trend line is reasonable."
527 
528 
529  plot_kind = "profile"
530 
531 
533  """Refiner for 2D scatterplots"""
534 
535  default_name = "{module.id}_{y_part_name}_by_{x_part_name}_scatter{groupby_key}{stackby_key}"
536 
537  default_title = "Scatter of {y_part_name} by {x_part_name} from {module.title}"
538 
539  default_contact = "{module.contact}"
540 
541  default_description = "This is a scatter of {y_part_name} over {x_part_name}."
542 
543  default_check = "Check if the distributions is reasonable."
544 
545 
546  plot_kind = "scatter"
547 
548 
550  """Refiner for truth-classification analyses"""
551 
552 
553  default_contact = "{module.contact}"
554 
555 
556  default_truth_name = "{part_name}_truth"
557 
558  default_estimate_name = "{part_name}_estimate"
559 
560  def __init__(self,
561  part_name=None,
562  contact=None,
563  estimate_name=None,
564  truth_name=None,
565  cut_direction=None,
566  cut=None,
567  lower_bound=None,
568  upper_bound=None,
569  outlier_z_score=None,
570  allow_discrete=False,
571  unit=None):
572  """Constructor for this refiner"""
573 
574 
575  self.part_namepart_name = part_name
576 
577  self.contactcontact = contact
578 
579  self.estimate_nameestimate_name = estimate_name
580 
581  self.truth_nametruth_name = truth_name
582 
583 
584  self.cutcut = cut
585 
586  self.cut_directioncut_direction = cut_direction
587 
588 
589  self.lower_boundlower_bound = lower_bound
590 
591  self.upper_boundupper_bound = upper_bound
592 
593  self.outlier_z_scoreoutlier_z_score = outlier_z_score
594 
595  self.allow_discreteallow_discrete = allow_discrete
596 
597  self.unitunit = unit
598 
599  def refine(self,
600  harvesting_module,
601  crops,
602  tdirectory=None,
603  groupby_part_name=None,
604  groupby_value=None,
605  **kwds):
606  """Process the truth-classification analysis"""
607 
608  replacement_dict = dict(
609  refiner=self,
610  module=harvesting_module,
611  groupby_key='_' + groupby_part_name + groupby_value if groupby_part_name else "",
612  groupby=groupby_part_name, # deprecated
613  groupby_value=groupby_value, # deprecated
614  )
615 
616  contact = self.contactcontact or self.default_contactdefault_contact
617  contact = formatter.format(contact, **replacement_dict)
618 
619  if self.truth_nametruth_name is not None:
620  truth_name = self.truth_nametruth_name
621  else:
622  truth_name = self.default_truth_namedefault_truth_name
623 
624  truth_name = formatter.format(truth_name, part_name=self.part_namepart_name)
625  truths = crops[truth_name]
626 
627  if self.estimate_nameestimate_name is not None:
628  estimate_name = self.estimate_nameestimate_name
629  else:
630  estimate_name = self.default_estimate_namedefault_estimate_name
631 
632  if isinstance(estimate_name, str):
633  estimate_names = [estimate_name, ]
634  else:
635  estimate_names = estimate_name
636 
637  for estimate_name in estimate_names:
638  estimate_name = formatter.format(estimate_name, part_name=self.part_namepart_name)
639  estimates = crops[estimate_name]
640 
641  classification_analysis = ClassificationAnalysis(quantity_name=estimate_name,
642  contact=contact,
643  cut_direction=self.cut_directioncut_direction,
644  cut=self.cutcut,
645  lower_bound=self.lower_boundlower_bound,
646  upper_bound=self.upper_boundupper_bound,
647  outlier_z_score=self.outlier_z_scoreoutlier_z_score,
648  allow_discrete=self.allow_discreteallow_discrete,
649  unit=self.unitunit)
650 
651  classification_analysis.analyse(estimates, truths)
652 
653  if tdirectory:
654  classification_analysis.write(tdirectory)
655 
656 
658  """Refiner for pull analyses"""
659 
660 
661  default_name = "{module.id}_{quantity_name}"
662 
663  default_contact = "{module.contact}"
664 
665  default_title_postfix = " from {module.title}"
666 
667 
668  default_truth_name = "{part_name}_truth"
669 
670  default_estimate_name = "{part_name}_estimate"
671 
672  default_variance_name = "{part_name}_variance"
673 
674  def __init__(self,
675  name=None,
676  contact=None,
677  title_postfix=None,
678  part_name=None,
679  part_names=None,
680  truth_name=None,
681  estimate_name=None,
682  variance_name=None,
683  quantity_name=None,
684  aux_names=None,
685  unit=None,
686  outlier_z_score=None,
687  absolute=False,
688  which_plots=None):
689  """Constructor for this refiner"""
690  if aux_names is None:
691  aux_names = []
692 
693  self.namename = name
694 
695  self.contactcontact = contact
696 
697  self.title_postfixtitle_postfix = title_postfix
698 
699 
700  self.part_namespart_names = []
701  if part_names is not None:
702  self.part_namespart_names = part_names
703 
704  if part_name is not None:
705  self.part_namespart_names.append(part_name)
706 
707 
708  self.truth_nametruth_name = truth_name
709 
710  self.estimate_nameestimate_name = estimate_name
711 
712  self.variance_namevariance_name = variance_name
713 
714 
715  self.quantity_namequantity_name = quantity_name
716 
717  self.unitunit = unit
718 
719 
720  self.aux_namesaux_names = aux_names
721 
722 
723  self.outlier_z_scoreoutlier_z_score = outlier_z_score
724 
725  self.absoluteabsolute = absolute
726 
727  self.which_plotswhich_plots = which_plots
728 
729  def refine(self,
730  harvesting_module,
731  crops,
732  tdirectory=None,
733  groupby_part_name=None,
734  groupby_value=None,
735  **kwds):
736  """Process the pull analysis"""
737 
738  replacement_dict = dict(
739  refiner=self,
740  module=harvesting_module,
741  # stackby_key='_' + stackby if stackby else "",
742  groupby_key='_' + groupby_part_name + groupby_value if groupby_part_name else "",
743  groupby=groupby_part_name, # deprecated
744  groupby_value=groupby_value, # deprecated
745  )
746 
747  contact = self.contactcontact or self.default_contactdefault_contact
748  contact = formatter.format(contact, **replacement_dict)
749 
750  name = self.namename or self.default_namedefault_name
751 
752  if self.aux_namesaux_names:
753  auxiliaries = select_crop_parts(crops, self.aux_namesaux_names)
754  else:
755  auxiliaries = {}
756 
757  for part_name in self.part_namespart_names:
758  name = formatter.format(name, part_name=part_name, **replacement_dict)
759  plot_name = name + "_{subplot_name}"
760 
761  title_postfix = self.title_postfixtitle_postfix
762  if title_postfix is None:
763  title_postfix = self.default_title_postfixdefault_title_postfix
764 
765  title_postfix = formatter.format(title_postfix, part_name=part_name, **replacement_dict)
766  plot_title = "{subplot_title} of {quantity_name}" + title_postfix
767 
768  if self.truth_nametruth_name is not None:
769  truth_name = self.truth_nametruth_name
770  else:
771  truth_name = self.default_truth_namedefault_truth_name
772 
773  if self.estimate_nameestimate_name is not None:
774  estimate_name = self.estimate_nameestimate_name
775  else:
776  estimate_name = self.default_estimate_namedefault_estimate_name
777 
778  if self.variance_namevariance_name is not None:
779  variance_name = self.variance_namevariance_name
780  else:
781  variance_name = self.default_variance_namedefault_variance_name
782 
783  truth_name = formatter.format(truth_name, part_name=part_name)
784  estimate_name = formatter.format(estimate_name, part_name=part_name)
785  variance_name = formatter.format(variance_name, part_name=part_name)
786 
787  truths = crops[truth_name]
788  estimates = crops[estimate_name]
789  try:
790  variances = crops[variance_name]
791  except KeyError:
792  variances = None
793 
794  quantity_name = self.quantity_namequantity_name or part_name
795 
796  which_plots = self.which_plotswhich_plots
797 
798  pull_analysis = PullAnalysis(quantity_name,
799  unit=self.unitunit,
800  absolute=self.absoluteabsolute,
801  outlier_z_score=self.outlier_z_scoreoutlier_z_score,
802  plot_name=plot_name,
803  plot_title=plot_title)
804 
805  pull_analysis.analyse(truths,
806  estimates,
807  variances,
808  auxiliaries=auxiliaries,
809  which_plots=which_plots)
810 
811  pull_analysis.contact = contact
812 
813  if tdirectory:
814  pull_analysis.write(tdirectory)
815 
816 
818  """Refiner for ROOT TTrees"""
819 
820 
821  default_name = "{module.id}_tree"
822 
823  default_title = "Tree of {module.id}"
824 
825  def __init__(self,
826  name=None,
827  title=None):
828  """Constructor for this refiner"""
829  super(SaveTreeRefiner, self).__init__()
830 
831 
832  self.namename = name
833 
834  self.titletitle = title
835 
836  def refine(self,
837  harvesting_module,
838  crops,
839  tdirectory=None,
840  groupby_part_name=None,
841  groupby_value=None,
842  **kwds):
843  """Process the TTree"""
844 
845  replacement_dict = dict(
846  refiner=self,
847  module=harvesting_module,
848  groupby_key='_' + groupby_part_name + groupby_value if groupby_part_name else "",
849  groupby=groupby_part_name, # deprecated
850  groupby_value=groupby_value, # deprecated
851  )
852 
853  with root_cd(tdirectory):
854  name = self.namename or self.default_namedefault_name
855  title = self.titletitle or self.default_titledefault_title
856 
857  name = formatter.format(name, **replacement_dict)
858  title = formatter.format(title, **replacement_dict)
859 
860  output_ttree = ROOT.TTree(root_save_name(name), title)
861  for part_name, parts in iter_items_sorted_for_key(crops):
862  self.add_branchadd_branch(output_ttree, part_name, parts)
863 
864  output_ttree.FlushBaskets()
865  output_ttree.Write()
866 
867  def add_branch(self, output_ttree, part_name, parts):
868  """Add a TBranch to the TTree"""
869  input_value = np.zeros(1, dtype=float)
870 
871  branch_type_spec = '%s/D' % part_name
872  tbranch = output_ttree.Branch(part_name, input_value, branch_type_spec)
873 
874  if output_ttree.GetNbranches() == 1:
875  # On filling of the first branch we need to use the fill method of the TTree
876  # For all other branches we can use the one of the branch
877  # #justrootthings
878  for value in parts:
879  input_value[0] = value
880  output_ttree.Fill()
881 
882  else:
883  for value in parts:
884  input_value[0] = value
885  tbranch.Fill()
886 
887  output_ttree.GetEntry(0)
888  output_ttree.ResetBranchAddress(tbranch)
889  also_subbranches = True # No subbranches here but we drop the buffers just in case.
890  output_ttree.DropBranchFromCache(tbranch, also_subbranches)
891 
892 
894  """Refiner for filters"""
895 
896  def __init__(self, wrapped_refiner, filter=None, on=None):
897  """Constructor for this refiner"""
898 
899 
900  self.wrapped_refinerwrapped_refiner = wrapped_refiner
901 
902  if filter is None:
903 
904  self.filterfilter = np.nonzero
905  else:
906  self.filterfilter = filter
907 
908 
909  self.onon = on
910 
911  def refine(self, harvesting_module, crops, *args, **kwds):
912  """Process this filter"""
913  filtered_crops = filter_crops(crops, self.filterfilter, part_name=self.onon)
914  self.wrapped_refinerwrapped_refiner(harvesting_module, filtered_crops, *args, **kwds)
915 
916 
918  """Refiner for selection"""
919 
920  def __init__(self, wrapped_refiner, select=None, exclude=None):
921  """Constructor for this refiner"""
922  if select is None:
923  select = []
924  if exclude is None:
925  exclude = []
926 
927  self.wrapped_refinerwrapped_refiner = wrapped_refiner
928 
929  self.selectselect = select
930 
931  self.excludeexclude = exclude
932 
933  def refine(self, harvesting_module, crops, *args, **kwds):
934  """Process this selection"""
935  selected_crops = select_crop_parts(crops, select=self.selectselect, exclude=self.excludeexclude)
936  self.wrapped_refinerwrapped_refiner(harvesting_module, selected_crops, *args, **kwds)
937 
938 
940  """Refiner for grouping"""
941 
942 
943  default_exclude_by = True
944 
945  def __init__(self,
946  wrapped_refiner,
947  by=None,
948  exclude_by=None):
949  """Constructor for this refiner"""
950  if by is None:
951  by = []
952 
953  self.wrapped_refinerwrapped_refiner = wrapped_refiner
954 
955  self.byby = by
956 
957  self.exclude_byexclude_by = exclude_by if exclude_by is not None else self.default_exclude_bydefault_exclude_by
958 
959  def refine(self,
960  harvesting_module,
961  crops,
962  groupby_part_name=None,
963  groupby_value=None,
964  *args,
965  **kwds):
966  """Process this grouping"""
967 
968  by = self.byby
969 
970  # A single name to do the group by
971  if isinstance(by, str) or by is None:
972  part_name = by
973  # Wrap it into a list an continue with the general case
974  by = [part_name, ]
975 
976  for groupby_spec in by:
977  if groupby_spec is None:
978  # Using empty string as groupby_value to indicate that all values have been selected
979  value = None
980  self.wrapped_refinerwrapped_refiner(harvesting_module,
981  crops,
982  groupby_part_name=None,
983  groupby_value=value,
984  *args,
985  **kwds)
986  continue
987 
988  elif isinstance(groupby_spec, str):
989  part_name = groupby_spec
990  groupby_parts = crops[part_name]
991  unique_values, index_of_values = np.unique(groupby_parts, return_inverse=True)
992  groupby_values = [" = {value}]".format(value=value) for value in unique_values]
993 
994  elif isinstance(groupby_spec, tuple):
995  part_name = groupby_spec[0]
996  cuts = groupby_spec[1]
997 
998  groupby_parts = crops[part_name]
999 
1000  # Take care of nans
1001  digitization_cuts = list(np.sort(cuts))
1002  if digitization_cuts[-1] != np.inf:
1003  digitization_cuts.append(np.inf)
1004  index_of_values = np.digitize(groupby_parts, digitization_cuts, right=True)
1005 
1006  groupby_values = ["below {upper_bound}".format(upper_bound=digitization_cuts[0])]
1007  bin_bounds = list(zip(digitization_cuts[0:], digitization_cuts[1:]))
1008  for lower_bound, upper_bound in bin_bounds:
1009  if lower_bound == upper_bound:
1010  # degenerated bin case
1011  groupby_values.append("= {lower_bound}".format(lower_bound=lower_bound))
1012  elif upper_bound == np.inf:
1013  groupby_values.append("above {lower_bound}".format(lower_bound=lower_bound))
1014  else:
1015  groupby_values.append("between {lower_bound} and {upper_bound}".format(lower_bound=lower_bound,
1016  upper_bound=upper_bound))
1017  groupby_values.append("is nan")
1018  assert len(groupby_values) == len(digitization_cuts) + 1
1019 
1020  else:
1021  raise ValueError("Unknown groupby specification %s" % groupby_spec)
1022 
1023  # Exclude the groupby variable if desired
1024  selected_crops = select_crop_parts(crops, exclude=part_name if self.exclude_byexclude_by else None)
1025  for index_of_value, groupby_value in enumerate(groupby_values):
1026  indices_for_value = index_of_values == index_of_value
1027  if not np.any(indices_for_value):
1028  continue
1029 
1030  filtered_crops = filter_crops(selected_crops, indices_for_value)
1031 
1032  self.wrapped_refinerwrapped_refiner(harvesting_module,
1033  filtered_crops,
1034  groupby_part_name=part_name,
1035  groupby_value=groupby_value,
1036  *args,
1037  **kwds)
1038 
1039 
1041  """Refiner for change-directory"""
1042 
1043 
1044  default_folder_name = ""
1045 
1046  default_groupby_addition = "_groupby_{groupby}_{groupby_value}"
1047 
1048  def __init__(self,
1049  wrapped_refiner,
1050  folder_name=None,
1051  groupby_addition=None):
1052  """Constructor for this refiner"""
1053 
1054 
1055  self.wrapped_refinerwrapped_refiner = wrapped_refiner
1056 
1057  self.folder_namefolder_name = folder_name
1058 
1059  self.groupby_additiongroupby_addition = groupby_addition
1060 
1061  def refine(self,
1062  harvesting_module,
1063  crops,
1064  tdirectory=None,
1065  groupby_part_name=None,
1066  groupby_value=None,
1067  *args,
1068  **kwds):
1069  """Process the change-directory"""
1070 
1071  folder_name = self.folder_namefolder_name
1072  if folder_name is None:
1073  if groupby_value is not None:
1074  folder_name = "{groupby_addition}"
1075  else:
1076  folder_name = self.default_folder_namedefault_folder_name
1077 
1078  groupby_addition = self.groupby_additiongroupby_addition
1079 
1080  if groupby_addition is None:
1081  groupby_addition = self.default_groupby_additiondefault_groupby_addition
1082 
1083  if groupby_part_name is None and groupby_value is None:
1084  groupby_addition = ""
1085  else:
1086  groupby_addition = formatter.format(groupby_addition,
1087  groupby=groupby_part_name,
1088  groupby_value=groupby_value)
1089 
1090  folder_name = formatter.format(folder_name,
1091  groupby_addition=groupby_addition,
1092  groupby=groupby_part_name,
1093  groupby_value=groupby_value)
1094 
1095  folder_name = '/'.join(root_save_name(name) for name in folder_name.split('/'))
1096 
1097  with root_cd(tdirectory):
1098  with root_cd(folder_name) as tdirectory:
1099  self.wrapped_refinerwrapped_refiner(harvesting_module,
1100  crops,
1101  tdirectory=tdirectory,
1102  groupby_part_name=groupby_part_name,
1103  groupby_value=groupby_value,
1104  *args,
1105  **kwds)
1106 
1107 
1109  """Refiner for expert-level categorization"""
1110 
1111  def __init__(self, wrapped_refiner, above_expert_level=None, below_expert_level=None):
1112  """Constructor for this refiner"""
1113 
1114 
1115  self.wrapped_refinerwrapped_refiner = wrapped_refiner
1116 
1117  self.above_expert_levelabove_expert_level = above_expert_level
1118 
1119  self.below_expert_levelbelow_expert_level = below_expert_level
1120 
1121  def refine(self, harvesting_module, crops, *args, **kwds):
1122  """Process the expert-level categorization"""
1123 
1124  above_expert_level = self.above_expert_levelabove_expert_level
1125  below_expert_level = self.below_expert_levelbelow_expert_level
1126 
1127  proceed = True
1128  if above_expert_level is not None:
1129  proceed = proceed and harvesting_module.expert_level > above_expert_level
1130 
1131  if below_expert_level is not None:
1132  proceed = proceed and harvesting_module.expert_level < below_expert_level
1133 
1134  if proceed:
1135  self.wrapped_refinerwrapped_refiner(harvesting_module, crops, *args, **kwds)
1136 
1137 
1138 # Meta refiner decorators
1139 def groupby(refiner=None, **kwds):
1140  def group_decorator(wrapped_refiner):
1141  return GroupByRefiner(wrapped_refiner, **kwds)
1142  if refiner is None:
1143  return group_decorator
1144  else:
1145  return group_decorator(refiner)
1146 
1147 
1148 def select(refiner=None, **kwds):
1149  def select_decorator(wrapped_refiner):
1150  return SelectRefiner(wrapped_refiner, **kwds)
1151  if refiner is None:
1152  return select_decorator
1153  else:
1154  return select_decorator(refiner)
1155 
1156 
1157 def filter(refiner=None, **kwds):
1158  def filter_decorator(wrapped_refiner):
1159  return FilterRefiner(wrapped_refiner, **kwds)
1160  if refiner is None:
1161  return filter_decorator
1162  else:
1163  return filter_decorator(refiner)
1164 
1165 
1166 def cd(refiner=None, **kwds):
1167  def cd_decorator(wrapped_refiner):
1168  return CdRefiner(wrapped_refiner, **kwds)
1169  if refiner is None:
1170  return cd_decorator
1171  else:
1172  return cd_decorator(refiner)
1173 
1174 
1175 def context(refiner=None,
1176  above_expert_level=None, below_expert_level=None,
1177  folder_name=None, folder_groupby_addition=None,
1178  filter=None, filter_on=None,
1179  groupby=None, exclude_groupby=None,
1180  select=None, exclude=None):
1181 
1182  def context_decorator(wrapped_refiner):
1183  # Apply meta refiners in the reverse order that they shall be executed
1184  if exclude is not None or select is not None:
1185  wrapped_refiner = SelectRefiner(wrapped_refiner,
1186  select=select, exclude=exclude)
1187 
1188  if folder_name is not None or groupby is not None or folder_groupby_addition is not None:
1189  wrapped_refiner = CdRefiner(wrapped_refiner,
1190  folder_name=folder_name,
1191  groupby_addition=folder_groupby_addition)
1192 
1193  if groupby is not None:
1194  wrapped_refiner = GroupByRefiner(wrapped_refiner,
1195  by=groupby,
1196  exclude_by=exclude_groupby)
1197 
1198  if filter is not None or filter_on is not None:
1199  wrapped_refiner = FilterRefiner(wrapped_refiner,
1200  filter=filter,
1201  on=filter_on)
1202 
1203  if above_expert_level is not None or below_expert_level is not None:
1204  wrapped_refiner = ExpertLevelRefiner(wrapped_refiner,
1205  above_expert_level=above_expert_level,
1206  below_expert_level=below_expert_level)
1207 
1208  if not isinstance(wrapped_refiner, Refiner):
1209  wrapped_refiner = Refiner(wrapped_refiner)
1210 
1211  return wrapped_refiner
1212 
1213  if refiner is None:
1214  return context_decorator
1215  else:
1216  return functools.wraps(refiner)(context_decorator(refiner))
1217 
1218 
1219 def refiner_with_context(refiner_factory):
1220  @functools.wraps(refiner_factory)
1221  def module_decorator_with_context(above_expert_level=None, below_expert_level=None,
1222  folder_name=None, folder_groupby_addition=None,
1223  filter=None, filter_on=None,
1224  groupby=None, exclude_groupby=None,
1225  select=None, exclude=None,
1226  **kwds_for_refiner_factory):
1227 
1228  refiner = refiner_factory(**kwds_for_refiner_factory)
1229 
1230  return context(refiner,
1231  above_expert_level=above_expert_level, below_expert_level=below_expert_level,
1232  folder_name=folder_name, folder_groupby_addition=folder_groupby_addition,
1233  filter=filter, filter_on=filter_on,
1234  groupby=groupby, exclude_groupby=exclude_groupby,
1235  select=select, exclude=exclude)
1236 
1237  return module_decorator_with_context
1238 
1239 
1240 @refiner_with_context
1241 def save_fom(**kwds):
1242  return SaveFiguresOfMeritRefiner(**kwds)
1243 
1244 
1245 @refiner_with_context
1246 def save_histograms(**kwds):
1247  return SaveHistogramsRefiner(**kwds)
1248 
1249 
1250 @refiner_with_context
1251 def save_profiles(**kwds):
1252  return SaveProfilesRefiner(**kwds)
1253 
1254 
1255 @refiner_with_context
1256 def save_scatters(**kwds):
1257  return SaveScatterRefiner(**kwds)
1258 
1259 
1260 @refiner_with_context
1261 def save_classification_analysis(**kwds):
1262  return SaveClassificationAnalysisRefiner(**kwds)
1263 
1264 
1265 @refiner_with_context
1266 def save_pull_analysis(**kwds):
1267  return SavePullAnalysisRefiner(**kwds)
1268 
1269 
1270 @refiner_with_context
1271 def save_tree(**kwds):
1272  return SaveTreeRefiner(**kwds)
1273 
1274 
1275 def select_crop_parts(crops, select=None, exclude=None):
1276  if select is None:
1277  select = []
1278  if exclude is None:
1279  exclude = []
1280 
1281  if isinstance(select, str):
1282  select = [select, ]
1283 
1284  if isinstance(exclude, str):
1285  exclude = [exclude, ]
1286 
1287  if isinstance(crops, collections.MutableMapping):
1288  part_names = list(crops.keys())
1289 
1290  if not select and not exclude:
1291  return crops
1292 
1293  if select:
1294  not_selected_part_names = [name for name in part_names if name not in select]
1295 
1296  # if the selection item is a callable function do not count it as not selectable yet
1297  select_not_in_part_names = [name for name in select
1298  if not isinstance(name, collections.Callable) and name not in part_names]
1299  if select_not_in_part_names:
1300  get_logger().warning("Cannot select %s, because they are not in crop part names %s",
1301  select_not_in_part_names, sorted(part_names))
1302  else:
1303  not_selected_part_names = []
1304 
1305  if exclude:
1306  excluded_part_names = [name for name in part_names if name in exclude]
1307  else:
1308  excluded_part_names = []
1309 
1310  excluded_part_names.extend(not_selected_part_names)
1311 
1312  # Make a shallow copy
1313  selected_crops = copy.copy(crops)
1314  for part_name in set(excluded_part_names):
1315  del selected_crops[part_name]
1316 
1317  if isinstance(select, collections.Mapping):
1318  # select is a rename mapping
1319  for part_name, new_part_name in list(select.items()):
1320  if isinstance(part_name, collections.Callable):
1321  selected_crops[new_part_name] = part_name(**crops)
1322  elif part_name in selected_crops:
1323  parts = selected_crops[part_name]
1324  del selected_crops[part_name]
1325  selected_crops[new_part_name] = parts
1326 
1327  return selected_crops
1328 
1329  else:
1330  raise ValueError("Unrecognised crop %s of type %s" % (crops, type(crops)))
1331 
1332 
1333 def filter_crops(crops, filter_function, part_name=None):
1334  if isinstance(filter_function, np.ndarray):
1335  filter_indices = filter_function
1336  else:
1337  parts = crops[part_name]
1338  filter_indices = filter_function(parts)
1339 
1340  if isinstance(crops, np.ndarray):
1341  return crops[filter_indices]
1342 
1343  elif isinstance(crops, collections.MutableMapping):
1344  # Make a shallow copy
1345  filtered_crops = copy.copy(crops)
1346  for part_name, parts in list(crops.items()):
1347  filtered_crops[part_name] = parts[filter_indices]
1348  return filtered_crops
1349 
1350  else:
1351  raise ValueError("Unrecognised crop %s of type %s" % (crops, type(crops)))
1352 
1353 
1354 def iter_items_sorted_for_key(crops):
1355  # is the type of crops is a dictionary assume, that it should be sorted
1356  # in all other cases the users class has to take care of the sorting
1357  if isinstance(crops, dict):
1358  keys = sorted(crops.keys())
1359  return ((key, crops[key]) for key in keys)
1360  else:
1361  return list(crops.items())
def __init__(self, wrapped_refiner, folder_name=None, groupby_addition=None)
Definition: refiners.py:1051
folder_name
cached value of the folder name
Definition: refiners.py:1057
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, *args, **kwds)
Definition: refiners.py:1068
wrapped_refiner
cached value of the wrapped refiner
Definition: refiners.py:1055
string default_groupby_addition
Default suffix for a groupby selection.
Definition: refiners.py:1046
groupby_addition
cached value of the suffix for a groupby selection
Definition: refiners.py:1059
string default_folder_name
Folder name to be used if a groupby selection is active.
Definition: refiners.py:1044
below_expert_level
cached value of the lower range of the expert level
Definition: refiners.py:1119
wrapped_refiner
cached value of the wrapped refiner
Definition: refiners.py:1115
def refine(self, harvesting_module, crops, *args, **kwds)
Definition: refiners.py:1121
def __init__(self, wrapped_refiner, above_expert_level=None, below_expert_level=None)
Definition: refiners.py:1111
above_expert_level
cached value of the upper range of the expert level
Definition: refiners.py:1117
on
cached value of the part name to filter on
Definition: refiners.py:909
wrapped_refiner
cached value of the wrapped refiner
Definition: refiners.py:900
def refine(self, harvesting_module, crops, *args, **kwds)
Definition: refiners.py:911
filter
cached value of the filter
Definition: refiners.py:904
def __init__(self, wrapped_refiner, filter=None, on=None)
Definition: refiners.py:896
by
cached value of the group-by classifier
Definition: refiners.py:955
def __init__(self, wrapped_refiner, by=None, exclude_by=None)
Definition: refiners.py:948
wrapped_refiner
cached value of the wrapped refiner
Definition: refiners.py:953
exclude_by
cached value of the exclude-by classifier
Definition: refiners.py:957
bool default_exclude_by
default value of the exclude-by classifier
Definition: refiners.py:943
def refine(self, harvesting_module, crops, groupby_part_name=None, groupby_value=None, *args, **kwds)
Definition: refiners.py:965
title
cached user-defined title for this profile histogram / scatterplot
Definition: refiners.py:344
y_log
cached flag for logarithmic y axis for this profile histogram / scatterplot
Definition: refiners.py:371
description
cached user-defined description for this profile histogram / scatterplot
Definition: refiners.py:347
contact
cached user-defined contact person for this profile histogram / scatterplot
Definition: refiners.py:351
fit
cached fit for this profile histogram / scatterplot
Definition: refiners.py:379
upper_bound
cached upper bound for this profile histogram / scatterplot
Definition: refiners.py:365
outlier_z_score
cached Z-score (for outlier detection) for this profile histogram / scatterplot
Definition: refiners.py:374
y_binary
cached flag for probability y axis (range 0.0 .
Definition: refiners.py:369
skip_single_valued
cached flag to skip single-valued bins for this profile histogram / scatterplot
Definition: refiners.py:384
allow_discrete
cached flag to allow discrete values for this profile histogram / scatterplot
Definition: refiners.py:376
fit_z_score
cached fit Z-score (for outlier detection) for this profile histogram / scatterplot
Definition: refiners.py:381
stackby
cached stacking selection for this profile histogram / scatterplot
Definition: refiners.py:358
y_unit
cached measurement unit for ordinate
Definition: refiners.py:360
def __init__(self, y, x=None, name=None, title=None, contact=None, description=None, check=None, stackby=None, y_unit=None, y_binary=None, y_log=None, lower_bound=None, upper_bound=None, bins=None, outlier_z_score=None, fit=None, fit_z_score=None, skip_single_valued=False, allow_discrete=False)
Definition: refiners.py:336
string plot_kind
by default, this refiner is for profile histograms
Definition: refiners.py:315
name
cached user-defined name for this profile histogram / scatterplot
Definition: refiners.py:342
bins
cached number of bins for this profile histogram / scatterplot
Definition: refiners.py:367
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, **kwds)
Definition: refiners.py:392
lower_bound
cached lower bound for this profile histogram / scatterplot
Definition: refiners.py:363
check
cached user-defined user-check action for this profile histogram / scatterplot
Definition: refiners.py:349
refiner_function
cached copy of the instance's refiner function
Definition: refiners.py:40
def __init__(self, refiner_function=None)
Definition: refiners.py:37
def refine(self, harvesting_module, *args, **kwds)
Definition: refiners.py:69
def __get__(self, harvesting_module, cls=None)
Definition: refiners.py:42
def __call__(self, harvesting_module, crops=None, *args, **kwds)
Definition: refiners.py:55
truth_name
cached truth-values-collection name for this truth-classification analysis
Definition: refiners.py:581
cut
cached threshold of estimates for this truth-classification analysis
Definition: refiners.py:584
contact
cached contact person for this truth-classification analysis
Definition: refiners.py:577
upper_bound
cached upper bound of estimates for this truth-classification analysis
Definition: refiners.py:591
outlier_z_score
cached Z-score (for outlier detection) of estimates for this truth-classification analysis
Definition: refiners.py:593
allow_discrete
cached discrete-value flag of estimates for this truth-classification analysis
Definition: refiners.py:595
unit
cached measurement unit of estimates for this truth-classification analysis
Definition: refiners.py:597
string default_truth_name
default name for the truth-classification analysis truth-values collection
Definition: refiners.py:556
estimate_name
cached estimates-collection name for this truth-classification analysis
Definition: refiners.py:579
string default_estimate_name
default name for the truth-classification analysis estimates collection
Definition: refiners.py:558
cut_direction
cached cut direction (> or <) of estimates for this truth-classification analysis
Definition: refiners.py:586
def __init__(self, part_name=None, contact=None, estimate_name=None, truth_name=None, cut_direction=None, cut=None, lower_bound=None, upper_bound=None, outlier_z_score=None, allow_discrete=False, unit=None)
Definition: refiners.py:571
part_name
cached part name for this truth-classification analysis
Definition: refiners.py:575
string default_contact
default contact person for this truth-classification analysis
Definition: refiners.py:553
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, **kwds)
Definition: refiners.py:605
lower_bound
cached lower bound of estimates for this truth-classification analysis
Definition: refiners.py:589
title
cached title of the figure of merit
Definition: refiners.py:113
description
cached description of the figure of merit
Definition: refiners.py:116
contact
cached contact person of the figure of merit
Definition: refiners.py:120
def __init__(self, name=None, title=None, contact=None, description=None, check=None, key=None, aggregation=None)
Definition: refiners.py:105
string default_description
default description for this refiner
Definition: refiners.py:83
def mean(xs)
return the mean of the parts, ignoring NaNs
Definition: refiners.py:91
string default_key
default key name for this refiner
Definition: refiners.py:87
def default_aggregation
default aggregation is the mean of the parts
Definition: refiners.py:95
aggregation
cached copy of the crops-aggregation method
Definition: refiners.py:125
string default_check
default user-check action for this refiner
Definition: refiners.py:85
string default_title
default title for this refiner
Definition: refiners.py:79
key
cached copy of the figures-of-merit key
Definition: refiners.py:123
name
cached name of the figure of merit
Definition: refiners.py:111
string default_contact
default contact person for this refiner
Definition: refiners.py:81
string default_name
default name for this refiner
Definition: refiners.py:77
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, **kwds)
Definition: refiners.py:133
check
cached user-check action of the figure of merit
Definition: refiners.py:118
title
cached user-defined title for this histogram
Definition: refiners.py:214
description
cached user-defined description for this histogram
Definition: refiners.py:217
contact
cached user-defined contact person for this histogram
Definition: refiners.py:221
fit
cached fit for this histogram
Definition: refiners.py:238
upper_bound
cached upper bound for this histogram
Definition: refiners.py:226
outlier_z_score
cached Z-score (for outlier detection) for this histogram
Definition: refiners.py:231
allow_discrete
cached flag to allow discrete values for this histogram
Definition: refiners.py:233
string default_description
default description for this histogram
Definition: refiners.py:189
def __init__(self, name=None, title=None, contact=None, description=None, check=None, lower_bound=None, upper_bound=None, bins=None, outlier_z_score=None, allow_discrete=False, stackby="", fit=None, fit_z_score=None)
Definition: refiners.py:206
fit_z_score
cached fit Z-score (for outlier detection) for this histogram
Definition: refiners.py:240
stackby
cached stacking selection for this histogram
Definition: refiners.py:235
string default_check
default user-check action for this histogram
Definition: refiners.py:191
string default_title
default title for this histogram
Definition: refiners.py:185
name
cached user-defined name for this histogram
Definition: refiners.py:212
string default_contact
default contact person for this histogram
Definition: refiners.py:187
string default_name
default name for this histogram
Definition: refiners.py:183
bins
cached number of bins for this histogram
Definition: refiners.py:228
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, **kwds)
Definition: refiners.py:248
lower_bound
cached lower bound for this histogram
Definition: refiners.py:224
check
cached user-defined user-check action for this histogram
Definition: refiners.py:219
variance_name
cached name for the pull analysis variances collection
Definition: refiners.py:712
truth_name
cached name for the pull analysis truth-values collection
Definition: refiners.py:708
string default_variance_name
default name for the pull analysis variances collection
Definition: refiners.py:672
quantity_name
cached name of the quantity for the pull analysis
Definition: refiners.py:715
contact
cached contact person for this pull analysis
Definition: refiners.py:695
outlier_z_score
cached Z-score (for outlier detection) for the pull analysis
Definition: refiners.py:723
part_names
cached array of part names for this pull analysis
Definition: refiners.py:700
unit
cached measurement unit for the pull analysis
Definition: refiners.py:717
aux_names
cached auxiliary names for the pull analysis
Definition: refiners.py:720
string default_truth_name
default name for the pull analysis truth-values collection
Definition: refiners.py:668
estimate_name
cached name for the pull analysis estimates collection
Definition: refiners.py:710
string default_estimate_name
default name for the pull analysis estimates collection
Definition: refiners.py:670
title_postfix
cached suffix for the title of this pull analysis
Definition: refiners.py:697
def __init__(self, name=None, contact=None, title_postfix=None, part_name=None, part_names=None, truth_name=None, estimate_name=None, variance_name=None, quantity_name=None, aux_names=None, unit=None, outlier_z_score=None, absolute=False, which_plots=None)
Definition: refiners.py:688
name
cached name for this pull analysis
Definition: refiners.py:693
string default_contact
default contact person for this pull analysis
Definition: refiners.py:663
string default_name
default name for this pull analysis
Definition: refiners.py:661
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, **kwds)
Definition: refiners.py:735
string default_title_postfix
default suffix for the title of this pull analysis
Definition: refiners.py:665
which_plots
cached list of plots produced by the pull analysis
Definition: refiners.py:727
absolute
cached absolute-value-comparison flag for the pull analysis
Definition: refiners.py:725
title
cached title for this TTree
Definition: refiners.py:834
def __init__(self, name=None, title=None)
Definition: refiners.py:827
def add_branch(self, output_ttree, part_name, parts)
Definition: refiners.py:867
string default_title
default title for this TTree
Definition: refiners.py:823
name
cached name for this TTree
Definition: refiners.py:832
string default_name
default name for this TTree
Definition: refiners.py:821
def refine(self, harvesting_module, crops, tdirectory=None, groupby_part_name=None, groupby_value=None, **kwds)
Definition: refiners.py:842
def __init__(self, wrapped_refiner, select=None, exclude=None)
Definition: refiners.py:920
wrapped_refiner
cached value of the wrapped refiner
Definition: refiners.py:927
def refine(self, harvesting_module, crops, *args, **kwds)
Definition: refiners.py:933
exclude
cached value of the exclusion flag
Definition: refiners.py:931
select
cached value of the selector
Definition: refiners.py:929
std::map< ExpRun, std::pair< double, double > > filter(const std::map< ExpRun, std::pair< double, double >> &runs, double cut, std::map< ExpRun, std::pair< double, double >> &runsRemoved)
filter events to remove runs shorter than cut, it stores removed runs in runsRemoved
Definition: Splitter.cc:38