Skip to content

Commit 38784ad

Browse files
authored
Merge pull request #54 from mfittere/bws
First version of BWS class and update BSRT variables
2 parents 0b565c2 + e245e27 commit 38784ad

File tree

5 files changed

+572
-59
lines changed

5 files changed

+572
-59
lines changed

pytimber/LHCBSRT.py

Lines changed: 118 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -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

117170
class 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

Comments
 (0)