示例#1
0
    def prepareForCollection(self):
        """ Method called before a scan starts. May be used to setup detector
            for collection, for example MAR345 uses this to erase. """
        if self.verbose:
            simpleLog("%s:%s() started... collectionTime=%r" %
                      (self.name, self.pfuncname(), self.collectionTime))

        #self.setupZebra() Doing this every time adds 40 seconds to the time it takes to prepare the scan

        self.acquire_time_in_pulses = self.collectionTime * 10  # 10Hz

        self.pvs['PC_GATE_NGATE'].caput(TIMEOUT, self.acquire_time_in_pulses)
        self.pvs['PC_PULSE_STEP'].caput(TIMEOUT,
                                        self.acquire_time_per_pulse_s + 0.001)
        self.pvs['PC_PULSE_DLY'].caput(TIMEOUT, self.acquire_time_per_pulse_s)
        # PC_PULSE is only used to determine when the capture is performed.
        # If PC_PULSE_DLY were less than acquire_time_per_pulse_s then the
        # capture of the final point would be too early and we would miss some
        # counts.

        self.pvs['PULSE1_DLY'].caput(TIMEOUT, self.absolute_delay_after_rise_s)
        self.pvs['PULSE1_WID'].caput(TIMEOUT, self.acquire_time_per_pulse_s)

        self.pvs['PULSE2_DLY'].caput(TIMEOUT, self.absolute_delay_after_fall_s)
        self.pvs['PULSE2_WID'].caput(TIMEOUT, self.acquire_time_per_pulse_s)

        # Ensure that the SOFT_IN1 is reset so we don't think we have started collection already..
        self.pvs['SOFT_IN:B0'].caput(TIMEOUT, 0)  # SOFT_IN1

        if self.verbose:
            simpleLog("%s:%s() completed." % (self.name, self.pfuncname()))

#    def endCollection(self):
        """ Method called at the end of collection to tell detector when a
示例#2
0
 def createsOwnFiles(self):
     """ Returns a value which indicates whether the detector creates its
         own files. If it does (return true) the readout() method returns
         the name of the latest file created as a string. If it does not
         (return false) the readout() method will return the data directly. """
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return False
示例#3
0
 def integratesBetweenPoints(self):
     """ Detectors that sample some value at the time of a trigger should return False. Detectors such as counter timers
         should return True. If true ,TrajectoryScanLine will generate a trigger half a point before the motor reaches a
         demanded point such that the resulting bin of data is centred on the demand position. Area detectors that will be
         triggered by the first pulse should also return true."""
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return True
 def moveTo(self, position):
     help_stop_me = ", to stop rocking run 'pos %s [%f 0]'" % (self.parent.name, self.centre)
     if self.parent.verbose:
         msg = self.name + ": Moving " + self.scannable.name + " to %f (%d)" % (position, self.rockCount) + help_stop_me
         simpleLog(msg)
     elif (datetime.now() - self.movelog_time) > timedelta(seconds=30):
         simpleLog("Continuously rocking" + help_stop_me)
         self.movelog_time = datetime.now()
     self.scannable.moveTo(position)
 def run(self):
     if self.parent.verbose:
         simpleLog(self.name + ": Running...")
     while (self.running):
         self.moveTo(self.centre-self.delta)
         self.rockCount+=1
         if not self.running or self.delta == 0:
             break
         self.moveTo(self.centre+self.delta)
         self.rockCount+=1
     simpleLog(self.name + ": Stopped.")
    def asynchronousMoveTo(self, position):
        assert(len(position)==2)
        if self.thread and self.thread.running:
            if   (abs(self.thread.centre-position[0]) < 0.00001 and
                   abs(self.thread.delta-position[1]) < 0.00001):
                simpleLog(self.name + ": New positions same as old.")
                return
            self.stop()
            self.thread.join()

        self.thread=RockerThread(self.name, self.scannable, position[0], position[1], self.rockCount, self)
        simpleLog(self.name + ": Starting RockerThread...")
        self.thread.start()
示例#7
0
    def collectData(self):
        """ Tells the detector to begin to collect a set of data, then returns
            immediately. """
        if self.verbose:
            simpleLog("%s:%s() started... collectionTime=%r" %
                      (self.name, self.pfuncname(), self.collectionTime))

        # Ensure that the SOFT_IN1 is reset before RESET is performed to ensure
        # that the Arm is not triggered by the RESET.
        self.pvs['SOFT_IN:B0'].caput(TIMEOUT, 0)  # SOFT_IN1

        # Perform a Zebra RESET to clear the DIV counters.
        self.pvs['SYS_RESET.PROC'].caput(TIMEOUT, 1)

        # Reset the last number of points captured so we don't finish before we've started
        self.pvs['PC_NUM_CAP'].caput(TIMEOUT, 0)

        # Set the SOFT_IN1 so that the next PULSE1 will Arm the position compare
        self.pvs['SOFT_IN:B0'].caput(TIMEOUT, 1)
        """ This delays the start of the first count until the first PULSE so that
            we only ever count over the whole PULSE period and never get a partial
            pulse at the start of acquisition:
            
            Option 1, SOFT_IN1 goes high while IN1_TTL is Low:
                10Hz (IN1_TTL) ____~~~~____~~~~____
                      SOFT_IN1 __~~~~~~~~~~~~~~~~~~
                         GATE1 __~~________________
               Not GATE1 (OR1) ~~__~~~~~~~~~~~~~~~~
                  Arm triggers     ^
            
            Option 2, SOFT_IN1 goes high while IN1_TTL is High, :
                10Hz (IN1_TTL) ____~~~~____~~~~____
                      SOFT_IN1 ______~~~~~~~~~~~~~~
                         GATE1 ______~~~~~~________
               Not GATE1 (OR1) ~~~~~~______~~~~~~~~
                  Arm triggers             ^
        """
        if self.verbose:
            simpleLog("%s:%s() completed." % (self.name, self.pfuncname()))

#    def setCollectionTime(self):
        """ Sets the collection time, in seconds, to be used during the next
            call of collectData.
        self.collectionTime defined by DetectorBase """

        #    def getCollectionTime(self):
        """ Returns the time, in seconds, the detector collects for during the
示例#8
0
    def setDelayAfterFall(self, delay_after_fall_s):
        """ Time from 10Hz fall to start of acquire, in seconds. """
        if delay_after_fall_s < 0.:
            simpleLog(
                "Note that %s delay_after_fall_s (%r) < 0 so %rs will be added at acquire time."
                % (self.name, delay_after_fall_s, self.negative_offset))
            self.absolute_delay_after_fall_s = delay_after_fall_s + self.negative_offset
            #low_limit = 0.05
            #high_limit = 0.1-self.acquire_time_per_pulse_s
        else:
            self.absolute_delay_after_fall_s = delay_after_fall_s
            #low_limit = 0
            #high_limit = 0.05-self.acquire_time_per_pulse_s
        # TODO: Work out how to sanity check these values.
        #if self.absolute_delay_after_fall_s < low_limit :
        #    simpleLog("Warning, %r is less than %r so acquire time per pulse should be reduced for this delay." % (delay_after_fall_s, low_limit))
        #if self.absolute_delay_after_fall_s > high_limit :
        #    simpleLog("Warning, %r is more than %r so acquire time per pulse should be reduced for this delay." % (delay_after_fall_s, high_limit))

        self.delay_after_fall_s = delay_after_fall_s
示例#9
0
    def readout(self):
        """ Returns the latest data collected. The size of the Object returned
            must be consistent with the values returned by getDataDimensions
            and getExtraNames. """
        if self.verbose:
            simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))

        wait_count = 0
        while True:
            sleep(.1)
            num_downloaded = int(float(self.pvs['PC_NUM_DOWN'].caget()))
            if num_downloaded == self.acquire_time_in_pulses:
                if self.verbose:
                    simpleLog(
                        "Number of points downloaded (%r) == acquire time in pulses (%r)"
                        % (num_downloaded, self.acquire_time_in_pulses))
                break
            if wait_count > 50:
                simpleLog(
                    "Waiting for Number of points downloaded (%r) == acquire time in pulses (%r)"
                    % (num_downloaded, self.acquire_time_in_pulses))
                wait_count = 0
            wait_count += 1

        # TODO: We really should return different values when delays are negative, since this also swaps the signals
        mon_rise = float(self.pvs['PC_DIV1_LAST'].caget())
        mon_fall = float(self.pvs['PC_DIV2_LAST'].caget())
        det_rise = float(self.pvs['PC_DIV3_LAST'].caget())
        det_fall = float(self.pvs['PC_DIV4_LAST'].caget())
        return [
            self.acquire_time_in_pulses * self.acquire_time_per_pulse_s,
            mon_rise, mon_fall, mon_rise - mon_fall, det_rise, det_fall,
            det_rise - det_fall
        ]
