Skip to content

Commit

Permalink
Merge branch 'master' into cleanup-test-files
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielYang59 authored Apr 14, 2024
2 parents b406c01 + 37d1066 commit e06eac4
Show file tree
Hide file tree
Showing 22 changed files with 273 additions and 237 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
pymatgen/io/ase.py @Andrew-S-Rosen
pymatgen/io/abinit/* @gmatteo
pymatgen/io/lobster/* @JaGeo
pymatgen/ext/* @ml-evs
tests/ext/* @ml-evs
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ci:

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.5
rev: v0.3.7
hooks:
- id: ruff
args: [--fix, --unsafe-fixes]
Expand Down
16 changes: 16 additions & 0 deletions docs/CHANGES.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 9 additions & 10 deletions pymatgen/analysis/chemenv/connectivity/connected_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,17 +241,16 @@ def __init__(
if links_data is None:
edge_data = None

elif (env_node1, env_node2, key) in links_data:
edge_data = links_data[(env_node1, env_node2, key)]
elif (env_node2, env_node1, key) in links_data:
edge_data = links_data[(env_node2, env_node1, key)]
elif (env_node1, env_node2) in links_data:
edge_data = links_data[(env_node1, env_node2)]
elif (env_node2, env_node1) in links_data:
edge_data = links_data[(env_node2, env_node1)]
else:
if (env_node1, env_node2, key) in links_data:
edge_data = links_data[(env_node1, env_node2, key)]
elif (env_node2, env_node1, key) in links_data:
edge_data = links_data[(env_node2, env_node1, key)]
elif (env_node1, env_node2) in links_data:
edge_data = links_data[(env_node1, env_node2)]
elif (env_node2, env_node1) in links_data:
edge_data = links_data[(env_node2, env_node1)]
else:
edge_data = None
edge_data = None

if edge_data:
self._connected_subgraph.add_edge(env_node1, env_node2, key, **edge_data)
Expand Down
5 changes: 4 additions & 1 deletion pymatgen/analysis/elasticity/stress.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
from __future__ import annotations

import math
from typing import TYPE_CHECKING

import numpy as np
from typing_extensions import Self

from pymatgen.core.tensors import SquareTensor

if TYPE_CHECKING:
from typing_extensions import Self

__author__ = "Joseph Montoya"
__copyright__ = "Copyright 2012, The Materials Project"
__credits__ = "Maarten de Jong, Mark Asta, Anubhav Jain"
Expand Down
27 changes: 7 additions & 20 deletions pymatgen/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# ruff: noqa: PLC0414
"""This package contains core modules and classes for representing structures and operations on them."""

from __future__ import annotations
Expand All @@ -10,25 +9,13 @@

from ruamel.yaml import YAML

from pymatgen.core.composition import Composition as Composition
from pymatgen.core.lattice import Lattice as Lattice
from pymatgen.core.operations import SymmOp as SymmOp
from pymatgen.core.periodic_table import DummySpecie as DummySpecie
from pymatgen.core.periodic_table import DummySpecies as DummySpecies
from pymatgen.core.periodic_table import Element as Element
from pymatgen.core.periodic_table import Species as Species
from pymatgen.core.periodic_table import get_el_sp as get_el_sp
from pymatgen.core.sites import PeriodicSite as PeriodicSite
from pymatgen.core.sites import Site as Site
from pymatgen.core.structure import IMolecule as IMolecule
from pymatgen.core.structure import IStructure as IStructure
from pymatgen.core.structure import Molecule as Molecule
from pymatgen.core.structure import PeriodicNeighbor as PeriodicNeighbor
from pymatgen.core.structure import SiteCollection as SiteCollection
from pymatgen.core.structure import Structure as Structure
from pymatgen.core.units import ArrayWithUnit as ArrayWithUnit
from pymatgen.core.units import FloatWithUnit as FloatWithUnit
from pymatgen.core.units import Unit as Unit
from pymatgen.core.composition import Composition
from pymatgen.core.lattice import Lattice
from pymatgen.core.operations import SymmOp
from pymatgen.core.periodic_table import DummySpecie, DummySpecies, Element, Species, get_el_sp
from pymatgen.core.sites import PeriodicSite, Site
from pymatgen.core.structure import IMolecule, IStructure, Molecule, PeriodicNeighbor, SiteCollection, Structure
from pymatgen.core.units import ArrayWithUnit, FloatWithUnit, Unit

__author__ = "Pymatgen Development Team"
__email__ = "pymatgen@googlegroups.com"
Expand Down
85 changes: 40 additions & 45 deletions pymatgen/electronic_structure/cohp.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,57 +772,52 @@ def from_file(
# LMTO COHPs have 5 significant figures
avg_data[i].update({spin: np.array([round_to_sigfigs(a, 5) for a in avg], dtype=float)})
avg_cohp = Cohp(efermi, energies, avg_data["COHP"], icohp=avg_data["ICOHP"])
elif not are_multi_center_cobis:
avg_cohp = Cohp(
efermi,
energies,
cohp_data["average"]["COHP"],
icohp=cohp_data["average"]["ICOHP"],
are_coops=are_coops,
are_cobis=are_cobis,
are_multi_center_cobis=are_multi_center_cobis,
)
del cohp_data["average"]
else:
if not are_multi_center_cobis:
avg_cohp = Cohp(
efermi,
energies,
cohp_data["average"]["COHP"],
icohp=cohp_data["average"]["ICOHP"],
are_coops=are_coops,
are_cobis=are_cobis,
are_multi_center_cobis=are_multi_center_cobis,
)
del cohp_data["average"]
else:
# only include two-center cobis in average
# do this for both spin channels
cohp = {}
cohp[Spin.up] = np.array(
[np.array(c["COHP"][Spin.up]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
# only include two-center cobis in average
# do this for both spin channels
cohp = {}
cohp[Spin.up] = np.array(
[np.array(c["COHP"][Spin.up]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
).mean(axis=0)
try:
cohp[Spin.down] = np.array(
[np.array(c["COHP"][Spin.down]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
).mean(axis=0)
except KeyError:
pass
try:
icohp = {}
icohp[Spin.up] = np.array(
[np.array(c["ICOHP"][Spin.up]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
).mean(axis=0)
try:
cohp[Spin.down] = np.array(
[np.array(c["COHP"][Spin.down]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
icohp[Spin.down] = np.array(
[np.array(c["ICOHP"][Spin.down]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
).mean(axis=0)
except KeyError:
pass
try:
icohp = {}
icohp[Spin.up] = np.array(
[np.array(c["ICOHP"][Spin.up]) for c in cohp_file.cohp_data.values() if len(c["sites"]) <= 2]
).mean(axis=0)
try:
icohp[Spin.down] = np.array(
[
np.array(c["ICOHP"][Spin.down])
for c in cohp_file.cohp_data.values()
if len(c["sites"]) <= 2
]
).mean(axis=0)
except KeyError:
pass
except KeyError:
icohp = None
avg_cohp = Cohp(
efermi,
energies,
cohp,
icohp=icohp,
are_coops=are_coops,
are_cobis=are_cobis,
are_multi_center_cobis=are_multi_center_cobis,
)
except KeyError:
icohp = None
avg_cohp = Cohp(
efermi,
energies,
cohp,
icohp=icohp,
are_coops=are_coops,
are_cobis=are_cobis,
are_multi_center_cobis=are_multi_center_cobis,
)

cohp_dict = {
key: Cohp(
Expand Down
27 changes: 25 additions & 2 deletions pymatgen/ext/optimade.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@
import logging
import sys
from collections import namedtuple
from typing import TYPE_CHECKING
from urllib.parse import urljoin, urlparse

import requests
from tqdm import tqdm
from typing_extensions import Self

from pymatgen.core import DummySpecies, Structure
from pymatgen.util.due import Doi, due
from pymatgen.util.provenance import StructureNL

if TYPE_CHECKING:
from typing_extensions import Self

# TODO: importing optimade-python-tool's data structures will make more sense
Provider = namedtuple("Provider", ["name", "base_url", "description", "homepage", "prefix"])

Expand Down Expand Up @@ -49,7 +52,9 @@ class OptimadeRester:
# these aliases are provided as a convenient shortcut for users of the OptimadeRester class
aliases = {
"aflow": "http://aflow.org/API/optimade/",
"alexandria": "https://alexandria.odbx.science",
"alexandria": "https://alexandria.icams.rub.de/pbe",
"alexandria.pbe": "https://alexandria.icams.rub.de/pbe",
"alexandria.pbesol": "https://alexandria.icams.rub.de/pbesol",
"cod": "https://www.crystallography.net/cod/optimade",
"cmr": "https://cmr-optimade.fysik.dtu.dk",
"mcloud.mc3d": "https://aiida.materialscloud.org/mc3d/optimade",
Expand All @@ -68,6 +73,7 @@ class OptimadeRester:
"nmd": "https://nomad-lab.eu/prod/rae/optimade/",
"odbx": "https://optimade.odbx.science",
"odbx.odbx_misc": "https://optimade-misc.odbx.science",
"odbx.gnome": "https://optimade-gnome.odbx.science",
"omdb.omdb_production": "http://optimade.openmaterialsdb.se",
"oqmd": "http://oqmd.org/optimade/",
"jarvis": "https://jarvis.nist.gov/optimade/jarvisdft",
Expand Down Expand Up @@ -127,6 +133,11 @@ def __init__(
# and values as the corresponding URL
self.resources = {}

# preprocess aliases to ensure they have a trailing slash where appropriate
for alias, url in self.aliases.items():
if urlparse(url).path is not None and not url.endswith("/"):
self.aliases[alias] += "/"

if not aliases_or_resource_urls:
aliases_or_resource_urls = list(self.aliases)
_logger.warning(
Expand Down Expand Up @@ -436,6 +447,10 @@ def _validate_provider(self, provider_url) -> Provider | None:
TODO: careful reading of OPTIMADE specification required
TODO: add better exception handling, intentionally permissive currently
"""
# Add trailing slash to all URLs if missing; prevents urljoin from scrubbing
# sections of the path
if urlparse(provider_url).path is not None and not provider_url.endswith("/"):
provider_url += "/"

def is_url(url) -> bool:
"""Basic URL validation thanks to https://stackoverflow.com/a/52455972."""
Expand Down Expand Up @@ -486,6 +501,9 @@ def _parse_provider(self, provider: str, provider_url: str) -> dict[str, Provide
A dictionary of keys (in format of "provider.database") to
Provider objects.
"""
# Add trailing slash to all URLs if missing; prevents urljoin from scrubbing
if urlparse(provider_url).path is not None and not provider_url.endswith("/"):
provider_url += "/"
try:
url = urljoin(provider_url, "v1/links")
provider_link_json = self._get_json(url)
Expand Down Expand Up @@ -546,6 +564,11 @@ def refresh_aliases(self, providers_url="https://providers.optimade.org/provider

self.aliases = {alias: provider.base_url for alias, provider in structure_providers.items()}

# Add missing trailing slashes to any aliases with a path that need them
for alias, url in self.aliases.items():
if urlparse(url).path is not None and not url.endswith("/"):
self.aliases[alias] += "/"

# TODO: revisit context manager logic here and in MPRester
def __enter__(self) -> Self:
"""Support for "with" context."""
Expand Down
5 changes: 4 additions & 1 deletion pymatgen/io/abinit/netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@
import logging
import os.path
import warnings
from typing import TYPE_CHECKING

import numpy as np
from monty.collections import AttrDict
from monty.dev import requires
from monty.functools import lazy_property
from monty.string import marquee
from typing_extensions import Self

from pymatgen.core.structure import Structure
from pymatgen.core.units import ArrayWithUnit
from pymatgen.core.xcfunc import XcFunc

if TYPE_CHECKING:
from typing_extensions import Self

try:
import netCDF4
except ImportError:
Expand Down
5 changes: 2 additions & 3 deletions pymatgen/io/aims/sets/bs.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ def prepare_band_input(structure: Structure, density: float = 20):
current_segment["length"] += 1
lines_and_labels.append(current_segment)
current_segment = None
else:
if current_segment is not None:
current_segment["length"] += 1
elif current_segment is not None:
current_segment["length"] += 1

bands = []
for segment in lines_and_labels:
Expand Down
Loading

0 comments on commit e06eac4

Please sign in to comment.