From b80d51bef0e8a7ad37594eb349e05734e9a285d2 Mon Sep 17 00:00:00 2001 From: Giulio Gaio <giulio.gaio@elettra.eu> Date: Wed, 5 Jan 2022 17:44:57 +0100 Subject: [PATCH] Adding attribute history --- Makefile | 19 + src/CalcStats.py | 1239 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1258 insertions(+) create mode 100644 Makefile create mode 100755 src/CalcStats.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..25e6187 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +NAME = calc-stats-cli +MAIN = CalcStats.py + +DIRNAME = $(NAME:-cli=) +MODNAME = $(MAIN:.py=) +PY_FILES += $(wildcard src/*.py) + +default: bin ${PY_FILES} + @cp ${PY_FILES} bin/${DIRNAME} + @echo "#!/usr/bin/env python\nimport sys\nsys.path.append(sys.path[0]+'/${DIRNAME}')\nfrom ${MODNAME} import main\nif __name__ == '__main__':\n main()\n" > bin/${NAME} + @chmod +x bin/${NAME} bin/${DIRNAME}/${MAIN} + +bin: + @test -d $@ || mkdir -p $@/${DIRNAME} + +clean: + @rm -fr bin/ src/*~ + +.PHONY: clean diff --git a/src/CalcStats.py b/src/CalcStats.py new file mode 100755 index 0000000..a645284 --- /dev/null +++ b/src/CalcStats.py @@ -0,0 +1,1239 @@ +#!/usr/bin/python3 + +# this script calculates the instantaneous, average and peak of the booster current +# python + +# G. Gaio + +from tango import * +#import matplotlib.pyplot as plt +import numpy as np +from scipy.stats import kurtosis, skew +import time, datetime +import sys, os +import math +import argparse + +SENSOR_TAG = "Sensor" +TARGET_TAG = "Target" + +property_name_list = ['SensorConfiguration','TargetConfiguration'] +tango_states=["ON","OFF","CLOSE","OPEN","INSERT","EXTRACT","MOVING","STANDBY","FAULT","INIT","RUNNING","ALARM","DISABLE","UNKNOWN"] + +MAX_NUM_SENSORS = 120 +MAX_NUM_TARGETS = 20 + +SENSOR_TAG = "Sensor" +TARGET_TAG = "Target" + +ACQ_RUN = 0x1 +RECOV_RUN = 0x2 +STATE_ERR = 0x4 +ACQ_ERR = 0x8 +TANGO_ERR = 0x10 +SAMPLES_ERR = 0x20 +EMPTY_ERR = 0x40 + +ALL_MASK = ACQ_RUN | RECOV_RUN | STATE_ERR | ACQ_ERR | TANGO_ERR | SAMPLES_ERR | EMPTY_ERR +ERR_MASK = STATE_ERR | ACQ_ERR | TANGO_ERR | SAMPLES_ERR | EMPTY_ERR + +NAN_DBG = 0 +DATA_DBG = 0 +ERR_DBG = 0 + +HISTORY_SIZE = 1000 + +min_process_samples = 0 +process_samples = 0 + +# +# state2mask() +# Convert list of state labels into a bitmask +# +def state2mask(state_string): + device_allowed_states = state_string.split(",") + if len(device_allowed_states) == 0: + device_allowed_states.append(state_string) + allowed_indexes = [tango_states.index(x) for x in device_allowed_states ] + state_mask = 0 + for x in allowed_indexes: + state_mask = state_mask + (1 << x) + return state_mask + +# +# getOptions() +# Parse properties +# +def getOptions(args): + parser = argparse.ArgumentParser(description="Parses command.") + parser.add_argument("-dev", "--device_name", help="Tango Device Name") + parser.add_argument("-dsc", "--device_desc", help="Device description") + parser.add_argument("-es", "--enable_states", help="Enable tango states [ex: ON,OFF,STANDBY]") + parser.add_argument("-et", "--enable_targets", type=int, help="Enable target correlation mask [ex: 0xaa]") + parser.add_argument("-min", "--min_thres_val", type=float, help="Minumum threshold value") + parser.add_argument("-max", "--max_thres_val", type=float, help="Maximum threshold value") + parser.add_argument("-ltp", "--low_thres_perc", type=float, help="Low percentile threshold [0..1]") + parser.add_argument("-htp", "--high_thres_perc",type=float, help="High percentile threshold [0..1]") + parser.add_argument("-cvme", "--coeff_var_mean_exp", type=float, help="Coefficient of Variation Mean Exponent [0..1]") + parser.add_argument("-cvse", "--coeff_var_std_exp",type=float, help="Coefficient of Variation STD Exponent [0..1]") + options = parser.parse_args(args) + return options + + + +# +# getOptions() +# Parse properties and set device default configuration +# +def setOptions(seq_devname,seq_property_devname): + + seq_dev = DeviceProxy(seq_devname) + seq_property_dev = DeviceProxy(seq_property_devname) + + for property_name in property_name_list: + + # get a dictionary from the property SensorConfiguration/TargetConfiguration + device_conf_dict = seq_property_dev.get_property(property_name) + + #print('device',seq_property_dev,'property',property_name) + + idx = 1 + if property_name == 'SensorConfiguration': + name = 'Sensor'; prefix = 's' + else: + name = 'Target'; prefix = 't' + + for device in device_conf_dict[property_name]: + device_conf = getOptions(device.split(" ")) # compress a space separate string into a array used by the parse + # device settings + try: + attribute=prefix+'{:03d}_'.format(idx)+name+"Name"; seq_dev.write_attribute(attribute,device_conf.device_name) + attribute=prefix+'{:03d}_'.format(idx)+name+"Desc"; seq_dev.write_attribute(attribute,device_conf.device_desc) + attribute=prefix+'{:03d}_'.format(idx)+"EnableStates"; seq_dev.write_attribute(attribute,state2mask(device_conf.enable_states)) + attribute=prefix+'{:03d}_'.format(idx)+"EnableTargets"; seq_dev.write_attribute(attribute,device_conf.enable_targets); + attribute=prefix+'{:03d}_'.format(idx)+"MinThresVal"; seq_dev.write_attribute(attribute,device_conf.min_thres_val) + attribute=prefix+'{:03d}_'.format(idx)+"MaxThresVal"; seq_dev.write_attribute(attribute,device_conf.max_thres_val) + attribute=prefix+'{:03d}_'.format(idx)+"LowThresPerc"; seq_dev.write_attribute(attribute,device_conf.low_thres_perc) + attribute=prefix+'{:03d}_'.format(idx)+"HighThresPerc"; seq_dev.write_attribute(attribute,device_conf.high_thres_perc) + attribute=prefix+'{:03d}_'.format(idx)+"CoeffVarMeanExp"; seq_dev.write_attribute(attribute,device_conf.coeff_var_mean_exp) + attribute=prefix+'{:03d}_'.format(idx)+"CoeffVarStdExp"; seq_dev.write_attribute(attribute,device_conf.coeff_var_std_exp) + # indipendent settings + attribute=prefix+'{:03d}_'.format(idx)+"Enable"; seq_dev.write_attribute(attribute,True) + except DevFailed as df: + if ERR_DBG: + print('Error configuring ', seq_devname) + print(str(df)) + + idx = idx + 1 + + +class DeviceObj: + def __init__(self, device_name, command, index, tag): + # init variables + self.device_name = device_name + self.command = command #Sensordevice1...TargetDevice1 + self.index = index + self.tag = tag + # these variables are read from the sequencer + self.enable = True + self.enable_targets = 0xffffffff + self.enable_states = 0xffff + try: + self.device = DeviceProxy(self.device_name) + self.device.set_timeout_millis(200) + self.util = tango.Util.instance() + print(util.get_host_name()) + except DevFailed as df: + if ERR_DBG: + print('Error initializing ', self.device_name,'/',self.command) + print(str(df)) + except: + if ERR_DBG: + print('Error (generic) initializing ', self.device_name,'/',self.command) + + self.min_thres_val = -1000 + self.max_thres_val = 1000 + self.min_process_samples = 1 + self.low_thres_perc = 0.1 # 0% discards bottom values + self.high_thres_perc = 0.9 + self.coeff_var_mean_exp = 1 + self.coeff_var_std_exp = 0 + self.sample_shift = 0 + # + # these variables are calculated and set to the sequencer + # + # state bits + # bit 0: acquisition set + # bit 1: acquisition running + # bit 2: state error + # bit 3: acquisition error + # bit 4: recovery running + # + self.acq_state = 0 + self.mean = 0 + self.minmax = 0 + self.median = 0 + self.min = 0 + self.max = 0 + self.std = 0 + self.skew = 0 + self.kurt = 0 + self.tot_samples = 0 + self.valid_samples = 0 + self.corr_low = np.zeros(MAX_NUM_TARGETS) + self.corr_high = np.zeros(MAX_NUM_TARGETS) + self.corr = np.zeros(MAX_NUM_TARGETS) + self.old_lp_filter_corr = np.zeros(MAX_NUM_TARGETS) + self.lp_filter_corr = np.zeros(MAX_NUM_TARGETS) + self.lp_filter_corr_min_thres_val = np.zeros(MAX_NUM_TARGETS) + self.lp_filter_corr_max_thres_val = np.ones(MAX_NUM_TARGETS) + self.sensor_direction = np.zeros(MAX_NUM_TARGETS) # -1 better target coeff variation with low sensor values, \ + # support variables + self.target_coefvar_low = np.zeros(MAX_NUM_TARGETS) + self.target_coefvar_high = np.zeros(MAX_NUM_TARGETS) + self.last_bn_start = 0 + self.last_bn_end = 0 + self.bn_start = 0 + self.bn_end = 0 + self.bn_end = 0 + self.bn_error = 0 + self.acquisition_samples = 1 + # raw data acquired from the device + self.data = np.zeros(10) + self.sort_data = np.zeros(10) + self.sort_filt_data = np.zeros(10) + # temporary data + self.min_thres_idx = np.zeros(10) + self.max_thres_idx = np.zeros(10) + self.nan_idx = np.zeros(10) + self.zero_idx = np.zeros(10) + self.sort_data_idx = np.zeros(10) + self.min_val_tmp = -1000 + self.max_val_tmp = 1000 + + #trigger_attr_polling(self, dev, name) → None + self.polling_configured = False + + # + # DeviceObj::get_data() + # + def get_data(self, new_bn_start, new_bn_end): + + if self.enable == False: + self.acq_state &= ~ACQ_RUN + if DATA_DBG: + print('Disabled ', self.device_name,'/',command) + return + else: + self.acq_state |= ACQ_RUN + + # retune bunch number start and end + if self.last_bn_end <= new_bn_start: + bn_start = new_bn_start + bn_end = new_bn_end + else: + bn_start = self.last_bn_end + 1 + bn_end = new_bn_end + + # read device state + try: + cur_state = self.device.read_attribute('State'); + if (int(1 << cur_state.value) & self.enable_states) == 0: + self.acq_state |= STATE_ERR + if ERR_DBG: + print('State error ', self.device_name,'/',self.command) + return + else: + self.acq_state &= ~STATE_ERR + self.acq_state &= ~TANGO_ERR + + # A=np.array([1,2, 3, 4, 5]) A[2:]=array([3, 4, 5]) B=np.array([6,7]) A=np.append(A[2:],B) + # sample_shift recovers the data shift in respect the bunch number + data_tmp = np.array(self.device.command_inout(self.command,[1, int(bn_start+self.sample_shift), int(bn_end+self.sample_shift)])) + + self.data = np.append(self.data[bn_end-bn_start+1:],data_tmp) # circular buffer + + # GG plot + #if self.command == 'GetArrival': + # plt.cla() + # plt.plot(self.data) + # plt.show() + # plt.pause(0.0001) + + if DATA_DBG: + print('Acquired',self.device_name,self.command) + + self.bn_start = new_bn_start + self.bn_end = new_bn_end + self.bn_error = 0 + self.acq_state &= ~ACQ_ERR + self.acq_state &= ~RECOV_RUN + self.last_bn_start = bn_start + self.last_bn_end = bn_end + + except DevFailed as df: + self.bn_error = new_bn_end + self.acq_state |= ACQ_ERR + if ERR_DBG: + print('Error reading ', self.device_name,'/', self.command, ' bn=', int(bn_start), ' bnend=',int(bn_end)) + print(str(df)) + + # recovery data strategy, ask data once at a time, accept at maximum 5 errors + # the skip data recovery + data_tmp = np.array([]) + + if self.bn_error == new_bn_end: + + self.acq_state |= RECOV_RUN + + # get the last element of the array as the last good value + # the last valid value is used to fill the acquisition missed data + if len(self.data) > 0: + last_valid_val = self.data[-1] + else: + last_valid_val = 0 + + tango_error = 0 + consec_error = 0 + error_flag = False + + for i in range(bn_start,bn_end): + + try: + # in recovery mode get elements one by one + tmp = np.array(self.device.command_inout(self.command,[1, long(i+self.sample_shift), long(i+self.sample_shift)])) + last_valid_val = tmp + consec_error = 0 + except: + if ERR_DBG: + print('Max recovery error ', self.device_name,'/',self.command) + tango_error = tango_error + 1 + consec_error = consec_error + 1 + tmp = last_valid_val + + # if more then 10 % of errors, stop recovery + if tango_error > (bn_end - bn_start + 1) * 0.1: + error_flag = True + self.acq_state |= TANGO_ERR + self.acq_state &= ~ACQ_ERR + break + + # if more then two consecutive error, stop recovery + if consec_error > 2: + error_flag = True + self.acq_state |= ACQ_ERR + self.acq_state &= ~TANGO_ERR + break + + data_tmp = np.append(data_tmp, tmp) + + if error_flag == False: + # data recovered, append data to the object + self.data = np.append(self.data[bn_end-bn_start+1:],data_tmp) # circular buffer + self.bn_start = new_bn_start + self.bn_end = new_bn_end + # reset bn error + self.bn_error = 0 + self.acq_state &= ~TANGO_ERR + self.acq_state &= ~ACQ_ERR + + + + + # + # DeviceObj::prefix() + # + def prefix(self): + if self.tag == SENSOR_TAG: + return "s"; + elif self.tag == TARGET_TAG: + return "t"; + else: + return ""; + + # + # DeviceObj::get_configuration() + # + def get_configuration(self, buf_len, acquisition_len, val_samples_perc): + try: + attribute=self.prefix()+'{:03d}_Enable'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.enable = val.value + attribute=self.prefix()+'{:03d}_EnableStates'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.enable_states = val.value + attribute=self.prefix()+'{:03d}_EnableTargets'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.enable_targets = val.value + attribute=self.prefix()+'{:03d}_MinThresVal'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.min_thres_val = val.value + attribute=self.prefix()+'{:03d}_MaxThresVal'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.max_thres_val = val.value + attribute=self.prefix()+'{:03d}_LowThresPerc'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.low_thres_perc = val.value + attribute=self.prefix()+'{:03d}_HighThresPerc'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.high_thres_perc = val.value + attribute=self.prefix()+'{:03d}_CoeffVarMeanExp'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.coeff_var_mean_exp = val.value + attribute=self.prefix()+'{:03d}_CoeffVarStdExp'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.coeff_var_std_exp = val.value + attribute=self.prefix()+'{:03d}_SampleShift'.format(self.index+1);val = selfseq_dev.read_attribute(attribute) + self.sample_shift = val.value + + if self.tag == SENSOR_TAG: + for target in target_dev: + if target.enable == True: + if self.enable_targets & (1 << target.index): + attribute='s{:03d}_t{:03d}_CorrFiltAbs_MinThresVal'.format(self.index+1,target.index+1) + val = selfseq_dev.read_attribute(attribute) + self.lp_filter_corr_min_thres_val[target.index] = val.value + attribute='s{:03d}_t{:03d}_CorrFiltAbs_MaxThresVal'.format(self.index+1,target.index+1) + val = selfseq_dev.read_attribute(attribute) + self.lp_filter_corr_max_thres_val[target.index] = val.value + elif self.tag == TARGET_TAG: + for target in target_dev: + if target.enable == True: + if (self.enable_targets & (1 << target.index)) and (self.index < target.index): + attribute='t{:03d}_t{:03d}_CorrFiltAbs_MinThresVal'.format(self.index+1,target.index+1) + val = selfseq_dev.read_attribute(attribute) + self.lp_filter_corr_min_thres_val[target.index] = val.value + attribute='t{:03d}_t{:03d}_CorrFiltAbs_MaxThresVal'.format(self.index+1,target.index+1) + val = selfseq_dev.read_attribute(attribute) + self.lp_filter_corr_max_thres_val[target.index] = val.value + + + + if buf_len != len(self.data): + self.data = np.zeros(buf_len) + self.sort_data = np.zeros(buf_len) + self.sort_filt_data = np.zeros(buf_len) + # temporary data + self.min_thres_idx = np.zeros(buf_len) + self.max_thres_idx = np.zeros(buf_len) + self.nan_idx = np.zeros(buf_len) + self.zero_idx = np.zeros(buf_len) + self.sort_data_idx = np.zeros(buf_len) + + if acquisition_len > buf_len: + acquisition_len = buf_len + self.acquisition_samples = acquisition_len + self.min_process_samples = buf_len * val_samples_perc + + except DevFailed as df: + if ERR_DBG: + print('Configuration reading error ', self.device_name,'/',command) + print(str(df)) + except: + if ERR_DBG: + print('Configuration reading error ', self.device_name,'/',command) + + + # + # DeviceObj::set_sequencer() + # + def set_sequencer(self): + + try: + + # copy statistics to the sequencer + attribute=self.prefix()+'{:03d}_BunchNumberStart'.format(self.index+1);selfseq_dev.write_attribute(attribute,self.bn_start) + attribute=self.prefix()+'{:03d}_AcqState'.format(self.index+1);selfseq_dev.write_attribute(attribute,self.acq_state); + attribute=self.prefix()+'{:03d}_Mean'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.mean); + attribute=self.prefix()+'{:03d}_MinMax'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.minmax); + attribute=self.prefix()+'{:03d}_Min'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.min); + attribute=self.prefix()+'{:03d}_Max'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.max); + attribute=self.prefix()+'{:03d}_Median'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.median); + attribute=self.prefix()+'{:03d}_Std'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.std); + attribute=self.prefix()+'{:03d}_Skew'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.skew); + attribute=self.prefix()+'{:03d}_Kurt'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.kurt); + attribute=self.prefix()+'{:03d}_ValidSamples'.format(self.index+1);val = selfseq_dev.write_attribute(attribute,self.valid_samples); + + # History for Mean,Median,Std,Skew,Kurt,Min,Max,MinMax + # mean + attribute = self.prefix()+'{:03d}_Mean_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.mean; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.mean); selfseq_dev.write_attribute(attribute,val) + # median + attribute = self.prefix()+'{:03d}_Median_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.median; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.median); selfseq_dev.write_attribute(attribute,val) + # std + attribute = self.prefix()+'{:03d}_Std_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.std; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.std); selfseq_dev.write_attribute(attribute,val) + # skew + attribute = self.prefix()+'{:03d}_Skew_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.skew; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.skew); selfseq_dev.write_attribute(attribute,val) + # kurt + attribute = self.prefix()+'{:03d}_Kurt_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.kurt; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.kurt); selfseq_dev.write_attribute(attribute,val) + # min + attribute = self.prefix()+'{:03d}_Min_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.min; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.min); selfseq_dev.write_attribute(attribute,val) + # max + attribute = self.prefix()+'{:03d}_Max_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = val = np.roll(val, 1);val[-1] = self.max; selfseq_dev.write_attribute(attribute,val) + else: + np.append(val,self.max); selfseq_dev.write_attribute(attribute,val) + # minmax + attribute = self.prefix()+'{:03d}_MinMax_History'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.minmax; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.minmax); selfseq_dev.write_attribute(attribute,val) + + if self.tag == SENSOR_TAG: + for target in target_dev: + if target.enable == True: + if self.enable_targets & (1 << target.index): + attribute='s{:03d}_t{:03d}_Corr'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.corr[target.index]); + attribute='s{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.lp_filter_corr[target.index]); + attribute='s{:03d}_t{:03d}_CorrHigh'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.corr_high[target.index]); + attribute='s{:03d}_t{:03d}_CorrLow'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.corr_low[target.index]); + attribute='s{:03d}_t{:03d}_Direction'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.sensor_direction[target.index]); + + # History for Corr, CorrFiltAbs, CorrLow, CorrHigh + # corr + attribute = self.prefix()+'s{:03d}_t{:03d}_Corr'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.corr[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.corr[target.index]); selfseq_dev.write_attribute(attribute,val) + # corrfiltabs + attribute = self.prefix()+'s{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.lp_filter_corr[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.lp_filter_corr[target.index]); selfseq_dev.write_attribute(attribute,val) + # corrlow + attribute = self.prefix()+'s{:03d}_t{:03d}_CorrLow'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.corr_low[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.corr_low[target.index]); selfseq_dev.write_attribute(attribute,val) + # corrhigh + attribute = self.prefix()+'s{:03d}_t{:03d}_CorrHigh'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.corr_high[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.corr_high[target.index]); selfseq_dev.write_attribute(attribute,val) + + + elif self.tag == TARGET_TAG: + for target in target_dev: + if target.enable == True: + if (self.enable_targets & (1 << target.index)) and (self.index < target.index): + attribute='t{:03d}_t{:03d}_Corr'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.corr[target.index]) + attribute='t{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.lp_filter_corr[target.index]) + attribute='t{:03d}_t{:03d}_CorrHigh'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.corr_high[target.index]) + attribute='t{:03d}_t{:03d}_CorrLow'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.corr_low[target.index]) + attribute='t{:03d}_t{:03d}_Direction'.format(self.index+1,target.index+1) + selfseq_dev.write_attribute(attribute,self.sensor_direction[target.index]) + + # History for Corr, CorrFiltAbs, CorrLow, CorrHigh + # corr + attribute = self.prefix()+'t{:03d}_t{:03d}_Corr'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.corr[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.corr[target.index]); selfseq_dev.write_attribute(attribute,val) + # corrfiltabs + attribute = self.prefix()+'t{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.lp_filter_corr[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.lp_filter_corr[target.index]); selfseq_dev.write_attribute(attribute,val) + # corrlow + attribute = self.prefix()+'t{:03d}_t{:03d}_CorrLow'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.corr_low[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.corr_low[target.index]); selfseq_dev.write_attribute(attribute,val) + # corrhigh + attribute = self.prefix()+'t{:03d}_t{:03d}_CorrHigh'.format(self.index+1); val = selfseq_dev.read_attribute(attribute); val = val.value + if val.size >= HISTORY_SIZE: + val = np.roll(val, 1);val[-1] = self.corr_high[target.index]; selfseq_dev.write_attribute(attribute,val) + else: + val = np.append(val,self.corr_high[target.index]); selfseq_dev.write_attribute(attribute,val) + + + attribute=self.prefix()+'{:03d}_BunchNumberEnd'.format(self.index+1);selfseq_dev.write_attribute(attribute,self.bn_end) + + except DevFailed as df: + if ERR_DBG: + print('Setting sequencer error ', self.device_name) + print(str(df)) + except: + if ERR_DBG: + print('Setting sequencer error ', self.device_name) + + # + # DeviceObj::set_polling_attribute() + # + def set_polling_state(self): + + if (self.index >= 0): + if self.polling_configured == False: + self.polling_configured = True + self.device.set_timeout_millis(10000) + if selfseq_dev.EnablePolling == True: + print("enable polling: ", self.device_name); + + #acquisition_period = int(selfseq_dev.AcquisitionPeriod * 1000 * 10) + acquisition_period = int(0) + + # copy statistics to the sequencer + if (self.enable == True): + try: + attribute=self.prefix()+'{:03d}_AcqState'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Mean'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_MinMax'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Min'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Max'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Median'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Std'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Skew'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_Kurt'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + try: + attribute=self.prefix()+'{:03d}_ValidSamples'.format(self.index+1);selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + if self.tag == SENSOR_TAG: + for target in target_dev: + if (target.enable == True) and (self.enable == True): + if self.enable_targets & (1 << target.index): + attribute='s{:03d}_t{:03d}_Corr'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='s{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='s{:03d}_t{:03d}_CorrHigh'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='s{:03d}_t{:03d}_CorrLow'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='s{:03d}_t{:03d}_Direction'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + + elif self.tag == TARGET_TAG: + for target in target_dev: + if (target.enable == True) and (self.enable == True): + if self.enable_targets & (1 << target.index): + attribute='t{:03d}_t{:03d}_Corr'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='t{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='t{:03d}_t{:03d}_CorrHigh'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='t{:03d}_t{:03d}_CorrLow'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + attribute='t{:03d}_t{:03d}_Direction'.format(self.index+1,target.index+1) + try: + selfseq_dev.poll_attribute(attribute,acquisition_period);print('Enable poll',attribute,acquisition_period); + except: + print('Error configuring',attribute) + if selfseq_dev.DisablePolling == True: + + # copy statistics to the sequencer + attribute=self.prefix()+'{:03d}_AcqState'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Mean'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_MinMax'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Min'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Max'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Median'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Std'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Skew'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_Kurt'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute=self.prefix()+'{:03d}_ValidSamples'.format(self.index+1);selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + + if self.tag == SENSOR_TAG: + for target in target_dev: + attribute='s{:03d}_t{:03d}_Corr'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='s{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='s{:03d}_t{:03d}_CorrHigh'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='s{:03d}_t{:03d}_CorrLow'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='s{:03d}_t{:03d}_Direction'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + + elif self.tag == TARGET_TAG: + for target in target_dev: + if (self.index+1) < (target.index+1): + attribute='t{:03d}_t{:03d}_Corr'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='t{:03d}_t{:03d}_CorrFiltAbs'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='t{:03d}_t{:03d}_CorrHigh'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='t{:03d}_t{:03d}_CorrLow'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + attribute='t{:03d}_t{:03d}_Direction'.format(self.index+1,target.index+1) + selfseq_dev.stop_poll_attribute(attribute);print('Disable poll',attribute); + + + + + self.device.set_timeout_millis(1000) + + # + # DeviceObj::filter_data() + # + def filter_data(self): + + try: + + self.tot_samples = len(self.data) + + if (self.tot_samples == 0): + self.acq_state |= TANGO_ERR + + if (self.acq_state & (STATE_ERR | ACQ_ERR | TANGO_ERR | SAMPLES_ERR)) or ((self.acq_state & ACQ_RUN) == 0): + if ERR_DBG: + print('Skip filtering',self.device_name,self.command,', state',self.acq_state) + return + + # sort the array and get the indexes of the sorted array + self.sort_data = np.sort(self.data) + self.sort_data_idx = np.argsort(self.data) + + # calculate the min max + idx_min = int(math.floor(self.low_thres_perc * self.tot_samples)) + idx_max = int(math.floor(math.ceil(self.high_thres_perc * self.tot_samples)-1)) + + self.min_thres_val_tmp = self.sort_data[idx_min] + if self.min_thres_val_tmp < self.min_thres_val: + self.min_thres_val_tmp = self.min_thres_val + + self.max_thres_val_tmp = self.sort_data[idx_max] + if self.max_thres_val_tmp > self.max_thres_val: + self.max_thres_val_tmp = self.max_thres_val + + # get the indexes of the elements outside the limits + if idx_min >= 0: + # get the indexes of the elements below the minimum threshold + # np.nonzero return a tuple of two arrays: + # Ex: self.min_thres_idx=(array([0, 1]),), + # [0] return the first array + self.min_thres_idx = np.nonzero(self.data < self.min_thres_val_tmp)[0] + + if idx_max <= (self.tot_samples-1): + # get the indexes of the elements above the maximum threshold + self.max_thres_thres_idx = np.nonzero(self.data > self.max_thres_val_tmp)[0] + + # remove NaN (np.nan) + self.nan_idx = np.argwhere(np.isnan(self.sort_data)); + + # remove elements equal to 0 + self.zero_idx = np.where(self.sort_data == 0)[0] + + removed_samples_idx = np.concatenate((self.min_thres_idx, self.max_thres_thres_idx, self.nan_idx), axis=None) + self.sort_data_idx = [i for i in self.sort_data_idx if i not in removed_samples_idx] + + # [A[index] for index in B] extract the elements A with the indexex present in B + # get the array of filtered data (used to calculate statistics) + self.sort_filt_data = [self.data[index] for index in self.sort_data_idx] + + if len(self.sort_filt_data) <= self.min_process_samples: + self.acq_state |= EMPTY_ERR + else: + self.acq_state &= ~EMPTY_ERR + + except: + if ERR_DBG: + print('ERROR: filter_data(),',self.device_name) + self.acq_state |= EMPTY_ERR + return + + # + # DeviceObj::check_nan_inf_stats() + # + def check_nan_inf_stats(self,reset): + if np.isnan(self.minmax) or np.isinf(self.minmax) or reset == True: + self.minmax = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' minmax INF NAN') + if np.isnan(self.mean) or np.isinf(self.mean) or reset == True: + self.mean = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' mean INF NAN') + if np.isnan(self.min) or np.isinf(self.min) or reset == True: + self.min = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' min INF NAN') + if np.isnan(self.max) or np.isinf(self.max) or reset == True: + self.max = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' max INF NAN') + if np.isnan(self.median) or np.isinf(self.median) or reset == True: + self.median = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' median INF NAN') + if np.isnan(self.std) or np.isinf(self.std) or reset == True: + self.std = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' std INF NAN') + if np.isnan(self.skew) or np.isinf(self.skew) or reset == True: + self.skew = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' skew INF NAN') + if np.isnan(self.kurt) or np.isinf(self.kurt) or reset == True: + self.kurt = 0 + if NAN_DBG: + print(self.device_name,'/',self.command, ' kurt INF NAN') + + # + # DeviceObj::process_stats() + # + def process_stats(self): + + try: + + if (self.acq_state & ERR_MASK) or (self.acq_state & ACQ_RUN) == 0: + self.check_nan_inf_stats(True) + return; + + # get the stats + #[self.valid_samples,self.minmax,self.avg,self.std,self.skew,self.kurt] = stats.describe(self.sort_filt_data) + #self.median = self.sort_filt_data[int(len(self.valid_samplest) / 2) - 1]; + self.valid_samples = len(self.sort_filt_data) + + self.minmax = np.ptp(self.sort_filt_data) + self.mean = np.mean(self.sort_filt_data) + self.min = np.min(self.sort_filt_data) + self.max = np.max(self.sort_filt_data) + self.median = self.sort_filt_data[int(self.valid_samples / 2) - 1]; + self.std = np.std(self.sort_filt_data) + self.skew = skew(self.sort_filt_data) + self.kurt = kurtosis(self.sort_filt_data) + + if DATA_DBG: + print(self.device_name,'/',self.command, ' valid samples ', self.valid_samples) + print(self.device_name,'/',self.command, ' minmax ', self.minmax) + print(self.device_name,'/',self.command, ' mean ', self.mean) + print(self.device_name,'/',self.command, ' min ', self.min) + print(self.device_name,'/',self.command, ' max ', self.max) + print(self.device_name,'/',self.command, ' median ', self.median) + print(self.device_name,'/',self.command, ' std ', self.std) + print(self.device_name,'/',self.command, ' skew ', self.skew) + print(self.device_name,'/',self.command, ' kurt ', self.kurt) + + self.check_nan_inf_stats(False) + + except: + if ERR_DBG: + print('ERROR: process_stats(),',self.device_name) + + self.valid_samples = 0 + self.minmax = 0 + self.mean = 0 + self.min = 0 + self.max = 0 + self.median = 0 + self.std = 0 + self.skew = 0 + self.kurt = 0 + self.acq_state = self.acq_state | ERR_MASK + self.check_nan_inf_stats(True) + + + # + # DeviceObj::check_nan_inf_corr() + # + def check_nan_inf_corr(self,reset): + for dev in target_dev: + if np.isnan(self.corr[dev.index]) or np.isinf(self.corr[dev.index]) or reset == True: + self.corr[dev.index] = 0 + if NAN_DBG: + print('Correlation ',self.device_name,'/',self.command, ' ',dev.device_name,'/',dev.command,' NAN INF') + + if np.isnan(self.lp_filter_corr[dev.index]) or np.isinf(self.lp_filter_corr[dev.index]) or reset == True: + self.lp_filter_corr[dev.index] = 0 + if NAN_DBG: + print('Low Pass Filter Correlation ',self.device_name,'/',self.command, ' ',dev.device_name,'/',dev.command,' NAN INF') + + if np.isnan(self.corr_low[dev.index]) or np.isinf(self.corr_low[dev.index]) or reset == True: + self.corr_low[dev.index] = 0 + if NAN_DBG: + print('Correlation low ',self.device_name,'/',self.command, ' ',dev.device_name,'/',dev.command,' NAN INF') + + if np.isnan(self.corr_high[dev.index]) or np.isinf(self.corr_high[dev.index]) or reset == True: + self.corr_high[dev.index] = 0 + if NAN_DBG: + print('Correlation high ',self.device_name,'/',self.command, ' ',dev.device_name,'/',dev.command,' NAN INF') + + if np.isnan(self.sensor_direction[dev.index]) or np.isinf(self.sensor_direction[dev.index]) or reset == True: + self.sensor_direction[dev.index] = 0 + if NAN_DBG: + print('Sensor direction ',self.device_name,'/',self.command, ' ',dev.device_name,'/',dev.command,' NAN INF') + + def process_corr(self): + + if (self.acq_state & ERR_MASK) or (self.acq_state & ACQ_RUN) == 0: + self.check_nan_inf_corr(True) + return; + + try: + + for dev in target_dev: + + t_idx = dev.index + + do_corr = True + if (self.tag == TARGET_TAG) and (dev.tag == TARGET_TAG) and (self.index >= dev.index): + do_corr = False + + if (self.acq_state & ERR_MASK == 0) and (dev.acq_state & ERR_MASK == 0) and ((self.enable_targets & (1 << dev.index)) > 0) and do_corr: + + + # array of indexes that are both valid for the sensor and the target + valid_idx = (np.intersect1d(self.sort_data_idx, dev.sort_data_idx)) + + if len(valid_idx) > 0: + + sensor_array = self.data[valid_idx] + target_array = dev.data[valid_idx] + + # sort B and change the order of A according to B + # ZB, ZA = zip(*[(a, b) for a, b in sorted(zip(B, A))]) + sensor_array_sort,target_array_sort = zip(*[(a, b) for a, b in sorted(zip(sensor_array, target_array))]) + + # zip sensor and target, the sort will be done in respect the sensor + #zipped = list(zip(sensor_array,target_array)) + + # sort the array of tuple + #zipped.sort() + # unzip the array of tuples into two separate arrays + #sensor_sort_array,target_sort_array = map(None, *zipped) + + # calculate the correlation, numpy indexes start from 1 + self.corr[t_idx] = np.corrcoef(sensor_array,target_array)[0,1] + # low pass filter correlation + self.old_lp_filter_corr[t_idx] = self.lp_filter_corr[t_idx]; + self.lp_filter_corr[t_idx] = lp_filter * np.absolute(self.corr[t_idx]) + (1 - lp_filter) * self.old_lp_filter_corr[t_idx] + + # correlation calculated with the bottom half of sensor values + self.corr_low[t_idx] = np.corrcoef(sensor_array_sort[1:int(self.valid_samples/2)],target_array_sort[1:int(self.valid_samples/2)])[0,1] + # correlation calculated with the top half of sensor values + self.corr_high[t_idx] = np.corrcoef(sensor_array_sort[int(self.valid_samples/2):self.valid_samples],target_array_sort[int(self.valid_samples/2):self.valid_samples])[0,1] + + # coefficiet of variation calculated for the bottom half of the target values + AL = np.power(np.mean(target_array_sort[1:int(self.valid_samples/2)]),self.coeff_var_mean_exp) + BL = np.power(np.std(target_array_sort[1:int(self.valid_samples/2)]),self.coeff_var_std_exp) + + if BL != 0: + self.target_coefvar_low[t_idx] = AL / BL + else: + self.target_coefvar_low[t_idx] = 0 + + # coefficiet of variation calculated for the top half of the target values + AH = np.power(np.mean(target_array_sort[int(self.valid_samples/2):self.valid_samples]),self.coeff_var_mean_exp) + BH = np.power(np.std(target_array_sort[int(self.valid_samples/2):self.valid_samples]),self.coeff_var_std_exp) + self.target_coefvar_high[t_idx] = AH / BH + + if BH != 0: + self.target_coefvar_high[t_idx] = AH / BH + else: + self.target_coefvar_high[t_idx] = 0 + + if self.target_coefvar_low[t_idx] > self.target_coefvar_high[t_idx]: + self.sensor_direction[t_idx] = -1 + elif self.target_coefvar_low[t_idx] < self.target_coefvar_high[t_idx]: + self.sensor_direction[t_idx] = 1 + else: + self.sensor_direction[t_idx] = 0 + + if DATA_DBG: + print('Corr ', self.device_name,'/',self.command,' ',dev.device_name,'/',dev.command,' ',self.corr[t_idx]) + print('Corr lp', self.device_name,'/',self.command,' ',dev.device_name,'/',dev.command,' ',self.lp_filter_corr[t_idx]) + print('Corr low ', self.device_name,'/',self.command,' ',dev.device_name,'/',dev.command,' ',self.corr_low[t_idx]) + print('Corr high ', self.device_name,'/',self.command,' ',dev.device_name,'/',dev.command,' ',self.corr_high[t_idx]) + print('Sensor direction ', self.device_name,'/',self.command,' ',dev.device_name,'/',dev.command,' ',self.sensor_direction[t_idx]) + + else: + self.corr[t_idx] = 0 + self.lp_filter_corr[t_idx] = 0 + self.corr_low[t_idx] = 0 + self.corr_high[t_idx] = 0 + self.sensor_direction[t_idx] = 0 + + else: + self.corr[t_idx] = 0 + self.lp_filter_corr[t_idx] = 0 + self.corr_low[t_idx] = 0 + self.corr_high[t_idx] = 0 + self.sensor_direction[t_idx] = 0 + + self.check_nan_inf_corr(False) + + except: + self.acq_state = self.acq_state | ERR_MASK + self.check_nan_inf_corr(True) + return; + +# +# get_devname_cmd() +# +def get_devname_cmd(label,idx): + # sensorname: s001_SensorName + if label == 'Sensor': + attribute='s{:03d}_'.format(idx+1)+label+'Name' + else: + attribute='t{:03d}_'.format(idx+1)+label+'Name' + + + a = selfseq_dev.read_attribute(attribute).value + + if len(a) < 5: + raise NameError('Too short device name') + + return a.rpartition('/')[0],a.rpartition('/')[2]; + +#Plot a figure for debugging purposes +#plt.ion() ## Note this correction +#fig=plt.figure() + +# Initialize variables +num_sensors = 0 +num_targets = 0 +old_buffer_length = 0 +last = time.time() +acquisition_period = 1 +lp_filter = 1 + +# Connect to the bunchnuber server +bn_dev = DeviceProxy('srv-tango-srf-01:20000/f/timing/bunchnumber_f') + +# Connect to the sequencer +selfseq_dev = DeviceProxy(sys.argv[1]) + +# Load default configuration +if selfseq_dev.InitAtStartupFlag == True: + setOptions(sys.argv[1],sys.argv[2]) + +# Configure sensor devices +sensor_dev = [] +for x in range(0,MAX_NUM_SENSORS-1): + try: + devname , cmd = get_devname_cmd(SENSOR_TAG,x) + sensor_dev.append(DeviceObj(devname,cmd,x,SENSOR_TAG)) + except: + break + +# Configure target devices +target_dev = [] +for x in range(0,MAX_NUM_TARGETS-1): + try: + devname , cmd = get_devname_cmd(TARGET_TAG,x) + target_dev.append(DeviceObj(devname,cmd,x,TARGET_TAG)) + except: + break + +# Set the number of devices +selfseq_dev.NumSensors = len(sensor_dev) +selfseq_dev.NumTargets = len(target_dev) + + +while 1: + + # calculate driftless repetition period + next1 = last + acquisition_period + sleep_time = next1 - time.time(); + if (sleep_time > 0): + time.sleep(sleep_time) # it's ok to sleep negative time + last = next1 + + start_acquisition_time = time.time(); + + buffer_length = selfseq_dev.read_attribute('BufferLength').value + acquisition_length = selfseq_dev.read_attribute('AcquisitionLength').value + valid_samples_perc = selfseq_dev.read_attribute('ValidSamplesPerc').value + acquisition_period = selfseq_dev.read_attribute('AcquisitionPeriod').value + pause_flag = selfseq_dev.read_attribute('PauseFlag').value + abort_flag = selfseq_dev.read_attribute('AbortFlag').value + lp_filter = selfseq_dev.read_attribute('LPFilter').value + cur_state = selfseq_dev.read_attribute('State') + if cur_state.value != 10: # RUNNING + break + + + # exit from acquisition + if abort_flag: + break + + # pause acquisition + while pause_flag: + pause_flag = selfseq_dev.read_attribute('PauseFlag').value + time.sleep(1) + + # get sensor configuration + for dev in sensor_dev: + try: + dev.get_configuration(buffer_length, acquisition_length, valid_samples_perc) + except: + pass + # get target configuration + for dev in target_dev: + try: + dev.get_configuration(buffer_length, acquisition_length, valid_samples_perc) + except: + pass + + # calculate start - end bunchnumbers + # set the margin to two samples due the sample_shift factor that can change between -1 and 1 + bn_start = bn_dev.BunchNumber - acquisition_length - 2 + bn_end = bn_start + acquisition_length - 2 + + # acquire sensor data + for dev in sensor_dev: + try: + dev.get_data(bn_start, bn_end) + except: + pass + # acquire target data + for dev in target_dev: + try: + dev.get_data(bn_start, bn_end) + except: + pass + + end_acquisition_time = time.time(); + + for dev in sensor_dev: + dev.filter_data() + + for dev in target_dev: + dev.filter_data() + + +# for dev in sensor_dev: +# dev.set_polling_state() + +# for dev in target_dev: +# dev.set_polling_state() + + for dev in sensor_dev: + dev.process_stats() + + for dev in target_dev: + dev.process_stats() + + for dev in sensor_dev: + dev.process_corr() + + for dev in target_dev: + dev.process_corr() + + for dev in sensor_dev: + dev.set_sequencer() + + for dev in target_dev: + dev.set_sequencer() + + end_processing_time = time.time() + + acquisition_time = end_acquisition_time - start_acquisition_time + processing_time = end_processing_time - end_acquisition_time + + selfseq_dev.write_attribute('AcquisitionTime',acquisition_time) + selfseq_dev.write_attribute('ProcessingTime',processing_time) + selfseq_dev.write_attribute('IdleTime',acquisition_period - (processing_time+acquisition_time)) + + + + + + + + + + + + + + + + + + + + + + + + -- GitLab