Ejemplo n.º 1
0
 def set_splineFile(self, splineFile):
     if splineFile is not None:
         self._splineFile = os.path.abspath(splineFile)
         self.spline = Spline(self._splineFile)
         # NOTA : X is axis 1 and Y is Axis 0
         self._pixel2, self._pixel1 = self.spline.getPixelSize()
         self._splineCache = {}
     else:
         self._splineFile = None
         self.spline = None
Ejemplo n.º 2
0
 def set_splineFile(self, splineFile):
     if splineFile is not None:
         self._splineFile = os.path.abspath(splineFile)
         self.spline = Spline(self._splineFile)
         # NOTA : X is axis 1 and Y is Axis 0
         self._pixel2, self._pixel1 = self.spline.getPixelSize()
         self._splineCache = {}
     else:
         self._splineFile = None
         self.spline = None
Ejemplo n.º 3
0
class Detector(object):
    """
    Generic class representing a 2D detector
    """
    force_pixel = False
    def __init__(self, pixel1=None, pixel2=None, splineFile=None):
        """
        @param pixel1: size of the pixel in meter along the slow dimension (often Y)
        @type pixel1: float
        @param pixel2: size of the pixel in meter along the fast dimension (ofter x)
        @type pixel2: float
        @param splineFile: path to file containing the geometric correction.
        @type splineFile: str
        """
        self.name = self.__class__.__name__
        self._pixel1 = None
        self._pixel2 = None
        if pixel1:
            self.pixel1 = pixel1
        if pixel2:
            self.pixel2 = pixel2
        self.max_shape = (None, None)
        self._binning = (1, 1)
        self._mask = False
        self._mask_crc = None
        self._maskfile = None
        self._splineFile = None
        self.spline = None
        self._splineCache = {}  # key=(dx,xpoints,ypoints) value: ndarray
        self._sem = threading.Semaphore()
        if splineFile:
            self.set_splineFile(splineFile)

    def __repr__(self):
        if (self._pixel1 is None) or (self._pixel2 is None):
            return "Undefined detector"
        return "Detector %s\t Spline= %s\t PixelSize= %.3e, %.3e m" % \
            (self.name, self.splineFile, self._pixel1, self._pixel2)

    def get_splineFile(self):
        return self._splineFile

    def set_splineFile(self, splineFile):
        if splineFile is not None:
            self._splineFile = os.path.abspath(splineFile)
            self.spline = Spline(self._splineFile)
            # NOTA : X is axis 1 and Y is Axis 0
            self._pixel2, self._pixel1 = self.spline.getPixelSize()
            self._splineCache = {}
        else:
            self._splineFile = None
            self.spline = None
    splineFile = property(get_splineFile, set_splineFile)

    def get_binning(self):
        return self._binning

    def set_binning(self, bin_size=(1, 1)):
        """
        Set the "binning" of the detector,

        @param bin_size: binning as integer or tuple of integers.
        @type bin_size: (int, int)
        """
        if "__len__" in dir(bin_size) and len(bin_size) >= 2:
            bin_size = (float(bin_size[0]), float(bin_size[1]))
        else:
            b = float(bin_size)
            bin_size = (b, b)
        if bin_size != self._binning:
            ratioX = bin_size[1] / self._binning[1]
            ratioY = bin_size[0] / self._binning[0]
            if self.spline is not None:
                self.spline.bin((ratioX, ratioY))
                self._pixel2, self._pixel1 = self.spline.getPixelSize()
                self._splineCache = {}
            else:
                self._pixel1 *= ratioY
                self._pixel2 *= ratioX
            self._binning = bin_size

    binning = property(get_binning, set_binning)


    def getPyFAI(self):
        """
        Helper method to serialize the description of a detector using the pyFAI way
        with everything in S.I units.

        @return: representation of the detector easy to serialize
        @rtype: dict
        """
        return {"detector": self.name,
                "pixel1": self._pixel1,
                "pixel2": self._pixel2,
                "splineFile": self._splineFile}

    def getFit2D(self):
        """
        Helper method to serialize the description of a detector using the Fit2d units

        @return: representation of the detector easy to serialize
        @rtype: dict
        """
        return {"pixelX": self._pixel2 * 1e6,
                "pixelY": self._pixel1 * 1e6,
                "splineFile": self._splineFile}

    def setPyFAI(self, **kwarg):
        """
        Twin method of getPyFAI: setup a detector instance according to a description

        @param kwarg: dictionary containing detector, pixel1, pixel2 and splineFile

        """
        if "detector" in kwarg:
            self = detector_factory(kwarg["detector"])
        for kw in kwarg:
            if kw in ["pixel1", "pixel2"]:
                setattr(self, kw, kwarg[kw])
            elif kw == "splineFile":
                self.set_splineFile(kwarg[kw])

    def setFit2D(self, **kwarg):
        """
        Twin method of getFit2D: setup a detector instance according to a description

        @param kwarg: dictionary containing pixel1, pixel2 and splineFile

        """
        for kw, val in kwarg.items():
            if kw == "pixelX":
                self.pixel2 = val * 1e-6
            elif kw == "pixelY":
                self.pixel1 = val * 1e-6
            elif kw == "splineFile":
                self.set_splineFile(kwarg[kw])

    def calc_cartesian_positions(self, d1=None, d2=None):
        """
        Calculate the position of each pixel center in cartesian coordinate
        and in meter of a couple of coordinates.
        The half pixel offset is taken into account here !!!

        @param d1: the Y pixel positions (slow dimension)
        @type d1: ndarray (1D or 2D)
        @param d2: the X pixel positions (fast dimension)
        @type d2: ndarray (1D or 2D)

        @return: position in meter of the center of each pixels.
        @rtype: ndarray

        d1 and d2 must have the same shape, returned array will have
        the same shape.
        """
        if (d1 is None):
            d1 = numpy.outer(numpy.arange(self.max_shape[0]), numpy.ones(self.max_shape[1]))

        if (d2 is None):
            d2 = numpy.outer(numpy.ones(self.max_shape[0]), numpy.arange(self.max_shape[1]))

        if self.spline is None:
            dX = 0.
            dY = 0.
        else:
            if d2.ndim == 1:
                keyX = ("dX", tuple(d1), tuple(d2))
                keyY = ("dY", tuple(d1), tuple(d2))
                if keyX not in self._splineCache:
                    self._splineCache[keyX] = \
                        numpy.array([self.spline.splineFuncX(i2, i1)
                                     for i1, i2 in zip(d1 + 0.5, d2 + 0.5)],
                                    dtype="float64")
                if keyY not in self._splineCache:
                    self._splineCache[keyY] = \
                        numpy.array([self.spline.splineFuncY(i2, i1)
                                     for i1, i2 in zip(d1 + 0.5, d2 + 0.5)],
                                    dtype="float64")
                dX = self._splineCache[keyX]
                dY = self._splineCache[keyY]
            else:
                dX = self.spline.splineFuncX(d2 + 0.5, d1 + 0.5)
                dY = self.spline.splineFuncY(d2 + 0.5, d1 + 0.5)
        p1 = (self._pixel1 * (dY + 0.5 + d1))
        p2 = (self._pixel2 * (dX + 0.5 + d2))
        return p1, p2

    def calc_mask(self):
        """
        Detectors with gaps should overwrite this method with
        something actually calculating the mask!
        """
