Flatfied calibration
Inspiration from: https://scripts.iucr.org/cgi-bin/paper?S1600577523001157
Work done for ID31
There are 9 positions investigated on the detector each of them contains calibration data and a flatfield image. First of all define an object container containing position, calibration, …
[1]:
%matplotlib widget
import copy, time
from dataclasses import dataclass
import numpy
import h5py
from matplotlib.pyplot import subplots
import fabio
import pyFAI
from pyFAI.gui import jupyter
from pyFAI.gui.jupyter.calib import Calibration
from pyFAI.gui.cli_calibration import AbstractCalibration
t0 = time.perf_counter()
print(f"Running pyFAI version {pyFAI.version}")
WARNING:pyFAI.gui.matplotlib:matplotlib already loaded, setting its backend may not work
Running pyFAI version 2024.9.0-dev0
[2]:
polarization = 0.999
npt = 512
energy = 75 #keV
wavelength = 1e-10*pyFAI.units.hc/energy
detector = pyFAI.detector_factory("Pilatus2M_CdTe")
calibrant = pyFAI.calibrant.CALIBRANT_FACTORY("AgBh")
calibrant.wavelength = wavelength
[3]:
# Here we download the test data
from silx.resources import ExternalResources
downloader = ExternalResources("flatfield", "http://www.silx.org/pub/pyFAI/testimages")
all_files = downloader.getdir("flatfield_ID31.tar.bz2")
master_file = [i for i in all_files if i.endswith("calibration_0001.h5")][0]
print(master_file)
/tmp/flatfield_testdata_edgar1993a/flatfield_ID31.tar.bz2__content/flatfield_ID31/calibration_0001.h5
[4]:
@dataclass
class Position:
"""All data related to one of the position"""
position: int
calibration_idx: int
scattering_idx: int
coordinates: tuple=tuple()
calibration_data: object=None
scattering_data: object=None
poni: object=None
ai: object=None
control_points: object=None
flatfield: object=None
@classmethod
def init(cls, h5_file, position, calibration_idx, scattering_idx, detector_name="p3", positioners=("cncx","cncy","cncz")):
with h5py.File(h5_file) as h:
calibration_str = f"{calibration_idx}."
scattering_str = f"{scattering_idx}."
keys = list(h.keys())
ids = [i for i in keys if i.startswith(calibration_str)]
if ids:
entry = h[ids[0]]
calibration_data = entry[f"measurement/{detector_name}"][0]
coordinates = tuple(entry[f"instrument/positioners/{positioner}"][()] for positioner in positioners)
else:
raise IndexError(f"no such Entry {calibration_idx}")
ids = [i for i in keys if i.startswith(scattering_str)]
if ids:
entry = h[ids[0]]
scattering_data = entry[f"measurement/{detector_name}"][0]
coordinates = tuple(entry[f"instrument/positioners/{positioner}"][()] for positioner in positioners)
else:
raise IndexError(f"no such Entry {calibration_idx}")
return cls(position, calibration_idx, scattering_idx, coordinates, calibration_data, scattering_data)
center = Position.init(master_file, "CC", 14, 13)
center
[4]:
Position(position='CC', calibration_idx=14, scattering_idx=13, coordinates=(6489.605, 20.0, 20.0), calibration_data=array([[2728, 2784, 2791, ..., 1582, 1636, 1544],
[2664, 2663, 2829, ..., 1542, 1485, 1533],
[2839, 2739, 2674, ..., 1542, 1581, 1478],
...,
[3216, 2998, 3165, ..., 3048, 2992, 3125],
[3121, 3252, 3299, ..., 3086, 3110, 2913],
[3231, 3261, 3414, ..., 3099, 3039, 3020]], dtype=int32), scattering_data=array([[102929, 101856, 105155, ..., 36466, 36234, 35175],
[100320, 98901, 104158, ..., 35047, 34531, 35871],
[102334, 101772, 98380, ..., 35634, 35428, 34703],
...,
[ 96866, 94780, 96978, ..., 95870, 94463, 97045],
[ 97101, 99105, 99604, ..., 97634, 97246, 94603],
[100027, 99620, 102607, ..., 95336, 96377, 94539]], dtype=int32), poni=None, ai=None, control_points=None, flatfield=None)
[5]:
data =[None,
Position.init(master_file, 1, 1, 5),
Position.init(master_file, 2, 7, 6),
Position.init(master_file, 3, 8, 9),
Position.init(master_file, 4, 11, 12),
Position.init(master_file, 5, 14, 13),
Position.init(master_file, 6, 15, 16),
Position.init(master_file, 7, 17, 18),
Position.init(master_file, 8, 20, 19),
Position.init(master_file, 9, 21, 22)]
[6]:
#calculate the mask:
mask = -detector.mask.astype(int)
for p in data[1:]:
numpy.minimum(mask, p.scattering_data, out=mask)
numpy.minimum(mask, p.calibration_data, out=mask)
detector.mask = (mask<0).astype(numpy.int8)
[7]:
#display scattering:
fig, ax = subplots(3,3, figsize=(12,12))
jupyter.display(data[1].calibration_data, ax=ax[0,2])
jupyter.display(data[2].calibration_data, ax=ax[0,1])
jupyter.display(data[3].calibration_data, ax=ax[0,0])
jupyter.display(data[4].calibration_data, ax=ax[1,0])
jupyter.display(data[5].calibration_data, ax=ax[1,1])
jupyter.display(data[6].calibration_data, ax=ax[1,2])
jupyter.display(data[7].calibration_data, ax=ax[2,2])
jupyter.display(data[8].calibration_data, ax=ax[2,1])
jupyter.display(data[9].calibration_data, ax=ax[2,0])
pass
Calibration of the central position
[16]:
calib = Calibration(center.calibration_data,
calibrant=calibrant,
wavelength=calibrant.wavelength,
#matplotlib.cm.ColormapRegistry.get_cmap
detector=detegth,matplotlib.cm.ColormapRegistry.get_cmapctor)
[17]:
print(calib.geoRef)
f2d = calib.geoRef.getFit2D()
f2d["tilt"] = 0
calib.geoRef.setFit2D(**f2d)
print(calib.geoRef)
calib.fixed+=["rot1", "rot2"]
print(f"Fixed parameters: {calib.fixed}")
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.378425e+00 m PONI= -2.184395e-01, -5.781937e-01 m rot1=-0.109975 rot2=0.059663 rot3=0.000000 rad
DirectBeamDist= 6428.631 mm Center: x=733.227, y=958.644 pix Tilt= 7.165° tiltPlanRotation= 28.558° 𝛌= 0.165Å
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.428631e+00 m PONI= 1.648867e-01, 1.261150e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6428.631 mm Center: x=733.227, y=958.644 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
Fixed parameters: ['wavelength', 'rot3', 'rot1', 'rot2']
[18]:
logger = pyFAI.gui.cli_calibration.logger
from silx.image import marchingsquares
def extract_cpt(self, method="massif", pts_per_deg=1.0, max_rings=numpy.iinfo(int).max):
"""
Performs an automatic keypoint extraction:
Can be used in recalib or in calib after a first calibration has been performed.
:param method: method for keypoint extraction
:param pts_per_deg: number of control points per azimuthal degree (increase for better precision)
:param max_rings: extract at most max_rings
"""
logger.info("in extract_cpt with method %s", method)
assert self.ai
assert self.calibrant
assert self.peakPicker
self.peakPicker.reset()
self.peakPicker.init(method, False)
if self.geoRef:
self.ai.setPyFAI(**self.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
if self.geoRef:
ttha = self.geoRef.get_ttha()
chia = self.geoRef.get_chia()
if (ttha is None) or (ttha.shape != self.peakPicker.data.shape):
ttha = self.geoRef.twoThetaArray(self.peakPicker.data.shape)
if (chia is None) or (chia.shape != self.peakPicker.data.shape):
chia = self.geoRef.chiArray(self.peakPicker.data.shape)
else:
ttha = self.ai.twoThetaArray(self.peakPicker.data.shape)
chia = self.ai.chiArray(self.peakPicker.data.shape)
rings = 0
self.peakPicker.sync_init()
if self.max_rings is None:
self.max_rings = tth.size
ms = marchingsquares.MarchingSquaresMergeImpl(ttha, self.mask, use_minmax_cache=True)
for i in range(tth.size):
if rings >= min(self.max_rings, max_rings):
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
self.peakPicker.massif_contour(mask)
# if self.gui:
# self.peakPicker.widget.update()
sub_data = self.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(self.peakPicker.data > upper_limit, mask)
size2 = mask2.sum(dtype=int)
if size2 < 1000:
upper_limit = mean
mask2 = numpy.logical_and(self.peakPicker.data > 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, self.peakPicker.data.shape[0]), points[:, 1].clip(0, self.peakPicker.data.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.peakPicker.peaks_from_area(mask=mask2, Imin=upper_limit, keep=keep, method=method, ring=i, dmin=dist_min, seed=seeds)
if self.basename:
self.peakPicker.points.save(self.basename + ".npt")
if self.weighted:
self.data = self.peakPicker.points.getWeightedList(self.peakPicker.data)
else:
self.data = self.peakPicker.points.getList()
if self.geoRef:
self.geoRef.data = numpy.array(self.data, dtype=numpy.float64)
Calibration.extract_cpt = extract_cpt
[19]:
calib.extract_cpt(max_rings=4)
[20]:
calib.refine()
Before refinement, the geometry is:
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.428631e+00 m PONI= 1.648867e-01, 1.261150e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6428.631 mm Center: x=733.227, y=958.644 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.429782e+00 m PONI= 1.643007e-01, 1.263860e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6429.782 mm Center: x=734.802, y=955.237 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.429782e+00 m PONI= 1.643007e-01, 1.263860e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6429.782 mm Center: x=734.802, y=955.237 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
[21]:
ai = pyFAI.load(calib.geoRef)
it = ai.integrate1d(center.scattering_data, npt, polarization_factor=polarization, error_model="no", method=("no", "csr", "opencl"))
sc = ai.sigma_clip(center.scattering_data, npt, polarization_factor=polarization, error_model="azimuthal", method=("no", "csr", "opencl"),
thres=0, max_iter=3)
md = ai.medfilt1d(center.scattering_data, npt, polarization_factor=polarization, method=("full", "csr", "opencl"))
[22]:
ax = jupyter.plot1d(it, label="integrate")
ax.errorbar(*sc, alpha=0.8, label="sigma-clip")
ax.plot(*md, alpha=0.8, label="median")
ax.legend()
[22]:
<matplotlib.legend.Legend at 0x7f20f5232790>
[23]:
# Approximate polarization correction needed:
ai.guess_polarization(center.scattering_data, unit='q_nm^-1', target_rad=10)
[23]:
0.9990997531534169
[24]:
# median filter provides the smoothest curve achievable
rebuilt = ai.calcfrom1d(md.radial,
md.intensity,
detector.shape,
dim1_unit=pyFAI.units.Q_NM,
polarization_factor=polarization)
flat = rebuilt/center.scattering_data
flat[numpy.where(detector.mask)] = numpy.nan
flat[center.scattering_data<=0] = numpy.nan
jupyter.display(flat)
/tmp/ipykernel_278476/3413793014.py:7: RuntimeWarning: divide by zero encountered in divide
flat = rebuilt/center.scattering_data
[24]:
<Axes: >
Calculate the approximate correction of the other positions
[25]:
dx,dy,dz = numpy.array(data[1].coordinates)-center.coordinates
ai1 = copy.copy(ai)
ai1.poni1 += dz*0.001
ai1.poni2 += dy*0.001
ai1
[25]:
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.429782e+00 m PONI= 2.643007e-01, 2.051260e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6429.782 mm Center: x=1192.593, y=1536.632 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
[26]:
AbstractCalibration.extract_cpt = extract_cpt
[27]:
calib1 = AbstractCalibration(data[1].scattering_data, detector.mask, detector, wavelength=wavelength, calibrant=calibrant)
calib1.preprocess()
calib1.data = []
calib1.geoRef = calib1.initgeoRef()
calib1.geoRef.setPyFAI(**ai1.getPyFAI())
[27]:
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.429782e+00 m PONI= 2.643007e-01, 2.051260e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6429.782 mm Center: x=1192.593, y=1536.632 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
[28]:
calib1.extract_cpt(max_rings=4)
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
[29]:
calib1.fixed+=["rot1", "rot2"]
calib1.geoRef.refine3(fix=calib1.fixed)
[29]:
1.271497880994544e-07
[30]:
calib1.geoRef
[30]:
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.014144e+00 m PONI= 2.627063e-01, 2.057110e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6014.144 mm Center: x=1195.994, y=1527.362 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
[31]:
data[1].ai = pyFAI.load(calib1.geoRef)
data[1].control_points = calib1.peakPicker.points
data[5].ai = pyFAI.load(calib.geoRef)
data[5].control_points = calib.peakPicker.points
Perform the geometry extraction for each of the position:
[32]:
for idx in [2,3,4,6,7,8,9]:
dx,dy,dz = numpy.array(data[idx].coordinates)-center.coordinates
ain = copy.copy(ai)
ain.poni1 += dz*0.001
ain.poni2 += dy*0.001
calibn = AbstractCalibration(data[idx].scattering_data, detector.mask, detector, wavelength=wavelength, calibrant=calibrant)
calibn.preprocess()
calibn.data = []
calibn.geoRef = calib1.initgeoRef()
calibn.geoRef.setPyFAI(**ain.getPyFAI())
calibn.extract_cpt(max_rings=4)
calibn.fixed+=["rot1", "rot2"]
calibn.geoRef.refine3(fix=calibn.fixed)
print(f"#### Position {idx} ####")
print(calibn.geoRef)
data[idx].ai = pyFAI.load(calibn.geoRef)
data[idx].control_points = calibn.peakPicker.points
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 2 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.152240e+00 m PONI= 2.641456e-01, 1.268375e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6152.240 mm Center: x=737.428, y=1535.730 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 3 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.137090e+00 m PONI= 2.637189e-01, 4.886695e-02 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6137.090 mm Center: x=284.110, y=1533.249 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 4 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.062984e+00 m PONI= 1.640642e-01, 4.816487e-02 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6062.984 mm Center: x=280.028, y=953.862 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 6 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.096212e+00 m PONI= 1.635525e-01, 2.058634e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6096.212 mm Center: x=1196.880, y=950.887 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 7 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.437632e+00 m PONI= 6.423896e-02, 2.052238e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6437.632 mm Center: x=1193.162, y=373.482 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 8 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.439459e+00 m PONI= 6.416683e-02, 1.264328e-01 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6439.459 mm Center: x=735.074, y=373.063 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
ERROR:root:No diffraction image available => not showing the contour
#### Position 9 ####
Detector Pilatus CdTe 2M PixelSize= 172µm, 172µm BottomRight (3)
Wavelength= 1.653123e-11 m
SampleDetDist= 6.438818e+00 m PONI= 6.416595e-02, 4.769705e-02 m rot1=0.000000 rot2=0.000000 rot3=0.000000 rad
DirectBeamDist= 6438.818 mm Center: x=277.308, y=373.058 pix Tilt= 0.000° tiltPlanRotation= 0.000° 𝛌= 0.165Å
[33]:
#display scattering:
fig, ax = subplots(3,3, figsize=(12,12))
jupyter.display(data[1].calibration_data, ai=data[1].ai, cp=data[1].control_points, ax=ax[0,2])
jupyter.display(data[2].calibration_data, ai=data[2].ai, cp=data[2].control_points, ax=ax[0,1])
jupyter.display(data[3].calibration_data, ai=data[3].ai, cp=data[3].control_points, ax=ax[0,0])
jupyter.display(data[4].calibration_data, ai=data[4].ai, cp=data[4].control_points, ax=ax[1,0])
jupyter.display(data[5].calibration_data, ai=data[5].ai, cp=data[5].control_points, ax=ax[1,1])
jupyter.display(data[6].calibration_data, ai=data[6].ai, cp=data[6].control_points, ax=ax[1,2])
jupyter.display(data[7].calibration_data, ai=data[7].ai, cp=data[7].control_points, ax=ax[2,2])
jupyter.display(data[8].calibration_data, ai=data[8].ai, cp=data[8].control_points, ax=ax[2,1])
jupyter.display(data[9].calibration_data, ai=data[9].ai, cp=data[9].control_points, ax=ax[2,0])
pass
Extract the flatfield for all positions
[34]:
for p in data[1:]:
md = p.ai.medfilt1d(p.scattering_data, npt, polarization_factor=polarization, method=("full", "csr", "opencl"))
rebuilt = p.ai.calcfrom1d(md.radial, md.intensity, detector.shape, dim1_unit=pyFAI.units.Q_NM, polarization_factor=polarization)
flat = rebuilt/p.scattering_data
flat[numpy.where(detector.mask)] = numpy.nan
flat[p.scattering_data<=0] = numpy.nan
p.flat = flat
/tmp/ipykernel_278476/1978307742.py:4: RuntimeWarning: divide by zero encountered in divide
flat = rebuilt/p.scattering_data
[35]:
#display flat:
fig, ax = subplots(3,3, figsize=(12,12))
jupyter.display(data[1].flat, ax=ax[0,2])
jupyter.display(data[2].flat, ax=ax[0,1])
jupyter.display(data[3].flat, ax=ax[0,0])
jupyter.display(data[4].flat, ax=ax[1,0])
jupyter.display(data[5].flat, ax=ax[1,1])
jupyter.display(data[6].flat, ax=ax[1,2])
jupyter.display(data[7].flat, ax=ax[2,2])
jupyter.display(data[8].flat, ax=ax[2,1])
jupyter.display(data[9].flat, ax=ax[2,0])
pass
The final Flatfield is the median of the flats calculated on the 9 positions
[36]:
flat_stack = numpy.array([p.flat for p in data[1:]])
flat = numpy.nanmedian(flat_stack, axis=0)
/tmp/ipykernel_278476/4120576390.py:2: RuntimeWarning: All-NaN slice encountered
flat = numpy.nanmedian(flat_stack, axis=0)
[37]:
jupyter.display(flat)
[37]:
<Axes: >
[38]:
fabio.edfimage.EdfImage(data=flat.astype("float32")).write("flat.edf")
[39]:
numpy.nanmean(flat)
[39]:
1.001724953057434
[40]:
print(f"Total run time: {time.perf_counter()-t0:.3f}s.")
Total run time: 533.202s.
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]:
[ ]: