Skip to content

Commit b191621

Browse files
committed
Merge branch 'develop' into 141-resolution-tutorial
2 parents d837cfe + b1504f1 commit b191621

32 files changed

+454
-184
lines changed

EasyReflectometry/calculators/bornagain/calculator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
__author__ = 'github.com/arm61'
22

33
import numpy as np
4-
from easyCore.Objects.Inferface import ItemContainer
4+
from easyscience.Objects.Inferface import ItemContainer
55

66
from EasyReflectometry.experiment import Model
77
from EasyReflectometry.sample import Layer

EasyReflectometry/calculators/bornagain/wrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
__author__ = 'github.com/arm61'
22

33
import bornagain as ba
4-
from easyCore import np
4+
import numpy as np
55
from scipy.stats import norm
66

77
from ..wrapper_base import WrapperBase

EasyReflectometry/calculators/calculator_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
from typing import Callable
55

66
import numpy as np
7-
from easyCore.Objects.core import ComponentSerializer
8-
from easyCore.Objects.Inferface import ItemContainer
7+
from easyscience.Objects.core import ComponentSerializer
8+
from easyscience.Objects.Inferface import ItemContainer
99

1010
from EasyReflectometry.experiment import Model
1111
from EasyReflectometry.sample import BaseAssembly

EasyReflectometry/calculators/factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__author__ = 'github.com/wardsimon'
22

3-
from easyCore.Objects.Inferface import InterfaceFactoryTemplate
3+
from easyscience.Objects.Inferface import InterfaceFactoryTemplate
44

55
from EasyReflectometry.calculators import CalculatorBase
66

EasyReflectometry/calculators/refl1d/wrapper.py

Lines changed: 112 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22

33
from typing import Tuple
44

5-
from easyCore import np
5+
import numpy as np
66
from refl1d import model
77
from refl1d import names
88

99
from EasyReflectometry.experiment.resolution_functions import is_constant_resolution_function
1010

1111
from ..wrapper_base import WrapperBase
1212

13-
PADDING_RANGE = 3.5
14-
UPSCALE_FACTOR = 21
13+
RESOLUTION_PADDING = 3.5
14+
OVERSAMPLING_FACTOR = 21
1515
MAGNETISM = False
16+
ALL_POLARIZATIONS = False
1617

1718

