Example #1
0
    def stateRequest(self, request, timeout=TIMEOUT):
        """
        Helper method used to get or set camera state.

        Parameters
        ----------
        request : `string`
            Command to be passed to the camera
        timeout : `float`
            Time to wait for camera answer

        Returns
        -------
        `int`
        """

        self.socket.send(request)
        timer = Timer(timeout)

        r = b''
        while b'\n' not in r and timer.wait(self.socket):
            r += self.socket.recv(1)

        if timer.expired():
            raise RuntimeError('Camera is not answering')

        r = r.strip(b'\x00\n')

        return int(r, 0)
Example #2
0
    def stateRequest(self, request, timeout=TIMEOUT):
        """
        Helper method used to get or set camera state.

        Parameters
        ----------
        request : `string`
            Command to be passed to the camera
        timeout : `float`
            Time to wait for camera answer

        Returns
        -------
        `int`
        """

        self.socket.send(request)
        timer = Timer(timeout)

        r = b''
        while b'\n' not in r and timer.wait(self.socket):
            r += self.socket.recv(1)

        if timer.expired():
            raise RuntimeError('Camera is not answering')

        r = r.strip(b'\x00\n')

        return int(r, 0)
Example #3
0
    def waitWhileOrUntil(self, condition, timeout=TIMEOUT, until=False):
        """
        Helper method that implements :meth:`waitWhile` and :meth:`waitUntil`
        """

        state = self.getState(timeout)
        timer = Timer(timeout)

        while until ^ bool(state & condition) and timer.check():
            state = self.getState(timeout)

            if state & self.STATE_MASK_ERROR:
                raise RuntimeError('Camera returned error: %x' % state)

        if timer.expired():
            raise RuntimeError('Camera got stuck condition: %x, state: %x' %
                               (condition, state))
Example #4
0
    def waitWhileOrUntil(self, condition, timeout=TIMEOUT, until=False):
        """
        Helper method that implements :meth:`waitWhile` and :meth:`waitUntil`
        """

        state = self.getState(timeout)
        timer = Timer(timeout)

        while until ^ bool(state & condition) and timer.check():
            state = self.getState(timeout)

            if state & self.STATE_MASK_ERROR:
                raise RuntimeError('Camera returned error: %x' % state)

        if timer.expired():
            raise RuntimeError('Camera got stuck condition: %x, state: %x' %
                               (condition, state))
