Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0a8cc51
Add potential resolver by arbitrary string and allow space in stack d…
aglavic May 12, 2025
ec5b5a3
Separate the basic building blocks in own module and add first comple…
aglavic Jun 2, 2025
3af56a1
Add E704, multiple statements per line, to flake8 exceptions as it is…
aglavic Jun 2, 2025
5f69496
Replace uniton of list with union type buidup manually
aglavic Jun 2, 2025
75ddad2
Replace type OR by Union for python<3.10
aglavic Jun 2, 2025
33e1aa0
minor
aglavic Jun 2, 2025
569f7c3
compatibility to pre-Protocol python
aglavic Jun 2, 2025
b445a4f
Change protocol to ABC, implement resolution based on sub_stack_class…
aglavic Jun 3, 2025
dae0688
Get rid of SUBSTACK_TYPES list and build type union dynamically from …
aglavic Jun 3, 2025
62a69c2
Introduce global slice_resolution parameter
aglavic Jun 4, 2025
6318616
Introduce global slice_resolution parameter
aglavic Jun 4, 2025
3821ac3
Fix Literal import for backport
aglavic Jun 4, 2025
4f51687
Skip a test that fails for backport python, define allowed names for …
aglavic Jun 4, 2025
2d6b7f7
minor
aglavic Jun 4, 2025
726fc56
fix test case wrong case
aglavic Jun 4, 2025
e069159
Allow unit conversion with ORSO default capital Angstrom, sort sub_st…
aglavic Jun 5, 2025
0b8d15a
Add LipidLeaflet class and change example 4 to use it
aglavic Jun 5, 2025
8c8d190
Extent with default solvent, possible SubStack environment material a…
aglavic Jun 6, 2025
141091f
add option to resolve a sample just to block elements to flatten the …
aglavic Jun 6, 2025
2414f20
fix one testcase
aglavic Jun 6, 2025
fc2390c
expand examples and model language tests to fully cover model_buildin…
aglavic Jun 6, 2025
ba2df9a
expand sample model tests to cover most cases
aglavic Jun 6, 2025
c96a45a
update schema
aglavic Jun 6, 2025
33924ad
Fix some resolution bugs within SubStack
aglavic Jun 11, 2025
c253d8e
Update version number
aglavic Jun 18, 2025
73875fe
remove LipidLeaflet to commit other changes before parameterization h…
aglavic Jun 27, 2025
f55dddc
update unit tests to work without LipidLeaflet
aglavic Jun 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ jobs:

- name: Lint
run: |
flake8 --max-line-length=120 --ignore=F401,W503,E203 --count --show-source --statistics orsopy
flake8 --max-line-length=120 --ignore=F401,W503,E203,E704 --count --show-source --statistics orsopy
34 changes: 34 additions & 0 deletions examples/sample_model_complex.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
sample:
model:
origin: ORSO test complex resolution
stack: air | 10 ( Si 70 | Fe 70 ) | ss1 | (ss1 in Fe) | ((ss2 | ss3) | 3 (ss1 | ss2) ) | ((((ss4 200))) in air ) | Si
sub_stacks:
ss1:
repetitions: 2
stack: ss2 | ss3
ss2:
repetitions: 1
sequence:
- {thickness: 2.0, material: Si}
- {thickness: 5.0, material: Ti}
ss3:
repetitions: 1
sequence:
- {thickness: 3.0, material: copper}
- {thickness: 1.0, material: mixin}
ss4:
sub_stack_class: FunctionTwoElements
material1: Ni
material2: Ti
function: x
materials:
copper:
formula: Cu
Fe:
formula: Fe[57]
mass_density: 7.0
composits:
mixin:
composition:
copper: 0.5
Si: 0.5
23 changes: 23 additions & 0 deletions examples/sample_model_example_4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
sample:
model:
origin: refnx example leaflet parameters
stack: Si | ( LL | rLL ) in D2O | 2 ( LL | rLL ) | water
sub_stacks:
LL:
sub_stack_class: LipidLeaflet
apm: 56.0
b_heads: 6.01e-4
vm_heads: 319.0
b_tails: -2.92e-4
vm_tails: 782.0
thickness_heads: 9.0
thickness: 23.0
rLL:
like: LL
but:
reverse_monolayer: true

