Exemple #1
0
class SimDetector(SingleTrigger, AreaDetector):
    """
    Simulated Detector used at 6-ID-D@APS
    This is based on the Point Grey detector
    """

    cam1 = ADComponent(SimDetectorCam6IDD, suffix="cam1:")  # camera
    proc1 = ADComponent(ProcessPlugin, suffix="Proc1:")  # processing
    tiff1 = ADComponent(TIFFPlugin, suffix="TIFF1:")  # tiff output
    hdf1 = ADComponent(HDF5Plugin6IDD, suffix="HDF1:")  # HDF5 output

    @property
    def status(self):
        """List all related PVs and corresponding values"""
        # TODO:
        #   provide acutal implementation here
        return "Not implemented yet"

    @property
    def help(self):
        """Return quick summary of the actual specs of the detector"""
        pass

    @property
    def position(self):
        """return the area detector position from the associated motor"""
        pass

    @position.setter
    def position(self, new_pos):
        """move the detector to the new location"""
        # NOTE:
        #   This is for interactive control only, cannot be used in scan plan
        #   We will need to use this position during scan, i.e. near field z scan
        pass
class PilatusFilePlugin(Device, FileStoreBulkWrite):
    file_path = ADComponent(EpicsSignalWithRBV, 'FilePath', string=True)
    file_number = ADComponent(EpicsSignalWithRBV, 'FileNumber')
    file_name = ADComponent(EpicsSignalWithRBV, 'FileName', string=True)
    file_template = ADComponent(EpicsSignalWithRBV, 'FileTemplate', string=True)
    reset_file_number = Cpt(Signal, name='reset_file_number', value=1)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._datum_kwargs_map = dict()  # store kwargs for each uid

    def stage(self):
        global proposal_id
        global run_id
        global current_sample
        global data_path
        global collection_lock_file

        set_and_wait(self.file_template, '%s%s_%6.6d_'+self.parent.detector_id+'.cbf', timeout=99999)
        if self.reset_file_number.get() == 1:
            set_and_wait(self.file_number, 1, timeout=99999)

        # original code by Hugo
        # this is done now when login()
        #path = '/GPFS/xf16id/exp_path/'
        #rpath = str(proposal_id)+"/"+str(run_id)+"/"
        #fpath = path + rpath
        #makedirs(fpath)
        
        # modified by LY
        # camserver saves data to the local ramdisk, a background process then move them to data_path
        # interesting to note that camserver saves the data to filename.tmp, then rename it filename after done writing
        # must have the '/' at the end, since camserver will add it to the RBV
        # this should done only once for all Pilatus detectors
        if self.parent.name == first_Pilatus():
            #print("first Pilatus is %s" % self.parent.name)
            change_path()
        
        #set_and_wait(self.file_path, "/ramdisk/", timeout=99999)
        set_and_wait(self.file_path, data_path, timeout=99999)
        set_and_wait(self.file_name, current_sample, timeout=99999)
        
        super().stage()
        res_kwargs = {'template': self.file_template.get(),
                      'filename': self.file_name.get(),
                      'frame_per_point': self.get_frames_per_point(),
                      'initial_number': self.file_number.get()}
        #self._resource = fs.insert_resource('AD_CBF', rpath, res_kwargs, root=path)
        self._resource = fs.insert_resource('AD_CBF', data_path, res_kwargs, root="/")
        
        if self.parent.name == first_Pilatus():
            caput("XF:16IDC-ES:Sol{ctrl}ready", 1)

    def unstage(self):        
        super().unstage()
        #if self.parent.name == first_Pilatus():
        #    release_lock()
        
    def get_frames_per_point(self):
        return 1
Exemple #3
0
class GEDetector(SingleTrigger, AreaDetector):
    """Generic detector abstraction for GE"""
    # e.g.  det = GEDetector("GE2:", name='det')
    # TODO
    # we migth need to switch to raw
    cam1 = ADComponent(CamBase, suffix="cam1:")
    proc1 = ADComponent(ProcessPlugin, suffix="Proc1:")
    tiff1 = ADComponent(TIFFPlugin, suffix="TIFF1:")