Example #5
0
class Pilatus(StandardDevice, ICountable):
    """
    Class to control Pilatus cameras via EPICS.

    Examples
    --------
    >>> from shutil import move
    >>> from py4syn.epics.PilatusClass import Pilatus
    >>> from py4syn.epics.ShutterClass import SimpleShutter
    >>> 
    >>> def getImage(pv, fileName='image.tif', shutter=''):
    ...     shutter = SimpleShutter(shutter, shutter)
    ...     camera = Pilatus('pilatus', pv)
    ...     camera.setImageName('/remote/' + fileName)
    ...     camera.setCountTime(10)
    ...     camera.startCount()
    ...     shutter.open()
    ...     camera.wait()
    ...     camera.stopCount()
    ...     shutter.close()
    ...     move('/remote/' + fileName, '/home/user/' + fileName)
    ...     camera.close()
    ...
    """
    RESPONSE_TIMEOUT = 35

    def __init__(self, mnemonic, pv):
        """
        **Constructor**
        See :class:`py4syn.epics.StandardDevice`

        Parameters
        ----------
        mnemonic : `string`
            A mnemonic for the camera
        pv : `string`
            Base name of the EPICS process variable
        """
        super().__init__(mnemonic)
        self.acquireChanged = Event()
        self.acquiring = False
        self.pvAcquire = PV(pv + ':Acquire')
        self.pvAcquire.add_callback(self.statusChange)

        caput(pv + ':FileTemplate', '%s%s\0')
        caput(pv + ':FilePath', '\0')

        self.pvAcquireTime = PV(pv + ':AcquireTime')
        self.pvAcquirePeriod = PV(pv + ':AcquirePeriod')
        self.pvFilePath = PV(pv + ':FilePath')
        self.pvFileName = PV(pv + ':FileName')
        self.pvFileTemplate = PV(pv + ':FileTemplate')
        self.pvThreshold = PV(pv + ':ThresholdEnergy')
        self.pvBeamX = PV(pv + ':BeamX')
        self.pvBeamY = PV(pv + ':BeamY')
        self.pvWavelength = PV(pv + ':Wavelength')
        self.pvStartAngle = PV(pv + ':StartAngle')
        self.pvAngleIncr = PV(pv + ':AngleIncr')
        self.pvDetDist = PV(pv + ':DetDist')
        self.pvNumImages = PV(pv + ':NumImages')
        self.pvDelayTime = PV(pv + ':DelayTime')
        self.pvTriggerMode = PV(pv + ':TriggerMode')
        self.pvDet2Theta = PV(pv + ':Det2theta')
        self.pvCamserverConnectStatus = PV(pv + ':CamserverAsyn.CNCT')
        self.pvLastFileName = PV(pv + ":FullFileName_RBV")

        self.timer = Timer(self.RESPONSE_TIMEOUT)

    def setImageName(self, name):
        """
        Sets the output image file name. The image will be saved with this name
        after the acquisition.
        
        Parameters
        ----------
        name : `string`
            The full pathname of the image.
        """
        self.pvFileName.put(name + "\0", wait=True)

    def setFilePath(self, path):
        """
        Sets the output image file path. The image will be saved in this location
        after the acquisition.
        
        Parameters
        ----------
        name : `string`
            The path of location to save the image.
        """
        self.pvFilePath.put(path + "\0", wait=True)

    def getFilePath(self):
        """
        Returns the path where image file should be saved.
        """
        return self.pvFilePath.get(as_string=True)

    def setFileName(self, name):
        """
        Sets the output image file name. The image will be saved with this name
        after the acquisition.
        
        Parameters
        ----------
        name : `string`
            The name of image to save.
        """
        self.pvFileName.put(name + "\0", wait=True)

    def getFileName(self):
        """
        Returns the name of the image to be saved.
        """
        return self.pvFileName.get(as_string=True)

    def setFileTemplate(self, template="%s%s"):
        self.pvFileTemplate.put(template + "\0", wait=True)

    def getFileTemplate(self):
        return self.pvFileTemplate.get(as_string=True)

    def statusChange(self, value, **kw):
        """
        Helper callback used to wait for the end of the acquisition.
        """
        self.acquiring = value
        self.acquireChanged.set()

    def close(self):
        """
        Stops an ongoing acquisition, if any, and puts the EPICS IOC in idle state.
        """
        self.pvAcquire.put(0, wait=True)

    def getValue(self, **kwargs):
        """
        This is a dummy method that always returns zero, which is part of the
        :class:`py4syn.epics.ICountable` interface. Pilatus does not return
        a value while scanning. Instead, it stores a file with the resulting image.
        """
        return 0

    def setCountTime(self, t):
        """
        Sets the image acquisition time.

        Parameters
        ----------
        t : `float`
            Acquisition time
        """
        self.pvAcquireTime.put(t, wait=True)
        self.pvAcquirePeriod.put(t + READOUTTIME, wait=True)
        self.timer = Timer(t + self.RESPONSE_TIMEOUT)

    def getAcquireTime(self):
        return self.pvAcquireTime.get()

    def setAcquirePeriod(self, period):
        """
        Sets the acquire period.

        Parameters
        ----------
        t : `float`
            Acquisition period
        """
        self.pvAcquirePeriod.put(period, wait=True)

    def getAcquirePeriod(self):
        return self.pvAcquirePeriod.get()

    def setPresetValue(self, channel, val):
        """
        Dummy method to set initial counter value.
        """
        pass

    def startCount(self):
        """
        Starts acquiring an image. It will acquire for the duration set with
        :meth:`setCountTime`. The resulting file will be stored in the file set with
        :meth:`setImageName`.

        See: :meth:`setCountTime`, :meth:`setImageName`

            Examples
            --------
            >>> def acquire(pilatus, time, filename):
            ...     pilatus.setCountTime(time)
            ...     pilatus.setImageName(filename)
            ...     pilatus.startCount()
            ...     pilatus.wait()
            ...     pilatus.stopCount()
            ...
        """
        if self.acquiring:
            raise RuntimeError('Already counting')

        self.acquiring = True
        self.pvAcquire.put(1)
        self.timer.mark()

    def stopCount(self):
        """
        Stops acquiring the image. This method simply calls :meth:`close`.
        
        See: :meth:`close`
        """
        self.close()

    def canMonitor(self):
        """
        Returns false indicating that Pilatus cannot be used as a counter monitor.
        """
        return False

    def canStopCount(self):
        """
        Returns true indicating that Pilatus has a stop command.
        """
        return True

    def isCounting(self):
        """
        Returns true if the camera is acquiring an image, or false otherwise.

        Returns
        -------
        `bool`
        """
        return self.acquiring

    def wait(self):
        """
        Blocks until the acquisition completes.
        """
        if not self.acquiring:
            return

        self.acquireChanged.clear()
        while self.acquiring and self.timer.check():
            self.acquireChanged.wait(5)
            self.acquireChanged.clear()

        if self.timer.expired():
            raise RuntimeError('Camera is not answering')

    def setThreshold(self, threshold, wait=True):
        self.pvThreshold.put(threshold, wait=wait)

    def getThreshold(self):
        return self.pvThreshold.get()

    def setBeamPosition(self, position=[0, 0]):
        self.pvBeamX.put(position[0], wait=True)
        self.pvBeamY.put(position[1], wait=True)

    def getBeamPosition(self):
        return [self.pvBeamX.get(), self.pvBeamY.get()]

    def setWavelength(self, wavelength):
        self.pvWavelength.put(wavelength, wait=True)

    def getWavelength(self):
        return self.pvWavelength.get()

    def setStartAngle(self, start):
        self.pvStartAngle.put(start, wait=True)

    def getStartAngle(self):
        return self.pvStartAngle.get()

    def setAngleIncr(self, incr):
        self.pvAngleIncr.put(incr, wait=True)

    def getAngleIncr(self):
        return self.pvAngleIncr.get()

    def setDetDist(self, distance):
        self.pvDetDist.put(distance, wait=True)

    def getDetDist(self):
        return self.pvDetDist.get()

    def setNumImages(self, num):
        self.pvNumImages.put(num, wait=True)

    def getNumImages(self):
        return self.pvNumImages.get()

    def setDelayTime(self, delay):
        self.pvDelayTime.put(delay, wait=True)

    def getDelayTime(self):
        return self.pvDelayTime.get()

    def setTriggerMode(self, mode):
        """
        Trigger mode

        Parameters
        ----------
        mode  : `int`
            0 : Internal
            1 : Ext. Enable
            2 : Ext. Trigger
            3 : Mult. Trigger
            4 : Alignment
        """
        self.pvTriggerMode.put(mode, wait=True)

    def getTriggerMode(self):
        return self.pvTriggerMode.get()

    def setDet2Theta(self, det2theta):
        self.pvDet2Theta.put(det2theta, wait=True)

    def getDet2Theta(self):
        return self.pvDet2Theta.get()

    def isCamserverConnected(self):
        return (self.pvCamserverConnectStatus.get() == 1)
