Skip to content

Commit 729245a

Browse files
authored
Merge pull request #2378 from EdgarGF93/sample_orientations_exif
Sample orientations exif
2 parents b0c0d93 + 032a3ce commit 729245a

File tree

4 files changed

+118
-155
lines changed

4 files changed

+118
-155
lines changed

sandbox/test_grazingincidence.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
data_file = UtilsTest.getimage("Y6.edf")
2222
data_2 = fabio.open(data_file).data
2323

24+
results = []
25+
fig, axes = subplots(ncols=4, nrows=2)
26+
for sample_orientation in range(1, 9):
27+
res = fi_2.integrate2d_grazing_incidence(data=data_2, incident_angle=0.0, tilt_angle=0.0, sample_orientation=sample_orientation)
28+
results.append(res)
29+
plot2d(res, ax=axes.ravel()[sample_orientation-1])
30+
plt.show()
31+
32+
33+
34+
2435
for fi, data in zip((fi_1, fi_2), (data_1, data_2)):
2536
res2d_1 = fi.integrate2d_grazing_incidence(data=data, incident_angle=0.0, tilt_angle=0.0, sample_orientation=1)
2637
res2d_2 = fi.integrate2d_grazing_incidence(data=data, incident_angle=0.2, tilt_angle=0.0, sample_orientation=1)

src/pyFAI/integrator/fiber.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,39 @@ def __repr__(self, dist_unit="m", ang_unit="rad", wl_unit="m"):
105105
return f"{core_repr}\nIncident angle: {self.incident_angle:.2f}° Tilt angle {self.tilt_angle:.2f}° Sample orientation {self.sample_orientation}"
106106

107107
@property
108-
def incident_angle(self):
108+
def incident_angle(self) -> float:
109+
"""Pitch angle: projection angle of the beam in the sample. Its rotation axis is the horizontal axis of the lab system.
110+
"""
109111
return self._cache_parameters.get('incident_angle', 0.0)
110112

111113
@property
112-
def tilt_angle(self):
114+
def tilt_angle(self) -> float:
115+
"""Roll angle. Its rotation axis is the beam axis. Tilting of the horizon for grazing incidence in thin films.
116+
"""
113117
return self._cache_parameters.get('tilt_angle', 0.0)
114118

115119
@property
116-
def sample_orientation(self):
120+
def sample_orientation(self) -> int:
121+
"""Orientation of the fiber axis according to EXIF orientation values
122+
123+
Sample orientations
124+
1 - No changes are applied to the image
125+
2 - Image is mirrored (flipped horizontally)
126+
3 - Image is rotated 180 degrees
127+
4 - Image is rotated 180 degrees and mirrored
128+
5 - Image is mirrored and rotated 90 degrees counter clockwise
129+
6 - Image is rotated 90 degrees counter clockwise
130+
7 - Image is mirrored and rotated 90 degrees clockwise
131+
8 - Image is rotated 90 degrees clockwise
132+
"""
117133
return self._cache_parameters.get('sample_orientation', 1)
118134

