Exemplo n.º 1
0
class XIntegratePlugin(ProcessingPlugin):
    name = 'X Integrate'
    ai = Input(description='A PyFAI.AzimuthalIntegrator object',
               type=AzimuthalIntegrator)
    data = Input(description='2d array representing intensity for each pixel',
                 type=np.ndarray)
    mask = Input(description='Array (same size as image) with 1 for masked pixels, and 0 for valid pixels',
                 type=np.ndarray)
    dark = Input(description='Dark noise image',
                 type=np.ndarray)
    flat = Input(description='Flat field image',
                 type=np.ndarray)
    normalization_factor = Input(description='Value of a normalization monitor',
                                 type=float, default=1.)
    qx = Output(description='Q_x bin center positions',
                type=np.array)
    Ix = Output(description='Binned/pixel-split integrated intensity',
                type=np.array)

    hints = [PlotHint(qx, Ix)]

    def evaluate(self):
        if self.dark.value is None: self.dark.value = np.zeros_like(self.data.value)
        if self.flat.value is None: self.flat.value = np.ones_like(self.data.value)
        if self.mask.value is None: self.mask.value = np.zeros_like(self.data.value)
        self.Ix.value = np.sum((self.data.value - self.dark.value) * np.average(self.flat.value - self.dark.value) / (
                self.flat.value - self.dark.value) * np.logical_not(self.mask.value), axis=0)
        centerx = self.ai.value.getFit2D()['centerX']
        centerz = self.ai.value.getFit2D()['centerY']
        self.qx.value = self.ai.value.qFunction(np.array([centerz] * self.data.value.shape[1]),
                                                np.arange(0, self.data.value.shape[1])) / 10.
        self.qx.value[np.arange(0, self.data.value.shape[1]) < centerx] *= -1.
Exemplo n.º 2
0
class ChiIntegratePlugin(ProcessingPlugin):
    ai = Input(description='A PyFAI.AzimuthalIntegrator object',
               type=AzimuthalIntegrator)
    data = Input(description='2d array representing intensity for each pixel',
                 type=np.ndarray)
    npt_azim = Input(description='Number of bins along chi', default=1000)
    polz_factor = Input(description='Polarization factor for correction',
                        type=float,
                        default=0)
    unit = Input(description='Output units for q',
                 type=[str, units.Unit],
                 default="q_A^-1")
    radial_range = Input(
        description=
        'The lower and upper range of the radial unit. If not provided, range is simply '
        '(data.min(), data.max()). Values outside the range are ignored.',
        type=tuple)
    azimuth_range = Input(
        description=
        'The lower and upper range of the azimuthal angle in degree. If not provided, '
        'range is simply (data.min(), data.max()). Values outside the range are ignored.',
        type=tuple)
    mask = Input(
        description=
        'Array (same size as image) with 1 for masked pixels, and 0 for valid pixels',
        type=np.ndarray)
    dark = Input(description='Dark noise image', type=np.ndarray)
    flat = Input(description='Flat field image', type=np.ndarray)
    method = Input(
        description=
        'Can be "numpy", "cython", "BBox" or "splitpixel", "lut", "csr", "nosplit_csr", '
        '"full_csr", "lut_ocl" and "csr_ocl" if you want to go on GPU. To Specify the device: '
        '"csr_ocl_1,2"',
        type=str,
        default='splitbbox')
    normalization_factor = Input(
        description='Value of a normalization monitor', type=float, default=1.)
    chi = Output(description='Q bin center positions', type=np.array)
    Ichi = Output(description='Binned/pixel-split integrated intensity',
                  type=np.array)

    hints = [PlotHint(chi, Ichi)]

    def evaluate(self):
        self.Ichi.value, q, chi = self.ai.value.integrate2d(
            data=nonesafe_flipud(self.data.value),
            npt_rad=1,
            npt_azim=self.npt_azim.value,
            radial_range=self.radial_range.value,
            azimuth_range=self.azimuth_range.value,
            mask=nonesafe_flipud(self.mask.value),
            polarization_factor=self.polz_factor.value,
            dark=nonesafe_flipud(self.dark.value),
            flat=nonesafe_flipud(self.flat.value),
            method=self.method.value,
            unit=self.unit.value,
            normalization_factor=self.normalization_factor.value)

        self.Ichi.value = np.sum(self.Ichi.value, axis=1)
        self.chi.value = chi