1819
class Refl1dWrapper(WrapperBase):
@@ -30,7 +31,7 @@ def create_layer(self, name: str):
3031
3132
:param name: The name of the layer
3233
"""
33-
if MAGNETISM:
34+
if MAGNETISM: # A test with hardcoded magnetism in all layers
3435
magnetism = names.Magnetism(rhoM=0.2, thetaM=270)
3536
else:
3637
magnetism = None
@@ -47,17 +48,6 @@ def create_item(self, name: str):
4748
)
4849
del self.storage['item'][name].stack[0]
4950

50-
def update_item(self, name: str, **kwargs):
51-
"""
52-
Update a layer.
53-
54-
:param name: The item name
55-
"""
56-
item = self.storage['item'][name]
57-
for key in kwargs.keys():
58-
ii = getattr(item, key)
59-
setattr(ii, 'value', kwargs[key])
60-
6151
def get_item_value(self, name: str, key: str) -> float:
6252
"""
6353
A function to get a given item value
@@ -155,61 +145,43 @@ def calculate(self, q_array: np.ndarray, model_name: str) -> np.ndarray:
155145
:param model_name: the model name
156146
:return: reflectivity calculated at q
157147
"""
158-
structure = model.Stack()
159-
# -1 to reverse the order
160-
for i in self.storage['model'][model_name]['items'][::-1]:
161-
if i.repeat.value == 1:
162-
# -1 to reverse the order
163-
for j in range(len(i.stack))[::-1]:
164-
structure |= i.stack[j]
165-
else:
166-
stack = model.Stack()
167-
# -1 to reverse the order
168-
for j in range(len(i.stack))[::-1]:
169-
stack |= i.stack[j]
170-
structure |= model.Repeat(stack, repeat=i.repeat.value)
171-
172-
argmin = np.argmin(q_array)
173-
argmax = np.argmax(q_array)
174-
dq_vector = self._resolution_function(q_array)
148+
sample = _build_sample(self.storage, model_name)
149+
dq_array = self._resolution_function(q_array)
175150

176151
if is_constant_resolution_function(self._resolution_function):
177152
# Get percentage of Q and change from sigma to FWHM
178-
dq_vector = dq_vector * q_array / 100 / (2 * np.sqrt(2 * np.log(2)))
179-
180-
if MAGNETISM:
181-
xs = []
182-
for _ in range(4):
183-
q = names.QProbe(
184-
Q=q_array,
185-
dQ=dq_vector,
186-
intensity=self.storage['model'][model_name]['scale'],
187-
background=self.storage['model'][model_name]['bkg'],
188-
)
189-
q.calc_Qo = np.linspace(
190-
q_array[argmin] - PADDING_RANGE * dq_vector[argmin],
191-
q_array[argmax] + PADDING_RANGE * dq_vector[argmax],
192-
UPSCALE_FACTOR * len(q_array),
193-
)
194-
xs.append(q)
195-
probe = names.PolarizedQProbe(xs=xs, name='polarized')
196-
197-
R = names.Experiment(probe=probe, sample=structure).reflectivity()[1]
198-
else:
199-
q = names.QProbe(
200-
Q=q_array,
201-
dQ=dq_vector,
202-
intensity=self.storage['model'][model_name]['scale'],
203-
background=self.storage['model'][model_name]['bkg'],
153+
dq_array = dq_array * q_array / 100 / (2 * np.sqrt(2 * np.log(2)))
154+
155+
if not MAGNETISM:
156+
probe = _get_probe(
157+
q_array=q_array,
158+
dq_array=dq_array,
159+
model_name=model_name,
160+
storage=self.storage,
161+
oversampling_factor=OVERSAMPLING_FACTOR,
204162
)
205-
q.calc_Qo = np.linspace(
206-
q_array[argmin] - PADDING_RANGE * dq_vector[argmin],
207-
q_array[argmax] + PADDING_RANGE * dq_vector[argmax],
208-
UPSCALE_FACTOR * len(q_array),
163+
_, reflectivity = names.Experiment(probe=probe, sample=sample).reflectivity()
164+
else:
165+
polarized_probe = _get_polarized_probe(
166+
q_array=q_array,
167+
dq_array=dq_array,
168+
model_name=model_name,
169+
storage=self.storage,
170+
oversampling_factor=OVERSAMPLING_FACTOR,
171+
all_polarizations=ALL_POLARIZATIONS,
209172
)
210-
R = names.Experiment(probe=q, sample=structure).reflectivity()[1]
173+
polarized_reflectivity = names.Experiment(probe=polarized_probe, sample=sample).reflectivity()
174+
175+
if ALL_POLARIZATIONS:
176+
raise NotImplementedError('Polarized reflectivity not yet implemented')
177+
# _, reflectivity_pp = polarized_reflectivity[0]
178+
# _, reflectivity_pm = polarized_reflectivity[1]
179+
# _, reflectivity_mp = polarized_reflectivity[2]
180+
# _, reflectivity_mm = polarized_reflectivity[3]
181+
else:
182+
_, reflectivity = polarized_reflectivity[0]
211183

212-
return R
184+
return reflectivity
213185

214186
def sld_profile(self, model_name: str) -> Tuple[np.ndarray, np.ndarray]:
215187
"""
@@ -218,26 +190,82 @@ def sld_profile(self, model_name: str) -> Tuple[np.ndarray, np.ndarray]:
218190
:param model_name: the model name
219191
:return: z and sld(z)
220192
"""
221-
structure = model.Stack()
222-
# -1 to reverse the order
223-
for i in self.storage['model'][model_name]['items'][::-1]:
224-
if i.repeat.value == 1:
225-
# -1 to reverse the order
226-
for j in range(len(i.stack))[::-1]:
227-
structure |= i.stack[j]
228-
else:
229-
stack = model.Stack()
230-
# -1 to reverse the order
231-
for j in range(len(i.stack))[::-1]:
232-
stack |= i.stack[j]
233-
structure |= model.Repeat(stack, repeat=i.repeat.value)
234-
235-
q = names.QProbe(
236-
np.linspace(0.001, 0.3, 10),
237-
np.linspace(0.001, 0.3, 10),
238-
intensity=self.storage['model'][model_name]['scale'],
239-
background=self.storage['model'][model_name]['bkg'],
193+
sample = _build_sample(self.storage, model_name)
194+
probe = _get_probe(
195+
q_array=np.array([1]), # dummy value
196+
dq_array=np.array([1]), # dummy value
197+
model_name=model_name,
198+
storage=self.storage,
240199
)
241-
z, sld, _ = names.Experiment(probe=q, sample=structure).smooth_profile()
200+
z, sld, _ = names.Experiment(probe=probe, sample=sample).smooth_profile()
242201
# -1 to reverse the order
243202
return z, sld[::-1]
203+
204+
205+
def _get_oversampling_q(q_array: np.ndarray, dq_array: np.ndarray, oversampling_factor: int) -> np.ndarray:
206+
argmin = np.argmin(q_array) # index of the smallest q element
207+
argmax = np.argmax(q_array) # index of the largest q element
208+
return np.linspace(
209+
q_array[argmin] - RESOLUTION_PADDING * dq_array[argmin], # dq element at the smallest q index
210+
q_array[argmax] + RESOLUTION_PADDING * dq_array[argmax], # dq element at the largest q index
211+
oversampling_factor * len(q_array),
212+
)
213+
214+
215+
def _get_probe(
216+
q_array: np.ndarray,
217+
dq_array: np.ndarray,
218+
model_name: str,
219+
storage: dict,
220+
oversampling_factor: int = 1,
221+
) -> names.QProbe:
222+
probe = names.QProbe(
223+
Q=q_array,
224+
dQ=dq_array,
225+
intensity=storage['model'][model_name]['scale'],
226+
background=storage['model'][model_name]['bkg'],
227+
)
228+
if oversampling_factor > 1:
229+
probe.calc_Qo = _get_oversampling_q(q_array, dq_array, oversampling_factor)
230+
return probe
231+
232+
233+
def _get_polarized_probe(
234+
q_array: np.ndarray,
235+
dq_array: np.ndarray,
236+
model_name: str,
237+
storage: dict,
238+
oversampling_factor: int = 1,
239+
all_polarizations: bool = False,
240+
) -> names.QProbe:
241+
four_probes = []
242+
for i in range(4):
243+
if i == 0 or all_polarizations:
244+
probe = _get_probe(
245+
q_array=q_array,
246+
dq_array=dq_array,
247+
model_name=model_name,
248+
storage=storage,
249+
oversampling_factor=oversampling_factor,
250+
)
251+
else:
252+
probe = None
253+
four_probes.append(probe)
254+
return names.PolarizedQProbe(xs=four_probes, name='polarized')
255+
256+
257+
def _build_sample(storage: dict, model_name: str) -> model.Stack:
258+
sample = model.Stack()
259+
# -1 to reverse the order
260+
for i in storage['model'][model_name]['items'][::-1]:
261+
if i.repeat.value == 1:
262+
# -1 to reverse the order
263+
for j in range(len(i.stack))[::-1]:
264+
sample |= i.stack[j]
265+
else:
266+
stack = model.Stack()
267+
# -1 to reverse the order
268+
for j in range(len(i.stack))[::-1]:
269+
stack |= i.stack[j]
270+
sample |= model.Repeat(stack, repeat=i.repeat.value)
271+
return sample

EasyReflectometry/calculators/refnx/calculator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ class Refnx(CalculatorBase):
2828
_model_link = {
2929
'scale': 'scale',
3030
'background': 'bkg',
31-
'resolution': 'dq',
3231
}
3332

3433
def __init__(self):

EasyReflectometry/calculators/refnx/wrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from typing import Tuple
44

5-
from easyCore import np
5+
import numpy as np
66
from refnx import reflect
77

88
from EasyReflectometry.experiment.resolution_functions import is_constant_resolution_function

EasyReflectometry/experiment/model.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
from typing import Callable
77
from typing import Union
88

9+
import numpy as np
910
import yaml
10-
from easyCore import np
11-
from easyCore.Objects.ObjectClasses import BaseObj
12-
from easyCore.Objects.ObjectClasses import Parameter
11+
from easyscience.Objects.ObjectClasses import BaseObj
12+
from easyscience.Objects.ObjectClasses import Parameter
1313

1414
from EasyReflectometry.experiment.resolution_functions import is_constant_resolution_function
1515
from EasyReflectometry.parameter_utils import get_as_parameter
@@ -217,7 +217,7 @@ def from_dict(cls, data: dict) -> Model:
217217
model = super().from_dict(data)
218218

219219
# Ensure that the sample is also converted
220-
# TODO Should probably be handled in EasyCore
220+
# TODO Should probably be handled in easyscience
221221
model.sample = model.sample.__class__.from_dict(data['sample'])
222222

223223
return model

EasyReflectometry/fitting.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import numpy as np
44
import scipp as sc
5-
from easyCore.Fitting.Fitting import MultiFitter as easyFitter
5+
from easyscience.Fitting.Fitting import MultiFitter as easyFitter
66

77
from EasyReflectometry.experiment import Model
88

99

1010
class Fitter:
1111
def __init__(self, *args: Model):
12-
r"""A convinence class for the :py:class:`easyCore.Fitting.Fitting`
12+
r"""A convinence class for the :py:class:`easyscience.Fitting.Fitting`
1313
which will populate the :py:class:`sc.DataGroup` appropriately
1414
after the fitting is performed.
1515

EasyReflectometry/parameter_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from numbers import Number
33
from typing import Union
44

5-
from easyCore.Objects.ObjectClasses import Parameter
5+
from easyscience.Objects.ObjectClasses import Parameter
66

77

88
def get_as_parameter(name: str, value: Union[Parameter, Number, None], default_dict: dict) -> Parameter:

EasyReflectometry/sample/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,24 @@
88
from .elements.layers.layer_collection import LayerCollection
99
from .elements.materials.material import Material
1010
from .elements.materials.material_collection import MaterialCollection
11+
from .elements.materials.material_density import MaterialDensity
1112
from .elements.materials.material_mixture import MaterialMixture
1213
from .elements.materials.material_solvated import MaterialSolvated
1314
from .sample import Sample
1415

1516
__all__ = (
1617
BaseAssembly,
1718
GradientLayer,
18-
Multilayer,
19-
RepeatingMultilayer,
20-
SurfactantLayer,
2119
Layer,
2220
LayerAreaPerMolecule,
2321
LayerCollection,
2422
Material,
25-
MaterialMixture,
2623
MaterialCollection,
24+
MaterialDensity,
25+
MaterialMixture,
2726
MaterialSolvated,
27+
Multilayer,
28+
RepeatingMultilayer,
2829
Sample,
30+
SurfactantLayer,
2931
)

EasyReflectometry/sample/assemblies/base_assembly.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any
22
from typing import Optional
33

4-
from easyCore.Fitting.Constraints import ObjConstraint
4+
from easyscience.Fitting.Constraints import ObjConstraint
55

66
from ..base_core import BaseCore
77
from ..elements.layers.layer import Layer
@@ -32,7 +32,7 @@ def __init__(
3232
):
3333
super().__init__(name=name, interface=interface, **layers)
3434

35-
# Type is needed when fitting in EasyCore
35+
# Type is needed when fitting in easyscience
3636
self._type = type
3737
self._roughness_constraints_setup = False
3838
self._thickness_constraints_setup = False

0 commit comments

Comments
 (0)