Skip to content

Commit

Permalink
Merge pull request #121 from Exabyte-io/update/SOF-7321-clean
Browse files Browse the repository at this point in the history
update/SOF 7321 clean
  • Loading branch information
timurbazhirov authored Apr 8, 2024
2 parents c356698 + 8260f40 commit bc267b9
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
path: actions

- name: Run python unit tests
uses: ./actions/py/test
uses: ./actions/py/pytest
with:
python-version: ${{ matrix.python-version }}
unit-test-directory: tests/py/unit
Expand Down
2 changes: 1 addition & 1 deletion .husky/post-checkout
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh
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; }
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; }
git lfs post-checkout "$@"
2 changes: 1 addition & 1 deletion .husky/post-commit
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh
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; }
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; }
git lfs post-commit "$@"
2 changes: 1 addition & 1 deletion .husky/post-merge
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh
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; }
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; }
git lfs post-merge "$@"
2 changes: 1 addition & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh
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; }
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; }
git lfs pre-push "$@"
26 changes: 26 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
repos:
- repo: https://github.com/Exabyte-io/pre-commit-hooks
rev: 2023.6.28
hooks:
- id: ruff
exclude: ^tests/fixtures*
- id: black
exclude: ^tests/fixtures*
- id: isort
exclude: ^tests/fixtures*
- id: mypy
exclude: ^tests/fixtures*
- id: check-yaml
exclude: ^tests/fixtures*
- id: end-of-file-fixer
exclude: ^tests/fixtures*
- id: trailing-whitespace
exclude: ^tests/fixtures*
- repo: local
hooks:
- id: lint-staged
name: lint-staged
language: node
entry: npx lint-staged
verbose: true # to see familiar lint-staged output
pass_filenames: false # lint-staged has its own glob expression
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ As below:

- 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
- High-level classes for the representation of the [Material](src/material.js) and the corresponding structural information, ie:
- [Basis](src/basis/basis.js),
- [Lattice](src/lattice/lattice.js),
- [ReciprocalLattice](src/lattice/reciprocal/lattice_reciprocal.js),
- [Cell](src/cell/cell.js),
- [AtomicConstraints](src/constraints/constraints.js)
- [Basis](src/basis/basis.js),
- [Lattice](src/lattice/lattice.js),
- [ReciprocalLattice](src/lattice/reciprocal/lattice_reciprocal.js),
- [Cell](src/cell/cell.js),
- [AtomicConstraints](src/constraints/constraints.js)
- and others to be added.
- input/output support, including:
- POSCAR [[3]](#links),
- POSCAR [[3]](#links),
- XYZ [[4]](#links),
- Quantum ESPRESSO [[5]](#links),
- and others to be added.
Expand Down Expand Up @@ -71,7 +71,7 @@ Made.js is written in EcmaScript 6th edition [[2]](#links) with the application

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.

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.
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.


### TODO list
Expand Down
50 changes: 37 additions & 13 deletions dist/js/lattice/lattice_bravais.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LatticeBravais = void 0;
const constants_1 = __importDefault(require("../constants"));
Expand All @@ -16,14 +18,24 @@ class LatticeBravais {
* Create a Bravais lattice.
*/
constructor(config) {
const { a = 1, // default lattice is cubic with unity in edge sizes
b = a, c = a, alpha = 90, beta = alpha, gamma = alpha,
// if we do not know what lattice type this is => set to TRI
type = "TRI", units = {
length: "angstrom",
angle: "degree",
}, } = config;
const k = constants_1.default.units.bohr === units.length ? constants_1.default.coefficients.BOHR_TO_ANGSTROM : 1;
const {
a = 1, // default lattice is cubic with unity in edge sizes
b = a,
c = a,
alpha = 90,
beta = alpha,
gamma = alpha,
// if we do not know what lattice type this is => set to TRI
type = "TRI",
units = {
length: "angstrom",
angle: "degree",
},
} = config;
const k =
constants_1.default.units.bohr === units.length
? constants_1.default.coefficients.BOHR_TO_ANGSTROM
: 1;
this.a = a * k;
this.b = b * k;
this.c = c * k;
Expand All @@ -39,7 +51,15 @@ class LatticeBravais {
/**
* Create a Bravais lattice from vectors.
*/
static fromVectors({ a, b, c, alat = 1, units = "angstrom", type = "TRI", skipRounding = false, }) {
static fromVectors({
a,
b,
c,
alat = 1,
units = "angstrom",
type = "TRI",
skipRounding = false,
}) {
const roundValue = skipRounding ? (x) => x : this._roundValue;
return new this.prototype.constructor({
// @ts-ignore
Expand Down Expand Up @@ -79,7 +99,11 @@ class LatticeBravais {
get editables() {
var _a;
const object = {};
const editablesList = (_a = types_1.LATTICE_TYPE_CONFIGS.find((entry) => entry.code === this.type)) === null || _a === void 0 ? void 0 : _a.editables;
const editablesList =
(_a = types_1.LATTICE_TYPE_CONFIGS.find((entry) => entry.code === this.type)) ===
null || _a === void 0
? void 0
: _a.editables;
// ["a", "gamma"] => {a: true, gamma: true}
if (editablesList) {
editablesList.forEach((element) => {
Expand Down
26 changes: 22 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ classifiers = [
]
dependencies = [
# add requirements here
"numpy"
"numpy",
"pymatgen",
"ase",
"mat3ra-esse",
"mat3ra-code",
]

[project.optional-dependencies]
Expand All @@ -27,9 +31,21 @@ tests = [
"ruff",
"isort",
"mypy",
"pip-tools"
"pip-tools",
"pytest",
"pytest-cov",
"pydantic",
"gradio",
]
# required to use the tools module
tools = [
"pymatgen",
"ase",
]
all = [
"mat3ra-made[tests]",
"mat3ra-made[tools]",
]
all = ["mat3ra-made[tests]"]

# Entrypoint scripts can be defined here, see examples below.
[project.scripts]
Expand All @@ -55,6 +71,7 @@ target-version = ['py38']
# 'extend-exclude' excludes files or directories in addition to the defaults
extend-exclude = '''
(
tests\/fixtures*,
examples\/.*\/.*\.py
| other\/.*\/.*\.(py|ipynb)
)
Expand All @@ -63,7 +80,8 @@ extend-exclude = '''
[tool.ruff]
# Exclude a variety of commonly ignored directories.
extend-exclude = [
"src/js"
"src/js",
"tests/fixtures"
]
line-length = 120
target-version = "py38"
Expand Down
5 changes: 0 additions & 5 deletions src/py/mat3ra/made/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
import numpy as np


def get_length(vec: np.ndarray) -> np.float_:
return np.linalg.norm(vec)
59 changes: 59 additions & 0 deletions src/py/mat3ra/made/material.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from typing import Any, Dict, List, Union

from mat3ra.code.constants import AtomicCoordinateUnits, Units
from mat3ra.code.entity import HasDescriptionHasMetadataNamedDefaultableInMemoryEntity
from mat3ra.esse.models.material import MaterialSchema

defaultMaterialConfig = {
"name": "Silicon FCC",
"basis": {
"elements": [
{
"id": 1,
"value": "Si",
},
{
"id": 2,
"value": "Si",
},
],
"coordinates": [
{
"id": 1,
"value": [0.0, 0.0, 0.0],
},
{
"id": 2,
"value": [0.25, 0.25, 0.25],
},
],
"units": AtomicCoordinateUnits.crystal,
},
"lattice": {
"type": "FCC",
"a": 3.867,
"b": 3.867,
"c": 3.867,
"alpha": 60,
"beta": 60,
"gamma": 60,
"units": {
"length": Units.angstrom,
"angle": Units.degree,
},
},
}

MaterialSchemaJSON = Dict[str, Union[MaterialSchema, Any]]


class Material(HasDescriptionHasMetadataNamedDefaultableInMemoryEntity):
jsonSchema: MaterialSchemaJSON
default_config = defaultMaterialConfig

def __init__(self, config: Any) -> None:
super().__init__(config)
self.name = super().name or self.formula

def to_json(self, exclude: List[str] = []) -> MaterialSchemaJSON:
return {**super().to_json()}
File renamed without changes.
44 changes: 44 additions & 0 deletions src/py/mat3ra/made/tools/material.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import Any, Dict, Union

from mat3ra.made.material import Material
from pymatgen.core.structure import Lattice, Structure


def to_pymatgen(material_or_material_data: Union[Material, Dict[str, Any]]) -> Structure:
"""
Converts material object in ESSE format to a pymatgen Structure object.
Args:
material_data (dict): A dictionary containing the material information in ESSE format.
Returns:
Structure: A pymatgen Structure object.
"""
material_data = material_or_material_data

if isinstance(material_or_material_data, Material):
material_data = material_or_material_data.to_json()

lattice_params = material_data["lattice"]
a = lattice_params["a"]
b = lattice_params["b"]
c = lattice_params["c"]
alpha = lattice_params["alpha"]
beta = lattice_params["beta"]
gamma = lattice_params["gamma"]

# Create a Lattice from parameters
lattice = Lattice.from_parameters(a, b, c, alpha, beta, gamma)

# Extract the basis information
basis = material_data["basis"]
elements = [element["value"] for element in basis["elements"]]
coordinates = [coord["value"] for coord in basis["coordinates"]]

# Assuming that the basis units are fractional since it's a crystal basis
coords_are_cartesian = "units" in basis and basis["units"].lower() == "angstrom"

# Create the Structure
structure = Structure(lattice, elements, coordinates, coords_are_cartesian=coords_are_cartesian)

return structure
9 changes: 9 additions & 0 deletions tests/py/unit/test_material.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from mat3ra.made.material import Material

REFERENCE_OBJECT_1 = {"key1": "value1", "key2": "value2"}


def test_create():
material = Material.create(Material.default_config)
assert material.to_json() == Material.default_config
assert material.name == Material.default_config["name"]
10 changes: 0 additions & 10 deletions tests/py/unit/test_sample.py

This file was deleted.

12 changes: 12 additions & 0 deletions tests/py/unit/test_tools_material.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from mat3ra.made.material import Material
from mat3ra.made.tools.material import to_pymatgen
from pymatgen.core.structure import Element, Lattice, Structure


def test_to_pymatgen():
material = Material.create(Material.default_config)
structure = to_pymatgen(material)
assert isinstance(structure, Structure)
assert structure.lattice == Lattice.from_parameters(3.867, 3.867, 3.867, 60, 60, 60)
assert structure.species == [Element("Si"), Element("Si")]
assert (structure.frac_coords == [[0.0, 0.0, 0.0], [0.25, 0.25, 0.25]]).all()

0 comments on commit bc267b9

Please sign in to comment.