#        logger.debug("Detector.calc_mask is not implemented for generic detectors")
        return None

    ############################################################################
    # Few properties
    ############################################################################
    def get_mask(self):
        if self._mask is False:
            with self._sem:
                if self._mask is False:
                    self._mask = self.calc_mask()  # gets None in worse cases
                    if self._mask is not None:
                        self._mask_crc = crc32(self._mask)
        return self._mask
    def set_mask(self, mask):
        with self._sem:
            self._mask = mask
            if mask is not None:
                self._mask_crc = crc32(mask)
            else:
                self._mask_crc = None
    mask = property(get_mask, set_mask)
    def set_maskfile(self, maskfile):
        if fabio:
            with self._sem:
                self._mask = numpy.ascontiguousarray(fabio.open(maskfile).data,
                                                     dtype=numpy.int8)
                self._mask_crc = crc32(self._mask)
                self._maskfile = maskfile
        else:
            logger.error("FabIO is not available, unable to load the image to set the mask.")

    def get_maskfile(self):
        return self._maskfile
    maskfile = property(get_maskfile, set_maskfile)

    def get_pixel1(self):
        return self._pixel1
    def set_pixel1(self, value):
        if isinstance(value, float):
            self._pixel1 = value
        elif isinstance(value, (tuple, list)):
            self._pixel1 = float(value[0])
        else:
            self._pixel1 = float(value)
    pixel1 = property(get_pixel1, set_pixel1)

    def get_pixel2(self):
        return self._pixel2
    def set_pixel2(self, value):
        if isinstance(value, float):
            self._pixel2 = value
        elif isinstance(value, (tuple, list)):
            self._pixel2 = float(value[0])
        else:
            self._pixel2 = float(value)
    pixel2 = property(get_pixel2, set_pixel2)