globals:
length_unit: angstrom
roughness: {magnitude: 3.0, unit: angstrom}
default_solvent: {formula: 'H2O', mass_density: {magnitude: 1.0, unit: g/cm^3}}
20 changes: 20 additions & 0 deletions examples/sample_model_example_6.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
sample:
model:
comment: Saw tooth sample model
stack: air | gtop 50 | 5 (rgradient 50 | gradient 50) | Si
sub_stacks:
gradient:
sub_stack_class: FunctionTwoElements
material1: Ni
material2: Ti
function: x
rgradient:
like: gradient
but:
function: 1-x
gtop:
like: gradient
but:
roughness: 15.0
globals:
slice_resolution: {magnitude: 10.0, unit: nm}
10 changes: 10 additions & 0 deletions examples/sample_model_example_7.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
sample:
model:
comment: Sine Wave SLD
stack: air | 5 (wave 10) | Si
sub_stacks:
wave:
sub_stack_class: FunctionTwoElements
material1: Ni
material2: Ti
function: 0.5+0.5*sin(x*2*pi)
10 changes: 10 additions & 0 deletions examples/sample_model_example_8.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
sample:
model:
comment: Modulated Sine Wave SLD
stack: air | wave 200 | Si
sub_stacks:
wave:
sub_stack_class: FunctionTwoElements
material1: Ni
material2: Ti
function: (0.5+0.5*sin(x*20.0*2*pi))*exp(-(x-0.5)**2/0.25**2)
28 changes: 0 additions & 28 deletions examples/simple_model_example_4.yml

This file was deleted.

2 changes: 1 addition & 1 deletion orsopy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Top-level package for orsopy."""

__version__ = "1.2.1"
__version__ = "1.3.0"
57 changes: 33 additions & 24 deletions orsopy/fileio/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Header:
"""

_orso_optionals: List[str] = []
# _orso_name_export_priority: List[str] # an optional list of attribute names to put first in the yaml export
_subclass_dict_ = {}

def __init_subclass__(cls, **kwargs):
Expand Down Expand Up @@ -271,12 +272,23 @@ def _resolve_type(hint: type, item: Any) -> Any:
# check if the item is in the list of allowed
# subtypes
return item
potential_res = []
for subt in subtypes:
# if it's not, then try to resolve its type.
res = Header._resolve_type(subt, item)
if res is not None:
# This type conversion worked, return the result.
return res
with warnings.catch_warnings(record=True) as w:
res = Header._resolve_type(subt, item)
if res is not None:
# This type conversion worked, return the result.
if len(w) > 0:
potential_res.append((w, res))
else:
return res
if len(potential_res) > 0:
# a potential type was found, but it raised a warning
w, res = potential_res[0]
# make sure the warning is displayed
warnings.warn(w[-1].message, w[-1].category, w[-1].lineno)
return res
elif hbase is Literal:
# Special case of a string Literal, which defines a list of valid strings.
# TODO: Should we first convert the value to a string?
Expand Down Expand Up @@ -375,6 +387,9 @@ def to_yaml(self) -> str:

def _to_object_dict(self):
output = {}
# define dictionary entries for attributes to be exported first
for fname in getattr(self, "_orso_name_export_priority", []):
output[fname] = None
for i, value in self.__dict__.items():
if i.startswith("_") or (value is None and i in self._orso_optionals):
continue
Expand Down Expand Up @@ -514,6 +529,16 @@ def represent_data(self, data):
unit_registry = None


def get_unit_registry():
global unit_registry
if unit_registry is None:
import pint

unit_registry = pint.UnitRegistry()
# unit_registry.define("Angstrom = angstrom") # optional extra units
return unit_registry


@dataclass
class ErrorValue(Header):
"""
Expand Down Expand Up @@ -598,11 +623,7 @@ def as_unit(self, output_unit):
if output_unit == self.unit:
return self.magnitude

global unit_registry
if unit_registry is None:
import pint

unit_registry = pint.UnitRegistry()
unit_registry = get_unit_registry()

val = self.magnitude * unit_registry(self.unit)
return val.to(output_unit).magnitude
Expand Down Expand Up @@ -642,11 +663,7 @@ def as_unit(self, output_unit):
if output_unit == self.unit:
return value

global unit_registry
if unit_registry is None:
import pint

unit_registry = pint.UnitRegistry()
unit_registry = get_unit_registry()

val = value * unit_registry(self.unit)
return val.to(output_unit).magnitude
Expand Down Expand Up @@ -684,11 +701,7 @@ def as_unit(self, output_unit):
if output_unit == self.unit:
return (self.min, self.max)

global unit_registry
if unit_registry is None:
import pint

unit_registry = pint.UnitRegistry()
unit_registry = get_unit_registry()

vmin = self.min * unit_registry(self.unit)
vmax = self.max * unit_registry(self.unit)
Expand Down Expand Up @@ -725,11 +738,7 @@ def as_unit(self, output_unit):
if output_unit == self.unit:
return (self.x, self.y, self.z)

global unit_registry
if unit_registry is None:
import pint

unit_registry = pint.UnitRegistry()
unit_registry = get_unit_registry()

vx = self.x * unit_registry(self.unit)
vy = self.y * unit_registry(self.unit)
Expand Down
Loading