示例#10
0
 def getReadOutTime(self):
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return 0.1  # ToDo: Word out if zero is appropriate here
示例#11
0
 def getHardwareTriggerProvider(self):
     """ Get the HardwareTriggerProvider that represents the controller this Detector is wired to."""
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return self.continuousMoveController
示例#12
0
 def getDetectorType(self):
     """ The type of detector. """
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return "FastDichroismZebraDetector"
示例#13
0
 def getDetectorID(self):
     """ A identifier for this detector. """
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return self.name
示例#14
0
 def getDescription(self):
     """ A description of the detector. """
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return "Fast Dicroism Zebra Detector"
示例#15
0
    def setupZebra(self):
        if self.verbose:
            simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))

        DISCONNECT = 0
        IN1_TTL = 1
        IN2_TTL = 4
        IN3_TTL = 7
        PC_ARM = 29
        AND1 = 32
        AND2 = 33
        AND3 = 34
        AND4 = 35
        OR1 = 36
        GATE1 = 40
        PULSE1 = 52
        PULSE2 = 53
        SOFT_IN1 = 60

        Yes = 1
        No = 0
        TriggerOnRisingEdge = No
        TriggerOnFallingEdge = Yes
        DivFirstPulseNumbered1_OUTN = No

        # Perform a Zebra RESET to ensure all of the PVs can be configured.
        self.pvs['SYS_RESET.PROC'].caput(TIMEOUT, 1)

        # The Position compare is used to control the length of acquisition
        # according to the number of pulses acquired, and capture the
        # total number of detector pulses for each phase of the acquisition.
        self.pvs['PC_BIT_CAP:B0'].caput(TIMEOUT, No)  # Enc1
        self.pvs['PC_BIT_CAP:B1'].caput(TIMEOUT, No)  # Enc2
        self.pvs['PC_BIT_CAP:B2'].caput(TIMEOUT, No)  # Enc3
        self.pvs['PC_BIT_CAP:B3'].caput(TIMEOUT, No)  # Enc4
        self.pvs['PC_BIT_CAP:B4'].caput(TIMEOUT, No)  # Sys1
        self.pvs['PC_BIT_CAP:B5'].caput(TIMEOUT, No)  # Sys2
        self.pvs['PC_BIT_CAP:B6'].caput(TIMEOUT, Yes)  # Div1
        self.pvs['PC_BIT_CAP:B7'].caput(TIMEOUT, Yes)  # Div2
        self.pvs['PC_BIT_CAP:B8'].caput(TIMEOUT, Yes)  # Div3
        self.pvs['PC_BIT_CAP:B9'].caput(TIMEOUT, Yes)  # Div4

        self.pvs['PC_ARM_SEL'].caput(TIMEOUT, 'External')
        self.pvs['PC_ARM_INP'].caput(TIMEOUT, OR1)

        self.pvs['PC_GATE_SEL'].caput(TIMEOUT, 'External')
        self.pvs['PC_GATE_INP'].caput(TIMEOUT, PULSE2)

        # PC_PULSE is only used to determine when the capture is performed.
        # If PC_PULSE_DLY were less than acquire_time_per_pulse_s then the
        # capture of the final point would be too early and we would miss some
        # counts.
        self.pvs['PC_PULSE_SEL'].caput(TIMEOUT, 'Time')
        self.pvs['PC_TSPRE'].caput(TIMEOUT, 's')

        # The AND gates are used to ensure that Detector and Monitor signals
        # are gated according to both the appropriate windows and whether the
        # acquisition is in progress.
        self.pvs['AND1_ENA:B0'].caput(TIMEOUT, Yes)  # INP1_ENA
        self.pvs['AND1_ENA:B1'].caput(TIMEOUT, Yes)  # INP2_ENA
        self.pvs['AND1_ENA:B2'].caput(TIMEOUT, Yes)  # INP3_ENA
        self.pvs['AND1_ENA:B3'].caput(TIMEOUT, No)  # INP4_ENA
        self.pvs['AND1_INP1'].caput(TIMEOUT, IN2_TTL)
        self.pvs['AND1_INP2'].caput(TIMEOUT, PULSE1)
        self.pvs['AND1_INP3'].caput(TIMEOUT, PC_ARM)
        self.pvs['AND1_INP4'].caput(TIMEOUT, DISCONNECT)
        self.pvs['AND1_INV:B0'].caput(TIMEOUT, No)  # INP1_INV
        self.pvs['AND1_INV:B1'].caput(TIMEOUT, No)  # INP2_INV
        self.pvs['AND1_INV:B2'].caput(TIMEOUT, No)  # INP3_INV
        self.pvs['AND1_INV:B3'].caput(TIMEOUT, No)  # INP4_INV

        self.pvs['AND2_ENA:B0'].caput(TIMEOUT, Yes)  # INP1_ENA
        self.pvs['AND2_ENA:B1'].caput(TIMEOUT, Yes)  # INP2_ENA
        self.pvs['AND2_ENA:B2'].caput(TIMEOUT, Yes)  # INP3_ENA
        self.pvs['AND2_ENA:B3'].caput(TIMEOUT, No)  # INP4_ENA
        self.pvs['AND2_INP1'].caput(TIMEOUT, IN2_TTL)
        self.pvs['AND2_INP2'].caput(TIMEOUT, PULSE2)
        self.pvs['AND2_INP3'].caput(TIMEOUT, PC_ARM)
        self.pvs['AND2_INP4'].caput(TIMEOUT, DISCONNECT)
        self.pvs['AND2_INV:B0'].caput(TIMEOUT, No)  # INP1_INV
        self.pvs['AND2_INV:B1'].caput(TIMEOUT, No)  # INP2_INV
        self.pvs['AND2_INV:B2'].caput(TIMEOUT, No)  # INP3_INV
        self.pvs['AND2_INV:B3'].caput(TIMEOUT, No)  # INP4_INV

        self.pvs['AND3_ENA:B0'].caput(TIMEOUT, Yes)  # INP1_ENA
        self.pvs['AND3_ENA:B1'].caput(TIMEOUT, Yes)  # INP2_ENA
        self.pvs['AND3_ENA:B2'].caput(TIMEOUT, Yes)  # INP3_ENA
        self.pvs['AND3_ENA:B3'].caput(TIMEOUT, No)  # INP4_ENA
        self.pvs['AND3_INP1'].caput(TIMEOUT, IN3_TTL)
        self.pvs['AND3_INP2'].caput(TIMEOUT, PULSE1)
        self.pvs['AND3_INP3'].caput(TIMEOUT, PC_ARM)
        self.pvs['AND3_INP4'].caput(TIMEOUT, DISCONNECT)
        self.pvs['AND3_INV:B0'].caput(TIMEOUT, No)  # INP1_INV
        self.pvs['AND3_INV:B1'].caput(TIMEOUT, No)  # INP2_INV
        self.pvs['AND3_INV:B2'].caput(TIMEOUT, No)  # INP3_INV
        self.pvs['AND3_INV:B3'].caput(TIMEOUT, No)  # INP4_INV

        self.pvs['AND4_ENA:B0'].caput(TIMEOUT, Yes)  # INP1_ENA
        self.pvs['AND4_ENA:B1'].caput(TIMEOUT, Yes)  # INP2_ENA
        self.pvs['AND4_ENA:B2'].caput(TIMEOUT, Yes)  # INP3_ENA
        self.pvs['AND4_ENA:B3'].caput(TIMEOUT, No)  # INP4_ENA
        self.pvs['AND4_INP1'].caput(TIMEOUT, IN3_TTL)
        self.pvs['AND4_INP2'].caput(TIMEOUT, PULSE2)
        self.pvs['AND4_INP3'].caput(TIMEOUT, PC_ARM)
        self.pvs['AND4_INP4'].caput(TIMEOUT, DISCONNECT)
        self.pvs['AND4_INV:B0'].caput(TIMEOUT, No)  # INP1_INV
        self.pvs['AND4_INV:B1'].caput(TIMEOUT, No)  # INP2_INV
        self.pvs['AND4_INV:B2'].caput(TIMEOUT, No)  # INP3_INV
        self.pvs['AND4_INV:B3'].caput(TIMEOUT, No)  # INP4_INV

        # OR1 is being used as a NOT gate, since there is no option to invert
        # the output of GATE1
        self.pvs['OR1_ENA:B0'].caput(TIMEOUT, Yes)  # INP1_ENA
        self.pvs['OR1_ENA:B1'].caput(TIMEOUT, No)  # INP2_ENA
        self.pvs['OR1_ENA:B2'].caput(TIMEOUT, No)  # INP3_ENA
        self.pvs['OR1_ENA:B3'].caput(TIMEOUT, No)  # INP4_ENA
        self.pvs['OR1_INP1'].caput(TIMEOUT, GATE1)
        self.pvs['OR1_INP2'].caput(TIMEOUT, DISCONNECT)
        self.pvs['OR1_INP3'].caput(TIMEOUT, DISCONNECT)
        self.pvs['OR1_INP4'].caput(TIMEOUT, DISCONNECT)
        self.pvs['OR1_INV:B0'].caput(TIMEOUT, Yes)  # INP1_INV
        self.pvs['OR1_INV:B1'].caput(TIMEOUT, No)  # INP2_INV
        self.pvs['OR1_INV:B2'].caput(TIMEOUT, No)  # INP3_INV
        self.pvs['OR1_INV:B3'].caput(TIMEOUT, No)  # INP4_INV

        # GATE1 is used to ensure that only whole acquisition windows are
        # acquired. See collectData() for details of how this works.
        self.pvs['GATE1_INP1'].caput(TIMEOUT, SOFT_IN1)
        self.pvs['POLARITY:B0'].caput(TIMEOUT,
                                      TriggerOnRisingEdge)  # GATE1 Set
        self.pvs['GATE1_INP2'].caput(TIMEOUT, PULSE1)
        self.pvs['POLARITY:B4'].caput(TIMEOUT,
                                      TriggerOnRisingEdge)  # GATE1 Reset

        # The DIV blocks are used to accumulate the detector counts during the
        # acquisition windows defined.
        MaxPulseCount = 1000000000
        self.pvs['DIV1_INP'].caput(TIMEOUT, AND1)
        self.pvs['POLARITY:B8'].caput(TIMEOUT,
                                      TriggerOnRisingEdge)  # DIV1 trigger
        self.pvs['DIV1_DIV'].caput(TIMEOUT, MaxPulseCount)
        self.pvs['DIV1_DIV'].caput(
            TIMEOUT, MaxPulseCount
        )  # Setting is not reliable, three times seems to be the charm
        self.pvs['DIV1_DIV'].caput(
            TIMEOUT, MaxPulseCount)  # TODO: Remove when this fixed
        self.pvs['DIV_FIRST:B0'].caput(TIMEOUT,
                                       DivFirstPulseNumbered1_OUTN)  # DIV1

        self.pvs['DIV2_INP'].caput(TIMEOUT, AND2)
        self.pvs['POLARITY:B9'].caput(TIMEOUT,
                                      TriggerOnRisingEdge)  # DIV2 trigger
        self.pvs['DIV2_DIV'].caput(TIMEOUT, MaxPulseCount)
        self.pvs['DIV2_DIV'].caput(
            TIMEOUT, MaxPulseCount
        )  # Setting is not reliable, three times seems to be the charm
        self.pvs['DIV2_DIV'].caput(
            TIMEOUT, MaxPulseCount)  # TODO: Remove when this fixed
        self.pvs['DIV_FIRST:B1'].caput(TIMEOUT,
                                       DivFirstPulseNumbered1_OUTN)  # DIV2

        self.pvs['DIV3_INP'].caput(TIMEOUT, AND3)
        self.pvs['POLARITY:BA'].caput(TIMEOUT,
                                      TriggerOnRisingEdge)  # DIV3 trigger
        self.pvs['DIV3_DIV'].caput(TIMEOUT, MaxPulseCount)
        self.pvs['DIV3_DIV'].caput(
            TIMEOUT, MaxPulseCount
        )  # Setting is not reliable, three times seems to be the charm
        self.pvs['DIV3_DIV'].caput(
            TIMEOUT, MaxPulseCount)  # TODO: Remove when this fixed
        self.pvs['DIV_FIRST:B2'].caput(TIMEOUT,
                                       DivFirstPulseNumbered1_OUTN)  # DIV3

        self.pvs['DIV4_INP'].caput(TIMEOUT, AND4)
        self.pvs['POLARITY:BB'].caput(TIMEOUT, TriggerOnRisingEdge)  # DIV4
        self.pvs['DIV4_DIV'].caput(TIMEOUT, MaxPulseCount)
        self.pvs['DIV4_DIV'].caput(
            TIMEOUT, MaxPulseCount
        )  # Setting is not reliable, three times seems to be the charm
        self.pvs['DIV4_DIV'].caput(
            TIMEOUT, MaxPulseCount)  # TODO: Remove when this fixed
        self.pvs['DIV_FIRST:B3'].caput(TIMEOUT,
                                       DivFirstPulseNumbered1_OUTN)  # DIV4

        self.pvs['PULSE1_INP'].caput(TIMEOUT, IN1_TTL)
        self.pvs['POLARITY:BC'].caput(TIMEOUT,
                                      TriggerOnRisingEdge)  # PULSE1 trigger
        self.pvs['PULSE1_PRE'].caput(TIMEOUT, 's')

        self.pvs['PULSE2_INP'].caput(TIMEOUT, IN1_TTL)
        self.pvs['POLARITY:BD'].caput(TIMEOUT,
                                      TriggerOnFallingEdge)  # PULSE2 trigger
        self.pvs['PULSE2_PRE'].caput(TIMEOUT, 's')

        if self.verbose:
            simpleLog("%s:%s() completed." % (self.name, self.pfuncname()))
