From 838009eabce513ca892d074fadb833d944b92bb9 Mon Sep 17 00:00:00 2001 From: Ana Clara Oliveira Date: Fri, 24 Feb 2023 18:04:36 -0300 Subject: [PATCH 01/19] macreport.ENH: refactor MacReport statistics calculation, clean up code and improve code readability --- siriuspy/siriuspy/machshift/macreport.py | 537 ++++++++++++----------- 1 file changed, 288 insertions(+), 249 deletions(-) diff --git a/siriuspy/siriuspy/machshift/macreport.py b/siriuspy/siriuspy/machshift/macreport.py index 21248456a..ba1620329 100644 --- a/siriuspy/siriuspy/machshift/macreport.py +++ b/siriuspy/siriuspy/machshift/macreport.py @@ -242,6 +242,15 @@ class MacReport: THOLD_FACTOR_USERSSBEAM = 0.5 # 50% QUERY_AVG_TIME = 60 # [s] + SHIFTS = [ + 'Injection', + 'MachineStudy', + 'Commissioning', + 'Conditioning', + 'Maintenance', + 'Users', + ] + def __init__(self, connector=None, logger=None): """Initialize object.""" # client archiver connector @@ -312,12 +321,12 @@ def __init__(self, connector=None, logger=None): self._lsusage_maintenance_operational = None self._lsusage_maintenance_time = None self._lsusage_maintenance = None - self._lsusage_user_failures_time = None - self._lsusage_user_failures = None - self._lsusage_user_operational_time = None - self._lsusage_user_operational = None - self._lsusage_user_time = None - self._lsusage_user = None + self._lsusage_users_failures_time = None + self._lsusage_users_failures = None + self._lsusage_users_operational_time = None + self._lsusage_users_operational = None + self._lsusage_users_time = None + self._lsusage_users = None # stored current stats self._current_machinestudy_singlebunch_average = None @@ -347,15 +356,15 @@ def __init__(self, connector=None, logger=None): self._current_conditioning_total_average = None self._current_conditioning_total_stddev = None self._current_conditioning_total_time = None - self._current_user_singlebunch_average = None - self._current_user_singlebunch_stddev = None - self._current_user_singlebunch_time = None - self._current_user_multibunch_average = None - self._current_user_multibunch_stddev = None - self._current_user_multibunch_time = None - self._current_user_total_average = None - self._current_user_total_stddev = None - self._current_user_total_time = None + self._current_users_singlebunch_average = None + self._current_users_singlebunch_stddev = None + self._current_users_singlebunch_time = None + self._current_users_multibunch_average = None + self._current_users_multibunch_stddev = None + self._current_users_multibunch_time = None + self._current_users_total_average = None + self._current_users_total_stddev = None + self._current_users_total_time = None self._current_ebeam_singlebunch_average = None self._current_ebeam_singlebunch_stddev = None self._current_ebeam_singlebunch_time = None @@ -371,20 +380,20 @@ def __init__(self, connector=None, logger=None): self._curr_times = None self._curr_values = None self._ps_fail_values = None - self._gamblk_fail_values = None - self._sofbloop_fail_values = None + self._gamma_fail_values = None + self._bbbstab_fail_values = None self._mps_fail_values = None - self._inj_shift_values = None + self._injection_shift_values = None self._machinestudy_shift_values = None self._commissioning_shift_values = None self._conditioning_shift_values = None self._maintenance_shift_values = None - self._user_shift_values = None - self._user_shift_act_values = None - self._user_shift_progmd_values = None - self._user_shift_inicurr_values = None - self._user_shift_delivd_values = None - self._user_shift_stable_values = None + self._users_shift_values = None + self._users_shift_act_values = None + self._users_shift_progmd_values = None + self._users_shift_inicurr_values = None + self._users_shift_delivd_values = None + self._users_shift_stable_values = None self._is_stored_total = None self._is_stored_users = None self._singlebunch_values = None @@ -735,34 +744,34 @@ def lsusage_maintenance(self): return self._lsusage_maintenance @property - def lsusage_user_failures_time(self): + def lsusage_users_failures_time(self): """Failures time in Users Shift.""" - return self._conv_sec_2_hour(self._lsusage_user_failures_time) + return self._conv_sec_2_hour(self._lsusage_users_failures_time) @property - def lsusage_user_failures(self): + def lsusage_users_failures(self): """Relative failures time in Users Shift.""" - return self._lsusage_user_failures + return self._lsusage_users_failures @property - def lsusage_user_operational_time(self): + def lsusage_users_operational_time(self): """Operational time in Users Shift.""" - return self._conv_sec_2_hour(self._lsusage_user_operational_time) + return self._conv_sec_2_hour(self._lsusage_users_operational_time) @property - def lsusage_user_operational(self): + def lsusage_users_operational(self): """Relative operational time in Users Shift.""" - return self._lsusage_user_operational + return self._lsusage_users_operational @property - def lsusage_user_time(self): + def lsusage_users_time(self): """Time in Users Shift.""" - return self._conv_sec_2_hour(self._lsusage_user_time) + return self._conv_sec_2_hour(self._lsusage_users_time) @property - def lsusage_user(self): + def lsusage_users(self): """Relative time in Users Shift.""" - return self._lsusage_user + return self._lsusage_users # stored current stats @@ -918,50 +927,50 @@ def current_conditioning_total_time(self): return self._conv_sec_2_hour(self._current_conditioning_total_time) @property - def current_user_singlebunch_average(self): + def current_users_singlebunch_average(self): """Current average for single bunch user shifts.""" - return self._current_user_singlebunch_average + return self._current_users_singlebunch_average @property - def current_user_singlebunch_stddev(self): + def current_users_singlebunch_stddev(self): """Current standard deviation for single bunch user shifts.""" - return self._current_user_singlebunch_stddev + return self._current_users_singlebunch_stddev @property - def current_user_singlebunch_time(self): + def current_users_singlebunch_time(self): """Time of single bunch user shifts. Consider any stored current.""" - return self._conv_sec_2_hour(self._current_user_singlebunch_time) + return self._conv_sec_2_hour(self._current_users_singlebunch_time) @property - def current_user_multibunch_average(self): + def current_users_multibunch_average(self): """Current average for multi bunch user shifts.""" - return self._current_user_multibunch_average + return self._current_users_multibunch_average @property - def current_user_multibunch_stddev(self): + def current_users_multibunch_stddev(self): """Current standard deviation for multi bunch user shifts.""" - return self._current_user_multibunch_stddev + return self._current_users_multibunch_stddev @property - def current_user_multibunch_time(self): + def current_users_multibunch_time(self): """Time of multi bunch user shifts. Consider any stored current.""" - return self._conv_sec_2_hour(self._current_user_multibunch_time) + return self._conv_sec_2_hour(self._current_users_multibunch_time) @property - def current_user_total_average(self): + def current_users_total_average(self): """Current average in all user shifts.""" - return self._current_user_total_average + return self._current_users_total_average @property - def current_user_total_stddev(self): + def current_users_total_stddev(self): """Current standard deviation in all user shifts.""" - return self._current_user_total_stddev + return self._current_users_total_stddev @property - def current_user_total_time(self): + def current_users_total_time(self): """Time of user shifts. Consider any stored current.""" - return self._conv_sec_2_hour(self._current_user_total_time) + return self._conv_sec_2_hour(self._current_users_total_time) @property def current_ebeam_singlebunch_average(self): @@ -1038,12 +1047,13 @@ def update(self): self._pvdata[self._current_pv].update(MacReport.QUERY_AVG_TIME) self._update_log(log_msg.format(self._current_pv, _time.time()-_t0)) - # macshift and sirius interlock + # macshift, interlock and stability indicators for pvn in self._pvnames: if pvn == self._current_pv: continue + interval, parallel = None, False _t0 = _time.time() - self._pvdata[pvn].update(parallel=False) + self._pvdata[pvn].update(mean_sec=interval, parallel=parallel) self._update_log(log_msg.format(pvn, _time.time()-_t0)) # ps @@ -1119,7 +1129,7 @@ def plot_raw_data(self): axs[7].xaxis.axis_date() axs[7].plot( - datetimes, self._raw_data['GammaShutter'], '-', + datetimes, self._raw_data['Failures']['GammaShutter'], '-', color='red', label='Failures - Gamma Shutter Closed') axs[7].legend(loc='upper left', fontsize=9) axs[7].grid() @@ -1259,117 +1269,106 @@ def _init_connectors(self): self._pv2default[pvn] = 0.0 def _compute_stats(self): + # will populate the following dict self._raw_data = dict() - # current data - _curr_times, _curr_values = self._get_pv_data(self._current_pv) - _curr_values[_curr_values < 0] = 0 - _curr_values[_curr_values > 500] = 0 - - # resample current data, from 1 pt in 60s, to 1pt in 5s - new_len = (len(_curr_times)-1)*12 + 1 - new_times = _np.linspace(_curr_times[0], _curr_times[-1], new_len) - self._curr_times = new_times - self._curr_values = _np.interp( - new_times, _curr_times, _curr_values) - + # get current data and timestamp base + self._curr_times, self._curr_values = self._get_current_data() self._raw_data['Timestamp'] = self._curr_times self._raw_data['Current'] = self._curr_values - # ps status data - psfail_all = [0] * len(self._curr_times) - for psnames in self._psgroup2psname.values(): - for psn in psnames: - psfail_times, psfail_values = \ - self._get_pv_data(psn+':DiagStatus-Mon') - psfail_values = _np.bitwise_and( # disregard alarms - psfail_values.astype(int), 0b1101111) + # get machine schedule data + self._users_shift_progmd_values, self._users_shift_inicurr_values, \ + self._usershift_progmd_count = self._get_macschedule_data() + self._raw_data['UserShiftProgmd'] = self._users_shift_progmd_values + self._raw_data['UserShiftInitCurr'] = self._users_shift_inicurr_values - psfail = 1 * (_interp1d_previous( - psfail_times, psfail_values, self._curr_times) > 0) + # get delivered shifts data + shifts_data = self._get_delivered_shift_data() + self._raw_data['Shift'] = dict() + for shift, value in zip(MacReport.SHIFTS, shifts_data): + self._raw_data['Shift'][shift] = value + setattr(self, f'_{shift.lower()}_shift_values', value) - psfail_all = _np.logical_or(psfail_all, psfail) - self._ps_fail_values = 1 * psfail_all - - # gamma - gamblk_times, gamblk_values = self._get_pv_data(self._gammashutt_pv) - self._gamblk_fail_values = _interp1d_previous( - gamblk_times, gamblk_values, self._curr_times) - self._raw_data['GammaShutter'] = self._gamblk_fail_values - - # sofb loop - sofbloop_times, sofbloop_values = \ - self._get_pv_data(self._sisofbloop_pv) - sofbloop_fail_rawvalues = _np.array( - [1*(v == _SOFBCte.LoopState.Open) for v in sofbloop_values]) - self._sofbloop_fail_values = _interp1d_previous( - sofbloop_times, sofbloop_fail_rawvalues, self._curr_times) + # get injection type data + self._singlebunch_values, self._multibunch_values = \ + self._get_egunmode_data() + self._raw_data['EgunModes'] = dict() + self._raw_data['EgunModes']['SingleBunch'] = self._singlebunch_values + self._raw_data['EgunModes']['MultiBunch'] = self._multibunch_values - # rf and mps status data - siintlk_times, siintlk_values = self._get_pv_data(self._siintlk_pv) - self._mps_fail_values = _interp1d_previous( - siintlk_times, siintlk_values, self._curr_times) + # get pvs data and calculate failures + self._raw_data['Failures'] = dict() - # delivered shift data - shift_times, shift_values = self._get_pv_data(self._macshift_pv) + # - subsystems status + self._ps_fail_values, self._mps_fail_values = \ + self._get_subsystems_status_data() + self._raw_data['Failures']['SubsystemsNOk'] = _np.logical_or( + self._ps_fail_values, self._mps_fail_values) - self._raw_data['Shift'] = dict() + # - gamma + self._gamma_fail_values = self._get_gammashutter_data() + self._raw_data['Failures']['GammaShutter'] = \ + self._gamma_fail_values.astype(int) + + # - is stored data + self._is_stored_total, self._is_stored_users = \ + self._get_storedebeam_data() + self._raw_data['Failures']['NoEBeam'] = \ + _np.logical_not(self._is_stored_users) + + # - wrong shift failures (ignore shorter than 60s) + wrong_shift = \ + 1 * ((self._users_shift_progmd_values - + self._users_shift_values) > 0) + ignore_wrong_shift = _np.zeros(wrong_shift.shape) + for i, val in enumerate(wrong_shift): + if i >= len(wrong_shift) - 12: + break + if val == 1 and not _np.sum(wrong_shift[(i-12):(i+12)]) >= 12: + ignore_wrong_shift[i] = 1 + consider_wrong_shift = wrong_shift - ignore_wrong_shift + self._raw_data['Failures']['WrongShift'] = consider_wrong_shift + + # get pvs data and calculate distortions + # - correction loops + self._raw_data['Distortions'] = dict() + sofbfail = self._get_orbcorr_data() + self._raw_data['Distortions']['SOFBLoop'] = sofbfail + + # calculate statistics + self._calc_beam_for_users_stats() + self._calc_light_source_usage_stats() + self._calc_stored_current_stats() + + def _get_current_data(self): + # current data + _curr_times, _curr_values = self._get_pv_data(self._current_pv) + _curr_values[_curr_values < 0] = 0 + _curr_values[_curr_values > 500] = 0 - inj_shift_values = _np.array( - [1*(v == _Cte.MachShift.Injection) for v in shift_values]) - self._inj_shift_values = _interp1d_previous( - shift_times, inj_shift_values, self._curr_times) - self._raw_data['Shift']['Injection'] = self._inj_shift_values - - stdy_shift_values = _np.array( - [1*(v == _Cte.MachShift.MachineStudy) for v in shift_values]) - self._machinestudy_shift_values = _interp1d_previous( - shift_times, stdy_shift_values, self._curr_times) - self._raw_data['Shift']['MachineStudy'] = \ - self._machinestudy_shift_values - - cmm_shift_values = _np.array( - [1*(v == _Cte.MachShift.Commissioning) for v in shift_values]) - self._commissioning_shift_values = _interp1d_previous( - shift_times, cmm_shift_values, self._curr_times) - self._raw_data['Shift']['Commissioning'] = \ - self._commissioning_shift_values - - cdt_shift_values = _np.array( - [1*(v == _Cte.MachShift.Conditioning) for v in shift_values]) - self._conditioning_shift_values = _interp1d_previous( - shift_times, cdt_shift_values, self._curr_times) - self._raw_data['Shift']['Conditioning'] = \ - self._conditioning_shift_values - - mtn_shift_values = _np.array( - [1*(v == _Cte.MachShift.Maintenance) for v in shift_values]) - self._maintenance_shift_values = _interp1d_previous( - shift_times, mtn_shift_values, self._curr_times) - self._raw_data['Shift']['Maintenance'] = self._maintenance_shift_values - - user_shift_values = _np.array( - [1*(v == _Cte.MachShift.Users) for v in shift_values]) - self._user_shift_values = _interp1d_previous( - shift_times, user_shift_values, self._curr_times) + # # resample current data, from 1 pt in 60s, to 1pt in 5s + new_len = (len(_curr_times)-1)*12 + 1 + new_times = _np.linspace(_curr_times[0], _curr_times[-1], new_len) + times = new_times + values = _np.interp(new_times, _curr_times, _curr_values) + return times, values + def _get_macschedule_data(self): # desired shift data _t0 = _time.time() - self._user_shift_progmd_values = \ - _MacScheduleData.is_user_shift_programmed( - timestamp=self._curr_times) - self._user_shift_inicurr_values = \ - _MacScheduleData.get_initial_current_programmed( - timestamp=self._curr_times) - self._usershift_progmd_count = \ - _MacScheduleData.get_users_shift_count( - self._curr_times[0], self._curr_times[-1]) + users_progmd_values = _MacScheduleData.is_user_shift_programmed( + timestamp=self._curr_times) + users_inicurr_values = _MacScheduleData.get_initial_current_programmed( + timestamp=self._curr_times) + users_progmd_count = _MacScheduleData.get_users_shift_count( + self._curr_times[0], self._curr_times[-1]) self._update_log( 'Query for machine schedule data took {0:.3f}s'.format( _time.time()-_t0)) - self._raw_data['UserShiftProgmd'] = self._user_shift_progmd_values - self._raw_data['UserShiftInitCurr'] = self._user_shift_inicurr_values + return users_progmd_values, users_inicurr_values, users_progmd_count + def _get_egunmode_data(self): # single/multi bunch mode data inj_ts, inj_vs = self._get_pv_data(self._injevt_pv) inj_vs = _interp1d_previous(inj_ts, inj_vs, self._curr_times) @@ -1386,97 +1385,118 @@ def _compute_stats(self): ind = mode_ts.argsort() mode_ts, mode_vs = mode_ts[ind], mode_vs[ind] mode_vs = _interp1d_previous(mode_ts, mode_vs, self._curr_times) - self._singlebunch_values = mode_vs - self._multibunch_values = _np.logical_not(mode_vs) - self._raw_data['EgunModes'] = dict() - self._raw_data['EgunModes']['SingleBunch'] = self._singlebunch_values - self._raw_data['EgunModes']['MultiBunch'] = self._multibunch_values - - # is stored data - self._is_stored_total = self._curr_values > MacReport.THOLD_STOREDBEAM - self._is_stored_users = self._curr_values >= \ - self._user_shift_inicurr_values*MacReport.THOLD_FACTOR_USERSSBEAM - - # auxiliary time vectors - dtimes = _np.diff(self._curr_times) - dtimes = _np.r_[dtimes, dtimes[-1]] + sbvals = mode_vs + mbvals = _np.logical_not(mode_vs) + return sbvals, mbvals - dtimes_users_progmd = dtimes*self._user_shift_progmd_values - dtimes_injection = dtimes*self._inj_shift_values - dtimes_machinestudy = dtimes*self._machinestudy_shift_values - dtimes_commissioning = dtimes*self._commissioning_shift_values - dtimes_conditioning = dtimes*self._conditioning_shift_values - dtimes_maintenance = dtimes*self._maintenance_shift_values - - # failures - self._raw_data['Failures'] = dict() - self._raw_data['Failures']['SubsystemsNOk'] = _np.logical_or( - self._ps_fail_values, self._mps_fail_values) - self._raw_data['Failures']['GammaShutter'] = \ - self._gamblk_fail_values.astype(int) - self._raw_data['Failures']['NoEBeam'] = \ - _np.logical_not(self._is_stored_users) + def _get_subsystems_status_data(self): + # ps status data + psfail_all = [0] * len(self._curr_times) + for psnames in self._psgroup2psname.values(): + for psn in psnames: + psfail_times, psfail_values = \ + self._get_pv_data(psn+':DiagStatus-Mon') + psfail_values = _np.bitwise_and( # disregard alarms + psfail_values.astype(int), 0b1101111) - # # # ignore wrong shift failures shorter than 60s - wrong_shift = \ - 1 * ((self._user_shift_progmd_values-self._user_shift_values) > 0) - ignore_wrong_shift = _np.zeros(wrong_shift.shape) - for i, val in enumerate(wrong_shift): - if i >= len(wrong_shift)-12: - break - if val == 1 and not _np.sum(wrong_shift[(i-12):(i+12)]) >= 12: - ignore_wrong_shift[i] = 1 - consider_wrong_shift = wrong_shift - ignore_wrong_shift - self._raw_data['Failures']['WrongShift'] = consider_wrong_shift + psfail = 1 * (_interp1d_previous( + psfail_times, psfail_values, self._curr_times) > 0) - self._failures_users = 1 * _np.logical_or.reduce( - [value for value in self._raw_data['Failures'].values()]) * \ - self._user_shift_progmd_values - dtimes_failures_users = dtimes*self._failures_users + psfail_all = _np.logical_or(psfail_all, psfail) + ps_fail_vals = 1 * psfail_all - self._user_shift_delivd_values = self._user_shift_progmd_values * \ - _np.logical_not(self._failures_users) - self._raw_data['UserShiftDelivd'] = self._user_shift_delivd_values - dtimes_users_delivd = dtimes*self._user_shift_delivd_values + # rf and mps status data + siintlk_times, siintlk_values = self._get_pv_data(self._siintlk_pv) + mps_fail_vals = _interp1d_previous( + siintlk_times, siintlk_values, self._curr_times) - # distortions - self._raw_data['Distortions'] = dict() - self._raw_data['Distortions']['SOFBLoop'] = self._sofbloop_fail_values + return ps_fail_vals, mps_fail_vals - self._distortions_users = 1 * _np.logical_or.reduce( - [value for value in self._raw_data['Distortions'].values()]) * \ - self._user_shift_delivd_values - dtimes_distortions_users = dtimes*self._distortions_users + def _get_gammashutter_data(self): + gamma_times, gamma_values = self._get_pv_data(self._gammashutt_pv) + gamma_fail_vals = _interp1d_previous( + gamma_times, gamma_values, self._curr_times) + return gamma_fail_vals - self._user_shift_stable_values = self._user_shift_delivd_values * \ - _np.logical_not(self._distortions_users) - self._raw_data['UserShiftStable'] = self._user_shift_stable_values - dtimes_users_stable = dtimes*self._user_shift_stable_values - - # user total and extra shift - self._user_shift_act_values = \ - self._user_shift_values*_np.logical_not(self._failures_users) - self._raw_data['UserShiftTotal'] = self._user_shift_act_values - dtimes_users_total = dtimes*self._user_shift_act_values - dtimes_users_extra = dtimes_users_total*_np.logical_not( - self._user_shift_progmd_values) + def _get_storedebeam_data(self): + is_stored_total = self._curr_values > MacReport.THOLD_STOREDBEAM + is_stored_users = self._curr_values >= \ + self._users_shift_inicurr_values*MacReport.THOLD_FACTOR_USERSSBEAM + return is_stored_total, is_stored_users - # calculate stats + def _get_delivered_shift_data(self): + # delivered shift data + shift_times, shift_values = self._get_pv_data(self._macshift_pv) + shifts_data = list() + for shift in MacReport.SHIFTS: + sid = getattr(_Cte.MachShift, shift) + value = _np.array([1*(v == sid) for v in shift_values]) + value = _interp1d_previous(shift_times, value, self._curr_times) + shifts_data.append(value) + return shifts_data + + def _get_orbcorr_data(self): + # sofb + sofb_times, sofb_values = self._get_pv_data(self._sisofbloop_pv) + sofb_fail_rawvalues = _np.array( + [1*(v == _SOFBCte.LoopState.Open) for v in sofb_values]) + sofb_fail_values = _interp1d_previous( + sofb_times, sofb_fail_rawvalues, self._curr_times) + + return sofb_fail_values + + def _get_stabinfo_data(self): + # stability indicators + bbbdata = dict() + for axis in ['h', 'v', 'l']: + pvname = getattr(self, '_sibbb'+axis+'stab_pv') + times, values = self._get_pv_data(pvname) + rawvalues = _np.array( + [1*(v == _StabCte.StabUnstab.Unstable) for v in values]) + failvalues = _interp1d_previous( + times, rawvalues, self._curr_times) + bbbdata[axis] = failvalues + return bbbdata + + def _calc_beam_for_users_stats(self): # # beam for users stats + # auxiliary time vectors + dtimes = _np.diff(self._curr_times) + dtimes = _np.r_[dtimes, dtimes[-1]] + # # # ----- users shift ----- + dtimes_users_progmd = dtimes*self._users_shift_progmd_values self._usershift_progmd_time = _np.sum(dtimes_users_progmd) - self._usershift_delivd_time = _np.sum(dtimes_users_delivd) + self._failures_users = 1 * _np.logical_or.reduce( + [value for value in self._raw_data['Failures'].values()]) * \ + self._users_shift_progmd_values + dtimes_failures_users = dtimes*self._failures_users + self._usershift_total_failures_time = _np.sum(dtimes_failures_users) - self._usershift_extra_time = _np.sum(dtimes_users_extra) + self._users_shift_delivd_values = self._users_shift_progmd_values * \ + _np.logical_not(self._failures_users) + self._raw_data['UserShiftDelivd'] = self._users_shift_delivd_values + dtimes_users_delivd = dtimes*self._users_shift_delivd_values + self._usershift_delivd_time = _np.sum(dtimes_users_delivd) + self._users_shift_act_values = \ + self._users_shift_values*_np.logical_not(self._failures_users) + self._raw_data['UserShiftTotal'] = self._users_shift_act_values + dtimes_users_total = dtimes*self._users_shift_act_values self._usershift_total_time = _np.sum(dtimes_users_total) - self._usershift_current_average, self._usershift_current_stddev = \ - self._calc_current_stats(dtimes_users_total) + dtimes_users_extra = dtimes_users_total*_np.logical_not( + self._users_shift_progmd_values) + self._usershift_extra_time = _np.sum(dtimes_users_extra) - transit = _np.diff(self._user_shift_delivd_values) + ave, std = self._calc_current_stats(dtimes_users_total) + self._usershift_current_average = ave + self._usershift_current_stddev = std + + # # # ----- current stats at the beggining and at the end ----- + transit = _np.diff(self._users_shift_delivd_values) beg_idcs = _np.where(transit == 1)[0] end_idcs = _np.where(transit == -1)[0] @@ -1485,7 +1505,7 @@ def _compute_stats(self): beg_idcs[i+1]-beg_idcs[i] > 15] beg_val += [beg_idcs.size-1] beg1, beg2 = beg_idcs[beg_val], beg_idcs[beg_val] + 15 - if beg2[-1] > self._user_shift_delivd_values.size-1: + if beg2[-1] > self._users_shift_delivd_values.size-1: beg1.pop() beg2.pop() beg_val = [i for i in range(beg1.size) if not @@ -1518,8 +1538,6 @@ def _compute_stats(self): self._usershift_current_end_stddev = 0 # # # ----- failures ----- - self._usershift_total_failures_time = _np.sum(dtimes_failures_users) - beam_dump_values = _np.logical_not( self._raw_data['Failures']['WrongShift']) * \ self._raw_data['Failures']['NoEBeam'] @@ -1537,6 +1555,15 @@ def _compute_stats(self): else self._usershift_progmd_time/self._usershift_failures_count # # # ----- distortions ----- + self._distortions_users = 1 * _np.logical_or.reduce( + [value for value in self._raw_data['Distortions'].values()]) * \ + self._users_shift_delivd_values + dtimes_distortions_users = dtimes*self._distortions_users + + self._users_shift_stable_values = self._users_shift_delivd_values * \ + _np.logical_not(self._distortions_users) + self._raw_data['UserShiftStable'] = self._users_shift_stable_values + dtimes_users_stable = dtimes*self._users_shift_stable_values self._usershift_total_unstable_beam_time = _np.sum( dtimes_distortions_users) @@ -1560,15 +1587,24 @@ def _compute_stats(self): self._usershift_delivd_time/self._usershift_progmd_time # # # ----- injection shift ----- + dtimes_injection = dtimes*self._injection_shift_values self._usershift_total_injection_time = _np.sum(dtimes_injection) ave, std, count = self._calc_interval_stats( - self._inj_shift_values, dtimes_injection) + self._injection_shift_values, dtimes_injection) self._usershift_injection_time_average = ave self._usershift_injection_time_stddev = std self._usershift_injection_count = count - # # light source usage stats + def _calc_light_source_usage_stats(self): + # light source usage stats + dtimes = _np.diff(self._curr_times) + dtimes = _np.r_[dtimes, dtimes[-1]] + dtimes_machinestudy = dtimes*self._machinestudy_shift_values + dtimes_commissioning = dtimes*self._commissioning_shift_values + dtimes_conditioning = dtimes*self._conditioning_shift_values + dtimes_maintenance = dtimes*self._maintenance_shift_values + self._lsusage_machinestudy_time = _np.sum(dtimes_machinestudy) self._lsusage_commissioning_time = _np.sum(dtimes_commissioning) @@ -1577,7 +1613,7 @@ def _compute_stats(self): self._lsusage_maintenance_time = _np.sum(dtimes_maintenance) - self._lsusage_user_time = self._usershift_progmd_time + \ + self._lsusage_users_time = self._usershift_progmd_time + \ self._usershift_extra_time self._lsusage_total_time = \ @@ -1585,7 +1621,7 @@ def _compute_stats(self): self._lsusage_commissioning_time + \ self._lsusage_conditioning_time + \ self._lsusage_maintenance_time + \ - self._lsusage_user_time + self._lsusage_users_time self._lsusage_machinestudy_failures_time = _np.sum( dtimes_machinestudy*self._raw_data['Failures']['SubsystemsNOk']) @@ -1599,11 +1635,11 @@ def _compute_stats(self): self._lsusage_maintenance_failures_time = 0.0 dtimes_failures_users_oper = dtimes*self._failures_users - self._lsusage_user_failures_time = _np.sum( + self._lsusage_users_failures_time = _np.sum( dtimes_failures_users_oper) for usage in ['machinestudy', 'commissioning', 'conditioning', - 'maintenance', 'user']: + 'maintenance', 'users']: fail_intvl = getattr(self, '_lsusage_'+usage+'_failures_time') total_intvl = getattr(self, '_lsusage_'+usage+'_time') oper_intvl = total_intvl - fail_intvl @@ -1621,9 +1657,12 @@ def _compute_stats(self): setattr(self, '_lsusage_'+usage, 100*total_intvl/self._lsusage_total_time) - # # stored current stats + def _calc_stored_current_stats(self): + # stored current stats + dtimes = _np.diff(self._curr_times) + dtimes = _np.r_[dtimes, dtimes[-1]] for shifttype in ['machinestudy', 'commissioning', 'conditioning', - 'user', 'ebeam']: + 'users', 'ebeam']: for fillmode in ['singlebunch', 'multibunch', 'total']: select = self._is_stored_total @@ -1759,12 +1798,12 @@ def __str__(self): ['lsusage_maintenance_operational', '%'], ['lsusage_maintenance_time', 'h'], ['lsusage_maintenance', '%'], - ['lsusage_user_failures_time', 'h'], - ['lsusage_user_failures', '%'], - ['lsusage_user_operational_time', 'h'], - ['lsusage_user_operational', '%'], - ['lsusage_user_time', 'h'], - ['lsusage_user', '%'], + ['lsusage_users_failures_time', 'h'], + ['lsusage_users_failures', '%'], + ['lsusage_users_operational_time', 'h'], + ['lsusage_users_operational', '%'], + ['lsusage_users_time', 'h'], + ['lsusage_users', '%'], ] ppties_storedcurrent = [ ['current_machinestudy_singlebunch_average', 'mA'], @@ -1794,15 +1833,15 @@ def __str__(self): ['current_conditioning_total_average', 'mA'], ['current_conditioning_total_stddev', 'mA'], ['current_conditioning_total_time', 'h'], - ['current_user_singlebunch_average', 'mA'], - ['current_user_singlebunch_stddev', 'mA'], - ['current_user_singlebunch_time', 'h'], - ['current_user_multibunch_average', 'mA'], - ['current_user_multibunch_stddev', 'mA'], - ['current_user_multibunch_time', 'h'], - ['current_user_total_average', 'mA'], - ['current_user_total_stddev', 'mA'], - ['current_user_total_time', 'h'], + ['current_users_singlebunch_average', 'mA'], + ['current_users_singlebunch_stddev', 'mA'], + ['current_users_singlebunch_time', 'h'], + ['current_users_multibunch_average', 'mA'], + ['current_users_multibunch_stddev', 'mA'], + ['current_users_multibunch_time', 'h'], + ['current_users_total_average', 'mA'], + ['current_users_total_stddev', 'mA'], + ['current_users_total_time', 'h'], ['current_ebeam_singlebunch_average', 'mA'], ['current_ebeam_singlebunch_stddev', 'mA'], ['current_ebeam_singlebunch_time', 'h'], From 9948f09bfefed174d6da8c4700fa9fb56960d2d0 Mon Sep 17 00:00:00 2001 From: Ana Clara Oliveira Date: Fri, 24 Feb 2023 18:08:24 -0300 Subject: [PATCH 02/19] macreport.ENH: include FOFB loop state and BbB instability indicators in distortion stats --- siriuspy/siriuspy/machshift/macreport.py | 92 +++++++++++++++++++----- 1 file changed, 74 insertions(+), 18 deletions(-) diff --git a/siriuspy/siriuspy/machshift/macreport.py b/siriuspy/siriuspy/machshift/macreport.py index ba1620329..8851a8d5e 100644 --- a/siriuspy/siriuspy/machshift/macreport.py +++ b/siriuspy/siriuspy/machshift/macreport.py @@ -11,6 +11,8 @@ from ..clientarch import ClientArchiver as _CltArch, Time as _Time, \ PVData as _PVData, PVDataSet as _PVDataSet from ..sofb.csdev import ConstTLines as _SOFBCte +from ..fofb.csdev import HLFOFBConst as _FOFBCte +from ..stabinfo.csdev import StabInfoConst as _StabCte from .csdev import Const as _Cte from .macschedule import MacScheduleData as _MacScheduleData from .utils import interp1d_previous as _interp1d_previous @@ -1073,7 +1075,7 @@ def plot_raw_data(self): datetimes = _np.array([_Time(t) for t in self._raw_data['Timestamp']]) - fig, axs = _plt.subplots(14, 1, sharex=True) + fig, axs = _plt.subplots(16, 1, sharex=True) fig.set_size_inches(9, 10) fig.subplots_adjust(top=0.96, left=0.08, bottom=0.05, right=0.96) axs[0].set_title('Raw data', fontsize=12) @@ -1157,11 +1159,34 @@ def plot_raw_data(self): axs[11].xaxis.axis_date() axs[11].plot( - datetimes, self._raw_data['Shift']['Injection'], '-', - color='lightsalmon', label='Injection Shifts') + datetimes, self._raw_data['Distortions']['FOFBLoop'], '-', + color='orangered', label='Distortions - FOFB Loop Open') axs[11].legend(loc='upper left', fontsize=9) axs[11].grid() + axs[12].xaxis.axis_date() + axs[12].plot( + datetimes[0], 0, '.', color='white', + label='Distortions - BbB Instabilities:') + axs[12].plot( + datetimes, self._raw_data['Distortions']['BbBHStab'], '-', + color='blue', label='H') + axs[12].plot( + datetimes, self._raw_data['Distortions']['BbBVStab'], '-', + color='red', label='V') + axs[12].plot( + datetimes, self._raw_data['Distortions']['BbBLStab'], '-', + color='green', label='L') + axs[12].legend(loc='upper left', fontsize=9, ncol=4) + axs[12].grid() + + axs[13].xaxis.axis_date() + axs[13].plot( + datetimes, self._raw_data['Shift']['Injection'], '-', + color='lightsalmon', label='Injection Shifts') + axs[13].legend(loc='upper left', fontsize=9) + axs[13].grid() + shift2color = { 'MachineStudy': ['MacStudy', 'skyblue'], 'Commissioning': ['Commi', 'royalblue'], @@ -1170,26 +1195,26 @@ def plot_raw_data(self): for shift, auxdata in shift2color.items(): ydata = self._raw_data['Shift'][shift] - axs[12].xaxis.axis_date() - axs[12].plot( + axs[14].xaxis.axis_date() + axs[14].plot( datetimes, ydata, '-', color=auxdata[1], label=auxdata[0]) - axs[12].legend(loc='upper left', ncol=4, fontsize=9) - axs[12].set_ylim(0.0, 2.0) - axs[12].grid() + axs[14].legend(loc='upper left', ncol=4, fontsize=9) + axs[14].set_ylim(0.0, 2.0) + axs[14].grid() egmodes2color = { 'MultiBunch': 'orangered', 'SingleBunch': 'orange'} for egmode, color in egmodes2color.items(): ydata = self._raw_data['EgunModes'][egmode] - axs[13].xaxis.axis_date() - axs[13].plot( + axs[15].xaxis.axis_date() + axs[15].plot( datetimes, ydata, '-', color=color, label=egmode) - axs[13].legend(loc='upper left', ncol=2, fontsize=9) - axs[13].set_ylim(0.0, 2.0) - axs[13].grid() + axs[15].legend(loc='upper left', ncol=2, fontsize=9) + axs[15].set_ylim(0.0, 2.0) + axs[15].grid() return fig @@ -1232,18 +1257,31 @@ def _init_connectors(self): self._gammashutt_pv = 'AS-Glob:PP-GammaShutter:Status-Mon' self._siintlk_pv = 'RA-RaSIA02:RF-IntlkCtrl:IntlkSirius-Mon' self._sisofbloop_pv = 'SI-Glob:AP-SOFB:LoopState-Sts' + self._sifofbloop_pv = 'SI-Glob:AP-FOFB:LoopState-Sts' + self._sibbbhstab_pv = 'SI-Glob:AP-StabilityInfo:BbBHStatus-Mon' + self._sibbbvstab_pv = 'SI-Glob:AP-StabilityInfo:BbBVStatus-Mon' + self._sibbblstab_pv = 'SI-Glob:AP-StabilityInfo:BbBLStatus-Mon' self._pvnames = [ self._current_pv, self._macshift_pv, self._egtrgen_pv, self._egpusel_pv, self._injevt_pv, self._gammashutt_pv, self._siintlk_pv, - self._sisofbloop_pv] + self._sisofbloop_pv, self._sifofbloop_pv, + self._sibbbhstab_pv, self._sibbbvstab_pv, self._sibbblstab_pv] self._pvdata = dict() self._pv2default = dict() + self._pv2tstart = dict() for pvname in self._pvnames: self._pvdata[pvname] = _PVData(pvname, self._connector) - self._pv2default[pvname] = 0.0 if pvname != self._macshift_pv\ - else _Cte.MachShift.Commissioning + defval = _FOFBCte.LoopState.Closed if 'FOFB' in pvname else \ + _SOFBCte.LoopState.Closed if 'SOFB' in pvname else \ + _Cte.MachShift.Commissioning if pvname == self._macshift_pv \ + else _StabCte.StabUnstab.Stable if 'Stability' in pvname \ + else 0.0 + self._pv2default[pvname] = defval + tstart = _Time(2022, 11, 1, 0, 0) if 'FOFB' in pvname \ + else _Time(2021, 1, 1, 0, 0) + self._pv2tstart[pvname] = tstart self._si_fams_psnames = _PSSearch.get_psnames( {'sec': 'SI', 'sub': 'Fam', 'dev': '(B|Q|S).*'}) @@ -1267,6 +1305,7 @@ def _init_connectors(self): for pvn in pvnames: self._pvdata[pvn] = self._pvdataset[group][pvn] self._pv2default[pvn] = 0.0 + self._pv2tstart[pvn] = _Time(2021, 1, 1, 0, 0) def _compute_stats(self): # will populate the following dict @@ -1333,8 +1372,15 @@ def _compute_stats(self): # get pvs data and calculate distortions # - correction loops self._raw_data['Distortions'] = dict() - sofbfail = self._get_orbcorr_data() + sofbfail, fofbfail = self._get_orbcorr_data() self._raw_data['Distortions']['SOFBLoop'] = sofbfail + self._raw_data['Distortions']['FOFBLoop'] = fofbfail + + # - stability indicators + bbbfaildata = self._get_stabinfo_data() + self._raw_data['Distortions']['BbBHStab'] = bbbfaildata['h'] + self._raw_data['Distortions']['BbBVStab'] = bbbfaildata['v'] + self._raw_data['Distortions']['BbBLStab'] = bbbfaildata['l'] # calculate statistics self._calc_beam_for_users_stats() @@ -1444,7 +1490,14 @@ def _get_orbcorr_data(self): sofb_fail_values = _interp1d_previous( sofb_times, sofb_fail_rawvalues, self._curr_times) - return sofb_fail_values + # fofb + fofb_times, fofb_values = self._get_pv_data(self._sifofbloop_pv) + fofb_fail_rawvalues = _np.array( + [1*(v == _FOFBCte.LoopState.Open) for v in fofb_values]) + fofb_fail_values = _interp1d_previous( + fofb_times, fofb_fail_rawvalues, self._curr_times) + + return sofb_fail_values, fofb_fail_values def _get_stabinfo_data(self): # stability indicators @@ -1687,6 +1740,7 @@ def _get_pv_data(self, pvname): t_start = self._time_start.timestamp() data = self._pvdata[pvname] defv = self._pv2default[pvname] + tstr = self._pv2tstart[pvname] if data.timestamp is None: times = _np.array([t_start, ]) values = _np.array([defv, ]) @@ -1696,6 +1750,8 @@ def _get_pv_data(self, pvname): if times[0] > t_start + MacReport.QUERY_AVG_TIME: times = _np.r_[t_start, times] values = _np.r_[defv, values] + idcsdefv = _np.where(times <= tstr.timestamp())[0] + values[idcsdefv] = defv return times, values def _calc_current_stats(self, dtimes): From 62b6d7b6f96d4f0db8f577223af666480ea12502 Mon Sep 17 00:00:00 2001 From: Ana Clara Oliveira Date: Fri, 24 Feb 2023 18:08:50 -0300 Subject: [PATCH 03/19] Update version to 2.68.0 --- siriuspy/siriuspy/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/VERSION b/siriuspy/siriuspy/VERSION index 9db2e998b..0f1ddc810 100644 --- a/siriuspy/siriuspy/VERSION +++ b/siriuspy/siriuspy/VERSION @@ -1 +1 @@ -2.67.1 +2.68.0 From 7755392d8df225051d4b471a37af4fdd802a8ed0 Mon Sep 17 00:00:00 2001 From: Fernando Date: Sat, 25 Feb 2023 09:50:57 -0300 Subject: [PATCH 04/19] DEV.TIM.BUG: Fix setter of EVG.nrpulses. --- siriuspy/siriuspy/devices/timing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/devices/timing.py b/siriuspy/siriuspy/devices/timing.py index 04073acf4..e0caf9f43 100644 --- a/siriuspy/siriuspy/devices/timing.py +++ b/siriuspy/siriuspy/devices/timing.py @@ -42,7 +42,7 @@ def nrpulses(self): @nrpulses.setter def nrpulses(self, value): """Set number of pulses to repeat Bucket List.""" - self['RepeatBucketList-SP'] = bool(value) + self['RepeatBucketList-SP'] = value @property def bucketlist_len(self): From 3142e489b20c98e54cfadc1db2baf4418f5e4b70 Mon Sep 17 00:00:00 2001 From: Fernando Date: Mon, 27 Feb 2023 08:18:11 -0300 Subject: [PATCH 05/19] DEV.PS.ENH: Add method to set strength and wait for mon PV. --- siriuspy/siriuspy/devices/pwrsupply.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/siriuspy/siriuspy/devices/pwrsupply.py b/siriuspy/siriuspy/devices/pwrsupply.py index a0c85fa5a..17c0e345d 100644 --- a/siriuspy/siriuspy/devices/pwrsupply.py +++ b/siriuspy/siriuspy/devices/pwrsupply.py @@ -203,6 +203,13 @@ def pwrstate(self, value): """.""" self['PwrState-Sel'] = value + def set_strength(self, value, tol=0.2, timeout=10, wait_mon=False): + """Set RF phase and wait until it gets there.""" + self.strength = value + pv2wait = self._strength_rb_propty if wait_mon \ + else self._strength_rb_propty + return self._wait_float(pv2wait, value, abs_tol=tol, timeout=timeout) + def cmd_turn_on(self, timeout=_default_timeout): """.""" self.pwrstate = self.PWRSTATE.On From 435a2178f345edafc5109e4e52a8a5e26e65dd28 Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 28 Feb 2023 10:26:13 -0300 Subject: [PATCH 06/19] DEV.BPM: remove auto monitor from FamBPMs class. --- siriuspy/siriuspy/devices/bpm.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/siriuspy/siriuspy/devices/bpm.py b/siriuspy/siriuspy/devices/bpm.py index b414afcb0..f817c6c06 100644 --- a/siriuspy/siriuspy/devices/bpm.py +++ b/siriuspy/siriuspy/devices/bpm.py @@ -826,15 +826,6 @@ def __init__(self, devname=None): super().__init__(devname, devs) self._bpm_names = bpm_names self._csbpm = devs[0].csdata - propties_to_keep = ['GEN_XArrayData', 'GEN_YArrayData'] - - self._mturn_flags = dict() - for bpm in devs: - for propty in propties_to_keep: - bpm.set_auto_monitor(propty, True) - pvo = bpm.pv_object(propty) - self._mturn_flags[pvo.pvname] = _Flag() - pvo.add_callback(self._mturn_set_flag) @property def bpm_names(self): @@ -1044,11 +1035,6 @@ def set_switching_mode(self, mode='direct'): for bpm in self._devices: bpm.switching_mode = mode - def mturn_reset_flags(self): - """Reset Multiturn flags to wait for a new orbit update.""" - for flag in self._mturn_flags.values(): - flag.clear() - def mturn_wait_update_flags(self, timeout=10) -> int: """Wait Multiturn orbit update. @@ -1064,13 +1050,6 @@ def mturn_wait_update_flags(self, timeout=10) -> int: """ orbx0, orby0 = self.get_mturn_orbit() - for i, flag in enumerate(self._mturn_flags.values()): - t00 = _time.time() - if not flag.wait(timeout=timeout): - return (i // 2) + 1 - timeout -= _time.time() - t00 - timeout = max(timeout, 0) - while timeout > 0: t00 = _time.time() orbx, orby = self.get_mturn_orbit() @@ -1103,10 +1082,6 @@ def mturn_wait_update_flags(self, timeout=10) -> int: return int(erry.nonzero()[0][0])+1 return False - def _mturn_set_flag(self, pvname, **kwargs): - _ = kwargs - self._mturn_flags[pvname].set() - class BPMLogicalTrigger(_ProptyDevice): """BPM Logical Trigger device.""" From 2f56f1bd81d4203d6ffb6896694602caf531c103 Mon Sep 17 00:00:00 2001 From: Ana Clara Oliveira Date: Tue, 22 Mar 2022 19:06:07 -0300 Subject: [PATCH 07/19] DEVORBINTLK.MNT: update convertion factor --- siriuspy/siriuspy/devices/orbit_interlock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/devices/orbit_interlock.py b/siriuspy/siriuspy/devices/orbit_interlock.py index 1ca41a274..5fc9449f9 100644 --- a/siriuspy/siriuspy/devices/orbit_interlock.py +++ b/siriuspy/siriuspy/devices/orbit_interlock.py @@ -654,7 +654,7 @@ class OrbitInterlock(BaseOrbitIntlk, _Devices): 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]) + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])*2**21 _bv = _np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, From 265b39a766ba9bd9e625488718b33de0e7198c01 Mon Sep 17 00:00:00 2001 From: Ana Clara Oliveira Date: Tue, 5 Apr 2022 15:22:54 -0300 Subject: [PATCH 08/19] DEVORBINTLK.API: rename PVs and properties and remove "Any" PVs --- siriuspy/siriuspy/devices/orbit_interlock.py | 544 ++++++++----------- 1 file changed, 234 insertions(+), 310 deletions(-) diff --git a/siriuspy/siriuspy/devices/orbit_interlock.py b/siriuspy/siriuspy/devices/orbit_interlock.py index 5fc9449f9..dc4dbee9a 100644 --- a/siriuspy/siriuspy/devices/orbit_interlock.py +++ b/siriuspy/siriuspy/devices/orbit_interlock.py @@ -99,12 +99,12 @@ def get_down_up_bpms(bpmname): return down, upn def calc_intlk_metric(self, posarray, operation='', metric=''): - """Return interlock metric, translation or angulation.""" + """Return interlock metric, position or angulation.""" if not operation: if not metric: raise ValueError( 'either the operation or the metric is required') - operation = 'mean' if 'trans' in metric.lower() else 'diff' + operation = 'mean' if 'pos' in metric.lower() else 'diff' data_values = list() for bpm in BaseOrbitIntlk.BPM_NAMES: @@ -138,7 +138,7 @@ class BPMOrbitIntlk(BaseOrbitIntlk, _Device): # General interlock enable: 'IntlkEn-Sel', 'IntlkEn-Sts', # General interlock clear: - 'IntlkClr-Sel', # maybe -Cmd? + 'IntlkClr-Cmd', # maybe -Cmd? # Minimum sum threshold enable: # Habilita interlock de órbita apenas quando threshold da soma # ultrapassar o valor em "IntlkLmtMinSum-SP" @@ -153,10 +153,10 @@ class BPMOrbitIntlk(BaseOrbitIntlk, _Device): # correspondente 'IntlkLtc-Mon', # =============================================================== - # Translation (interlock de translação) + # Position (interlock de posição) # +++++++++++++++++++++++++++++++++++++ # *************************************************************** - # Condição para interlock de translação: + # Condição para interlock de posição: # thres_min > (pos BPM downstream + pos BPM upstream)/2 or # thres_max < (pos BPM downstream + pos BPM upstream)/2 # BPMs são agrupados 2 a 2 seguindo a ordem do feixe: @@ -167,26 +167,24 @@ class BPMOrbitIntlk(BaseOrbitIntlk, _Device): # BPM upstream é sempre o "primeiro" BPM da dupla acima e BPM # downstream é sempre o "segundo" BPM da dupla. # *************************************************************** - # Translation interlock enable: - 'IntlkTransEn-Sel', 'IntlkTransEn-Sts', - # Translation interlock clear: - 'IntlkTransClr-Sel', + # Position interlock enable: + 'IntlkPosEn-Sel', 'IntlkPosEn-Sts', + # Position interlock clear: + 'IntlkPosClr-Cmd', # Thresholds (em nm da taxa Monit1): - 'IntlkLmtTransMaxX-SP', 'IntlkLmtTransMaxX-RB', - 'IntlkLmtTransMinX-SP', 'IntlkLmtTransMinX-RB', - 'IntlkLmtTransMaxY-SP', 'IntlkLmtTransMaxY-RB', - 'IntlkLmtTransMinY-SP', 'IntlkLmtTransMinY-RB', + 'IntlkLmtPosMaxX-SP', 'IntlkLmtPosMaxX-RB', + 'IntlkLmtPosMinX-SP', 'IntlkLmtPosMinX-RB', + 'IntlkLmtPosMaxY-SP', 'IntlkLmtPosMaxY-RB', + 'IntlkLmtPosMinY-SP', 'IntlkLmtPosMinY-RB', + # Todos os interlocks são mascarados pelo "Enable" # Status Instantâneo: - # XouY mascarado pelo "Enable" - 'IntlkTransSmaller-Mon', 'IntlkTransBigger-Mon', - # the ones bellow are not masked by "Enable" - 'IntlkTransSmallerAny-Mon', 'IntlkTransBiggerAny-Mon', # X ou Y - 'IntlkTransSmallerX-Mon', 'IntlkTransBiggerX-Mon', # X - 'IntlkTransSmallerY-Mon', 'IntlkTransBiggerY-Mon', # Y - # limpo apenas acionando-se a PV "Clr" correspondente - 'IntlkTransSmallerLtc-Mon', 'IntlkTransBiggerLtc-Mon', - 'IntlkTransSmallerLtcX-Mon', 'IntlkTransBiggerLtcX-Mon', - 'IntlkTransSmallerLtcY-Mon', 'IntlkTransBiggerLtcY-Mon', + 'IntlkPosLower-Mon', 'IntlkPosUpper-Mon', # X ou Y + 'IntlkPosLowerX-Mon', 'IntlkPosUpperX-Mon', # X + 'IntlkPosLowerY-Mon', 'IntlkPosUpperY-Mon', # Y + # Status Latch, limpo apenas acionando-se a PV "Clr" correspondente: + 'IntlkPosLowerLtc-Mon', 'IntlkPosUpperLtc-Mon', + 'IntlkPosLowerLtcX-Mon', 'IntlkPosUpperLtcX-Mon', + 'IntlkPosLowerLtcY-Mon', 'IntlkPosUpperLtcY-Mon', # ============================================================= # Angular (interlock de ângulo) # +++++++++++++++++++++++++++++ @@ -205,7 +203,7 @@ class BPMOrbitIntlk(BaseOrbitIntlk, _Device): # Angulation interlock enable: 'IntlkAngEn-Sel', 'IntlkAngEn-Sts', # Angulation interlock clear: - 'IntlkAngClr-Sel', + 'IntlkAngClr-Cmd', # Thresholds (em rad.nm da taxa Monit1). # Thresholds devem ser calculados como ângulo (em rad) # entre os 2 BPMs adjacentes * distância (em nm) entre eles): @@ -213,17 +211,15 @@ class BPMOrbitIntlk(BaseOrbitIntlk, _Device): 'IntlkLmtAngMinX-SP', 'IntlkLmtAngMinX-RB', 'IntlkLmtAngMaxY-SP', 'IntlkLmtAngMaxY-RB', 'IntlkLmtAngMinY-SP', 'IntlkLmtAngMinY-RB', + # Todos os interlocks são mascarados pelo "Enable" # Status Instantâneo: - # X ou Y mascarado pelo "Enable" - 'IntlkAngSmaller-Mon', 'IntlkAngBigger-Mon', - # the ones bellow are not masked by "Enable" - 'IntlkAngSmallerAny-Mon', 'IntlkAngBiggerAny-Mon', # X ou Y - 'IntlkAngSmallerX-Mon', 'IntlkAngBiggerX-Mon', # X - 'IntlkAngSmallerY-Mon', 'IntlkAngBiggerY-Mon', # Y - # limpo apenas acionando-se a PV "Clr" correspondente - 'IntlkAngSmallerLtc-Mon', 'IntlkAngBiggerLtc-Mon', - 'IntlkAngSmallerLtcX-Mon', 'IntlkAngBiggerLtcX-Mon', - 'IntlkAngSmallerLtcY-Mon', 'IntlkAngBiggerLtcY-Mon', + 'IntlkAngLower-Mon', 'IntlkAngUpper-Mon', + 'IntlkAngLowerX-Mon', 'IntlkAngUpperX-Mon', # X + 'IntlkAngLowerY-Mon', 'IntlkAngUpperY-Mon', # Y + # Status Latch, limpo apenas acionando-se a PV "Clr" correspondente: + 'IntlkAngLowerLtc-Mon', 'IntlkAngUpperLtc-Mon', + 'IntlkAngLowerLtcX-Mon', 'IntlkAngUpperLtcX-Mon', + 'IntlkAngLowerLtcY-Mon', 'IntlkAngUpperLtcY-Mon', # ============================================================ ) @@ -268,7 +264,7 @@ def gen_enable(self, value): def cmd_reset_gen(self): """General interlock clear.""" - self['IntlkClr-Sel'] = 1 + self['IntlkClr-Cmd'] = 1 return True @property @@ -306,169 +302,153 @@ def minsumthres(self): def minsumthres(self, value): self['IntlkLmtMinSum-SP'] = int(value) - # --- translation interlock --- + # --- position interlock --- @property - def trans_enable(self): - """Translation interlock enable.""" - return self['IntlkTransEn-Sts'] + def pos_enable(self): + """Position interlock enable.""" + return self['IntlkPosEn-Sts'] - @trans_enable.setter - def trans_enable(self, value): - self['IntlkTransEn-Sel'] = int(value) + @pos_enable.setter + def pos_enable(self, value): + self['IntlkPosEn-Sel'] = int(value) - def cmd_reset_trans(self): - """Translation interlock clear.""" - self['IntlkTransClr-Sel'] = 1 + def cmd_reset_pos(self): + """Position interlock clear.""" + self['IntlkPosClr-Cmd'] = 1 return True @property - def trans_thresminx(self): - """Minimum X translation threshold.""" - return self['IntlkLmtTransMinX-RB'] + def pos_thresminx(self): + """Minimum X position threshold.""" + return self['IntlkLmtPosMinX-RB'] - @trans_thresminx.setter - def trans_thresminx(self, value): - self['IntlkLmtTransMinX-SP'] = value + @pos_thresminx.setter + def pos_thresminx(self, value): + self['IntlkLmtPosMinX-SP'] = value @property - def trans_thresmaxx(self): - """Maximum X translation threshold.""" - return self['IntlkLmtTransMaxX-RB'] + def pos_thresmaxx(self): + """Maximum X position threshold.""" + return self['IntlkLmtPosMaxX-RB'] - @trans_thresmaxx.setter - def trans_thresmaxx(self, value): - self['IntlkLmtTransMaxX-SP'] = value + @pos_thresmaxx.setter + def pos_thresmaxx(self, value): + self['IntlkLmtPosMaxX-SP'] = value @property - def trans_thresminy(self): - """Minimum Y translation threshold.""" - return self['IntlkLmtTransMinY-RB'] + def pos_thresminy(self): + """Minimum Y position threshold.""" + return self['IntlkLmtPosMinY-RB'] - @trans_thresminy.setter - def trans_thresminy(self, value): - self['IntlkLmtTransMinY-SP'] = value + @pos_thresminy.setter + def pos_thresminy(self, value): + self['IntlkLmtPosMinY-SP'] = value @property - def trans_thresmaxy(self): - """Maximum Y translation threshold.""" - return self['IntlkLmtTransMaxY-RB'] + def pos_thresmaxy(self): + """Maximum Y position threshold.""" + return self['IntlkLmtPosMaxY-RB'] - @trans_thresmaxy.setter - def trans_thresmaxy(self, value): - self['IntlkLmtTransMaxY-SP'] = value + @pos_thresmaxy.setter + def pos_thresmaxy(self, value): + self['IntlkLmtPosMaxY-SP'] = value @property - def trans_mask_smaller(self): + def pos_inst_lower(self): """ - Instantaneous translation interlock set when either X or Y - minimum thresholds are exceeded, masked by general enable. - """ - return self['IntlkTransSmaller-Mon'] - - @property - def trans_mask_bigger(self): - """ - Instantaneous translation interlock set when either X or Y - maximum thresholds are exceeded, masked by general enable. - """ - return self['IntlkTransBigger-Mon'] - - @property - def trans_inst_smaller(self): - """ - Instantaneous translation interlock set when either X or Y + Instantaneous position interlock set when either X or Y minimum thresholds are exceeded. """ - return self['IntlkTransSmallerAny-Mon'] + return self['IntlkPosLower-Mon'] @property - def trans_inst_bigger(self): + def pos_inst_upper(self): """ - Instantaneous translation interlock set when either X or Y + Instantaneous position interlock set when either X or Y maximum thresholds are exceeded. """ - return self['IntlkTransBiggerAny-Mon'] + return self['IntlkPosUpper-Mon'] @property - def trans_inst_smaller_x(self): + def pos_inst_lower_x(self): """ - Instantaneous translation interlock set when X + Instantaneous position interlock set when X minimum threshold is exceeded. """ - return self['IntlkTransSmallerX-Mon'] + return self['IntlkPosLowerX-Mon'] @property - def trans_inst_bigger_x(self): + def pos_inst_upper_x(self): """ - Instantaneous translation interlock set when X + Instantaneous position interlock set when X maximum threshold is exceeded. """ - return self['IntlkTransBiggerX-Mon'] + return self['IntlkPosUpperX-Mon'] @property - def trans_inst_smaller_y(self): + def pos_inst_lower_y(self): """ - Instantaneous translation interlock set when Y + Instantaneous position interlock set when Y minimum threshold is exceeded. """ - return self['IntlkTransSmallerY-Mon'] + return self['IntlkPosLowerY-Mon'] @property - def trans_inst_bigger_y(self): + def pos_inst_upper_y(self): """ - Instantaneous translation interlock set when Y + Instantaneous position interlock set when Y maximum threshold is exceeded. """ - return self['IntlkTransBiggerY-Mon'] + return self['IntlkPosUpperY-Mon'] @property - def trans_latch_smaller(self): + def pos_latch_lower(self): """ - Latch translation interlock set when either X or Y + Latch position interlock set when either X or Y minimum thresholds are exceeded. """ - return self['IntlkTransSmallerLtc-Mon'] + return self['IntlkPosLowerLtc-Mon'] @property - def trans_latch_bigger(self): + def pos_latch_upper(self): """ - Latch translation interlock set when either X or Y + Latch position interlock set when either X or Y maximum thresholds are exceeded. """ - return self['IntlkTransBiggerLtc-Mon'] + return self['IntlkPosUpperLtc-Mon'] @property - def trans_latch_smaller_x(self): + def pos_latch_lower_x(self): """ - Latch translation interlock set when X + Latch position interlock set when X minimum threshold is exceeded. """ - return self['IntlkTransSmallerLtcX-Mon'] + return self['IntlkPosLowerLtcX-Mon'] @property - def trans_latch_bigger_x(self): + def pos_latch_upper_x(self): """ - Latch translation interlock set when X + Latch position interlock set when X maximum threshold is exceeded. """ - return self['IntlkTransBiggerLtcX-Mon'] + return self['IntlkPosUpperLtcX-Mon'] @property - def trans_latch_smaller_y(self): + def pos_latch_lower_y(self): """ - Latch translation interlock set when Y + Latch position interlock set when Y minimum threshold is exceeded. """ - return self['IntlkTransSmallerLtcY-Mon'] + return self['IntlkPosLowerLtcY-Mon'] @property - def trans_latch_bigger_y(self): + def pos_latch_upper_y(self): """ - Latch translation interlock set when Y + Latch position interlock set when Y maximum threshold is exceeded. """ - return self['IntlkTransBiggerLtcY-Mon'] + return self['IntlkPosUpperLtcY-Mon'] # --- angulation interlock --- @@ -483,7 +463,7 @@ def ang_enable(self, value): def cmd_reset_ang(self): """Angulation interlock clear.""" - self['IntlkAngClr-Sel'] = 1 + self['IntlkAngClr-Cmd'] = 1 return True @property @@ -523,116 +503,100 @@ def ang_thresmaxy(self, value): self['IntlkLmtAngMaxY-SP'] = value @property - def ang_mask_smaller(self): - """ - Instantaneous angulation interlock set when either X or Y - minimum thresholds are exceeded, masked by general enable. - """ - return self['IntlkAngSmaller-Mon'] - - @property - def ang_mask_bigger(self): - """ - Instantaneous angulation interlock set when either X or Y - maximum thresholds are exceeded, masked by general enable. - """ - return self['IntlkAngBigger-Mon'] - - @property - def ang_inst_smaller(self): + def ang_inst_lower(self): """ Instantaneous angulation interlock set when either X or Y minimum thresholds are exceeded. """ - return self['IntlkAngSmallerAny-Mon'] + return self['IntlkAngLower-Mon'] @property - def ang_inst_bigger(self): + def ang_inst_upper(self): """ Instantaneous angulation interlock set when either X or Y maximum thresholds are exceeded. """ - return self['IntlkAngBiggerAny-Mon'] + return self['IntlkAngUpper-Mon'] @property - def ang_inst_smaller_x(self): + def ang_inst_lower_x(self): """ Instantaneous angulation interlock set when X minimum threshold is exceeded. """ - return self['IntlkAngSmallerX-Mon'] + return self['IntlkAngLowerX-Mon'] @property - def ang_inst_bigger_x(self): + def ang_inst_upper_x(self): """ Instantaneous angulation interlock set when X maximum threshold is exceeded. """ - return self['IntlkAngBiggerX-Mon'] + return self['IntlkAngUpperX-Mon'] @property - def ang_inst_smaller_y(self): + def ang_inst_lower_y(self): """ Instantaneous angulation interlock set when Y minimum threshold is exceeded. """ - return self['IntlkAngSmallerY-Mon'] + return self['IntlkAngLowerY-Mon'] @property - def ang_inst_bigger_y(self): + def ang_inst_upper_y(self): """ Instantaneous angulation interlock set when Y maximum threshold is exceeded. """ - return self['IntlkAngBiggerY-Mon'] + return self['IntlkAngUpperY-Mon'] @property - def ang_latch_smaller(self): + def ang_latch_lower(self): """ Latch angulation interlock set when either X or Y minimum thresholds are exceeded. """ - return self['IntlkAngSmallerLtc-Mon'] + return self['IntlkAngLowerLtc-Mon'] @property - def ang_latch_bigger(self): + def ang_latch_upper(self): """ Latch angulation interlock set when either X or Y maximum thresholds are exceeded. """ - return self['IntlkAngBiggerLtc-Mon'] + return self['IntlkAngUpperLtc-Mon'] @property - def ang_latch_smaller_x(self): + def ang_latch_lower_x(self): """ Latch angulation interlock set when X minimum threshold is exceeded. """ - return self['IntlkAngSmallerLtcX-Mon'] + return self['IntlkAngLowerLtcX-Mon'] @property - def ang_latch_bigger_x(self): + def ang_latch_upper_x(self): """ Latch angulation interlock set when X maximum threshold is exceeded. """ - return self['IntlkAngBiggerLtcX-Mon'] + return self['IntlkAngUpperLtcX-Mon'] @property - def ang_latch_smaller_y(self): + def ang_latch_lower_y(self): """ Latch angulation interlock set when Y minimum threshold is exceeded. """ - return self['IntlkAngSmallerLtcY-Mon'] + return self['IntlkAngLowerLtcY-Mon'] @property - def ang_latch_bigger_y(self): + def ang_latch_upper_y(self): """ Latch angulation interlock set when Y maximum threshold is exceeded. """ - return self['IntlkAngBiggerLtcY-Mon'] + return self['IntlkAngUpperLtcY-Mon'] class OrbitInterlock(BaseOrbitIntlk, _Devices): @@ -761,231 +725,211 @@ def minsumthres(self, value): for idx, dev in enumerate(self.devices): dev.minsumthres = value[idx] - # --- translation interlock --- + # --- position interlock --- - def cmd_trans_enable(self, timeout=TIMEOUT): - """Enable all BPM translation interlock.""" + def cmd_pos_enable(self, timeout=TIMEOUT): + """Enable all BPM position interlock.""" for dev in self.devices: - dev.trans_enable = 1 + dev.pos_enable = 1 return self._wait_devices_propty( - self.devices, 'IntlkTransEn-Sts', 1, timeout=timeout) + self.devices, 'IntlkPosEn-Sts', 1, timeout=timeout) - def cmd_trans_disable(self, timeout=TIMEOUT): - """Disable all BPM translation interlock.""" + def cmd_pos_disable(self, timeout=TIMEOUT): + """Disable all BPM position interlock.""" for dev in self.devices: - dev.trans_enable = 0 + dev.pos_enable = 0 return self._wait_devices_propty( - self.devices, 'IntlkTransEn-Sts', 0, timeout=timeout) + self.devices, 'IntlkPosEn-Sts', 0, timeout=timeout) - def cmd_reset_trans(self): - """Reset all BPM translation interlock.""" + def cmd_reset_pos(self): + """Reset all BPM position interlock.""" for dev in self.devices: - dev.cmd_reset_trans() + dev.cmd_reset_pos() return True @property - def trans_thresminx(self): - """Minimum x translation thresholds. + def pos_thresminx(self): + """Minimum x position thresholds. Returns: thres (numpy.ndarray, 160): - min. x translation threshold for each BPM. + min. x position threshold for each BPM. """ - return _np.array([b.trans_thresminx for b in self._devices]) + return _np.array([b.pos_thresminx for b in self._devices]) - @trans_thresminx.setter - def trans_thresminx(self, value): + @pos_thresminx.setter + def pos_thresminx(self, value): value = self._handle_thres_input(value) for idx, dev in enumerate(self.devices): - dev.trans_thresminx = value[idx] + dev.pos_thresminx = value[idx] @property - def trans_thresmaxx(self): - """Maximum x translation thresholds. + def pos_thresmaxx(self): + """Maximum x position thresholds. Returns: thres (numpy.ndarray, 160): - max. x translation threshold for each BPM. + max. x position threshold for each BPM. """ - return _np.array([b.trans_thresmaxx for b in self._devices]) + return _np.array([b.pos_thresmaxx for b in self._devices]) - @trans_thresmaxx.setter - def trans_thresmaxx(self, value): + @pos_thresmaxx.setter + def pos_thresmaxx(self, value): value = self._handle_thres_input(value) for idx, dev in enumerate(self.devices): - dev.trans_thresmaxx = value[idx] + dev.pos_thresmaxx = value[idx] @property - def trans_thresminy(self): - """Minimum y translation thresholds. + def pos_thresminy(self): + """Minimum y position thresholds. Returns: thres (numpy.ndarray, 160): - min. y translation threshold for each BPM. + min. y position threshold for each BPM. """ - return _np.array([b.trans_thresminy for b in self._devices]) + return _np.array([b.pos_thresminy for b in self._devices]) - @trans_thresminy.setter - def trans_thresminy(self, value): + @pos_thresminy.setter + def pos_thresminy(self, value): value = self._handle_thres_input(value) for idx, dev in enumerate(self.devices): - dev.trans_thresminy = value[idx] + dev.pos_thresminy = value[idx] @property - def trans_thresmaxy(self): - """Maximum y translation thresholds. + def pos_thresmaxy(self): + """Maximum y position thresholds. Returns: thres (numpy.ndarray, 160): - max. y translation threshold for each BPM. + max. y position threshold for each BPM. """ - return _np.array([b.trans_thresmaxy for b in self._devices]) + return _np.array([b.pos_thresmaxy for b in self._devices]) - @trans_thresmaxy.setter - def trans_thresmaxy(self, value): + @pos_thresmaxy.setter + def pos_thresmaxy(self, value): value = self._handle_thres_input(value) for idx, dev in enumerate(self.devices): - dev.trans_thresmaxy = value[idx] - - @property - def trans_mask_smaller(self): - """Instantaneous translation interlock set when either X or Y - minimum thresholds are exceeded, masked by general enable. - - Returns: - intlk (numpy.ndarray, 160): interlock status for each BPM. - """ - return _np.array([b.trans_mask_smaller for b in self._devices]) + dev.pos_thresmaxy = value[idx] @property - def trans_mask_bigger(self): - """Instantaneous translation interlock set when either X or Y - maximum thresholds are exceeded, masked by general enable. - - Returns: - intlk (numpy.ndarray, 160): interlock status for each BPM. - """ - return _np.array([b.trans_mask_bigger for b in self._devices]) - - @property - def trans_inst_smaller(self): - """Instantaneous translation interlock set when either X or Y + def pos_inst_lower(self): + """Instantaneous position interlock set when either X or Y minimum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_inst_smaller for b in self._devices]) + return _np.array([b.pos_inst_lower for b in self._devices]) @property - def trans_inst_bigger(self): - """Instantaneous translation interlock set when either X or Y + def pos_inst_upper(self): + """Instantaneous position interlock set when either X or Y maximum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_inst_bigger for b in self._devices]) + return _np.array([b.pos_inst_upper for b in self._devices]) @property - def trans_inst_smaller_x(self): - """Instantaneous translation interlock set when X + def pos_inst_lower_x(self): + """Instantaneous position interlock set when X minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_inst_smaller_x for b in self._devices]) + return _np.array([b.pos_inst_lower_x for b in self._devices]) @property - def trans_inst_bigger_x(self): - """Instantaneous translation interlock set when X + def pos_inst_upper_x(self): + """Instantaneous position interlock set when X maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_inst_bigger_x for b in self._devices]) + return _np.array([b.pos_inst_upper_x for b in self._devices]) @property - def trans_inst_smaller_y(self): - """Instantaneous translation interlock set when Y + def pos_inst_lower_y(self): + """Instantaneous position interlock set when Y minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_inst_smaller_y for b in self._devices]) + return _np.array([b.pos_inst_lower_y for b in self._devices]) @property - def trans_inst_bigger_y(self): - """Instantaneous translation interlock set when Y + def pos_inst_upper_y(self): + """Instantaneous position interlock set when Y maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_inst_bigger_y for b in self._devices]) + return _np.array([b.pos_inst_upper_y for b in self._devices]) @property - def trans_latch_smaller(self): - """Latch translation interlock set when either X or Y + def pos_latch_lower(self): + """Latch position interlock set when either X or Y minimum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_latch_smaller for b in self._devices]) + return _np.array([b.pos_latch_lower for b in self._devices]) @property - def trans_latch_bigger(self): - """Latch translation interlock set when either X or Y + def pos_latch_upper(self): + """Latch position interlock set when either X or Y maximum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_latch_bigger for b in self._devices]) + return _np.array([b.pos_latch_upper for b in self._devices]) @property - def trans_latch_smaller_x(self): - """Latch translation interlock set when X + def pos_latch_lower_x(self): + """Latch position interlock set when X minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_latch_smaller_x for b in self._devices]) + return _np.array([b.pos_latch_lower_x for b in self._devices]) @property - def trans_latch_bigger_x(self): - """Latch translation interlock set when X + def pos_latch_upper_x(self): + """Latch position interlock set when X maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_latch_bigger_x for b in self._devices]) + return _np.array([b.pos_latch_upper_x for b in self._devices]) @property - def trans_latch_smaller_y(self): - """Latch translation interlock set when Y + def pos_latch_lower_y(self): + """Latch position interlock set when Y minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_latch_smaller_y for b in self._devices]) + return _np.array([b.pos_latch_lower_y for b in self._devices]) @property - def trans_latch_bigger_y(self): - """Latch translation interlock set when Y + def pos_latch_upper_y(self): + """Latch position interlock set when Y maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.trans_latch_bigger_y for b in self._devices]) + return _np.array([b.pos_latch_upper_y for b in self._devices]) # --- angulation interlock --- @@ -1074,144 +1018,124 @@ def ang_thresmaxy(self, value): dev.ang_thresmaxy = value[idx] @property - def ang_mask_smaller(self): - """Instantaneous angulation interlock set when either X or Y - minimum thresholds are exceeded, masked by general enable. - - Returns: - intlk (numpy.ndarray, 160): interlock status for each BPM. - """ - return _np.array([b.ang_mask_smaller for b in self._devices]) - - @property - def ang_mask_bigger(self): - """Instantaneous angulation interlock set when either X or Y - maximum thresholds are exceeded, masked by general enable. - - Returns: - intlk (numpy.ndarray, 160): interlock status for each BPM. - """ - return _np.array([b.ang_mask_bigger for b in self._devices]) - - @property - def ang_inst_smaller(self): + def ang_inst_lower(self): """Instantaneous angulation interlock set when either X or Y minimum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_inst_smaller for b in self._devices]) + return _np.array([b.ang_inst_lower for b in self._devices]) @property - def ang_inst_bigger(self): + def ang_inst_upper(self): """Instantaneous angulation interlock set when either X or Y maximum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_inst_bigger for b in self._devices]) + return _np.array([b.ang_inst_upper for b in self._devices]) @property - def ang_inst_smaller_x(self): + def ang_inst_lower_x(self): """Instantaneous angulation interlock set when X minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_inst_smaller_x for b in self._devices]) + return _np.array([b.ang_inst_lower_x for b in self._devices]) @property - def ang_inst_bigger_x(self): + def ang_inst_upper_x(self): """Instantaneous angulation interlock set when X maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_inst_bigger_x for b in self._devices]) + return _np.array([b.ang_inst_upper_x for b in self._devices]) @property - def ang_inst_smaller_y(self): + def ang_inst_lower_y(self): """Instantaneous angulation interlock set when Y minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_inst_smaller_y for b in self._devices]) + return _np.array([b.ang_inst_lower_y for b in self._devices]) @property - def ang_inst_bigger_y(self): + def ang_inst_upper_y(self): """Instantaneous angulation interlock set when Y maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_inst_bigger_y for b in self._devices]) + return _np.array([b.ang_inst_upper_y for b in self._devices]) @property - def ang_latch_smaller(self): + def ang_latch_lower(self): """Latch angulation interlock set when either X or Y minimum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_latch_smaller for b in self._devices]) + return _np.array([b.ang_latch_lower for b in self._devices]) @property - def ang_latch_bigger(self): + def ang_latch_upper(self): """Latch angulation interlock set when either X or Y maximum thresholds are exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_latch_bigger for b in self._devices]) + return _np.array([b.ang_latch_upper for b in self._devices]) @property - def ang_latch_smaller_x(self): + def ang_latch_lower_x(self): """Latch angulation interlock set when X minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_latch_smaller_x for b in self._devices]) + return _np.array([b.ang_latch_lower_x for b in self._devices]) @property - def ang_latch_bigger_x(self): + def ang_latch_upper_x(self): """Latch angulation interlock set when X maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_latch_bigger_x for b in self._devices]) + return _np.array([b.ang_latch_upper_x for b in self._devices]) @property - def ang_latch_smaller_y(self): + def ang_latch_lower_y(self): """Latch angulation interlock set when Y minimum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_latch_smaller_y for b in self._devices]) + return _np.array([b.ang_latch_lower_y for b in self._devices]) @property - def ang_latch_bigger_y(self): + def ang_latch_upper_y(self): """Latch angulation interlock set when Y maximum threshold is exceeded. Returns: intlk (numpy.ndarray, 160): interlock status for each BPM. """ - return _np.array([b.ang_latch_bigger_y for b in self._devices]) + return _np.array([b.ang_latch_upper_y for b in self._devices]) @property def slow_orbit(self): @@ -1240,20 +1164,20 @@ def possum(self): return _np.array([b.possum for b in self._devices]) @property - def translation(self): - """Translation vectors. + def position(self): + """Position vectors. - Translation at each BPM is defined as: + Position at each BPM is defined as: (pos BPM downstream + pos BPM upstream)/2 Returns: - transx (numpy.ndarray, 160): Horizontal Translation. - transy (numpy.ndarray, 160): Vertical Translation. + posx (numpy.ndarray, 160): Horizontal Position. + posy (numpy.ndarray, 160): Vertical Position. """ orbx, orby = self.slow_orbit - transx = _np.array(self.calc_intlk_metric(orbx, metric='trans')) - transy = _np.array(self.calc_intlk_metric(orby, metric='trans')) - return transx, transy + posx = _np.array(self.calc_intlk_metric(orbx, metric='pos')) + posy = _np.array(self.calc_intlk_metric(orby, metric='pos')) + return posx, posy @property def angulation(self): From 61993523cc9fcea5045685c75578eca9ff548514 Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 2 Mar 2023 10:22:53 -0300 Subject: [PATCH 09/19] CLTARCH.ENH: Fix update of PVDataSet in case there is only one PV. --- siriuspy/siriuspy/clientarch/pvarch.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/siriuspy/siriuspy/clientarch/pvarch.py b/siriuspy/siriuspy/clientarch/pvarch.py index 6b60aed13..6b8bd129e 100644 --- a/siriuspy/siriuspy/clientarch/pvarch.py +++ b/siriuspy/siriuspy/clientarch/pvarch.py @@ -508,8 +508,13 @@ def update(self, mean_sec=None, parallel=True): data = self.connector.getData( self._pvnames, timestamp_start, timestamp_stop, process_type=process_type, interval=mean_sec) + if not data: return + if len(self._pvnames) == 1: + pvname = self._pvnames[0] + data = dict(pvname=data) + for pvname in self._pvnames: self._pvdata[pvname].set_data(**data[pvname]) From ff87bb07b38327f6ad17b5c7f9970d8c32774b59 Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 2 Mar 2023 10:37:05 -0300 Subject: [PATCH 10/19] CLTARCH.BUG: Fix bug in last commit. --- siriuspy/siriuspy/clientarch/pvarch.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/siriuspy/siriuspy/clientarch/pvarch.py b/siriuspy/siriuspy/clientarch/pvarch.py index 6b8bd129e..b327d1d6d 100644 --- a/siriuspy/siriuspy/clientarch/pvarch.py +++ b/siriuspy/siriuspy/clientarch/pvarch.py @@ -513,8 +513,7 @@ def update(self, mean_sec=None, parallel=True): return if len(self._pvnames) == 1: pvname = self._pvnames[0] - data = dict(pvname=data) - + data = {pvname: data} for pvname in self._pvnames: self._pvdata[pvname].set_data(**data[pvname]) From ca8c5baa7b4dcf5a2608b5058fb35355049464a3 Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 2 Mar 2023 10:37:41 -0300 Subject: [PATCH 11/19] Update VERSION file to 2.67.3. --- siriuspy/siriuspy/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/VERSION b/siriuspy/siriuspy/VERSION index 456312b41..1eda73de6 100644 --- a/siriuspy/siriuspy/VERSION +++ b/siriuspy/siriuspy/VERSION @@ -1 +1 @@ -2.67.2 +2.67.3 From af655ae7d74a95464a9981c31e13a772db5936cb Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 3 Mar 2023 11:30:40 -0300 Subject: [PATCH 12/19] DEV.FAMBPM.ENH: Improve logic of checking if orbit was update. Remove all auto-monitors. --- siriuspy/siriuspy/devices/bpm.py | 200 +++++++++++++++++++++++-------- 1 file changed, 149 insertions(+), 51 deletions(-) diff --git a/siriuspy/siriuspy/devices/bpm.py b/siriuspy/siriuspy/devices/bpm.py index f817c6c06..21e2089e6 100644 --- a/siriuspy/siriuspy/devices/bpm.py +++ b/siriuspy/siriuspy/devices/bpm.py @@ -164,6 +164,11 @@ def switching_mode(self, val): """.""" self['SwMode-Sel'] = val + @property + def harmonic_number(self): + """.""" + return self['INFOHarmonicNumber-RB'] + @property def adcfreq(self): """.""" @@ -171,7 +176,7 @@ def adcfreq(self): @property def tbt_rate(self): - """.""" + """Divisor or TbT in relation to ADC.""" return self['INFOTBTRate-RB'] @property @@ -231,7 +236,7 @@ def fofb_sync_enbl(self, val): @property def fofb_rate(self): - """.""" + """Divisor or FOFB in relation to ADC.""" return self['INFOFOFBRate-RB'] @property @@ -261,7 +266,7 @@ def monit1_sync_enbl(self, val): @property def monit_rate(self): - """.""" + """Divisor or Monit in relation to ADC.""" return self['INFOMONITRate-RB'] @property @@ -918,8 +923,8 @@ def get_mturn_orbit(self, return_sum=False): return orbx, orby return orbx, orby, _np.array(possum).T - @staticmethod - def get_sampling_frequency(rf_freq: float, acq_rate='Monit1'): + def get_sampling_frequency( + self, rf_freq: float, acq_rate='Monit1') -> float: """Return the sampling frequency of the acquisition. Args: @@ -930,18 +935,19 @@ def get_sampling_frequency(rf_freq: float, acq_rate='Monit1'): float: acquisition frequency. """ - fsamp = rf_freq / 864 + bpm = self._devices[0] + fadc = rf_freq / bpm.harmonic_number * bpm.tbt_rate if acq_rate.lower().startswith('tbt'): - return fsamp - fsamp /= 23 - if acq_rate.lower().startswith('fofb'): - return fsamp - fsamp /= 25 - return fsamp + return fadc / bpm.tbt_rate + elif acq_rate.lower().startswith('fofb'): + return fadc / bpm.fofb_rate + elif acq_rate.lower().startswith('monit1'): + return fadc / bpm.monit1_rate + return fadc / bpm.monit_rate def mturn_config_acquisition( self, nr_points_after: int, nr_points_before=0, - acq_rate='Monit1', repeat=True, external=True): + acq_rate='Monit1', repeat=True, external=True) -> int: """Configure acquisition for BPMs. Args: @@ -955,6 +961,12 @@ def mturn_config_acquisition( external (bool, optional): Whether or not external trigger should be used. Defaults to True. + Returns: + int: code describing what happened: + =0: BPMs are ready. + <0: Index of the first BPM which did not stop last acq. plus 1. + >0: Index of the first BPM which is not ready for acq. plus 1. + """ if acq_rate.lower().startswith('monit1'): acq_rate = self._csbpm.AcqChan.Monit1 @@ -975,7 +987,9 @@ def mturn_config_acquisition( else: trig = self._csbpm.AcqTrigTyp.Now - self.cmd_mturn_acq_abort() + ret = self.cmd_mturn_acq_abort() + if ret > 0: + return -ret for bpm in self._devices: bpm.acq_repeat = repeat @@ -984,39 +998,86 @@ def mturn_config_acquisition( bpm.acq_nrsamples_pre = nr_points_before bpm.acq_nrsamples_post = nr_points_after - self.cmd_mturn_acq_start() + return self.cmd_mturn_acq_start() - def cmd_mturn_acq_abort(self) -> bool: + def cmd_mturn_acq_abort(self, wait=True, timeout=10) -> int: """Abort BPMs acquistion. + Args: + wait (bool, optional): whether or not to wait BPMs get ready. + Defaults to True. + timeout (int, optional): Time to wait. Defaults to 10. + Returns: - bool: Whether or not abort was successful. + int: code describing what happened: + =0: BPMs are ready. + >0: Index of the first BPM which did not updated plus 1. """ for bpm in self._devices: bpm.acq_ctrl = self._csbpm.AcqEvents.Abort - for bpm in self._devices: - boo = bpm.wait_acq_finish() - if not boo: - return False - return True + if wait: + return self.wait_acquisition_finish(timeout=timeout) + return 0 + + def wait_acquisition_finish(self, timeout=10) -> int: + """Wait for all BPMs to be ready for acquisition. + + Args: + timeout (int, optional): Time to wait. Defaults to 10. + + Returns: + int: code describing what happened: + =0: BPMs are ready. + >0: Index of the first BPM which did not updated plus 1. - def cmd_mturn_acq_start(self) -> bool: + """ + for i, bpm in enumerate(self._devices): + t0_ = _time.time() + if not bpm.wait_acq_finish(timeout): + return i + 1 + timeout -= _time.time() - t0_ + return 0 + + def cmd_mturn_acq_start(self, wait=True, timeout=10) -> int: """Start BPMs acquisition. + Args: + wait (bool, optional): whether or not to wait BPMs get ready. + Defaults to True. + timeout (int, optional): Time to wait. Defaults to 10. + Returns: - bool: Whether or not start was successful. + int: code describing what happened: + =0: BPMs are ready. + >0: Index of the first BPM which did not updated plus 1. """ for bpm in self._devices: bpm.acq_ctrl = self._csbpm.AcqEvents.Start + if wait: + return self.wait_acquisition_start(timeout=timeout) + return 0 - for bpm in self._devices: - boo = bpm.wait_acq_start() - if not boo: - return False - return True + def wait_acquisition_start(self, timeout=10) -> bool: + """Wait for all BPMs to be ready for acquisition. + + Args: + timeout (int, optional): Time to wait. Defaults to 10. + + Returns: + int: code describing what happened: + =0: BPMs are ready. + >0: Index of the first BPM which did not updated plus 1. + + """ + for i, bpm in enumerate(self._devices): + t0_ = _time.time() + if not bpm.wait_acq_start(timeout): + return i + 1 + timeout -= _time.time() - t0_ + return 0 def set_switching_mode(self, mode='direct'): """Set switching mode of BPMS. @@ -1035,36 +1096,49 @@ def set_switching_mode(self, mode='direct'): for bpm in self._devices: bpm.switching_mode = mode - def mturn_wait_update_flags(self, timeout=10) -> int: - """Wait Multiturn orbit update. + def mturn_update_initial_orbit(self, consider_sum=False): + """Call this method before acquisition to get orbit for comparison.""" + self._initial_orbs = self.get_mturn_orbit(return_sum=consider_sum) + + def mturn_wait_update_orbit(self, timeout=10, consider_sum=False) -> int: + """Call this method after acquisition to check if orbit was updated. + + For this method to work it is necessary to call + mturn_update_initial_orbit + before the acquisition starts, so that a reference for comparison is + created. Args: timeout (int, optional): Waiting timeout. Defaults to 10. + consider_sum (bool, optional): Whether to also wait for sum signal + to be updated. Defaults to False. Returns: int: code describing what happened: - -2: TypeError ocurred - -1: Size of X orbit is different than Y orbit. - 0: Orbit updated. + -4: unknown error; + -3: initial orbit was not acquired before acquisition; + -2: TypeError ocurred (maybe because some of them are None); + -1: Orbits have different sizes; + =0: Orbit updated. >0: Index of the first BPM which did not updated plus 1. """ - orbx0, orby0 = self.get_mturn_orbit() + orbs0, self._initial_orbs = self._initial_orbs, None + if orbs0 is None: + return -3 while timeout > 0: t00 = _time.time() - orbx, orby = self.get_mturn_orbit() + orbs = self.get_mturn_orbit(return_sum=consider_sum) typ = False try: - sizx = min(orbx.shape[0], orbx0.shape[0]) - sizy = min(orby.shape[0], orby0.shape[0]) - continue_ = sizx != sizy - errx = _np.all( - _np.isclose(orbx0[:sizx], orbx[:sizx]), axis=0) - erry = _np.all( - _np.isclose(orby0[:sizy], orby[:sizy]), axis=0) - continue_ |= _np.any(errx) | _np.any(erry) + sizes = [ + min(o.shape[0], o0.shape[0]) for o, o0 in zip(orbs, orbs0)] + continue_ = max(sizes) != min(sizes) + errs = _np.any([ + _np.all(_np.isclose(o[:s], o0[:s]), axis=0) + for o, o0, s in zip(orbs, orbs0, sizes)], axis=0) + continue_ |= _np.any(errs) except TypeError: - print('TypeError') typ = True continue_ = True if not continue_: @@ -1074,13 +1148,37 @@ def mturn_wait_update_flags(self, timeout=10) -> int: if typ: return -1 - elif sizx != sizy: + elif max(sizes) != min(sizes): return -2 - elif _np.any(errx): - return int(errx.nonzero()[0][0])+1 - elif _np.any(erry): - return int(erry.nonzero()[0][0])+1 - return False + elif _np.any(errs): + return int(errs.nonzero()[0][0])+1 + return -4 + + def mturn_wait_update(self, timeout=10, consider_sum=False) -> int: + """Combine wait_acquistion_finish and mturn_wait_update_orbit. + + Args: + timeout (int, optional): Waiting timeout. Defaults to 10. + consider_sum (bool, optional): Whether to also wait for sum signal + to be updated. Defaults to False. + + Returns: + int: code describing what happened: + -4: unknown error; + -3: initial orbit was not acquired before acquisition; + -2: TypeError ocurred (maybe because some of them are None); + -1: Orbits have different sizes; + =0: Orbit updated. + >0: Index of the first BPM which did not updated plus 1. + + """ + t00 = _time.time() + ret = self.wait_acquisition_finish(timeout) + if ret > 0: + return ret + timeout -= _time.time() - t00 + + return self.mturn_wait_update_orbit(timeout, consider_sum=consider_sum) class BPMLogicalTrigger(_ProptyDevice): From 9f8ec52a973183833000dc791c6406a1881ac664 Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 3 Mar 2023 15:14:06 -0300 Subject: [PATCH 13/19] SOFB.ENH: Do not use `auto_monitor=True` for array PVs, check acquisition status instead. --- siriuspy/siriuspy/sofb/bpms.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/siriuspy/siriuspy/sofb/bpms.py b/siriuspy/siriuspy/sofb/bpms.py index 7e3fe36e8..686e50d93 100644 --- a/siriuspy/siriuspy/sofb/bpms.py +++ b/siriuspy/siriuspy/sofb/bpms.py @@ -24,14 +24,12 @@ def __init__(self, name, callback=None): self._name = name self._orb_conv_unit = self._csorb.ORBIT_CONVERSION_UNIT pvpref = LL_PREF + ('-' if LL_PREF else '') + self._name + ':' - opt = {'connection_timeout': TIMEOUT} + opt = {'connection_timeout': TIMEOUT, 'auto_monitor': False} self._poskx = _PV(pvpref + 'PosKx-RB', **opt) self._posky = _PV(pvpref + 'PosKy-RB', **opt) self._ksum = _PV(pvpref + 'PosKsum-RB', **opt) self._polyx = _PV(pvpref + 'GEN_PolyXArrayCoeff-RB', **opt) self._polyy = _PV(pvpref + 'GEN_PolyYArrayCoeff-RB', **opt) - opt['callback'] = self._set_needs_update - opt['auto_monitor'] = True self._arraya = _PV(pvpref + 'GEN_AArrayData', **opt) self._arrayb = _PV(pvpref + 'GEN_BArrayData', **opt) self._arrayc = _PV(pvpref + 'GEN_CArrayData', **opt) @@ -39,8 +37,6 @@ def __init__(self, name, callback=None): self._arrayx = _PV(pvpref + 'GEN_XArrayData', **opt) self._arrayy = _PV(pvpref + 'GEN_YArrayData', **opt) self._arrays = _PV(pvpref + 'GEN_SUMArrayData', **opt) - opt.pop('callback') - opt.pop('auto_monitor') self._offsetx = _PV(pvpref + 'PosXOffset-RB', **opt) self._offsety = _PV(pvpref + 'PosYOffset-RB', **opt) self._config_ok_vals = { @@ -144,6 +140,8 @@ def __init__(self, name, callback=None): 'SUMPosCal': 'SUMPosCal-Sts'} self._config_pvs_rb = { k: _PV(pvpref + v, **opt) for k, v in pvs.items()} + self._config_pvs_rb['ACQStatus'].auto_monitor = True + self._config_pvs_rb['ACQStatus'].add_callback(self._set_needs_update) @property def name(self): From 181cc9d6c1e69b502a6be9653738c1f0f10a9020 Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 3 Mar 2023 15:28:39 -0300 Subject: [PATCH 14/19] SOFB.MNT: complement of last commit transforming needs_update in a counter. --- siriuspy/siriuspy/sofb/bpms.py | 10 ++++++---- siriuspy/siriuspy/sofb/orbit.py | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/siriuspy/siriuspy/sofb/bpms.py b/siriuspy/siriuspy/sofb/bpms.py index 686e50d93..92498be18 100644 --- a/siriuspy/siriuspy/sofb/bpms.py +++ b/siriuspy/siriuspy/sofb/bpms.py @@ -15,11 +15,12 @@ class BPM(_BaseTimingConfig): """.""" + MAX_UPT_CNT = 20 # equivalent of 10s of orbit update after Acq. PV update def __init__(self, name, callback=None): """.""" super().__init__(name[:2], callback) - self.needs_update = True + self.needs_update_cnt = self.MAX_UPT_CNT self._name = name self._orb_conv_unit = self._csorb.ORBIT_CONVERSION_UNIT @@ -141,7 +142,8 @@ def __init__(self, name, callback=None): self._config_pvs_rb = { k: _PV(pvpref + v, **opt) for k, v in pvs.items()} self._config_pvs_rb['ACQStatus'].auto_monitor = True - self._config_pvs_rb['ACQStatus'].add_callback(self._set_needs_update) + self._config_pvs_rb['ACQStatus'].add_callback( + self._reset_needs_update_cnt) @property def name(self): @@ -740,9 +742,9 @@ def _calc_poly(self, th1, ot1, plane='x'): th7*(pol[12] + ot2*pol[13]) + th9*pol[14]) - def _set_needs_update(self, *args, **kwargs): + def _reset_needs_update_cnt(self, *args, **kwargs): _ = args, kwargs - self.needs_update = True + self.needs_update_cnt = self.MAX_UPT_CNT class TimingConfig(_BaseTimingConfig): diff --git a/siriuspy/siriuspy/sofb/orbit.py b/siriuspy/siriuspy/sofb/orbit.py index 44679dd60..5d7baf3ca 100644 --- a/siriuspy/siriuspy/sofb/orbit.py +++ b/siriuspy/siriuspy/sofb/orbit.py @@ -836,8 +836,8 @@ def _update_multiturn_orbits(self): nr_pts = self._smooth_npts do_update = False for i, bpm in enumerate(self.bpms): - if not leng or bpm.needs_update: - bpm.needs_update = False + if not leng or bpm.needs_update_cnt > 0: + bpm.needs_update_cnt -= 1 do_update = True posx = self._get_pos( bpm.mtposx, self.ref_orbs['X'][i], samp) @@ -912,8 +912,8 @@ def _update_singlepass_orbits(self): nr_pts = self._smooth_npts do_update = False for i, bpm in enumerate(self.bpms): - if not leng or bpm.needs_update: - bpm.needs_update = False + if not leng or bpm.needs_update_cnt > 0: + bpm.needs_update_cnt -= 1 do_update = True dic.update({ 'refx': self.ref_orbs['X'][i], From 58cb360e44f3d3e1c6a84b6f7be6b1cecdcff817 Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 3 Mar 2023 17:05:42 -0300 Subject: [PATCH 15/19] DEV.BUG: Implement @murilobalves suggestions and fixes. --- siriuspy/siriuspy/devices/bpm.py | 12 ++++++------ siriuspy/siriuspy/devices/pwrsupply.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/siriuspy/siriuspy/devices/bpm.py b/siriuspy/siriuspy/devices/bpm.py index 21e2089e6..00528d1b8 100644 --- a/siriuspy/siriuspy/devices/bpm.py +++ b/siriuspy/siriuspy/devices/bpm.py @@ -1011,7 +1011,7 @@ def cmd_mturn_acq_abort(self, wait=True, timeout=10) -> int: Returns: int: code describing what happened: =0: BPMs are ready. - >0: Index of the first BPM which did not updated plus 1. + >0: Index of the first BPM which did not update plus 1. """ for bpm in self._devices: @@ -1030,7 +1030,7 @@ def wait_acquisition_finish(self, timeout=10) -> int: Returns: int: code describing what happened: =0: BPMs are ready. - >0: Index of the first BPM which did not updated plus 1. + >0: Index of the first BPM which did not update plus 1. """ for i, bpm in enumerate(self._devices): @@ -1051,7 +1051,7 @@ def cmd_mturn_acq_start(self, wait=True, timeout=10) -> int: Returns: int: code describing what happened: =0: BPMs are ready. - >0: Index of the first BPM which did not updated plus 1. + >0: Index of the first BPM which did not update plus 1. """ for bpm in self._devices: @@ -1069,7 +1069,7 @@ def wait_acquisition_start(self, timeout=10) -> bool: Returns: int: code describing what happened: =0: BPMs are ready. - >0: Index of the first BPM which did not updated plus 1. + >0: Index of the first BPM which did not update plus 1. """ for i, bpm in enumerate(self._devices): @@ -1120,7 +1120,7 @@ def mturn_wait_update_orbit(self, timeout=10, consider_sum=False) -> int: -2: TypeError ocurred (maybe because some of them are None); -1: Orbits have different sizes; =0: Orbit updated. - >0: Index of the first BPM which did not updated plus 1. + >0: Index of the first BPM which did not update plus 1. """ orbs0, self._initial_orbs = self._initial_orbs, None @@ -1169,7 +1169,7 @@ def mturn_wait_update(self, timeout=10, consider_sum=False) -> int: -2: TypeError ocurred (maybe because some of them are None); -1: Orbits have different sizes; =0: Orbit updated. - >0: Index of the first BPM which did not updated plus 1. + >0: Index of the first BPM which did not update plus 1. """ t00 = _time.time() diff --git a/siriuspy/siriuspy/devices/pwrsupply.py b/siriuspy/siriuspy/devices/pwrsupply.py index 17c0e345d..fc386576f 100644 --- a/siriuspy/siriuspy/devices/pwrsupply.py +++ b/siriuspy/siriuspy/devices/pwrsupply.py @@ -204,9 +204,9 @@ def pwrstate(self, value): self['PwrState-Sel'] = value def set_strength(self, value, tol=0.2, timeout=10, wait_mon=False): - """Set RF phase and wait until it gets there.""" + """Set strength and wait until it gets there.""" self.strength = value - pv2wait = self._strength_rb_propty if wait_mon \ + pv2wait = self._strength_mon_propty if wait_mon \ else self._strength_rb_propty return self._wait_float(pv2wait, value, abs_tol=tol, timeout=timeout) From b3d023a6a2bfdf1d617865f0972231cac7918f9e Mon Sep 17 00:00:00 2001 From: Ana Clara Oliveira Date: Fri, 3 Mar 2023 17:49:55 -0300 Subject: [PATCH 16/19] DEVORBINTLK.API: removed unused CONV_POLY_MONIT1_2_MONIT constant --- siriuspy/siriuspy/devices/orbit_interlock.py | 33 -------------------- 1 file changed, 33 deletions(-) diff --git a/siriuspy/siriuspy/devices/orbit_interlock.py b/siriuspy/siriuspy/devices/orbit_interlock.py index dc4dbee9a..94c4bfba5 100644 --- a/siriuspy/siriuspy/devices/orbit_interlock.py +++ b/siriuspy/siriuspy/devices/orbit_interlock.py @@ -604,39 +604,6 @@ class OrbitInterlock(BaseOrbitIntlk, _Devices): TIMEOUT = 10 - # NOTE: this is a temporary location, will migrate to csconstants. - # The values will be replaced by the measured calibration data. - _av = _np.array([ - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])*2**21 - _bv = _np.array([ - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) - - # for each BPM, folowing BPM_NAMES indices - # a, b: monit = a*monit1 + b - CONV_POLY_MONIT1_2_MONIT = _np.vstack([_av, _bv]) - class DEVICES: """.""" SI = 'SI-Fam:DI-BPM' From ae232cb4f6f34b89595d7d2fc3602a8cb1733978 Mon Sep 17 00:00:00 2001 From: Fernando Date: Mon, 6 Mar 2023 09:06:37 -0300 Subject: [PATCH 17/19] SOFB.BUG: Add auto_monitor back to configuration PVs. --- siriuspy/siriuspy/sofb/bpms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/siriuspy/siriuspy/sofb/bpms.py b/siriuspy/siriuspy/sofb/bpms.py index 92498be18..b2150ce84 100644 --- a/siriuspy/siriuspy/sofb/bpms.py +++ b/siriuspy/siriuspy/sofb/bpms.py @@ -38,6 +38,7 @@ def __init__(self, name, callback=None): self._arrayx = _PV(pvpref + 'GEN_XArrayData', **opt) self._arrayy = _PV(pvpref + 'GEN_YArrayData', **opt) self._arrays = _PV(pvpref + 'GEN_SUMArrayData', **opt) + opt.pop('auto_monitor') self._offsetx = _PV(pvpref + 'PosXOffset-RB', **opt) self._offsety = _PV(pvpref + 'PosYOffset-RB', **opt) self._config_ok_vals = { From 1449303b4a93b8f79957d33bce25c618257e2570 Mon Sep 17 00:00:00 2001 From: Fernando Date: Mon, 6 Mar 2023 13:19:39 -0300 Subject: [PATCH 18/19] DEV.BPM.ENH: Add option of connecting with PostMorten PVs. --- siriuspy/siriuspy/devices/bpm.py | 171 ++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 58 deletions(-) diff --git a/siriuspy/siriuspy/devices/bpm.py b/siriuspy/siriuspy/devices/bpm.py index 00528d1b8..c07c889db 100644 --- a/siriuspy/siriuspy/devices/bpm.py +++ b/siriuspy/siriuspy/devices/bpm.py @@ -69,13 +69,15 @@ class BPM(_Device): CONV_NM2UM = 1e-3 # [nm] --> [um] - def __init__(self, devname, auto_mon=True): + def __init__(self, devname, auto_mon=True, ispost_mortem=False): """.""" # call base class constructor if not _BPMSearch.is_valid_devname(devname): raise ValueError(devname + ' is not a valid BPM or PBPM name.') - properties = set(BPM._properties) + self._ispost_mortem = ispost_mortem + properties = {self._get_postmorten_prop(p) for p in BPM._properties} + if _BPMSearch.is_photon_bpm(devname): properties -= {'RFFEAtt-SP', 'RFFEAtt-RB'} properties = list(properties) @@ -399,82 +401,98 @@ def ampld(self): @property def mt_posx(self): """.""" - return self['GEN_XArrayData'] * self.CONV_NM2UM + prop = self._get_postmorten_prop('GEN_XArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_posy(self): """.""" - return self['GEN_YArrayData'] * self.CONV_NM2UM + prop = self._get_postmorten_prop('GEN_YArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_possum(self): """.""" - return self['GEN_SUMArrayData'] + prop = self._get_postmorten_prop('GEN_SUMArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_posq(self): """.""" - return self['GEN_QArrayData'] + prop = self._get_postmorten_prop('GEN_QArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_ampla(self): """.""" - return self['GEN_AArrayData'] + prop = self._get_postmorten_prop('GEN_AArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_amplb(self): """.""" - return self['GEN_BArrayData'] + prop = self._get_postmorten_prop('GEN_BArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_amplc(self): """.""" - return self['GEN_CArrayData'] + prop = self._get_postmorten_prop('GEN_CArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_ampld(self): """.""" - return self['GEN_DArrayData'] + prop = self._get_postmorten_prop('GEN_DArrayData') + return self[prop] * self.CONV_NM2UM @property def mt_polyx(self): """.""" - return self['GEN_PolyXArrayCoeff-RB'] + prop = self._get_postmorten_prop('GEN_PolyXArrayCoeff-RB') + return self[prop] * self.CONV_NM2UM @mt_polyx.setter def mt_polyx(self, value): """.""" - self['GEN_PolyXArrayCoeff-SP'] = _np.array(value) + prop = self._get_postmorten_prop('GEN_PolyXArrayCoeff-SP') + self[prop] = _np.array(value) @property def mt_polyy(self): """.""" - return self['GEN_PolyYArrayCoeff-RB'] + prop = self._get_postmorten_prop('GEN_PolyYArrayCoeff-RB') + return self[prop] * self.CONV_NM2UM @mt_polyy.setter def mt_polyy(self, value): """.""" - self['GEN_PolyYArrayCoeff-SP'] = _np.array(value) + prop = self._get_postmorten_prop('GEN_PolyYArrayCoeff-SP') + self[prop] = _np.array(value) @property def mt_polysum(self): """.""" - return self['GEN_PolySUMArrayCoeff-RB'] + prop = self._get_postmorten_prop('GEN_PolySUMArrayCoeff-RB') + return self[prop] * self.CONV_NM2UM @mt_polysum.setter def mt_polysum(self, value): """.""" - self['GEN_PolySUMArrayCoeff-SP'] = _np.array(value) + prop = self._get_postmorten_prop('GEN_PolySUMArrayCoeff-SP') + self[prop] = _np.array(value) @property def mt_polyq(self): """.""" - return self['GEN_PolyQArrayCoeff-RB'] + prop = self._get_postmorten_prop('GEN_PolyQArrayCoeff-RB') + return self[prop] * self.CONV_NM2UM @mt_polyq.setter def mt_polyq(self, value): """.""" - self['GEN_PolyQArrayCoeff-SP'] = _np.array(value) + prop = self._get_postmorten_prop('GEN_PolyQArrayCoeff-SP') + self[prop] = _np.array(value) @property def mt_polyxy_enbl(self): @@ -509,22 +527,26 @@ def mt_polyq_enbl(self, val): @property def mtraw_posx(self): """Multi turn raw X array data.""" - return self['GEN_RawXArrayData'] + prop = self._get_postmorten_prop('GEN_RawXArrayData') + return self[prop] * self.CONV_NM2UM @property def mtraw_posy(self): """Multi turn raw Y array data.""" - return self['GEN_RawYArrayData'] + prop = self._get_postmorten_prop('GEN_RawYArrayData') + return self[prop] * self.CONV_NM2UM @property def mtraw_possum(self): """Multi turn raw sum array data.""" - return self['GEN_RawSUMArrayData'] + prop = self._get_postmorten_prop('GEN_RawSUMArrayData') + return self[prop] * self.CONV_NM2UM @property def mtraw_posq(self): """Multi turn raw Q array data.""" - return self['GEN_RawQArrayData'] + prop = self._get_postmorten_prop('GEN_RawQArrayData') + return self[prop] * self.CONV_NM2UM @property def sp_posx(self): @@ -589,147 +611,162 @@ def sp_arrayd(self): @property def acq_mode(self): """.""" - return self['ACQBPMMode-Sts'] + prop = self._get_postmorten_prop('ACQBPMMode-Sts') + return self[prop] * self.CONV_NM2UM @acq_mode.setter def acq_mode(self, mode): """.""" - self['ACQBPMMode-Sel'] = mode + self[self._get_postmorten_prop('ACQBPMMode-Sel')] = mode @property def acq_ctrl(self): """.""" - return self['ACQTriggerEvent-Sts'] + prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + return self[prop] * self.CONV_NM2UM @acq_ctrl.setter def acq_ctrl(self, val): """.""" - self['ACQTriggerEvent-Sel'] = val + self[self._get_postmorten_prop('ACQTriggerEvent-Sel')] = val @property def acq_status(self): """.""" - return self['ACQStatus-Sts'] + prop = self._get_postmorten_prop('ACQStatus-Sts') + return self[prop] * self.CONV_NM2UM @property def acq_channel(self): """.""" - return self['ACQChannel-Sts'] + prop = self._get_postmorten_prop('ACQChannel-Sts') + return self[prop] * self.CONV_NM2UM @acq_channel.setter def acq_channel(self, val): """.""" - self['ACQChannel-Sel'] = val + self[self._get_postmorten_prop('ACQChannel-Sel')] = val @property def acq_trigger(self): """.""" - return self['ACQTrigger-Sts'] + prop = self._get_postmorten_prop('ACQTrigger-Sts') + return self[prop] * self.CONV_NM2UM @acq_trigger.setter def acq_trigger(self, val): """.""" - self['ACQTrigger-Sel'] = val + self[self._get_postmorten_prop('ACQTrigger-Sel')] = val @property def acq_repeat(self): """.""" - return self['ACQTriggerRep-Sts'] + prop = self._get_postmorten_prop('ACQTriggerRep-Sts') + return self[prop] * self.CONV_NM2UM @acq_repeat.setter def acq_repeat(self, val): """.""" - self['ACQTriggerRep-Sel'] = val + self[self._get_postmorten_prop('ACQTriggerRep-Sel')] = val @property def acq_update_time(self): """.""" - return self['ACQUpdateTime-RB'] / 1e3 + prop = self._get_postmorten_prop('ACQUpdateTime-RB') / 1e3 + return self[prop] * self.CONV_NM2UM @acq_update_time.setter def acq_update_time(self, val): """.""" - self['ACQUpdateTime-SP'] = val * 1e3 + self[self._get_postmorten_prop('ACQUpdateTime-SP')] = val * 1e3 @property def acq_trig_datachan(self): """.""" - return self['ACQDataTrigChan-Sts'] + prop = self._get_postmorten_prop('ACQDataTrigChan-Sts') + return self[prop] * self.CONV_NM2UM @acq_trig_datachan.setter def acq_trig_datachan(self, val): """.""" - self['ACQDataTrigChan-Sel'] = val + self[self._get_postmorten_prop('ACQDataTrigChan-Sel')] = val @property def acq_trig_datasel(self): """.""" - return self['ACQTriggerDataSel-RB'] + prop = self._get_postmorten_prop('ACQTriggerDataSel-RB') + return self[prop] * self.CONV_NM2UM @acq_trig_datasel.setter def acq_trig_datasel(self, val): """.""" - self['ACQTriggerDataSel-SP'] = val + self[self._get_postmorten_prop('ACQTriggerDataSel-SP')] = val @property def acq_trig_datathres(self): """.""" - return self['ACQTriggerDataThres-RB'] + prop = self._get_postmorten_prop('ACQTriggerDataThres-RB') + return self[prop] * self.CONV_NM2UM @acq_trig_datathres.setter def acq_trig_datathres(self, val): """.""" - self['ACQTriggerDataThres-SP'] = val + self[self._get_postmorten_prop('ACQTriggerDataThres-SP')] = val @property def acq_trig_datahyst(self): """.""" - return self['ACQTriggerDataHyst-RB'] + prop = self._get_postmorten_prop('ACQTriggerDataHyst-RB') + return self[prop] * self.CONV_NM2UM @acq_trig_datahyst.setter def acq_trig_datahyst(self, val): """.""" - self['ACQTriggerDataHyst-SP'] = val + self[self._get_postmorten_prop('ACQTriggerDataHyst-SP')] = val @property def acq_trig_datapol(self): """.""" - return self['ACQTriggerDataPol-RB'] + prop = self._get_postmorten_prop('ACQTriggerDataPol-RB') + return self[prop] * self.CONV_NM2UM @acq_trig_datapol.setter def acq_trig_datapol(self, val): """.""" - self['ACQTriggerDataPol-SP'] = val + self[self._get_postmorten_prop('ACQTriggerDataPol-SP')] = val @property def acq_nrsamples_post(self): """.""" - return self['ACQSamplesPost-RB'] + prop = self._get_postmorten_prop('ACQSamplesPost-RB') + return self[prop] * self.CONV_NM2UM @acq_nrsamples_post.setter def acq_nrsamples_post(self, val): """.""" - self['ACQSamplesPost-SP'] = val + self[self._get_postmorten_prop('ACQSamplesPost-SP')] = val @property def acq_nrsamples_pre(self): """.""" - return self['ACQSamplesPre-RB'] + prop = self._get_postmorten_prop('ACQSamplesPre-RB') + return self[prop] * self.CONV_NM2UM @acq_nrsamples_pre.setter def acq_nrsamples_pre(self, val): """.""" - self['ACQSamplesPre-SP'] = val + self[self._get_postmorten_prop('ACQSamplesPre-SP')] = val @property def acq_nrshots(self): """.""" - return self['ACQShots-RB'] + prop = self._get_postmorten_prop('ACQShots-RB') + return self[prop] * self.CONV_NM2UM @acq_nrshots.setter def acq_nrshots(self, val): """.""" - self['ACQShots-SP'] = val + self[self._get_postmorten_prop('ACQShots-SP')] = val def wait_acq_finish(self, timeout=10): """Wait Acquisition to finish.""" @@ -738,8 +775,9 @@ def wait_acq_finish(self, timeout=10): _csbpm.AcqStates.Aborted, _csbpm.AcqStates.Too_Many_Samples, _csbpm.AcqStates.Too_Few_Samples, _csbpm.AcqStates.No_Memory, _csbpm.AcqStates.Acq_Overflow} + prop = self._get_postmorten_prop('ACQStatus-Sts') return self._wait( - 'ACQStatus-Sts', vals, timeout=timeout, comp=lambda x, y: x in y) + prop, vals, timeout=timeout, comp=lambda x, y: x in y) def wait_acq_start(self, timeout=10): """Wait Acquisition to start.""" @@ -747,23 +785,27 @@ def wait_acq_start(self, timeout=10): _csbpm.AcqStates.Waiting, _csbpm.AcqStates.External_Trig, _csbpm.AcqStates.Data_Trig, _csbpm.AcqStates.Software_Trig, _csbpm.AcqStates.Acquiring} + prop = self._get_postmorten_prop('ACQStatus-Sts') return self._wait( - 'ACQStatus-Sts', vals, timeout=timeout, comp=lambda x, y: x in y) + prop, vals, timeout=timeout, comp=lambda x, y: x in y) def cmd_acq_start(self): """Command Start Acquisition.""" self.acq_ctrl = _csbpm.AcqEvents.Start - return self._wait('ACQTriggerEvent-Sts', _csbpm.AcqEvents.Start) + prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + return self._wait(prop, _csbpm.AcqEvents.Start) def cmd_acq_stop(self): """Command Stop Acquisition.""" self.acq_ctrl = _csbpm.AcqEvents.Stop - return self._wait('ACQTriggerEvent-Sts', _csbpm.AcqEvents.Stop) + prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + return self._wait(prop, _csbpm.AcqEvents.Stop) def cmd_acq_abort(self): """Command Abort Acquisition.""" self.acq_ctrl = _csbpm.AcqEvents.Abort - return self._wait('ACQTriggerEvent-Sts', _csbpm.AcqEvents.Abort) + prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + return self._wait(prop, _csbpm.AcqEvents.Abort) def cmd_turn_on_switching(self): """Command Turn on Switching.""" @@ -803,6 +845,15 @@ def cmd_sync_monit(self): self.monit_sync_enbl = 0 return self._wait('Monit1TagEn-Sts', 0) + def _get_postmorten_prop(self, prop): + if not self._ispost_mortem: + return prop + if prop.startswith('GEN'): + return prop.replace('GEN', 'PM') + elif prop.startswith('ACQ'): + return prop.replace('ACQ', 'ACQ_PM') + return prop + class FamBPMs(_Devices): """.""" @@ -812,11 +863,12 @@ class FamBPMs(_Devices): class DEVICES: """.""" + SI = 'SI-Fam:DI-BPM' BO = 'BO-Fam:DI-BPM' ALL = (BO, SI) - def __init__(self, devname=None): + def __init__(self, devname=None, ispost_mortem=False): """.""" if devname is None: devname = self.DEVICES.SI @@ -826,7 +878,10 @@ def __init__(self, devname=None): devname = _PVName(devname) bpm_names = _BPMSearch.get_names( filters={'sec': devname.sec, 'dev': devname.dev}) - devs = [BPM(dev, auto_mon=False) for dev in bpm_names] + self._ispost_mortem = ispost_mortem + devs = [ + BPM(dev, auto_mon=False, ispost_mortem=ispost_mortem) + for dev in bpm_names] super().__init__(devname, devs) self._bpm_names = bpm_names From 8d443434a6b79f80d8a49700ba46890b5d418bea Mon Sep 17 00:00:00 2001 From: Fernando Date: Mon, 6 Mar 2023 16:15:00 -0300 Subject: [PATCH 19/19] DEV.BPM.MNT: Change name of hiden method. --- siriuspy/siriuspy/devices/bpm.py | 112 +++++++++++++++---------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/siriuspy/siriuspy/devices/bpm.py b/siriuspy/siriuspy/devices/bpm.py index c07c889db..336e882a8 100644 --- a/siriuspy/siriuspy/devices/bpm.py +++ b/siriuspy/siriuspy/devices/bpm.py @@ -76,7 +76,7 @@ def __init__(self, devname, auto_mon=True, ispost_mortem=False): raise ValueError(devname + ' is not a valid BPM or PBPM name.') self._ispost_mortem = ispost_mortem - properties = {self._get_postmorten_prop(p) for p in BPM._properties} + properties = {self._get_propname(p) for p in BPM._properties} if _BPMSearch.is_photon_bpm(devname): properties -= {'RFFEAtt-SP', 'RFFEAtt-RB'} @@ -401,97 +401,97 @@ def ampld(self): @property def mt_posx(self): """.""" - prop = self._get_postmorten_prop('GEN_XArrayData') + prop = self._get_propname('GEN_XArrayData') return self[prop] * self.CONV_NM2UM @property def mt_posy(self): """.""" - prop = self._get_postmorten_prop('GEN_YArrayData') + prop = self._get_propname('GEN_YArrayData') return self[prop] * self.CONV_NM2UM @property def mt_possum(self): """.""" - prop = self._get_postmorten_prop('GEN_SUMArrayData') + prop = self._get_propname('GEN_SUMArrayData') return self[prop] * self.CONV_NM2UM @property def mt_posq(self): """.""" - prop = self._get_postmorten_prop('GEN_QArrayData') + prop = self._get_propname('GEN_QArrayData') return self[prop] * self.CONV_NM2UM @property def mt_ampla(self): """.""" - prop = self._get_postmorten_prop('GEN_AArrayData') + prop = self._get_propname('GEN_AArrayData') return self[prop] * self.CONV_NM2UM @property def mt_amplb(self): """.""" - prop = self._get_postmorten_prop('GEN_BArrayData') + prop = self._get_propname('GEN_BArrayData') return self[prop] * self.CONV_NM2UM @property def mt_amplc(self): """.""" - prop = self._get_postmorten_prop('GEN_CArrayData') + prop = self._get_propname('GEN_CArrayData') return self[prop] * self.CONV_NM2UM @property def mt_ampld(self): """.""" - prop = self._get_postmorten_prop('GEN_DArrayData') + prop = self._get_propname('GEN_DArrayData') return self[prop] * self.CONV_NM2UM @property def mt_polyx(self): """.""" - prop = self._get_postmorten_prop('GEN_PolyXArrayCoeff-RB') + prop = self._get_propname('GEN_PolyXArrayCoeff-RB') return self[prop] * self.CONV_NM2UM @mt_polyx.setter def mt_polyx(self, value): """.""" - prop = self._get_postmorten_prop('GEN_PolyXArrayCoeff-SP') + prop = self._get_propname('GEN_PolyXArrayCoeff-SP') self[prop] = _np.array(value) @property def mt_polyy(self): """.""" - prop = self._get_postmorten_prop('GEN_PolyYArrayCoeff-RB') + prop = self._get_propname('GEN_PolyYArrayCoeff-RB') return self[prop] * self.CONV_NM2UM @mt_polyy.setter def mt_polyy(self, value): """.""" - prop = self._get_postmorten_prop('GEN_PolyYArrayCoeff-SP') + prop = self._get_propname('GEN_PolyYArrayCoeff-SP') self[prop] = _np.array(value) @property def mt_polysum(self): """.""" - prop = self._get_postmorten_prop('GEN_PolySUMArrayCoeff-RB') + prop = self._get_propname('GEN_PolySUMArrayCoeff-RB') return self[prop] * self.CONV_NM2UM @mt_polysum.setter def mt_polysum(self, value): """.""" - prop = self._get_postmorten_prop('GEN_PolySUMArrayCoeff-SP') + prop = self._get_propname('GEN_PolySUMArrayCoeff-SP') self[prop] = _np.array(value) @property def mt_polyq(self): """.""" - prop = self._get_postmorten_prop('GEN_PolyQArrayCoeff-RB') + prop = self._get_propname('GEN_PolyQArrayCoeff-RB') return self[prop] * self.CONV_NM2UM @mt_polyq.setter def mt_polyq(self, value): """.""" - prop = self._get_postmorten_prop('GEN_PolyQArrayCoeff-SP') + prop = self._get_propname('GEN_PolyQArrayCoeff-SP') self[prop] = _np.array(value) @property @@ -527,25 +527,25 @@ def mt_polyq_enbl(self, val): @property def mtraw_posx(self): """Multi turn raw X array data.""" - prop = self._get_postmorten_prop('GEN_RawXArrayData') + prop = self._get_propname('GEN_RawXArrayData') return self[prop] * self.CONV_NM2UM @property def mtraw_posy(self): """Multi turn raw Y array data.""" - prop = self._get_postmorten_prop('GEN_RawYArrayData') + prop = self._get_propname('GEN_RawYArrayData') return self[prop] * self.CONV_NM2UM @property def mtraw_possum(self): """Multi turn raw sum array data.""" - prop = self._get_postmorten_prop('GEN_RawSUMArrayData') + prop = self._get_propname('GEN_RawSUMArrayData') return self[prop] * self.CONV_NM2UM @property def mtraw_posq(self): """Multi turn raw Q array data.""" - prop = self._get_postmorten_prop('GEN_RawQArrayData') + prop = self._get_propname('GEN_RawQArrayData') return self[prop] * self.CONV_NM2UM @property @@ -611,162 +611,162 @@ def sp_arrayd(self): @property def acq_mode(self): """.""" - prop = self._get_postmorten_prop('ACQBPMMode-Sts') + prop = self._get_propname('ACQBPMMode-Sts') return self[prop] * self.CONV_NM2UM @acq_mode.setter def acq_mode(self, mode): """.""" - self[self._get_postmorten_prop('ACQBPMMode-Sel')] = mode + self[self._get_propname('ACQBPMMode-Sel')] = mode @property def acq_ctrl(self): """.""" - prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + prop = self._get_propname('ACQTriggerEvent-Sts') return self[prop] * self.CONV_NM2UM @acq_ctrl.setter def acq_ctrl(self, val): """.""" - self[self._get_postmorten_prop('ACQTriggerEvent-Sel')] = val + self[self._get_propname('ACQTriggerEvent-Sel')] = val @property def acq_status(self): """.""" - prop = self._get_postmorten_prop('ACQStatus-Sts') + prop = self._get_propname('ACQStatus-Sts') return self[prop] * self.CONV_NM2UM @property def acq_channel(self): """.""" - prop = self._get_postmorten_prop('ACQChannel-Sts') + prop = self._get_propname('ACQChannel-Sts') return self[prop] * self.CONV_NM2UM @acq_channel.setter def acq_channel(self, val): """.""" - self[self._get_postmorten_prop('ACQChannel-Sel')] = val + self[self._get_propname('ACQChannel-Sel')] = val @property def acq_trigger(self): """.""" - prop = self._get_postmorten_prop('ACQTrigger-Sts') + prop = self._get_propname('ACQTrigger-Sts') return self[prop] * self.CONV_NM2UM @acq_trigger.setter def acq_trigger(self, val): """.""" - self[self._get_postmorten_prop('ACQTrigger-Sel')] = val + self[self._get_propname('ACQTrigger-Sel')] = val @property def acq_repeat(self): """.""" - prop = self._get_postmorten_prop('ACQTriggerRep-Sts') + prop = self._get_propname('ACQTriggerRep-Sts') return self[prop] * self.CONV_NM2UM @acq_repeat.setter def acq_repeat(self, val): """.""" - self[self._get_postmorten_prop('ACQTriggerRep-Sel')] = val + self[self._get_propname('ACQTriggerRep-Sel')] = val @property def acq_update_time(self): """.""" - prop = self._get_postmorten_prop('ACQUpdateTime-RB') / 1e3 + prop = self._get_propname('ACQUpdateTime-RB') / 1e3 return self[prop] * self.CONV_NM2UM @acq_update_time.setter def acq_update_time(self, val): """.""" - self[self._get_postmorten_prop('ACQUpdateTime-SP')] = val * 1e3 + self[self._get_propname('ACQUpdateTime-SP')] = val * 1e3 @property def acq_trig_datachan(self): """.""" - prop = self._get_postmorten_prop('ACQDataTrigChan-Sts') + prop = self._get_propname('ACQDataTrigChan-Sts') return self[prop] * self.CONV_NM2UM @acq_trig_datachan.setter def acq_trig_datachan(self, val): """.""" - self[self._get_postmorten_prop('ACQDataTrigChan-Sel')] = val + self[self._get_propname('ACQDataTrigChan-Sel')] = val @property def acq_trig_datasel(self): """.""" - prop = self._get_postmorten_prop('ACQTriggerDataSel-RB') + prop = self._get_propname('ACQTriggerDataSel-RB') return self[prop] * self.CONV_NM2UM @acq_trig_datasel.setter def acq_trig_datasel(self, val): """.""" - self[self._get_postmorten_prop('ACQTriggerDataSel-SP')] = val + self[self._get_propname('ACQTriggerDataSel-SP')] = val @property def acq_trig_datathres(self): """.""" - prop = self._get_postmorten_prop('ACQTriggerDataThres-RB') + prop = self._get_propname('ACQTriggerDataThres-RB') return self[prop] * self.CONV_NM2UM @acq_trig_datathres.setter def acq_trig_datathres(self, val): """.""" - self[self._get_postmorten_prop('ACQTriggerDataThres-SP')] = val + self[self._get_propname('ACQTriggerDataThres-SP')] = val @property def acq_trig_datahyst(self): """.""" - prop = self._get_postmorten_prop('ACQTriggerDataHyst-RB') + prop = self._get_propname('ACQTriggerDataHyst-RB') return self[prop] * self.CONV_NM2UM @acq_trig_datahyst.setter def acq_trig_datahyst(self, val): """.""" - self[self._get_postmorten_prop('ACQTriggerDataHyst-SP')] = val + self[self._get_propname('ACQTriggerDataHyst-SP')] = val @property def acq_trig_datapol(self): """.""" - prop = self._get_postmorten_prop('ACQTriggerDataPol-RB') + prop = self._get_propname('ACQTriggerDataPol-RB') return self[prop] * self.CONV_NM2UM @acq_trig_datapol.setter def acq_trig_datapol(self, val): """.""" - self[self._get_postmorten_prop('ACQTriggerDataPol-SP')] = val + self[self._get_propname('ACQTriggerDataPol-SP')] = val @property def acq_nrsamples_post(self): """.""" - prop = self._get_postmorten_prop('ACQSamplesPost-RB') + prop = self._get_propname('ACQSamplesPost-RB') return self[prop] * self.CONV_NM2UM @acq_nrsamples_post.setter def acq_nrsamples_post(self, val): """.""" - self[self._get_postmorten_prop('ACQSamplesPost-SP')] = val + self[self._get_propname('ACQSamplesPost-SP')] = val @property def acq_nrsamples_pre(self): """.""" - prop = self._get_postmorten_prop('ACQSamplesPre-RB') + prop = self._get_propname('ACQSamplesPre-RB') return self[prop] * self.CONV_NM2UM @acq_nrsamples_pre.setter def acq_nrsamples_pre(self, val): """.""" - self[self._get_postmorten_prop('ACQSamplesPre-SP')] = val + self[self._get_propname('ACQSamplesPre-SP')] = val @property def acq_nrshots(self): """.""" - prop = self._get_postmorten_prop('ACQShots-RB') + prop = self._get_propname('ACQShots-RB') return self[prop] * self.CONV_NM2UM @acq_nrshots.setter def acq_nrshots(self, val): """.""" - self[self._get_postmorten_prop('ACQShots-SP')] = val + self[self._get_propname('ACQShots-SP')] = val def wait_acq_finish(self, timeout=10): """Wait Acquisition to finish.""" @@ -775,7 +775,7 @@ def wait_acq_finish(self, timeout=10): _csbpm.AcqStates.Aborted, _csbpm.AcqStates.Too_Many_Samples, _csbpm.AcqStates.Too_Few_Samples, _csbpm.AcqStates.No_Memory, _csbpm.AcqStates.Acq_Overflow} - prop = self._get_postmorten_prop('ACQStatus-Sts') + prop = self._get_propname('ACQStatus-Sts') return self._wait( prop, vals, timeout=timeout, comp=lambda x, y: x in y) @@ -785,26 +785,26 @@ def wait_acq_start(self, timeout=10): _csbpm.AcqStates.Waiting, _csbpm.AcqStates.External_Trig, _csbpm.AcqStates.Data_Trig, _csbpm.AcqStates.Software_Trig, _csbpm.AcqStates.Acquiring} - prop = self._get_postmorten_prop('ACQStatus-Sts') + prop = self._get_propname('ACQStatus-Sts') return self._wait( prop, vals, timeout=timeout, comp=lambda x, y: x in y) def cmd_acq_start(self): """Command Start Acquisition.""" self.acq_ctrl = _csbpm.AcqEvents.Start - prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + prop = self._get_propname('ACQTriggerEvent-Sts') return self._wait(prop, _csbpm.AcqEvents.Start) def cmd_acq_stop(self): """Command Stop Acquisition.""" self.acq_ctrl = _csbpm.AcqEvents.Stop - prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + prop = self._get_propname('ACQTriggerEvent-Sts') return self._wait(prop, _csbpm.AcqEvents.Stop) def cmd_acq_abort(self): """Command Abort Acquisition.""" self.acq_ctrl = _csbpm.AcqEvents.Abort - prop = self._get_postmorten_prop('ACQTriggerEvent-Sts') + prop = self._get_propname('ACQTriggerEvent-Sts') return self._wait(prop, _csbpm.AcqEvents.Abort) def cmd_turn_on_switching(self): @@ -845,7 +845,7 @@ def cmd_sync_monit(self): self.monit_sync_enbl = 0 return self._wait('Monit1TagEn-Sts', 0) - def _get_postmorten_prop(self, prop): + def _get_propname(self, prop): if not self._ispost_mortem: return prop if prop.startswith('GEN'):