reflectorch 1.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. reflectorch/__init__.py +17 -0
  2. reflectorch/data_generation/__init__.py +128 -0
  3. reflectorch/data_generation/dataset.py +216 -0
  4. reflectorch/data_generation/likelihoods.py +80 -0
  5. reflectorch/data_generation/noise.py +471 -0
  6. reflectorch/data_generation/priors/__init__.py +60 -0
  7. reflectorch/data_generation/priors/base.py +55 -0
  8. reflectorch/data_generation/priors/exp_subprior_sampler.py +298 -0
  9. reflectorch/data_generation/priors/independent_priors.py +195 -0
  10. reflectorch/data_generation/priors/multilayer_models.py +311 -0
  11. reflectorch/data_generation/priors/multilayer_structures.py +104 -0
  12. reflectorch/data_generation/priors/no_constraints.py +206 -0
  13. reflectorch/data_generation/priors/parametric_models.py +842 -0
  14. reflectorch/data_generation/priors/parametric_subpriors.py +369 -0
  15. reflectorch/data_generation/priors/params.py +252 -0
  16. reflectorch/data_generation/priors/sampler_strategies.py +370 -0
  17. reflectorch/data_generation/priors/scaler_mixin.py +65 -0
  18. reflectorch/data_generation/priors/subprior_sampler.py +371 -0
  19. reflectorch/data_generation/priors/utils.py +118 -0
  20. reflectorch/data_generation/process_data.py +41 -0
  21. reflectorch/data_generation/q_generator.py +280 -0
  22. reflectorch/data_generation/reflectivity/__init__.py +102 -0
  23. reflectorch/data_generation/reflectivity/abeles.py +97 -0
  24. reflectorch/data_generation/reflectivity/kinematical.py +71 -0
  25. reflectorch/data_generation/reflectivity/memory_eff.py +105 -0
  26. reflectorch/data_generation/reflectivity/numpy_implementations.py +120 -0
  27. reflectorch/data_generation/reflectivity/smearing.py +138 -0
  28. reflectorch/data_generation/reflectivity/smearing_pointwise.py +110 -0
  29. reflectorch/data_generation/scale_curves.py +112 -0
  30. reflectorch/data_generation/smearing.py +99 -0
  31. reflectorch/data_generation/utils.py +223 -0
  32. reflectorch/extensions/__init__.py +0 -0
  33. reflectorch/extensions/jupyter/__init__.py +11 -0
  34. reflectorch/extensions/jupyter/api.py +85 -0
  35. reflectorch/extensions/jupyter/callbacks.py +34 -0
  36. reflectorch/extensions/jupyter/components.py +758 -0
  37. reflectorch/extensions/jupyter/custom_select.py +268 -0
  38. reflectorch/extensions/jupyter/log_widget.py +241 -0
  39. reflectorch/extensions/jupyter/model_selection.py +495 -0
  40. reflectorch/extensions/jupyter/plotly_plot_manager.py +329 -0
  41. reflectorch/extensions/jupyter/widget.py +625 -0
  42. reflectorch/extensions/matplotlib/__init__.py +5 -0
  43. reflectorch/extensions/matplotlib/losses.py +32 -0
  44. reflectorch/extensions/refnx/refnx_conversion.py +77 -0
  45. reflectorch/inference/__init__.py +28 -0
  46. reflectorch/inference/inference_model.py +848 -0
  47. reflectorch/inference/input_interface.py +239 -0
  48. reflectorch/inference/loading_data.py +55 -0
  49. reflectorch/inference/multilayer_fitter.py +171 -0
  50. reflectorch/inference/multilayer_inference_model.py +193 -0
  51. reflectorch/inference/plotting.py +524 -0
  52. reflectorch/inference/preprocess_exp/__init__.py +7 -0
  53. reflectorch/inference/preprocess_exp/attenuation.py +36 -0
  54. reflectorch/inference/preprocess_exp/cut_with_q_ratio.py +31 -0
  55. reflectorch/inference/preprocess_exp/footprint.py +81 -0
  56. reflectorch/inference/preprocess_exp/interpolation.py +19 -0
  57. reflectorch/inference/preprocess_exp/normalize.py +21 -0
  58. reflectorch/inference/preprocess_exp/preprocess.py +121 -0
  59. reflectorch/inference/query_matcher.py +82 -0
  60. reflectorch/inference/record_time.py +43 -0
  61. reflectorch/inference/sampler_solution.py +56 -0
  62. reflectorch/inference/scipy_fitter.py +364 -0
  63. reflectorch/inference/torch_fitter.py +87 -0
  64. reflectorch/ml/__init__.py +32 -0
  65. reflectorch/ml/basic_trainer.py +292 -0
  66. reflectorch/ml/callbacks.py +81 -0
  67. reflectorch/ml/dataloaders.py +27 -0
  68. reflectorch/ml/loggers.py +56 -0
  69. reflectorch/ml/schedulers.py +356 -0
  70. reflectorch/ml/trainers.py +201 -0
  71. reflectorch/ml/utils.py +2 -0
  72. reflectorch/models/__init__.py +16 -0
  73. reflectorch/models/activations.py +50 -0
  74. reflectorch/models/encoders/__init__.py +19 -0
  75. reflectorch/models/encoders/conv_encoder.py +219 -0
  76. reflectorch/models/encoders/conv_res_net.py +115 -0
  77. reflectorch/models/encoders/fno.py +134 -0
  78. reflectorch/models/encoders/integral_kernel_embedding.py +390 -0
  79. reflectorch/models/networks/__init__.py +14 -0
  80. reflectorch/models/networks/mlp_networks.py +434 -0
  81. reflectorch/models/networks/residual_net.py +157 -0
  82. reflectorch/paths.py +29 -0
  83. reflectorch/runs/__init__.py +31 -0
  84. reflectorch/runs/config.py +25 -0
  85. reflectorch/runs/slurm_utils.py +93 -0
  86. reflectorch/runs/train.py +78 -0
  87. reflectorch/runs/utils.py +405 -0
  88. reflectorch/test_config.py +4 -0
  89. reflectorch/train.py +4 -0
  90. reflectorch/train_on_cluster.py +4 -0
  91. reflectorch/utils.py +98 -0
  92. reflectorch-1.5.1.dist-info/METADATA +151 -0
  93. reflectorch-1.5.1.dist-info/RECORD +96 -0
  94. reflectorch-1.5.1.dist-info/WHEEL +5 -0
  95. reflectorch-1.5.1.dist-info/licenses/LICENSE.txt +21 -0
  96. reflectorch-1.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,17 @@