Ejemplo n.º 4
0
class Detector(object):
    """
    Generic class representing a 2D detector
    """
    force_pixel = False
    def __init__(self, pixel1=None, pixel2=None, splineFile=None):
        """
        @param pixel1: size of the pixel in meter along the slow dimension (often Y)
        @type pixel1: float
        @param pixel2: size of the pixel in meter along the fast dimension (ofter x)
        @type pixel2: float
        @param splineFile: path to file containing the geometric correction.
        @type splineFile: str
        """
        self.name = self.__class__.__name__
        self._pixel1 = None
        self._pixel2 = None
        if pixel1:
            self.pixel1 = pixel1
        if pixel2:
            self.pixel2 = pixel2
        self.max_shape = (None, None)
        self._binning = (1, 1)
        self._mask = False
        self._mask_crc = None
        self._maskfile = None
        self._splineFile = None
        self.spline = None
        self._splineCache = {}  # key=(dx,xpoints,ypoints) value: ndarray
        self._sem = threading.Semaphore()
        if splineFile:
            self.set_splineFile(splineFile)

    def __repr__(self):
        if (self._pixel1 is None) or (self._pixel2 is None):
            return "Undefined detector"
        return "Detector %s\t Spline= %s\t PixelSize= %.3e, %.3e m" % \
            (self.name, self.splineFile, self._pixel1, self._pixel2)

    def get_splineFile(self):
        return self._splineFile

    def set_splineFile(self, splineFile):
        if splineFile is not None:
            self._splineFile = os.path.abspath(splineFile)
            self.spline = Spline(self._splineFile)
            # NOTA : X is axis 1 and Y is Axis 0
            self._pixel2, self._pixel1 = self.spline.getPixelSize()
            self._splineCache = {}
        else:
            self._splineFile = None
            self.spline = None
    splineFile = property(get_splineFile, set_splineFile)

    def get_binning(self):
        return self._binning

    def set_binning(self, bin_size=(1, 1)):
        """
        Set the "binning" of the detector,

        @param bin_size: binning as integer or tuple of integers.
        @type bin_size: (int, int)
        """
        if "__len__" in dir(bin_size) and len(bin_size) >= 2:
            bin_size = (float(bin_size[0]), float(bin_size[1]))
        else:
            b = float(bin_size)
            bin_size = (b, b)
        if bin_size != self._binning:
            ratioX = bin_size[1] / self._binning[1]
            ratioY = bin_size[0] / self._binning[0]
            if self.spline is not None:
                self.spline.bin((ratioX, ratioY))
                self._pixel2, self._pixel1 = self.spline.getPixelSize()
                self._splineCache = {}
            else:
                self._pixel1 *= ratioY
                self._pixel2 *= ratioX
            self._binning = bin_size

    binning = property(get_binning, set_binning)


    def getPyFAI(self):
        """
        Helper method to serialize the description of a detector using the pyFAI way
        with everything in S.I units.

        @return: representation of the detector easy to serialize
        @rtype: dict
        """
        return {"detector": self.name,
                "pixel1": self._pixel1,
                "pixel2": self._pixel2,
                "splineFile": self._splineFile}

    def getFit2D(self):
        """
        Helper method to serialize the description of a detector using the Fit2d units

        @return: representation of the detector easy to serialize
        @rtype: dict
        """
        return {"pixelX": self._pixel2 * 1e6,
                "pixelY": self._pixel1 * 1e6,
                "splineFile": self._splineFile}

    def setPyFAI(self, **kwarg):
        """
        Twin method of getPyFAI: setup a detector instance according to a description

        @param kwarg: dictionary containing detector, pixel1, pixel2 and splineFile

        """
        if "detector" in kwarg:
            self = detector_factory(kwarg["detector"])
        for kw in kwarg:
            if kw in ["pixel1", "pixel2"]:
                setattr(self, kw, kwarg[kw])
            elif kw == "splineFile":
                self.set_splineFile(kwarg[kw])

    def setFit2D(self, **kwarg):
        """
        Twin method of getFit2D: setup a detector instance according to a description

        @param kwarg: dictionary containing pixel1, pixel2 and splineFile

        """
        for kw, val in kwarg.items():
            if kw == "pixelX":
                self.pixel2 = val * 1e-6
            elif kw == "pixelY":
                self.pixel1 = val * 1e-6
            elif kw == "splineFile":
                self.set_splineFile(kwarg[kw])

    def calc_cartesian_positions(self, d1=None, d2=None):
        """
        Calculate the position of each pixel center in cartesian coordinate
        and in meter of a couple of coordinates.
        The half pixel offset is taken into account here !!!

        @param d1: the Y pixel positions (slow dimension)
        @type d1: ndarray (1D or 2D)
        @param d2: the X pixel positions (fast dimension)
        @type d2: ndarray (1D or 2D)

        @return: position in meter of the center of each pixels.
        @rtype: ndarray

        d1 and d2 must have the same shape, returned array will have
        the same shape.
        """
        if (d1 is None):
            d1 = numpy.outer(numpy.arange(self.max_shape[0]), numpy.ones(self.max_shape[1]))

        if (d2 is None):
            d2 = numpy.outer(numpy.ones(self.max_shape[0]), numpy.arange(self.max_shape[1]))

        if self.spline is None:
            dX = 0.
            dY = 0.
        else:
            if d2.ndim == 1:
                keyX = ("dX", tuple(d1), tuple(d2))
                keyY = ("dY", tuple(d1), tuple(d2))
                if keyX not in self._splineCache:
                    self._splineCache[keyX] = \
                        numpy.array([self.spline.splineFuncX(i2, i1)
                                     for i1, i2 in zip(d1 + 0.5, d2 + 0.5)],
                                    dtype="float64")
                if keyY not in self._splineCache:
                    self._splineCache[keyY] = \
                        numpy.array([self.spline.splineFuncY(i2, i1)
                                     for i1, i2 in zip(d1 + 0.5, d2 + 0.5)],
                                    dtype="float64")
                dX = self._splineCache[keyX]
                dY = self._splineCache[keyY]
            else:
                dX = self.spline.splineFuncX(d2 + 0.5, d1 + 0.5)
                dY = self.spline.splineFuncY(d2 + 0.5, d1 + 0.5)
        p1 = (self._pixel1 * (dY + 0.5 + d1))
        p2 = (self._pixel2 * (dX + 0.5 + d2))
        return p1, p2

    def calc_mask(self):
        """
        Detectors with gaps should overwrite this method with
        something actually calculating the mask!
        """