示例#16
0
 def getDataDimensions(self):
     """ Returns the dimensions of the data object returned by the readout()
         method. """
     if self.verbose:
         simpleLog("%s:%s() started..." % (self.name, self.pfuncname()))
     return [1]
示例#17
0
def tomoScan(
    description,
    inBeamPosition,
    outOfBeamPosition,
    exposureTime=1.0,
    start=0.0,
    stop=180.0,
    step=0.1,
    darkFieldInterval=0,
    flatFieldInterval=0,
    imagesPerDark=10,
    imagesPerFlat=10,
    optimizeBeamInterval=0,
    pattern="default",
    tomoRotationAxis=0,
    addNXEntry=True,
    autoAnalyse=True,
    additionalScannables=[],
):
    """
    Function to collect a tomography step scan
    Arguments:
    description - description of the scan or the sample that is being scanned. This is generally user-specific information that may be used to map to this scan later and is available in the NeXus file)
    inBeamPosition - position of X drive to move sample into the beam to take a projection
    outOfBeamPosition - position of X drive to move sample out of the beam to take a flat field image
    exposureTime - exposure time in seconds (default=1.0)
    start - first rotation angle (default=0.0)
    stop  - last rotation angle (default=180.0)
    step - rotation step size (default=0.1)
    darkFieldInterval - number of projections between each dark-field sub-sequence. 
        NOTE: at least 1 dark is ALWAYS taken both at the start and end of the scan provided imagesPerDark>0 
        (default=0: use this value if you DON'T want to take any darks between projections)
    flatFieldInterval - number of projections between each flat-field sub-sequence. 
        NOTE: at least 1 flat is ALWAYS taken both at the start and end the scan provided imagesPerFlat>0 
        (default=0: use this value if you DON'T want to take any flats between projections)
    imagesPerDark - number of images to be taken for each dark-field sub-sequence (default=10)
    imagesPerFlat - number of images to be taken for each flat-field sub-sequence (default=10)
    
    General scan sequence is: D, F, P,..., P, F, D
    where D stands for dark field, F - for flat field, and P - for projection.
    """
    dataFormat = LocalProperties.get("gda.data.scan.datawriter.dataFormat")
    try:
        darkFieldInterval = int(darkFieldInterval)
        flatFieldInterval = int(flatFieldInterval)
        optimizeBeamInterval = int(optimizeBeamInterval)

        jns = beamline_parameters.JythonNameSpaceMapping(InterfaceProvider.getJythonNamespace())
        tomography_theta = jns.tomography_theta
        if tomography_theta is None:
            raise "tomography_theta is not defined in Jython namespace"
        tomography_shutter = jns.tomography_shutter
        if tomography_shutter is None:
            raise "tomography_shutter is not defined in Jython namespace"
        tomography_translation = jns.tomography_translation
        if tomography_translation is None:
            raise "tomography_translation is not defined in Jython namespace"

        tomography_detector = jns.tomography_detector
        if tomography_detector is None:
            raise "tomography_detector is not defined in Jython namespace"

        tomography_optimizer = jns.tomography_optimizer
        if tomography_optimizer is None:
            raise "tomography_optimizer is not defined in Jython namespace"

        tomography_time = jns.tomography_time
        if tomography_time is None:
            raise "tomography_time is not defined in Jython namespace"

        tomography_beammonitor = jns.tomography_beammonitor
        if tomography_beammonitor is None:
            raise "tomography_beammonitor is not defined in Jython namespace"

        tomography_camera_stage = jns.tomography_camera_stage
        if tomography_camera_stage is None:
            raise "tomography_camera_stage is not defined in Jython namespace"

        tomography_sample_stage = jns.tomography_sample_stage
        if tomography_sample_stage is None:
            raise "tomography_sample_stage is not defined in Jython namespace"

        tomo_additional_scannables = jns.tomography_additional_scannables
        if tomo_additional_scannables is None:
            raise "tomo_additional_scannables is not defined in Jython namespace"

        index = SimpleScannable()
        index.setCurrentPosition(0.0)
        index.setInputNames(["imageNumber"])
        index.setName("imageNumber")
        index.configure()

        image_key = SimpleScannable()
        image_key.setCurrentPosition(0.0)
        image_key.setInputNames(["image_key"])
        image_key.setName("image_key")
        image_key.configure()

        tomoScanDevice = make_tomoScanDevice(
            tomography_theta, tomography_shutter, tomography_translation, tomography_optimizer, image_key, index
        )

        #        return tomoScanDevice
        # generate list of positions
        numberSteps = ScannableUtils.getNumberSteps(tomography_theta, start, stop, step)
        theta_points = []
        theta_points.append(start)
        previousPoint = start
        for i in range(numberSteps):
            nextPoint = ScannableUtils.calculateNextPoint(previousPoint, step)
            theta_points.append(nextPoint)
            previousPoint = nextPoint

        # generateScanPoints
        optimizeBeamNo = 0
        optimizeBeamYes = 1
        shutterOpen = 1
        shutterClosed = 0
        shutterNoChange = 2
        scan_points = []
        theta_pos = theta_points[0]
        index = 0
        # Added shutterNoChange state for the shutter. The scan points are added using the (pseudo) ternary operator,
        # if index is 0 then the shutterPosition is added to the scan point, else shutterNoChange is added to scan points.
        for i in range(imagesPerDark):
            scan_points.append(
                (
                    theta_pos,
                    [shutterClosed, shutterNoChange][i != 0],
                    inBeamPosition,
                    optimizeBeamNo,
                    image_key_dark,
                    index,
                )
            )  # dark
            index = index + 1

        for i in range(imagesPerFlat):
            scan_points.append(
                (
                    theta_pos,
                    [shutterOpen, shutterNoChange][i != 0],
                    outOfBeamPosition,
                    optimizeBeamNo,
                    image_key_flat,
                    index,
                )
            )  # flat
            index = index + 1
        scan_points.append((theta_pos, shutterOpen, inBeamPosition, optimizeBeamNo, image_key_project, index))  # first
        index = index + 1
        imageSinceDark = 1
        imageSinceFlat = 1
        optimizeBeam = 0
        for i in range(numberSteps):
            theta_pos = theta_points[i + 1]
            scan_points.append(
                (
                    theta_pos,
                    [shutterOpen, shutterNoChange][i != 0],
                    inBeamPosition,
                    optimizeBeamNo,
                    image_key_project,
                    index,
                )
            )  # main image
            index = index + 1

            imageSinceFlat = imageSinceFlat + 1
            if imageSinceFlat == flatFieldInterval and flatFieldInterval != 0:
                for i in range(imagesPerFlat):
                    scan_points.append(
                        (
                            theta_pos,
                            [shutterOpen, shutterNoChange][i != 0],
                            outOfBeamPosition,
                            optimizeBeamNo,
                            image_key_flat,
                            index,
                        )
                    )
                    index = index + 1
                    imageSinceFlat = 0

            imageSinceDark = imageSinceDark + 1
            if imageSinceDark == darkFieldInterval and darkFieldInterval != 0:
                for i in range(imagesPerDark):
                    scan_points.append(
                        (
                            theta_pos,
                            [shutterClosed, shutterNoChange][i != 0],
                            inBeamPosition,
                            optimizeBeamNo,
                            image_key_dark,
                            index,
                        )
                    )
                    index = index + 1
                    imageSinceDark = 0

            optimizeBeam = optimizeBeam + 1
            if optimizeBeam == optimizeBeamInterval and optimizeBeamInterval != 0:
                scan_points.append(
                    (
                        theta_pos,
                        [shutterOpen, shutterNoChange][i != 0],
                        inBeamPosition,
                        optimizeBeamYes,
                        image_key_project,
                        index,
                    )
                )
                index = index + 1
                optimizeBeam = 0

        # add dark and flat only if not done in last steps
        if imageSinceFlat != 0:
            for i in range(imagesPerFlat):
                scan_points.append(
                    (
                        theta_pos,
                        [shutterOpen, shutterNoChange][i != 0],
                        outOfBeamPosition,
                        optimizeBeamNo,
                        image_key_flat,
                        index,
                    )
                )  # flat
                index = index + 1
        if imageSinceDark != 0:
            for i in range(imagesPerDark):
                scan_points.append(
                    (
                        theta_pos,
                        [shutterClosed, shutterNoChange][i != 0],
                        inBeamPosition,
                        optimizeBeamNo,
                        image_key_dark,
                        index,
                    )
                )  # dark
                index = index + 1
        scan_points1 = generateScanPoints(
            inBeamPosition,
            outOfBeamPosition,
            theta_points,
            darkFieldInterval,
            flatFieldInterval,
            imagesPerDark,
            imagesPerFlat,
            optimizeBeamInterval,
            pattern=pattern,
        )
        if pattern == "default" or pattern == "DFPFD":
            i = 0
            for pt1 in scan_points1:
                pt = scan_points[i]
                if pt1 != pt:
                    print "Mismatch - please tell Kaz about your scan and its arguments!"
                    print "i = ", i
                    print "pt = ", pt
                    print "pt1 = ", pt1
                i += 1
        # return None
        positionProvider = tomoScan_positions(
            start,
            stop,
            step,
            darkFieldInterval,
            imagesPerDark,
            flatFieldInterval,
            imagesPerFlat,
            inBeamPosition,
            outOfBeamPosition,
            optimizeBeamInterval,
            scan_points,
        )
        scan_args = [
            tomoScanDevice,
            positionProvider,
            tomography_time,
            tomography_beammonitor,
            tomography_detector,
            exposureTime,
            tomography_camera_stage,
            tomography_sample_stage,
        ]
        # scan_args.append(RotationAxisScannable("approxCOR", tomoRotationAxis))
        # meta_add(RotationAxisScannable("approxCOR", tomoRotationAxis))
        # meta_add("RotationCoord_as_list", [tomoRotationAxis])
        meta_add("approxCOR", tomoRotationAxis)
        for scannable in additionalScannables:
            scan_args.append(scannable)
        for scannable in tomo_additional_scannables:
            scan_args.append(scannable)
        """ setting the description provided as the title"""
        if not description == None:
            setTitle(description)
        else:
            setTitle("undefined")

        dataFormat = LocalProperties.get("gda.data.scan.datawriter.dataFormat")
        if not dataFormat == "NexusDataWriter":
            handle_messages.simpleLog(
                "Data format inconsistent. Setting 'gda.data.scan.datawriter.dataFormat' to 'NexusDataWriter'"
            )
            LocalProperties.set("gda.data.scan.datawriter.dataFormat", "NexusDataWriter")
        scanObject = createConcurrentScan(scan_args)
        if addNXEntry:
            addNXTomoSubentry(scanObject, tomography_detector.name, tomography_theta.name)
        scanObject.runScan()
        if autoAnalyse:
            lsdp = jns.lastScanDataPoint()
            OSCommandRunner.runNoWait(
                ["/dls_sw/apps/tomopy/tomopy/bin/gda/tomo_at_scan_end", lsdp.currentFilename],
                OSCommandRunner.LOGOPTION.ALWAYS,
                None,
            )
        return scanObject
    except InterruptedException:
        exceptionType, exception, traceback = sys.exc_info()
        handle_messages.log(None, "User interrupted the scan", exceptionType, exception, traceback, False)
        raise InterruptedException("User interrupted the scan")
    except:
        exceptionType, exception, traceback = sys.exc_info()
        handle_messages.log(None, "Error during tomography scan", exceptionType, exception, traceback, False)
        raise Exception("Error during tomography scan", exception)
    finally:
        handle_messages.simpleLog("Data Format reset to the original setting: " + dataFormat)
        LocalProperties.set("gda.data.scan.datawriter.dataFormat", dataFormat)