Example #6
0
class OceanOpticsSpectrometer(ImageHDF):
    # CONSTRUCTOR OF Ocean CLASS
    def __init__(self,
                 mnemonic,
                 pv=None,
                 responseTimeout=15,
                 output="./out",
                 numPoints=1044,
                 mcas=False):
        """Constructor
        responseTimeout : how much time to wait qe65000 answer
        numPoints : how many points are collected each time
        """
        super().__init__(mnemonic, numPoints, output, 'ocean')
        self.acquireChanged = Event()
        self.acquiring = False

        try:
            # determines the start of counting
            self.pvStart = PV(pv + ":Acquire")
            # determines mode of Acquisition (Single,Continous, Dark Spectrum)
            self.pvAcquireMode = PV(pv + ":AcquisitionMode")

            # use darkcorrection
            self.pvDarkCorrection = PV(pv + ":ElectricalDark")

            # spectrum
            self.pvSpectrum = PV(pv + ":Spectra")
            self.pvSpectrumCorrected = PV(pv + ":DarkCorrectedSpectra")

            # set Acquire Time
            self.pvAcquireTime = PV(pv + ":SetIntegration")

            # integration Time
            self.pvTime = PV(pv + ":IntegrationTime:Value")

            # control the end of acquire process
            self.pvAcquire = PV(pv + ":Acquiring")
            self.pvAcquire.add_callback(self.statusChange)

            # acquisition mode
            self.pvAcMode = PV(pv + ":AcquisitionMode")
            # set to single mode
            self.pvAcMode.put("Single")

            # axis Spectra
            pvAxis = PV(pv + ":SpectraAxis")
            self.axis = pvAxis.get(as_numpy=True)[:self.numPoints]

            # regions of interest
            self.ROIS = []

            self.mcas = mcas

            self.responseTimeout = responseTimeout
            self.timer = Timer(self.responseTimeout)
        except TypeError:
            raise RuntimeError('PV not found')
        except ValueError:
            raise RuntimeError('Device is offline')

    def statusChange(self, value, **kw):
        """
        Helper callback used to wait for the end of the acquisition.
        """
        if value == 0:
            self.acquiring = False
        else:
            self.acquiring = True
        # threads waiting are awakened
        self.acquireChanged.set()

    def setCountTime(self, time):
        """
        Method to set the count time of a scaler device.

        Parameters
        ----------
        time : `float`
            Count time to set to scaler device .

        Returns
        -------
        out : None
        """
        self.pvTime.put(time, wait=True)
        self.timer = Timer(time + self.responseTimeout)

    def getCountTime(self):
        return self.pvTime.get()

    def setCountStop(self):
        # TODO: test
        # Work only when in continuos mode
        pass

    def close(self):
        self.setCountStop()

    def saveUniquePoint(self, data, fmt, suffixName=""):
        self.mcaFile = super().nameFile(self.output, self.prefix + suffixName,
                                        "mca")
        np.savetxt(self.mcaFile, data, fmt=fmt)

    def saveSpectrum(self, **kwargs):
        ''' save the spectrum intensity in a mca file or an hdf file '''
        dark = self.pvDarkCorrection.get()

        # the spectra come from different pv if use darkcorrection
        if dark == 1:
            allSpectrum =\
                self.pvSpectrumCorrected.get(as_numpy=True)[:self.numPoints]
        else:
            allSpectrum = self.pvSpectrum.get(as_numpy=True)[:self.numPoints]

        self.spectrum = allSpectrum

        suffix = ""
        if self.image:
            super().saveSpectrum()

        if not self.image or self.mcas:
            self.saveUniquePoint(
                np.array([self.axis, self.spectrum]).T, "%f\t%f")

        # there are ROIS to save / works only for points
        if len(self.ROIS) > 0 and not self.image:
            i = 1
            for mini, maxi in self.ROIS:
                # get the spectrum positions
                start = bisect(self.axis, mini)
                end = bisect(self.axis, maxi)
                roi = allSpectrum[start:end]
                self.spectrum = roi
                data = np.array([self.axis[start:end], self.spectrum]).T
                self.saveUniquePoint(data,
                                     "%f\t%f",
                                     suffixName="_ROI" + str(i))
                i += 1

    def isCountRunning(self):
        return (self.acquiring)

    def wait(self):
        """
        Blocks until the acquisition completes.
        """
        if self.acquiring is False:
            return

        self.acquireChanged.clear()
        # while acquiring and not time out waits
        # TODO: find a better way to do this
        while self.acquiring and self.timer.check():
            self.acquireChanged.wait(0.001)
            self.acquireChanged.clear()

        if self.timer.expired():
            raise RuntimeError('Ocean is not answering')

    def canMonitor(self):
        """ Returns false indicating cannot be use as a counter monitor"""
        return False

    def canStopCount(self):
        """
        Returns true indicating that Dxp has a stop command.
        """
        return False

    def getValue(self, **kwargs):
        """Return intensity
        It's a dummy method, always return 1.0. """
        self.saveSpectrum()
        return 1.0

    def isCounting(self):
        return self.acquiring

    def startCount(self):
        """ Starts acquiring an spectrum
        It's necessary to call setCounTime before"""

        if self.acquiring:
            raise RuntimeError('Already counting')

        self.acquiring = True
        self.pvStart.put("Stop")
        # resets initial time value
        self.timer.mark()

    def stopCount(self):
        self.setCountStop()

    def setPresetValue(self, channel, val):
        """Dummy method"""
        pass

    def startCollectImage(self, rows=0, cols=0):
        super().startCollectImage('float32', rows, cols)

    def addRoi(self, roi):
        """ Insert a new roi
        roi: a tuple with begin and end: (begin,end)"""
        self.ROIS.append(roi)
