Skip to content
Snippets Groups Projects
PilatusXM.py 59 KiB
Newer Older
    def StartStandardAcq(self):
        """ Start an acquisition with the propositioned parameters
        """
        self.debug_stream("In StartStandardAcq()")
        #----- PROTECTED REGION ID(PilatusXM.StartStandardAcq) ENABLED START -----#
        if self.Simulation:
            self.total_exp_time = self.attr_ExposureTime_read * self.attr_NbFrames_read * self.attr_NbExposures_read
            self.start_time = time.time()
            self.set_state(PyTango.DevState.RUNNING)
            self.set_status("The device is in RUNNING state.")
            return
        expPeriodAttr = fakeAttr()
        self.read_ExposurePeriod(expPeriodAttr)
        expTimeAttr = fakeAttr()
        self.read_ExposureTime(expTimeAttr)
        if (expPeriodAttr.value  < (expTimeAttr.value + self.ReadOutTime) ):
            expPeriodAttr.set_value(expTimeAttr.value + self.ReadOutTime)
            self.write_ExposurePeriod(expPeriodAttr)
        fullname = "%s%05d%s" % (self.attr_FilePrefix_read,self.attr_FileStartNum_read,self.attr_FilePostfix_read)
        trgModes = {0:"exposure", 1:"extenable",2:"exttrigger",3:"extmtrigger"}
        #
        self.attr_LastImageTaken_read = ''
        self.attr_LastImagePath_read = ''
        cmd = trgModes[self.attr_TriggerMode_read] +" "+fullname
        reply = self.comm.send_to_detector(cmd)
        if reply is None:
            PyTango.Except.throw_exception("Communication error","Pilatus does not reply","StartStandardAcq")
        elif "ERR" in reply:
            PyTango.Except.throw_exception("Command error","Pilatus reply: %s" % reply,"StartStandardAcq")
        elif "15 OK" in reply and "Starting" in reply:
            self.set_state(PyTango.DevState.RUNNING)
        self.set_status("The device is in RUNNING state.")

        #----- PROTECTED REGION END -----#    //    PilatusXM.StartStandardAcq
        
    def is_StartStandardAcq_allowed(self):
        self.debug_stream("In is_StartStandardAcq_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.DISABLE,
            PyTango.DevState.RUNNING,
            PyTango.DevState.FAULT])
        #----- PROTECTED REGION ID(PilatusXM.is_StartStandardAcq_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#    //    PilatusXM.is_StartStandardAcq_allowed
        return state_ok
        
    def StopAcq(self):
        """ Stop the acquisition. This works only for multi images acquisitions.
        A single image acquisition will always finish.
        """
        self.debug_stream("In StopAcq()")
        #----- PROTECTED REGION ID(PilatusXM.StopAcq) ENABLED START -----#
        if self.Simulation:
            self.set_state(PyTango.DevState.ON)
            self.set_status("The device is in ON state. Ready")
        cmd = "camcmd k"
        reply = self.comm.send_to_detector(cmd, wait_reply = False)
        
        #----- PROTECTED REGION END -----#    //    PilatusXM.StopAcq
        
    def is_StopAcq_allowed(self):
        self.debug_stream("In is_StopAcq_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.DISABLE,
            PyTango.DevState.FAULT])
        #----- PROTECTED REGION ID(PilatusXM.is_StopAcq_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#    //    PilatusXM.is_StopAcq_allowed
        return state_ok
        
    def Reset(self):
        """ Reset a state
        """
        self.debug_stream("In Reset()")
        #----- PROTECTED REGION ID(PilatusXM.Reset) ENABLED START -----#
        if self.Simulation:
            self.set_state(PyTango.DevState.ON)
            self.set_status("The device is in ON state. Ready")
        cmd = "camcmd ResetCam"
        reply = self.comm.send_to_detector(cmd, wait_reply = False)
        #----- PROTECTED REGION END -----#    //    PilatusXM.Reset
        

    #----- PROTECTED REGION ID(PilatusXM.programmer_methods) ENABLED START -----#
    
    #----- PROTECTED REGION END -----#    //    PilatusXM.programmer_methods

