示例#1
0
    def getRings(self):
        """
        Returns polygons of rings

        :returns: List of ring angle with the associated polygon
        :rtype: List[Tuple[float,List[numpy.ndarray]]]
        """
        tth = self.__geoRef.twoThetaArray(self.__peakPicker.shape)

        result = collections.OrderedDict()

        tth_max = tth.max()
        tth_min = tth.min()
        if not self.__calibrant:
            return result

        angles = [
            i for i in self.__calibrant.get_2th()
            if (i is not None) and (i >= tth_min) and (i <= tth_max)
        ]
        if len(angles) == 0:
            return result

        ms = marchingsquares.MarchingSquaresMergeImpl(tth,
                                                      self.__mask,
                                                      use_minmax_cache=True)
        rings = []
        for angle in angles:
            polygons = ms.find_contours(angle)
            rings.append((angle, polygons))

        return rings
示例#2
0
文件: GeometryTask.py 项目: kif/pyFAI
    def update(self, calibration):
        """Update the state from a current calibration process.

        :param RingCalibration calibration: A calibration process
        """
        mask = calibration.getMask()
        self.__geoRef = calibration.getPyfaiGeometry()
        self.__geometry = None
        self.__rings = calibration.getRings()
        self.__previousRms = self.__rms
        self.__rms = calibration.getRms()
        tth = calibration.getTwoThetaArray()
        # Make sure there is no more copy
        self.__tth = numpy.ascontiguousarray(tth)
        self.__poni = calibration.getPoni()
        self.__beamCenter = calibration.getBeamCenter()
        self.__empty = False
        ms = marchingsquares.MarchingSquaresMergeImpl(tth,
                                                      mask,
                                                      use_minmax_cache=True)
        self.__ms = ms
        self.__ringPolygons = {}

        self.changed.emit()
示例#3
0
    def extract(self,
                peaks,
                method="massif",
                maxRings=None,
                pointPerDegree=1.0):
        """
        Performs an automatic keypoint extraction:
        Can be used in recalib or in calib after a first calibration has been performed.

        # FIXME pts_per_deg
        """
        fixed = pyFAI.utils.FixedParameters()
        fixed.add("wavelength")

        geoRef = self.__createGeoRef(peaks, fixed=fixed)
        self.__geoRef = geoRef

        peakPicker = PeakPicker(data=self.__image,
                                mask=self.__mask,
                                calibrant=self.__calibrant,
                                wavelength=self.__wavelength,
                                detector=self.__detector,
                                method=method)

        peakPicker.reset()
        peakPicker.init(method, False)
        # if geoRef:
        #     ai.setPyFAI(**geoRef.getPyFAI())
        tth = numpy.array(
            [i for i in self.__calibrant.get_2th() if i is not None])
        tth = numpy.unique(tth)
        tth_min = numpy.zeros_like(tth)
        tth_max = numpy.zeros_like(tth)
        delta = (tth[1:] - tth[:-1]) / 4.0
        tth_max[:-1] = delta
        tth_max[-1] = delta[-1]
        tth_min[1:] = -delta
        tth_min[0] = -delta[0]
        tth_max += tth
        tth_min += tth

        ttha = geoRef.get_ttha()
        chia = geoRef.get_chia()
        if (ttha is None) or (ttha.shape != peakPicker.data.shape):
            ttha = geoRef.twoThetaArray(peakPicker.data.shape)
        if (chia is None) or (chia.shape != peakPicker.data.shape):
            chia = geoRef.chiArray(peakPicker.data.shape)

        rings = 0
        peakPicker.sync_init()
        if maxRings is None:
            maxRings = tth.size
        ms = marchingsquares.MarchingSquaresMergeImpl(ttha,
                                                      self.__mask,
                                                      use_minmax_cache=True)

        for i in range(tth.size):
            if rings >= maxRings:
                break
            mask = numpy.logical_and(ttha >= tth_min[i], ttha < tth_max[i])
            # if self.mask is not None:
            #     mask = numpy.logical_and(mask, numpy.logical_not(self.mask))
            size = mask.sum(dtype=int)
            if (size > 0):
                rings += 1
                peakPicker.massif_contour(mask)
                # if self.gui:
                #     update_fig(self.peakPicker.fig)
                sub_data = peakPicker.data.ravel()[numpy.where(mask.ravel())]
                mean = sub_data.mean(dtype=numpy.float64)
                std = sub_data.std(dtype=numpy.float64)
                upper_limit = mean + std
                mask2 = numpy.logical_and(peakPicker.data > upper_limit, mask)
                size2 = mask2.sum(dtype=int)
                if size2 < 1000:
                    upper_limit = mean
                    mask2 = numpy.logical_and(peakPicker.data > upper_limit,
                                              mask)
                    size2 = mask2.sum()
                # length of the arc:
                # Coords in points are y, x
                points = ms.find_pixels(tth[i])

                seeds = set((i[0], i[1]) for i in points if mask2[i[0], i[1]])
                # max number of points: 360 points for a full circle
                azimuthal = chia[points[:,
                                        0].clip(0, peakPicker.data.shape[0]),
                                 points[:,
                                        1].clip(0, peakPicker.data.shape[1])]
                nb_deg_azim = numpy.unique(
                    numpy.rad2deg(azimuthal).round()).size
                keep = int(nb_deg_azim * pointPerDegree)
                if keep == 0:
                    continue
                dist_min = len(seeds) / 2.0 / keep
                # why 3.0, why not ?

                msg = "Extracting datapoint for ring %s (2theta = %.2f deg); "\
                    "searching for %i pts out of %i with I>%.1f, dmin=%.1f"
                _logger.info(msg, i, numpy.degrees(tth[i]), keep, size2,
                             upper_limit, dist_min)
                _res = peakPicker.peaks_from_area(mask=mask2,
                                                  Imin=upper_limit,
                                                  keep=keep,
                                                  method=method,
                                                  ring=i,
                                                  dmin=dist_min,
                                                  seed=seeds)

        # self.peakPicker.points.save(self.basename + ".npt")
        # if self.weighted:
        #     self.data = self.peakPicker.points.getWeightedList(self.peakPicker.data)
        # else:
        #     self.data = peakPicker.points.getList()
        return peakPicker.points.getList()