Example #7
0
class Dxp(StandardDevice, ICountable):
    # CONSTRUCTOR OF DXP CLASS
    def __init__(self,
                 mnemonic,
                 output,
                 numberOfChannels=4,
                 numberOfRois=32,
                 pv=None,
                 dxpType="mca",
                 responseTimeout=15):
        """ Constructor
        responseTimeout : how much time to wait dxp answer
        """
        super().__init__(mnemonic)
        self.acquireChanged = Event()
        self.acquiring = False
        self.fileName = output

        # determines the start of counting
        self.pvDxpEraseStart = PV(pv + ":EraseStart.VAL")
        # determines mode of counting (Live Time, Real Time, ...)
        self.pvDxpPresetMode = PV(pv + ":PresetMode.VAL")

        self.pvDxpStop = PV(pv + ":StopAll.VAL")
        # store all channels
        self.pvDxpChannels = []
        # store ROIs
        self.pvDxpRois = []

        # store Acquire Time for each channel
        self.pvDxpAcquireTime = []

        for c in range(0, numberOfChannels):
            # store each channel
            self.pvDxpChannels.append(PV(pv + ":" + dxpType + str(c + 1)))
            # for each channel store the PV for AcquireTime
            self.pvDxpAcquireTime.append(
                PV(pv + ":" + dxpType + "%d.PLTM" % (c + 1)))
            self.pvDxpRois.append([])
            # storeing each ROI in your channel
            for r in range(0, numberOfRois):
                self.pvDxpRois[c].append(
                    PV(pv + ":" + dxpType + str(c + 1) + '.R' + str(r)))

        self.pvDxpAcquire = PV(pv + ":Acquiring")
        self.pvDxpAcquire.add_callback(self.statusChange)
        self.channels = numberOfChannels
        self.dxpType = dxpType
        self.rois = numberOfRois

        self.responseTimeout = responseTimeout
        self.timer = Timer(self.responseTimeout)

    def statusChange(self, value, **kw):
        """
        Helper callback used to wait for the end of the acquisition.
        """
        self.acquiring = value
        # threads waiting are awakened
        self.acquireChanged.set()

    def setCountTime(self, time):
        """
        Method to set the count time of a scaler device.

        Parameters
        ----------
        time : `float`
            Count time to set to scaler device .

        Returns
        -------
        out : None
        """
        for i in range(0, self.channels):
            self.pvDxpAcquireTime[i].put(time, wait=True)
        self.timer = Timer(time + self.responseTimeout)

    def getCountTime(self):
        return self.pvDxpTime.get()

    def setCountStop(self):
        self.pvDxpStop.put(1, wait=True)

    def getValueChannel(self, **kwargs):
        """Return intensity
        channel is on format mcaC.Rr, where C is  the channel and
        r is the ROI"""
        channel = kwargs['channel']
        c = int(channel[3]) - 1
        if (len(channel) > 4):
            r = int(channel[5])
            return self.pvDxpRois[c][r]
        else:
            self.saveSpectrum(c, **kwargs)
            return 1.0

    # save the spectrum intensity in a mca file
    def saveSpectrum(self, ch, **kwargs):
        fileName = self.fileName
        idx = 0
        if (fileName):
            spectrum = self.pvDxpChannels[ch].get(as_numpy=True)
            prefix = fileName.split('.')[0]
            while os.path.exists('%s_%s%d_%04d.mca' %
                                 (prefix, self.dxpType, ch, idx)):
                idx += 1
            fileName = '%s_%s%d_%04d.mca' % \
                       (prefix, self.dxpType, ch, idx)
        np.savetxt(fileName, spectrum, fmt='%f')

    def isCountRunning(self):
        return (self.pvDxpAcquire.get())

    def wait(self):
        """
        Blocks until the acquisition completes.
        """
        if self.acquiring is False:
            return

        self.acquireChanged.clear()
        # while acquiring and not time out waits
        # TODO: find a better way to do this
        while self.acquiring and self.timer.check():
            self.acquireChanged.wait(0.001)
            self.acquireChanged.clear()

        if self.timer.expired():
            raise RuntimeError('DXP is not answering')

    def canMonitor(self):
        """ Returns false indcating Dxp cannot be use as a counter monitor"""
        return False

    def canStopCount(self):
        """
        Returns true indicating that Dxp has a stop command.
        """
        return True

    def getValue(self, **kwargs):
        """
        This is a dummy method that always returns zero, which is part of the
        :class:`py4syn.epics.ICountable` interface. Dxp does not return
        a value while scanning. Instead, it stores a mca file with result .
        """
        if (kwargs):
            return self.getValueChannel(**kwargs)
        return self.getValueChannel()

    def isCounting(self):
        return self.acquiring

    def startCount(self):
        """ Starts acquiring an spectrum
        It's necessary to call setCounTime before"""

        if self.acquiring:
            raise RuntimeError('Already counting')

        self.acquiring = True
        self.pvDxpEraseStart.put(1)
        # resets initial time value
        self.timer.mark()

    def stopCount(self):
        self.setCountStop()

    def setPresetValue(self, channel, val):
        """Dummy method"""
        pass

    def close(self):
        """Stops an ongoing acquisition, if any, and puts the EPICS IOC in
        idle state."""
        self.pvDxpStop.put(1, wait=True)
