|
30 | 30 | __contact__ = "valentin.valls@esrf.eu"
|
31 | 31 | __license__ = "MIT"
|
32 | 32 | __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
|
33 |
| -__date__ = "04/04/2025" |
| 33 | +__date__ = "16/05/2025" |
34 | 34 | __status__ = "development"
|
35 | 35 |
|
36 | 36 | import sys
|
| 37 | +import copy |
37 | 38 | from dataclasses import fields, asdict, dataclass as _dataclass
|
38 | 39 | from collections import namedtuple
|
39 | 40 | from enum import IntEnum
|
|
55 | 56 | dataclass = _dataclass
|
56 | 57 |
|
57 | 58 |
|
58 |
| - |
59 | 59 | class ErrorModel(IntEnum):
|
60 | 60 | NO = 0
|
61 | 61 | VARIANCE = 1
|
@@ -91,10 +91,45 @@ def as_str(self):
|
91 | 91 | return self.name.lower()
|
92 | 92 |
|
93 | 93 |
|
94 |
| -class IntegrateResult(tuple): |
| 94 | +class _CopyableTuple(tuple): |
| 95 | + "Abstract class that can be copied using the copy module" |
| 96 | + COPYABLE_ATTR = tuple() # list of copyable attributes |
| 97 | + |
| 98 | + def __copy__(self): |
| 99 | + "Helper function for copy.copy()" |
| 100 | + other = self.__class__(*self) |
| 101 | + for attr in self.COPYABLE_ATTR: |
| 102 | + setattr(other, attr, getattr(self, attr)) |
| 103 | + return other |
| 104 | + |
| 105 | + def __deepcopy__(self, memo=None): |
| 106 | + "Helper function for copy.deepcopy()" |
| 107 | + if memo is None: |
| 108 | + memo = {} |
| 109 | + args = [] |
| 110 | + for i in self: |
| 111 | + cpy = copy.deepcopy(i, memo) |
| 112 | + memo[id(i)] = cpy |
| 113 | + args.append(cpy) |
| 114 | + other = self.__class__(*args) |
| 115 | + for attr in self.COPYABLE_ATTR: |
| 116 | + org = getattr(self, attr) |
| 117 | + cpy = copy.deepcopy(org, memo) |
| 118 | + memo[id(org)] = cpy |
| 119 | + setattr(other, attr, cpy) |
| 120 | + return other |
| 121 | + |
| 122 | + |
| 123 | +class IntegrateResult(_CopyableTuple): |
95 | 124 | """
|
96 | 125 | Class defining shared information between Integrate1dResult and Integrate2dResult.
|
97 | 126 | """
|
| 127 | + COPYABLE_ATTR = {"_sum_signal", "_sum_variance", "_sum_normalization", "_sum_normalization2", |
| 128 | + "_count", "_unit", "_has_mask_applied", "_has_dark_correction", |
| 129 | + "_has_flat_correction", "_has_solidangle_correction", "_normalization_factor", |
| 130 | + "_polarization_factor", "_metadata", "_npt_azim", "_percentile", "_method", |
| 131 | + "_method_called", "_compute_engine", "_error_model", "_std", "_sem", |
| 132 | + "_poni", "_weighted_average"} |
98 | 133 |
|
99 | 134 | def __init__(self):
|
100 | 135 | self._sum_signal = None # sum of signal
|
@@ -396,8 +431,7 @@ def _set_error_model(self, value):
|
396 | 431 |
|
397 | 432 | @property
|
398 | 433 | def poni(self):
|
399 |
| - """content of the PONI-file |
400 |
| - """ |
| 434 | + "content of the PONI-file" |
401 | 435 | return self._poni
|
402 | 436 |
|
403 | 437 | def _set_poni(self, value):
|
@@ -594,14 +628,20 @@ def _set_azimuthal_unit(self, unit):
|
594 | 628 | self._azimuthal_unit = unit
|
595 | 629 |
|
596 | 630 |
|
597 |
| -class SeparateResult(tuple): |
| 631 | +class SeparateResult(_CopyableTuple): |
598 | 632 | """
|
599 | 633 | Class containing the result of AzimuthalIntegrator.separte which separates the
|
600 | 634 |
|
601 | 635 | * Amorphous isotropic signal (from a median filter or a sigma-clip)
|
602 | 636 | * Bragg peaks (signal > amorphous)
|
603 | 637 | * Shadow areas (signal < amorphous)
|
604 | 638 | """
|
| 639 | + COPYABLE_ATTR = {'_radial', '_intensity', '_sigma', |
| 640 | + '_sum_signal', '_sum_variance', '_sum_normalization', |
| 641 | + '_count', '_unit', '_has_mask_applied', '_has_dark_correction', |
| 642 | + '_has_flat_correction', '_normalization_factor', '_polarization_factor', |
| 643 | + '_metadata', '_npt_rad', '_npt_azim', '_percentile', '_method', |
| 644 | + '_method_called', '_compute_engine', '_shadow'} |
605 | 645 |
|
606 | 646 | def __new__(self, bragg, amorphous):
|
607 | 647 | return tuple.__new__(SeparateResult, (bragg, amorphous))
|
@@ -907,8 +947,17 @@ def _set_npt_azim(self, value):
|
907 | 947 | self._npt_azim = value
|
908 | 948 |
|
909 | 949 |
|
910 |
| -class SparseFrame(tuple): |
| 950 | +class SparseFrame(_CopyableTuple): |
911 | 951 | """Result of the sparsification of a diffraction frame"""
|
| 952 | + COPYABLE_ATTR = {'_shape', '_dtype', '_mask', |
| 953 | + '_radius', '_dummy', '_background_avg', |
| 954 | + '_background_std', '_unit', '_has_dark_correction', |
| 955 | + '_has_flat_correction', '_normalization_factor', '_polarization_factor', |
| 956 | + '_metadata', '_percentile', '_method', |
| 957 | + '_method_called', '_compute_engine', |
| 958 | + '_cutoff_clip', '_cutoff_pick', '_cutoff_peak', |
| 959 | + '_background_cycle', '_noise', '_radial_range', '_error_model', |
| 960 | + '_peaks', '_peak_patch_size', '_peak_connected'} |
912 | 961 |
|
913 | 962 | def __new__(self, index, intensity):
|
914 | 963 | return tuple.__new__(SparseFrame, (index, intensity))
|
@@ -1045,23 +1094,24 @@ def peak_connected(self):
|
1045 | 1094 | def unit(self):
|
1046 | 1095 | return self._unit
|
1047 | 1096 |
|
| 1097 | + |
1048 | 1098 | def rebin1d(res2d):
|
1049 | 1099 | """Function that rebins an Integrate2dResult into a Integrate1dResult
|
1050 | 1100 |
|
1051 | 1101 | :param res2d: Integrate2dResult instance obtained from ai.integrate2d
|
1052 | 1102 | :return: Integrate1dResult
|
1053 | 1103 | """
|
1054 | 1104 | bins_rad = res2d.radial
|
1055 |
| - sum_signal = res2d.sum_signal.sum(axis=0) |
1056 |
| - sum_normalization = res2d.sum_normalization.sum(axis=0) |
| 1105 | + sum_signal = res2d.sum_signal.sum(axis=0) |
| 1106 | + sum_normalization = res2d.sum_normalization.sum(axis=0) |
1057 | 1107 | I = sum_signal / sum_normalization
|
1058 | 1108 | if res2d.sum_variance is not None:
|
1059 |
| - sum_variance = res2d.sum_variance.sum(axis=0) |
| 1109 | + sum_variance = res2d.sum_variance.sum(axis=0) |
1060 | 1110 | sem = numpy.sqrt(sum_variance) / sum_normalization
|
1061 | 1111 | result = Integrate1dResult(bins_rad, I, sem)
|
1062 | 1112 | result._set_sum_normalization2(res2d.sum_normalization2.sum(axis=0))
|
1063 | 1113 | result._set_sum_variance(sum_variance)
|
1064 |
| - result._set_std(numpy.sqrt(sum_variance) / sum_normalization ) |
| 1114 | + result._set_std(numpy.sqrt(sum_variance) / sum_normalization) |
1065 | 1115 | result._set_std(sem)
|
1066 | 1116 | else:
|
1067 | 1117 | result = Integrate1dResult(bins_rad, I)
|
|
0 commit comments