Exemple #4
0
class PointGreyDetector6BM(SingleTrigger, AreaDetector):
    """Point Gray area detector used at 6BM"""
    # cam component
    cam = ADComponent(PointGreyDetectorCam6BM, "cam1:")
    # proc plugin
    proc1 = ADComponent(ProcessPlugin, suffix="Proc1:")
    # tiff plugin
    tiff1 = ADComponent(TIFFPlugin, suffix="TIFF1:")
    # HDF5 plugin
    hdf1 = ADComponent(HDF5Plugin6BM, suffix="HDF1:")
class MySimDetector(SingleTrigger, DetectorBase):
    """ADSimDetector"""

    cam = ADComponent(MyFixedCam, "cam1:")
    image = ADComponent(ImagePlugin_V34, "image1:")
    hdf1 = ADComponent(
        MyHDF5Plugin,
        "HDF1:",
        write_path_template=WRITE_PATH_TEMPLATE,
        read_path_template=READ_PATH_TEMPLATE,
    )
    pva = ADComponent(PvaPlugin_V34, "Pva1:")
Exemple #6
0
class MyDexelaDetector(SingleTrigger, DexelaDetector):
    """Dexela detector(s) as used by 9-ID-C USAXS."""

    hdf1 = ADComponent(
        MyHDF5Plugin,
        "HDF1:",
        write_path_template=WRITE_HDF5_FILE_PATH_DEXELA,
        read_path_template=READ_HDF5_FILE_PATH_DEXELA,
        path_semantics="windows",
    )
    image = ADComponent(ImagePlugin, "image1:")
    proc1 = ADComponent(MyProcessPlugin, "Proc1:")
class MyPcoDetector(SingleTrigger, AreaDetector):
    """PCO detectors as used by 2-BM tomography"""
    # TODO: configure the "root" and "write_path_template" attributes

    cam = ADComponent(MyPcoCam, "cam1:")
    image = ADComponent(ImagePlugin, "image1:")
    hdf1 = ADComponent(
        MyHDF5Plugin,
        "HDF1:",
        root="/",  # root path for HDF5 files (for databroker filestore)
        write_path_template=
        "/tmp",  # path for HDF5 files (for EPICS area detector)
        reg=db.reg,
    )
Exemple #8
0
class MyPointGreyDetectorJPEG(MyPointGreyDetector, AreaDetector):
    """
    Variation to write image as JPEG

    To save an image (using existing configuration)::

        blackfly_optical.stage()
        blackfly_optical.trigger()
        blackfly_optical.unstage()

    """

    jpeg1 = ADComponent(
        EpicsDefinesJpegFileNames,
        suffix = "JPEG1:",
        root = DATABROKER_ROOT_PATH,
        write_path_template = WRITE_IMAGE_FILE_PATH,
        read_path_template = READ_IMAGE_FILE_PATH,
        kind="normal",
        )
    trans1 = ADComponent(TransformPlugin, "Trans1:")
    cc1 = ADComponent(ColorConvPlugin, "CC1:")

    @property
    def image_file_name(self):
        return self.jpeg1.full_file_name.get()

    def image_prep(self, path, filename_base, order_number):
        plugin = self.jpeg1
        path = "/mnt" + os.path.abspath(path) + "/"  # MUST end with "/"
        yield from bps.mv(
            plugin.file_path, path,
            plugin.file_name, filename_base,
            plugin.file_number, order_number,
        )

    @property
    def should_save_image(self):
        return _flag_save_sample_image_.get() in (1, "Yes")

    def take_image(self):
        yield from bps.stage(self)
        yield from bps.trigger(self, wait=True)
        yield from bps.unstage(self)
class MyHDF5Plugin(HDF5Plugin, FileStoreHDF5IterativeWrite):
    #class MyHDF5Plugin(HDF5Plugin):
    """adapt HDF5 plugin for AD 2.5+"""

    file_number_sync = None
    # FIXME:  .put() works OK but .value returns numpy object metadata
    # In [48]: pco_edge.hdf1.xml_layout_file.get()
    # Out[48]: '<array size=21, type=time_char>'
    # FIXME: xml_layout_file = Component(EpicsSignalWithRBV, "XMLFileName", string=True)
    xml_layout_file = ADComponent(
        EpicsSignal, "XMLFileName",
        string=True)  # use as WRITE-ONLY for now due to error above
    xml_layout_valid = ADComponent(EpicsSignalRO, "XMLValid_RBV")
    xml_layout_error_message = ADComponent(EpicsSignalRO,
                                           "XMLErrorMsg_RBV",
                                           string=True)

    def get_frames_per_point(self):
        return self.parent.cam.num_images.get()
