def get_T(E='auto'): """ get transmission from current CHX attenuator settings call: get_T(E='auto') E='auto': read beamline energy from PV (currently DCM) | e.g. E=7645: manual input of energy reports Si wafer and metal foil configuration as well as transmission return transmission dependencies: calls att_conf() imports xfuncs, numpy by LW 12/10/2015 """ # attenuator setup att_conf=att_setup() Si_th=np.array(att_conf[2]) Cu_th=np.array(att_conf[1]) abs_mat=att_conf[0] if E is 'auto': #E=8000 # temporary: don't have channel access -> set E to 8000eV E=caget('XF:11IDA-OP{Mono:DCM-Ax:Energy}Mtr.RBV') ### get energy automatically with channel access print ('getting energy from global PV: E=',E,'eV (currently not implemented in test version (no channel access) -> 8000eV default)') # future: add PV name for house keeping if E> 30000 or E< 2000: raise attfuncs_Exception("error: Input argument E has to be 2000<E<30000 [eV]") else: if E<= 30000 and E>=2000: E=np.array(E) print ('manual input: E= ',E,'eV') else: raise attfuncs_Exception("error: could not convert energy argument. Input argument E has to be 2000<E<30000 [eV] or 'auto'") abs_th=np.append(Cu_th,Si_th) read_conf=np.zeros(len(abs_th)) for m in range(0,len(abs_th)): ### uncomment when chennel access and PVs available read_conf[m] = caget ('XF:11IDB-BI{Attn:%02d}Pos-Sts'%(m+1)) #read_conf[m]=caget("'XF:11IDB-ATT{slot:",str(int(m+1)),"}RBV-VALUE'") # read_conf=np.array([0,1,0,1,0,1,0,0,1]) ### just for testing!! comment/delete! sT=np.zeros(len(abs_th)) for m in range(0, len(abs_th)): sT[m]=xf.get_T(abs_mat[m],E/1000.,abs_th[m]) x=sT*read_conf;x[x==0]=1 T_tot=np.product(x) Si_ind=read_conf[len(Cu_th):len(read_conf)] Cu_ind=read_conf[0:len(Cu_th)] print ('Found:') print ('Si wafer configuration: ',Si_th*Si_ind,' Cu foil configuration: ',Cu_th*Cu_ind) print ('current Transmission at ',E, 'eV: T= ','{:.2e}'.format(T_tot)) return T_tot
def calc_T(T,E='auto', foil_mode='Si'): """ calc_T(T,E='auto',foil_mode='Si'): funtion to calculate CHX attenuator settings for a commanded transmission required arument: T: commanded tranmission (e.g. 1e-3) optional arguments: E='auto': get beamline energy from PV (currently: DCM) | E=7894: manual overwrite of energy parameter foil_mode='Si'|'mix': 'Si': calculating optimal configuration using only Si wafers (for coherence applications) | 'mix': using Si wafers and metal foils function returns dictionary of the form: {'tot_index':a,'Si_index':Si_ind,'Cu_index':Cu_ind} 'tot_index': 'binary' np.array, where '1' means attenuator 'in', '0' means attenuator 'out' 'Si_index': same as above, just for the Si wafer slots 'Cu_index': same as above, just for the metal foil slots dependencies: imports numpy and xfuncs calls att_setup() to get physical configuration of attenuator system by LW 12/09/2015 """ T=np.array(T) if E is 'auto': #E=8000 # temporary: don't have channel access -> set E to 8000eV E=caget('XF:11IDA-OP{Mono:DCM-Ax:Energy}Mtr.RBV') ### get energy automatically with channel access print ('getting energy from global PV: E=',E,'eV (currently not implemented in test version (no channel access) -> 8000eV default)') # future: add PV name for house keeping if E> 30000 or E< 2000: raise attfuncs_Exception("error: Input argument E has to be 2000<E<30000 [eV]") else: if E<= 30000 and E>=2000: E=np.array(E) print ('manual input: E= ',E,'eV') else: raise attfuncs_Exception("error: could not convert energy argument. Input argument E has to be 2000<E<30000 [eV] or 'auto'") if foil_mode is 'Si': print ('selected foil mode is "Si" -> only Si wafers will be used for attenuation') elif foil_mode is 'mix': print ('selected foil mode is "mix" -> both Si wafers and metal foils will be used for attenuation') else: raise attfuncs_Exception("error: foil_mode has to be either 'Si' or 'mix'") # attenuator setup att_conf=att_setup() Si_th=np.array(att_conf[2]) Cu_th=np.array(att_conf[1]) abs_mat=att_conf[0] if foil_mode is 'Si': Cu_th=Cu_th*0 # calculate all available absorption possibilities abs_th=np.append(Cu_th,Si_th) f=str('{:0'+str(len(abs_th))+'b}') a=np.zeros(len(abs_th)) T_tot=np.zeros(2**len(abs_th)) sT=np.zeros(len(abs_th)) for m in range(0, len(abs_th)): sT[m]=xf.get_T(abs_mat[m],E/1000,abs_th[m]) for l in range(0, 2**len(abs_th)): k=f.format(l) a=np.zeros(len(abs_th)) for h in range(0, len(abs_th)): a[h]=int(k[h]) x=sT*a;x[x==0]=1 T_tot[l]=np.product(x) # determine best attenuator configuration diff=np.abs(T_tot-T); best_T=T_tot[np.argmin(diff)] k=f.format(np.argmin(diff)) for m in range(0, len(abs_th)): a[m]=int(k[m]) Si_ind=a[len(Cu_th):len(a)] Cu_ind=a[0:len(Cu_th)] print ('*'*40) print (T, best_T) print ('*'*40) caput ('XF:11IDB-BI{Attn}Val:Trans-SP', T) #set point caput ('XF:11IDB-BI{Attn}Val:Trans-I', best_T) #the best available # some output and return value print ('requested transmission: ','{:.2e}'.format(float(T)),' closest match: ','{:.2e}'.format(best_T),' difference: ','{:.2e}'.format(best_T-T)) print ('Si wafer configuration: ',Si_th*Si_ind,' Cu foil configuration: ',Cu_th*Cu_ind) return {'tot_index':a,'Si_index':Si_ind,'Cu_index':Cu_ind}