#        logger.debug("Detector.calc_mask is not implemented for generic detectors")
        return None

    ############################################################################
    # Few properties
    ############################################################################
    def get_mask(self):
        if self._mask is False:
            with self._sem:
                if self._mask is False:
                    self._mask = self.calc_mask()  # gets None in worse cases
                    if self._mask is not None:
                        self._mask_crc = crc32(self._mask)
        return self._mask
    def set_mask(self, mask):
        with self._sem:
            self._mask = mask
            if mask is not None:
                self._mask_crc = crc32(mask)
            else:
                self._mask_crc = None
    mask = property(get_mask, set_mask)
    def set_maskfile(self, maskfile):
        if fabio:
            with self._sem:
                self._mask = numpy.ascontiguousarray(fabio.open(maskfile).data,
                                                     dtype=numpy.int8)
                self._mask_crc = crc32(self._mask)
                self._maskfile = maskfile
        else:
            logger.error("FabIO is not available, unable to load the image to set the mask.")

    def get_maskfile(self):
        return self._maskfile
    maskfile = property(get_maskfile, set_maskfile)

    def get_pixel1(self):
        return self._pixel1
    def set_pixel1(self, value):
        if isinstance(value, float):
            self._pixel1 = value
        elif isinstance(value, (tuple, list)):
            self._pixel1 = float(value[0])
        else:
            self._pixel1 = float(value)
    pixel1 = property(get_pixel1, set_pixel1)

    def get_pixel2(self):
        return self._pixel2
    def set_pixel2(self, value):
        if isinstance(value, float):
            self._pixel2 = value
        elif isinstance(value, (tuple, list)):
            self._pixel2 = float(value[0])
        else:
            self._pixel2 = float(value)
    pixel2 = property(get_pixel2, set_pixel2)