Exemplo n.º 3
0
class LinecutPlugin(ProcessingPlugin):
    name = 'Linecut'
    coordinate = Input(description='Coordinate of the cut',
                       type=int,
                       default=0)
    parallelAxis = Input(description='Axis the cut is parallel to',
                         type=str,
                         default="x")
    data = Input(description='2d array representing intensity for each pixel',
                 type=np.ndarray)
    mask = Input(
        description=
        'Array (same size as image) with 1 for masked pixels, and 0 for valid pixels',
        type=np.ndarray)
    dark = Input(description='Dark noise image', type=np.ndarray)
    flat = Input(description='Flat field image', type=np.ndarray)
    normalization_factor = Input(
        description='Value of a normalization monitor', type=float, default=1.)
    px = Output(name='px', description='Bin center positions', type=np.array)
    I = Output(name='Intensity',
               description='Binned/pixel-split intensity',
               type=np.array)

    hints = [PlotHint(px, I)]

    def evaluate(self):
        x = self.parallelAxis.value == "x"
        lperp = self.data.value.shape[not x]  #booleans are ints
        if self.coordinate.value >= lperp:
            self.coordinate.value = lperp - 1
        if self.coordinate.value < 0:
            self.coordinate.value = 0
        if self.dark.value is None:
            self.dark.value = np.zeros_like(self.data.value)
        if self.flat.value is None:
            self.flat.value = np.ones_like(self.data.value)
        if self.mask.value is None:
            self.mask.value = np.zeros_like(self.data.value)
        h = ((self.data.value - self.dark.value) *
             np.average(self.flat.value - self.dark.value) /
             (self.flat.value - self.dark.value) *
             np.logical_not(self.mask.value))
        self.I.value = (h[lperp - 1 - self.coordinate.value]
                        if x else [b[self.coordinate.value] for b in h][::-1])
        self.px.value = range(self.data.value.shape[x])  #booleans are ints

    def getCategory() -> str:
        return "Cuts"
Exemplo n.º 4
0
class QBackgroundFit(ProcessingPlugin):
    name = 'Q Background Fit'

    q = InOut(description='Q bin center positions', type=np.array)
    Iq = InOut(description='Q spectra bin intensities', type=np.array)
    # model = Input(description='Fittable model class in the style of Astropy', type=Enum)
    domainmin = Input(description='Min bound on the domain of the input data',
                      type=float)
    domainmax = Input(description='Max bound on the domain of the input data',
                      type=float)
    degree = Input(name='Polynomial Degree',
                   description='Polynomial degree number',
                   type=int,
                   min=1,
                   default=4)
    # fitter = Input(description='Fitting algorithm', default=fitting.LevMarLSQFitter(), type=Enum, limits={'Linear LSQ':fitting.LinearLSQFitter(), 'Levenberg-Marquardt LSQ':fitting.LevMarLSQFitter(), 'SLSQP LSQ':fitting.SLSQPLSQFitter(), 'Simplex LSQ':fitting.SimplexLSQFitter()})
    domainfilter = Input(
        description=
        'Domain limits where peaks will be fitted; auto-populated by ')

    backgroundmodel = Output(
        description=
        'A new model with the fitted parameters; behaves as parameterized function',
        type=Fittable1DModel)
    backgroundprofile = Output(
        description='The fitted profile from the evaluation of the '
        'resulting model over the input range.')
    rawIq = Output(description='The spectra data before subtraction.')

    hints = [
        PlotHint(q, Iq),
        PlotHint(q, backgroundprofile),
        PlotHint(q, rawIq)
    ]

    modelvars = {}

    def __init__(self):
        super(QBackgroundFit, self).__init__()
        self.peakranges = []

    @property
    def parameter(self):
        self._workflow.attach(self.find_peak_ranges)  # order may be bad...
        return super(QBackgroundFit, self).parameter

    def find_peak_ranges(self):
        from xicam.SAXS.processing.astropyfit import \
            AstropyQSpectraFit  # must be a late import to avoid being picked up first by plugin manager
        thisindex = self._workflow.processes.index(self)
        self.peakranges = [
            (process.domainmin.value, process.domainmax.value)
            for process in self._workflow.processes[thisindex + 1:]
            if isinstance(process, AstropyQSpectraFit)
        ]

    def detach(self):
        self._workflow.detach(self.find_peak_ranges)

    def evaluate(self):
        model = models.Polynomial1D(degree=self.degree.value)

        norange = self.domainmin.value == self.domainmax.value
        if self.domainmin.value is None and self.q.value is not None or norange:  # truncate the q and I arrays with limits
            self.domainmin.value = self.q.value.min()
        if self.domainmax.value is None and self.q.value is not None or norange:  # truncate the q and I arrays with limits
            self.domainmax.value = self.q.value.max()

        filter = np.logical_and(self.domainmin.value <= self.q.value,
                                self.q.value <= self.domainmax.value)
        for peakrange in self.peakranges:
            print('applying peak range:', peakrange)
            filter &= np.logical_or(peakrange[0] >= self.q.value,
                                    self.q.value >= peakrange[1])

        q = self.q.value[filter]
        Iq = self.Iq.value[filter]
        self.backgroundmodel.value = fitting.LinearLSQFitter()(model, q, Iq)
        self.backgroundprofile.value = self.backgroundmodel.value(self.q.value)
        self.rawIq.value = self.Iq.value.copy()
        self.Iq.value = self.Iq.value - self.backgroundprofile.value

    def getCategory() -> str:
        return "Fits"
