@mat3ra/made 2024.3.30-0 → 2024.4.8-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.
@@ -1,3 +1,3 @@
1
1
  #!/bin/sh
2
- command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-checkout'.\n"; exit 2; }
2
+ command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-checkout' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; }
3
3
  git lfs post-checkout "$@"
@@ -1,3 +1,3 @@
1
1
  #!/bin/sh
2
- command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-commit'.\n"; exit 2; }
2
+ command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-commit' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; }
3
3
  git lfs post-commit "$@"
package/.husky/post-merge CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/bin/sh
2
- command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/post-merge'.\n"; exit 2; }
2
+ command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'post-merge' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; }
3
3
  git lfs post-merge "$@"
package/.husky/pre-push CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/bin/sh
2
- command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting '.git/hooks/pre-push'.\n"; exit 2; }
2
+ command -v git-lfs >/dev/null 2>&1 || { echo >&2 "\nThis repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting the 'pre-push' file in the hooks directory (set by 'core.hookspath'; usually '.git/hooks').\n"; exit 2; }
3
3
  git lfs pre-push "$@"
@@ -0,0 +1,26 @@
1
+ repos:
2
+ - repo: https://github.com/Exabyte-io/pre-commit-hooks
3
+ rev: 2023.6.28
4
+ hooks:
5
+ - id: ruff
6
+ exclude: ^tests/fixtures*
7
+ - id: black
8
+ exclude: ^tests/fixtures*
9
+ - id: isort
10
+ exclude: ^tests/fixtures*
11
+ - id: mypy
12
+ exclude: ^tests/fixtures*
13
+ - id: check-yaml
14
+ exclude: ^tests/fixtures*
15
+ - id: end-of-file-fixer
16
+ exclude: ^tests/fixtures*
17
+ - id: trailing-whitespace
18
+ exclude: ^tests/fixtures*
19
+ - repo: local
20
+ hooks:
21
+ - id: lint-staged
22
+ name: lint-staged
23
+ language: node
24
+ entry: npx lint-staged
25
+ verbose: true # to see familiar lint-staged output
26
+ pass_filenames: false # lint-staged has its own glob expression
package/README.md CHANGED
@@ -15,14 +15,14 @@ As below:
15
15
 
