From 7014351eb49324b77267ee573781c5f84183bb67 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Thu, 24 Oct 2024 12:11:50 +0200 Subject: [PATCH] SFELPHOTON-1335:try to debug --- Readme.md | 40 ++++++------- psi_device.py | 160 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 128 insertions(+), 72 deletions(-) diff --git a/Readme.md b/Readme.md index 7bf0c5d..a480c74 100644 --- a/Readme.md +++ b/Readme.md @@ -16,6 +16,10 @@ psigithub git@git.psi.ch:epics_support_apps/ppmac.git --> ~/Documents/prj/Sw packages needed by PBTools for lowest level communication to PowerBrick additional module 'slic' is needed, which is provided by Sven and covers the JungFrau acquisition framefork + +For motion/frame synchronization read: + ~/Documents/prj/SwissFEL/apps/PBSwissMX/Readme.md + ``` deployment and tests (update: 18.01.24) @@ -24,7 +28,6 @@ deployment and tests (update: 18.01.24) #initial full deployment: git commit-amend && git push psigithub -f && make uninstall init update - Document to start SwissMX in cristallina environment: https://docs.google.com/document/d/1yEmV_DbRBKQKVCoovjXriNgSjNEBaz50WA0l3yA5jtg/edit#heading=h.z9io692b8tow ``` @@ -32,25 +35,18 @@ https://docs.google.com/document/d/1yEmV_DbRBKQKVCoovjXriNgSjNEBaz50WA0l3yA5jtg/ * push local stuff to git * *************************** zamofing_t@ganymede: -cd ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX &&\ +cd ~/Documents/prj/SwissFEL/apps/SwissMX &&\ git commit-amend &&\ -git push psigithub +git push psigithub -f -cd ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX &&\ +cd ~/Documents/prj/SwissFEL/apps/PBSwissMX &&\ git commit-amend &&\ -git push psigithub +git push psigithub -f ************************************* * switch to latest test environment * ************************************* -ssh zamofing_t@saresc-cons-03 - -#first time only: -cd /sf/cristallina/applications/ -git clone -o psigithub git@git.psi.ch:grp-sf_cristallina/SwissMX.git -git clone -o psigithub git@git.psi.ch:grp-sf_cristallina/SwissMX_PB.git -rsync -vain ~/Documents/prj/SwissFEL/apps/SwissMX/simCamImg saresc-cons-03:/sf/cristallina/applications/SwissMX/ -cd /sf/cristallina/applications/SwissMX +ssh saresc-cons-03 cd /sf/cristallina/applications/SwissMX &&\ git checkout master &&\ @@ -60,7 +56,7 @@ git reset psigithub/master --hard &&\ git stash pop #git pull psigithub --ff-only master -cd /sf/cristallina/applications/SwissMX_PB &&\ +cd /sf/cristallina/applications/SwissMX/PBSwissMX &&\ git checkout master &&\ git stash push &&\ git fetch psigithub master &&\ @@ -68,18 +64,22 @@ git reset psigithub/master --hard &&\ git stash pop #git pull psigithub --ff-only master +chmod -R g+w /sf/cristallina/applications/SwissMX + ******************* * run application * ******************* -additionally needed packages on an RH8 system: -pip install --user pandas zmq qtawesome -mkdir -p /sf/cristallina/applications/python3.6-packages -pip3.6 install --prefix /sf/cristallina/applications/SwissMX pandas zmq qtawesome -cd /sf/cristallina/applications/SwissMX -/opt/gfa/python-3.8/latest/bin/python swissmx.py +*** with official python *** +additionally needed packages: +RH7: +[saresc-vcons-01 ~]$ /opt/gfa/python-3.8/latest/bin/pip install --user qtawesome +RH8: +[saresc-cons-03 ~]$ pip install --user qtawesome +swissmx +#with conda environment: ssh gac-cristall@saresc-cons-03 (pw:ValToira_2021) cd /sf/cristallina/applications/SwissMX/ # conda env list diff --git a/psi_device.py b/psi_device.py index f15be63..256e019 100644 --- a/psi_device.py +++ b/psi_device.py @@ -17,6 +17,7 @@ if __name__ == "__main__": sys.path.insert(0, os.path.join(base,'PBSwissMX/python')) elif socket.gethostname()!='ganymede': sys.path.insert(0, os.path.expanduser('/sf/cristallina/applications/slic/slic-package')) + sys.path.insert(0, os.path.expanduser('/sf/cristallina/applications/mx/swissmx_tools/jfj')) from PyQt5.QtWidgets import (QApplication,) from app_config import AppCfg #settings, option, toggle_option @@ -28,12 +29,14 @@ import shapepath try: from slic.core.acquisition import SFAcquisition + from slic.core.acquisition.broker.tools import get_endstation from slic.devices.timing.events import CTASequencer from ctadaq import CTAAcquisition from jfjoch_device import JFJ except ImportError as e: _log.warning(e) + class Shutter: def __init__(self,mode=1): @@ -49,15 +52,20 @@ class Shutter: _log.info('open simulated shutter') elif mode==1: # open laser shutter - epics.caput("SLAAR31-LPSYS-ESC:LHX1_SHUT_OPEN", 1) - if self.sync_flag==0: #if using cta, sets pulse_picker output to follow pulser 3 + #epics.caput("SLAAR31-LPSYS-ESC:LHX1_SHUT_OPEN", 1) '''think this shutter is no longer used''' + if epics.caget("SLAAR31-LPSYS-ESCIP23:ONOFF.RVAL") == 1: + epics.caput("SLAAR31-LPSYS-ESCOP0:ONOFF", 1) + _log.info('laser shutter opened') + + if self.sync_flag==0: #if using cta, sets pulse_picker output to follow pulser 0 # open fast shutter - epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD", 3) - epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD2", 3) epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SOURCE", 0) epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SOURCE2", 0) + epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD", 0) + epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD2", 0) + epics.caput("SARES30-LTIM01-EVR0:RearUniv0-Ena-SP", 1) - _log.info('shutter opened') + _log.info('fast shutter opened') def close(self): mode=self._mode @@ -66,16 +74,19 @@ class Shutter: elif mode==1: # close laser shutter - epics.caput("SLAAR31-LPSYS-ESC:LHX1_SHUT_CLOSE", 1) - _log.info('shutter closed') + if epics.caget("SLAAR31-LPSYS-ESCIP23:ONOFF.RVAL") == 1: + epics.caput("SLAAR31-LPSYS-ESCOP2:ONOFF", 1) + _log.info('laser shutter closed') + #epics.caput("SLAAR31-LPSYS-ESC:LHX1_SHUT_CLOSE", 1) '''think this shutter is no longer used''' # close fast shutter epics.caput("SARES30-LTIM01-EVR0:RearUniv0-Ena-SP", 0) if self.sync_flag==0: #if using cta, sets pulse_picker output back to high low, could do this every time? - epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD", 1) - epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD2", 1) epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SOURCE", 3) epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SOURCE2", 4) + epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD", 4) + epics.caput("SARES30-LTIM01-EVR0:RearUniv0_SNUMPD2", 4) + _log.info('fast shutter closed') class Deltatau: def __init__(self,sim=False): @@ -112,6 +123,8 @@ class Jungfrau: self._pv_pulse_id.connect() except NameError as e: _log.critical(f'Jungfrau not connected: {e}') + self.n_pulses_run = None + self.bsdata_scalar = 1 def config(self,**kwargs): if getattr(self,'_sim',False): @@ -129,61 +142,57 @@ class Jungfrau: code_gen=kwargs.get('code_gen',0) sync_mode=dt_misc['sync_mode'] sync_flag=dt_misc['sync_flag'] + self.n_pulses_run = None if loc['jungfraujoch']: try: self.jfj = JFJ("http://sf-daq-2:5232") self.detectors=None - except: + _log.info(f'JungFrauJoch connected') + except NameError as e: self.jfj = None + _log.critical(f'JungfrauJoch not connected: {e}') + is_scan_step=False else: self.jfj = None if sync_flag==0: grid_cnt=kwargs['grid']['count'] repetitions=grid_cnt[0] #'x' or number of columns cta_multiplier=grid_cnt[1] #'y' or number of appertures in a column/number of rows + number_of_appertures = repetitions*cta_multiplier cta=CTASequencer("SAR-CCTA-ESC") + cta.cfg.repetitions = repetitions + self.images=repetitions*cta_multiplier if code_gen==3: - wait_pulses=kwargs['twait']//kwargs['tmove'] + if kwargs['tmove']==0: + wait_pulses=0 + else: + wait_pulses=kwargs['twait']//kwargs['tmove'] #xray_seq=[0,]*wait_pulses+[1] # multiplier is proportional to wait_time i.e. 10 ms = 1, 20 ms =2, 30 ms =3. - xray_seq=[1,]+[0,]*wait_pulses - cta.seq[200]=xray_seq*cta_multiplier # x-ray_shutter - laser_seq=[1,]*wait_pulses+[1] - cta.seq[215]=laser_seq*cta_multiplier # laser_shutter - droplet_sequence=[0, 1, 0, 0] # sub 8 ms delay = [0, 0, 1, 0] - cta.seq[216]=droplet_sequence*(cta_multiplier//2) - cta.seq[214]=[1,]+[0,]*(len(laser_seq*cta_multiplier)-1) + xray_sequence=[0,]*wait_pulses+[1] + cta.seq[200]=xray_sequence*cta_multiplier # x-ray_shutter + cta.seq[214] = [1,] + [0,] * (len(xray_sequence * cta_multiplier) -1) + trigger_sequence=[1,]*wait_pulses+[1] + cta.seq[215]=trigger_sequence*(cta_multiplier//2) # laser_shutter + image_label_sequence = [0,] * wait_pulses + [1] + [0,] * wait_pulses + [0] + cta.seq[216]=image_label_sequence*(cta_multiplier//2) + cta.seq[219] = xray_sequence * cta_multiplier + else: print('not code gen 3') - #cta_multiplier-=14 - #cta.seq[200]=[0,0,0,0,0,0,0]+[1,]*cta_multiplier + [0,0,0,0,0,0,0] # for +7 row chip x-ray - #cta.seq[215]=[0,0,0,0,0,0,0]+[1,]*cta_multiplier + [0,0,0,0,0,0,0] # for +7 row chip laser - #cta.seq[214]=[1,0,0,0,0,0,0]+[0,]*cta_multiplier + [0,0,0,0,0,0,0] # for +7 row chip start - - # no extra rows - cta.seq[214]=[1,]+[0,]*(cta_multiplier-1) + # no extra rows 1:1 + cta.seq[214]=[1,]+[0,]*(cta_multiplier-1) #start motion cta.seq[200]=[1,]*cta_multiplier # x-ray_shutter - #cta.seq[215]=[1,]*cta_multiplier # laser_shutter - #cta.seq[216]=[1,]*cta_multiplier # droplet_ejector all - cta.seq[216]=[1,0,]*(cta_multiplier//2) # droplet_ejector 1:1 - #cta.seq[216]=[1,0,0,]*(cta_multiplier//3) # droplet_ejector 1:2 - #cta.seq[216]=[1,0,0,0,0,0,]*(cta_multiplier//6) # droplet_ejector 1:5 - #cta.seq[216]=[1,0,0,0,0,0,0,0,0,]*(cta_multiplier//9) # droplet_ejector 1:8 - #cta.seq[216]=[1,0,0,0,0,0,0,0,0,0,0,0,]*(cta_multiplier//12) # droplet_ejector 1:11 + cta.seq[219]=[1,]*cta_multiplier #trigger detector + cta.seq[215]=[1,0,]*(cta_multiplier//2) # Trigger 1:1 + cta.seq[216]=[1,0,]*(cta_multiplier//2) # Label image light dark 1:1 - # skip 6 rows add 6 on end -- first 2 and 1 216 - #cta.seq[214]=[1,0,0,0,0,0,]+[0,]*(cta_multiplier-12)+[0,0,0,0,0,0,] - #cta.seq[200]=[0,0,0,0,0,0,]+[1,]*(cta_multiplier-12)+[0,0,0,0,0,0,] # x-ray_shutter - #cta.seq[216]=[0,0,0,0,0,0,]+[1,]*(cta_multiplier-12)+[0,0,0,0,0,0,] # droplet_ejector all - #cta.seq[216]=[0,0,0,0,0,0,]+[1,0,]*((cta_multiplier-12)//2)+[0,0,0,0,0,0,] # droplet_ejector 1:1 - #cta.seq[216]=[0,0,0,0,0,0,]+[1,0,0,]*((cta_multiplier-12)//3)+[0,0,0,0,0,0] # droplet_ejector 1:2 - #cta.seq[216]=[0,0,0,0,0,0,]+[1,0,0,0]*((cta_multiplier-12)//4)+[0,0,0,0,0,0] # droplet_ejector 1:3 - #cta.seq[216]=[0,0,0,0,0,0,]+[1,0,0,0,0,0,]*((cta_multiplier-12)//6)+[0,0,0,0,0,0]# droplet_ejector 1:5 - #cta.seq[216]=[0,0,0,0,0,0,]+[1,0,0,0,0,0,0,0,0,0,0,0,]*((cta_multiplier-12)//12)+[0,0,0,0,0,0] # droplet_ejector 1:11 - cta.cfg.repetitions=repetitions # self._cta.cfg.repetitions = n_pulses_run/cta_multiplier + self.n_pulses_run = len(cta.seq[200])*repetitions + self.bsdata_scalar = self.n_pulses_run/number_of_appertures + _log.info(f'The multiplier of the block size is {self.bsdata_scalar}') cta.seq.upload() self._daq=CTAAcquisition(cta, loc['end_station'], loc['p_group'], default_detectors=detectors, default_channels=bs_channels, - default_pvs=pv_channels, rate_multiplicator=1, append_user_tag_to_data_dir=True) + default_pvs=pv_channels, rate_multiplicator=1, append_user_tag_to_data_dir=True, timeout=30) else: self._daq=SFAcquisition( loc['end_station'], loc['p_group'], @@ -202,21 +211,68 @@ class Jungfrau: app=QApplication.instance() cfg=app._cfg run=cfg.value(AppCfg.DAQ_RUN) + loc=cfg.value(AppCfg.DAQ_LOC) + #data_proc=cfg.value(AppCfg.DATA_PROC) + #daq_sample=cfg.value(AppCfg.DAQ_SAMPLE) + #daq_uc=cfg.value(AppCfg.DAQ_UC) try: self._pulse_id_start=int(self._pv_pulse_id.value) except TypeError as e: _log.warning(f'failed to get _pulse_id_start: {e}') - n_pulses_run = n_pulses + run['padding'] - n_pulses_run*=2 # comment me out please when not using 10 ms wait (for stop and go) - print('number of triggers ', n_pulses_run, ' is greater than the number of appertures', n_pulses) - block_size = run['block_size'] - if self.jfj: - self.jfj.acquire(beam_x_pxl = 1613, beam_y_pxl = 1666, detector_distance_mm = 151, photon_energy_keV = 12, sample_name = run['cell_name'], file_prefix = run['prefix'], ntrigger = n_pulses_run) - if type(self._daq) is CTAAcquisition: - self._daq.acquire(run['prefix'], n_pulses=max(n_pulses_run, block_size), n_block_size=block_size, wait=False, cell_name=run['cell_name']) + if self.n_pulses_run: + n_pulses_run=self.n_pulses_run + _log.info(f'self.n_pulses_run {self.n_pulses_run} is equal to n_pulses_run {n_pulses_run}') + _log.info(f'number of images to JFJ is {self.images}') else: - self._daq.acquire(run['prefix'], n_pulses=max(n_pulses_run, block_size), n_repeat=ceil(n_pulses_run/block_size), wait=False, cell_name=run['cell_name']) + n_pulses_run = n_pulses + run['padding'] + _log.info(f'self.n_pulses_run {self.n_pulses_run} is not equal to n_pulses_run {n_pulses_run}') + #n_pulses_run*=2 # comment me out please when not using 10 ms wait (for stop and go) + images_per_file = run['block_size'] + sample_name = run['prefix'] #daq_sample['sample_name'] #protein_name + prefix = run['prefix'] + user_tag = f'{sample_name}_{prefix}' + if self.jfj: + daq_uc={"a":70,"b":70,"c":70,"alpha":90,"beta":90,"gamma":90} + unit_cell = {"a":daq_uc['a'],"b":daq_uc['b'], "c":daq_uc['c'],"alpha":daq_uc['alpha'], "beta":daq_uc['beta'], "gamma":daq_uc['gamma']} + transmission_ATT53 = epics.caget("SARFE10-OATT053:UsrRec.TD") + transmission_ATT150 = epics.caget("SAROP31-OATA150:UsrRec.TD") + transmission = transmission_ATT53*transmission_ATT150 + detector_distance_mm = round(epics.caget("SAR-EXPMX:MOT_DET_Z.RBV"),2) + + run_number = self._daq.client.next_run() + is_scan_step = True + pgroup=loc['p_group'] + try: + endstation = get_endstation() + _log.info(f'got endstation through slic:{endstation}') + except: + endstation = loc['end_station'] #'cristallina' #need cdoe form slic to direct this + _log.info(f'got endstation through gui:{endstation}') + jfj_file_prefix = f'sf/{endstation}/data/{pgroup}/raw/run{run_number:04}-{user_tag}/data/acq' + + header_appendix ='{' + #for key in data_proc.keys(): + # value = data_proc[key] + # pair =f'"{key}":{value},' + # header_appendix+=pair + header_appendix+='}' #some keys are different in JFJoch + + self.jfj.acquire(beam_x_pxl = loc['beam_x'], beam_y_pxl = loc['beam_y'], detector_distance_mm = detector_distance_mm, incident_energy_keV = loc['incident_energy_kev'], transmission = transmission, + sample_name = sample_name, run_number = run_number, file_prefix = jfj_file_prefix, experiment_group=pgroup, ntrigger = self.images, images_per_file = images_per_file, + unit_cell=unit_cell, space_group_number='42',#daq_uc['space_group_number'], + header_appendix=header_appendix + ) + _log.info('JFJ primed') + else: + is_scan_step=False + block_size = int(run['block_size']*self.bsdata_scalar) #scales block_size for bsdata acquisition only + _log.info(f'The multiplier of the block size is {self.bsdata_scalar}, new block size is {block_size}') + if type(self._daq) is CTAAcquisition: + self._daq.acquire(user_tag, n_pulses=max(n_pulses_run, block_size), n_block_size=block_size, wait=False, cell_name=run['cell_name'], is_scan_step=is_scan_step) + else: + self._daq.acquire(user_tag, n_pulses=max(n_pulses_run, block_size), n_repeat=ceil(n_pulses_run/block_size), wait=False, cell_name=run['cell_name'], is_scan_step=is_scan_step) cfg.setValue(AppCfg.DAQ_RUN,run) + is_scan_step=False def gather_upload(self): if getattr(self,'_sim',False):