Source code for easyreflectometry.sample.sample
from __future__ import annotations
__author__ = 'github.com/arm61'
from typing import Union
from easyscience.Objects.Groups import BaseCollection
from easyreflectometry.parameter_utils import yaml_dump
from .assemblies.base_assembly import BaseAssembly
from .assemblies.multilayer import Multilayer
from .elements.layers.layer import Layer
NR_DEFAULT_LAYERS = 2
[docs]
class Sample(BaseCollection):
"""Collection of assemblies that represent the sample for which experimental measurements exist."""
[docs]
def __init__(
self,
*list_layer_like: list[Union[Layer, BaseAssembly]],
name: str = 'EasySample',
interface=None,
populate_if_none: bool = True,
**kwargs,
):
"""Constructor.
:param args: The assemblies in the sample.
:param name: Name of the sample, defaults to 'EasySample'.
:param interface: Calculator interface, defaults to `None`.
"""
new_items = []
if not list_layer_like:
if populate_if_none:
list_layer_like = [Multilayer(interface=interface) for _ in range(NR_DEFAULT_LAYERS)]
else:
list_layer_like = []
# Needed to ensure an empty list is created when saving and instatiating the object as_dict -> from_dict
# Else collisions might occur in global_object.map
self.populate_if_none = False
for layer_like in list_layer_like:
if issubclass(type(layer_like), Layer):
new_items.append(Multilayer(layer_like, name=layer_like.name))
elif issubclass(type(layer_like), BaseAssembly):
new_items.append(layer_like)
else:
raise ValueError('The items must be either a Layer or an Assembly.')
super().__init__(name, *new_items, **kwargs)
self.interface = interface
# Representation
@property
def _dict_repr(self) -> dict:
"""A simplified dict representation."""
return {self.name: [i._dict_repr for i in self]}
def __repr__(self) -> str:
"""String representation of the sample."""
return yaml_dump(self._dict_repr)
[docs]
def as_dict(self, skip: list = None) -> dict:
"""Produces a cleaned dict using a custom as_dict method to skip necessary things.
The resulting dict matches the parameters in __init__
:param skip: List of keys to skip, defaults to `None`.
"""
if skip is None:
skip = []
this_dict = super().as_dict(skip=skip)
for i, layer in enumerate(self.data):
this_dict['data'][i] = layer.as_dict(skip=skip)
this_dict['populate_if_none'] = self.populate_if_none
return this_dict