@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.
- package/.husky/post-checkout +1 -1
- package/.husky/post-commit +1 -1
- package/.husky/post-merge +1 -1
- package/.husky/pre-push +1 -1
- package/.pre-commit-config.yaml +26 -0
- package/README.md +7 -7
- package/dist/js/lattice/lattice_bravais.js +37 -13
- package/package.json +1 -1
- package/pyproject.toml +22 -4
- package/src/py/mat3ra/made/__init__.py +0 -5
- package/src/py/mat3ra/made/material.py +59 -0
- package/src/py/mat3ra/made/tools/material.py +44 -0
- package/tests/py/unit/test_material.py +9 -0
- package/tests/py/unit/test_tools_material.py +12 -0
- package/tests/py/unit/test_sample.py +0 -10
- /package/{tests/py → src/py/mat3ra/made/tools}/__init__.py +0 -0
package/.husky/post-checkout
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
|
|
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 "$@"
|
package/.husky/post-commit
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
|
|
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
|
|
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
|
|
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 =
|
|
3
|
-
|
|
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 {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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({
|
|
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 =
|
|
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
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"
|
|
@@ -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()
|
|
File without changes
|