Skip to content

Commit c0588b4

Browse files
authored
Add tutorial for wrapping PDFgetx3 and PyFai with funcxy (#264)
* funcxy initial * Add preliminary pyfai morph * Add links to tutorials * News
1 parent 9ec8774 commit c0588b4

File tree

4 files changed

+221
-2
lines changed

4 files changed

+221
-2
lines changed

docs/source/funcxy.rst

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
.. _funcxy:
2+
3+
Using funcxy with Commonly-Used Diffraction Software
4+
####################################################
5+
6+
The general xy morph ``funcxy`` can be used to tune parameters
7+
of many popular diffraction software functions.
8+
9+
Below, we give templates for how one can use ``funcxy``
10+
with `PDFgetx3 <https://www.diffpy.org/products/pdfgetx.html>`_
11+
and `PyFai <https://pyfai.readthedocs.io/en/stable/>`_.
12+
13+
Getting a Better PDF with PDFgetx3
14+
==================================
15+
16+
In PDFgetx3, the ``PDFGetter`` takes in a 1D diffraction
17+
pattern I(Q) and returns a PDF G(r).
18+
19+
There are many parameters you can specify, such as
20+
- ``qmin``: Lower Q-cutoff for the Fourier transform giving the PDF
21+
- ``qmax``: Upper Q-cutoff for the Fourier transform giving the PDF
22+
- ``qmaxinst``: Upper Q-boundary for meaningful signal
23+
- ``rpoly``: Approximately the low-r bound of meaningful G(r) values
24+
25+
Furthermore, you can supply a background file ``backgroundfile``
26+
and subtract a scaled version of the background file by the
27+
scaling factor ``bgscale``.
28+
29+
We will showcase an example of how one would refine over the
30+
``PDFGetter`` parameters using ``funcxy`` to obtain a PDF.
31+
32+
Let's say you have a measured I(Q) with Q in angstroms of a lead
33+
nanoparticle (composition PbS) named ``sample.chi`` taken on a
34+
glass background. We want to match a target calculated PDF G(r)
35+
stored in a file named ``target.cgr``.
36+
Let's also say we have a measured I(Q) of the
37+
glass background ``background.chi``.
38+
39+
.. code-block:: python
40+
41+
from diffpy.pdfgetx.pdfgetter import PDFGetter
42+
from diffpy.morph.morphpy import morph_arrays
43+
from diffpy.utils.parsers.loaddata import loadData
44+
45+
pg = PDFGetter()
46+
47+
backgroundfile = loadData("background.chi")
48+
composition = "PbS"
49+
50+
51+
def wrap(x, y, **kwargs):
52+
xy_out = pg.__call__(
53+
x=x, y=y, dataformat="QA",
54+
composition=composition,
55+
backgroundfile=backgroundfile,
56+
**kwargs
57+
)
58+
r = xy_out[0]
59+
gr = xy_out[1]
60+
return (r, gr)
61+
62+
63+
sample_iq = loadData("sample.chi")
64+
target_gr = loadData("target.cgr")
65+
params_to_morph = {
66+
"bgscale": 1.0,
67+
"qmin": 0.0, "qmax": 25.0,
68+
"qmaxinst": 25.0, "rpoly": 0.9
69+
}
70+
71+
morph_info, morphed_gr = morph_arrays(
72+
sample_iq, target_gr,
73+
funcxy=(wrap, params_to_morph)
74+
)
75+
76+
You can now plot ``morphed_gr`` against your ``target_gr`` to see
77+
how well your morphing refinement of the PDF-getting parameters
78+
as done!
79+
To see what the refined values of the parameters are,
80+
print out ``morph_info``.
81+
You can freely add and remove entries in
82+
``params_to_morph`` to include or not include them as
83+
parameters to refine over.
84+
85+
If you expect to see thermal effect differences between your
86+
measured PDF and ``target_gr``, you can also include
87+
the ``stretch``, ``scale``, and ``smear`` morphs in your
88+
call to ``morph_arrays``.
89+
90+
91+
Performing Detector Calibration with PyFai
92+
==========================================
93+
94+
When performing azimuthal integration, it is important to
95+
ensure your beam center and detector distances are calibrated.
96+
However, it is possible that they have shifted
97+
across measurements. Here, we will use morphing to the rescue!
98+
99+
Let's say we just measured a diffraction pattern stored
100+
as a NumPy object in ``diffraction_image.npy``, but some
101+
of the detector geometries are off.
102+
Our azimuthally integrated ``sample.chi`` looks a bit off.
103+
Before this measurement, you measured an amazing
104+
I(Q) pattern ``target.chi`` with a perfectly calibrated
105+
sample-to-detector distance and beam center.
106+
We will use morphing to try to match the integration of
107+
the 2D pattern to the target 1D function.
108+
109+
For the integration, we will need some information, such as
110+
the wavelength of the beam,
111+
the size of each pixel in the 2D image
112+
(``pixel1`` is the horizontal length in meters and
113+
``pixel2`` is the vertical length in meters),
114+
and a guess of the beam center.
115+
This information can be found on the
116+
`PyFai documentation <https://pyfai.readthedocs.io/en/stable/usage/cookbook/integration_with_python.html>`_.
117+
For our example, let's say we have a ``1024``x``1024`` pixel image
118+
where each pixel is a ``100`` micron by ``100`` micron region, and
119+
our wavelength was ``1.11`` angstroms.
120+
121+
.. code-block:: python
122+
123+
import numpy as np
124+
import pyFAI.integrator.azimuthal as pyfai
125+
import pyFAI.detectors as pfd
126+
from diffpy.morph.morphpy import morph_arrays
127+
from diffpy.utils.parsers.loaddata import loadData
128+
129+
pattern_2d = np.load("diffraction_image.npy")
130+
wavelength = 0.1110e-9 # in m
131+
pixel1 = 1e-4 # in m
132+
pixel2 = 1e-4 # in m
133+
cent_x = 511 # in number of pixels
134+
cent_y = 511 # in number of pixels
135+
136+
ai = pyfai.AzimuthalIntegrator()
137+
ai.wavelength = wavelength
138+
detector = pfd.Detector()
139+
detector.max_shape = pattern_2d.shape
140+
141+
142+
def wrap(x, y, sample_to_detector_dist, cent_offset_x, cent_offset_y):
143+
detector.pixel1 = pixel1
144+
detector.pixel2 = pixel2
145+
ai.detector = detector
146+
147+
ai.setFit2D(
148+
directDist=sample_to_detector_dist,
149+
centerX=cent_x+cent_offset_x,
150+
centerY=cent_y+cent_offset_y
151+
)
152+
153+
return ai.integrate1D_ng(
154+
pattern_2d,
155+
npt=1000, unit="q_A^-1",
156+
method="mean"
157+
)
158+
159+
160+
params_to_morph = {
161+
"sample_to_detector_dist": 60, # in mm
162+
"cent_offset_x": 0, # in number of pixels
163+
"cent_offset_y": 0 # in number of pixels
164+
}
165+
166+
sample_chi = loadData("sample.chi")
167+
target_chi = loadData("target.chi")
168+
169+
morph_info, morphed_chi = morph_arrays(
170+
sample_chi, target_chi,
171+
funcxy=(wrap, params_to_morph)
172+
)
173+
174+
You can now plot ``morphed_chi`` against your ``target_chi``
175+
to see if the refinement has helped in the calibration!
176+
To see the calibrated values, you can print out ``morph_info``.
177+
178+
If you would like to morph over other PyFai parameters
179+
(e.g. ``rot1``, ``tilt``, ``wavelength``),
180+
you can adjust the wrapper function ``wrap`` to take in
181+
these parameters.

docs/source/morphpy.rst

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ This page is intended for those acquainted with the basic morphs
1010
described in the aforementioned quickstart tutorial who want to use ``diffpy.morph`` in their
1111
Python scripts.
1212

13+
For those looking to use the Python-specific morph ``MorphFuncxy`` (described below)
14+
with commonly used diffraction software like `PDFgetx3 <https://www.diffpy.org/products/pdfgetx.html>`_
15+
and `PyFai <https://pyfai.readthedocs.io/en/stable/>`_ are directed to the
16+
`funcxy tutorials <funcxy.html>`__.
17+
1318
Python Morphing Functions
1419
=========================
1520

@@ -408,8 +413,10 @@ This is equivalent to applying a ``MorphFuncx`` and ``MorphFuncy``
408413
simultaneously.
409414

410415
This morph is useful when you want to apply operations that modify both
411-
the grid and function value. A PDF-specific example includes computing
412-
PDFs from 1D diffraction data (see paragraph at the end of this section).
416+
the grid and function value.
417+
Examples of using ``MorphFuncxy`` with ``PyFai`` azimuthal integration
418+
and ``PDFgetx3`` PDF calculation are included `here <funcxy.html>`__.
419+
413420

414421
For this tutorial, we will go through two examples. One simple one
415422
involving shifting a function in the ``x`` and ``y`` directions, and

docs/source/tutorials.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ Tutorials for these are included below. The files required for these tutorials c
88

99
For a full list of options offered by ``diffpy.morph``, please run ``diffpy.morph --help`` on the command line.
1010

11+
Using MorphFuncxy
12+
=================
13+
14+
Examples of how to use the general morph ``MorphFuncxy`` with commonly used
15+
diffraction software like `PDFgetx3 <https://www.diffpy.org/products/pdfgetx.html>`_
16+
and `PyFai <https://pyfai.readthedocs.io/en/stable/>`_ are directed to the
17+
`funcxy tutorials <funcxy.html>`__.
18+
1119
Performing Multiple Morphs
1220
==========================
1321

news/funcxy_tutorial.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* Tutorials for wrapping PDFgetx3 and PyFai with funcxy.
4+
5+
**Changed:**
6+
7+
* <news item>
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* <news item>
20+
21+
**Security:**
22+
23+
* <news item>

0 commit comments

Comments
 (0)