diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/PhElAbsCross_Si.dat b/chxtools/X-ray_database/PhElAbsCross_Si.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/id_CHX_IVU20_12202014.dat b/chxtools/X-ray_database/id_CHX_IVU20_12202014.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/id_ivu20_chx.dat b/chxtools/X-ray_database/id_ivu20_chx.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/mu_Be.dat b/chxtools/X-ray_database/mu_Be.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/mu_Si.dat b/chxtools/X-ray_database/mu_Si.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/mu_Si3N4.dat b/chxtools/X-ray_database/mu_Si3N4.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Ag.dat b/chxtools/X-ray_database/n_Ag.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Al.dat b/chxtools/X-ray_database/n_Al.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Au.dat b/chxtools/X-ray_database/n_Au.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Be.dat b/chxtools/X-ray_database/n_Be.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_C.dat b/chxtools/X-ray_database/n_C.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_C_test.dat b/chxtools/X-ray_database/n_C_test.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Cu.dat b/chxtools/X-ray_database/n_Cu.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_H2O.dat b/chxtools/X-ray_database/n_H2O.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Hg.dat b/chxtools/X-ray_database/n_Hg.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Pd.dat b/chxtools/X-ray_database/n_Pd.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Pt.dat b/chxtools/X-ray_database/n_Pt.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Si.dat b/chxtools/X-ray_database/n_Si.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_Si3N4.dat b/chxtools/X-ray_database/n_Si3N4.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_SiO2.dat b/chxtools/X-ray_database/n_SiO2.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_W.dat b/chxtools/X-ray_database/n_W.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_diamond.dat b/chxtools/X-ray_database/n_diamond.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_dna.dat b/chxtools/X-ray_database/n_dna.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_ice.dat b/chxtools/X-ray_database/n_ice.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_kapton.dat b/chxtools/X-ray_database/n_kapton.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_lipid.dat b/chxtools/X-ray_database/n_lipid.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_mica.dat b/chxtools/X-ray_database/n_mica.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_nucleosome.dat b/chxtools/X-ray_database/n_nucleosome.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/n_protein.dat b/chxtools/X-ray_database/n_protein.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/rc_Ge111.dat b/chxtools/X-ray_database/rc_Ge111.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/rc_Ge220.dat b/chxtools/X-ray_database/rc_Ge220.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/rc_Si111.dat b/chxtools/X-ray_database/rc_Si111.dat old mode 100755 new mode 100644 diff --git a/chxtools/X-ray_database/rc_Si220.dat b/chxtools/X-ray_database/rc_Si220.dat old mode 100755 new mode 100644 diff --git a/chxtools/__init__.py b/chxtools/__init__.py old mode 100755 new mode 100644 diff --git a/chxtools/chx_wrapper.py b/chxtools/chx_wrapper.py old mode 100755 new mode 100644 index fc8994d..f69fe24 --- a/chxtools/chx_wrapper.py +++ b/chxtools/chx_wrapper.py @@ -3,7 +3,12 @@ by LW 03/20/2015 some wrapper functions for ophyd """ -import Tkinter, tkFileDialog +from __future__ import print_function +import tkinter, tkinter.filedialog +import time +import os +import stat +from epics import caget, caput def det_select(det): """ @@ -16,19 +21,20 @@ def det_select(det): calling sequence: det_select(det) """ try: - rm_det=ascan.user_detectors[0].name - ascan.user_detectors.remove(session_mgr[rm_det]) + rm_det = ascan.user_detectors[0].name + ascan.user_detectors.remove(session_mgr[rm_det]) ascan.default_triggers = [] ascan.default_detectors = [] - print 'removed previous default detector: ',rm_det - except: print 'list of detectors appeared to be empty...' - + print('removed previous default detector: ',rm_det) + except: + print('list of detectors appeared to be empty...') + ascan.user_detectors.append(det) # add detector - new_def_det=ascan.user_detectors[0].name - - print '' - print 'new default detector: ',new_def_det - + new_def_det=ascan.user_detectors[0].name + + print('') + print('new default detector: ',new_def_det) + def cw_ascan(mot,xmin,xmax,npoints,acqt='default',pos_ret=True): """ @@ -46,27 +52,29 @@ def cw_ascan(mot,xmin,xmax,npoints,acqt='default',pos_ret=True): ini_motpos=caget(mot.record+'.RBV') # current detector: acq_pv=session_mgr[ascan.user_detectors[0].name].pvname - + # set different exposure time for the scan, if requested: if acqt!='default': try: ini_expt=caget(acq_pv[2]) # initial exposure time session_mgr[ascan.user_detectors[0].name].acquire_time = acqt - print 'successfully set exposure time to [s]: ',acqt - except: print 'could not set exposure time to ',acqt - + print('successfully set exposure time to [s]: ',acqt) + except: + print('could not set exposure time to ',acqt) + # execute the scan ascan(mot,xmin,xmax,npoints) - + # put beamline back into initial state if pos_ret==True: caput(mot.record+'.VAL',ini_motpos) - print 'returned axes to: ',ini_motpos + print('returned axes to: ',ini_motpos) if acqt!='default': try: session_mgr[ascan.user_detectors[0].name].acquire_time = ini_expt - print 'successfully reset exposure time to [s]: ',ini_expt - except: print 'could not reset exposure time to ',ini_expt + print('successfully reset exposure time to [s]: ',ini_expt) + except: + print('could not reset exposure time to ',ini_expt) def cw_dscan(mot,mdx,pdx,npoints,acqt='default',pos_ret=True): """ @@ -79,24 +87,26 @@ def cw_dscan(mot,mdx,pdx,npoints,acqt='default',pos_ret=True): """ # current detector: acq_pv=session_mgr[ascan.user_detectors[0].name].pvname - + # set different exposure time for the scan, if requested: if acqt!='default': try: ini_expt=caget(acq_pv[2]) # initial exposure time session_mgr[ascan.user_detectors[0].name].acquire_time = acqt - print 'successfully set exposure time to [s]: ',acqt - except: print 'could not set exposure time to ',acqt - + print('successfully set exposure time to [s]: ',acqt) + except: + print('could not set exposure time to ',acqt) + # execute the scan dscan(mot,mdx,pdx,npoints) - #print 'finished scan' - + #print 'finished scan' + if acqt!='default': try: session_mgr[ascan.user_detectors[0].name].acquire_time = ini_expt - print 'successfully reset exposure time to [s]: ',ini_expt - except: print 'could not reset exposure time to ',ini_expt + print('successfully reset exposure time to [s]: ',ini_expt) + except: + print('could not reset exposure time to ',ini_expt) def cw_CCDseries(folder,filename,detector,imnum='default',startn=1,acqt='default',acqperiod='default'): """ @@ -112,41 +122,41 @@ def cw_CCDseries(folder,filename,detector,imnum='default',startn=1,acqt='default - currently saving .tiff as default calling sequence: cw_CCDseries(folder,filename,detector,imnum='default',startn=1,acqt='default',acqperiod='default') """ - import time - import Tkinter, tkFileDialog - import os, stat, sys + + import tkinter, tkinter.filedialog + # get the detector name:: detector.pvname.split('}')[0]+'}' #get folder interactively: - + if folder == 'ia': - root=Tkinter.Tk() + root=tkinter.Tk() root.withdraw() - directory=tkFileDialog.askdirectory() + directory=tkinter.filedialog.askdirectory() folder=directory # check whether target directory exists and create it, if it doesn't if not os.path.exists(folder): os.mkdir(folder) - os.chmod(folder,436) #make sure everybody can read an write + os.chmod(folder,436) #make sure everybody can read an write os.chmod(folder,stat.S_IRWXO) - print 'successfully created new directory: ',folder - - + print('successfully created new directory: ',folder) + + # put folder: r=caput(detector.pvname.split('}')[0]+'}TIFF1:FilePath', folder) # have some problem with syntax here... if r==1: - print 'changed saving directory to: ',folder - else: print 'error: could not change directory for saving data files.' + print('changed saving directory to: ',folder) + else: print('error: could not change directory for saving data files.') # put the filename: r=caput(detector.pvname.split('}')[0]+'}TIFF1:FileName', filename) # have some problem with syntax here... if r==1: - print 'filename for saving: ',filename - else: print 'error: could not change file name for saving.' + print('filename for saving: ',filename) + else: print('error: could not change file name for saving.') + - # put start number caput(detector.pvname.split('}')[0]+'}TIFF1:FileNumber',startn) - + #gather information about current camera settings acq_pv=session_mgr[ascan.user_detectors[0].name].pvname ini_acq=caget(acq_pv.split('}')[0]+'}cam1:Acquire') # initial state: started or stopped @@ -154,89 +164,90 @@ def cw_CCDseries(folder,filename,detector,imnum='default',startn=1,acqt='default ini_expt=caget(acq_pv.split('}')[0]+'}cam1:AcquireTime') # initial exposure time ini_acqperiod=caget(acq_pv.split('}')[0]+'}cam1:AcquirePeriod') # initial acquiring period ini_imnum=caget(acq_pv.split('}')[0]+'}cam1:NumImages') # initial image number - + if acqt!='default': try: caput(acq_pv.split('}')[0]+'}cam1:AcquireTime',acqt) - print 'successfully set exposure time to [s]: ',acqt - except: print 'could not set exposure time to ',acqt + print('successfully set exposure time to [s]: ',acqt) + except: print('could not set exposure time to ',acqt) # stop camara: try: caput(acq_pv.split('}')[0]+'}cam1:Acquire',0) - print 'successfully stopped camera' - except: print 'could not stop camera' + print('successfully stopped camera') + except: print('could not stop camera') # try to set image mode to multiple try: caput(acq_pv.split('}')[0]+'}cam1:ImageMode',1) - print 'successfully set ImageMode to "multiple"' - except: print 'could not set ImageMode to "multiple"' + print('successfully set ImageMode to "multiple"') + except: print('could not set ImageMode to "multiple"') if acqperiod!='default': - try: + try: caput(acq_pv.split('}')[0]+'}cam1:AcquirePeriod',acqperiod) - print 'successfully set acquiering period to: ',acqperiod - except: print 'could not set aquireing period to ',acqperiod + print('successfully set acquiering period to: ',acqperiod) + except: print('could not set aquireing period to ',acqperiod) # set number of images to be taken: if imnum!='default': try: caput(acq_pv.split('}')[0]+'}cam1:NumImages',imnum) - print 'successfully set number of images to: ',imnum - except: print 'could not set number of images to ',imnum - print 'going to start the acquisition...' + print('successfully set number of images to: ',imnum) + except: print('could not set number of images to ',imnum) + print('going to start the acquisition...') time.sleep(1) # start the acquisition!!! caput(acq_pv.split('}')[0]+'}cam1:ArrayCounter',0)#set Images acquired (image counter) to 0 - - caput(detector.pvname.split('}')[0]+'}TIFF1:AutoSave',1) # start auto save - caput(acq_pv.split('}')[0]+'}cam1:Acquire',1) # start series acquisition - + + caput(detector.pvname.split('}')[0]+'}TIFF1:AutoSave',1) # start auto save + caput(acq_pv.split('}')[0]+'}cam1:Acquire',1) # start series acquisition + counting=0 current_file=caget(detector.pvname.split('}')[0]+'}TIFF1:FullFileName_RBV',as_string=True) while counting==0: - time.sleep(.5) - if caget(acq_pv.split('}')[0]+'}cam1:ArrayCounter_RBV')==imnum: counting=1 - if caget(detector.pvname.split('}')[0]+'}TIFF1:FullFileName_RBV',as_string=True)!=current_file: - current_file=caget(detector.pvname.split('}')[0]+'}TIFF1:FullFileName_RBV',as_string=True) - print 'file written: ',current_file - time.sleep(.1) - - print 'going to stop the acquisition...' + time.sleep(.5) + if caget(acq_pv.split('}')[0]+'}cam1:ArrayCounter_RBV')==imnum: counting=1 + if caget(detector.pvname.split('}')[0]+'}TIFF1:FullFileName_RBV',as_string=True)!=current_file: + current_file=caget(detector.pvname.split('}')[0]+'}TIFF1:FullFileName_RBV',as_string=True) + print('file written: ',current_file) + time.sleep(.1) + + print('going to stop the acquisition...') time.sleep(.5) - caput(acq_pv.split('}')[0]+'}cam1:Acquire',0) # stop series acquisition (redundent...should have stopped already - caput(detector.pvname.split('}')[0]+'}TIFF1:AutoSave',0) # stop auto save - - print 'going to reset camera...' + caput(acq_pv.split('}')[0]+'}cam1:Acquire',0) # stop series acquisition (redundent...should have stopped already + caput(detector.pvname.split('}')[0]+'}TIFF1:AutoSave',0) # stop auto save + + print('going to reset camera...') #time.sleep(5) # put camera back into initial state: if acqt!='default': try: caput(acq_pv.split('}')[0]+'}cam1:AcquireTime',ini_expt) - print 'successfully reset exposure time to [s]: ',ini_expt - except: print 'could not reset exposure time to ',ini_expt + print('successfully reset exposure time to [s]: ',ini_expt) + except: + print('could not reset exposure time to ',ini_expt) try: caput(acq_pv.split('}')[0]+'}cam1:ImageMode',ini_mode) - print 'successfully reset ImageMode' - except: print 'could not reset ImageMode' + print('successfully reset ImageMode') + except: + print('could not reset ImageMode') try: caput(acq_pv.split('}')[0]+'}cam1:Acquire',ini_acq) - print 'successfully reset camera acqusition mode' - except: print 'could not reset camera acquisition mode' + print('successfully reset camera acqusition mode') + except: + print('could not reset camera acquisition mode') if acqperiod!='default': try: caput(acq_pv.split('}')[0]+'}cam1:AcquirePeriod',ini_acqperiod) - print 'successfully reset acquisition period to [s]: ',ini_acqperiod - except: print 'could not reset acquisition period to ',ini_acqperiod - if imnum!='default': + print('successfully reset acquisition period to [s]: ',ini_acqperiod) + except: + print('could not reset acquisition period to ',ini_acqperiod) + if imnum != 'default': try: caput(acq_pv.split('}')[0]+'}cam1:NumImages',ini_imnum) - print 'successfully reset image numbers to: ',ini_imnum - except: print 'could not reset image numbers to ',ini_imnum + print('successfully reset image numbers to: ',ini_imnum) + except: + print('could not reset image numbers to ',ini_imnum) time.sleep(.5) - try: - caput(acq_pv.split('}')[0]+'}cam1:Acquire',ini_acq) # restart camera if it was running before taking the series - print 'restarted camera' - except: print 'could not restart camera...' - - - - - + try: + caput(acq_pv.split('}')[0]+'}cam1:Acquire',ini_acq) # restart camera if it was running before taking the series + print('restarted camera') + except: + print('could not restart camera...') diff --git a/chxtools/ophyd_tools.py b/chxtools/ophyd_tools.py old mode 100755 new mode 100644 diff --git a/chxtools/pims_readers/__init__.py b/chxtools/pims_readers/__init__.py old mode 100755 new mode 100644 diff --git a/chxtools/pims_readers/edf.py b/chxtools/pims_readers/edf.py old mode 100755 new mode 100644 diff --git a/chxtools/pims_readers/eiger.py b/chxtools/pims_readers/eiger.py old mode 100755 new mode 100644 diff --git a/chxtools/plot.py b/chxtools/plot.py old mode 100755 new mode 100644 index 7b81aa2..1818c38 --- a/chxtools/plot.py +++ b/chxtools/plot.py @@ -22,13 +22,13 @@ def new_queue(header, queue=None): vlines = {'center_of_mass': {'color': 'red'}, 'cen': {'color': 'red', 'ls': '--'},} -hlines = {'avgy': {'color': 'blue', 'ls': '-'}, - 'ymin': {'color': 'black', 'ls': '--'}, +hlines = {'avgy': {'color': 'blue', 'ls': '-'}, + 'ymin': {'color': 'black', 'ls': '--'}, 'ymax': {'color': 'black', 'ls': '--'}, } points = {'cen': {'color': 'red', 'marker': 'o'}, - 'fwmh_left': {'color': 'red', 'marker': '<'}, + 'fwmh_left': {'color': 'red', 'marker': '<'}, 'fwhm_right': {'color': 'red', 'marker': '>'}} - + def plot1d(y, x=None, scans=None, live=True, sleep_time=1): """Plot live data and on-the-fly peak stats estimator @@ -37,8 +37,8 @@ def plot1d(y, x=None, scans=None, live=True, sleep_time=1): y : str The name of the y value to plot x : str, optional - The name of the value to plot on the x axis. If None, defaults - to the sequence number of the event (Note that this probably works, + The name of the value to plot on the x axis. If None, defaults + to the sequence number of the event (Note that this probably works, but I'm not sure as it has not been tested!) scans : list, optional List of other scan indices to plot. uses db[] syntax, so any valid @@ -108,7 +108,7 @@ def plot1d(y, x=None, scans=None, live=True, sleep_time=1): lines1[scan_id].set_data(new_x, new_y) ax1.relim(visible_only=True) ax1.legend(loc=0).draggable() - + # now deal with axis 2 try: stats = estimate(np.asarray(new_x), np.asarray(new_y)) @@ -122,7 +122,7 @@ def plot1d(y, x=None, scans=None, live=True, sleep_time=1): for stat, vals in stats.items(): if stat in points: # sometimes 'cen' comes back as one or two values. This - # try/except block is a way to do the right thing when + # try/except block is a way to do the right thing when # this happens try: vals[0] @@ -141,4 +141,3 @@ def plot1d(y, x=None, scans=None, live=True, sleep_time=1): fig.canvas.draw() fig.canvas.flush_events() ttime.sleep(sleep_time) - diff --git a/chxtools/plot_sid.py b/chxtools/plot_sid.py old mode 100755 new mode 100644 index 90b8db2..1df6755 --- a/chxtools/plot_sid.py +++ b/chxtools/plot_sid.py @@ -3,40 +3,35 @@ def plot_scan( sid = -1, x=None, y=None ): '''plot scan_ids, - Options: + Options: sid: the scan id, a number or a list x: the x-axis, a string y: the y-axis, a string ''' from databroker import DataBroker as db, get_table #get_events, get_images, import matplotlib.pyplot as plt - + if not isinstance(sid,list):sid=[sid] if x is None: x='time' if y is None: y='time' - fig,ax=plt.subplots() + fig,ax=plt.subplots() for s in sid: dat = get_table( db[s] ) - #print ('here') - if x not in dat.keys(): - print ('Wrong x input!') - print ('The available X includes: %s'%dat.keys()) + #print ('here') + if x not in dat.keys(): + print('Wrong x input!') + print('The available X includes: %s'%list(dat.keys())) break - if y not in dat.keys(): - print ('Wrong y input!') - print ('The available Y includes: %s'%dat.keys()) - + if y not in dat.keys(): + print('Wrong y input!') + print('The available Y includes: %s'%list(dat.keys())) + break #datx=dat[x] #daty=dat[y] #print (x,y) - + dat.plot( x=x,y=y,ax=ax, label='sid: %s'%s ) ax.set_ylabel( y ) - - - - - diff --git a/chxtools/pv_explorer/__init__.py b/chxtools/pv_explorer/__init__.py old mode 100755 new mode 100644 diff --git a/chxtools/pv_explorer/model.py b/chxtools/pv_explorer/model.py old mode 100755 new mode 100644 index 928a04e..95cce28 --- a/chxtools/pv_explorer/model.py +++ b/chxtools/pv_explorer/model.py @@ -37,8 +37,7 @@ def __init__(self): self._fig.set_tight_layout(True) pvs = ['pv1', 'pv2', 'pv3', 'pv4'] - for idx, (name, position) in enumerate(zip(pvs, - range(1, len(pvs)+1))): + for idx, (name, position) in enumerate(zip(pvs, range(1, len(pvs)+1))): if idx == 0: sharex = None else: diff --git a/chxtools/pv_explorer/run.py b/chxtools/pv_explorer/run.py old mode 100755 new mode 100644 diff --git a/chxtools/pv_explorer/view.enaml b/chxtools/pv_explorer/view.enaml old mode 100755 new mode 100644 diff --git a/chxtools/xfuncs.py b/chxtools/xfuncs.py old mode 100755 new mode 100644 index 5d1bd9e..f28773d --- a/chxtools/xfuncs.py +++ b/chxtools/xfuncs.py @@ -1,493 +1,493 @@ -# -*- coding: utf-8 -*- -""" -Created on Fri Apr 05 16:19:42 2013 -package contains standard x-ray related functions. Needs to be linked to database!!! -@author: lwiegart -version 0.1: included help function in all macros [12/01/2014] -version 0.1.1: added get_gap & get_Es -version 0.1.2: added get_EBragg -version 0.1.3: fixed error messages in get_gap and get_Es -version 0.1.4: added lattice spacings for Si111 and Si220 @80K (from XOP) (02/26/2015) -version 0.2.0: (this file) fixed some problems wiht arrays as inputs, e.g. in get_gap - and changed the help files to use the standard python 'help' and docstring functions; - added xfuncs_exeption class for handling xfuncs specific exeptions within python (03/23/2015) - added get_pinflux: calculates photon flux from photo current from pin diode -""" - -import pylab as pl -import numpy as np -from os import listdir -from os.path import isfile, join -import re - -# path to X-ray data files -datapath='/nfs/xf11id/shared/xfuncs/X-ray_database/' - - -def get_Lambda(E,u='SI'): - """ - calculates X-ray wavelength as a function of Energy [keV] in optional units. - Syntax: getLambda(E,u), - where E=X-ray energy; optional: u= 'A','nm','um','cm','mm','m','SI' (='m'), default in the absence of u: 'SI' - - """ - hPlank=6.62606876e-34; - cvac=2.99792458e8; - Qelectron=1.602176463e-19; - scale=1 - #l=hPlank*cvac/(E*1000*Qelectron) - l=hPlank*cvac/(E*1000*Qelectron); - if u is 'A': - scale=1e10;return l*scale # Angstroem - elif u is 'nm': - scale=1e9; return l*scale # nm - elif u is 'um': - scale=1e6; return l*scale # um - elif u is 'mm': - scale=1e3; return l*scale # mm - elif u is 'cm': - scale=1e2; return l*scale # cm - elif u is 'm' or u is 'SI': - scale=1; return l*scale - else: - print ('invalid option, type "get_Lambda(\'?\')" for available options and syntax') - - -def get_saxsQ(theta,E=8): - """ - written by LW 13/03/2008. - Calculates Q value for SAXS experiments [1/A], - input parameters: scattering angle theta [deg] (not theta/2!!!), - X-ray energy in keV (default: 8keV) function is vector compatible - calling sequence: get_saxsQ(theta,E) - """ - lam=get_Lambda(E,'A') - return 4*np.pi/lam*np.sin(np.rad2deg(theta/2)); - -def get_ac(material,E=8): - """ - by LW 10/03/2010 - function calculates the critical angle for total external reflection as a function of - the material and the X-ray energy according to ac=sqrt(2*delta) - index of refraction is a .dat file from http://henke.lbl.gov/optical_constants/getdb2.html - (energy range: 2-30keV,delete the header % lines, name the file n_material.dat) % - calling sequence: ac=get_ac(material,E) where ac: critial angle in degrees, E [keV] (default: 8keV) - type get_ac(\'materilal?\') to show list of supported materials" - """ - - #get list_of supported materials from data file directory: - xdatafiles = [ f for f in listdir(datapath) if isfile(join(datapath,f)) ] - name=[] - for i in range(0, np.size(xdatafiles)): - m=re.search('(?<=n_)\w+', xdatafiles[i]) - if m is not None: - name.append(m.group(0)) - - E=np.array(E) - if material in name: - loadn=datapath+'n_'+material+'.dat' - n=pl.loadtxt(loadn,comments='%') - if np.min(E)>=np.min(n[:,0]/1000) and np.max(E)<=np.max(n[:,0]/1000): - d=np.interp(E*1000,n[:,0],n[:,1]) - return np.degrees(np.sqrt(2*d)) - else: print ('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(n[:,0]/1000)+'==np.min(n[:,0]/1000) and np.max(E)<=np.max(n[:,0]/1000): - d=np.interp(E*1000,n[:,0],n[:,1]) - b=np.interp(E*1000,n[:,0],n[:,2]) - return d-1j*b - else: print ('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(n[:,0]/1000)+'==np.min(m[:,0]/1000) and np.max(E)<=np.max(m[:,0]/1000): - mu=np.interp(E*1000,m[:,0],m[:,1]) - return mu - else: print ('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(m[:,0]/1000))+'==np.min(n[:,0]/1000) and np.max(E)<=np.max(n[:,0]/1000): - b=np.interp(E*1000,n[:,0],n[:,2]) - mu=4*np.pi/get_Lambda(E,'um')*b; - return np.exp(-mu*l); - else: print ('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(n[:,0]/1000)+'= don't check - E=np.array(E) - lam=get_Lambda(E,'A') - if reflection in reflstr: - ind=reflstr.index(reflection) - print (reflstr[ind] +': d_{hkl}=' + "%3.4f" %dspace[ind] +'A I/I_o='+ "%3.4f" %Irel[ind]) - theta=np.degrees(np.arcsin(lam/2/dspace[ind])) - ds=[];I=[] - for l in range(0,np.size(theta)): - ds.append(dspace[ind]) - I.append(Irel[ind]) - res=np.array([theta,np.array(ds),np.array(I)]) - return res.T - elif reflection=='reflections?': - print ('List of available reflections (T=25C):') - print (reflstr ) - else: print ('error: reflection not found. Type get_Bragg("reflections?") for list of available reflections.') - else: print ('error: reflection has to be a string and E needs to be numeric. Type get_Bragg? for help') - -def get_EBragg(reflection,theta_Bragg=12.0): - """ - by LW 17/03/2010 - function returns the X-ray energy [keV] of a given crystal and Bragg reflection. - Calling sequence: EBragg=get_EBragg(reflection,theta_Bragg (default: 12deg)), thetaB(1)=Bragg angle[deg.] thetaB(2)=dhkl [A], thetaB(3)=I/Io [%]. - E: x-ray energy in keV (can be an array of energies), - reflection: string, e.g. 'Si111'. Reflections implemented from http://database.iem.ac.ru/mincryst, T=25C or calculated from XOP, e.g. for Si111 and Si220 @80K - type get_Bragg(\'reflections?\') for a list of currently availabel materials - """ - reflstr=['Si111cryo','Si220cryo','Si111', 'Si220', 'Si113', 'Si224', 'Si331', 'Si400','Ge111', 'Ge220', 'Ge113', 'Ge224', 'Ge331', 'Ge620', 'Ge531', 'Ge400', 'Ge115', 'Ge335','Ge440', 'Ge444', 'Ge333', 'C111', 'C220'] - dspace=np.array([3.13379852,1.91905183,3.13542,1.92004,1.63742,1.10854,1.24589,1.35767,3.26627,2.00018,1.70576,1.15480,1.29789,0.89451,0.95627,1.41434,1.08876,0.86274,1.00009,0.81657,1.08876,2.05929,1.26105]) - Irel=np.array([100,67.80,40.50,23.80,16.60,10.90,100,73.80,44.10,23.10,17.00,15.90,15.70,11.50,9.80,8.50,8.20,7.30,3.30,100,39.00]) - # constants needed: - hPlank=6.62606876e-34 - cvac=2.99792458e8 - Qelectron=1.602176463e-19 - - if isinstance(reflection, basestring): # and all(isinstance(E, (int, long, float, complex)) for item in [E,E]): # <- bug in python: check for E is numeric works in standalone function, but not in this package => don't check - theta_Bragg=np.array(theta_Bragg) - if reflection in reflstr: - ind=reflstr.index(reflection) - #print reflstr[ind] +': d_{hkl}=' + "%3.4f" %dspace[ind] +'A I/I_o='+ "%3.4f" %Irel[ind] - ds=[];I=[] - for l in range(0,np.size(theta_Bragg)): - ds.append(dspace[ind]) - I.append(Irel[ind]) - dspace=np.array(ds) - lam=2*dspace*np.sin(theta_Bragg/180*np.pi) - EthetaB=hPlank*cvac/(lam*Qelectron)*1e7; - return EthetaB.T - elif reflection=='reflections?': - print ('List of available reflections (T=25C):') - print (reflstr ) - else: print ('error: reflection not found. Type get_EBragg("reflections?") for list of available reflections.') - - else: print ('error: reflection has to be a string and E needs to be numeric. Type get_Bragg? for help') - - -def get_Qpixel(center=[0,0],cord=[100,100],dis=1000,ps=75,E=8): - """ - written by LW 13/03/2008. - calculates Q [1/A] value for SAXS experiments from detector position, - input parameters: position of the direct beam [x,y] in pixel numbers, pixel coordinate to calculte Q [x y], - sample detector distance in mm, pixel size [um], X-ray energy in keV. - function is vector compatible for parameters dis OR ps OR E. - calling sequence: get_Qpixel([xc,yc],[x,y],dis,ps,E) - """ - center=np.array(center);cord=np.array(cord);dis=np.array(dis);ps=np.array(ps);E=np.array(E) - lam=get_Lambda(E,'A') - xc=center[0] - yc=center[1] - x=cord[0] - y=cord[1] - ps=ps/1000 #convert pixel size to mm - #real space distance on the CCD [mm]: - u=np.sqrt(((x-xc)**2+(y-yc)**2))*ps - #wavevector transfer [1/A] - return 4*np.pi/lam*np.sin(np.arctan(u/dis/2)) - -def get_2theta(Qxy, E=8): - """ - by LW 16/06/2005 - Returns the 2theta angle [deg] as a function of the input prameters Qxy [1/A] and Energy. - Type get_2theta(Qxy [1/A], E [keV] (default: 8keV) ). This function is vector compatible. - """ - Qxy=np.array(Qxy);E=np.array(E) - lam=get_Lambda(E,'A') - return np.degrees(2*np.arcsin(Qxy/(4*np.pi)*lam)) - -def get_Gam(Qz,alpha_i=.12,E=8): - hlpstr="by sof 01/12/2003 Returns the angle Gamma (out-of-plane angle in GIXD) defined in terms of Qz, the incident angle and the energy of the X-Ray beam. Type getGam(Qz [1/A], Incident Angle [deg] (default: 0.12deg) , E[keV] (default:8keV)), This function is vector compatible. Type get_Gam(\'?\') for help" - if Qz=='?': - print (hlpstr) - else: - Qz=np.array(Qz);alpha_i=np.array(alpha_i);E=np.array(E) - lam=get_Lambda(E,'A') - return np.degrees(lam*Qz/(2*np.pi)-np.sin(alpha_i)) - -def get_Qll(Ty,alpha_i=.12,d=1000,E=8): - hlpstr="LW 26-01-2005 Function returns the parallel wavevector transfer in GI-XPCS geometry [cm^-1]. Type: get_Qll(Ty[mm],alpha_i[deg] (default: 0.12deg), d [mm] (default: 1000mm),E[keV] (default:8keV))=>qll[cm^-1]; type get_Qll(\'?\') for help" - if Ty=='?': - print ( hlpstr) - else: - Ty=np.array(Ty);alpha_i=np.array(alpha_i);E=np.array(E) - lam=get_Lambda(E,'A') - af=np.arctan((d*np.tan(np.deg2rad(alpha_i))+Ty)/d) - return (2*np.pi/lam)*(np.cos(np.deg2rad(alpha_i))-np.cos(af))*1e8 - -def get_Qxy(theta,E=8): - hlpstr="sof 26/11/2003 To return for in plane X-ray scattering the parallel wavevector transfer in 1/A. Type get_Qxy(FULL scattering angle [deg], E [keV] (default:8keV), the function returns the Q vector [1/A] in the surface plane. Angle measured in surface from specular direction! This function is vector compatible. Type get_QXY(\'?\') for help." - if theta=='?': - print (hlpstr) - else: - theta=np.array(theta);E=np.array(E) - lam=get_Lambda(E,'A') - return 4*np.pi*np.sin(np.deg2rad(theta)/2)/lam - -def get_Qz(Gam,alpha_i=.12,E=8): - hlpstr="function by sof 01/12/2003 Returns the Qz z-component of wavevector transfer defined in terms of the incident and measured angles and the energy of the X-Ray beam. Type get_Qz(Gam [deg], alpha_i [deg] (default: 0.12deg), E[keV] (default: 8keV)). This function is vector compatible. Type get_Qz(\'?\') for help." - if Gam=='?': - print (hlpstr) - else: - E=np.array(E);Gam=np.deg2rad(np.array(Gam));alpha_i=np.deg2rad(np.array(alpha_i)) - lam=get_Lambda(E,'A') - return 2*np.pi*(np.sin(Gam)+np.sin(alpha_i))/lam - -def ch2deg(chn,channel_per_degree=100,chOff=0): - """ - LW 08-07-2005 - function converts the PSD channel (chn) into angles [deg], - needed are the calibration parameters channels/deg (channel_per_degree) - and the channel number of the direct beam (chOff). - Calling sequence: ch2deg(chan,channel_per_degree (default: 100),chOff (default=0) -> corresponding angle [deg]. - Function is vector compatible. - """ - chn=np.array(chn);channel_per_degree=np.array(channel_per_degree);chOff=np.array(chOff) - return (chn-chOff)/channel_per_degree - -def get_Vineyard(Qz,E=8,ra0=1): - """ - by LW 20/07/2006 - function calculates the Vineyard (transmission) Function for a given (range) of Qz(s) - and given X-ray energy and scattering length density ra0 of the subphase media. - Type: getVineyard(Qz [A], E [keV] (default: 8keV), ra0 [SI] (default: 1 ). - """ - lam=get_Lambda(E,'A') - Qc=4*np.pi*np.sin(np.sqrt(np.pi*ra0)*lam/np.pi)/lam - rx=Qz/Qc - V=np.ones(np.size(Qz)) - for i in range(0,np.size(Qz)): - if rx[i]<=1: - V[i]=2*rx[i] - else: V[i]=2*rx[i]/(rx[i]+np.sqrt(rx[i]**2-1)) - return V - -def get_gap(E,harmonic=3,ID='CHX_IVU20_12202014'): - """ - by LW 12/03/2014, function calculates the undulator gap for a requested energy - and harmonic based on magnetic measurement data in the database - type get_gap(E [kev], harmonic [integer] (default=3), id (default+'CHX_IVU20_12202014')); - E can be an array of energies. Type get_gap\"ID?\") for a list of available magnetic datasets. - """ - #get list_of available magnetic measurements from data file directory: - xdatafiles = [ f for f in listdir(datapath) if isfile(join(datapath,f)) ] - name=[] - for i in range(0, np.size(xdatafiles)): - m=re.search('(?<=id_)\w+', xdatafiles[i]) - if m is not None: - name.append(m.group(0)) - - if E=='ID?': - print ('list of available magnetic measurements (based on data files in directory '+datapath+':') - print (name) - else: - E=np.array(E)*1.0 - harm_check(harmonic) - if ID in name: - loadn=datapath+'id_'+ID+'.dat' - magdat=pl.loadtxt(loadn,comments='%') - #harmonic=harmonic*1.0 - if np.min(E/harmonic)>=np.min(magdat[:,2]) and np.max(E/harmonic)<=np.max(magdat[:,2]): - gap=np.interp(E/harmonic,magdat[:,2],magdat[:,0]) - return gap - # this else should be a warning only and should return NaN - else: raise xfuncs_Exception ('error: energy '+"%3.4f" %E +'[keV] out of range for requested harmonic number, gap limit: ('+"%3.4f" % np.min(magdat[:,0])+'==np.min(magdat[:,0]) and np.max(gap)<=np.max(magdat[:,0]): - Es=np.interp(gap,magdat[:,0],magdat[:,2]) - Eharmonics=np.array([harmonic,harmonic*Es]) - return Eharmonics.T - else: print ('error: gap '+"%3.4f" % gap +'[mm] out of range for gap ('+"%3.4f" % np.min(magdat[:,0])+'= PhElAbsCross_si.dat in database - assumes Silicon as material as other materials would be pretty exotic - calling sequence: get_pinflux(current,Energy,thickness=300) - current: current [A] - Energy: X-ray energy [keV] - thickness: Si diode thickness [um] - """ - # some conversions and contstants: - rho_Si=2.329 # density of Si in g/cm^3!!! - epsilon=3.66 # energy for creation of electron-hole pair in Si [eV] - thickness=thickness/1.0E4 #conversion to cm - # read datafile with scattering cross section: - loadn=datapath+'PhElAbsCross_Si.dat' - crossdat=pl.loadtxt(loadn,comments='%') - # check for energy range: - xmin=min(crossdat[:,0])*1E3 - xmax=max(crossdat[:,0])*1E3 - Energy=np.array(Energy)*1.0 - current=np.array(current)*1.0 - if np.max(Energy) > xmax or np.min(Energy) =1 (number of undulator harmonics) - calling sequence: harm_check(harm_n), where harm_n is a single value or list of values - function raises an exception is harm_n does contain values other than integers >=1 - """ - state=True - - if np.all(np.array(harm_n)>=1)!=True: - raise xfuncs_Exception("Type Error: Harmonic numbers need to be >=1!") - - try: - list(harm_n) # b is the list to be checked - for i in list(harm_n): - #print isinstance(i,int) - state=state*isinstance(i,int) - except: # check for b being a single integer - try: - state=state*isinstance(harm_n, int) - #print isinstance(harm_n, int) - except: pass - - if state !=True: - raise xfuncs_Exception("Type Error: Harmonic numbers need to be integers >=1!") +# -*- coding: utf-8 -*- +""" +Created on Fri Apr 05 16:19:42 2013 +package contains standard x-ray related functions. Needs to be linked to database!!! +@author: lwiegart +version 0.1: included help function in all macros [12/01/2014] +version 0.1.1: added get_gap & get_Es +version 0.1.2: added get_EBragg +version 0.1.3: fixed error messages in get_gap and get_Es +version 0.1.4: added lattice spacings for Si111 and Si220 @80K (from XOP) (02/26/2015) +version 0.2.0: (this file) fixed some problems wiht arrays as inputs, e.g. in get_gap + and changed the help files to use the standard python 'help' and docstring functions; + added xfuncs_exeption class for handling xfuncs specific exeptions within python (03/23/2015) + added get_pinflux: calculates photon flux from photo current from pin diode +""" + +import pylab as pl +import numpy as np +from os import listdir +from os.path import isfile, join +import re + +# path to X-ray data files +datapath='/nfs/xf11id/shared/xfuncs/X-ray_database/' + + +def get_Lambda(E,u='SI'): + """ + calculates X-ray wavelength as a function of Energy [keV] in optional units. + Syntax: getLambda(E,u), + where E=X-ray energy; optional: u= 'A','nm','um','cm','mm','m','SI' (='m'), default in the absence of u: 'SI' + + """ + hPlank=6.62606876e-34; + cvac=2.99792458e8; + Qelectron=1.602176463e-19; + scale=1 + #l=hPlank*cvac/(E*1000*Qelectron) + l=hPlank*cvac/(E*1000*Qelectron); + if u is 'A': + scale=1e10;return l*scale # Angstroem + elif u is 'nm': + scale=1e9; return l*scale # nm + elif u is 'um': + scale=1e6; return l*scale # um + elif u is 'mm': + scale=1e3; return l*scale # mm + elif u is 'cm': + scale=1e2; return l*scale # cm + elif u is 'm' or u is 'SI': + scale=1; return l*scale + else: + print ('invalid option, type "get_Lambda(\'?\')" for available options and syntax') + + +def get_saxsQ(theta,E=8): + """ + written by LW 13/03/2008. + Calculates Q value for SAXS experiments [1/A], + input parameters: scattering angle theta [deg] (not theta/2!!!), + X-ray energy in keV (default: 8keV) function is vector compatible + calling sequence: get_saxsQ(theta,E) + """ + lam=get_Lambda(E,'A') + return 4*np.pi/lam*np.sin(np.rad2deg(theta/2)); + +def get_ac(material,E=8): + """ + by LW 10/03/2010 + function calculates the critical angle for total external reflection as a function of + the material and the X-ray energy according to ac=sqrt(2*delta) + index of refraction is a .dat file from http://henke.lbl.gov/optical_constants/getdb2.html + (energy range: 2-30keV,delete the header % lines, name the file n_material.dat) % + calling sequence: ac=get_ac(material,E) where ac: critial angle in degrees, E [keV] (default: 8keV) + type get_ac(\'materilal?\') to show list of supported materials" + """ + + #get list_of supported materials from data file directory: + xdatafiles = [ f for f in listdir(datapath) if isfile(join(datapath,f)) ] + name=[] + for i in range(0, np.size(xdatafiles)): + m=re.search('(?<=n_)\w+', xdatafiles[i]) + if m is not None: + name.append(m.group(0)) + + E=np.array(E) + if material in name: + loadn=datapath+'n_'+material+'.dat' + n=pl.loadtxt(loadn,comments='%') + if np.min(E)>=np.min(n[:,0]/1000) and np.max(E)<=np.max(n[:,0]/1000): + d=np.interp(E*1000,n[:,0],n[:,1]) + return np.degrees(np.sqrt(2*d)) + else: print(('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(n[:,0]/1000)+'==np.min(n[:,0]/1000) and np.max(E)<=np.max(n[:,0]/1000): + d=np.interp(E*1000,n[:,0],n[:,1]) + b=np.interp(E*1000,n[:,0],n[:,2]) + return d-1j*b + else: print(('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(n[:,0]/1000)+'==np.min(m[:,0]/1000) and np.max(E)<=np.max(m[:,0]/1000): + mu=np.interp(E*1000,m[:,0],m[:,1]) + return mu + else: print(('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(m[:,0]/1000))+'==np.min(n[:,0]/1000) and np.max(E)<=np.max(n[:,0]/1000): + b=np.interp(E*1000,n[:,0],n[:,2]) + mu=4*np.pi/get_Lambda(E,'um')*b; + return np.exp(-mu*l); + else: print(('error: energy '+"%3.4f" %E +'[keV] out of range ('+"%3.4f" % np.min(n[:,0]/1000)+'= don't check + E=np.array(E) + lam=get_Lambda(E,'A') + if reflection in reflstr: + ind=reflstr.index(reflection) + print((reflstr[ind] +': d_{hkl}=' + "%3.4f" %dspace[ind] +'A I/I_o='+ "%3.4f" %Irel[ind])) + theta=np.degrees(np.arcsin(lam/2/dspace[ind])) + ds=[];I=[] + for l in range(0,np.size(theta)): + ds.append(dspace[ind]) + I.append(Irel[ind]) + res=np.array([theta,np.array(ds),np.array(I)]) + return res.T + elif reflection=='reflections?': + print ('List of available reflections (T=25C):') + print (reflstr ) + else: print ('error: reflection not found. Type get_Bragg("reflections?") for list of available reflections.') + else: print ('error: reflection has to be a string and E needs to be numeric. Type get_Bragg? for help') + +def get_EBragg(reflection,theta_Bragg=12.0): + """ + by LW 17/03/2010 + function returns the X-ray energy [keV] of a given crystal and Bragg reflection. + Calling sequence: EBragg=get_EBragg(reflection,theta_Bragg (default: 12deg)), thetaB(1)=Bragg angle[deg.] thetaB(2)=dhkl [A], thetaB(3)=I/Io [%]. + E: x-ray energy in keV (can be an array of energies), + reflection: string, e.g. 'Si111'. Reflections implemented from http://database.iem.ac.ru/mincryst, T=25C or calculated from XOP, e.g. for Si111 and Si220 @80K + type get_Bragg(\'reflections?\') for a list of currently availabel materials + """ + reflstr=['Si111cryo','Si220cryo','Si111', 'Si220', 'Si113', 'Si224', 'Si331', 'Si400','Ge111', 'Ge220', 'Ge113', 'Ge224', 'Ge331', 'Ge620', 'Ge531', 'Ge400', 'Ge115', 'Ge335','Ge440', 'Ge444', 'Ge333', 'C111', 'C220'] + dspace=np.array([3.13379852,1.91905183,3.13542,1.92004,1.63742,1.10854,1.24589,1.35767,3.26627,2.00018,1.70576,1.15480,1.29789,0.89451,0.95627,1.41434,1.08876,0.86274,1.00009,0.81657,1.08876,2.05929,1.26105]) + Irel=np.array([100,67.80,40.50,23.80,16.60,10.90,100,73.80,44.10,23.10,17.00,15.90,15.70,11.50,9.80,8.50,8.20,7.30,3.30,100,39.00]) + # constants needed: + hPlank=6.62606876e-34 + cvac=2.99792458e8 + Qelectron=1.602176463e-19 + + if isinstance(reflection, str): # and all(isinstance(E, (int, long, float, complex)) for item in [E,E]): # <- bug in python: check for E is numeric works in standalone function, but not in this package => don't check + theta_Bragg=np.array(theta_Bragg) + if reflection in reflstr: + ind=reflstr.index(reflection) + #print reflstr[ind] +': d_{hkl}=' + "%3.4f" %dspace[ind] +'A I/I_o='+ "%3.4f" %Irel[ind] + ds=[];I=[] + for l in range(0,np.size(theta_Bragg)): + ds.append(dspace[ind]) + I.append(Irel[ind]) + dspace=np.array(ds) + lam=2*dspace*np.sin(theta_Bragg/180*np.pi) + EthetaB=hPlank*cvac/(lam*Qelectron)*1e7; + return EthetaB.T + elif reflection=='reflections?': + print ('List of available reflections (T=25C):') + print (reflstr ) + else: print ('error: reflection not found. Type get_EBragg("reflections?") for list of available reflections.') + + else: print ('error: reflection has to be a string and E needs to be numeric. Type get_Bragg? for help') + + +def get_Qpixel(center=[0,0],cord=[100,100],dis=1000,ps=75,E=8): + """ + written by LW 13/03/2008. + calculates Q [1/A] value for SAXS experiments from detector position, + input parameters: position of the direct beam [x,y] in pixel numbers, pixel coordinate to calculte Q [x y], + sample detector distance in mm, pixel size [um], X-ray energy in keV. + function is vector compatible for parameters dis OR ps OR E. + calling sequence: get_Qpixel([xc,yc],[x,y],dis,ps,E) + """ + center=np.array(center);cord=np.array(cord);dis=np.array(dis);ps=np.array(ps);E=np.array(E) + lam=get_Lambda(E,'A') + xc=center[0] + yc=center[1] + x=cord[0] + y=cord[1] + ps=ps/1000 #convert pixel size to mm + #real space distance on the CCD [mm]: + u=np.sqrt(((x-xc)**2+(y-yc)**2))*ps + #wavevector transfer [1/A] + return 4*np.pi/lam*np.sin(np.arctan(u/dis/2)) + +def get_2theta(Qxy, E=8): + """ + by LW 16/06/2005 + Returns the 2theta angle [deg] as a function of the input prameters Qxy [1/A] and Energy. + Type get_2theta(Qxy [1/A], E [keV] (default: 8keV) ). This function is vector compatible. + """ + Qxy=np.array(Qxy);E=np.array(E) + lam=get_Lambda(E,'A') + return np.degrees(2*np.arcsin(Qxy/(4*np.pi)*lam)) + +def get_Gam(Qz,alpha_i=.12,E=8): + hlpstr="by sof 01/12/2003 Returns the angle Gamma (out-of-plane angle in GIXD) defined in terms of Qz, the incident angle and the energy of the X-Ray beam. Type getGam(Qz [1/A], Incident Angle [deg] (default: 0.12deg) , E[keV] (default:8keV)), This function is vector compatible. Type get_Gam(\'?\') for help" + if Qz=='?': + print (hlpstr) + else: + Qz=np.array(Qz);alpha_i=np.array(alpha_i);E=np.array(E) + lam=get_Lambda(E,'A') + return np.degrees(lam*Qz/(2*np.pi)-np.sin(alpha_i)) + +def get_Qll(Ty,alpha_i=.12,d=1000,E=8): + hlpstr="LW 26-01-2005 Function returns the parallel wavevector transfer in GI-XPCS geometry [cm^-1]. Type: get_Qll(Ty[mm],alpha_i[deg] (default: 0.12deg), d [mm] (default: 1000mm),E[keV] (default:8keV))=>qll[cm^-1]; type get_Qll(\'?\') for help" + if Ty=='?': + print ( hlpstr) + else: + Ty=np.array(Ty);alpha_i=np.array(alpha_i);E=np.array(E) + lam=get_Lambda(E,'A') + af=np.arctan((d*np.tan(np.deg2rad(alpha_i))+Ty)/d) + return (2*np.pi/lam)*(np.cos(np.deg2rad(alpha_i))-np.cos(af))*1e8 + +def get_Qxy(theta,E=8): + hlpstr="sof 26/11/2003 To return for in plane X-ray scattering the parallel wavevector transfer in 1/A. Type get_Qxy(FULL scattering angle [deg], E [keV] (default:8keV), the function returns the Q vector [1/A] in the surface plane. Angle measured in surface from specular direction! This function is vector compatible. Type get_QXY(\'?\') for help." + if theta=='?': + print (hlpstr) + else: + theta=np.array(theta);E=np.array(E) + lam=get_Lambda(E,'A') + return 4*np.pi*np.sin(np.deg2rad(theta)/2)/lam + +def get_Qz(Gam,alpha_i=.12,E=8): + hlpstr="function by sof 01/12/2003 Returns the Qz z-component of wavevector transfer defined in terms of the incident and measured angles and the energy of the X-Ray beam. Type get_Qz(Gam [deg], alpha_i [deg] (default: 0.12deg), E[keV] (default: 8keV)). This function is vector compatible. Type get_Qz(\'?\') for help." + if Gam=='?': + print (hlpstr) + else: + E=np.array(E);Gam=np.deg2rad(np.array(Gam));alpha_i=np.deg2rad(np.array(alpha_i)) + lam=get_Lambda(E,'A') + return 2*np.pi*(np.sin(Gam)+np.sin(alpha_i))/lam + +def ch2deg(chn,channel_per_degree=100,chOff=0): + """ + LW 08-07-2005 + function converts the PSD channel (chn) into angles [deg], + needed are the calibration parameters channels/deg (channel_per_degree) + and the channel number of the direct beam (chOff). + Calling sequence: ch2deg(chan,channel_per_degree (default: 100),chOff (default=0) -> corresponding angle [deg]. + Function is vector compatible. + """ + chn=np.array(chn);channel_per_degree=np.array(channel_per_degree);chOff=np.array(chOff) + return (chn-chOff)/channel_per_degree + +def get_Vineyard(Qz,E=8,ra0=1): + """ + by LW 20/07/2006 + function calculates the Vineyard (transmission) Function for a given (range) of Qz(s) + and given X-ray energy and scattering length density ra0 of the subphase media. + Type: getVineyard(Qz [A], E [keV] (default: 8keV), ra0 [SI] (default: 1 ). + """ + lam=get_Lambda(E,'A') + Qc=4*np.pi*np.sin(np.sqrt(np.pi*ra0)*lam/np.pi)/lam + rx=Qz/Qc + V=np.ones(np.size(Qz)) + for i in range(0,np.size(Qz)): + if rx[i]<=1: + V[i]=2*rx[i] + else: V[i]=2*rx[i]/(rx[i]+np.sqrt(rx[i]**2-1)) + return V + +def get_gap(E,harmonic=3,ID='CHX_IVU20_12202014'): + """ + by LW 12/03/2014, function calculates the undulator gap for a requested energy + and harmonic based on magnetic measurement data in the database + type get_gap(E [kev], harmonic [integer] (default=3), id (default+'CHX_IVU20_12202014')); + E can be an array of energies. Type get_gap\"ID?\") for a list of available magnetic datasets. + """ + #get list_of available magnetic measurements from data file directory: + xdatafiles = [ f for f in listdir(datapath) if isfile(join(datapath,f)) ] + name=[] + for i in range(0, np.size(xdatafiles)): + m=re.search('(?<=id_)\w+', xdatafiles[i]) + if m is not None: + name.append(m.group(0)) + + if E=='ID?': + print(('list of available magnetic measurements (based on data files in directory '+datapath+':')) + print (name) + else: + E=np.array(E)*1.0 + harm_check(harmonic) + if ID in name: + loadn=datapath+'id_'+ID+'.dat' + magdat=pl.loadtxt(loadn,comments='%') + #harmonic=harmonic*1.0 + if np.min(E/harmonic)>=np.min(magdat[:,2]) and np.max(E/harmonic)<=np.max(magdat[:,2]): + gap=np.interp(E/harmonic,magdat[:,2],magdat[:,0]) + return gap + # this else should be a warning only and should return NaN + else: raise xfuncs_Exception ('error: energy '+"%3.4f" %E +'[keV] out of range for requested harmonic number, gap limit: ('+"%3.4f" % np.min(magdat[:,0])+'==np.min(magdat[:,0]) and np.max(gap)<=np.max(magdat[:,0]): + Es=np.interp(gap,magdat[:,0],magdat[:,2]) + Eharmonics=np.array([harmonic,harmonic*Es]) + return Eharmonics.T + else: print(('error: gap '+"%3.4f" % gap +'[mm] out of range for gap ('+"%3.4f" % np.min(magdat[:,0])+'= PhElAbsCross_si.dat in database + assumes Silicon as material as other materials would be pretty exotic + calling sequence: get_pinflux(current,Energy,thickness=300) + current: current [A] + Energy: X-ray energy [keV] + thickness: Si diode thickness [um] + """ + # some conversions and contstants: + rho_Si=2.329 # density of Si in g/cm^3!!! + epsilon=3.66 # energy for creation of electron-hole pair in Si [eV] + thickness=thickness/1.0E4 #conversion to cm + # read datafile with scattering cross section: + loadn=datapath+'PhElAbsCross_Si.dat' + crossdat=pl.loadtxt(loadn,comments='%') + # check for energy range: + xmin=min(crossdat[:,0])*1E3 + xmax=max(crossdat[:,0])*1E3 + Energy=np.array(Energy)*1.0 + current=np.array(current)*1.0 + if np.max(Energy) > xmax or np.min(Energy) =1 (number of undulator harmonics) + calling sequence: harm_check(harm_n), where harm_n is a single value or list of values + function raises an exception is harm_n does contain values other than integers >=1 + """ + state=True + + if np.all(np.array(harm_n)>=1)!=True: + raise xfuncs_Exception("Type Error: Harmonic numbers need to be >=1!") + + try: + list(harm_n) # b is the list to be checked + for i in list(harm_n): + #print isinstance(i,int) + state=state*isinstance(i,int) + except: # check for b being a single integer + try: + state=state*isinstance(harm_n, int) + #print isinstance(harm_n, int) + except: pass + + if state !=True: + raise xfuncs_Exception("Type Error: Harmonic numbers need to be integers >=1!") diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh old mode 100755 new mode 100644 diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml old mode 100755 new mode 100644 diff --git a/pyXPCS/Bfiber_4871eV_Apr10.py b/pyXPCS/Bfiber_4871eV_Apr10.py old mode 100755 new mode 100644 diff --git a/pyXPCS/Bfiber_4871eV_waterfall.png b/pyXPCS/Bfiber_4871eV_waterfall.png old mode 100755 new mode 100644 diff --git a/pyXPCS/Bfiber_7230_init.py b/pyXPCS/Bfiber_7230_init.py old mode 100755 new mode 100644 diff --git a/pyXPCS/Init_for_Bfiber.py b/pyXPCS/Init_for_Bfiber.py old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/LICENSE b/pyXPCS/ModestImage-0.1/LICENSE old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/MANIFEST.in b/pyXPCS/ModestImage-0.1/MANIFEST.in old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/PKG-INFO b/pyXPCS/ModestImage-0.1/PKG-INFO old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/README.md b/pyXPCS/ModestImage-0.1/README.md old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/modest_image/__init__.py b/pyXPCS/ModestImage-0.1/modest_image/__init__.py old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/modest_image/modest_image.py b/pyXPCS/ModestImage-0.1/modest_image/modest_image.py old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/setup.cfg b/pyXPCS/ModestImage-0.1/setup.cfg old mode 100755 new mode 100644 diff --git a/pyXPCS/ModestImage-0.1/setup.py b/pyXPCS/ModestImage-0.1/setup.py old mode 100755 new mode 100644 diff --git a/pyXPCS/Untitled.ipynb b/pyXPCS/Untitled.ipynb old mode 100755 new mode 100644 diff --git a/pyXPCS/XPCS_Code_0407.py b/pyXPCS/XPCS_Code_0407.py old mode 100755 new mode 100644 diff --git a/pyXPCS/__init__.py b/pyXPCS/__init__.py old mode 100755 new mode 100644 diff --git a/pyXPCS/img_process.py b/pyXPCS/img_process.py old mode 100755 new mode 100644 diff --git a/pyXPCS/mask.npy b/pyXPCS/mask.npy old mode 100755 new mode 100644 diff --git a/pyXPCS/pipeline.py b/pyXPCS/pipeline.py old mode 100755 new mode 100644 diff --git a/pyXPCS/setupQ.py b/pyXPCS/setupQ.py old mode 100755 new mode 100644 diff --git a/pyXPCS/tests/__init__.py b/pyXPCS/tests/__init__.py old mode 100755 new mode 100644 diff --git a/pyXPCS/tests/test_legacy.py b/pyXPCS/tests/test_legacy.py old mode 100755 new mode 100644 diff --git a/pyXPCS/tests/test_waterfall.py b/pyXPCS/tests/test_waterfall.py old mode 100755 new mode 100644 diff --git a/pyXPCS/waterfall.py b/pyXPCS/waterfall.py old mode 100755 new mode 100644 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index d0583e5..230f320 --- a/setup.py +++ b/setup.py @@ -1,10 +1,6 @@ #!/usr/bin/env python from __future__ import (absolute_import, division, print_function) -import sys -import warnings - - from setuptools import setup setup(