示例#4
0
    def extract_cp(self, max_rings=None, pts_per_deg=1.0, Imin=0):
        """Performs an automatic keypoint extraction and update the geometry refinement part

        :param max_ring: extract at most N rings from the image
        :param pts_per_deg: number of control points per azimuthal degree (increase for better precision)
        """
        if self.massif is None:
            self.massif = Massif(self.image)

        tth = numpy.array(
            [i for i in self.calibrant.get_2th() if i is not None])
        tth = numpy.unique(tth)
        tth_min = numpy.zeros_like(tth)
        tth_max = numpy.zeros_like(tth)
        delta = (tth[1:] - tth[:-1]) / 4.0
        tth_max[:-1] = delta
        tth_max[-1] = delta[-1]
        tth_min[1:] = -delta
        tth_min[0] = -delta[0]
        tth_max += tth
        tth_min += tth
        shape = self.image.shape
        ttha = self.geometry_refinement.twoThetaArray(shape)
        chia = self.geometry_refinement.chiArray(shape)
        rings = 0
        cp = ControlPoints(calibrant=self.calibrant)
        if max_rings is None:
            max_rings = tth.size

        ms = marchingsquares.MarchingSquaresMergeImpl(
            ttha,
            mask=self.geometry_refinement.detector.mask,
            use_minmax_cache=True)
        for i in range(tth.size):
            if rings >= max_rings:
                break
            mask = numpy.logical_and(ttha >= tth_min[i], ttha < tth_max[i])
            if self.detector.mask is not None:
                mask = numpy.logical_and(
                    mask,
                    numpy.logical_not(self.geometry_refinement.detector.mask))
            size = mask.sum(dtype=int)
            if (size > 0):
                rings += 1
                sub_data = self.image.ravel()[numpy.where(mask.ravel())]
                mean = sub_data.mean(dtype=numpy.float64)
                std = sub_data.std(dtype=numpy.float64)
                upper_limit = mean + std
                mask2 = numpy.logical_and(self.image > upper_limit, mask)
                size2 = mask2.sum(dtype=int)
                if size2 < 1000:
                    upper_limit = mean
                    mask2 = numpy.logical_and(self.image > upper_limit, mask)
                    size2 = mask2.sum()
                # length of the arc:
                points = ms.find_pixels(tth[i])
                seeds = set((i[0], i[1]) for i in points if mask2[i[0], i[1]])
                # max number of points: 360 points for a full circle
                azimuthal = chia[points[:, 0].clip(0, shape[0]),
                                 points[:, 1].clip(0, shape[1])]
                nb_deg_azim = numpy.unique(
                    numpy.rad2deg(azimuthal).round()).size
                keep = int(nb_deg_azim * pts_per_deg)
                if keep == 0:
                    continue
                dist_min = len(seeds) / 2.0 / keep
                # why 3.0, why not ?

                logger.info(
                    "Extracting datapoint for ring %s (2theta = %.2f deg); " +
                    "searching for %i pts out of %i with I>%.1f, dmin=%.1f", i,
                    numpy.degrees(tth[i]), keep, size2, upper_limit, dist_min)
                res = self.massif.peaks_from_area(mask2,
                                                  Imin=Imin,
                                                  keep=keep,
                                                  dmin=dist_min,
                                                  seed=seeds,
                                                  ring=i)
                cp.append(res, i)
        self.control_points = cp
        self.geometry_refinement.data = numpy.asarray(cp.getList(),
                                                      dtype=numpy.float64)
        return cp