class PilatusXMClass(PyTango.DeviceClass):
    # -------- Add you global class variables here --------------------------
    #----- PROTECTED REGION ID(PilatusXM.global_class_variables) ENABLED START -----#
    
    #----- PROTECTED REGION END -----#    //    PilatusXM.global_class_variables


    #    Class Properties
    class_property_list = {
        }


    #    Device Properties
    device_property_list = {
        'ServerAddress':
            [PyTango.DevString, 
            "The IP address of the PilatusXM camserver.",
            [] ],
        'Simulation':
            [PyTango.DevBoolean, 
             '',
            [False]],
        'ReadOutTime':
            [PyTango.DevFloat, 
            "Minimum ReadOUt influences the minimum difference between ExposurePeriod and ExposureTime.",
            [0.003]],
        }


    #    Command definitions
    cmd_list = {
        'StartStandardAcq':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'StopAcq':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Reset':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        }


    #    Attribute definitions
    attr_list = {
        'ExposureTime':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Exposure Time",
                'unit': "s",
                'format': "%10.8f",
                'min value': "0",
                'description': "The exposure time for the detector.\nIn the External Enable mode this value is not used by camserver.",
                'Memorized':"true"
            } ],
        'ExposurePeriod':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Exposure Period",
                'unit': "s",
                'format': "%10.8f",
                'min value': "0",
                'description': "Controls the exposure period between to images in seconds. \nIt applies only in Internal or External Trigger modes when NbFrames > 1.",
                'Memorized':"true"
            } ],
        'NbFrames':
            [[PyTango.DevLong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Number of Frames",
                'unit': " ",
                'format': "%6d",
                'min value': "1",
                'description': "The number of images to acquire when starting the detector",
                'Memorized':"true"
            } ],
        'NbExposures':
            [[PyTango.DevLong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Number of Exposures",
                'unit': " ",
                'format': "%6d",
                'min value': "1",
                'description': "The number of exposures per images.\nIt applies only in External Enable mode.",
                'Memorized':"true"
            } ],
        'DelayTime':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Delay Time",
                'unit': "s",
                'format': "%6.4f",
                'min value': "0",
                'description': "Delay in seconds between the external trigger and the start of image acquisition. \nIt only applies in External Trigger mode",
                'Memorized':"true"
            } ],
        'ShutterEnable':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Enable Shutter Control",
                'description': "Enable the shutter control by the detector.",
                'Memorized':"true"
            } ],
        'TriggerMode':
            [[PyTango.DevShort,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Trigger Mode",
                'format': "%1d",
                'max value': "3",
                'min value': "0",
                'description': "The possible trigger modes for the Pilatus detector are:\n<p>\n    0 = Internal (external signal not used)\n<br />\n    1 = External Enable (count while external trigger line is high, readout on high to low transition)\n <br />  \n    2 =  External Trigger (begin acquisition sequence on high to low transition of external trigger line)\n <br />   \n    3 = Multiple External Trigger (high to low transition on external signal triggers a single acquisition for the programmed exposure time)\n</p><p>\nThe 4 modes correspond directly to the camserver \ncommands Exposure, ExtEnable, ExtTrigger, and ExtMTrigger respectively.\n</p></Font>",
                'Memorized':"true"
            } ],
        'UseRamDisk':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Use RAM Disk",
                'description': "When true, will force image file to be written to /ramdisk.\nTherefore, attribute FileDir will be ignored.",
                'Memorized':"true"
            } ],
        'FileDir':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Image File Path",
                'unit': " ",
                'description': "Path to the dector image files.",
                'Memorized':"true"
            } ],
        'FilePrefix':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Image File Prefix",
                'unit': " ",
                'description': "The prefix of the image files to be created.\nThe full image file name will be composed as\n<br />\n<b>prefix_number.postfix </b>\n<br />\nwhen acquiring images.",
                'Memorized':"true"
            } ],
        'FileStartNum':
            [[PyTango.DevLong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Image File Number",
                'unit': " ",
                'format': "%5d",
                'description': "The file number used when taking an image.\n<br />\nWhen taking more than one frame, the detector creates\nthe file numbers automatically from this number onwards.\n<p>\nWhen saving multiple images (NImages>1) camserver has its own rules for \ncreating the names of the individual files.\nThe following examples shows the interpretation of the basename.\n</p><p>\nBasename -  Files produced\n<br />\ntest6.tif  - test6_00000.tif,  test6_00001.tif, ...\n<br />\ntest6_.tif  -  test6_00000.tif,  test6_00001.tif, ...\n<br />\ntest6_00008.tif -  test6_00008.tif,   test6_00009.tif, ...\n<br />\ntest6_2_00035.tif -  test6_2_00035.tif, test6_2_00036.tif, ...\n</p>\nThe numbers following the last '_' are taken as a format template, \nand as a start value. \nThe format is also constrained by the requested number of images.",
                'Memorized':"true"
            } ],
        'FilePostfix':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Image File Postfix",
                'unit': " ",
                'description': "The Pilatus detector allows the following postfix:\n<br />\n<b>.tif, .edf, .img, .cbf</b>\n<br />\nThe postfix determines the image format for the saved\nimage files.\n<p>\nThe camserver uses the file extension to determine what format to save \nthe files in.\n</p>",
                'Memorized':"true"
            } ],
        'LastImageTaken':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Last Image File Name",
                'unit': " ",
                'description': "The name of the last image file written.",
            } ],
        'Energy':
            [[PyTango.DevLong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Photon Energy",
                'unit': "eV",
                'format': "%5d",
                'description': "Simplified method to set gain and threshold for the\ndetector.\nThe threshold will be set to half the photon energy.\nThe detecor loads the corresponding trim files\nwhen changing the energy.\nModifying the detector setting will take several\nseconds.",
                'Memorized':"true_without_hard_applied"
            } ],
        'Threshold':
            [[PyTango.DevLong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Threshold Energy",
                'unit': "eV",
                'format': "%5d",
                'max value': "14337",
                'min value': "2113",
                'description': "The threshold energy for the detector.\nThe detecor loads the corresponding trim files\nwhen changing the energy threshold.\nThe threshold energy will always be set together with the gain.\nModifying the detector setting will take several\nseconds.",
                'Memorized':"true_without_hard_applied"
            } ],
        'Gain':
            [[PyTango.DevShort,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Gain (Energy Range)",
                'unit': " ",
                'format': "%1d",
                'max value': "3",
                'min value': "0",
                'description': "The gain controls the value of Vrf, which determines the shaping time and gain of\nthe input amplifiers.\nThe allowed gain values for the Pilatus detector are:\n\n    0 = lowG = Fastest shaping time (~125ns) and lowest gain.\n\n    1 = midG = Medium shaping time (~200ns) and medium gain.\n    \n    2 =  highG = Slow shaping time (~400ns) and high gain.\n    \n    3 = uhighG = Slowest peaking time and highest gain.\nThe gain will always be set together with the threshold energy.\nModifying the detector setting will take several\nseconds.",
                'Memorized':"true_without_hard_applied"
            } ],
        'LastImagePath':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Last Image Path",
                'description': "The last path where an  image was written.",
            } ],
        'MxSettings':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'description': "Set crystallographic parameters in the image header.\nPossible parameter names are: Wavelength, Energy_range, Detector_distance, ...\n(see Pilatus manual for a complete list).",
            } ],
        'GapFill':
            [[PyTango.DevShort,
            PyTango.SCALAR,
            PyTango.READ_WRITE]],
        'LdBadPixMap':
            [[PyTango.DevString,
            PyTango.SCALAR,
            PyTango.READ_WRITE]],
        }


def main():
    try:
        py = PyTango.Util(sys.argv)
        py.add_class(PilatusXMClass, PilatusXM, 'PilatusXM')
        #----- PROTECTED REGION ID(PilatusXM.add_classes) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#    //    PilatusXM.add_classes

        U = PyTango.Util.instance()
        U.server_init()
        U.server_run()

    except PyTango.DevFailed as e:
        print ('-------> Received a DevFailed exception:', e)
    except Exception as e:
        print ('-------> An unforeseen exception occured....', e)

if __name__ == '__main__':
    main()