281 lines
8.9 KiB
Python
281 lines
8.9 KiB
Python
import logging
|
|
_log=logging.getLogger(__name__)
|
|
|
|
#from glob import glob
|
|
|
|
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
|
|
|
|
#import eventer
|
|
#import qsingleton
|
|
#from detector_integration_api import DetectorIntegrationClient
|
|
#from app_config import settings, appsconf, simulated
|
|
#config = appsconf['jungfrau']
|
|
#dia_client = DetectorIntegrationClient(config['uri'])
|
|
|
|
class JungfrauWaiter(QObject):
|
|
finished = pyqtSignal()
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
@pyqtSlot()
|
|
def work(self):
|
|
pass
|
|
|
|
class JungfrauMissingConfiguration(Exception):
|
|
pass
|
|
|
|
class Jungfrau(QObject):
|
|
pedestal_selected = pyqtSignal(str)
|
|
configured = pyqtSignal()
|
|
armed = pyqtSignal()
|
|
started = pyqtSignal()
|
|
triggered = pyqtSignal()
|
|
aborted = pyqtSignal()
|
|
|
|
def __init__(self, parent=None, **kwargs):
|
|
super(Jungfrau, self).__init__(parent, **kwargs)
|
|
self._save_raw = True
|
|
self._runJungfrau = False
|
|
self._number_of_frames = 1
|
|
#self._gain_maps = config["gain_maps"]
|
|
self._uid = None
|
|
#self._serial_number = config['serialnr']
|
|
self.writer_config = {}
|
|
self.backend_config = {}
|
|
self.detector_config = {}
|
|
self.bsread_config = {}
|
|
|
|
@pyqtSlot(bool)
|
|
def set_run_jungfrau(self, run):
|
|
"""running or not jungfrau, global simulated flag overrides"""
|
|
_log.warning(f"{'' if run else 'not '}running jungfrau detector")
|
|
if not self._simulated:
|
|
self._runJungfrau = run
|
|
else:
|
|
self._runJungfrau = False
|
|
|
|
@pyqtSlot(bool)
|
|
def set_save_raw(self, save_raw):
|
|
"""enable or not writer_config"""
|
|
_log.warning(f"{'' if save_raw else 'not '}saving data")
|
|
self._save_raw = save_raw
|
|
|
|
@pyqtSlot(str)
|
|
def set_detector_serial(self, serial_number):
|
|
"""set serial number for main detector"""
|
|
_log.info(f"jungfrau serial number: {serial_number}")
|
|
self._serial_number = serial_number
|
|
|
|
def is_saving_data(self):
|
|
"""if False writer_config is not issued"""
|
|
return self._save_raw
|
|
|
|
def is_running_detector(self):
|
|
"""if False nothing is actually called"""
|
|
return self._runJungfrau
|
|
|
|
@pyqtSlot(int)
|
|
def set_number_of_frames(self, frames):
|
|
_log.info(f"jungfrau number of frames: {frames}")
|
|
self._number_of_frames = frames
|
|
|
|
@pyqtSlot(int)
|
|
def set_data_owner_uid(self, uid):
|
|
_log.info(f"data owner set to UID = {uid}")
|
|
self._uid = uid
|
|
|
|
@pyqtSlot(str)
|
|
def set_gain_filename(self, gainfile:str):
|
|
_log.info(f"gain file: {gainfile}")
|
|
self._gain_maps = gainfile
|
|
|
|
def configure(self, outfile=None, outdir=None, **kwargs):
|
|
if not self._runJungfrau:
|
|
_log.warning("jungfrau not required: configure dismissed")
|
|
return
|
|
|
|
if self._gain_maps is None:
|
|
raise JungfrauMissingConfiguration("missing gain maps filename")
|
|
gain_filename = self._gain_maps
|
|
|
|
if self._uid is None:
|
|
raise JungfrauMissingConfiguration("missing data owner p-group UID")
|
|
uid = self._uid
|
|
|
|
n_frames = self._number_of_frames
|
|
|
|
pede_pattern = "/sf/bernina/data/p{}/res/JF_pedestals/pedestal_*.JF07T32V01.res.h5".format(
|
|
uid
|
|
)
|
|
try:
|
|
pf = sorted(glob(pede_pattern))[-1]
|
|
pf = pf[: pf.index(".JF07T32V01")]
|
|
except IndexError:
|
|
pf = None
|
|
|
|
pede_filename = pf
|
|
_log.info(f"Pedestal file {pede_filename}")
|
|
|
|
exptime = 0.000005
|
|
instrument = "Bernina"
|
|
|
|
self.writer_config = {
|
|
"output_file": outdir + "/" + outfile,
|
|
"user_id": uid,
|
|
"n_frames": n_frames,
|
|
"general/user": str(uid),
|
|
"general/process": __name__,
|
|
"general/created": str(datetime.now()),
|
|
"general/instrument": instrument,
|
|
}
|
|
|
|
if not self._save_raw:
|
|
self.writer_config["output_file"] = "/dev/null"
|
|
|
|
self.detector_config = {
|
|
"exptime": exptime,
|
|
"frames": 1,
|
|
"cycles": n_frames,
|
|
"timing": "trigger",
|
|
"dr": 16,
|
|
}
|
|
|
|
self.backend_config = {
|
|
"n_frames": n_frames,
|
|
"bit_depth": 16,
|
|
"run_name": outfile,
|
|
"beam_center_x": 2110.0,
|
|
"beam_center_y": 2210.0,
|
|
"beam_energy": 6000.0,
|
|
"detector_distance": 0.06,
|
|
"hitfinder_min_snr": 6.0,
|
|
"hitfinder_min_pix_count": 5,
|
|
"hitfinder_adc_thresh": 20.0,
|
|
"swissmx_trajectory_method": "grid",
|
|
"swissmx_trajectory_details_1": [100],
|
|
"swissmx_trajectory_details_2": [n_frames // 100 + 1],
|
|
}
|
|
|
|
backend_extras = kwargs.get("backend_extras", None)
|
|
if backend_extras:
|
|
self.backend_config.update(backend_extras)
|
|
|
|
# """
|
|
# "swissmx_trajectory_method": "grid",
|
|
# "swissmx_trajectory_details_1": [100],
|
|
# "swissmx_trajectory_details_2": [n_frames//100+1],
|
|
#
|
|
# "swissmx_trajectory_method": "rotation",
|
|
# "swissmx_trajectory_details_1": [360],
|
|
# "swissmx_trajectory_details_2": [0.1],
|
|
#
|
|
# "swissmx_trajectory_method": "trajectory",
|
|
# "swissmx_trajectory_details_1": [random()*100 for i in range(int(n_frames*0.9))],
|
|
# "swissmx_trajectory_details_2": [random()*100 for i in range(int(n_frames*0.9))],
|
|
#
|
|
# """
|
|
self.bsread_config = {
|
|
"output_file": outdir + "/" + outfile,
|
|
"user_id": uid,
|
|
"general/user": str(uid),
|
|
"general/process": __name__,
|
|
"general/created": str(datetime.now()),
|
|
"general/instrument": instrument,
|
|
}
|
|
|
|
if gain_filename != "" or pede_filename != "":
|
|
self.backend_config["gain_corrections_filename"] = gain_filename
|
|
self.backend_config["gain_corrections_dataset"] = "gains"
|
|
self.backend_config["pede_corrections_filename"] = pede_filename
|
|
self.backend_config["pede_corrections_dataset"] = "gains"
|
|
self.backend_config["pede_mask_dataset"] = "pixel_mask"
|
|
self.backend_config["activate_corrections_preview"] = True
|
|
_log.info("Corrections in online viewer activated")
|
|
|
|
configuration = {
|
|
"writer": self.writer_config,
|
|
"backend": self.backend_config,
|
|
"detector": self.detector_config,
|
|
"bsread": self.bsread_config,
|
|
}
|
|
|
|
_log.info("resetting & configuring detector: approx. 6 seconds")
|
|
dia_client.reset()
|
|
dia_client.set_config(configuration)
|
|
_log.info(dia_client.get_config())
|
|
|
|
def arm(self) -> int:
|
|
"""arm detector and return an ID for this series"""
|
|
if not self._runJungfrau:
|
|
_log.warning("jungfrau not required: arm dismissed")
|
|
return
|
|
|
|
_log.info("arming detector: approx. 2 seconds")
|
|
dia_client.start(trigger_start=False)
|
|
|
|
def wait_finished(self):
|
|
"""close shutter after this wait is finished regardless of exceptions"""
|
|
if not self._runJungfrau:
|
|
_log.warning("jungfrau not required: wait_finished dismissed")
|
|
return
|
|
|
|
try:
|
|
dia_client.wait_for_status(["IntegrationStatus.FINISHED"], polling_interval=0.1)
|
|
except:
|
|
_log.info("Got IntegrationStatus ERROR")
|
|
_log.info(dia_client.get_status())
|
|
_log.info(dia_client.get_status_details())
|
|
|
|
_log.info("Stopping acquisition")
|
|
dia_client.reset()
|
|
|
|
_log.info("Done")
|
|
|
|
def disarm(self) -> int:
|
|
"""arm detector and return an ID for this series"""
|
|
if not self._runJungfrau:
|
|
_log.warning("jungfrau not required: disarm dismissed")
|
|
return
|
|
|
|
dia_client.reset()
|
|
|
|
def trigger(self):
|
|
if not self._runJungfrau:
|
|
_log.warning("jungfrau not required: trigger dismissed")
|
|
return
|
|
_log.info("Trigger in detector is called")
|
|
eventer.start()
|
|
|
|
def abort(self):
|
|
if not self._runJungfrau:
|
|
_log.warning("jungfrau not required: abort dismissed")
|
|
return
|
|
|
|
self.disarm()
|
|
eventer.stop()
|
|
|
|
if __name__=='__main__':
|
|
def main():
|
|
jungfrau_detector = Jungfrau()
|
|
import argparse
|
|
from datetime import datetime
|
|
date_string = datetime.now().strftime("%Y%m%d_%H%M")
|
|
parser = argparse.ArgumentParser(description="Create a pedestal file for Jungrau")
|
|
parser.add_argument("--api", default="http://sf-daq-1:10000", required=True)
|
|
parser.add_argument("--filename", default="run_%s.h5" % date_string, help="Output file name")
|
|
parser.add_argument("--pede", default="", help="File containing pedestal corrections")
|
|
parser.add_argument("--gain", default="", help="File containing gain corrections")
|
|
parser.add_argument("--directory", default="/sf/bernina/data/raw/p16582", help="Output directory")
|
|
parser.add_argument("--uid", default=16582, help="User ID which needs to own the file", type=int)
|
|
parser.add_argument("--period", default=0.01, help="Period (default is 10Hz - 0.01)", type=float)
|
|
parser.add_argument("--exptime",default=0.000010,help="Integration time (default 0.000010 - 10us)",type=float,)
|
|
parser.add_argument("--frames", default=10, help="Number of frames to take", type=int)
|
|
parser.add_argument("--save", default=False, help="Save data file", action="store_true")
|
|
parser.add_argument("--highgain", default=False, help="Enable High Gain (HG0)", action="store_true")
|
|
parser.add_argument("--instrument", default="", help="Name of the instrument, e.g. Alvra")
|
|
# parser.add_argument("--caput", default=False, help="Use the CAPUT trick (experts only!!!)", action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
main()
|