class PilatusFilePlugin(Device, FileStoreIterativeWrite):
    file_path = ADComponent(EpicsSignalWithRBV, 'FilePath', string=True)
    file_number = ADComponent(EpicsSignalWithRBV, 'FileNumber')
    file_name = ADComponent(EpicsSignalWithRBV, 'FileName', string=True)
    file_template = ADComponent(EpicsSignalWithRBV,
                                'FileTemplate',
                                string=True)
    file_number_reset = 1
    sub_directory = None
    froot = data_file_path.gpfs
    enable = SimpleNamespace(get=lambda: True)

    # this is not necessary to record since it contains the UID for the scan, useful
    # to save in the CBF file but no need in the data store
    #file_header = ADComponent(EpicsSignal, "HeaderString", string=True)

    # this is not necessary to record in the data store either, move to the parent
    #reset_file_number = Cpt(Signal, name='reset_file_number', value=1)

    #filemover_files = Cpt(EpicsSignal, 'filemover.filename')
    #filemover_target_dir = Cpt(EpicsSignal, 'filemover.target')
    #filemover_move = Cpt(EpicsSignal, 'filemover.moving')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._datum_kwargs_map = dict()  # store kwargs for each uid
        self.filestore_spec = 'AD_CBF'

    def stage(self):
        global proposal_id
        global run_id
        global current_sample
        global data_path

        f_tplt = '%s%s_%06d_' + self.parent.detector_id + '.cbf'
        set_and_wait(self.file_template, f_tplt, timeout=99999)

        if self.parent.name == first_Pilatus(
        ) or self.parent.name == first_PilatusExt():
            #print("first Pilatus is %s" % self.parent.name)
            change_path()

        # if file number reset is Ture, use 1 as the next file #
        # if reset is False, when the first Pilatus/PilatusExt instance is staged, the file# will be
        # synchronized to the highest current value
        if PilatusFilePlugin.file_number_reset == 1:
            print("resetting file number for ", self.parent.name)
            # it is a bad idea to wait since auto-increment may change this value immediately
            #set_and_wait(self.file_number, 1, timeout=99999)
            self.file_number.put(1)
            print('done.')
        elif self.parent.name == first_Pilatus():
            next_file_number = np.max(
                [d.file.file_number.get() for d in pilatus_detectors])
            for d in pilatus_detectors:
                print("setting file number for %s to %d." %
                      (d.name, next_file_number))
                set_and_wait(d.file.file_number,
                             next_file_number,
                             timeout=99999)
        elif self.parent.name == first_PilatusExt():
            next_file_number = np.max(
                [d.file.file_number.get() for d in pilatus_detectors_ext])
            for d in pilatus_detectors_ext:
                print("setting file number for %s to %d." %
                      (d.name, next_file_number))
                set_and_wait(d.file.file_number,
                             next_file_number,
                             timeout=99999)

        if PilatusFilePlugin.sub_directory is not None:
            f_path = data_path + PilatusFilePlugin.sub_directory
            RE.md['subdir'] = PilatusFilePlugin.sub_directory
        else:
            f_path = data_path
            if 'subdir' in RE.md.keys():
                del RE.md['subdir']
        f_fn = current_sample
        # file_path must ends with '/'
        print('%s: setting file path ...' % self.name)
        #if DET_replace_data_path:
        if self.froot == data_file_path.ramdisk:
            #f_path = f_path.replace(default_data_path_root, substitute_data_path_root)
            f_path = f_path.replace(data_file_path.gpfs.value,
                                    data_file_path.ramdisk.value)
        set_and_wait(self.file_path, f_path, timeout=99999)
        #set_and_wait(self.file_path, f_path, timeout=99999)
        set_and_wait(self.file_name, f_fn, timeout=99999)
        self._fn = Path(f_path)

        fpp = self.get_frames_per_point()
        # when camserver collects in "multiple" mode, another number is added to the file name
        # even though the template does not specify it.
        # Camserver doesn't like the template to include the second number
        # The template will be revised in the CBF handler if fpp>1

        print('%s: super().stage() ...' % self.name)
        super().stage()
        res_kwargs = {
            'template': f_tplt,  # self.file_template(),
            'filename': f_fn,  # self.file_name(),
            'frame_per_point': fpp,
            'initial_number': self.file_number.get()
        }
        print('%s: _generate_resource() ...' % self.name)
        self._generate_resource(res_kwargs)

    def unstage(self):
        super().unstage()
        ##12/19/17 commented out
        # move the files from ramdisk to GPFS
        #if self.filemover_move.get()==1:
        #    print("files are still being moved from the detector server to ",self.filemover_target_dir.get())
        #    while self.filemover_move.get()==1:
        #        sleep(1)
        #    print("done.")
        #self.filemover_files.put(current_sample)
        #self.filemover_target_dir.put(data_path)
        #self.filemover_move.put(1)
        ##12/19/17 commented out
        #if self.parent.name == first_Pilatus() or self.parent.name == first_PilatusExt():
        #    release_lock()

    def get_frames_per_point(self):
        #return self.parent.cam.num_images.get()   # always return 1 before 2018
        return self.parent._num_images