示例#18
0
def tomoScanWithFrames(description,
                       inBeamPosition,
                       outOfBeamPosition,
                       exposureTime=1.,
                       start=0.,
                       stop=180.,
                       step=0.1,
                       darkFieldInterval=0,
                       flatFieldInterval=0,
                       imagesPerDark=10,
                       imagesPerFlat=10,
                       optimizeBeamInterval=0,
                       pattern="default",
                       nframes=1,
                       tomoRotationAxis=0,
                       addNXEntry=True,
                       autoAnalyse=True,
                       additionalScannables=[]):
    """
    Function to collect a tomography step scan with multiple projection frames per scan point 
    Arguments:
    description - description of the scan or the sample that is being scanned. This is generally user-specific information that may be used to map to this scan later and is available in the NeXus file)
    inBeamPosition - position of X drive to move sample into the beam to take a projection
    outOfBeamPosition - position of X drive to move sample out of the beam to take a flat field image
    exposureTime - exposure time in seconds (default=1.0)
    start - first rotation angle (default=0.0)
    stop  - last rotation angle (default=180.0)
    step - rotation step size (default=0.1)
    darkFieldInterval - number of projection-frame sub-series between each dark-field sub-series. 
        NOTE: at least 1 dark is ALWAYS taken both at the start and end of the scan, provided imagesPerDark>0 
        (default=0: use this value if you DON'T want to take any darks between projections)
    flatFieldInterval - number of projection-frame sub-series between each flat-field sub-series. 
        NOTE: at least 1 flat is ALWAYS taken both at the start and end the scan, provided imagesPerFlat>0 
        (default=0: use this value if you DON'T want to take any flats between projections)
    imagesPerDark - number of images to be taken in each dark-field sub-series (default=10)
    imagesPerFlat - number of images to be taken in each flat-field sub-series (default=10)
    nframes - number of projection frames per angular position (default=1)
    
    General scan sequence is: D, F, P,..., P, F, D
    where D stands for dark field, F - for flat field, and P - for projection.
    """
    dataFormat = LocalProperties.get("gda.data.scan.datawriter.dataFormat")
    try:
        darkFieldInterval = int(darkFieldInterval)
        flatFieldInterval = int(flatFieldInterval)
        optimizeBeamInterval = int(optimizeBeamInterval)

        image_key_frame = 3
        nframes = int(nframes)
        if nframes < 1:
            nframes = 1

        jns = beamline_parameters.JythonNameSpaceMapping(
            InterfaceProvider.getJythonNamespace())
        tomography_theta = jns.tomography_theta
        if tomography_theta is None:
            raise NameError(
                "tomography_theta is not defined in Jython namespace")
        tomography_shutter = jns.tomography_shutter
        if tomography_shutter is None:
            raise NameError(
                "tomography_shutter is not defined in Jython namespace")
        tomography_translation = jns.tomography_translation
        if tomography_translation is None:
            raise NameError(
                "tomography_translation is not defined in Jython namespace")

        tomography_detector = jns.tomography_detector
        if tomography_detector is None:
            raise NameError(
                "tomography_detector is not defined in Jython namespace")

        tomography_optimizer = jns.tomography_optimizer
        if tomography_optimizer is None:
            raise NameError(
                "tomography_optimizer is not defined in Jython namespace")

        tomography_time = jns.tomography_time
        if tomography_time is None:
            raise NameError(
                "tomography_time is not defined in Jython namespace")

        tomography_beammonitor = jns.tomography_beammonitor
        if tomography_beammonitor is None:
            raise NameError(
                "tomography_beammonitor is not defined in Jython namespace")

        tomography_camera_stage = jns.tomography_camera_stage
        if tomography_camera_stage is None:
            raise NameError(
                "tomography_camera_stage is not defined in Jython namespace")

        tomography_sample_stage = jns.tomography_sample_stage
        if tomography_sample_stage is None:
            raise NameError(
                "tomography_sample_stage is not defined in Jython namespace")

        tomo_additional_scannables = jns.tomography_additional_scannables
        if tomo_additional_scannables is None:
            raise NameError(
                "tomo_additional_scannables is not defined in Jython namespace"
            )

        index = SimpleScannable()
        index.setCurrentPosition(0.0)
        index.setInputNames(["imageNumber"])
        index.setName("imageNumber")
        index.configure()

        image_key = SimpleScannable()
        image_key.setCurrentPosition(0.0)
        image_key.setInputNames(["image_key"])
        image_key.setName("image_key")
        image_key.configure()

        tomoScanDevice = make_tomoScanDevice(tomography_theta,
                                             tomography_shutter,
                                             tomography_translation,
                                             tomography_optimizer, image_key,
                                             index)

        #        return tomoScanDevice
        #generate list of positions
        numberSteps = ScannableUtils.getNumberSteps(tomography_theta, start,
                                                    stop, step)
        theta_points = []
        theta_points.append(start)
        previousPoint = start
        for i in range(numberSteps):
            nextPoint = ScannableUtils.calculateNextPoint(previousPoint, step)
            theta_points.append(nextPoint)
            previousPoint = nextPoint

        #generateScanPoints
        optimizeBeamNo = 0
        optimizeBeamYes = 1
        shutterOpen = 1
        shutterClosed = 0
        shutterNoChange = 2
        scan_points = []
        theta_pos = theta_points[0]
        index = 0
        #Added shutterNoChange state for the shutter. The scan points are added using the (pseudo) ternary operator,
        #if index is 0 then the shutterPosition is added to the scan point, else shutterNoChange is added to scan points.
        for i in range(imagesPerDark):
            scan_points.append(
                (theta_pos, [shutterClosed, shutterNoChange][i != 0],
                 inBeamPosition, optimizeBeamNo, image_key_dark, index))  #dark
            index = index + 1

        for i in range(imagesPerFlat):
            scan_points.append(
                (theta_pos, [shutterOpen,
                             shutterNoChange][i != 0], outOfBeamPosition,
                 optimizeBeamNo, image_key_flat, index))  #flat
            index = index + 1
        for frm in range(nframes):
            scan_points.append(
                (theta_pos, shutterOpen, inBeamPosition, optimizeBeamNo,
                 image_key_project if frm == 0 else image_key_frame,
                 index))  #first
            index = index + 1
        imageSinceDark = 1
        imageSinceFlat = 1
        optimizeBeam = 0
        for i in range(numberSteps):
            theta_pos = theta_points[i + 1]
            for frm in range(nframes):
                scan_points.append(
                    (theta_pos, [shutterOpen, shutterNoChange
                                 ][i != 0], inBeamPosition, optimizeBeamNo,
                     image_key_project if frm == 0 else image_key_frame,
                     index))  #main image
                index = index + 1

            imageSinceFlat = imageSinceFlat + 1
            if imageSinceFlat == flatFieldInterval and flatFieldInterval != 0:
                for i in range(imagesPerFlat):
                    scan_points.append(
                        (theta_pos, [shutterOpen, shutterNoChange
                                     ][i != 0], outOfBeamPosition,
                         optimizeBeamNo, image_key_flat, index))
                    index = index + 1
                    imageSinceFlat = 0

            imageSinceDark = imageSinceDark + 1
            if imageSinceDark == darkFieldInterval and darkFieldInterval != 0:
                for i in range(imagesPerDark):
                    scan_points.append(
                        (theta_pos, [shutterClosed,
                                     shutterNoChange][i != 0], inBeamPosition,
                         optimizeBeamNo, image_key_dark, index))
                    index = index + 1
                    imageSinceDark = 0

            optimizeBeam = optimizeBeam + 1
            if optimizeBeam == optimizeBeamInterval and optimizeBeamInterval != 0:
                scan_points.append(
                    (theta_pos, [shutterOpen,
                                 shutterNoChange][i != 0], inBeamPosition,
                     optimizeBeamYes, image_key_project, index))
                index = index + 1
                optimizeBeam = 0

        #add dark and flat only if not done in last steps
        if imageSinceFlat != 0:
            for i in range(imagesPerFlat):
                scan_points.append(
                    (theta_pos, [shutterOpen,
                                 shutterNoChange][i != 0], outOfBeamPosition,
                     optimizeBeamNo, image_key_flat, index))  #flat
                index = index + 1
        if imageSinceDark != 0:
            for i in range(imagesPerDark):
                scan_points.append(
                    (theta_pos, [shutterClosed,
                                 shutterNoChange][i != 0], inBeamPosition,
                     optimizeBeamNo, image_key_dark, index))  #dark
                index = index + 1