16
16
  - the package provides a software environment for interacting with Materials-related data structures from ESSE Data Convention [[1]](#links) and is written in ECMAScript 2015 for use on the web
17
17
  - High-level classes for the representation of the [Material](src/material.js) and the corresponding structural information, ie:
18
- - [Basis](src/basis/basis.js),
19
- - [Lattice](src/lattice/lattice.js),
20
- - [ReciprocalLattice](src/lattice/reciprocal/lattice_reciprocal.js),
21
- - [Cell](src/cell/cell.js),
22
- - [AtomicConstraints](src/constraints/constraints.js)
18
+ - [Basis](src/basis/basis.js),
19
+ - [Lattice](src/lattice/lattice.js),
20
+ - [ReciprocalLattice](src/lattice/reciprocal/lattice_reciprocal.js),
21
+ - [Cell](src/cell/cell.js),
22
+ - [AtomicConstraints](src/constraints/constraints.js)
23
23
  - and others to be added.
24
24
  - input/output support, including:
25
- - POSCAR [[3]](#links),
25
+ - POSCAR [[3]](#links),
26
26
  - XYZ [[4]](#links),
27
27
  - Quantum ESPRESSO [[5]](#links),
28
28
  - and others to be added.
@@ -71,7 +71,7 @@ Made.js is written in EcmaScript 6th edition [[2]](#links) with the application
71
71
 
72
72
  3. `tools` directory contains helper functions that act on one or more classes and include an external parameter. Functions that use class data without any external parameters should be implemented inside the class. For example, `basis.clone()` is implemented in `Basis`, but basis repetition is implemented as a tool in the correspondingly named function ([tools/basis.js#repeat](src/tools/basis.js)) because the repetion requires a parameter external to basis - number of repetitions in 3 spatial dimensions.
73
73
 
74
- 4. `parsers` directory contains the parsers to- and from- ESSE format mentioned in 1. All functionality related to external data conversion is contained in this directory.
74
+ 4. `parsers` directory contains the parsers to- and from- ESSE format mentioned in 1. All functionality related to external data conversion is contained in this directory.
75
75
 
76
76
 
77
77
  ### TODO list
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __importDefault =
3
+ (this && this.__importDefault) ||
4
+ function (mod) {
5
+ return mod && mod.__esModule ? mod : { default: mod };
6
+ };
5
7
  Object.defineProperty(exports, "__esModule", { value: true });
6
8
  exports.LatticeBravais = void 0;
7
9
  const constants_1 = __importDefault(require("../constants"));
@@ -16,14 +18,24 @@ class LatticeBravais {
16
18
  * Create a Bravais lattice.
17
19
  */
18
20
  constructor(config) {
19
- const { a = 1, // default lattice is cubic with unity in edge sizes
20
- b = a, c = a, alpha = 90, beta = alpha, gamma = alpha,
21
- // if we do not know what lattice type this is => set to TRI
22
- type = "TRI", units = {
23
- length: "angstrom",
24
- angle: "degree",
25
- }, } = config;
26
- const k = constants_1.default.units.bohr === units.length ? constants_1.default.coefficients.BOHR_TO_ANGSTROM : 1;
21
+ const {
22
+ a = 1, // default lattice is cubic with unity in edge sizes
23
+ b = a,
24
+ c = a,
25
+ alpha = 90,
26
+ beta = alpha,
27
+ gamma = alpha,
28
+ // if we do not know what lattice type this is => set to TRI
29
+ type = "TRI",
30
+ units = {
31
+ length: "angstrom",
32
+ angle: "degree",
33
+ },
34
+ } = config;
35
+ const k =
36
+ constants_1.default.units.bohr === units.length
37
+ ? constants_1.default.coefficients.BOHR_TO_ANGSTROM
38
+ : 1;
27
39
  this.a = a * k;
28
40
  this.b = b * k;
29
41
  this.c = c * k;
@@ -39,7 +51,15 @@ class LatticeBravais {
39
51
  /**
40
52
  * Create a Bravais lattice from vectors.
41
53
  */
42
- static fromVectors({ a, b, c, alat = 1, units = "angstrom", type = "TRI", skipRounding = false, }) {
54
+ static fromVectors({
55
+ a,
56
+ b,
57
+ c,
58
+ alat = 1,
59
+ units = "angstrom",
60
+ type = "TRI",
61
+ skipRounding = false,
62
+ }) {
43
63
  const roundValue = skipRounding ? (x) => x : this._roundValue;
44
64
  return new this.prototype.constructor({
45
65
  // @ts-ignore
@@ -79,7 +99,11 @@ class LatticeBravais {
79
99
  get editables() {
80
100
  var _a;
81
101
  const object = {};
82
- const editablesList = (_a = types_1.LATTICE_TYPE_CONFIGS.find((entry) => entry.code === this.type)) === null || _a === void 0 ? void 0 : _a.editables;
102
+ const editablesList =
103
+ (_a = types_1.LATTICE_TYPE_CONFIGS.find((entry) => entry.code === this.type)) ===
104
+ null || _a === void 0
105
+ ? void 0
106
+ : _a.editables;
83
107
  // ["a", "gamma"] => {a: true, gamma: true}
84
108
  if (editablesList) {
85
109
  editablesList.forEach((element) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mat3ra/made",
3
- "version": "2024.3.30-0",
3
+ "version": "2024.4.8-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",
package/pyproject.toml CHANGED
@@ -16,7 +16,11 @@ classifiers = [
16
16
  ]
17
17
  dependencies = [
18
18
  # add requirements here
19
- "numpy"
19
+ "numpy",
20
+ "pymatgen",
21
+ "ase",
22
+ "mat3ra-esse",
23
+ "mat3ra-code",
20
24
  ]
21
25
 
22
26
  [project.optional-dependencies]
@@ -27,9 +31,21 @@ tests = [
27
31
  "ruff",
28
32
  "isort",
29
33
  "mypy",
30
- "pip-tools"
34
+ "pip-tools",
35
+ "pytest",
36
+ "pytest-cov",
37
+ "pydantic",
38
+ "gradio",
39
+ ]
40
+ # required to use the tools module
41
+ tools = [
42
+ "pymatgen",
43
+ "ase",
44
+ ]
45
+ all = [
46
+ "mat3ra-made[tests]",
47
+ "mat3ra-made[tools]",
31
48
  ]
32
- all = ["mat3ra-made[tests]"]
33
49
 
34
50
  # Entrypoint scripts can be defined here, see examples below.
35
51
  [project.scripts]
@@ -55,6 +71,7 @@ target-version = ['py38']
55
71
  # 'extend-exclude' excludes files or directories in addition to the defaults
56
72
  extend-exclude = '''
57
73
  (
74
+ tests\/fixtures*,
58
75
  examples\/.*\/.*\.py
59
76
  | other\/.*\/.*\.(py|ipynb)
60
77
  )
@@ -63,7 +80,8 @@ extend-exclude = '''
63
80
  [tool.ruff]
64
81
  # Exclude a variety of commonly ignored directories.
65
82
  extend-exclude = [
66
- "src/js"
83
+ "src/js",
84
+ "tests/fixtures"
67
85
  ]
68
86
  line-length = 120
69
87
  target-version = "py38"
@@ -1,5 +0,0 @@
1
- import numpy as np
2
-
3
-
4
- def get_length(vec: np.ndarray) -> np.float_:
5
- return np.linalg.norm(vec)
@@ -0,0 +1,59 @@
1
+ from typing import Any, Dict, List, Union
2
+
3
+ from mat3ra.code.constants import AtomicCoordinateUnits, Units
4
+ from mat3ra.code.entity import HasDescriptionHasMetadataNamedDefaultableInMemoryEntity
5
+ from mat3ra.esse.models.material import MaterialSchema
6
+
7
+ defaultMaterialConfig = {
8
+ "name": "Silicon FCC",
9
+ "basis": {
10
+ "elements": [
11
+ {
12
+ "id": 1,
13
+ "value": "Si",
14
+ },
15
+ {
16
+ "id": 2,
17
+ "value": "Si",
18
+ },
19
+ ],
20
+ "coordinates": [
21
+ {
22
+ "id": 1,
23
+ "value": [0.0, 0.0, 0.0],
24
+ },
25
+ {
26
+ "id": 2,
27
+ "value": [0.25, 0.25, 0.25],
28
+ },
29
+ ],
30
+ "units": AtomicCoordinateUnits.crystal,
31
+ },
32
+ "lattice": {
33
+ "type": "FCC",
34
+ "a": 3.867,
35
+ "b": 3.867,
36
+ "c": 3.867,
37
+ "alpha": 60,
38
+ "beta": 60,
39
+ "gamma": 60,
40
+ "units": {
41
+ "length": Units.angstrom,
42
+ "angle": Units.degree,
43
+ },
44
+ },
45
+ }
46
+
47
+ MaterialSchemaJSON = Dict[str, Union[MaterialSchema, Any]]
48
+
49
+
50
+ class Material(HasDescriptionHasMetadataNamedDefaultableInMemoryEntity):
51
+ jsonSchema: MaterialSchemaJSON
52
+ default_config = defaultMaterialConfig
53
+
54
+ def __init__(self, config: Any) -> None:
55
+ super().__init__(config)
56
+ self.name = super().name or self.formula
57
+
58
+ def to_json(self, exclude: List[str] = []) -> MaterialSchemaJSON:
59
+ return {**super().to_json()}
@@ -0,0 +1,44 @@
1
+ from typing import Any, Dict, Union
2
+
3
+ from mat3ra.made.material import Material
4
+ from pymatgen.core.structure import Lattice, Structure
5
+
6
+
7
+ def to_pymatgen(material_or_material_data: Union[Material, Dict[str, Any]]) -> Structure:
8
+ """
9
+ Converts material object in ESSE format to a pymatgen Structure object.
10
+
11
+ Args:
12
+ material_data (dict): A dictionary containing the material information in ESSE format.
13
+
14
+ Returns:
15
+ Structure: A pymatgen Structure object.
16
+ """
17
+ material_data = material_or_material_data
18
+
19
+ if isinstance(material_or_material_data, Material):
20
+ material_data = material_or_material_data.to_json()
21
+
22
+ lattice_params = material_data["lattice"]
23
+ a = lattice_params["a"]
24
+ b = lattice_params["b"]
25
+ c = lattice_params["c"]
26
+ alpha = lattice_params["alpha"]
27
+ beta = lattice_params["beta"]
28
+ gamma = lattice_params["gamma"]
29
+
30
+ # Create a Lattice from parameters
31
+ lattice = Lattice.from_parameters(a, b, c, alpha, beta, gamma)
32
+
33
+ # Extract the basis information
34
+ basis = material_data["basis"]
35
+ elements = [element["value"] for element in basis["elements"]]
36
+ coordinates = [coord["value"] for coord in basis["coordinates"]]
37
+
38
+ # Assuming that the basis units are fractional since it's a crystal basis
39
+ coords_are_cartesian = "units" in basis and basis["units"].lower() == "angstrom"
40
+
41
+ # Create the Structure
42
+ structure = Structure(lattice, elements, coordinates, coords_are_cartesian=coords_are_cartesian)
43
+
44
+ return structure
@@ -0,0 +1,9 @@
1
+ from mat3ra.made.material import Material
2
+
3
+ REFERENCE_OBJECT_1 = {"key1": "value1", "key2": "value2"}
4
+
5
+
6
+ def test_create():
7
+ material = Material.create(Material.default_config)
8
+ assert material.to_json() == Material.default_config
9
+ assert material.name == Material.default_config["name"]
@@ -0,0 +1,12 @@
1
+ from mat3ra.made.material import Material
2
+ from mat3ra.made.tools.material import to_pymatgen
3
+ from pymatgen.core.structure import Element, Lattice, Structure
4
+
5
+
6
+ def test_to_pymatgen():
7
+ material = Material.create(Material.default_config)
8
+ structure = to_pymatgen(material)
9
+ assert isinstance(structure, Structure)
10
+ assert structure.lattice == Lattice.from_parameters(3.867, 3.867, 3.867, 60, 60, 60)
11
+ assert structure.species == [Element("Si"), Element("Si")]
12
+ assert (structure.frac_coords == [[0.0, 0.0, 0.0], [0.25, 0.25, 0.25]]).all()
@@ -1,10 +0,0 @@
1
- import unittest
2
-
3
- import numpy as np
4
- from mat3ra.made import get_length
5
-
6
-
7
- class TestSample(unittest.TestCase):
8
- def test_type(self):
9
- a = get_length(np.array([1, 2]))
10
- self.assertTrue(type(a) == np.float_)