Capillary sample self-absorption correction#
CapillarySelfAbsorptionCorrection corrects detector-resolved scattering from
a sample inside a straight, concentric cylindrical capillary. It supports a
two-dimensional detector, a measured or analytic two-dimensional beam profile,
separate absorption by the sample and capillary wall, and a horizontal or
tilted capillary.
The correction traces rays from illuminated scattering points to the actual detector pixels. It does not reduce the detector to a one-dimensional $2\theta$ curve, so pixels with the same $2\theta$ may receive different corrections when their azimuth or the capillary orientation differs.
MoDaCor provides two process steps over the same numerical model:
CapillarySelfAbsorptionCorrectionapplies the sample-origin correction when wall scattering is negligible or has already been removed consistently;CapillarySampleContainerCorrectionjointly treats matched filled and empty measurements, including the different wall-origin attenuation in each.
The wall attenuation of sample scattering is included in both. The second step is required when the wall’s own scattering cannot be neglected.
What the module calculates#
The initial geometry consists of two concentric radial phases:
a central sample of radius
sample_radiusand linear attenuation coefficientsample_mu;an optional capillary wall of thickness
wall_thicknessand coefficientwall_mu.
The radius and coefficient are deliberately separate inputs. Both phases may therefore use independently measured or calculated values, and the code forms products such as $\mu R$ only internally. All configured lengths and coefficients are converted to metres and reciprocal metres before the calculation.
For detector pixel $d$, the absolute sample-origin attenuation is
$$ A_{s,sc}(d) = \frac{\sum_v w_v \exp[-\mu_s L_{s,v,d} - \mu_w L_{w,v,d}]} {\sum_v w_v}. $$
Here $v$ indexes beam-weighted quadrature points in the illuminated sample volume. $L_s$ and $L_w$ are the total incoming-plus-outgoing path lengths in the sample and wall for that point and detector pixel. The calculation uses analytic ray intersections with each cylindrical boundary and Gauss–Legendre quadrature along only the occupied sample chords. It does not construct a three-dimensional voxel box.
The module also predicts the direct-beam transmission
$$ T_{calc} = \frac{\sum_b w_b \exp[-\mu_s L^{through}{s,b} - \mu_w L^{through}{w,b}]} {\sum_b w_b}, $$
where $b$ runs over the complete beam profile. Rays that miss the capillary have zero material path and are included with transmission one.
T_calc is a diagnostic. It is not substituted for an experimentally measured
transmission. It is also not generally equal to the forward-scattering limit
of $A_{s,sc}$: direct transmission is beam-area weighted, whereas scattering
attenuation is illuminated-volume weighted.
Geometry and coordinate convention#
The default MoDaCor laboratory frame is:
incident beam direction: $(0,0,1)$;
horizontal capillary axis: $(1,0,0)$;
vertical direction: $(0,1,0)$.
The default configuration is therefore:
capillary_axis: [1.0, 0.0, 0.0]
incident_direction: [0.0, 0.0, 1.0]
capillary_centre: [0.0, 0.0, 0.0]
capillary_centre_units: m
capillary_centre is a point on the cylinder centreline. The beam-profile
plane passes through that point, which expresses the current assumption that
the capillary is centred in the beam.
The module reads coord_x, coord_y, and coord_z from each selected
DataBundle. These arrays must be length-valued detector-element centres and
must broadcast to a two-dimensional detector grid. They are normally produced
by PixelCoordinates3D before this correction runs. Tilted or rotated detector
panels work because the calculation uses their three-dimensional pixel
positions rather than an assumed flat angular grid.
Tilted capillaries#
Any finite, non-zero capillary_axis vector is normalized internally, so a
tilted capillary can be configured directly:
capillary_axis: [1.0, 0.15, 0.05]
The implemented cylinder is straight and effectively infinite. A beam or exit ray that is parallel, or numerically too close to parallel, to the capillary axis is rejected. In that geometry the capillary end faces and finite length determine the path, and the infinite-cylinder model is insufficient.
Even for a horizontal capillary, the correction need not be constant along the detector direction parallel to its axis. At finite detector distance, pixels displaced along that direction receive oblique rays with longer physical paths. Mirror symmetry is expected for a centred symmetric setup; strict one-dimensional invariance is not.
Required upstream data#
Each processing key selected through with_processing_keys requires:
Key |
Meaning |
|---|---|
|
Detector signal to correct. |
|
Lab-frame detector-pixel x coordinate. |
|
Lab-frame detector-pixel y coordinate. |
|
Lab-frame detector-pixel z coordinate. |
|
Optional boolean mask; |
The coordinate key names and mask key are configurable. The default mask name
is mask, with Mask accepted as a compatibility alias.
For a scan-shaped mask, a detector pixel is skipped only when it is masked in every leading scan or frame position. A pixel active in at least one frame receives the static geometric correction so that the resulting two-dimensional factor map can broadcast across the scan.
Masked pixels retain an identity factor. They are not sent through the point-ray integrator. Non-finite detector coordinates are accepted only at masked pixels.
Complete pipeline example#
This example uses values supplied directly in the pipeline. Every scalar
geometry or attenuation value can instead be loaded through its corresponding
*_source and *_units_source setting.
CAPILLARY_ABSORPTION:
module: CapillarySelfAbsorptionCorrection
short_title: Correct capillary sample absorption
requires_steps: [PIXEL_COORDINATES, MERGE_MASKS, TRANSMISSION_NORMALIZATION]
configuration:
with_processing_keys: [sample]
coord_x_key: coord_x
coord_y_key: coord_y
coord_z_key: coord_z
mask_key: mask
capillary_axis: [1.0, 0.0, 0.0]
capillary_centre: [0.0, 0.0, 0.0]
capillary_centre_units: m
sample_radius: 0.50
sample_radius_units: mm
sample_mu: 8.2
sample_mu_units: 1/mm
wall_thickness: 0.010
wall_thickness_units: mm
wall_mu: 1.7
wall_mu_units: 1/mm
beam_profile:
type: image
signal_source: measurement::/entry1/instrument/beam/profile
pixel_pitch: [0.01, 0.01] # slow, fast
pixel_pitch_units: mm
image_centre: [127.5, 127.5]
downsample: [4, 4]
relative_weight_cutoff: 1.0e-6
input_state: transmission_normalized
transmission_source: measurement::/entry1/sample/transmission
transmission_units_source: measurement::/entry1/sample/transmission@units
transmission_uncertainties_sources:
transmission_SEM: measurement::/entry1/sample/transmission_sem
evaluation_mode: adaptive
relative_tolerance: 1.0e-3
absolute_tolerance: 1.0e-12
max_depth: 10
chord_order: 12
detector_chunk_size: 256
The requires_steps identifiers are illustrative; they must match the step IDs
in the actual pipeline.
Supplying sample and wall parameters#
Direct parameters and source-based parameters have the following mapping:
Direct value |
Data source |
Units source |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
When a source and direct value are both configured, the source takes
precedence. sample_radius must be positive. Wall thickness and both
coefficients must be non-negative. A zero wall thickness reduces the geometry
to a homogeneous sample cylinder; a zero wall coefficient is allowed for
limit checks.
The wall currently requires a linear attenuation coefficient. The sample
accepts either a coefficient or the effective-coefficient path described
below. The module does not fit a transmission z scan.
Composition/density/energy calculations may be performed upstream, including
with MoDaCor’s existing xraylib-based material utilities, and the result
supplied as sample_mu or wall_mu.
Deriving an effective sample coefficient from measurement metadata#
When the sample coefficient is not otherwise known, sample_mu may instead be
derived from either a sample-phase transmission or a sample-phase absorbed
fraction and a transmission path thickness:
$$ \mu_{eff} = \frac{-\ln T_s}{t_s}, \qquad A_s=1-T_s. $$
The accepted alternatives are:
Quantity |
Direct value |
Data source |
Units source |
Uncertainty sources |
|---|---|---|---|---|
Sample-only transmission $T_s$ |
|
|
dimensionless |
|
Sample-only absorbed fraction $A_s=1-T_s$ |
|
|
dimensionless |
|
Transmission path thickness $t_s$ |
|
|
|
|
Configure exactly one of sample_mu, sample_phase_transmission, or
sample_phase_absorption. The two sample-phase factors are mutually exclusive
and each requires sample_phase_thickness. Source references take precedence
over direct values of the same quantity. Transmission must be in $(0,1]$,
absorption in $[0,1)$, and thickness must be positive.
Uncertainty values use the same units as their associated quantity and must be
scalar or constant-valued.
For example, values already separated from the empty-container absorption can be read directly from a measurement HDF5 file:
sample_mu: null
sample_phase_absorption_source: sample::/entry1/sample/absorption_by_sample
sample_phase_absorption_uncertainties_sources:
sample_absorption_SEM: sample::/entry1/sample/absorption_by_sample_sem
sample_phase_thickness_source: sample::/entry1/sample/thickness_averaged/mean
sample_phase_thickness_units_source: sample::/entry1/sample/thickness_averaged/mean@units
sample_phase_thickness_uncertainties_sources:
sample_thickness_SEM: sample::/entry1/sample/thickness_averaged/sem
Equivalently, use sample_phase_transmission_source for a sample-only
transmission factor. Here “sample phase” is important: the value must exclude
the capillary wall or background contribution. It is used only to derive
$\mu_{eff}$; it does not divide or otherwise normalize the scattering signal,
so it is compatible with the composite module’s prohibition on a separate
measurement-transmission normalization step.
For a capillary illuminated over a finite beam height, the measured transmission averages different chord lengths. Consequently $-\ln(T_s)/t_s$ is generally an effective coefficient unless $t_s$ is a matching effective transmission path. Do not silently substitute the capillary diameter or centreline chord for a whole-beam effective measurement. The calculated whole-beam transmission output provides a useful consistency check.
Uncertainty support#
The current implementation distinguishes measured input uncertainty, derived effective-$\mu$ uncertainty, and unsupported model-parameter uncertainty.
Uncertainties already attached to the input
signalBaseDatapropagate through division by the sample factor. In the composite module, filled- and empty-signal uncertainties propagate through attenuation-aware subtraction and the final division. MoDaCor uses first-order, uncorrelated propagation; named uncertainty sources are retained.Covariance is not represented. In particular, a monitor or normalization uncertainty shared by the filled and empty measurements is still treated as uncorrelated by ordinary
BaseDataarithmetic; the module does not model its cancellation or correlation. The same limitation applies when the sample-phase absorption estimate and empty-capillary scattering originate from a common background measurement.For the sample-only module with
input_state: transmission_normalized, measured-transmission uncertainties supplied throughtransmission_uncertainties_sourcespropagate through the residual divisor and corrected signal.Uncertainties configured for the sample-phase transmission or absorption and thickness propagate first to the derived coefficient according to
$$ \sigma_{\mu,T}=\frac{\sigma_T}{t_sT_s},\qquad \sigma_{\mu,A}=\frac{\sigma_A}{t_s(1-A_s)},\qquad \sigma_{\mu,t}=\frac{\mu_{eff}\sigma_t}{t_s}. $$
Distinct mapping keys remain distinct uncertainty components. Contributions with the same key are combined in quadrature.
The derived-$\mu$ terms propagate to
capillary_effective_sample_mu, the affected attenuation-factor maps, calculated filled/sample transmission, and corrected signal. The empty-wall factor and empty-capillary calculated transmission do not depend on sample $\mu$ and therefore receive no such component.The composite module differentiates its complete expression. Thus the same physical sample-$\mu$ uncertainty is correlated between $A_{s,sc}$ and $A_{c,sc}$ rather than being incorrectly combined as two independent factor errors.
Factor sensitivities use nominal and perturbed sample coefficients while
sharing scattering points, geometric path calculations, and one adaptive
detector mesh. A central difference is used except close to $\mu=0$, where a
forward difference avoids a negative coefficient. The dimensionless control
sample_mu_sensitivity_relative_step defaults to $10^{-2}$; it scales against
the larger of $\mu$ and $1/R$. Check stability by changing this value when
establishing a high-accuracy pipeline.
Direct sample_mu and wall_mu uncertainties are intentionally not exposed
yet because reliable coefficient-uncertainty metadata appears uncommon.
Uncertainties in sample radius, wall thickness, capillary orientation, detector
geometry, and beam-profile parameters are also not propagated. Those would be
geometry/model-parameter uncertainties rather than the implemented
measurement-derived effective-$\mu$ path.
Beam profiles#
Beam coordinates use (slow, fast) ordering in the plane normal to the
incident direction. All profile weights are non-negative and normalized
internally. Profile intensity normalization does not replace the pipeline’s
separate incident-flux normalization.
Measured image#
beam_profile:
type: image
signal_source: measurement::/entry1/instrument/beam/profile
pixel_pitch: [0.01, 0.01]
pixel_pitch_units: mm
image_centre: [127.5, 127.5]
rotation: 0.0
rotation_units: degree
downsample: [4, 4]
relative_weight_cutoff: 1.0e-6
Instead of signal_source, a small profile may be supplied inline as signal.
image_centre is the fractional (slow, fast) image index aligned with
capillary_centre; it defaults to the geometric array centre.
Downsampling groups image blocks without losing their integrated intensity. Each retained block is represented at its intensity-weighted centroid, which preserves the first spatial moment. The relative cutoff removes pixels below a fraction of the image maximum. The retained fraction of the original incident weight is stored as a diagnostic.
Downsampling is a numerical approximation: preserving total weight and the centroid does not guarantee that attenuation is unchanged when a block spans a capillary boundary or a strongly varying chord. Refine it until the resulting correction is stable.
Two-dimensional Gaussian#
beam_profile:
type: gaussian_2d
standard_deviations: [0.08, 0.15] # slow, fast principal widths
width_units: mm
rotation: 12.0
rotation_units: degree
quadrature_order: [12, 16]
truncation_sigma: [4.0, 4.0]
The standard deviations are the two principal widths. Rotation permits a correlated Gaussian in the laboratory slow/fast basis. The finite truncation keeps the calculation bounded; the analytically retained Gaussian fraction is recorded.
Two-dimensional trapezoid#
beam_profile:
type: trapezoid_2d
plateau_width: [0.10, 0.25]
ramp_widths:
- [0.03, 0.04] # slow negative, slow positive
- [0.05, 0.06] # fast negative, fast positive
width_units: mm
rotation: 0.0
rotation_units: degree
quadrature_order_per_region: [6, 6]
This is a separable product of slow- and fast-axis trapezoids. The four ramp widths are independent, allowing an asymmetric beam. Quadrature nodes are placed separately in each plateau and linear-ramp region, which is more efficient and accurate than sampling the entire bounding rectangle uniformly.
Input-state algebra#
The module always calculates the absolute factor $A_{s,sc}$. What it divides
the supplied signal by depends on input_state:
|
Meaning of supplied signal |
Applied divisor $C(d)$ |
|---|---|---|
|
Uncorrected detector intensity. |
$A_{s,sc}(d)$ |
|
Incident-flux normalized, but not transmission normalized. |
$A_{s,sc}(d)$ |
|
Already divided by measured transmission $T_{meas}$. |
$A_{s,sc}(d)/T_{meas}$ |
The operation is
$$ I_{corrected}(d) = \frac{I_{input}(d)}{C(d)}. $$
For transmission-normalized input this is equivalent to
$$ I_{corrected}(d) = \frac{T_{meas} I_{input}(d)}{A_{s,sc}(d)}. $$
transmission_normalized is the default and requires transmission_source.
The transmission must be an effective measurement over the same complete beam
used for the data; it must not be a centreline Beer–Lambert value. The module
does not guess the input state from numeric values.
Measured-transmission uncertainties configured through
transmission_uncertainties_sources are propagated through the residual
divisor and into the corrected signal. Sample-$\mu$ uncertainty derived from
uncertain phase transmission/absorption and thickness is also propagated as
described below. Uncertainties on a directly specified $\mu$, radius, wall
thickness, detector geometry, and beam-profile calibration are not yet
propagated by this process step.
Exact and adaptive detector evaluation#
evaluation_mode: exact traces every active detector pixel from every
scattering quadrature point. It is the reference mode and should be used for
validation, small regions of interest, and convergence studies.
evaluation_mode: adaptive recursively divides the regular detector-index
grid. For each fully active cell it calculates the corners, edge midpoints,
centre, and four interior quarter points. Bilinear interpolation is accepted
when every non-corner checkpoint meets the configured mixed absolute/relative
tolerance. A failed cell subdivides. A cell that reaches max_depth is
calculated exactly.
Cells crossing a mask boundary subdivide independently. Fully masked cells are discarded, and unresolved boundary cells evaluate only their active pixels. The output diagnostic distinguishes exactly evaluated pixels from interpolated ones.
The adaptive tolerance is an a posteriori checkpoint criterion, not a formal error bound everywhere between checkpoints. Compare adaptive output with exact pixels or a tighter tolerance for new geometry, very high attenuation, close detectors, or structured beam profiles.
Current performance indication#
Development measurements on an arm64 machine used a 512 by 512 detector, 3,072 illuminated-volume points, and $\mu R=3$:
Geometry |
Exact nodes |
Fraction of detector |
Adaptive time |
Maximum error at 1,024 withheld pixels |
|---|---|---|---|---|
Horizontal cylinder |
4,225 |
1.61% |
1.77 s |
$4.5\times10^{-4}$ |
Axis proportional to $(1,0.3,0.1)$ |
3,903 |
1.49% |
1.60 s |
$8.7\times10^{-4}$ |
The requested relative tolerance was $10^{-3}$. The same case was estimated at
about 110 s when every detector pixel was evaluated exactly. These are
development measurements, not guarantees for arbitrary instruments. Peak
temporary allocation and runtime scale strongly with detector_chunk_size
and the number of illuminated-volume points.
Output data#
The default output keys are:
Key |
Contents |
|---|---|
|
Absolute sample-origin attenuation $A_{s,sc}(d)$. |
|
Residual divisor $C(d)$ actually applied to |
|
Scalar model prediction $T_{calc}$. |
|
Resolved or measurement-derived effective sample coefficient, in $mathrm{m}^{-1}$. |
|
Boolean map: |
|
Scalar incident-weight fraction retained after profile truncation or thresholding. |
Each name can be changed with the corresponding *_key configuration. Masked
pixels have attenuation and divisor one, and are false in the evaluated map.
The distinction between the first two outputs matters for transmission-normalized data: the absolute factor remains $A_{s,sc}$ while the applied divisor is $A_{s,sc}/T_{meas}$.
Container scattering is a separate problem#
Absorption of sample scattering by the wall is already included in $A_{s,sc}$. Scattering generated by the wall itself has a different spatial origin and a different attenuation factor. Ordinary empty-capillary subtraction followed by this sample correction is therefore not generally exact.
For raw or flux-normalized measurements, the intended composite relation is
$$ I_s = \frac{I_{sc}^{raw} - (A_{c,sc}/A_{c,c})I_c^{raw}}{A_{s,sc}}, $$
where $A_{c,sc}$ is the wall-origin factor in the filled capillary and $A_{c,c}$ the wall-origin factor in the empty capillary. If both measurements were divided by their own measured transmissions, the equivalent algebra would be
$$ I_s = \frac{T_{sc}N_{sc} - (A_{c,sc}/A_{c,c})T_cN_c}{A_{s,sc}}. $$
CapillarySampleContainerCorrection intentionally implements only the first
equation. It does not attempt to undo an earlier transmission normalization,
because the result can depend on where that normalization occurred relative to
other pipeline operations. Do not emulate this module by applying two
independent sample corrections and then subtracting: those operations are not
algebraically interchangeable.
Composite pipeline configuration#
The filled and empty signals must have the same shape, compatible units, matching detector geometry, and comparable exposure and incident-flux normalization. If they were measured on different grids, regrid them before this step.
Important
If you use CapillarySampleContainerCorrection, do not include a separate
normalization by the measured filled- or empty-capillary transmission in the
same correction pipeline. Exposure-time, incident-flux, detector-response, and
other common-scale normalizations are allowed, provided the filled and empty
signals remain directly comparable.
CAPILLARY_SAMPLE_AND_CONTAINER:
module: CapillarySampleContainerCorrection
short_title: Correct sample and capillary wall attenuation
requires_steps: [PIXEL_COORDINATES, MERGE_MASKS, NORMALIZE_EXPOSURE_AND_FLUX]
configuration:
filled_processing_key: sample
empty_processing_key: background
mask_key: mask
empty_mask_key: mask
capillary_axis: [1.0, 0.0, 0.0]
sample_radius: 0.50
sample_radius_units: mm
sample_mu: 8.2
sample_mu_units: 1/mm
wall_thickness: 0.010
wall_thickness_units: mm
wall_mu: 1.7
wall_mu_units: 1/mm
# Usually zero for an empty capillary; it may represent a gas or other
# known material in the central region of the background measurement.
empty_centre_mu: 0.0
empty_centre_mu_units: 1/mm
beam_profile:
type: gaussian_2d
standard_deviations: [0.08, 0.15]
width_units: mm
quadrature_order: [12, 16]
truncation_sigma: [4.0, 4.0]
evaluation_mode: adaptive
relative_tolerance: 1.0e-3
chord_order: 12
# Wall-origin quadrature may need more nodes at high sample absorption.
wall_chord_order: 32
The corrected sample signal replaces signal in the filled DataBundle. The
empty bundle remains unchanged. The filled and empty masks are combined with a
logical OR and stored on the filled output. At scan dimensions, a detector
pixel is ray-traced only if there is at least one paired frame in which both
measurements are active. Values at combined-mask positions are preserved from
the original filled signal and ignored downstream through the union mask.
The composite step requires a positive wall thickness because wall-origin
quadrature is part of the calculation. empty_centre_mu defaults to zero but
may be configured as a value or with empty_centre_mu_source and
empty_centre_mu_units_source. wall_chord_order controls wall-origin
integration independently and defaults to chord_order when omitted.
The filled- and empty-capillary wall factors share the same geometric path calculation and adaptive detector mesh. Only their attenuation coefficients differ. This both reduces runtime and avoids introducing two independently chosen interpolation meshes into their ratio.
Composite outputs#
The filled output bundle receives:
Key |
Contents |
|---|---|
|
$A_{s,sc}$, sample-origin attenuation in the filled capillary. |
|
$A_{c,sc}$, wall-origin attenuation with the sample present. |
|
$A_{c,c}$, wall-origin attenuation in the empty capillary. |
|
Pixelwise ratio $A_{c,sc}/A_{c,c}$. |
|
Calculated effective transmission of the filled capillary. |
|
Calculated effective transmission of the empty capillary. |
|
Resolved or measurement-derived effective sample coefficient. |
|
Incident weight retained by profile truncation or thresholding. |
|
Exact-evaluation mask for $A_{s,sc}$. |
|
Exact-evaluation mask for $A_{c,sc}$. |
|
Exact-evaluation mask for $A_{c,c}$. |
Filled- and empty-signal uncertainties propagate through the subtraction and sample division. When $\mu_{eff}$ is derived from uncertain sample-phase absorption/transmission and thickness, those uncertainty components also propagate through the correlated sample- and wall-factor dependence described above. Other model-parameter uncertainties are not yet included. The two calculated transmissions are diagnostics only and are not used to rescale the signals. Sample-origin refinement is independent, while the two wall maps use one shared refinement mesh whose acceptance test covers both factors. Validate the composite output and wall-scale ratio against exact mode when establishing settings for a new instrument.
Accuracy controls and convergence#
For a new setup, establish stability in this order:
Run a small detector region or selected frames with
evaluation_mode: exact.Increase
chord_orderandwall_chord_orderindependently until the exact correction changes acceptably little.For analytic profiles, increase their quadrature order; for image profiles, reduce downsampling and cutoff.
Compare the intended adaptive settings against exact values, including high-angle detector regions and mask boundaries.
Compare
capillary_calculated_transmissionwith the measured effective transmission. A discrepancy is a diagnostic for geometry, beam-profile, coefficient, or normalization mismatch; it is not automatically a scale factor to apply.
The factor must remain positive and finite. The module rejects active-pixel
values below minimum_attenuation_factor rather than dividing by an unstable
number.
Wall-origin quadrature can converge more slowly than sample-origin quadrature when sample absorption is strong, because an outgoing wall ray can become tangent to the inner cylinder within an integration segment. In one deliberately difficult development case with radius ratio 1.1 and sample $\mu R=3$, the maximum relative change against 96 wall nodes was about $6.0\times10^{-3}$ at 12 nodes, $2.9\times10^{-3}$ at 20, $1.2\times10^{-3}$ at 32, and $8.8\times10^{-4}$ at 48. At sample $\mu R=0.5$, 12 nodes were already within about $1.6\times10^{-4}$. These figures are not universal tolerances; they show why the two chord orders are separate controls.
Model limitations#
The implemented model assumes:
a straight, circular, concentric and effectively infinite cylinder;
a capillary centred in the incident beam;
parallel incident rays;
single scattering and Beer–Lambert attenuation;
one central sample phase and an optional concentric wall;
a static detector geometry represented by pixel-centre coordinates.
It does not currently model finite capillary ends, eccentric or non-circular walls, wall texture or crystallographic diffraction, refraction, multiple scattering, or uncertainty in geometry/profile parameters. Detector pixels are treated as point centres; detector-pixel area quadrature is not currently performed.
Further reading#
The implementation and validation plan is documented in Capillary self-absorption and container correction. The principal literature references are:
Y. Chen et al., Crystal Growth & Design 26 (2026), 1036–1047, https://doi.org/10.1021/acs.cgd.5c00551.
S. N. Sulyanov, A. A. Gogin & H. Boysen, J. Appl. Cryst. 45 (2012), 93–97, https://doi.org/10.1107/S0021889811048217.
M. E. Bowden & M. Ryan, J. Appl. Cryst. 43 (2010), 693–698, https://doi.org/10.1107/S0021889810021114.
The one-dimensional homogeneous-cylinder implementation in
diffpy.labpdfproc is used as an independent regression reference, not as a
runtime dependency. It does not cover the two-phase, arbitrary-axis,
beam-profile, or detector-azimuth requirements described here.