Example #8
0
class Dxp(ImageHDF):

    # CONSTRUCTOR OF DXP CLASS
    def __init__(self,
                 mnemonic,
                 numberOfChannels=4,
                 numberOfRois=32,
                 pv=None,
                 dxpType="mca",
                 responseTimeout=15,
                 output="./out",
                 numPoints=2048):
        """ Constructor
        responseTimeout : how much time to wait dxp answer
        imageDeep : how many points are collected each time
        """
        super().__init__(mnemonic, numPoints, output, dxpType)

        self.dxpType = dxpType
        self.acquireChanged = Event()
        self.acquiring = False

        # determines the start of counting
        self.pvDxpEraseStart = PV(pv + ":EraseStart.VAL")
        # determines mode of counting (Live Time, Real Time, ...)
        self.pvDxpPresetMode = PV(pv + ":PresetMode.VAL")

        self.pvDxpStop = PV(pv + ":StopAll.VAL")
        # store all channels
        self.pvDxpChannels = []
        # store ROIs
        self.pvDxpRois = []

        # store Acquire Time for each channel
        self.pvDxpAcquireTime = []
        self.pvDxpRealTime = []

        for c in range(0, numberOfChannels):
            # store each channel
            self.pvDxpChannels.append(PV(pv + ":" + dxpType + str(c + 1)))
            # for each channel store the PV for AcquireTime
            self.pvDxpAcquireTime.append(
                PV(pv + ":" + dxpType + "%d.PLTM" % (c + 1)))
            # real time
            self.pvDxpRealTime.append(
                PV(pv + ":" + dxpType + "%d.ERTM" % (c + 1)))
            self.pvDxpRois.append([])
            # storeing each ROI in your channel
            for r in range(0, numberOfRois):
                self.pvDxpRois[c].append(
                    PV(pv + ":" + dxpType + str(c + 1) + '.R' + str(r)))

        self.pvDxpAcquire = PV(pv + ":Acquiring")
        self.pvDxpAcquire.add_callback(self.statusChange)
        self.channels = numberOfChannels
        self.rois = numberOfRois

        self.responseTimeout = responseTimeout
        self.timer = Timer(self.responseTimeout)

    def statusChange(self, value, **kw):
        """
        Helper callback used to wait for the end of the acquisition.
        """
        self.acquiring = value
        # threads waiting are awakened
        self.acquireChanged.set()

    def setCountTime(self, time):
        """
        Method to set the count time of a scaler device.

        Parameters
        ----------
        time : `float`
            Count time to set to scaler device .

        Returns
        -------
        out : None
        """
        for i in range(0, self.channels):
            self.pvDxpAcquireTime[i].put(time, wait=True)

        # This make long exposure time works
        if (self.responseTimeout < time * 0.4):
            self.responseTimeout = time * 0.4

        self.timer = Timer(time + self.responseTimeout)

    def getCountTime(self):
        # AcquireTimes are the same
        return self.pvDxpAcquireTime[0].get()

    def getRealTime(self):
        """Return the Real Time"""
        if self.channels == 1:
            return self.pvDxpRealTime[0].get()
        else:
            times = []
            for i in range(0, self.channels):
                times.append(self.pvDxpRealTime[i].get())
            return times

    def setCountStop(self):
        self.pvDxpStop.put(1, wait=True)

    def getValueChannel(self, **kwargs):
        """Return intensity
        channel is on format mcaC.Rr, where C is  the channel and
        r is the ROI"""
        channel = kwargs['channel']
        c = int(channel[CHANNELPOSITION]) - 1
        if (len(channel) > ROIPOSITION):
            r = int(channel[ROIPOSITION])
            return self.pvDxpRois[c][r].get()
        else:
            self.saveSpectrum(c, **kwargs)
            return 1.0

    def saveSpectrum(self, ch, **kwargs):
        '''save the spectrum intensity in a mca file or an hdf file
        This method load spectrum from a PV and then save it to HDF file'''
        self.pvDxpPresetMode.put("Live time")
        self.ch = ch
        self.spectrum = self.pvDxpChannels[self.ch].get(as_numpy=True)

        if self.image is None:
            # if is a point, prefix is different
            self.prefix = self.dxpType + str(self.ch)

        super().saveSpectrum()

    def isCountRunning(self):
        return (self.pvDxpAcquire.get())

    def wait(self):
        """
        Blocks until the acquisition completes.
        """
        if self.acquiring is False:
            return

        self.acquireChanged.clear()
        # while acquiring and not time out waits
        # TODO: find a better way to do this
        while self.acquiring and self.timer.check():
            self.acquireChanged.wait(0.001)
            self.acquireChanged.clear()

        if self.timer.expired():
            raise RuntimeError('DXP is not answering')

    def canMonitor(self):
        """ Returns false indcating Dxp cannot be use as a counter monitor"""
        return False

    def canStopCount(self):
        """
        Returns true indicating that Dxp has a stop command.
        """
        return True

    def getValue(self, **kwargs):
        """
        This is a dummy method that always returns zero, which is part of the
        :class:`py4syn.epics.ICountable` interface. Dxp does not return
        a value while scanning. Instead, it stores a mca file with result .
        """
        if (kwargs):
            return self.getValueChannel(**kwargs)
        return self.getValueChannel()

    def isCounting(self):
        return self.acquiring

    def startCount(self):
        """ Starts acquiring an spectrum
        It's necessary to call setCounTime before"""
        if self.acquiring:
            raise RuntimeError('Already counting')

        self.acquiring = True
        self.pvDxpEraseStart.put(1)
        # resets initial time value
        self.timer.mark()

    def stopCount(self):
        self.setCountStop()

    def setPresetValue(self, channel, val):
        """Dummy method"""
        pass

    def close(self):
        """Stops an ongoing acquisition, if any, and puts the EPICS IOC in
        idle state."""
        self.pvDxpStop.put(1, wait=True)

    def startCollectImage(self, rows=0, cols=0):
        """Start to collect an image
        When collect an image, the points will be  saved on a hdf file"""
        super().startCollectImage("int32", rows, cols)

    def setNormValue(self, value):
        """Applies normalization"""
        if self.image is None:
            self.prefix = self.dxpType + str(self.ch)

        super().setNormValue(value)