Source code for easyreflectometry.sample.collections.sample
from __future__ import annotations
__author__ = 'github.com/arm61'
from typing import List
from typing import Optional
from ..assemblies.base_assembly import BaseAssembly
from ..assemblies.multilayer import Multilayer
from ..assemblies.repeating_multilayer import RepeatingMultilayer
from ..assemblies.surfactant_layer import SurfactantLayer
from ..elements.layers.layer import Layer
from .base_collection import BaseCollection
# Needs to be a function, elements are added to the global_object.map
def DEFAULT_ELEMENTS(interface):
""":meta private:"""
return (
Multilayer(interface=interface),
Multilayer(interface=interface),
)
[docs]
class Sample(BaseCollection):
"""A sample is a collection of assemblies that represent the structure for which experimental measurements exist."""
[docs]
def __init__(
self,
*assemblies: Optional[List[BaseAssembly]],
name: str = 'EasySample',
interface=None,
unique_name: Optional[str] = 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`.
"""
if not assemblies:
if populate_if_none:
assemblies = DEFAULT_ELEMENTS(interface)
else:
assemblies = []
for assembly in assemblies:
if not issubclass(type(assembly), BaseAssembly):
raise ValueError('The elements must be an Assembly.')
super().__init__(name, interface, unique_name=unique_name, *assemblies, **kwargs)
self._disable_changes_to_outermost_layers()
[docs]
def add_assembly(self, assembly: Optional[BaseAssembly] = None):
"""Add an assembly to the sample.
:param assembly: Assembly to add.
"""
if assembly is None:
assembly = Multilayer(
name='EasyMultilayer added',
interface=self.interface,
)
self._enable_changes_to_outermost_layers()
self.append(assembly)
self._disable_changes_to_outermost_layers()
[docs]
def duplicate_assembly(self, index: int):
"""Add an assembly to the sample.
:param assembly: Assembly to add.
"""
self._enable_changes_to_outermost_layers()
to_be_duplicated = self[index]
if isinstance(to_be_duplicated, Multilayer):
duplicate = Multilayer.from_dict(to_be_duplicated.as_dict(skip=['unique_name']))
elif isinstance(to_be_duplicated, RepeatingMultilayer):
duplicate = RepeatingMultilayer.from_dict(to_be_duplicated.as_dict(skip=['unique_name']))
elif isinstance(to_be_duplicated, SurfactantLayer):
duplicate = SurfactantLayer.from_dict(to_be_duplicated.as_dict(skip=['unique_name']))
duplicate.name = duplicate.name + ' duplicate'
self.append(duplicate)
self._disable_changes_to_outermost_layers()
[docs]
def move_up(self, index: int):
"""Move the assembly at the given index up in the sample.
:param index: Index of the assembly to move up.
"""
self._enable_changes_to_outermost_layers()
super().move_up(index)
self._disable_changes_to_outermost_layers()
[docs]
def move_down(self, index: int):
"""Move the assembly at the given index down in the sample.
:param index: Index of the assembly to move down.
"""
self._enable_changes_to_outermost_layers()
super().move_down(index)
self._disable_changes_to_outermost_layers()
[docs]
def remove_assembly(self, index: int):
"""Remove the assembly at the given index from the sample.
:param index: Index of the assembly to remove.
"""
self._enable_changes_to_outermost_layers()
self.pop(index)
self._disable_changes_to_outermost_layers()
@property
def superphase(self) -> Layer:
"""The superphase of the sample."""
return self[0].front_layer
@property
def subphase(self) -> Layer:
"""The subphase of the sample."""
# This assembly only got one layer
if self[-1].back_layer is None:
return self[-1].front_layer
else:
return self[-1].back_layer
def _enable_changes_to_outermost_layers(self):
"""Allowed to change the outermost layers of the sample.
Superphase can change thickness and roughness.
Subphase can change thickness.
"""
if len(self) != 0:
self.superphase.thickness.enabled = True
self.superphase.roughness.enabled = True
self.subphase.thickness.enabled = True
def _disable_changes_to_outermost_layers(self):
"""No allowed to change the outermost layers of the sample.
Superphase can change thickness and roughness.
Subphase can change thickness.
"""
if len(self) != 0:
self.superphase.thickness.enabled = False
self.superphase.roughness.enabled = False
self.subphase.thickness.enabled = False
# Representation
[docs]
def as_dict(self, skip: Optional[List[str]] = 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`.
"""
this_dict = super().as_dict(skip=skip)
this_dict['populate_if_none'] = self.populate_if_none
return this_dict