@mat3ra/made 2025.8.9-0 → 2025.8.13-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mat3ra/made",
3
- "version": "2025.8.9-0",
3
+ "version": "2025.8.13-0",
4
4
  "description": "MAterials DEsign library",
5
5
  "scripts": {
6
6
  "lint": "eslint --cache src/js tests/js && prettier --write src/js tests/js",
@@ -184,9 +184,17 @@ class Basis(BasisSchema, InMemoryEntityPydantic):
184
184
  self.coordinates.filter_by_ids(ids)
185
185
  return self
186
186
 
187
- def set_labels_from_list(self, labels: List[Union[int, str]]) -> None:
187
+ def set_labels_from_list(self, labels: Optional[List[Union[int, str]]]) -> None:
188
+ """
189
+ Set the labels of the basis from a list of labels (i. e. [1,1,1] for a 3-atom basis).
190
+ If None or [] are passed, the labels are removed (set to an empty array).
191
+ """
188
192
  num_atoms = len(self.elements.values)
189
193
 
194
+ if labels is None or len(labels) == 0:
195
+ self.labels = ArrayWithIds.from_values([])
196
+ return
197
+
190
198
  if len(labels) != num_atoms:
191
199
  raise ValueError(f"Number of labels ({len(labels)}) must match number of atoms ({num_atoms})")
192
200
 
@@ -1,4 +1,4 @@
1
- from typing import Any, List, Union
1
+ from typing import Any, List, Optional, Union
2
2
 
3
3
  from mat3ra.code.constants import AtomicCoordinateUnits, Units
4
4
  from mat3ra.code.entity import HasDescriptionHasMetadataNamedDefaultableInMemoryEntityPydantic
@@ -103,7 +103,7 @@ class Material(MaterialSchema, HasDescriptionHasMetadataNamedDefaultableInMemory
103
103
  def add_atom(self, element: str, coordinate: List[float], use_cartesian_coordinates: bool = False) -> None:
104
104
  self.basis.add_atom(element, coordinate, use_cartesian_coordinates)
105
105
 
106
- def set_labels_from_list(self, labels: List[Union[int, str]]) -> None:
106
+ def set_labels_from_list(self, labels: Optional[List[Union[int, str]]]) -> None:
107
107
  self.basis.set_labels_from_list(labels)
108
108
 
109
109
  def set_labels_from_value(self, value: Union[int, str]) -> None:
@@ -5,6 +5,7 @@ from mat3ra.esse.models.core.reusable.axis_enum import AxisEnum
5
5
 
6
6
  from mat3ra.made.material import Material
7
7
  from .. import InterfaceBuilder, InterfaceConfiguration
8
+ from ......build_components.entities.core.two_dimensional.vacuum.configuration import VacuumConfiguration
8
9
  from .....pristine_structures.two_dimensional.slab_strained_supercell.configuration import (
9
10
  SlabStrainedSupercellConfiguration,
10
11
  )
@@ -142,8 +143,9 @@ def create_interface_commensurate(
142
143
  use_conventional_cell=use_conventional_cell,
143
144
  )
144
145
 
146
+ vacuum_config = VacuumConfiguration(size=vacuum, crystal=None, direction=direction)
145
147
  interface_config = InterfaceConfiguration(
146
- stack_components=strained_configs,
148
+ stack_components=strained_configs + [vacuum_config],
147
149
  gaps=ArrayWithIds.from_values([gap, gap]),
148
150
  direction=direction,
149
151
  )
@@ -1,8 +1,10 @@
1
1
  import numpy as np
2
+ import pytest
2
3
  from mat3ra.made.basis import Basis, Coordinates
3
4
  from mat3ra.made.lattice import Lattice
4
5
  from mat3ra.made.material import Material
5
6
  from mat3ra.utils import assertion as assertion_utils
7
+ from unit.fixtures.bulk import BULK_Si_PRIMITIVE
6
8
  from unit.fixtures.slab import BULK_Si_CONVENTIONAL
7
9
  from unit.utils import assert_two_entities_deep_almost_equal
8
10
 
@@ -91,3 +93,28 @@ def test_basis_cell_lattice_sync():
91
93
  assertion_utils.assert_deep_almost_equal(new_vectors, material.basis.cell.vector_arrays)
92
94
  assertion_utils.assert_deep_almost_equal(new_vectors, material.lattice.vector_arrays)
93
95
  # Verify basis coordinates are still correct
96
+
97
+
98
+ @pytest.mark.parametrize(
99
+ "initial_labels, reset_labels, expected_final",
100
+ [
101
+ # Test resetting with empty list
102
+ ([1, 2], [], []),
103
+ # Test resetting with None
104
+ ([1, 2], None, []),
105
+ # Test normal behavior with non-empty lists
106
+ ([], [1, 2], [1, 2]),
107
+ ],
108
+ )
109
+ def test_set_labels_from_list(initial_labels, reset_labels, expected_final):
110
+ material = Material.create(BULK_Si_PRIMITIVE)
111
+
112
+ if initial_labels:
113
+ material.basis.set_labels_from_list(initial_labels)
114
+ assert len(material.basis.labels.values) == len(initial_labels)
115
+ assert material.basis.labels.values == initial_labels
116
+
117
+ material.basis.set_labels_from_list(reset_labels)
118
+
119
+ assert len(material.basis.labels.values) == len(expected_final)
120
+ assert material.basis.labels.values == expected_final