Exemple #11
0
class MyPointGreyDetector(SingleTrigger, AreaDetector):
    """PointGrey Black Fly detector(s) as used by 9-ID-C USAXS"""

    cam = ADComponent(PointGreyDetectorCam, "cam1:")
    image = ADComponent(ImagePlugin, "image1:")
class MyFixedCam(SimDetectorCam):
    pool_max_buffers = None
    offset = ADComponent(EpicsSignalWithRBV, "Offset")
Exemple #13
0
class SimDetectorCam6IDD(PointGreyDetectorCam):
    """
    Using SimDetector as PointGrey:
    cam plugin customizations (properties)
    """
    auto_exposure_on_off = ADComponent(EpicsSignalWithRBV, "AutoExposureOnOff")
    auto_exposure_auto_mode = ADComponent(EpicsSignalWithRBV,
                                          "AutoExposureAutoMode")
    sharpness_on_off = ADComponent(EpicsSignalWithRBV, "SharpnessOnOff")
    sharpness_auto_mode = ADComponent(EpicsSignalWithRBV, "SharpnessAutoMode")
    gamma_on_off = ADComponent(EpicsSignalWithRBV, "GammaOnOff")
    shutter_auto_mode = ADComponent(EpicsSignalWithRBV, "ShutterAutoMode")
    gain_auto_mode = ADComponent(EpicsSignalWithRBV, "GainAutoMode")
    trigger_mode_on_off = ADComponent(EpicsSignalWithRBV, "TriggerModeOnOff")
    trigger_mode_auto_mode = ADComponent(EpicsSignalWithRBV,
                                         "TriggerModeAutoMode")
    trigger_delay_on_off = ADComponent(EpicsSignalWithRBV, "TriggerDelayOnOff")
    frame_rate_on_off = ADComponent(EpicsSignalWithRBV, "FrameRateOnOff")
    frame_rate_auto_mode = ADComponent(EpicsSignalWithRBV, "FrameRateAutoMode")
