xboa
_hit.py
Go to the documentation of this file.
1 #This file is a part of xboa
2 #
3 #xboa is free software: you can redistribute it and/or modify
4 #it under the terms of the GNU General Public License as published by
5 #the Free Software Foundation, either version 3 of the License, or
6 #(at your option) any later version.
7 #
8 #xboa is distributed in the hope that it will be useful,
9 #but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 #GNU General Public License for more details.
12 #
13 #You should have received a copy of the GNU General Public License
14 #along with xboa in the doc folder. If not, see
15 #<http://www.gnu.org/licenses/>.
16 #
17 
18 import copy
19 import xboa.common as Common
20 import math
21 import gzip
22 import warnings
23 import array
24 try:
25  import json
26 except ImportError:
27  pass
28 
29 from xboa.core import Hitcore
30 import xboa.hit.factory
31 try:
32  import numpy
33  from numpy import matrix
34 except ImportError:
35  pass #safety provided by calls to Common.has_numpy whenever I use this library
36 
37 class BadEventError(IOError):
38  """
39  BadEventError is raised if Hit reads a bad
40  """
41 
42  def __init__(self, value):
43  self.value = value
44 
45  def __str__(self):
46  return repr(self.value)
47 
48 class Hit(object):
49  """
50  Represents a particle at a point in some phase space. Hit contains functions for i/o,
51  as well as accessors for rectangular or cylindrical coordinate systems and functions to
52  perform translations, abelian transformations etc.
53 
54  Hit has the following variables (stored for real in C struct Hitcore)
55 
56  - **x** transverse horizontal position
57  - **y** transverse vertical position
58  - **z** longitudinalposition
59  - **t** time
60  - **px** transverse horizontal component of momentum
61  - **py** transverse vertical component of momentum
62  - **pz** longitudinal component of momentum
63  - **energy** total energy
64  - **local_weight** local statistical weight (for a particular hit)
65  - **mass** particle mass
66  - **bx** horizontal component of magnetic field
67  - **by** vertical component of magnetic field
68  - **bz** longitudinal component of magnetic field
69  - **ex** x component of electric field
70  - **ey** y component of electric field
71  - **ez** z component of electric field
72  - **sx** x component of spin vector
73  - **sy** y component of spin vector
74  - **sz** z component of spin vector
75  - **path_length** total distance traversed by a particle
76  - **proper_time** proper time of the particle
77  - **e_dep** energy deposited, as registered by a Monte Carlo code
78  - **charge** particle charge, in units of electron charge
79  - **station** output plane index
80  - **pid** PDG particle ID (am I an electron? am I a proton?)
81  - **status** is the particle track okay? (code dependent)
82  - **spill** indexes the spill (for MICE)
83  - **event_number** indexes the event
84  - **particle_number** indexes the particle track within the event
85 
86  Additionally,
87 
88  - global_weight is a global statistical weight (for a particular particle).
89  All hits with the same (spill, event_number, particle_number) will register
90  the same global weight.
91  """
92  #this lets python define a global vtable rather than one for each instance
93  __slots__ = ['__hitcore']
94 
95  def __init__(self):
96  """Initialise to an empty event. Alternatively use static initialisers defined below - I prefer static initialisers"""
97  self.__hitcore = Hitcore()
98 
99  def __repr__(self):
100  """Formatting for print command"""
101  return 'Hit.new_from_dict('+repr(self.dict_from_hit())+')'
102 
103  def __copy__(self):
104  """Shallow copy i.e. copy as reference"""
105  hitCopy = self
106  return hitCopy
107 
108  def __deepcopy__(self, target):
109  """Deep copy i.e. copy as data"""
110  target = Hit.new_from_dict(self.dict_from_hit())
111  return target
112 
113  def __eq__(self, target, float_tolerance=Common.float_tolerance):
114  """Test for equality of data values between self and target"""
115  if type(self) != type(target): return False
116  for key in self.__hitcore.get_variables():
117  if abs(self.__hitcore.get(key) - target.__hitcore.get(key)) > float_tolerance: return False
118  return True
119 
120  def __ne__(self, target, float_tolerance=Common.float_tolerance):
121  """Test for inequality of data values between self and target"""
122  return not self.__eq__(target, float_tolerance)
123 
124  def __getitem__(self, variable):
125  """Mimic some aspects of dict"""
126  return self.get(variable)
127 
128  def __setitem__(self, variable, value):
129  """Mimic some aspects of dict"""
130  return self.set(variable, value)
131 
132  def __del__(self):
133  """Clean up"""
134  del(self.__hitcore)
135 
136  # static initialisers #############
137  def new_from_dict(set_dict, mass_shell_string=''):
138  """
139  Static function returns a new hit object, setting data using string:value dict. Then forces E^2=p^2+m^2 by changing mass_shell_string.
140 
141  - set_dict = dict of string:value pairs where strings are from set_variables()
142  - mass_shell_string = string from list mass_shell_variables that references the value that will be changed to force E^2=p^2+m^2
143 
144  e.g. myHit = Hit.new_from_dict({'x':5, 'y':0, 'z':100, 'px':0, 'py':5, 'pz':200, 'pid':-13}, 'energy' )
145  """
146  my_hit = Hit()
147  for k,v in set_dict.iteritems():
148  my_hit.set(k, v)
149  if(mass_shell_string != ''):
150  my_hit.mass_shell_condition(mass_shell_string)
151  return my_hit
152  new_from_dict = staticmethod(new_from_dict)
153 
154  def new_from_read_builtin(format, filehandle):
155  """
156  Static function returns a new hit object, read from filehandle with a built-in format
158  - format = string from the list file_types() that defines the format of the input
159  - filehandle = filehandle from which the hit object will be read
160 
161  e.g. myHit = Hit.new_from_read_builtin('zgoubi', myfile)
162  Note that this will read one event, typically corresponding to one line in <filehandle>
163  """
164  if format == 'opal_loss':
165  hit = Hit()
166  opal_read = hit.__read_opal_loss_file(filehandle)
167  return hit
168  else:
169  return xboa.hit.factory.BuiltinHitFactory(format, filehandle).make_hit()
170  new_from_read_builtin = staticmethod(new_from_read_builtin)
171 
172  def new_from_read_user(format_list, format_units_dict, filehandle, mass_shell_condition=''):
173  """
174  Static function returns a new hit object sets data using string/value pairs from set_dict and forces E^2=p^2+m^2 by changing mass_shell_string
175 
176  - format_list = ordered list of variables from get_variables() that contains the particle variables on each line of your input file
177  - format_units_dict = dict of variables:units that are used to transform to internal system of units
178  - filehandle = file handle, created using e.g. filehandle = open('for009.dat')
179 
180  e.g. myHit = Hit.new_from_read_user(['x','y','z','px','py','pz'], {'x':'mm', 'y':'mm', 'z':'mm', 'px':'MeV/c', 'py':'MeV/c', 'pz':'MeV/c'}, my_input_file)
181  """
183  format_list,
184  format_units_dict,
185  filehandle,
186  mass_shell_condition
187  ).make_hit()
188  new_from_read_user = staticmethod(new_from_read_user)
189 
190  @classmethod
191  def new_list_from_maus_root(cls, format, root_tree, entry_number = 0):
192  """
193  Static function returns a list of hit objects found in the spill
194 
195  - format = type to take from the maus file.
196  - root_tree = TTree containing maus spill data, of type ROOT.TTree
197  - entry_number = index of the spill entry in the TTree
198 
199  Returns a list of hit objects. Station number will be taken from the relevant maus_type. event_number will be given by the spill_number. track_number will be given by
200  the index on mc_events or recon_events
201  """
202  fac = xboa.hit.factory.factory.MausRootHitFactory(format, root_tree, entry_number)
203  hit_list = [hit for hit in fac.hit_generator()]
204  return hit_list
205 
206  @classmethod
207  def new_list_from_maus_json(cls, format, filehandle):
208  """
209  Static function returns a list of hit objects found in the spill
210 
211  - format = type to take from the maus file.
212  - filehandle = filehandle containing json formatted data
213 
214  Returns a list of hit objects. Station number will be taken from the
215  relevant maus_type. event_number will be given by the spill_number.
216  track_number will be given by the index on mc_events or recon_events.
217  """
218  fac = xboa.hit.factory.factory.MausJsonHitFactory(format, file_handle)
219  hit_list = [hit for hit in fac.hit_generator()]
220  return hit_list
221 
222  def copy(self):
223  """Return a shallow copy of self (copying data as references)"""
224  return self.__copy__()
225 
226  def deepcopy(self):
227  """Return a deep copy of target (deep copying target's data to self as well)"""
228  target = Hit()
229  target = copy.deepcopy(self)
230  return target
231 
232  # Transformations #################
233  def get_vector(self, get_variable_list, origin_dict={}):
234  """
235  Return a numpy vector of data values taking data from get_variable_list, relative to some origin
236 
237  - get_variable_list = list of variable strings from get_variables()
238  - origin_dict = dict of variable strings to origin value; if not set, assumes 0
239 
240  e.g. transverse_vector = myHit.get_vector(['x', 'y', 'px', 'py'])
241  """
242  Common.has_numpy()
243  my_list = []
244  for key in get_variable_list:
245  if key in origin_dict: origin = origin_dict[key]
246  else: origin = 0.
247  my_list.append(self.get(key) - origin)
248  return matrix(numpy.array(my_list))
249 
250  def translate(self, translation_dict, mass_shell_string):
251  """
252  Iterate over translation_dict and add the value in the dict to the value stored in Hit. Then force E^2 = p^2 + m^2
253 
254  - translation_dict = dict of strings from list set_variables() to floats
255  - mass_shell_string = string from list mass_shell_variables()
256  """
257  for k,v in translation_dict.iteritems():
258  self.set(k, v+self.get(k))
259  self.mass_shell_condition(mass_shell_string)
261  def abelian_transformation(self, rotation_list, rotation_matrix, translation_dict={}, origin_dict={}, mass_shell_variable=''):
262  """
263  Perform an abelian transformation about the origin, i.e. V_out - O = R*(V_in-O) + T.
264  Then force E^2 = p^2 + m^2
265 
266  - rotation_list = list of variables to be rotated
267  - rotation_matrix = matrix R
268  - translation_dict = dict of strings from set_variables() to floats. Becomes O
269  - mass_shell_variable = string from list mass_shell_variables()
270  - origin_dict = dict of strings from set_variables() to floats. Becomes t
271 
272  e.g. hit.abelian_transformation(['x','px'], array[[1,0.5],[0,1]],{'x':10},'energy') will
273  look like a drift space plus a translation
274  """
275  vector = (self.get_vector(rotation_list)).transpose()
276  origin = copy.deepcopy(origin_dict)
277  trans = copy.deepcopy(translation_dict)
278  for key in rotation_list:
279  if not key in origin: origin[key] = 0
280  if not key in trans: trans [key] = 0
281  for i in range( len(rotation_list) ):
282  vector[i,0] -= origin[rotation_list[i]]
283  vector = rotation_matrix*vector
284  for i in range( len(rotation_list) ):
285  self.set(rotation_list[i], float(vector[i,0]+trans[rotation_list[i]]+origin[rotation_list[i]]))
286  self.mass_shell_condition(mass_shell_variable)
287  return self
288 
289  def mass_shell_condition(self, variable_string, float_tolerance = 1.e-6):
290  """
291  Change variable represented by variable_string to force E^2 = p^2 + m^2
292 
293  - variable_string = string which should be one of the list mass_shell_variables().
294  """
295  if(variable_string == ''):
296  return
297  px = self.get('px')
298  py = self.get('py')
299  pz = self.get('pz')
300  e = self.get('energy')
301  m = self.get('mass')
302  if(variable_string == 'p'):
303  self.set('p', ( (e-m)*(e+m) )**0.5 )
304  elif(variable_string == 'px'):#get direction right!
305  val = (e*e-m*m-py*py-pz*pz)
306  if val>float_tolerance: self.set('px', abs(val)**1.5/val )
307  else: self.set('px', 0.)
308  elif(variable_string == 'py'):
309  val = (e*e-m*m-px*px-pz*pz)
310  if val>float_tolerance: self.set('py', abs(val)**1.5/val )
311  else: self.set('py', 0.)
312  elif(variable_string == 'pz'):
313  val = (e*e-m*m-px*px-py*py)
314  if val>float_tolerance: self.set('pz', abs(val)**1.5/val )
315  else: self.set('pz', 0.)
316  elif(variable_string == 'energy'):
317  self.set('energy', (m*m+px*px+py*py+pz*pz) **0.5 )
318  else:
319  raise IndexError('mass_shell_condition did not recognise \''+str(variable_string)+'\'. Options are '+str(self.__mass_shell_variables))
320 
321  # Manipulators ################
322 
323  def get(self, key):
324  """
325  Return the value referenced by key
326 
327  - key = string which should be one of the list get_variables()
328  """
329  try:
330  return self.__hitcore.get(key)
331  except Exception:
332  pass
333  if(key in self.__get_variables):
334  return self.__get_variables[key](self)
335  else:
336  raise IndexError('Key \''+str(key)+'\' could not be found for Hit.get() - should be one of '+str(Hit.get_variables()))
337 
338  def set(self, key, value):
339  """
340  Set the value referenced by key
341 
342  - key = string which should be one of the list get_variables()
343  - value = float
344  """
345  try:
346  self.__hitcore.set(key, value)
347  return
348  except: pass
349  if(key in self.__set_variables):
350  self.__set_variables[key](self, value)
351  else:
352  raise IndexError('Key \''+str(key)+'\' could not be found for Hit.set() - should be one of '+str(Hit.set_variables()))
353 
354  def check(self, tolerance_float=1e-3):
355  """Return True if mass shell condition is obeyed and pid is correct for the mass else return False"""
356  pid = self.get('pid')
357  if (not abs(pid) in Common.pdg_pid_to_mass) and (not pid in Hit.__bad_pids) and (not pid == 0):
358  print 'pid not recognised',self.get('pid')
359  return False
360  if abs(pid) in Common.pdg_pid_to_mass.keys():
361  if abs(self.get('mass')-Common.pdg_pid_to_mass[abs(pid)]) > tolerance_float:
362  print 'Mass',self.get('mass'),'does not match pid',self.get('pid')
363  return False
364  if abs(round(self.get('p')**2 + self.get('mass')**2) - round(self.get('energy')**2)) > tolerance_float :
365  return False
366  return True
367 
368  def dict_from_hit(self):
369  """
370  Return a dict that uniquely defines the hit, so that new_from_dict(dict_from_hit(hit)) returns a copy of hit
371  """
372  my_dict = {}
373  for key in self.__hitcore.set_variables():
374  my_dict[key] = self.__hitcore.get(key)
375  return my_dict
376 
377  # IO ###################
378 
379  def write_builtin_formatted(self, format, file_handle):
380  """
381  Write to a file formatted according to built-in file_type format
382 
383  - format = string from file_types
384  - file_handle = file handle made using e.g. open() command
385 
386  e.g. aHit.write_builtin_formatted('icool_for009', for009_dat) would write aHit in icool_for009 format to for009_dat
387  """
388  if( format.find('maus') > -1 ):
389  raise IOError("Can't write single maus hits, only lists of hits")
390  if( format.find('icool') > -1 ):
391  self.set('pid', Common.pdg_pid_to_icool[self.get('pid')])
392  if( format.find('mars') > -1 ):
393  self.set('pid', Common.pdg_pid_to_mars [self.get('pid')])
394  self.__write_formatted(self.__file_formats[format], self.__file_units[format], file_handle)
395  if( format.find('icool') > -1 ):
396  self.set('pid', Common.icool_pid_to_pdg[self.get('pid')])
397  if( format.find('mars') > -1 ):
398  self.set('pid', Common.mars_pid_to_pdg [self.get('pid')])
399 
400  def write_list_builtin_formatted(list_of_hits, file_type_string, file_name, user_comment=None):
401  """
402  Write a list of hits to a file formatted according to built-in file_type format
403 
404  - format = string from file_types
405  - file_handle = file handle made using e.g. open() command
406  - user_comment = comment included in some output formats (e.g. problem title, etc)
407 
408  For example,
409  aHit.write_list_builtin_formatted([hit1, hit2] 'icool_for009', 'for009_dat')
410  would write hit1, hit2 in icool_for009 format to for009_dat
411  """
412  if( file_type_string.find('maus_root') > -1 ):
413  raise IOError("Can't write maus_root formats")
414  filehandle = Hit.open_filehandle_for_writing(file_type_string, file_name, user_comment)
415  if( file_type_string.find('maus') > -1 ):
416  Common.has_json()
417  maus_tree = Hit.get_maus_tree(list_of_hits, file_type_string)
418  for spill_number, item in enumerate(maus_tree):
419  item["maus_event_type"] = "Spill"
420  item["spill_number"] = spill_number
421  print >>filehandle,json.dumps(item)
422  return
423  comptor = (Hit.__station_cmp)
424  list_of_hits.sort(comptor)
425  old_hit = None
426  current_hits = []
427  for hit_in in list_of_hits:
428  if old_hit == None or comptor(hit_in, old_hit) == 0:
429  current_hits.append(hit_in)
430  else:
431  for hit_out in current_hits:
432  try: hit_out.write_builtin_formatted(file_type_string, filehandle)
433  except: pass
434  current_hits = [hit_in]
435  old_hit = hit_in
436  for hit_out in current_hits:
437  try:
438  hit_out.write_builtin_formatted(file_type_string, filehandle)
439  except:
440  print 'Warning - failed to write ',hit_out
441  filehandle.close()
442  return
443  write_list_builtin_formatted = staticmethod(write_list_builtin_formatted)
444 
445  def open_filehandle_for_writing(file_type_string, file_name, user_comment=None):
446  """
447  Open a file handle of the specified type for writing. Some filehandles need special care, e.g. some are gzipped etc
448 
449  - file_type_string = open filehandle for this file type
450  - file_name = string name of the file
451  """
452  filehandle = None
453  filehandle = open(file_name, 'w')
454  filehandle.write(Hit.file_header(file_type_string, user_comment))
455  return filehandle
456  open_filehandle_for_writing = staticmethod(open_filehandle_for_writing)
457 
458  def file_header(file_type_string, user_comment=None):
459  """
460  Return the file_header for the given file_type. Optionally, can add a user comment
461 
462  - file_type_string = header returned for this file type. Select from file_types()
463  - user_comment = add a user comment - default is 'File generated by xboa'
464 
465  e.g. Hit.file_header('icool_for009', 'This is my for009 file') would set 'This is my for009 file'
466  as a user comment and return the header string
467  """
468  if user_comment == None: file_header = Hit.__file_headers[file_type_string].replace(str('<user>'), str(Hit.__default_user_string))
469  else: file_header = Hit.__file_headers[file_type_string].replace(str('<user>'), str(user_comment))
470  return file_header
471  file_header = staticmethod(file_header)
472 
473  def write_user_formatted(self, format_list, format_units_dict, file_handle, separator=' '):
474  """
475  Write to a file formatted according to built-in file_type format
476 
477  - format_list = ordered list of strings from get_variables()
478  - format_units_dict = dict of formats from format_list to units
479  - file_handle = file handle made using e.g. open() command
481  e.g. aHit.write_user_formatted(['x','px','y','py'], ['x':'m','y':'m','px':'MeV/c','py':'MeV/c'], some_file, '@') would make output like
482  0.001@0.002@0.001@0.002 in some_file
483  """
484  self.__write_formatted(format_list, format_units_dict, file_handle, separator)
486  def file_types():
487  """Static function returns a list of available file types"""
488  return Hit.__file_types
489  file_types = staticmethod(file_types)
490 
491  def get_maus_dict(self, type_name):
492  """
493  Convert from hit to a maus dict for MAUS IO
494 
495  - type_name = name of the maus type to generate
496 
497  Returns a tuple of (maus_dict, spill_number)
498  """
499  maus_dict = {}
500  three_vec_conversions = Hit.__maus_three_vec_conversions[type_name]
501  conversion_dict = Hit.__maus_variable_conversions[type_name]
502  for maus_name, xboa_suffix in three_vec_conversions.iteritems():
503  maus_dict[maus_name] = {}
504  for xyz in ['x','y','z']:
505  maus_dict[maus_name][xyz] = self[xboa_suffix+xyz]
506  for maus_key, xboa_key in conversion_dict.iteritems():
507  maus_dict[maus_key] = self[xboa_key]
508  for key, value in Hit._Hit__file_units[type_name]:
509  xboa_dict[key] *= Hit._Hit__file_units[type_name][key]
510  return (maus_dict, self['event_number'])
511 
512 
513  def get_maus_tree(list_of_hits, type_name):
514  """
515  Convert from list of hits to a tree of maus objects
516 
517  - list_of_hits = list of hits to be converted
518  - type_name = maus type, used to define position in the maus tree
520  Return value is a list of maus spills (each of which is a data tree)
521  """
522  # tried to be fairly general here; this should work for any tree that has all hit data
523  # stored either directly at the same level or in three vectors at the same level
524  # if we need to put pid here, momentum there, etc... then we need to think again
525  return Hit.__get_maus_tree_recursive(list_of_hits, [["event_number"]]+Hit.__maus_paths[type_name], type_name)
526  get_maus_tree = staticmethod(get_maus_tree)
527 
528  # static data that describe the class #################
529 
530  def mass_shell_variables():
531  """Static function returns a list of variables suitable for mass_shell_condition calls"""
532  return Hit.__mass_shell_variables
533  mass_shell_variables = staticmethod(mass_shell_variables)
534 
535  def get_variables():
536  """Static function returns a list of variable suitable for get calls"""
537  return Hit.__get_keys
538  get_variables = staticmethod(get_variables)
539 
540  def set_variables():
541  """Static function returns a list of variable suitable for set calls"""
542  return Hit.__set_keys
543  set_variables = staticmethod(set_variables)
544 
545 
546  # get and set variables ####################
547  def get_p (self):
548  """Returns total momentum of the hit"""
549  return (self.get('px')**2+self.get('py')**2+self.get('pz')**2)**0.5
550 
551  def get_r (self):
552  """Returns transverse distance (i.e. in x,y space) from 0,0"""
553  return (self.get('x')**2+self.get('y')**2)**0.5
554 
555  def get_phi (self):
556  """Returns transverse angle (i.e. in x,y space) in range (-pi, pi); phi = 0. is positive y and phi = pi/2 is positive x"""
557  return math.atan2(self['y'], self['x'])
558 
559  def get_pt (self):
560  """Returns transverse momentum of the hit"""
561  return (self['px']**2+self['py']**2)**0.5
562 
563  def get_pphi(self):
564  """Returns transverse angle of momentum (i.e. in px,py space) in range (-pi, pi); phi = 0. is positive py and phi = pi/2 is positive px"""
565  return math.atan2(self['py'], self['px'])
566 
567  def get_r_squared(self):
568  """Returns x divergence i.e. px/pz of the hit"""
569  return (self['x']**2+self['y']**2)
570 
571  def get_xP (self):
572  """Returns x divergence i.e. px/pz of the hit"""
573  return (self['px']/self['pz'])
574 
575  def get_yP (self):
576  """Returns y divergence i.e. py/pz of the hit"""
577  return (self['py']/self['pz'])
578 
579  def get_tP (self):
580  """Returns t \'divergence\' i.e. E/pz of the hit"""
581  return (-self['energy']/self['pz'])
582 
583  def get_rP (self):
584  """Returns dr/dz = pt/pz of the hit"""
585  return (self.get('pt')/self['pz'])
586 
587  def get_spin(self):
588  """Returns absolute value of the spin"""
589  return (self.get('sx')**2+self.get('sy')**2+self.get('sz')**2)**0.5
590 
591  def get_ct (self):
592  """Returns speed_of_light*t of the hit"""
593  return (self['t']*Common.constants['c_light'])
594 
595  def get_ek (self):
596  """Returns total energy - mass, ie kinetic energy of the hit"""
597  return self['energy'] - self.get('mass')
598 
599  def set_ek (self, value_float):
600  """Sets kinetic energy = total energy - mass of the hit"""
601  self['energy'] = value_float + self.get('mass')
602 
603  def get_l_kin(self):
604  """Returns kinetic angular momentum about the z-axis.
605  To use a different axis, you will have to perform your own transformation"""
606  return self['x']*self['py'] - self['y']*self['px']
607 
608  def set_ct (self, value_float):
609  """Sets t = value_float/c_light"""
610  self['t'] = value_float/Common.constants['c_light']
611 
612  def set_p(self, value_float):
613  """Set p to value_float keeping momentum direction constant"""
614  p = self.get_p()
615  if(p == 0):
616  self.set('pz', 1.)
617  scale = value_float/self.get_p()
618  self['px'] *= scale
619  self['py'] *= scale
620  self['pz'] *= scale
621 
622  def set_xP (self, value_float):
623  """Set x\' to value_float keeping pz constant"""
624  if(math.fabs(self['pz']) < 1e-9): raise FloatingPointError('Cant set x\' while pz is 0')
625  self['px'] = value_float*self['pz']
626 
627  def set_yP (self, value_float):
628  """Set y\' to value_float keeping pz constant"""
629  if(math.fabs(self['pz']) < 1e-9): raise FloatingPointError('Cant set y\' while pz is 0')
630  self['py'] = value_float*self['pz']
631 
632  def set_tP (self, value_float):
633  """Set t\' (dt/dz=-E/pz) to value_float keeping pz constant; note sign of pz may change"""
634  if(math.fabs(self['pz']) < 1e-9): raise FloatingPointError('Cant set t\' while pz is 0')
635  self['energy'] = -value_float*self['pz']
636  if self['pz'] < 0.:
637  self['energy'] *= -1.
638  self['pz'] *= -1.
639  if self['energy'] < self.get('mass'): raise FloatingPointError('Energy less than muon mass')
640 
641  def get_weight(self):
642  """Returns total weight for this Hit"""
643  return self.get('global_weight')*self.get('local_weight')
644 
645  def clear_global_weights():
646  """Set all global weights to 1"""
647  Hitcore.clear_global_weights()
648  clear_global_weights = staticmethod(clear_global_weights)
649 
650  def delete_global_weights():
651  """Clear memory allocated to global weights - also resets global weights to 1"""
652  raise NotImplementedError("delete_global_weights is deprecated - please use clear_global_weights")
653  delete_global_weights = staticmethod(delete_global_weights)
654 
655  def get_local_weight(self):
656  """Returns local weight for this Hit"""
657  return self.get('local_weight')
658 
659  def set_local_weight(self, value):
660  """Set local weight for this Hit to be value"""
661  self.set('local_weight', value)
663  def get_global_weight(self):
664  """Returns global weight for this Hit"""
665  return self.get('global_weight')
666 
667  def set_global_weight(self, value):
668  """Set global weight for this Hit to be value"""
669  self.set('global_weight', value)
670 
671  def set_g4bl_unit(unit):
672  """
673  g4beamline_track_file can take different units for length - set the unit here
674 
675  - unit = string that is a unit of length
676 
677  e.g. set_g4bl_unit('m') would set the length unit to metres
678  """
679  Hit.__file_units['g4beamline_bl_track_file']['x'] = unit
680  Hit.__file_units['g4beamline_bl_track_file']['y'] = unit
681  Hit.__file_units['g4beamline_bl_track_file']['z'] = unit
682  set_g4bl_unit = staticmethod(set_g4bl_unit)
683 
684  #write formatted output - don't touch mass or pid beyond reading them
685  def __write_formatted(self, format_list, format_units_dict, file_handle, separator=' '):
686  for key in format_list:
687  if key == '': value = 0
688  else: value = Hit._default_var_types[key](self.get(key)/Common.units[ format_units_dict[key] ])
689  file_handle.write( str( value )+separator)
690  file_handle.write('\n')
691 
692  # extract virtual hits from the root tree
693  def __get_maus_root_virtual_hits(mc_event, track_number):
694  hit_list = []
695  for i in range(mc_event.GetVirtualHitsSize()):
696  maus_hit = mc_event.GetAVirtualHit(i)
697  pid = maus_hit.GetParticleId()
698  hit_dict = {'pid':pid, 't':maus_hit.GetTime(), 'charge':maus_hit.GetCharge(), 'proper_time':maus_hit.GetProperTime(),
699  'path_length':maus_hit.GetPathLength(), 'station':maus_hit.GetStationId(),
700  'x':maus_hit.GetPosition().x(), 'y':maus_hit.GetPosition().y(), 'z':maus_hit.GetPosition().z(),
701  'px':maus_hit.GetMomentum().x(), 'py':maus_hit.GetMomentum().y(), 'pz':maus_hit.GetMomentum().z(),
702  'bx':maus_hit.GetBField().x(), 'by':maus_hit.GetBField().y(), 'bz':maus_hit.GetBField().z(),
703  'ex':maus_hit.GetEField().x(), 'ey':maus_hit.GetEField().y(), 'ez':maus_hit.GetEField().z(),
704  'particle_number':maus_hit.GetTrackId()}
705  hit_dict['mass'] = Common.pdg_pid_to_mass[abs(pid)]
706  if hit_dict['pid'] != 0:
707  hit_list.append(Hit.new_from_dict(hit_dict, 'energy'))
708  else:
709  print 'Warning - pid 0 detected in maus_root_virtual_hit; hit will not be loaded'
710  return hit_list
711  __get_maus_root_virtual_hits = staticmethod(__get_maus_root_virtual_hits)
712 
713  def __get_maus_root_primary_hits(mc_event, track_number):
714  maus_hit = mc_event.GetPrimary()
715  pid = maus_hit.GetParticleId()
716  hit_dict = {'pid':pid, 'energy':maus_hit.GetEnergy(), 't':maus_hit.GetTime(),
717  'x':maus_hit.GetPosition().x(), 'y':maus_hit.GetPosition().y(), 'z':maus_hit.GetPosition().z(),
718  'px':maus_hit.GetMomentum().x(), 'py':maus_hit.GetMomentum().y(), 'pz':maus_hit.GetMomentum().z()}
719  hit_dict['particle_number'] = 0
720  hit_dict['charge'] = Common.pdg_pid_to_charge[abs(pid)]
721  hit_dict['mass'] = Common.pdg_pid_to_mass[abs(pid)]
722  return [Hit.new_from_dict(hit_dict, 'energy')]
723  __get_maus_root_primary_hits = staticmethod(__get_maus_root_primary_hits)
724 
725  # split a list into sub lists where items in sublist have item1[sort_value] == item2[sort_value]
726  def __split_list_by_equality(a_list, sort_attribute):
727  a_dict = {}
728  for item in a_list:
729  value = item[sort_attribute]
730  if not value in a_dict: a_dict[value] = []
731  a_dict[value].append(item)
732  return a_dict.values()
733  __split_list_by_equality = staticmethod(__split_list_by_equality)
734 
735  # recursively reconstruct the maus_path
736  def __get_maus_tree_recursive(list_of_hits, maus_path, format):
737  if len(maus_path) == 1:
738  if type(maus_path[0]) == type(""):
739  if len(list_of_hits) > 1:
740  for hit in list_of_hits:
741  print hit
742  raise IOError("More than one hit for maus key")
743  return {maus_path[0]:list_of_hits[0].get_maus_dict(format)[0]}
744  if type(maus_path[0]) == type([]):
745  return [hit.get_maus_dict(format)[0] for hit in list_of_hits]
746  if type(maus_path[0]) == type([]):
747  list_of_hits_new = Hit.__split_list_by_equality(list_of_hits, maus_path[0][0])
748  my_output = [Hit.__get_maus_tree_recursive(x, maus_path[1:], format) for x in list_of_hits_new]
749  if len(maus_path) == 1:
750  output = []
751  for out in my_output: output += out
752  else: output = my_output
753  return my_output
754  if type(maus_path[0]) == type(""):
755  return {maus_path[0]:Hit.__get_maus_tree_recursive(list_of_hits, maus_path[1:], format)}
756  __get_maus_tree_recursive = staticmethod(__get_maus_tree_recursive)
757 
758  # split a list into sub lists where items in sublist have item1[sort_value] == item2[sort_value]
759  def __split_list_by_equality(a_list, sort_attribute):
760  a_dict = {}
761  for item in a_list:
762  value = item[sort_attribute]
763  if not value in a_dict: a_dict[value] = []
764  a_dict[value].append(item)
765  return a_dict.values()
766  __split_list_by_equality = staticmethod(__split_list_by_equality)
767 
768  def __return_one(self, value=''):
769  return 1.
770 
771  def __do_nothing(self, value = ''):
772  pass
773 
774  #internal data
775  #information on available types
776  __file_types = ['icool_for009', 'icool_for003', 'g4beamline_bl_track_file', 'mars_1'] #'opal_loss'
777  try:
778  Common.has_json()
779  __file_types += ['maus_json_virtual_hit', 'maus_json_primary']
780  except ImportError:
781  pass
782  try:
783  Common.has_maus()
784  __file_types += ['maus_root_virtual_hit', 'maus_root_primary']
785  except ImportError:
786  pass
787 
788  __mass_shell_variables = ['', 'p', 'px', 'py', 'pz', 'energy']
789  __get_variables = {'p':get_p,'r':get_r,'phi':get_phi,'pt':get_pt,'pphi':get_pphi,'x\'':get_xP,'y\'':get_yP,'t\'':get_tP, 'ct\'':get_tP,'r\'':get_rP,'spin':get_spin,
790  'weight':get_weight,'ct':get_ct,'r_squared':get_r_squared,'z\'':__return_one,'kinetic_energy':get_ek,
791  'l_kin':get_l_kin,'':__do_nothing}
792  __set_variables = {'p':set_p,'x\'':set_xP,'y\'':set_yP,'t\'':set_tP,'ct':set_ct,'kinetic_energy':set_ek,'':__do_nothing}
793  _default_var_types = {'x':float,'y':float,'z':float,'t':float,'px':float,'py':float,'pz':float,'energy':float,'bx':float,'by':float,'bz':float,
794  'ex':float,'ey':float,'ez':float,'eventNumber':int, 'event_number':int, 'particleNumber':int, 'particle_number':int, 'pid':int,'status':int,'station':int,'local_weight':float,
795  'sx':float,'sy':float,'sz':float,'mass':float,'path_length':float,'proper_time':float,'e_dep':float, 'charge':float}
796 
797  __get_keys = []
798  __set_keys = []
799  for key in Hitcore.get_variables():
800  __get_keys.append(key)
801  for key in Hitcore.set_variables():
802  __set_keys.append(key)
803  for key, value in __get_variables.iteritems():
804  __get_keys.append(key)
805  for key, value in __set_variables.iteritems():
806  __set_keys.append(key)
807  for key, value in __get_variables.iteritems():
808  if not key in _default_var_types:
809  _default_var_types[key] = float #assume everything else is a float
810 
811 
812  __maus_three_vec_conversions = { # maus three vectors are sub-dicts of virtual_hit
813  "maus_json_virtual_hit":{"position":"", "momentum":"p", "b_field":"b", "e_field":"e"},
814  "maus_json_primary":{"position":"", "momentum":"p"}
815  }
816 
817  __maus_variable_conversions = {
818  "maus_json_virtual_hit":{"station_id":"station", "particle_id":"pid", "track_id":"particle_number", "time":"t", "mass":"mass", "charge":"charge", "proper_time":"proper_time", "path_length":"path_length"},
819  "maus_json_primary":{"particle_id":"pid", "time":"t", "energy":"energy"} # we also force "mass" from "pid"
820  }
822  __maus_paths = {
823  "maus_json_virtual_hit":["mc_events", ["particle_number"], "virtual_hits", ["station"]],
824  "maus_json_primary":["mc_events", ["particle_number"], "primary"],
825  }
826 
827  __maus_root_mc_types = {
828  "maus_root_virtual_hit": lambda x, y: Hit.__get_maus_root_virtual_hits(x, y),
829  "maus_root_primary": lambda x, y: Hit.__get_maus_root_primary_hits(x, y)
830  }
831  __maus_root_recon_types = {}
832 
833  #formatting information
834  __file_formats = {
835  'icool_for009' : ['eventNumber', 'particleNumber', 'pid', 'status', 'station', 't', 'x', 'y', 'z', 'px', 'py', 'pz', 'bx', 'by', 'bz', 'local_weight',
836  'ex', 'ey', 'ez', '', 'sx', 'sy', 'sz'],
837  'icool_for003' : ['eventNumber', 'particleNumber', 'pid', 'status', 't', 'local_weight', 'x', 'y', 'z', 'px', 'py', 'pz', 'sx', 'sy', 'sz'],
838  'g4beamline_bl_track_file' : ['x','y','z','px','py','pz','t','pid','eventNumber','particleNumber', '','local_weight'],
839  'ZGoubi' : [],
840  'Turtle' : [],
841  'MadX' : [],
842  'mars_1' : ['eventNumber','pid','x','y','z','px','py','pz','energy','ct','local_weight']
843  }
844  __file_units = {
845  'icool_for009' : {'eventNumber':'', 'particleNumber':'', 'pid':'', 'status':'', 'station':'', 't':'s', 'x':'m', 'y':'m', 'z':'m', 'px':'GeV/c', 'py':'GeV/c',
846  'pz':'GeV/c', 'bx':'T', 'by':'T', 'bz':'T', 'local_weight':'',
847  'ex':'GV/m', 'ey':'GV/m', 'ez':'GV/m', 'sx':'', 'sy':'', 'sz':'', '':''},
848  'icool_for003' : {'eventNumber':'', 'particleNumber':'', 'pid':'', 'status':'', 't':'s', 'local_weight':'', 'x':'m', 'y':'m', 'z':'m', 'px':'GeV/c', 'py':'GeV/c', 'pz':'GeV/c', 'sx':'', 'sy':'', 'sz':''},
849  'g4beamline_bl_track_file' : {'x':'mm','y':'mm','z':'mm','px':'MeV/c','py':'MeV/c','pz':'MeV/c','t':'ns','pid':'','eventNumber':'','station':'','local_weight':'', 'particleNumber':''},
850  'ZGoubi' : {},
851  'Turtle' : {},
852  'MadX' : {},
853  'mars_1' : {'eventNumber':'','pid':'','x':'mm','y':'mm','z':'mm','px':'GeV/c','py':'GeV/c','pz':'GeV/c','energy':'GeV','ct':'cm','local_weight':''},
854  'maus_json_virtual_hit': {},
855  'maus_json_primary': {},
856  }
858  __file_headers = {
859  'icool_for003':'<user>\n0. 0. 0. 0. 0. 0. 0. 0.\n',
860  'icool_for009':'#<user>\n# units = [s] [m] [GeV/c] [T] [V/m]\nevt par typ flg reg time x y z Px Py Pz Bx By Bz wt Ex Ey Ez arclength polX polY polZ\n',
861  'g4beamline_bl_track_file':'#BLTrackFile <user>\n#x y z Px Py Pz t PDGid EvNum TrkId Parent weight\n',
862  'ZGoubi':'',
863  'Turtle':'',
864  'MadX':'',
865  'mars_1':'',
866  'maus_json_virtual_hit':'',
867  'maus_json_primary':'',
868  }
869  __default_user_string = 'File generated by X_BOA'
870 
871  def __event_cmp(lhs, rhs):
872  return cmp(lhs.get('eventNumber'), rhs.get('eventNumber'))
873  __event_cmp = staticmethod(__event_cmp)
874 
875  def __station_cmp(lhs, rhs):
876  return cmp(lhs.get('station'), rhs.get('station'))
877  __station_cmp = staticmethod(__station_cmp)
878 
879 
880  __hit_sort_comparator = {
881  'icool_for009': __event_cmp,
882  'icool_for003': __event_cmp,
883  'g4beamline_bl_track_file': __event_cmp,
884  'ZGoubi': __event_cmp,
885  'Turtle': __event_cmp,
886  'MadX': __event_cmp,
887  'maus_json_virtual_hit': __event_cmp,
888  'maus_json_primary': __event_cmp,
889  'mars_1': __event_cmp,
890  }
891 
892  __angular_momentum_centroid = (0.,0.,0.)
893  __angular_momentum_vector = (0.,0.,1.)
894  __bad_pids = []
895 
896  __maus_root_mc_types = {
897  "maus_root_virtual_hit": lambda x, y: Hit.__get_maus_root_virtual_hits(x, y),
898  "maus_root_primary": lambda x, y: Hit.__get_maus_root_primary_hits(x, y)
899  }
900  __maus_root_recon_types = {}
901 
902  __opal_ignore_probes = ["RING"]
903  __opal_probes = {}
904  __opal_pid = 0
905 
906  def hit_overview_doc(verbose = False):
907  """Creates some summary documentation for the Hit class. If verbose is True then will also print any functions or data not included in summary"""
908  name_list = ['initialise', 'get', 'set', 'transform', 'io', 'ancillary']
909  function_list = {
910  'initialise' : ['new_from_dict', 'new_from_read_builtin', 'new_from_read_user', 'copy', 'deepcopy'],
911  'get' : ['get', 'get_ct', 'get_ek', 'get_global_weight', 'get_l_kin', 'get_local_weight', 'get_p', 'get_phi', 'get_pphi', 'get_pt', 'get_r', 'get_rP', 'get_r_squared', 'get_spin', 'get_tP', 'get_vector', 'get_weight', 'get_xP', 'get_yP'],
912  'set' : ['set', 'set_ct', 'set_ek', 'set_local_weight', 'set_p', 'set_tP', 'set_variables', 'set_xP', 'set_yP', 'set_global_weight'],
913  'transform' : ['abelian_transformation', 'translate', 'mass_shell_condition'],
914  'io' : ['file_header', 'file_types', 'set_g4bl_unit', 'write_builtin_formatted', 'write_list_builtin_formatted', 'write_user_formatted', 'open_filehandle_for_writing', 'get_maus_dict', 'get_maus_paths', 'get_maus_tree'],
915  'ancillary' : ['check','clear_global_weights', 'delete_global_weights', 'get_bad_pids', 'set_bad_pids', 'dict_from_hit', 'mass_shell_variables', 'get_variables']
916  }
917  function_doc = {
918  'initialise':'Functions that can be used to initialise a Hit in various different ways:',
919  'get' :'Functions to get Hit data',
920  'set' :'Functions to set Hit data',
921  'transform' :'Functions that transform a Hit in some way:',
922  'io' :'Output and some input helper functions:',
923  'ellipse':'Functions to calculate beam ellipses based on Twiss parameters etc:',
924  'ancillary':'Some other useful functions'
925  }
926  hit_doc = '\nHit class stores all data for a Hit on e.g. a detector - so for example, (x,y,z) and (px,py,pz) data. Mimics a string-indexed dict; full documentation for internal variables is given below under Hitcore. In brief, gettable variables are\n'+str(Hit.get_variables())+'\n and settable variables are\n'+str(Hit.set_variables())+'.\n Call using e.g. my_hit[\'x\'] = 3. Also has IO functions and a few other useful functions.\n'
927  dir_hit = dir(Hit)
928  if verbose:
929  print 'The following functions and data are in Bunch but not in overview_doc:'
930  for func in dir_hit:
931  found = False
932  for func_sublist in function_list.values():
933  if func in func_sublist: found = True
934  if not found: print func,
935  print '\n'
937  print 'The following functions and data are in bunch_overview_doc but not in Bunch:'
938  for func_sublist in function_list.values():
939  for func in func_sublist:
940  if func not in dir_hit:
941  print func,
942  print
943 
944  doc = hit_doc
945  for key in name_list:
946  doc = doc + function_doc[key]+'\n'
947  for item in function_list[key]:
948  doc = doc+' '+item+'\n'
949  return doc
950  hit_overview_doc = staticmethod(hit_overview_doc)
951 
952 __doc__ = Hit.hit_overview_doc()
953 
def get_phi
Returns transverse angle (i.e.
Definition: _hit.py:596
tuple __station_cmp
Definition: _hit.py:942
dictionary __file_formats
Definition: _hit.py:899
def __do_nothing
Definition: _hit.py:836
def __setitem__
Mimic some aspects of dict.
Definition: _hit.py:139
The hit factory module defines a number of factory classes used for generating hit objects...
Definition: __init__.py:1
def __ne__
Test for inequality of data values between self and target.
Definition: _hit.py:129
def get_local_weight
Returns local weight for this Hit.
Definition: _hit.py:717
def dict_from_hit
Return a dict that uniquely defines the hit, so that new_from_dict(dict_from_hit(hit)) returns a copy...
Definition: _hit.py:397
tuple __split_list_by_equality
Definition: _hit.py:798
def __repr__
Formatting for print command.
Definition: _hit.py:104
dictionary __file_units
Definition: _hit.py:909
Factory class for line by line reads of output files using a user-defined format. ...
def clear_global_weights
Set all global weights to 1.
Definition: _hit.py:705
def get_xP
Returns x divergence i.e.
Definition: _hit.py:616
def get_weight
Returns total weight for this Hit.
Definition: _hit.py:700
def __write_formatted
Definition: _hit.py:750
tuple __get_maus_root_virtual_hits
Definition: _hit.py:776
def abelian_transformation
Perform an abelian transformation about the origin, i.e.
Definition: _hit.py:295
BadEventError is raised if Hit reads a bad.
Definition: _hit.py:41
def translate
Iterate over translation_dict and add the value in the dict to the value stored in Hit...
Definition: _hit.py:276
tuple new_from_read_builtin
Definition: _hit.py:183
def copy
Return a shallow copy of self (copying data as references)
Definition: _hit.py:240
def set_ek
Sets kinetic energy = total energy - mass of the hit.
Definition: _hit.py:651
def write_user_formatted
Write to a file formatted according to built-in file_type format.
Definition: _hit.py:514
def set_tP
Set t\' (dt/dz=-E/pz) to value_float keeping pz constant; note sign of pz may change.
Definition: _hit.py:690
def check
Return True if mass shell condition is obeyed and pid is correct for the mass else return False...
Definition: _hit.py:380
def get_tP
Returns t \'divergence\' i.e.
Definition: _hit.py:626
def __eq__
Test for equality of data values between self and target.
Definition: _hit.py:121
def get_rP
Returns dr/dz = pt/pz of the hit.
Definition: _hit.py:631
tuple __get_maus_tree_recursive
Definition: _hit.py:821
def get_pphi
Returns transverse angle of momentum (i.e.
Definition: _hit.py:606
def write_builtin_formatted
Write to a file formatted according to built-in file_type format.
Definition: _hit.py:414
Factory class for line by line reads of output files.
def __del__
Clean up.
Definition: _hit.py:144
tuple hit_overview_doc
Definition: _hit.py:1016
def __deepcopy__
Deep copy i.e.
Definition: _hit.py:115
def get_pt
Returns transverse momentum of the hit.
Definition: _hit.py:601
tuple new_from_dict
Definition: _hit.py:164
def get_vector
Return a numpy vector of data values taking data from get_variable_list, relative to some origin...
Definition: _hit.py:260
common module defines common utility data and functions that are used elsewhere
Definition: __init__.py:1
def new_list_from_maus_root
Static function returns a list of hit objects found in the spill.
Definition: _hit.py:216
def __getitem__
Mimic some aspects of dict.
Definition: _hit.py:134
def set_local_weight
Set local weight for this Hit to be value.
Definition: _hit.py:722
tuple get_maus_tree
Definition: _hit.py:560
list __mass_shell_variables
Definition: _hit.py:853
tuple __get_maus_root_primary_hits
Definition: _hit.py:788
def mass_shell_condition
Change variable represented by variable_string to force E^2 = p^2 + m^2.
Definition: _hit.py:316
def set_ct
Sets t = value_float/c_light.
Definition: _hit.py:662
def __return_one
Definition: _hit.py:833
dictionary __set_variables
Definition: _hit.py:857
def __init__
Initialise to an empty event.
Definition: _hit.py:99
def new_list_from_maus_json
Static function returns a list of hit objects found in the spill.
Definition: _hit.py:233
def file_types
Static function returns a list of available file types.
Definition: _hit.py:519
def get_r
Returns transverse distance (i.e.
Definition: _hit.py:591
def mass_shell_variables
Static function returns a list of variables suitable for mass_shell_condition calls.
Definition: _hit.py:566
def set_variables
Static function returns a list of variable suitable for set calls.
Definition: _hit.py:578
tuple set_g4bl_unit
Definition: _hit.py:747
dictionary __get_variables
Definition: _hit.py:854
Represents a particle at a point in some phase space.
Definition: _hit.py:93
def get_l_kin
Returns kinetic angular momentum about the z-axis.
Definition: _hit.py:657
tuple write_list_builtin_formatted
Definition: _hit.py:471
def set_global_weight
Set global weight for this Hit to be value.
Definition: _hit.py:732
def get_ct
Returns speed_of_light*t of the hit.
Definition: _hit.py:641
tuple new_from_read_user
Definition: _hit.py:202
def get_spin
Returns absolute value of the spin.
Definition: _hit.py:636
def delete_global_weights
Clear memory allocated to global weights - also resets global weights to 1.
Definition: _hit.py:711
def deepcopy
Return a deep copy of target (deep copying target's data to self as well)
Definition: _hit.py:245
tuple open_filehandle_for_writing
Definition: _hit.py:485
def get_maus_dict
Convert from hit to a maus dict for MAUS IO.
Definition: _hit.py:531
tuple file_header
Definition: _hit.py:501
def get_ek
Returns total energy - mass, ie kinetic energy of the hit.
Definition: _hit.py:646
def get_p
Returns total momentum of the hit.
Definition: _hit.py:586
def __copy__
Shallow copy i.e.
Definition: _hit.py:109
tuple __event_cmp
Definition: _hit.py:938
def get
Return the value referenced by key.
Definition: _hit.py:351
def set_xP
Set x\' to value_float keeping pz constant.
Definition: _hit.py:678
def get_r_squared
Returns x divergence i.e.
Definition: _hit.py:611
def get_variables
Static function returns a list of variable suitable for get calls.
Definition: _hit.py:572
def set_yP
Set y\' to value_float keeping pz constant.
Definition: _hit.py:684
def get_global_weight
Returns global weight for this Hit.
Definition: _hit.py:727
def get_yP
Returns y divergence i.e.
Definition: _hit.py:621
def set_p
Set p to value_float keeping momentum direction constant.
Definition: _hit.py:667
def set
Set the value referenced by key.
Definition: _hit.py:368