#        scan_points1 = generateScanPoints(inBeamPosition, outOfBeamPosition, theta_points, darkFieldInterval, flatFieldInterval,
#              imagesPerDark, imagesPerFlat, optimizeBeamInterval, pattern=pattern)
#        if pattern == 'default' or pattern == 'DFPFD':
#            i = 0
#            for pt1 in scan_points1:
#                pt = scan_points[i]
#                if pt1 != pt:
#                    print "Mismatch - please tell Kaz about your scan and its arguments!"
#                    print "i = ", i
#                    print "pt = ", pt
#                    print "pt1 = ", pt1
#                i += 1
#return None
        positionProvider = tomoScan_positions(start, stop, step, darkFieldInterval, imagesPerDark, flatFieldInterval, imagesPerFlat, \
                                               inBeamPosition, outOfBeamPosition, optimizeBeamInterval, scan_points)
        scan_args = [
            tomoScanDevice, positionProvider, tomography_time,
            tomography_beammonitor, tomography_detector, exposureTime,
            tomography_camera_stage, tomography_sample_stage
        ]
        #scan_args.append(RotationAxisScannable("approxCOR", tomoRotationAxis))
        #meta_add(RotationAxisScannable("approxCOR", tomoRotationAxis))
        #meta_add("RotationCoord_as_list", [tomoRotationAxis])
        meta_add("approxCOR", tomoRotationAxis)
        for scannable in additionalScannables:
            scan_args.append(scannable)
        for scannable in tomo_additional_scannables:
            scan_args.append(scannable)
        ''' setting the description provided as the title'''
        if not description == None:
            setTitle(description)
        else:
            setTitle("undefined")

        dataFormat = LocalProperties.get("gda.data.scan.datawriter.dataFormat")
        if not dataFormat == "NexusDataWriter":
            handle_messages.simpleLog(
                "Data format inconsistent. Setting 'gda.data.scan.datawriter.dataFormat' to 'NexusDataWriter'"
            )
            LocalProperties.set("gda.data.scan.datawriter.dataFormat",
                                "NexusDataWriter")
        scanObject = createConcurrentScan(scan_args)
        if addNXEntry:
            addNXTomoSubentry(scanObject, tomography_detector.name,
                              tomography_theta.name)
        scanObject.runScan()
        if autoAnalyse:
            lsdp = jns.lastScanDataPoint()
            OSCommandRunner.runNoWait([
                "/dls_sw/apps/tomopy/tomopy/bin/gda/tomo_at_scan_end_kz",
                lsdp.currentFilename
            ], OSCommandRunner.LOGOPTION.ALWAYS, None)
        return scanObject
    except InterruptedException:
        exceptionType, exception, traceback = sys.exc_info()
        handle_messages.log(None, "User interrupted the scan", exceptionType,
                            exception, traceback, False)
        raise InterruptedException("User interrupted the scan")
    except:
        exceptionType, exception, traceback = sys.exc_info()
        handle_messages.log(None, "Error during tomography scan",
                            exceptionType, exception, traceback, False)
        raise Exception("Error during tomography scan", exception)
    finally:
        handle_messages.simpleLog(
            "Data Format reset to the original setting: " + dataFormat)
        LocalProperties.set("gda.data.scan.datawriter.dataFormat", dataFormat)