1
+ from reflectorch.data_generation import *
2
+ from reflectorch.ml import *
3
+ from reflectorch.models import *
4
+ from reflectorch.utils import *
5
+ from reflectorch.paths import *
6
+ from reflectorch.runs import *
7
+ from reflectorch.inference import *
8
+
9
+ from reflectorch.data_generation import __all__ as all_data_generation
10
+ from reflectorch.ml import __all__ as all_ml
11
+ from reflectorch.models import __all__ as all_models
12
+ from reflectorch.utils import __all__ as all_utils
13
+ from reflectorch.paths import __all__ as all_paths
14
+ from reflectorch.runs import __all__ as all_runs
15
+ from reflectorch.inference import __all__ as all_inference
16
+
17
+ __all__ = all_data_generation + all_ml + all_models + all_utils + all_paths + all_runs + all_inference
@@ -0,0 +1,128 @@
1
+ from reflectorch.data_generation.dataset import BasicDataset, BATCH_DATA_TYPE
2
+ from reflectorch.data_generation.priors import (
3
+ Params,
4
+ PriorSampler,
5
+ BasicPriorSampler,
6
+ SingleParamPrior,
7
+ SimplePriorSampler,
8
+ UniformParamPrior,
9
+ GaussianParamPrior,
10
+ TruncatedGaussianParamPrior,
11
+ UniformSubPriorParams,
12
+ UniformSubPriorSampler,
13
+ NarrowSldUniformSubPriorSampler,
14
+ ExpUniformSubPriorSampler,
15
+ SimpleMultilayerSampler,
16
+ SubpriorParametricSampler,
17
+ BasicParams,
18
+ ParametricModel,
19
+ MULTILAYER_MODELS,
20
+ SamplerStrategy,
21
+ BasicSamplerStrategy,
22
+ ConstrainedRoughnessSamplerStrategy,
23
+ ConstrainedRoughnessAndImgSldSamplerStrategy,
24
+ )
25
+ from reflectorch.data_generation.process_data import ProcessData, ProcessPipeline
26
+ from reflectorch.data_generation.q_generator import (
27
+ QGenerator,
28
+ ConstantAngle,
29
+ ConstantQ,
30
+ VariableQ,
31
+ EquidistantQ,
32
+ MaskedVariableQ,
33
+ )
34
+ from reflectorch.data_generation.noise import (
35
+ QNoiseGenerator,
36
+ IntensityNoiseGenerator,
37
+ QNormalNoiseGenerator,
38
+ QSystematicShiftGenerator,
39
+ PoissonNoiseGenerator,
40
+ MultiplicativeLogNormalNoiseGenerator,
41
+ ShiftNoise,
42
+ ScalingNoise,
43
+ BackgroundNoise,
44
+ BasicExpIntensityNoise,
45
+ GaussianExpIntensityNoise,
46
+ BasicQNoiseGenerator,
47
+ )
48
+ from reflectorch.data_generation.scale_curves import (
49
+ CurvesScaler,
50
+ LogAffineCurvesScaler,
51
+ MeanNormalizationCurvesScaler,
52
+ )
53
+ from reflectorch.data_generation.utils import (
54
+ get_reversed_params,
55
+ get_density_profiles,
56
+ uniform_sampler,
57
+ logdist_sampler,
58
+ triangular_sampler,
59
+ get_param_labels,
60
+ )
61
+
62
+ from reflectorch.data_generation.smearing import Smearing
63
+
64
+ from reflectorch.data_generation.reflectivity import reflectivity
65
+
66
+ from reflectorch.data_generation.likelihoods import (
67
+ LogLikelihood,
68
+ PoissonLogLikelihood,
69
+ )
70
+
71
+ __all__ = [
72
+ "Params",
73
+ "PriorSampler",
74
+ "BasicPriorSampler",
75
+ "BasicDataset",
76
+ "ProcessData",
77
+ "ProcessPipeline",
78
+ "QGenerator",
79
+ "ConstantQ",
80
+ "VariableQ",
81
+ "EquidistantQ",
82
+ "MaskedVariableQ",
83
+ "QNoiseGenerator",
84
+ "IntensityNoiseGenerator",
85
+ "MultiplicativeLogNormalNoiseGenerator",
86
+ "PoissonNoiseGenerator",
87
+ "CurvesScaler",
88
+ "ShiftNoise",
89
+ "ScalingNoise",
90
+ "BackgroundNoise",
91
+ "QNormalNoiseGenerator",
92
+ "QSystematicShiftGenerator",
93
+ "LogAffineCurvesScaler",
94
+ "MeanNormalizationCurvesScaler",
95
+ "get_reversed_params",
96
+ "get_density_profiles",
97
+ "logdist_sampler",
98
+ "uniform_sampler",
99
+ "triangular_sampler",
100
+ "get_param_labels",
101
+ "reflectivity",
102
+ "Smearing",
103
+ "SingleParamPrior",
104
+ "SimplePriorSampler",
105
+ "UniformParamPrior",
106
+ "GaussianParamPrior",
107
+ "TruncatedGaussianParamPrior",
108
+ "UniformSubPriorParams",
109
+ "UniformSubPriorSampler",
110
+ "NarrowSldUniformSubPriorSampler",
111
+ "ExpUniformSubPriorSampler",
112
+ "SimpleMultilayerSampler",
113
+ "BATCH_DATA_TYPE",
114
+ "LogLikelihood",
115
+ "PoissonLogLikelihood",
116
+ "BasicExpIntensityNoise",
117
+ "GaussianExpIntensityNoise",
118
+ "BasicQNoiseGenerator",
119
+ "ConstantAngle",
120
+ "SubpriorParametricSampler",
121
+ "BasicParams",
122
+ "ParametricModel",
123
+ "MULTILAYER_MODELS",
124
+ "SamplerStrategy",
125
+ "BasicSamplerStrategy",
126
+ "ConstrainedRoughnessSamplerStrategy",
127
+ "ConstrainedRoughnessAndImgSldSamplerStrategy",
128
+ ]
@@ -0,0 +1,216 @@
1
+ from typing import Dict, Union
2
+ import warnings
3
+
4
+ from torch import Tensor
5
+ import torch
6
+
7
+ from reflectorch.data_generation.priors import PriorSampler, BasicParams
8
+ from reflectorch.data_generation.noise import QNoiseGenerator, IntensityNoiseGenerator
9
+ from reflectorch.data_generation.q_generator import QGenerator
10
+ from reflectorch.data_generation.scale_curves import CurvesScaler, LogAffineCurvesScaler
11
+ from reflectorch.data_generation.smearing import Smearing
12
+
13
+ BATCH_DATA_TYPE = Dict[str, Union[Tensor, BasicParams]]
14
+
15
+
16
+ class BasicDataset(object):
17
+ """Reflectometry dataset. It generates the q positions, samples the thin film parameters from the prior,
18
+ simulates the reflectivity curves and applies noise to the curves.
19
+
20
+ Args:
21
+ q_generator (QGenerator): the momentum transfer (q) generator
22
+ prior_sampler (PriorSampler): the prior sampler
23
+ intensity_noise (IntensityNoiseGenerator, optional): the intensity noise generator. Defaults to None.
24
+ q_noise (QNoiseGenerator, optional): the q noise generator. Defaults to None.
25
+ curves_scaler (CurvesScaler, optional): the reflectivity curve scaler. Defaults to an instance of LogAffineCurvesScaler,
26
+ which scales the curves to the range [-1, 1], the minimum considered intensity being 1e-10.
27
+ calc_denoised_curves (bool, optional): whether to add the curves without noise to the dictionary. Defaults to False.
28
+ calc_nonsmeared_curves (bool, optional): whether to add the curves without smearing to the dictionary (only relevant when smearing is applied). Defaults to False.
29
+ add_noisy_curves (bool, optional): whether to add the noisy curves to the dictionary. Defaults to False.
30
+ smearing (Smearing, optional): curve smearing generator. Defaults to None.
31
+ """
32
+ def __init__(self,
33
+ q_generator: QGenerator,
34
+ prior_sampler: PriorSampler,
35
+ intensity_noise: IntensityNoiseGenerator = None,
36
+ q_noise: QNoiseGenerator = None,
37
+ curves_scaler: CurvesScaler = None,
38
+ calc_denoised_curves: bool = False,
39
+ calc_nonsmeared_curves: bool = False,
40
+ add_noisy_curves: bool = False,
41
+ smearing: Smearing = None,
42
+ ):
43
+ self.q_generator = q_generator
44
+ self.intensity_noise = intensity_noise
45
+ self.q_noise = q_noise
46
+ self.curves_scaler = curves_scaler or LogAffineCurvesScaler()
47
+ self.prior_sampler = prior_sampler
48
+ self.smearing = smearing
49
+ self.calc_denoised_curves = calc_denoised_curves
50
+ self.calc_nonsmeared_curves = calc_nonsmeared_curves
51
+ self.add_noisy_curves = add_noisy_curves
52
+
53
+ def update_batch_data(self, batch_data: BATCH_DATA_TYPE) -> None:
54
+ """implement in a subclass to edit batch_data dict inplace"""
55
+ pass
56
+
57
+ def _sample_from_prior(self, batch_size: int):
58
+ params: BasicParams = self.prior_sampler.sample(batch_size)
59
+ scaled_params: Tensor = self.prior_sampler.scale_params(params)
60
+ return params, scaled_params
61
+
62
+ def get_batch(self, batch_size: int) -> BATCH_DATA_TYPE:
63
+ """get a batch of data as a dictionary with keys ``params``, ``scaled_params``, ``q_values``, ``curves``, ``scaled_noisy_curves``
64
+
65
+ Args:
66
+ batch_size (int): the batch size
67
+ """
68
+ batch_data = {}
69
+
70
+ params, scaled_params = self._sample_from_prior(batch_size)
71
+
72
+ batch_data['params'] = params
73
+ batch_data['scaled_params'] = scaled_params
74
+
75
+ q_values: Tensor = self.q_generator.get_batch(batch_size, batch_data)
76
+
77
+ if self.q_noise:
78
+ batch_data['original_q_values'] = q_values
79
+ q_values = self.q_noise.apply(q_values, batch_data)
80
+
81
+ batch_data['q_values'] = q_values
82
+
83
+ refl_kwargs = {}
84
+
85
+ curves, q_resolutions, nonsmeared_curves = self._calc_curves(q_values, params, refl_kwargs)
86
+
87
+ if torch.is_tensor(q_resolutions):
88
+ batch_data['q_resolutions'] = q_resolutions
89
+
90
+ if torch.is_tensor(nonsmeared_curves):
91
+ batch_data['nonsmeared_curves'] = nonsmeared_curves
92
+
93
+ if self.calc_denoised_curves:
94
+ batch_data['curves'] = curves
95
+
96
+ noisy_curves = curves
97
+
98
+ if self.intensity_noise:
99
+ noisy_curves = self.intensity_noise(noisy_curves, batch_data)
100
+
101
+ if self.add_noisy_curves:
102
+ batch_data['noisy_curves'] = noisy_curves
103
+
104
+ scaled_noisy_curves = self.curves_scaler.scale(noisy_curves)
105
+ batch_data['scaled_noisy_curves'] = scaled_noisy_curves
106
+
107
+ is_finite = torch.all(torch.isfinite(scaled_noisy_curves), -1)
108
+
109
+ if not torch.all(is_finite).item():
110
+ infinite_indices = ~is_finite
111
+ to_recalculate = infinite_indices.sum().item()
112
+ warnings.warn(f'Infinite number appeared in the curve simulation! Recalculate {to_recalculate} curves.')
113
+ recalculated_batch_data = self.get_batch(to_recalculate)
114
+ _insert_batch_data(batch_data, recalculated_batch_data, infinite_indices)
115
+
116
+ is_finite = torch.all(torch.isfinite(batch_data['scaled_noisy_curves']), -1)
117
+ assert torch.all(is_finite).item()
118
+
119
+ self.update_batch_data(batch_data)
120
+
121
+ return batch_data
122
+
123
+ def _calc_curves(self, q_values: Tensor, params: BasicParams, refl_kwargs):
124
+ nonsmeared_curves = None
125
+
126
+ if self.smearing:
127
+ if self.calc_nonsmeared_curves:
128
+ nonsmeared_curves = params.reflectivity(q_values, **refl_kwargs)
129
+ curves, q_resolutions = self.smearing.get_curves(q_values, params, refl_kwargs)
130
+ else:
131
+ curves = params.reflectivity(q_values, **refl_kwargs)
132
+ q_resolutions = None
133
+
134
+ curves = curves.to(q_values)
135
+ return curves, q_resolutions, nonsmeared_curves
136
+
137
+
138
+ def _insert_batch_data(tgt_batch_data, add_batch_data, indices):
139
+ for key in tuple(tgt_batch_data.keys()):
140
+ value = tgt_batch_data[key]
141
+ if isinstance(value, BasicParams) or len(value.shape) == 2:
142
+ value[indices] = add_batch_data[key]
143
+ else:
144
+ warnings.warn(f'Ignore {key} while merging batch_data.')
145
+
146
+
147
+ if __name__ == '__main__':
148
+ from reflectorch.data_generation.q_generator import ConstantQ
149
+ from reflectorch.data_generation.priors import BasicPriorSampler, UniformSubPriorSampler
150
+ from reflectorch.data_generation.noise import BasicExpIntensityNoise
151
+ from reflectorch.data_generation.noise import BasicQNoiseGenerator
152
+ from reflectorch.utils import to_np
153
+ from time import perf_counter
154
+
155
+ q_generator = ConstantQ((0, 0.2, 65), device='cpu')
156
+ noise_gen = BasicExpIntensityNoise(
157
+ relative_errors=(0.05, 0.2),
158
+ # scale_range=(-1e-2, 1e-2),
159
+ logdist=True,
160
+ apply_shift=True,
161
+ )
162
+ q_noise_gen = BasicQNoiseGenerator(
163
+ shift_std=5e-4,
164
+ noise_std=(0, 1e-3),
165
+ )
166
+ prior_sampler = UniformSubPriorSampler(
167
+ thickness_range=(0, 250),
168
+ roughness_range=(0, 40),
169
+ sld_range=(0, 60),
170
+ num_layers=2,
171
+ device=torch.device('cpu'),
172
+ dtype=torch.float64,
173
+ smaller_roughnesses=True,
174
+ logdist=True,
175
+ relative_min_bound_width=5e-4,
176
+ )
177
+ smearing = Smearing(
178
+ sigma_range=(0.8e-3, 5e-3),
179
+ gauss_num=31,
180
+ share_smeared=0.5,
181
+ )
182
+
183
+ dataset = BasicDataset(
184
+ q_generator,
185
+ prior_sampler,
186
+ noise_gen,
187
+ q_noise=q_noise_gen,
188
+ smearing=smearing
189
+ )
190
+ start = perf_counter()
191
+ batch_data = dataset.get_batch(32)
192
+ print(f'Total time = {(perf_counter() - start):.3f} sec ')
193
+ print(batch_data['params'].roughnesses[:10])
194
+ print(batch_data['scaled_noisy_curves'].min().item())
195
+
196
+ scaled_noisy_curves = batch_data['scaled_noisy_curves']
197
+ scaled_curves = dataset.curves_scaler.scale(
198
+ batch_data['params'].reflectivity(q_generator.q)
199
+ )
200
+
201
+ try:
202
+ import matplotlib.pyplot as plt
203
+
204
+ for i in range(16):
205
+ plt.plot(
206
+ to_np(q_generator.q.squeeze().cpu().numpy()),
207
+ to_np(scaled_curves[i])
208
+ )
209
+ plt.plot(
210
+ to_np(q_generator.q.squeeze().cpu().numpy()),
211
+ to_np(scaled_noisy_curves[i])
212
+ )
213
+
214
+ plt.show()
215
+ except ImportError:
216
+ pass
@@ -0,0 +1,80 @@
1
+ from typing import Union, Tuple
2
+
3
+ import torch
4
+ from torch import Tensor
5
+
6
+ from reflectorch.data_generation import (
7
+ PriorSampler,
8
+ Params,
9
+ )
10
+
11
+
12
+ class LogLikelihood(object):
13
+ """Computes the gaussian log likelihood of the thin film parameters
14
+
15
+ Args:
16
+ q (Tensor): the q values
17
+ exp_curve (Tensor): the experimental reflectivity curve
18
+ priors (PriorSampler): the prior sampler
19
+ sigmas (Union[float, Tensor]): the sigmas (i.e. intensity error bars)
20
+ """
21
+ def __init__(self, q: Tensor, exp_curve: Tensor, priors: PriorSampler, sigmas: Union[float, Tensor]):
22
+ self.exp_curve = torch.atleast_2d(exp_curve)
23
+ self.priors: PriorSampler = priors
24
+ self.q = q
25
+ self.sigmas = sigmas
26
+ self.sigmas2 = self.sigmas ** 2
27
+
28
+ def calc_log_likelihood(self, curves: Tensor):
29
+ "computes the gaussian log likelihood"
30
+ log_probs = - (self.exp_curve - curves) ** 2 / self.sigmas2 / 2
31
+ return log_probs.sum(-1)
32
+
33
+ def __call__(self, params: Union[Params, Tensor], curves: Tensor = None):
34
+ if not isinstance(params, Params):
35
+ params: Params = self.priors.PARAM_CLS.from_tensor(params)
36
+ log_priors: Tensor = self.priors.log_prob(params)
37
+ indices: Tensor = torch.isfinite(log_priors)
38
+
39
+ if not indices.sum().item():
40
+ return log_priors
41
+
42
+ finite_params: Params = params[indices]
43
+
44
+ if curves is None:
45
+ curves: Tensor = finite_params.reflectivity(self.q)
46
+ else:
47
+ curves = curves[indices]
48
+
49
+ log_priors[indices] += self.calc_log_likelihood(curves)
50
+
51
+ return log_priors
52
+
53
+ calc_log_posterior = __call__
54
+
55
+ def get_importance_sampling_weights(
56
+ self, sampled_params: Params, nf_log_probs: Tensor, curves: Tensor = None
57
+ ) -> Tuple[Tensor, Tensor, Tensor]:
58
+ log_probs = self.calc_log_posterior(sampled_params, curves=curves)
59
+ log_weights = log_probs - nf_log_probs
60
+ log_weights = log_weights - log_weights.max()
61
+
62
+ weights = torch.exp(log_weights.to(torch.float64)).to(log_weights)
63
+ weights = weights / weights.sum()
64
+
65
+ return weights, log_weights, log_probs
66
+
67
+
68
+ class PoissonLogLikelihood(LogLikelihood):
69
+ """Computes the Poisson log likelihood of the thin film parameters
70
+
71
+ Args:
72
+ q (Tensor): the q values
73
+ exp_curve (Tensor): the experimental reflectivity curve
74
+ priors (PriorSampler): the prior sampler
75
+ sigmas (Union[float, Tensor]): the sigmas (i.e. intensity error bars)
76
+ """
77
+ def calc_log_likelihood(self, curves: Tensor):
78
+ """computes the Poisson log likelihood"""
79
+ log_probs = self.exp_curve / self.sigmas2 * (self.exp_curve * torch.log(curves) - curves)
80
+ return log_probs.sum(-1)