Skip to content

Commit dc2ea11

Browse files
authored
191 adjust model and modelcollection to hold functionality from app (#192)
* from materials collection to base collection * added color to Model * renaming up and down to be consistent with other code * adjusted collections * placeholder for calculated data * ready to expose data * datastore and tests * added functionality * code cleaning * explicit clean global obejct for surfactant tests * unique name in surfactant and layer area per molecule * code clean * code cleaning * code cleaning * pr response * pr response and tests * pr response
1 parent 0601013 commit dc2ea11

File tree

19 files changed

+362
-155
lines changed

19 files changed

+362
-155
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
from .data_store import DataSet1D
12
from .data_store import ProjectData
23
from .measurement import load
34

45
__all__ = [
56
load,
67
ProjectData,
8+
DataSet1D,
79
]

src/easyreflectometry/data/data_store.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ def __init__(
8181
y_label: str = 'y',
8282
):
8383
self._model = model
84-
self._model.background = np.min(y)
84+
if y is not None and model is not None:
85+
self._model.background = np.min(y)
8586

8687
if x is None:
8788
x = np.array([])
@@ -92,6 +93,9 @@ def __init__(
9293
if xe is None:
9394
xe = np.zeros_like(x)
9495

96+
if len(x) != len(y):
97+
raise ValueError('x and y must be the same length')
98+
9599
self.name = name
96100
if not isinstance(x, np.ndarray):
97101
x = np.array(x)
@@ -125,5 +129,8 @@ def is_experiment(self) -> bool:
125129
def is_simulation(self) -> bool:
126130
return self._model is None
127131

132+
def data_points(self) -> int:
133+
return zip(self.x, self.y)
134+
128135
def __repr__(self) -> str:
129136
return "1D DataStore of '{:s}' Vs '{:s}' with {} data points".format(self.x_label, self.y_label, len(self.x))

src/easyreflectometry/model/model.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def __init__(
6060
background: Union[Parameter, Number, None] = None,
6161
resolution_function: Union[ResolutionFunction, None] = None,
6262
name: str = 'EasyModel',
63+
color: str = 'black',
6364
unique_name: Optional[str] = None,
6465
interface=None,
6566
):
@@ -81,6 +82,7 @@ def __init__(
8182

8283
scale = get_as_parameter('scale', scale, DEFAULTS)
8384
background = get_as_parameter('background', background, DEFAULTS)
85+
self.color = color
8486

8587
super().__init__(
8688
name=name,
@@ -173,6 +175,7 @@ def _dict_repr(self) -> dict[str, dict[str, str]]:
173175
'scale': float(self.scale.value),
174176
'background': float(self.background.value),
175177
'resolution': resolution,
178+
'color': self.color,
176179
'sample': self.sample._dict_repr,
177180
}
178181
}

src/easyreflectometry/model/model_collection.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
from __future__ import annotations
22

3-
__author__ = 'github.com/arm61'
4-
53
from typing import List
4+
from typing import Optional
65
from typing import Tuple
76

87
from easyreflectometry.sample.collections.base_collection import BaseCollection
@@ -35,21 +34,24 @@ def __init__(
3534

3635
super().__init__(name, interface, *models, **kwargs)
3736

38-
def add_model(self, new_model: Model):
39-
"""
40-
Add a model to the models.
37+
def add_model(self, model: Optional[Model] = None):
38+
"""Add a model to the collection.
4139
42-
:param new_model: New model to be added.
40+
:param model: Model to add.
4341
"""
44-
self.append(new_model)
42+
if model is None:
43+
model = Model(name='Model new', interface=self.interface)
44+
self.append(model)
4545

46-
def remove_model(self, index: int):
47-
"""
48-
Remove an model from the models.
46+
def duplicate_model(self, index: int):
47+
"""Duplicate a model in the collection.
4948
50-
:param index: Index of the model to remove
49+
:param index: Model to duplicate.
5150
"""
52-
self.pop(index)
51+
to_be_duplicated = self[index]
52+
duplicate = Model.from_dict(to_be_duplicated.as_dict(skip=['unique_name']))
53+
duplicate.name = duplicate.name + ' duplicate'
54+
self.append(duplicate)
5355

5456
def as_dict(self, skip: List[str] | None = None) -> dict:
5557
this_dict = super().as_dict(skip=skip)
@@ -62,7 +64,6 @@ def from_dict(cls, this_dict: dict) -> ModelCollection:
6264
Create an instance of a collection from a dictionary.
6365
6466
:param data: The dictionary for the collection
65-
:return: An instance of the collection
6667
"""
6768
collection_dict = this_dict.copy()
6869
# We neeed to call from_dict on the base class to get the models

src/easyreflectometry/project.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
from typing import Optional
77
from typing import Union
88

9+
import numpy as np
910
from easyscience import global_object
1011
from easyscience.fitting import AvailableMinimizers
1112

12-
from easyreflectometry.data.data_store import DataSet1D
13+
from easyreflectometry.data import DataSet1D
1314
from easyreflectometry.model import Model
1415
from easyreflectometry.model import ModelCollection
1516
from easyreflectometry.sample import Layer
@@ -18,6 +19,29 @@
1819
from easyreflectometry.sample import Sample
1920
from easyreflectometry.sample.collections.base_collection import BaseCollection
2021

22+
MODELS_SAMPLE_DATA = [
23+
DataSet1D(
24+
name='Sample Data 0',
25+
x=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
26+
y=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
27+
)
28+
]
29+
MODELS_MODEL_DATA = [
30+
DataSet1D(
31+
name='Model Data 0',
32+
x=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
33+
y=np.array([1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5]),
34+
)
35+
]
36+
EXPERIMENTAL_DATA = [
37+
DataSet1D(
38+
name='Example Data 0',
39+
x=np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
40+
y=np.array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]),
41+
ye=np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]),
42+
)
43+
]
44+
2145

2246
class Project:
2347
def __init__(self):
@@ -95,6 +119,15 @@ def experiments(self, experiments: List[DataSet1D]) -> None:
95119
def path_json(self):
96120
return self.path / 'project.json'
97121

122+
def sample_data_for_model_at_index(self, index: int = 0) -> DataSet1D:
123+
return MODELS_SAMPLE_DATA[index]
124+
125+
def model_data_for_model_at_index(self, index: int = 0) -> DataSet1D:
126+
return MODELS_MODEL_DATA[index]
127+
128+
def experimental_data_for_model_at_index(self, index: int = 0) -> DataSet1D:
129+
return EXPERIMENTAL_DATA[index]
130+
98131
def default_model(self):
99132
self._replace_collection(MaterialCollection(), self._materials)
100133

src/easyreflectometry/sample/assemblies/surfactant_layer.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Optional
44

5+
from easyscience import global_object
56
from easyscience.Constraints import ObjConstraint
67
from easyscience.Objects.new_variable import Parameter
78

@@ -44,8 +45,17 @@ def __init__(
4445
:param conformal_roughness: Constrain the roughness to be the same for both layers, defaults to `False`.
4546
:param interface: Calculator interface, defaults to `None`.
4647
"""
48+
if unique_name is None:
49+
unique_name = global_object.generate_unique_name(self.__class__.__name__)
50+
4751
if tail_layer is None:
48-
air = Material(0, 0, 'Air')
52+
air = Material(
53+
sld=0,
54+
isld=0,
55+
name='Air',
56+
unique_name=unique_name + '_MaterialTail',
57+
interface=interface,
58+
)
4959
tail_layer = LayerAreaPerMolecule(
5060
molecular_formula='C32D64',
5161
thickness=16,
@@ -54,9 +64,17 @@ def __init__(
5464
area_per_molecule=48.2,
5565
roughness=3,
5666
name='DPPC Tail',
67+
unique_name=unique_name + '_LayerAreaPerMoleculeTail',
68+
interface=interface,
5769
)
5870
if head_layer is None:
59-
d2o = Material(6.36, 0, 'D2O')
71+
d2o = Material(
72+
sld=6.36,
73+
isld=0,
74+
name='D2O',
75+
unique_name=unique_name + '_MaterialHead',
76+
interface=interface,
77+
)
6078
head_layer = LayerAreaPerMolecule(
6179
molecular_formula='C10H18NO8P',
6280
thickness=10.0,
@@ -65,8 +83,16 @@ def __init__(
6583
area_per_molecule=48.2,
6684
roughness=3.0,
6785
name='DPPC Head',
86+
unique_name=unique_name + '_LayerAreaPerMoleculeHead',
87+
interface=interface,
6888
)
69-
surfactant = LayerCollection(tail_layer, head_layer, name=name)
89+
surfactant = LayerCollection(
90+
tail_layer,
91+
head_layer,
92+
name='Layers',
93+
unique_name=unique_name + '_LayerCollection',
94+
interface=interface,
95+
)
7096
super().__init__(
7197
name=name,
7298
unique_name=unique_name,

src/easyreflectometry/sample/collections/base_collection.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,32 @@ def names(self) -> list:
3737
"""
3838
return [i.name for i in self]
3939

40+
def move_up(self, index: int):
41+
"""Move the element at the given index up in the collection.
42+
43+
:param index: Index of the element to move up.
44+
"""
45+
if index == 0:
46+
return
47+
self.insert(index - 1, self.pop(index))
48+
49+
def move_down(self, index: int):
50+
"""Move the element at the given index down in the collection.
51+
52+
:param index: Index of the element to move down.
53+
"""
54+
if index == len(self) - 1:
55+
return
56+
self.insert(index + 1, self.pop(index))
57+
58+
def remove(self, index: int):
59+
"""
60+
Remove an element from the elements.
61+
62+
:param index: Index of the element to remove
63+
"""
64+
self.pop(index)
65+
4066
@property
4167
def _dict_repr(self) -> dict:
4268
"""

src/easyreflectometry/sample/collections/layer_collection.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,25 @@ def __init__(
2020
layers = []
2121

2222
super().__init__(name, interface, unique_name=unique_name, *layers, **kwargs)
23+
24+
def add_layer(self, layer: Optional[Layer] = None):
25+
"""Add a layer to the collection.
26+
27+
:param layer: Layer to add.
28+
"""
29+
if layer is None:
30+
layer = Layer(
31+
name='New EasyLayer',
32+
interface=self.interface,
33+
)
34+
self.append(layer)
35+
36+
def duplicate_layer(self, index: int):
37+
"""Duplicate a layer in the collection.
38+
39+
:param layer: Assembly to add.
40+
"""
41+
to_be_duplicated = self[index]
42+
duplicate = Layer.from_dict(to_be_duplicated.as_dict(skip=['unique_name']))
43+
duplicate.name = duplicate.name + ' duplicate'
44+
self.append(duplicate)

src/easyreflectometry/sample/collections/material_collection.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def add_material(self, material: Optional[Material] = None):
4545
:param material: Material to add.
4646
"""
4747
if material is None:
48-
material = Material(sld=2.074, isld=0.000, name='Si new', interface=self.interface)
48+
material = Material(sld=2.074, isld=0.000, name='Si new')
49+
material.interface = self.interface
4950
self.append(material)
5051

5152
def duplicate_material(self, index: int):
@@ -57,28 +58,3 @@ def duplicate_material(self, index: int):
5758
duplicate = Material.from_dict(to_be_duplicated.as_dict(skip=['unique_name']))
5859
duplicate.name = duplicate.name + ' duplicate'
5960
self.append(duplicate)
60-
61-
def move_material_up(self, index: int):
62-
"""Move the material at the given index up in the collection.
63-
64-
:param index: Index of the material to move up.
65-
"""
66-
if index == 0:
67-
return
68-
self.insert(index - 1, self.pop(index))
69-
70-
def move_material_down(self, index: int):
71-
"""Move the material at the given index down in the collection.
72-
73-
:param index: Index of the material to move down.
74-
"""
75-
if index == len(self) - 1:
76-
return
77-
self.insert(index + 1, self.pop(index))
78-
79-
def remove_material(self, index: int):
80-
"""Remove the material at the given index from the collection.
81-
82-
:param index: Index of the material to remove.
83-
"""
84-
self.pop(index)

src/easyreflectometry/sample/collections/sample.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ def add_assembly(self, assembly: Optional[BaseAssembly] = None):
5656
:param assembly: Assembly to add.
5757
"""
5858
if assembly is None:
59-
assembly = Multilayer(name='New EasyMultilayer', interface=self.interface)
59+
assembly = Multilayer(
60+
name='New EasyMultilayer',
61+
interface=self.interface,
62+
)
6063
self._enable_changes_to_outermost_layers()
6164
self.append(assembly)
6265
self._disable_changes_to_outermost_layers()
@@ -78,26 +81,22 @@ def duplicate_assembly(self, index: int):
7881
self.append(duplicate)
7982
self._disable_changes_to_outermost_layers()
8083

81-
def move_assembly_up(self, index: int):
84+
def move_up(self, index: int):
8285
"""Move the assembly at the given index up in the sample.
8386
8487
:param index: Index of the assembly to move up.
8588
"""
86-
if index == 0:
87-
return
8889
self._enable_changes_to_outermost_layers()
89-
self.insert(index - 1, self.pop(index))
90+
super().move_up(index)
9091
self._disable_changes_to_outermost_layers()
9192

92-
def move_assembly_down(self, index: int):
93+
def move_down(self, index: int):
9394
"""Move the assembly at the given index down in the sample.
9495
9596
:param index: Index of the assembly to move down.
9697
"""
97-
if index == len(self) - 1:
98-
return
9998
self._enable_changes_to_outermost_layers()
100-
self.insert(index + 1, self.pop(index))
99+
super().move_down(index)
101100
self._disable_changes_to_outermost_layers()
102101

103102
def remove_assembly(self, index: int):

0 commit comments

Comments
 (0)