示例#19
0
def localStation_exception(exc_info, msg):
    typ, exception, traceback = exc_info
    simpleLog("! Failure %s !" % msg)
    localStation_exceptions.append("    %s" % msg)
    handle_messages.log(None, "Error %s -  " % msg , typ, exception, traceback, False)
示例#20
0
wherescannables = [tth, th, chi, phi, h, k, l, en]  # @UndefinedVariable
try:
    wh = PositionWrapper(wherescannables)  ##can only be used with diffcalc
except:
    localStation_exception(sys.exc_info(), "create wh error.")

alias('wh')

from scannable.rocking.detectorWithRockingMotion import NXDetectorWithRockingMotion  # @UnusedImport
from gdaserver import pimte, pixis  # @UnresolvedImport

thpimte = NXDetectorWithRockingMotion("thpimte", th, pimte)
thpixis = NXDetectorWithRockingMotion("thpixis", th, pixis)

from scannable.positions.magnet_instances import magnetCurrent, magnetField  # @UnusedImport

#Please leave Panic stop customisation last - specify scannables to be excluded from Panic stop
from i10commands.stopJythonScannables import stopJythonScannablesExceptExcluded  # @UnusedImport
STOP_ALL_EXCLUSIONS = []  # @UndefinedVariable

if len(localStation_exceptions) > 0:
    simpleLog("=============== %r ERRORS DURING STARTUP ================" %
              len(localStation_exceptions))

for localStationException in localStation_exceptions:
    simpleLog(localStationException)

print "**************************************************"
print "localStation.py completed."
print "**************************************************"