Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
#!/usr/bin/env python # -*- coding: utf-8 -*-
Further implementation of QHistV3, providing the descriptor tailored for each attribute.
"""
equiplist_nullcheck_typecheck, equiplist_typecheck, override_getter_default, getter_plus_doc, setter_isinstance, setter_from_return_plus_doc )
## 3rd-party
#==============================================================================
""" Provide suite of small test here since most of them are already tested in its origin's implementation, just to make sure that the inheritance does not interfere with the mechanism.
Use `prefix` field since it's simplest and has no extra mechanism
Doctest::
## check default >>> h = QHist() >>> h.prefix is None True
## check assignment >>> h.prefix = 'hello' >>> h.prefix 'hello'
## check static assigment >>> h.prefix = 'hola' Traceback (most recent call last): ... AttributeError: Attribute "prefix" already set to 'hello'
## Check slots protection >>> h.xxx = 123 Traceback (most recent call last): ... AttributeError: 'QHist' object has no attribute 'xxx'
## check copying >>> h2 = h() >>> h2.prefix 'hello' >>> h2.prefix = 'world' Traceback (most recent call last): ... AttributeError: Attribute "prefix" already set to 'hello'
## check clearing >>> h2.clear() >>> h2.prefix is None True >>> h2.prefix = 'hello2' >>> h2.prefix 'hello2'
"""
## From lazy_property '_lazy_timestamp', '_lazy_wrapper', '_lazy_filename', ## New attribute '_stats', '_anchors', '_histos', )
#---------------# # Inner methods # #---------------#
""" Allow the init with kwargs.
Doctest::
## Assert that two methods are equivalent. >>> h1 = QHist(name='somename') >>> h1.name 'somename' >>> h2 = QHist() >>> h2.name = 'somename' >>> h1.name == h2.name True
""" ## Note: The order below is very important. ## 1. Super class first ## 2. Initialize local initial value ## 3. Supplied attributes # prefer these first # the rest alphabetically
""" Override the functionality of copy.copy, such that only the attribute at the level of static_struct is transfered, not at QHist level.
Usage::
## Transfer & Independent >>> h1 = QHist(name='myname') >>> h2 = h1() >>> h2.title = 'newtitle' >>> h1.name 'myname' >>> h2.name 'myname'
""" ## Prepare queue, list of attrs that existed only in baseclass and used for prop. ## Transfer queue ## Initialize local initial value ## Finally, return
## For iterator protocol """
>>> len(QHist()) 0 """
""" Get the member histograms, available only after draw. """
#-----------------------------# # Read-only property -- AdHoc # #-----------------------------#
def has_name(self): """ Check if name is originally provided or not.
>>> h = QHist() >>> h.has_name False >>> h.name = 'analysis' >>> h.has_name True """
def is_advance_stack(self): """ True if TPC stack is advance mode. Note to self: This is actually much easier than `is_simple_stack`.
Doctest::
## Default fails >>> QHist().is_advance_stack False
## Not-advance, fails >>> QHist(params='PT').is_advance_stack False >>> QHist(trees=tree).is_advance_stack False >>> QHist(trees=tree, params=['PX','PY']).is_advance_stack False
## Genuine advance TPC >>> QHist(tpc=[[tree, 'PT', '']]).is_advance_stack True >>> QHist(tpc=tpc).is_advance_stack True
"""
def is_simple_stack(self): """ True if condition of simple stack is met, i.e., only one or less of (trees, params, cuts) is a collection, the rest is a single entry.
Doctest::
## Default fails >>> QHist().is_simple_stack False
## Incomplete, consider True to disable advance-TPC >>> QHist(trees=tree).is_simple_stack True >>> QHist(params='PT').is_simple_stack True >>> QHist(cuts='c').is_simple_stack True
## TPC is valid, success >>> QHist(trees=tree, params='PT').is_simple_stack True >>> QHist(trees=[tree,tree], params='PT').is_simple_stack True >>> QHist(trees=tree, params=['PT','PZ']).is_simple_stack True
## False if already an advance stack >>> QHist(tpc=[[tree, 'PT', '']]).is_simple_stack False
""" ## Require this to avoid circular self.tree, self.params ## Because I already have the setter exclude the multiple-stacking, # I have to only check for the empty-inital-condition.
def filename(self): """ Return the current filename (without path, nor extension), deduce from the script that the instance is made.
>>> getfixture('mainfile') >>> QHist().filename 'mainfile' """
def dim(self): """ Doctest::
## Default is zero >>> QHist().dim 0
## Simple TPC >>> QHist(params='PT').dim 1 >>> QHist(params='PT:PZ').dim 2 >>> QHist(params='TMath::Log10(PT)').dim 1 >>> QHist(params='TMath::Log10(PT):PZ').dim 2 >>> QHist(params='PX:PY:PZ').dim 3 >>> QHist(params=('PT:PZ','P:PZ')).dim 2
## 'prof' flag does not change the dim >>> QHist(params='PX:PY:PZ', options='prof').dim 3
## Advance TPC >>> QHist(tpc=[(tree, 'PT', '')]).dim 1 >>> QHist(tpc=[(tree, 'PX:PY', 'nPVs>1')]).dim 2
"""
def height_legend_console(self): """ Return expected height of legend console. """
def height_debug_console(self): """Return expected height of debug console"""
def is_profile(self): """ >>> QHist().is_profile False >>> QHist(options='prof').is_profile True >>> QHist(options='blah').is_profile False >>> QHist(options='sameprof').is_profile True
"""
def debug_messages(self): """ Generate pair of (header,message) to be put in debug console.
>>> getfixture('mainfile'); getfixture('freeze_time')
>>> h = QHist() >>> h.trees = tree >>> h.params = 'mu_PT: DPHI' >>> h.cuts = 'M > 20e3' >>> h.xmin = 1 >>> h.xmax = 100 >>> h.ymin = 0. >>> h.ymax = 3.14 >>> h.ybin = 20 >>> h.filters = {'mu_BPVIP<0.1', 'pi_BPVIP<0.1'} >>> h.comment = 'trying new optmz'
>>> for line in h.debug_messages: ... print('{:12} {:}'.format(*line)) Filters (pi_BPVIP<0.1) | (mu_BPVIP<0.1) Tree h1_mu [#303] Param[0] mu_PT: DPHI Cut[0] M > 20e3 Axis X=[ 1.0, 100.0 ]/Auto=None, Y=[ 0.0, 3.14 ]/20 Comment trying new optmz Timestamp 20200101_000000000000 Script /mainfile
"""
## Filters # show raw because it's with AND/OR complexity.
## Trees
## Params & cuts
## Axis
## Misc
#--------------------------------------------------# # Read-only property -- Stored # # These has to be explicitly declared in __slots__ # #--------------------------------------------------#
def wrapper(self): """ Once this has been called, it's considered initialized. """
def timestamp(self): """ Lazy-method (to freeze value) of the timestamp string. Note: The timestamp is thus made the first time this method is called.
>>> ## Timestamp should be unique >>> h1 = QHist() >>> h2 = QHist() >>> h1.timestamp == h2.timestamp False
>>> ## ...even for the clones >>> h3 = h2() >>> h3.timestamp == h2.timestamp False
"""
def guessname(self): """ Specialize method to try to return a good naming, for saving file. Note that it only helps in the `name` part if missing. It won't concern prefix/suffix, which is why this method should be called inside `name` getter.
>>> ## Ignore the prefix/suffix >>> QHist(trees=tree, params='M', prefix='pf', suffix='sf').guessname 'M'
>>> ## Ignore scale >>> QHist(trees=tree, params='M/1e3').guessname 'M' """ ## 1. If single param else: ## Correction: scale # note: this part is similar to safename ## Finally
## No public setter available def stats(self): """ Return the stats object, contains array of statistics (min, max, count) for each entry queue in this QHist instance.
>>> ## Initially is empty stat >>> QHist().stats <Stats> len=0 nbin=None X=[None, None]
>>> ## Read-only >>> QHist().stats = {} Traceback (most recent call last): ... AttributeError: can't set attribute
"""
def anchors(self): """ Return the anchor object, which hold 'pointers' to different TObject involved in this QHist instance.
>>> ## Initially empty >>> print(QHist().anchors) ------------------... KEY | VALUE ( * differs from default ) canvas | None debug | None debugpad | None legend | None legendpad | None mainpad | None stack | None ----------------------------------------------------...
>>> ## Read-only >>> QHist().anchors = {} Traceback (most recent call last): ... AttributeError: can't set attribute
"""
def xarr(self): """ Return the python list representing array of bins in xaxis
>>> ## uninitialized case >>> QHist().xarr is None True
>>> ## Linear bins >>> QHist(xmin=0, xmax=10, xbin=4).xarr array('d', [0.0, 2.5, 5.0, 7.5, 10.0])
>>> ## Logarithmic bins >>> QHist(xmin=1, xmax=256, xbin=2).xarr array('d', [1.0, 16.0, 256.0])
"""
def yarr(self): """ >>> QHist().yarr is None True >>> QHist(ymin=0, ymax=10, ybin=4).yarr array('d', [0.0, 2.5, 5.0, 7.5, 10.0]) >>> QHist(ymin=1, ymax=256, ybin=2).yarr array('d', [1.0, 16.0, 256.0])
"""
#-------------------# # Overridden getter # #-------------------#
def name(self): """ >>> ## final name = prefix + name + suffix >>> h = QHist(name='test', prefix='prelim') >>> h.name 'prelim_test' >>> h.suffix = 'v0' >>> h.name 'prelim_test_v0'
>>> ## Default to timestamp, ignoring prefix >>> getfixture('freeze_time') >>> QHist(prefix='blah').name 'temp_20200101_000000000000'
""" ## Check if there's name, guessing if needed. else: ## Construct the name = prefix + name0 + suffix ## Finally, clean name (can be very weird name disturbing the namespace).
def title(self): """ >>> ## If title is missing, fallback to name >>> h = QHist(name='somename') >>> h.title 'somename'
>>> ## If given, it's now different from name >>> h.title = 'mytitle' >>> h.title != h.name True >>> h.prefix = 'prelim' >>> h.title 'prelim_mytitle'
>>> ## Title doesn't need safename >>> QHist(title='TMath::Abs(phi)').title 'TMath::Abs(phi)'
""" ## Borrow from name immediately if null ## Construct the same way as name, but no need for safename. # in order to show it entirely on canvas
## TPC: Equiplist on default value (None) # By equiping, I mean the value is already a list. The check for initial # value is then performed on the first element, e.g., self.trees[0] is None # - null of trees : None # - null of params: blank string # - null of cuts : blank string # Therefore, their setter has to also guard against there null value.
def trees(self): """ >>> QHist().trees [] >>> QHist(tpc=tpc).trees [<ROOT.TTree ...>, <ROOT.TTree ...>]
"""
def params(self): """ >>> QHist().params [] >>> QHist(tpc=tpc).params ['pi_BPVIP', 'mu_BPVIP']
"""
def cuts(self): """ >>> QHist().cuts [] >>> QHist(tpc=tpc).cuts ['pi_BPVIP > 0', 'mu_BPVIP > 0']
"""
def filters(self): # return ('',)
def tpc(self): """ Return current TPC state with given inputs.
>>> ## Simple TPC, no stacking >>> h = QHist(trees=tree, params='p') >>> h.tpc [(<ROOT.TTree ...>, 'p', '')] >>> h.cuts = 'PT>20' >>> h.tpc [(<ROOT.TTree ...>, 'p', 'PT>20')]
>>> ## TPC with stacking >>> h = QHist(trees=tree, params=['P1', 'P2'], cuts='PT>20') >>> h.tpc [(<ROOT.TTree ...>, 'P1', 'PT>20'), (<ROOT.TTree ...>, 'P2', 'PT>20')]
"""
def normalize(self): """ Always return list of matched length with TPC.
Doctest::
## default is tuple of length-0 >>> QHist().normalize ()
## Length to TPC, correct stack level. >>> QHist(tpc=tpc, normalize=True).normalize (True, True) >>> QHist(tpc=tpc, normalize=None).normalize (None, None) >>> QHist(tpc=tpc, normalize=[154, 100]).normalize (154, 100)
## In some case, TPC is not ready, but norms are given. Show them regardless. # The validation will make sure that the length matches. >>> QHist(normalize=[154, 100]).normalize (154, 100)
"""
def comment(self): """ No extra logic.
>>> QHist().comment ''
"""
def legends(self): """ Handles the educated-guess of legends to be used.
>>> ## From multiple trees/params/cuts >>> QHist(trees=(tree,tree), params='P').legends ('h1_mu', 'h1_mu') >>> QHist(trees=tree, params=('P1','P2')).legends ('P1', 'P2') >>> QHist(trees=tree, params='P', cuts=('C1','C2')).legends ('C1', 'C2')
>>> ## From advance TPC >>> for leg in QHist(tpc=tpc).legends: ... print leg [0] tree='h1_mu', param='pi_BPVIP', cut='pi_BPVIP > 0' [1] tree='h1_mu', param='mu_BPVIP', cut='mu_BPVIP > 0'
""" ## Do generically for advance stacking else: ## Simple stacking guesswork. # by trees (REMARK: T >= 1) ## Remove Ganga's prefix. It'll be in debug console later. # res = tuple(t.GetTitle().split('::')[-1].split('/')[-1] for t in self.trees) # disable backslash in case of genuine usage (GeV/c)
def options(self): """ >>> ## default to empty string like ROOT:TTree >>> QHist().options [''] """
def save_types(self): """ >>> ## default to root/pdf >>> QHist().save_types set(['pdf', 'root'])
"""
#-----------------------------
def xmin(self):
def xmax(self):
def xbin(self):
def xlog(self): """ 1. Use explicit value. 2. Use from explicit bound. 3. Use from scanned bound.
>>> QHist().xlog is None True >>> QHist(xlog=True).xlog True
"""
def xlabel(self): """ >>> QHist().xlabel '' >>> QHist(params='P').xlabel # guess 'P' >>> QHist(params='PX:PY').xlabel # guess 'PX' >>> QHist(tpc=[(tree, 'P', '')]).xlabel # guess 'P' >>> QHist(tpc=[(tree, 'P', 'c1'), (tree, 'P', 'c2')]).xlabel # guess 'P' >>> QHist(tpc=tpc).xlabel # complex, don't guess ''
""" ## Guess from params if it's simple enough. ## make sure to return the first dim. ## Prefer blank string than None for easy SetTitle later
def ymin(self):
def ymax(self):
def ybin(self):
def ylog(self):
def ylabel(self): """ Attempt to guess from the params if it's not ambigious
>>> QHist().ylabel '' >>> QHist(params='P').ylabel # not enough dim '' >>> QHist(params='PX:PY').ylabel # guess 'PY' >>> QHist(tpc=[(tree, 'P', '')]).ylabel # not enough dim '' >>> QHist(tpc=[(tree, 'PX:PY', '')]).ylabel # guess 'PY' >>> QHist(tpc=tpc).ylabel # complex, don't guess ''
""" ## Fast check from global dim ## Guess from params if it's simple enough. ## make sure to return the first dim. ## Prefer blank string than None for easy SetTitle later return ''
def zbin(self):
def zlog(self):
def zlabel(self): """ Attempt to guess from the params if it's not ambigious
>>> QHist().zlabel '' >>> QHist(params='P').zlabel # not enough dim '' >>> QHist(params='PX:PY:PZ').zlabel # guess 'PZ' >>> QHist(tpc=[(tree, 'P', '')]).zlabel # not enough dim '' >>> QHist(tpc=[(tree, 'PX:PY:PZ', '')], options='prof').zlabel # guess 'PZ' >>> QHist(tpc=tpc).zlabel # complex, don't guess ''
""" ## Fast check from global dim ## Guess from params if it's simple enough. ## make sure to return the first dim. ## Prefer blank string than None for easy SetTitle later return ''
#------------------------------------# # Overridden setter ~ Pre-validation # #------------------------------------#
def trees( self, val ): """ Doctest::
## Default is empty list >>> QHist().trees []
## Equip to list >>> QHist(trees=tree).trees (<ROOT.TTree object ("h1_mu") at ...>,)
## Raise error if other stacked >>> h = QHist(params=['PX', 'PY']) >>> h.trees = tree,tree Traceback (most recent call last): ... AttributeError: Cannot expand `trees`, already expanded elsewhere.
## Raise error is already have advance-TPC >>> h = QHist(tpc=tpc) >>> h.trees = tree Traceback (most recent call last): ... AttributeError: ...
""" ## Abort if advance mode already there ## Raise error if other component has been stacked. ## Finally
def params( self, val ): """ Doctest::
## Default is empty list >>> QHist().params []
## Equip to list >>> QHist(params='PT').params ('PT',)
## Raise error if other stacked >>> h = QHist(cuts=['Q>0', 'Q<0']) >>> h.params = 'PT1', 'PT2' Traceback (most recent call last): ... AttributeError: Cannot expand `params`, already expanded elsewhere.
## Inconsistent dimensions >>> h = QHist(params=('PT','PX:PY')) # inconsistent Traceback (most recent call last): ... AttributeError: ...
## Too-large dimensions >>> h = QHist(params='PX:PY:PZ') # 3 is okay >>> h = QHist(params='PX:PY:PZ:PE') Traceback (most recent call last): ... AttributeError: ...
## Raise error is already have advance-TPC >>> h = QHist(tpc=tpc) >>> h.params = 'P' Traceback (most recent call last): ... AttributeError: ...
""" ## Abort if advance mode already there ## Raise error if other component has been stacked. ## Dimensionality check ## Finally
def cuts( self, val ): """
>>> ## Default is empty list >>> QHist().cuts []
>>> ## Equip to list >>> QHist(cuts='ISMUON').cuts ('ISMUON',)
>>> ## Allow explicit null string >>> QHist(cuts='').cuts ('',)
>>> ## Raise error if other stacked >>> h = QHist(params=['PT1','PT2']) >>> h.cuts = 'Q>0', 'Q<0' Traceback (most recent call last): ... AttributeError: Cannot expand `cuts`, already expanded elsewhere.
>>> ## Raise error is already have advance-TPC >>> h = QHist(tpc=tpc) >>> h.cuts = 'c' Traceback (most recent call last): ... AttributeError: ...
""" ## Abort if advance mode already there ## Raise error if other component has been stacked. ## Finally
def filters( self, val ): """ Doctest::
>>> QHist().filters [] >>> QHist(filters='cut').filters ('cut',) >>> QHist(filters=['cut1','cut2']).filters ('cut1', 'cut2') >>> QHist(filters={'cut1','cut2'}).filters set(['cut1', 'cut2']) >>> QHist(filters={('cut1A','cut1B'),('cut2A','cut2B')}).filters set([('cut1A', 'cut1B'), ('cut2A', 'cut2B')])
## Error >>> QHist(filters=None) Traceback (most recent call last): ... TypeError: ...
"""
def tpc( self, val ): """
The triplet must be well-defined --------------------------------
>>> QHist(tpc=[('param',)]) Traceback (most recent call last): ... AttributeError: TPC: Need a triplet.
>>> QHist(tpc=[('param', 'cuts')]) Traceback (most recent call last): ... AttributeError: TPC: Need a triplet.
>>> QHist(tpc=(tree, 'P', 'C')) # need triplet in a list, not naked. Traceback (most recent call last): ... TypeError: ...
Correct triplet types ---------------------
>>> QHist(tpc=[('BAD', 'p', 'c')]) Traceback (most recent call last): ... AttributeError: ... >>> QHist(tpc=[(tree, 5555, 'c' )]) Traceback (most recent call last): ... AttributeError: ... >>> QHist(tpc=[(tree, 'c', None )]) Traceback (most recent call last): ... AttributeError: ...
Disable advance-TPC setter if simple one is already used. ---------------------------------------------------------
>>> h = QHist(trees=tree) >>> h.tpc = tpc Traceback (most recent call last): ... AttributeError: Simple mode is already used. Cannot use advance TPC.
>>> h = QHist(params='P') >>> h.tpc = tpc Traceback (most recent call last): ... AttributeError: Simple mode is already used. Cannot use advance TPC.
>>> h = QHist(cuts='c') >>> h.tpc = tpc Traceback (most recent call last): ... AttributeError: Simple mode is already used. Cannot use advance TPC.
Need consistent dim -------------------
>>> QHist(tpc=[(tree, 'PT', ''), (tree, 'PX:PY', '')]) Traceback (most recent call last): ... AttributeError: TPC: Inconsistent dimension.
>>> QHist(tpc=[(tree, 'D1:D2:D3:D4', '')]) Traceback (most recent call last): ... AttributeError: QHist cannot do dim>3 histogram.
""" ## Abort if simple mode already there ## Check for being len 3 ## Check for correct type: ## Check dimension consistency ## Finally
#--------------# # AXIS setters # #--------------#
def xmin( self, val ): """ >>> QHist().xmin is None True >>> QHist(xmin=10).xmin 10.0
>>> QHist(xmax=10).xmin = 20 Traceback (most recent call last): ... ValueError: ...
""" ## Check min < max
def xmax( self, val ): """ >>> QHist().xmax is None True >>> QHist(xmax=10).xmax 10.0
>>> QHist(xmin=10).xmax = 5 Traceback (most recent call last): ... ValueError: ...
""" ## Check min < max
def xbin( self, val ): """ >>> QHist(xbin=20).xbin 20
>>> ## no zero >>> QHist(xbin=0) Traceback (most recent call last): ... ValueError: ...
>>> ## no negative >>> QHist(xbin=-10) Traceback (most recent call last): ... ValueError: ...
>>> ## no float >>> QHist(xbin=10.) Traceback (most recent call last): ... TypeError: ...
"""
def xlog( self, val ): """ >>> QHist(xlog=True).xlog True >>> QHist(xlog=False).xlog False >>> QHist(xlog=None) Traceback (most recent call last): ... TypeError: ...
"""
def xlabel( self, val ): """ >>> ## Simple >>> QHist(xlabel='mass').xlabel 'mass'
"""
def ymin( self, val ): """ >>> QHist().ymin is None True >>> QHist(ymin=10).ymin 10.0
>>> QHist(ymax=10).ymin = 20 Traceback (most recent call last): ... ValueError: ...
""" ## Check min < max
def ymax( self, val ): """ >>> QHist().ymax is None True >>> QHist(ymax=10).ymax 10.0
>>> QHist(ymin=10).ymax = 5 Traceback (most recent call last): ... ValueError: ...
""" ## Check min < max
def ybin( self, val ): """ >>> QHist(ybin=-10) Traceback (most recent call last): ... ValueError: ...
"""
def ylog( self, val ):
def ylabel( self, val ): """ >>> QHist(ylabel='count').ylabel 'count'
"""
def zbin( self, val ): """ >>> QHist(zbin=-10) Traceback (most recent call last): ... ValueError: ...
"""
def zlog( self, val ): pass
def zlabel( self, val ): """ >>> QHist(zlabel='count').zlabel 'count'
"""
#-------------------------
def normalize( self, val ): """ Doctest::
## Equip to tuple of length-1 internally, ready for mult. # even though TPC is not available >>> QHist(normalize=True)._staticprop_normalize (True,) >>> QHist(normalize=False)._staticprop_normalize (False,) >>> QHist(normalize=None)._staticprop_normalize (None,) >>> QHist(normalize=100)._staticprop_normalize (100,)
## Error on empty inputs >>> QHist(normalize=[]) Traceback (most recent call last): ... AttributeError: Require non-empty list ...
"""
def comment(self, val): """ Doctest::
## Stringify everything threw into it. >>> QHist(comment='Hello world').comment u'Hello world'
"""
def legends( self, val ): """
>>> ## In general, do not allow setting in legends if there's no TPC. >>> QHist(legends=['a', 'b']) Traceback (most recent call last): ... ValueError: ...
>>> ## Disable legends if stacking==1 (too verbose) >>> QHist(trees=tree, params='P', legends='text') Traceback (most recent call last): ... AttributeError: Legends is disable without stacking.
>>> ## Mismatch dim >>> QHist(tpc=tpc, legends=['1', '2', '3']) # dim=2 Traceback (most recent call last): ... ValueError: Need legends of same length as TPC.
""" return val
def options( self, val ): """ >>> QHist(options='prof') <qhist.v3.lifecycle.QHist object at ...>
>>> QHist(options=['opt1', 'opt2', 'opt3']) Traceback (most recent call last): ... ValueError: Missing tree/param
>>> QHist(tpc=tpc, options=['opt1', 'opt2']) <qhist.v3.lifecycle.QHist object at ...>
>>> QHist(tpc=tpc, options=['opt1', 'opt2', 'opt3']) Traceback (most recent call last): ... ValueError: Need options of same length as TPC.
"""
def save_types( self, val ): """
# Equip list >>> QHist(save_types='png').save_types set(['png'])
# Force to lower case, remove dot >>> QHist(save_types=['PDF', '.C']).save_types set(['pdf', 'c'])
>>> QHist(save_types=['xxx']).save_types Traceback (most recent call last): ... ValueError: Unsupported file type: set(['xxx'])
"""
#----------------# # HIDDEN METHODS # #----------------#
""" Return the ROOT-ready string represent all cuts to be used in TTree::Draw. The arguments (p,c) is usually a subset of (params, cuts) found in the instance of qhist, sliced to single-stack and single-dim.
The fullcuts is composed of these components: 1. Explicit cut: c 2. Filters 3. Implicit/Axis cut
Leverage functionality of utils.join
Note: - Note that p can be 1D/2D/3D
- ???? If is_prof is True, the cut on y-axis should NOT be added to this since it directly affect the result.
## Basic >>> QHist()._fullcuts('p', '') '' >>> QHist()._fullcuts('p', 'c<0') 'c<0'
## With filters >>> QHist(filters='c<0')._fullcuts('p', '') 'c<0' >>> QHist(filters=['a>1','b>2'])._fullcuts('p', 'c==3') '(c==3) & ((a>1) & (b>2))' >>> QHist(filters={'a>1','b>2'})._fullcuts('p', 'c==3') '(c==3) & ((b>2) | (a>1))'
## With axis >>> QHist(xmin=123, xmax=234)._fullcuts('p', 'c==0') '(c==0) & ((p >= 123.0) & (p <= 234.0))' >>> QHist(xmin=80, xmax=100, ymin=0, ymax=3.14)._fullcuts('PY:PX', 'Z02MuMu') '(Z02MuMu) & ((PX >= 80.0) & (PX <= 100.0)) & ((PY >= 0.0) & (PY <= 3.14))'
## Higher dim >>> QHist(xmin=1, xmax=2, ymin=3, ymax=4, zmin=5, zmax=6)._fullcuts('X:Y:Z') '((X >= 1.0) & (X <= 2.0)) & ((Y >= 3.0) & (Y <= 4.0)) & ((Z >= 5) & (Z <= 6))'
"""
## 1. Explicit cuts
## 2. filters
## 3. Axis cut else: raise ValueError('Dimension > 3 not supported.')
## Finally, use smart join for return
def _tpc_fullcuts(self): """ Based on self.tpc, but now include the effect of _fullcuts. This is for the actual lifecycle methods. """
#===============================================================================
def _validate(self): """ Performs all validation before processing further, no change in its internal state.
## Default is not valid >>> QHist()._validate() Traceback (most recent call last): ... ValueError: ...
## Incomplete-simple-TPC is not valid >>> QHist(trees=tree)._validate() Traceback (most recent call last): ... ValueError: ...
>>> QHist(params='P')._validate() Traceback (most recent call last): ... ValueError: ...
## Complete simple-TPC is valid >>> QHist(trees=tree, params='P')._validate() True
## Complete advance-TPC is valid >>> QHist(tpc=tpc)._validate() True
## Error on mismatch normalize dim >>> QHist(tpc=tpc, normalize=[10, 20, 15])._validate() Traceback (most recent call last): ... AttributeError: ...
## 1D + profile is impossible >>> QHist(tpc=tpc, options='prof')._validate() Traceback (most recent call last): ... ValueError: Profile plot can only be used in 2D/3D plot.
## 2D + profile is okay! >>> QHist(tpc=[(tree, 'p1:p2', 'c')], options='prof')._validate() True
""" ## Need TPC ready. Rely on earlier setters logic
## Profile plot can only be used in 2D/3D plot
## Normalize dim
## For traditional status code
#=============================================================================== |