Exemple #14
0
class RetigaDetectorCam(CamBase):
    """Retiga camera """
    # NOTE:
    # Different camera module from different manufacture requires different
    # configuration, see
    #  https://github.com/bluesky/ophyd/blob/master/ophyd/areadetector/cam.py
    # for more examples on how to make the PointGrey cam
    # NOTE:
    # - The PV settings are based on QIMAGE2@1-ID-C,APS
    # - The following PVs are defined in CamBase, but the available values
    #   might differe from other cams  // bookkeeping for inconsistent naming
    #    ---------------    |||   ------------
    #    MEDM/GUI/caQTdm    |||    PV/BlueSky
    #    ---------------    |||   ------------
    #   acquire_time        ===   exposure_time
    #   attributes          ===   nd_attributes_file
    #   buffer max/used     ===   pool_max/used_buffers
    #   buffer alloc/free   ===   pool_alloc/free_buffers
    #   buffer max/used     ===   pool_max_buffers
    #   memory max/userd    ===   pool_max/used_mem
    #   image_counter       ===   array_counter
    #   image_rate          ===   array_rate
    #   Sensor size         ===   max_size                  // bundled fields
    #   Region start        ===   min_x/y
    #   Region size         ===   size                      // bundled fields
    #   Image size          ===   array_size                // bundled fields
    #
    # - Nominal values for special fields
    #   * image_mode
    #       0: Single; 1: Multiple; 2: Continuous; 3: Single Fast
    #   * trigger_mode
    #       0: Freerun;  1: EdgeHi;  2: EdgeLow;   3: PulseHi;     4: PulseLow
    #       5: Software; 6: StrobeHi 7: StrobeLow; 8: Trigger_last
    # DEV:
    # - PVs with ?? requires double check during testing
    #

    _html_docs = ['retigaDoc.html']  # ??

    # ---
    # --- Define missing fields in the collect & attribute panel
    # ---
    auto_exposure = ADComponent(EpicsSignalWithRBV, 'aAutoExposure')  # ??

    exposure_max = ADComponent(EpicsSignalRO, 'ExposureMax_RBV')
    exposure_min = ADComponent(EpicsSignalRO, 'ExposureMin_RBV')

    exposure_status_message = ADComponent(EpicsSignalRO,
                                          'qExposureStatusMessage_RBV')
    frame_status_message = ADComponent(EpicsSignalRO,
                                       'qFrameStatusMessage_RBV')

    pool_used_mem_scan = ADComponent(EpicsSignalWithRBV,
                                     'PoolUsedMem.SCAN')  # ??
    # available values for pool_used_mem_scan
    # 0: Passive;    1: Event;      2: I/O Intr;
    # 3: 10 second;  4: 5 second;   5: 2 second;  6: 1 second;
    # 7: 0.5 second; 8: 0.2 second; 9: 0.1 second

    # ---
    # --- Define missing fields in the Setup panel
    # ---
    asyn_io_connected = ADComponent(
        EpicsSignalWithRBV, 'AsynIO.CNCT')  # 0: Disconnected; 1: Connected
    reset_cam = ADComponent(EpicsSignalWithRBV, 'qResetCam')

    # ---
    # --- Define missing fields in the Readout panel
    # ---
    binning = ADComponent(EpicsSignalWithRBV, 'qBinning')
    # 0: 1x1;  1: 2x2; 2: 4x4;  3: 8x8
    # WARNING:
    # retiga does not have individual binning fields, therefore the predefined
    # bin_x and bin_y will lead to error...
    gain_max = ADComponent(EpicsSignalRO, 'GainMax_RBV')
    gain_min = ADComponent(EpicsSignalRO, 'GainMin_RBV')

    abs_offset = ADComponent(EpicsSignalWithRBV, 'qOffset')  # ??
    image_format = ADComponent(EpicsSignalWithRBV, 'qImageFormat')
    # -- available values for image_format
    #  0: Raw       8;    1: Raw       16;
    #  2: Mono      8;    3: Mono      16;
    #  4: RGB Plane 8;    5: GBR Plane 16;
    #  6: BGR      24;
    #  7: XRGB     32;
    #  8: RGB      48;
    #  9: BGRX     32;
    # 10: RGB      24;
    readout_speed = ADComponent(EpicsSignalWithRBV, 'qReadoutSpeed')
    # -- available values for readout speed
    # 0: 20 Mhz;  1: 10 Mhz;  2: 5 Mhz

    # ---
    # --- Define missing fileds in the Cooling Panel
    # ---
    cooler = ADComponent(EpicsSignalWithRBV, 'qCoolerActive')