Exemplo n.º 5
0
class AstropyQSpectraFit(ProcessingPlugin):
    name = 'Q Fit (Astropy)'

    q = InOut(description='Q bin center positions',
              type=np.array)
    Iq = InOut(description='Q spectra bin intensities', type=np.array)
    model = Input(description='Fittable model class in the style of Astropy', type=Enum)
    domainmin = Input(description='Min bound on the domain of the input data', type=float)
    domainmax = Input(description='Max bound on the domain of the input data', type=float)
    fitter = Input(description='Fitting algorithm', default=fitting.LevMarLSQFitter(), type=Enum,
                   limits={'Linear LSQ': fitting.LinearLSQFitter(),
                           'Levenberg-Marquardt LSQ': fitting.LevMarLSQFitter(), 'SLSQP LSQ': fitting.SLSQPLSQFitter(),
                           'Simplex LSQ': fitting.SimplexLSQFitter()})

    fittedmodel = Output(description='A new model with the fitted parameters; behaves as parameterized function',
                         type=Fittable1DModel)
    fittedprofile = Output(
        description='The fitted profile from the evaluation of the resulting model over the input range.')

    hints = [PlotHint(q, Iq), PlotHint(q, fittedprofile)]

    modelvars = {}

    def __init__(self):
        super(AstropyQSpectraFit, self).__init__()
        self.model.limits = {plugin.name: plugin.plugin_object for plugin in
                             pluginmanager.getPluginsOfCategory('Fittable1DModelPlugin')}
        self.model.value = list(self.model.limits.values())[0]

    @property
    def parameter(self):

        # clear cache in
        for input in self.modelvars:
            del self.__dict__[input]
        varcache = self.modelvars.copy()
        self.modelvars = {}
        self._inputs = None
        self._inverted_vars = None
        if hasattr(self, '_inverted_vars'): del self._inverted_vars

        for name in self.model.value.param_names:
            param = getattr(self.model.value, name)
            # TODO: CHECK NAMESPACE
            if name in varcache:
                input = varcache[name]
            else:
                input = InOut(name=name, default=param.default, limits=param.bounds, type=float, fixed=False,
                              fixable=True)
            setattr(self, name, input)
            self.modelvars[name] = input
        parameter = super(AstropyQSpectraFit, self).parameter
        parameter.child('model').sigValueChanged.connect(self.reset_parameter)
        return parameter

    def reset_parameter(self):
        # cache old parameter
        oldparam = self._param

        # empty it
        for child in oldparam.children():
            child.remove()

        # reset attribute so new parameter is generated
        self._param = None

        # add new children to old parameter
        for child in self.parameter.children():  # type: Parameter
            oldparam.addChild(child)

        # set old parameter to attribute
        self._param = oldparam

    def evaluate(self):
        if self.model.value is None or self.model.value == '----': return
        norange = self.domainmin.value == self.domainmax.value
        if self.domainmin.value is None and self.q.value is not None or norange:  # truncate the q and I arrays with limits
            self.domainmin.value = self.q.value.min()
        if self.domainmax.value is None and self.q.value is not None or norange:  # truncate the q and I arrays with limits
            self.domainmax.value = self.q.value.max()
        for name, input in self.modelvars.items():  # propogate user-defined values to the model
            getattr(self.model.value, name).value = input.value
            getattr(self.model.value, name).fixed = input.fixed
        filter = np.logical_and(self.domainmin.value <= self.q.value, self.q.value <= self.domainmax.value)
        q = self.q.value[filter]
        Iq = self.Iq.value[filter]
        self.fittedmodel.value = self.fitter.value(self.model.value, q, Iq)
        self.fittedprofile.value = self.fittedmodel.value(self.q.value)

    def getCategory() -> str:
        return "Fits"