@@ -36,14 +36,12 @@ def _get_timber_data(beam,t1,t2,db=None):
3636 *_time = time stamps for rarely logged
3737 variables, explicitly timber variables
3838 %LHC%BSRT%LSF_%, %LHC%BSRT%BETA% and
39- LHC.STATS:ENERGY
39+ LHC.BOFSU:OFC_ENERGY
4040 """
4141 # -- some checks
4242 if t2 < t1 :
4343 raise ValueError ('End time smaller than start time, t2 = ' +
4444 '%s > %s = t1' % (t2 ,t1 ))
45- if beam not in ['B1' ,'B2' ]:
46- raise ValueError ("beam = %s must be either 'B1' or 'B2'" % beam )
4745 # --- get data
4846 # timber variable names are stored in *_var variables
4947 # bsrt_sig and bsrt_lsf = BSRT data from timber
@@ -70,25 +68,32 @@ def _get_timber_data(beam,t1,t2,db=None):
7068 + '%LSF_%' )
7169 [beta_h_var , beta_v_var ] = db .search ('%LHC%BSRT%' + beam .upper ()
7270 + '%BETA%' )
73- energy_var = u'LHC.STATS:ENERGY '
71+ energy_var = u'LHC.BOFSU:OFC_ENERGY '
7472 bsrt_lsf_var = [lsf_h_var , lsf_v_var , beta_h_var , beta_v_var ,
7573 energy_var ]
7674 t1_lsf = t1
7775 bsrt_lsf = db .get (bsrt_lsf_var , t1_lsf , t2 )
7876 # only logged rarely, loop until array is not empty, print warning
7977 # if time window exceeds one month
80- while (bsrt_lsf [lsf_h_var ][0 ].size == 0 or
81- bsrt_lsf [lsf_v_var ][0 ].size == 0 or
82- bsrt_lsf [beta_h_var ][0 ].size == 0 or
83- bsrt_lsf [beta_v_var ][0 ].size == 0 or
84- bsrt_lsf [energy_var ][0 ].size == 0 ):
85- if (np .abs (t1_lsf - t1 ) > 30 * 24 * 60 * 60 ):
86- raise ValueError (('Last logging time for ' + ', %s' * 5
87- + ' exceeds 1 month! Check your data!!!' )% tuple (bsrt_lsf_var ))
88- return
89- else :
90- t1_lsf = t1_lsf - 24 * 60 * 60
91- bsrt_lsf = db .get (bsrt_lsf_var , t1_lsf , t2 )
78+ # check that time stamp of lsf,beta,energy is before first sigma
79+ # timestamp
80+ for var in bsrt_lsf_var :
81+ while (bsrt_lsf [var ][0 ].size == 0 ):
82+ if (np .abs (t1_lsf - t1 ) > 30 * 24 * 60 * 60 ):
83+ raise ValueError (('Last logging time for ' + ', %s' * 5
84+ + ' exceeds 1 month! Check your data!!!' )% tuple (bsrt_lsf_var ))
85+ return
86+ else :
87+ t1_lsf = t1_lsf - 24 * 60 * 60
88+ bsrt_lsf = db .get (bsrt_lsf_var , t1_lsf , t2 )
89+ while (bsrt_lsf [var ][0 ][0 ] > bsrt_sig [bsrt_sig_var [0 ]][0 ][0 ]):
90+ if (np .abs (t1_lsf - t1 ) > 30 * 24 * 60 * 60 ):
91+ raise ValueError (('Last logging time for ' + ', %s' * 5
92+ + ' exceeds 1 month! Check your data!!!' )% tuple (bsrt_lsf_var ))
93+ return
94+ else :
95+ t1_lsf = t1_lsf - 24 * 60 * 60
96+ bsrt_lsf = db .get (bsrt_lsf_var , t1_lsf , t2 )
9297 # -- create list containing all the data (bsrt_list), then save
9398 # data in structured array bsrt_data
9499 # take timestamp from GATE_DELAY (same as for other variables)
@@ -113,6 +118,54 @@ def _get_timber_data(beam,t1,t2,db=None):
113118 ('energy' ,float )]
114119 bsrt_data = np .array (bsrt_list ,dtype = ftype )
115120 return bsrt_data
121+ def _timber_to_emit (bsrt_array ):
122+ """
123+ returns dictionary with emittance etc. as used in BSRT.fromdb
124+
125+ Parameters:
126+ -----------
127+ bsrt_array : data extracted from timber with _get_timber_data
128+
129+ Returns:
130+ --------
131+ emit_dict: dictionary with emittances
132+ {slot: [time [s],emith [um],emitv[um],sigh[mm],sigv[mm],
133+ lsfh [mm], lsfv[mm], beth[mm], betv[mm],energy[GeV]]}
134+ """
135+ # create dictionary indexed with slot number
136+ emit_dict = {}
137+ # loop over slots
138+ for j in set (bsrt_array ['gate' ]):
139+ # data for slot j
140+ bsrt_slot = bsrt_array [bsrt_array ['gate' ]== j ]
141+ bsrt_emit = []
142+ # loop over all timestamps for slot j
143+ for tt in set (bsrt_slot ['time' ]):
144+ # data for slot j and timestamp tt
145+ bsrt_aux = bsrt_slot [bsrt_slot ['time' ]== tt ]
146+ # gives back several values per timestamp -> take the mean value
147+ # energy [GeV]
148+ energy_aux = np .mean (bsrt_aux ['energy' ])
149+ sigh ,lsfh ,beth = bsrt_aux ['sigh' ],bsrt_aux ['lsfh' ],bsrt_aux ['beth' ]
150+ sigv ,lsfv ,betv = bsrt_aux ['sigv' ],bsrt_aux ['lsfv' ],bsrt_aux ['betv' ]
151+ # geometric emittance [um]
152+ emith_aux = np .mean ((sigh ** 2 - lsfh ** 2 )/ beth )
153+ emitv_aux = np .mean ((sigv ** 2 - lsfv ** 2 )/ betv )
154+ sigh ,lsfh ,beth = np .mean ([sigh ,lsfh ,beth ],axis = 1 )
155+ sigv ,lsfv ,betv = np .mean ([sigv ,lsfv ,betv ],axis = 1 )
156+ # normalized emittance
157+ emith = emitnorm (emith_aux , energy_aux )
158+ emitv = emitnorm (emitv_aux , energy_aux )
159+ bsrt_emit .append ((tt ,emith ,emitv ,sigh ,sigv ,lsfh ,lsfv ,
160+ beth ,betv ,energy_aux ))
161+ # sort after the time
162+ emit_dict [j ] = np .sort (np .array (bsrt_emit ,
163+ dtype = [('time' ,float ),('emith' ,float ),('emitv' ,float ),
164+ ('sigh' ,float ),('sigv' ,float ),
165+ ('lsfh' ,float ),('lsfv' ,float ),
166+ ('beth' ,float ),('betv' ,float ),('energy' ,float )]),
167+ axis = 0 )
168+ return emit_dict
116169
117170class BSRT (object ):
118171 """
@@ -127,8 +180,9 @@ class to analyze BSRT data
127180
128181 Attributes:
129182 -----------
130- timber_variables : timber variables needed to calculate
183+ timber_vars : timber variables needed to calculate
131184 normalized emittance
185+ beam : 'B1' for beam 1 or 'B2' for beam2
132186 t_start, t_end : start/end time of extracted data
133187 emit : dictionary of normalized emittances
134188 {slot: [time[s], emith[um], emitv[um]]}
@@ -144,20 +198,21 @@ class to analyze BSRT data
144198 Values are added to *emitfit*.
145199 get_fit : extract fit data for specific slot and times
146200 """
147- timber_variables = {}
148- timber_variables ['B1' ] = [u'LHC.BSRT.5R4.B1:FIT_SIGMA_H' ,
201+ timber_vars = {}
202+ timber_vars ['B1' ] = [u'LHC.BSRT.5R4.B1:FIT_SIGMA_H' ,
149203 u'LHC.BSRT.5R4.B1:FIT_SIGMA_V' , u'LHC.BSRT.5R4.B1:GATE_DELAY' ,
150204 u'LHC.BSRT.5R4.B1:LSF_H' , u'LHC.BSRT.5R4.B1:LSF_V' ,
151205 u'LHC.BSRT.5R4.B1:BETA_H' , u'LHC.BSRT.5R4.B1:BETA_V' ,
152- 'LHC.STATS:ENERGY ' ]
153- timber_variables ['B2' ]= [u'LHC.BSRT.5L4.B2:FIT_SIGMA_H' ,
206+ 'LHC.BOFSU:OFC_ENERGY ' ]
207+ timber_vars ['B2' ]= [u'LHC.BSRT.5L4.B2:FIT_SIGMA_H' ,
154208 u'LHC.BSRT.5L4.B2:FIT_SIGMA_V' , u'LHC.BSRT.5L4.B2:GATE_DELAY' ,
155209 u'LHC.BSRT.5L4.B2:LSF_H' , u'LHC.BSRT.5L4.B2:LSF_V' ,
156210 u'LHC.BSRT.5L4.B2:BETA_H' , u'LHC.BSRT.5L4.B2:BETA_V' ,
157- 'LHC.STATS:ENERGY ' ]
158- def __init__ (self ,db = None ,emit = None ,emitfit = None ,t_start = None ,
211+ 'LHC.BOFSU:OFC_ENERGY ' ]
212+ def __init__ (self ,db = None ,beam = None , emit = None ,emitfit = None ,t_start = None ,
159213 t_end = None ):
160214 self .db = db
215+ self .beam = beam
161216 self .emit = emit
162217 self .emitfit = emitfit
163218 self .t_start = t_start
@@ -189,8 +244,11 @@ def fromdb(cls,t1,t2,beam='B1',db=None,verbose=False):
189244 -------
190245 class: BSRT class instance with dictionary of normalized emittances
191246 stored in self.emit. self.emit is sorted after slot number
192- {slot: [time [s],emith [um],emitv[um]]}
247+ {slot: [time [s],emith [um],emitv[um],sigh[mm],sigv[mm],
248+ lsfh [mm], lsfv[mm], beth[mm], betv[mm],energy[GeV]]}
193249 """
250+ if beam not in ['B1' ,'B2' ]:
251+ raise ValueError ("beam = %s must be either 'B1' or 'B2'" % beam )
194252 # if no database is given create dummy database to extract data
195253 if db is None :
196254 db = pytimber .LoggingDB ()
@@ -199,40 +257,15 @@ def fromdb(cls,t1,t2,beam='B1',db=None,verbose=False):
199257 'pytimber.LoggingDB()' )
200258 if verbose :
201259 print ('... extracting data from timber' )
260+ if verbose :
261+ print ('... calculating emittance for non-empty slots' )
202262 # -- get timber data
203263 bsrt_array = _get_timber_data (beam = beam ,t1 = t1 ,t2 = t2 ,db = db )
204264 # -- calculate emittances, store them in
205265 # dictionary self.emit = emit
206- if verbose :
207- print ('... calculating emittance for non-empty slots' )
208- # create dictionary indexed with slot number
209- emit_dict = {}
210- # loop over slots
211- for j in set (bsrt_array ['gate' ]):
212- # data for slot j
213- bsrt_slot = bsrt_array [bsrt_array ['gate' ]== j ]
214- bsrt_emit = []
215- # loop over all timestamps for slot j
216- for k in set (bsrt_slot ['time' ]):
217- # data for slot j and timestamp k
218- bsrt_aux = bsrt_slot [bsrt_slot ['time' ]== k ]
219- # gives back several values per timestamp -> take the mean value
220- # energy [GeV]
221- energy_aux = np .mean (bsrt_aux ['energy' ])
222- # geometric emittance [um]
223- emith_aux = np .mean ((bsrt_aux ['sigh' ]** 2
224- - bsrt_aux ['lsfh' ]** 2 )/ bsrt_aux ['beth' ])
225- emitv_aux = np .mean ((bsrt_aux ['sigv' ]** 2
226- - bsrt_aux ['lsfv' ]** 2 )/ bsrt_aux ['betv' ])
227- # normalized emittance
228- emith = emitnorm (emith_aux , energy_aux )
229- emitv = emitnorm (emitv_aux , energy_aux )
230- bsrt_emit .append ((k ,emith ,emitv ))
231- # sort after the time
232- emit_dict [j ] = np .sort (np .array (bsrt_emit ,
233- dtype = [('time' ,float ),('emith' ,float ),('emitv' ,float )]),
234- axis = 0 )
235- return cls (db = db ,emit = emit_dict ,emitfit = None ,t_start = t1 ,t_end = t2 )
266+ emit_dict = _timber_to_emit (bsrt_array )
267+ return cls (db = db ,emit = emit_dict ,emitfit = None ,
268+ t_start = t1 ,t_end = t2 ,beam = beam )
236269 def get_timber_data (self ,beam ,t1 ,t2 ,db = None ):
237270 """
238271 retrieve data from timber needed for
@@ -255,9 +288,36 @@ def get_timber_data(self,beam,t1,t2,db=None):
255288 *_time = time stamps for rarely logged
256289 variables, explicitly timber variables
257290 %LHC%BSRT%LSF_%, %LHC%BSRT%BETA% and
258- LHC.STATS:ENERGY
291+ LHC.BOFSU:OFC_ENERGY
292+ """
293+ return _get_timber_data (beam = beam ,t1 = t1 ,t2 = t2 ,db = db )
294+ def update_beta_lsf_energy (self ,t1 ,t2 ,beth = None ,betv = None ,
295+ lsfh = None ,lsfv = None ,energy = None ,verbose = False ):
296+ """
297+ update beta and lsf factor within t1 and t2.
298+
299+ Parameters:
300+ ----------
301+ t1,t2: start/end time in unix time [s]
302+ betah,betav: hor./vert. beta function [m]
303+ lsfh, lsfv: hor./vert. lsf factor [mm]
304+ energy: beam energy [GeV]
259305 """
260- return _get_timber_data (beam ,t1 ,t2 ,db )
306+ bsrt_array = _get_timber_data (beam = self .beam ,
307+ t1 = self .t_start ,t2 = self .t_end ,
308+ db = self .db )
309+ # only change values between t1 and t2
310+ mask = np .logical_and (bsrt_array ['time' ]>= t1 ,bsrt_array ['time' ]<= t2 )
311+ for k ,v in zip (['beth' ,'betv' ,'lsfh' ,'lsfv' ,'energy' ],[beth ,betv ,lsfh ,lsfv ,energy ]):
312+ if verbose :
313+ print k ,'old=' ,bsrt_array [k ][mask ],'new=' ,v
314+ if v is None :
315+ continue
316+ bsrt_array [k ][mask ] = v
317+ # -- calculate emittances, store them in
318+ # dictionary self.emit = emit
319+ self .emit = _timber_to_emit (bsrt_array )
320+
261321 def get_fit (self ,slot ,t1 = None ,t2 = None ,verbose = False ):
262322 """
263323 Function to access fit values for slot *slot* between t1 and t2.
@@ -483,7 +543,8 @@ def plot(self,plane='h',t1=None,t2=None,slots=None,avg=10,fit=True,
483543 if fit :
484544 self .plot_fit (plane = plane ,t1 = t1 ,t2 = t2 ,slots = slots ,
485545 linestyle = '--' ,color = 'k' ,verbose = verbose )
486- set_xaxis_date ()
546+ else :
547+ set_xaxis_date ()
487548 pl .ylabel (r'$\epsilon_{N,%s} \ [\mu\mathrm{ m}]$' % plane .upper ())
488549 pl .grid (b = True )
489550 if label is not None :
0 commit comments