Exemple #15
0
class PointGreyDetector(SingleTrigger, AreaDetector):
    """PointGrey Detector used at 6-ID-D@APS for tomo and nf-HEDM"""

    cam1 = ADComponent(PointGreyDetectorCam6IDD, suffix="cam1:")  # camera
    proc1 = ADComponent(ProcessPlugin, suffix="Proc1:")  # processing
    tiff1 = ADComponent(TIFFPlugin, suffix="TIFF1:")  # tiff output
    hdf1 = ADComponent(HDF5Plugin6IDD, suffix="HDF1:")  # HDF5 output
    trans1 = ADComponent(TransformPlugin, suffix="Trans1:")  # Transform images
    image1 = ADComponent(ImagePlugin,
                         suffix="image1:")  # Image plugin, rarely used in plan

    @property
    def status(self):
        """List all related PVs and corresponding values"""
        # TODO:
        #   provide acutal implementation here
        return "Not implemented yet"

    @property
    def help(self):
        """Return quick summary of the actual specs of the detector"""
        pass

    @property
    def position(self):
        """return the area detector position from the associated motor"""
        pass

    @position.setter
    def position(self, new_pos):
        """move the detector to the new location"""
        # NOTE:
        #   This is for interactive control only, cannot be used in scan plan
        #   We will need to use this position during scan, i.e. near field z scan
        pass

    # TODO:
    #  Additional PVs can be wrapped as property for interactive use when the
    #  acutal PVs are known.

    def cont_acq(self, _exp, _period, _nframes=-1):
        """
        cont_acq(a, b, c)
        acuqre 'c' images with exposure of 'a' seconds every 'b' seconds
        b is default to -1 to continue acquiring until manual interruption
        """
        from time import sleep
        self.cam1.acquire_time.put(_exp)
        self.cam1.acquire_period.put(_period)
        self.cam1.image_mode.put("Continuous")  # To be checked
        if _nframes <= 0:
            # do infinite number of frames....
            print(f"Start taking images with {_exp} seconds of exposure\n")
            print(f"Press \"Stop\" on 1idPG4:cam1 to stop acquisition.\n")
            sleep(0.5)
        else:
            self.cam1.image_mode.put("Multiple")
            print(
                f"Start taking {_nframes} images with {_exp} seconds of exposure\n"
            )
            print(f"Press \"Stop\" on 1idPG4:cam1 to stop acquisition.\n")
            self.cam1.n_images.put(_nframes)
            sleep(0.5)  # To be updated
        self.cam1.acquire.put(1)
Exemple #16
0
class HDF5Plugin6IDD(HDF5Plugin):
    """AD HDF5 plugin customizations (properties)"""
    xml_file_name = ADComponent(EpicsSignalWithRBV, "XMLFileName")
Exemple #17
0
class VarexTransformPlugin(TransformPlugin):
    """Add Types handle"""
    transformation_type = ADComponent(EpicsSignal, "Type")
class MyPcoCam(PcoDetectorCam):
    """PCO Dimax detector"""
    pco_cancel_dump = ADComponent(EpicsSignal, "pco_cancel_dump")
    pco_live_view = ADComponent(EpicsSignal, "pco_live_view")
    pco_trigger_mode = ADComponent(EpicsSignal, "pco_trigger_mode")
    pco_edge_fastscan = ADComponent(EpicsSignal, "pco_edge_fastscan")
    pco_is_frame_rate_mode = ADComponent(EpicsSignal, "pco_is_frame_rate_mode")
    pco_imgs2dump = ADComponent(EpicsSignalWithRBV, "pco_imgs2dump")
    pco_dump_counter = ADComponent(EpicsSignal, "pco_dump_counter")
    pco_dump_camera_memory = ADComponent(EpicsSignal, "pco_dump_camera_memory")
    pco_max_imgs_seg0 = ADComponent(EpicsSignalRO, "pco_max_imgs_seg0_RBV")
    pco_ready2acquire = ADComponent(EpicsSignal, "pco_ready2acquire")
    pco_set_frame_rate = ADComponent(EpicsSignal, "pco_set_frame_rate")

    # FIXME: ophyd has problem with trying to unstage the RBV value inside RE()
    image_mode = ADComponent(EpicsSignal, "ImageMode")
    num_images = ADComponent(EpicsSignal, "NumImages")
    acquire_time = ADComponent(EpicsSignal, "AcquireTime")
    frame_type = ADComponent(EpicsSignal, "FrameType")