mirror of https://github.com/silx-kit/pyFAI.git
260 lines
7.6 KiB
Python
260 lines
7.6 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Project: Azimuthal integration
|
|
# https://github.com/silx-kit/pyFAI
|
|
#
|
|
# Copyright (C) 2018 European Synchrotron Radiation Facility, Grenoble, France
|
|
#
|
|
# Principal author: Jérôme Kieffer (Jerome.Kieffer@ESRF.eu)
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
__author__ = "Jérôme Kieffer"
|
|
__contact__ = "Jerome.Kieffer@ESRF.eu"
|
|
__license__ = "GPLv3+"
|
|
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
|
|
__date__ = "27/10/2016"
|
|
__status__ = "beta"
|
|
|
|
import logging
|
|
import numpy
|
|
|
|
logger = logging.getLogger("pyFAI.refinment2D")
|
|
|
|
from .azimuthalIntegrator import AzimuthalIntegrator
|
|
from PyMca import SGModule
|
|
|
|
|
|
class Refinment2D(object):
|
|
"""
|
|
refine the parameters from image itself ...
|
|
(Jerome est-ce que tu peux elaborer un petit peu plus ???)
|
|
"""
|
|
def __init__(self, img, ai=None):
|
|
"""
|
|
:param img: raw image we are working on
|
|
:type img: ndarray
|
|
:param ai: azimuhal integrator we are working on
|
|
:type ai: pyFAI.azimuthalIntegrator.AzimutalIntegrator
|
|
"""
|
|
self.img = img
|
|
if ai is None:
|
|
self.ai = AzimuthalIntegrator()
|
|
else:
|
|
self.ai = ai
|
|
|
|
def get_shape(self):
|
|
return self.img.shape
|
|
shape = property(get_shape)
|
|
|
|
def reconstruct(self, tth, I):
|
|
"""
|
|
Reconstruct a perfect image according to 2th / I given in
|
|
input
|
|
|
|
:param tth: 2 theta array
|
|
:type tth: ndarray
|
|
:param I: intensity array
|
|
:type I: ndarray
|
|
|
|
:return: a reconstructed image
|
|
:rtype: ndarray
|
|
"""
|
|
return numpy.interp(self.ai.twoThetaArray(self.shape), tth, I)
|
|
|
|
def diff_tth_X(self, dx=0.1):
|
|
"""
|
|
Jerome peux-tu décrire de quoi il retourne ???
|
|
|
|
:param dx: ???
|
|
:type: float ???
|
|
|
|
:return: ???
|
|
:rtype: ???
|
|
"""
|
|
f = self.ai.getFit2D()
|
|
fp = f.copy()
|
|
fm = f.copy()
|
|
fm["centerX"] -= dx / 2.0
|
|
fp["centerX"] += dx / 2.0
|
|
ap = AzimuthalIntegrator()
|
|
am = AzimuthalIntegrator()
|
|
ap.setFit2D(**fp)
|
|
am.setFit2D(**fm)
|
|
dtthX = (ap.twoThetaArray(self.shape) - am.twoThetaArray(self.shape))\
|
|
/ dx
|
|
tth, I = self.ai.xrpd(self.img, max(self.shape))
|
|
dI = SGModule.getSavitzkyGolay(I, npoints=5, degree=2, order=1)\
|
|
/ (tth[1] - tth[0])
|
|
dImg = self.reconstruct(tth, dI)
|
|
return (dtthX * dImg).sum()
|
|
|
|
def diff_tth_tilt(self, dx=0.1):
|
|
"""
|
|
idem ici ???
|
|
|
|
:param dx: ???
|
|
:type dx: float ???
|
|
|
|
:return: ???
|
|
:rtype: ???
|
|
"""
|
|
f = self.ai.getFit2D()
|
|
fp = f.copy()
|
|
fm = f.copy()
|
|
fm["tilt"] -= dx / 2.0
|
|
fp["tilt"] += dx / 2.0
|
|
ap = AzimuthalIntegrator()
|
|
am = AzimuthalIntegrator()
|
|
ap.setFit2D(**fp)
|
|
am.setFit2D(**fm)
|
|
dtthX = (ap.twoThetaArray(self.shape) - am.twoThetaArray(self.shape))\
|
|
/ dx
|
|
tth, I = self.ai.xrpd(self.img, max(self.shape))
|
|
dI = SGModule.getSavitzkyGolay(I, npoints=5, degree=2, order=1)\
|
|
/ (tth[1] - tth[0])
|
|
dImg = self.reconstruct(tth, dI)
|
|
return (dtthX * dImg).sum()
|
|
|
|
def diff_Fit2D(self, axis="all", dx=0.1):
|
|
"""
|
|
???
|
|
|
|
:param axis: ???
|
|
:type axis: ???
|
|
:param dx: ???
|
|
:type dx: ???
|
|
|
|
:return: ???
|
|
:rtype: ???
|
|
"""
|
|
tth, I = self.ai.xrpd(self.img, max(self.shape))
|
|
dI = SGModule.getSavitzkyGolay(I, npoints=5, degree=2, order=1)\
|
|
/ (tth[1] - tth[0])
|
|
dImg = self.reconstruct(tth, dI)
|
|
f = self.ai.getFit2D()
|
|
_tth2d_ref = self.ai.twoThetaArray(self.shape) # useless variable ???
|
|
|
|
keys = ["centerX", "centerY", "tilt", "tiltPlanRotation"]
|
|
if axis != "all":
|
|
keys = [i for i in keys if i == axis]
|
|
grad = {}
|
|
for key in keys:
|
|
fp = f.copy()
|
|
fp[key] += dx
|
|
ap = AzimuthalIntegrator()
|
|
ap.setFit2D(**fp)
|
|
dtth = (ap.twoThetaArray(self.shape)
|
|
- self.ai.twoThetaArray(self.shape)) / dx
|
|
grad[key] = (dtth * dImg).sum()
|
|
if axis == "all":
|
|
return grad
|
|
else:
|
|
return grad[axis]
|
|
|
|
def scan_centerX(self, width=1.0, points=10):
|
|
"""
|
|
???
|
|
|
|
:param width: ???
|
|
:type width: float ???
|
|
:param points: ???
|
|
:type points: int ???
|
|
|
|
:return: ???
|
|
:rtype: ???
|
|
"""
|
|
f = self.ai.getFit2D()
|
|
out = []
|
|
for x in numpy.linspace(f["centerX"] - width / 2.0,
|
|
f["centerX"] + width / 2.0,
|
|
points):
|
|
ax = AzimuthalIntegrator()
|
|
fx = f.copy()
|
|
fx["centerX"] = x
|
|
ax.setFit2D(**fx)
|
|
# print ax
|
|
ref = Refinment2D(self.img, ax)
|
|
res = ref.diff_tth_X()
|
|
print("x= %.3f mean= %e" % (x, res))
|
|
out.append(res)
|
|
return numpy.linspace(f["centerX"] - width / 2.0,
|
|
f["centerX"] + width / 2.0,
|
|
points), out
|
|
|
|
def scan_tilt(self, width=1.0, points=10):
|
|
"""
|
|
???
|
|
|
|
:param width: ???
|
|
:type width: float ???
|
|
:param points: ???
|
|
:type points: int ???
|
|
|
|
:return: ???
|
|
:rtype: ???
|
|
"""
|
|
f = self.ai.getFit2D()
|
|
out = []
|
|
for x in numpy.linspace(f["tilt"] - width / 2.0,
|
|
f["tilt"] + width / 2.0,
|
|
points):
|
|
ax = AzimuthalIntegrator()
|
|
fx = f.copy()
|
|
fx["tilt"] = x
|
|
ax.setFit2D(**fx)
|
|
# print ax
|
|
ref = Refinment2D(self.img, ax)
|
|
res = ref.diff_tth_tilt()
|
|
print("x= %.3f mean= %e" % (x, res))
|
|
out.append(res)
|
|
return numpy.linspace(f["tilt"] - width / 2.0,
|
|
f["tilt"] + width / 2.0,
|
|
points), out
|
|
|
|
def scan_Fit2D(self, width=1.0, points=10, axis="tilt", dx=0.1):
|
|
"""
|
|
???
|
|
|
|
:param width: ???
|
|
:type width: float ???
|
|
:param points: ???
|
|
:type points: int ???
|
|
:param axis: ???
|
|
:type axis: str ???
|
|
:param dx: ???
|
|
:type dx: float ???
|
|
|
|
:return: ???
|
|
:rtype: ???
|
|
"""
|
|
logger.info("Scanning along axis %s", axis)
|
|
f = self.ai.getFit2D()
|
|
out = []
|
|
meas_pts = numpy.linspace(f[axis] - width / 2.0,
|
|
f[axis] + width / 2.0,
|
|
points)
|
|
for x in meas_pts:
|
|
ax = AzimuthalIntegrator()
|
|
fx = f.copy()
|
|
fx[axis] = x
|
|
ax.setFit2D(**fx)
|
|
ref = Refinment2D(self.img, ax)
|
|
res = ref.diff_Fit2D(axis=axis, dx=dx)
|
|
print("x= %.3f mean= %e" % (x, res))
|
|
out.append(res)
|
|
return meas_pts, out
|