119135
def reset_integrator(self, incident_angle, tilt_angle, sample_orientation):
136+
"""Reset the cache values for the gi/fiber parameters
137+
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
138+
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
139+
:param int sample_orientation: 1-8, orientation of the fiber axis according to EXIF orientation values (see def sample_orientation)
140+
"""
120141
reset = False
121142
if incident_angle != self.incident_angle:
122143
logger.info(f"Incident angle set to {incident_angle}. AzimuthalIntegrator will be reset.")
@@ -161,7 +182,7 @@ def integrate_fiber(self, data,
161182
:param bool vertical_integration: If True, integrates along unit_ip; if False, integrates along unit_oop
162183
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
163184
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
164-
:param int sample_orientation: 1-4, four different orientation of the fiber axis regarding the detector main axis, from 1 to 4 is +90º
185+
:param int sample_orientation: 1-8, orientation of the fiber axis according to EXIF orientation values (see def sample_orientation)
165186
:param str filename: output filename in 2/3 column ascii format
166187
:param bool correctSolidAngle: correct for solid angle of each pixel if True
167188
:param ndarray mask: array (same size as image) with 1 for masked pixels, and 0 for valid pixels
@@ -299,7 +320,7 @@ def integrate2d_fiber(self, data,
299320
:param list oop_range: The lower and upper range of the out-of-plane unit. If not provided, range is simply (data.min(), data.max()). Values outside the range are ignored. Optional.
300321
:param incident_angle: tilting of the sample towards the beam (analog to rot2): in radians
301322
:param tilt_angle: tilting of the sample orthogonal to the beam direction (analog to rot3): in radians
302-
:param int sample_orientation: 1-4, four different orientation of the fiber axis regarding the detector main axis, from 1 to 4 is +90º
323+
:param int sample_orientation: 1-8, orientation of the fiber axis according to EXIF orientation values (see def sample_orientation)
303324
:param str filename: output filename in 2/3 column ascii format
304325
:param bool correctSolidAngle: correct for solid angle of each pixel if True
305326
:param ndarray mask: array (same size as image) with 1 for masked pixels, and 0 for valid pixels

src/pyFAI/test/test_fiber_integrator.py

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -488,107 +488,6 @@ def test_integrate1d_horizontal_deprecated_units(self):
488488
self.assertFalse(abs(res1d_ref.radial - res1d_deprecated.radial).max(), 0)
489489
self.assertFalse(abs(res1d_ref.intensity - res1d_deprecated.intensity).max(), 0)
490490

491-
def test_sample_orientation_equivalence(self):
492-
incident_angle = 0.0
493-
tilt_angle =0.0
494-
npt_ip = 100
495-
npt_oop = 100
496-
497-
threshold = 1.0
498-
499-
sample_orientation = 1
500-
oop_range_1 = [-5,5]
501-
ip_range_1 = [0,20]
502-
res_so_1 = self.fi.integrate_grazing_incidence(data=self.data, npt_ip=npt_ip, npt_oop=npt_oop,
503-
ip_range=ip_range_1, oop_range=oop_range_1,
504-
incident_angle=incident_angle, tilt_angle=tilt_angle,
505-
sample_orientation=sample_orientation,
506-
vertical_integration=False,
507-
)
508-
509-
sample_orientation = 2
510-
ip_range_2 = [-5,5]
511-
oop_range_2 = [0,20]
512-
res_so_2 = self.fi.integrate_grazing_incidence(data=self.data, npt_ip=npt_ip, npt_oop=npt_oop,
513-
ip_range=ip_range_2, oop_range=oop_range_2,
514-
incident_angle=incident_angle, tilt_angle=tilt_angle,
515-
sample_orientation=sample_orientation,
516-
vertical_integration=True,
517-
)
518-
519-
self.assertLess((abs(res_so_1.intensity) - abs(res_so_2.intensity)).max(), threshold)
520-
521-
sample_orientation = 3
522-
oop_range_3 = [-5,5]
523-
ip_range_3 = [-20,0]
524-
res_so_3 = self.fi.integrate_grazing_incidence(data=self.data, npt_ip=npt_ip, npt_oop=npt_oop,
525-
ip_range=ip_range_3, oop_range=oop_range_3,
526-
incident_angle=incident_angle, tilt_angle=tilt_angle,
527-
sample_orientation=sample_orientation,
528-
vertical_integration=False,
529-
)
530-
531-
self.assertLess((abs(res_so_3.intensity) - abs(res_so_2.intensity)).max(), threshold)
532-
533-
sample_orientation = 4
534-
oop_range_4 = [-20,5]
535-
ip_range_4 = [-5,5]
536-
res_so_4 = self.fi.integrate_grazing_incidence(data=self.data, npt_ip=npt_ip, npt_oop=npt_oop,
537-
ip_range=ip_range_4, oop_range=oop_range_4,
538-
incident_angle=incident_angle, tilt_angle=tilt_angle,
539-
sample_orientation=sample_orientation,
540-
vertical_integration=True,
541-
)
542-
543-
self.assertLess((abs(res_so_4.intensity) - abs(res_so_3.intensity)).max(), threshold)
544-
545-
def test_numexpr_equations(self):
546-
incident_angle = 0.2
547-
tilt_angle = -1.0
548-
sample_orientation = 3
549-
550-
qhorz = get_unit_fiber(name="qxgi_nm^-1", incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
551-
qvert = get_unit_fiber(name="qygi_nm^-1", incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
552-
qbeam = get_unit_fiber(name="qzgi_nm^-1", incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
553-
qip = get_unit_fiber(name="qip_nm^-1", incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
554-
qoop = get_unit_fiber(name="qoop_nm^-1", incident_angle=incident_angle, tilt_angle=tilt_angle, sample_orientation=sample_orientation)
555-
556-
self.fi.reset()
557-
arr_qhorz_fast = self.fi.array_from_unit(unit=qhorz)
558-
arr_qvert_fast = self.fi.array_from_unit(unit=qvert)
559-
arr_qbeam_fast = self.fi.array_from_unit(unit=qbeam)
560-
arr_qip_fast = self.fi.array_from_unit(unit=qip)
561-
arr_qoop_fast = self.fi.array_from_unit(unit=qoop)
562-
res2d_fast = self.fi.integrate2d_grazing_incidence(data=self.data, unit_ip=qip, unit_oop=qoop)
563-
564-
qhorz.formula = None
565-
qhorz.equation = qhorz._equation
566-
qvert.formula = None
567-
qvert.equation = qvert._equation
568-
qbeam.formula = None
569-
qbeam.equation = qbeam._equation
570-
qip.formula = None
571-
qip.equation = qip._equation
572-
qoop.formula = None
573-
qoop.equation = qoop._equation
574-
575-
self.fi.reset()
576-
arr_qhorz_slow = self.fi.array_from_unit(unit=qhorz)
577-
arr_qvert_slow = self.fi.array_from_unit(unit=qvert)
578-
arr_qbeam_slow = self.fi.array_from_unit(unit=qbeam)
579-
arr_qip_slow = self.fi.array_from_unit(unit=qip)
580-
arr_qoop_slow = self.fi.array_from_unit(unit=qoop)
581-
res2d_slow = self.fi.integrate2d_grazing_incidence(data=self.data, unit_ip=qip, unit_oop=qoop)
582-
583-
self.assertAlmostEqual((arr_qhorz_fast - arr_qhorz_slow).max(), 0.0)
584-
self.assertAlmostEqual((arr_qvert_fast - arr_qvert_slow).max(), 0.0)
585-
self.assertAlmostEqual((arr_qbeam_fast - arr_qbeam_slow).max(), 0.0)
586-
self.assertAlmostEqual((arr_qip_fast - arr_qip_slow).max(), 0.0)
587-
self.assertAlmostEqual((arr_qoop_fast - arr_qoop_slow).max(), 0.0)
588-
self.assertAlmostEqual((res2d_fast.intensity - res2d_slow.intensity).max(), 0.0)
589-
self.assertAlmostEqual((res2d_fast.radial - res2d_slow.radial).max(), 0.0)
590-
self.assertAlmostEqual((res2d_fast.azimuthal - res2d_slow.azimuthal).max(), 0.0)
591-
592491
def suite():
593492
testsuite = unittest.TestSuite()
594493
loader = unittest.defaultTestLoader.loadTestsFromTestCase

0 commit comments

Comments
 (0)