示例#5
0
    def _extract(self, peaks=None, geometryModel=None):
        """
        Performs an automatic keypoint extraction:
        Can be used in recalib or in calib after a first calibration has been performed.

        :param List[int] ringNumbers: If set, extraction will only be done on
            rings number contained in this list (the number 0 identify the first
            ring)
        """
        assert (numpy.logical_xor(peaks is not None, geometryModel
                                  is not None))
        method = "massif"
        maxRings = self.__maxRings
        ringNumbers = self.__ringNumbers
        pointPerDegree = self.__pointPerDegree

        if ringNumbers is not None:
            ringNumbers = set(ringNumbers)

        if peaks is not None:
            # Energy from from experiment settings
            wavelength = self.__wavelength
            self.__calibrant.setWavelength_change2th(wavelength)
            geoRef = self.__createGeoRefFromPeaks(peaks)
        elif geometryModel is not None:
            # Fitted energy
            assert (geometryModel.isValid())
            wavelength = geometryModel.wavelength().value()
            self.__calibrant.setWavelength_change2th(wavelength)
            geoRef = self.__createGeoRefFromGeometry(geometryModel)

        self.__geoRef = geoRef

        peakPicker = PeakPicker(data=self.__image,
                                mask=self.__mask,
                                calibrant=self.__calibrant,
                                wavelength=wavelength,
                                detector=self.__detector,
                                method=method)

        peakPicker.reset()
        peakPicker.init(method, False)

        tth = numpy.array(
            [i for i in self.__calibrant.get_2th() if i is not None])
        tth = numpy.unique(tth)
        tth_min = numpy.zeros_like(tth)
        tth_max = numpy.zeros_like(tth)
        delta = (tth[1:] - tth[:-1]) / 4.0
        tth_max[:-1] = delta
        tth_max[-1] = delta[-1]
        tth_min[1:] = -delta
        tth_min[0] = -delta[0]
        tth_max += tth
        tth_min += tth

        ttha = geoRef.get_ttha()
        chia = geoRef.get_chia()
        if (ttha is None) or (ttha.shape != peakPicker.data.shape):
            ttha = geoRef.twoThetaArray(peakPicker.data.shape)
        if (chia is None) or (chia.shape != peakPicker.data.shape):
            chia = geoRef.chiArray(peakPicker.data.shape)

        rings = 0
        peakPicker.sync_init()
        if maxRings is None:
            maxRings = tth.size
        ms = marchingsquares.MarchingSquaresMergeImpl(ttha,
                                                      self.__mask,
                                                      use_minmax_cache=True)

        for i in range(tth.size):
            if ringNumbers is not None:
                if i not in ringNumbers:
                    continue
            if rings >= maxRings:
                break
            mask = numpy.logical_and(ttha >= tth_min[i], ttha < tth_max[i])
            size = mask.sum(dtype=int)
            if (size > 0):
                rings += 1
                self._updateProcessingLocation(mask)
                sub_data = peakPicker.data.ravel()[numpy.where(mask.ravel())]
                mean = sub_data.mean(dtype=numpy.float64)
                std = sub_data.std(dtype=numpy.float64)
                upper_limit = mean + std
                mask2 = numpy.logical_and(peakPicker.data > upper_limit, mask)
                size2 = mask2.sum(dtype=int)
                if size2 < 1000:
                    upper_limit = mean
                    mask2 = numpy.logical_and(peakPicker.data > upper_limit,
                                              mask)
                    size2 = mask2.sum()
                # Coords in points are y, x
                points = ms.find_pixels(tth[i])

                seeds = set((i[0], i[1]) for i in points if mask2[i[0], i[1]])
                # Max number of points: 360 points for a full circle
                azimuthal = chia[points[:,
                                        0].clip(0, peakPicker.data.shape[0]),
                                 points[:,
                                        1].clip(0, peakPicker.data.shape[1])]
                nb_deg_azim = numpy.unique(
                    numpy.rad2deg(azimuthal).round()).size
                keep = int(nb_deg_azim * pointPerDegree)
                if keep == 0:
                    continue
                dist_min = len(seeds) / 2.0 / keep
                # why 3.0, why not ?

                msg = "Extracting datapoint for ring %s (2theta = %.2f deg); "\
                    "searching for %i pts out of %i with I>%.1f, dmin=%.1f"
                _logger.info(msg, i, numpy.degrees(tth[i]), keep, size2,
                             upper_limit, dist_min)
                _res = peakPicker.peaks_from_area(mask=mask2,
                                                  Imin=upper_limit,
                                                  keep=keep,
                                                  method=method,
                                                  ring=i,
                                                  dmin=dist_min,
                                                  seed=seeds)

        return peakPicker.points.getList()