Skip to content

Commit

Permalink
Fix GitHub language statistics after test files migration (#3214)
Browse files Browse the repository at this point in the history
* refactor TestStructureGraph.test_draw use PymatgenTest.tmp_path

* BalancedReaction don't create unnecessary lists

* .gitattributes fix tests/files/ path causing wrong repo language statistics

* rename function my_solid_angle()->solid_angle() in coordination_geometry_utils.py
  • Loading branch information
janosh authored Aug 4, 2023
1 parent 73ccbd6 commit e0638d4
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# declare HTML, rST and test files as vendored/docs to exclude them when calculating repo languages on GitHub
**/test/files/**/* linguist-vendored
tests/files/**/* linguist-vendored
cmd_line/* linguist-vendored
docs/**/* linguist-generated
docs_rst/**/* linguist-documentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

from pymatgen.analysis.chemenv.utils.coordination_geometry_utils import (
get_lower_and_upper_f,
my_solid_angle,
rectangle_surface_intersection,
solid_angle,
)
from pymatgen.analysis.chemenv.utils.defs_utils import AdditionalConditions
from pymatgen.analysis.chemenv.utils.math_utils import normal_cdf_step
Expand Down Expand Up @@ -164,7 +164,7 @@ def setup_voronoi_list(self, indices, voronoi_cutoff):

ridge_point2 = max(ridge_points)
facets = [all_vertices[i] for i in ridge_vertices_indices]
sa = my_solid_angle(site.coords, facets)
sa = solid_angle(site.coords, facets)
maxangle = max([sa, maxangle])

mindist = min([mindist, distances[ridge_point2]])
Expand Down
63 changes: 32 additions & 31 deletions pymatgen/analysis/chemenv/utils/coordination_geometry_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import math
from typing import TYPE_CHECKING, Callable

import numpy as np
from numpy.linalg import norm
Expand All @@ -12,6 +13,9 @@

from pymatgen.analysis.chemenv.utils.chemenv_errors import SolidAngleError

if TYPE_CHECKING:
from numpy.typing import ArrayLike

__author__ = "David Waroquiers"
__copyright__ = "Copyright 2012, The Materials Project"
__credits__ = "Geoffroy Hautier"
Expand Down Expand Up @@ -84,51 +88,49 @@ def function_comparison(f1, f2, x1, x2, numpoints_check=500):
raise RuntimeError("Error in comparing functions f1 and f2 ...")


def quarter_ellipsis_functions(xx, yy):
def quarter_ellipsis_functions(xx: ArrayLike, yy: ArrayLike) -> dict[str, Callable]:
"""
Method that creates two quarter-ellipse functions based on points xx and yy. The ellipsis is supposed to
be aligned with the axes. The two ellipsis pass through the two points xx and yy.
Args:
xx:
First point
yy:
Second point
xx: First point
yy: Second point
Returns:
A dictionary with the lower and upper quarter ellipsis functions.
"""
npxx = np.array(xx)
npyy = np.array(yy)
if np.any(npxx == npyy):
xx = np.asarray(xx)
yy = np.asarray(yy)
if np.any(xx == yy):
raise RuntimeError("Invalid points for quarter_ellipsis_functions")
if np.all(npxx < npyy) or np.all(npxx > npyy):
if npxx[0] < npyy[0]:
p1 = npxx
p2 = npyy
if np.all(xx < yy) or np.all(xx > yy):
if xx[0] < yy[0]:
p1 = xx
p2 = yy
else:
p1 = npyy
p2 = npxx
p1 = yy
p2 = xx
c_lower = np.array([p1[0], p2[1]])
c_upper = np.array([p2[0], p1[1]])
b2 = (p2[1] - p1[1]) ** 2
else:
if npxx[0] < npyy[0]:
p1 = npxx
p2 = npyy
if xx[0] < yy[0]:
p1 = xx
p2 = yy
else:
p1 = npyy
p2 = npxx
p1 = yy
p2 = xx
c_lower = np.array([p2[0], p1[1]])
c_upper = np.array([p1[0], p2[1]])
b2 = (p1[1] - p2[1]) ** 2
b2overa2 = b2 / (p2[0] - p1[0]) ** 2
b2_over_a2 = b2 / (p2[0] - p1[0]) ** 2

def lower(x):
return c_lower[1] - np.sqrt(b2 - b2overa2 * (x - c_lower[0]) ** 2)
return c_lower[1] - np.sqrt(b2 - b2_over_a2 * (x - c_lower[0]) ** 2)

def upper(x):
return c_upper[1] + np.sqrt(b2 - b2overa2 * (x - c_upper[0]) ** 2)
return c_upper[1] + np.sqrt(b2 - b2_over_a2 * (x - c_upper[0]) ** 2)

return {"lower": lower, "upper": upper}

Expand Down Expand Up @@ -348,10 +350,9 @@ def diff(x):
return quad(diff, xmin, xmax)


def my_solid_angle(center, coords):
def solid_angle(center, coords):
"""
Helper method to calculate the solid angle of a set of coords from the
center.
Helper method to calculate the solid angle of a set of coords from the center.
Args:
center:
Expand All @@ -368,17 +369,17 @@ def my_solid_angle(center, coords):
n = [np.cross(r[i + 1], r[i]) for i in range(len(r) - 1)]
n.append(np.cross(r[1], r[0]))
phi = 0.0
for i in range(len(n) - 1):
for idx in range(len(n) - 1):
try:
value = math.acos(-np.dot(n[i], n[i + 1]) / (np.linalg.norm(n[i]) * np.linalg.norm(n[i + 1])))
value = math.acos(-np.dot(n[idx], n[idx + 1]) / (np.linalg.norm(n[idx]) * np.linalg.norm(n[idx + 1])))
except ValueError:
mycos = -np.dot(n[i], n[i + 1]) / (np.linalg.norm(n[i]) * np.linalg.norm(n[i + 1]))
if 0.999999999999 < mycos < 1.000000000001:
cos = -np.dot(n[idx], n[idx + 1]) / (np.linalg.norm(n[idx]) * np.linalg.norm(n[idx + 1]))
if 0.999999999999 < cos < 1.000000000001:
value = math.acos(1.0)
elif -0.999999999999 > mycos > -1.000000000001:
elif -0.999999999999 > cos > -1.000000000001:
value = math.acos(-1.0)
else:
raise SolidAngleError(mycos)
raise SolidAngleError(cos)
phi += value
return phi + (3 - len(r)) * math.pi

Expand Down
6 changes: 3 additions & 3 deletions pymatgen/analysis/dimensionality.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,10 @@ def visit(atom, atom_cluster):
atom_cluster = visit(new_atom, atom_cluster)
return atom_cluster

for i in range(n_atoms):
if not visited[i]:
for idx in range(n_atoms):
if not visited[idx]:
atom_cluster = set()
cluster = visit(i, atom_cluster)
cluster = visit(idx, atom_cluster)
clusters.append(cluster)
cluster_sizes.append(len(cluster))

Expand Down
16 changes: 8 additions & 8 deletions pymatgen/analysis/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,11 @@ def get_rms(x, y):
# sort by volume
e_v = sorted(e_v, key=lambda x: x[1])
# index of minimum energy tuple in the volume sorted list
emin_idx = e_v.index(e_min)
e_min_idx = e_v.index(e_min)
# the volume lower than the volume corresponding to minimum energy
v_before = e_v[emin_idx - 1][1]
v_before = e_v[e_min_idx - 1][1]
# the volume higher than the volume corresponding to minimum energy
v_after = e_v[emin_idx + 1][1]
v_after = e_v[e_min_idx + 1][1]
e_v_work = deepcopy(e_v)

# loop over the data points.
Expand All @@ -472,18 +472,18 @@ def get_rms(x, y):
e = [ei[0] for ei in e_v_work]
v = [ei[1] for ei in e_v_work]
# loop over polynomial order
for i in range(min_poly_order, max_poly_order + 1):
coeffs = np.polyfit(v, e, i)
for idx in range(min_poly_order, max_poly_order + 1):
coeffs = np.polyfit(v, e, idx)
pder = np.polyder(coeffs)
a = np.poly1d(pder)(v_before)
b = np.poly1d(pder)(v_after)
if a * b < 0:
rms = get_rms(e, np.poly1d(coeffs)(v))
rms_min = min(rms_min, rms * i / ndata_fit)
all_coeffs[(i, ndata_fit)] = [coeffs.tolist(), rms]
rms_min = min(rms_min, rms * idx / ndata_fit)
all_coeffs[(idx, ndata_fit)] = [coeffs.tolist(), rms]
# store the fit coefficients small to large,
# i.e a0, a1, .. an
all_coeffs[(i, ndata_fit)][0].reverse()
all_coeffs[(idx, ndata_fit)][0].reverse()
# remove 1 data point from each end.
e_v_work.pop()
e_v_work.pop(0)
Expand Down
4 changes: 2 additions & 2 deletions pymatgen/analysis/graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -683,8 +683,8 @@ def map_indices(grp):
atoms = len(grp) - 1
offset = len(self.structure) - atoms

for i in range(atoms):
grp_map[i] = i + offset
for idx in range(atoms):
grp_map[idx] = idx + offset

return grp_map

Expand Down
12 changes: 5 additions & 7 deletions pymatgen/analysis/reaction_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ def __init__(self, reactants_coeffs, products_coeffs):
Reactants and products to be specified as dict of {Composition: coeff}.
Args:
reactants_coeffs ({Composition: float}): Reactants as dict of
{Composition: amt}.
products_coeffs ({Composition: float}): Products as dict of
{Composition: amt}.
reactants_coeffs (dict[Composition, float]): Reactants as dict of {Composition: amt}.
products_coeffs (dict[Composition, float]): Products as dict of {Composition: amt}.
"""
# sum reactants and products
all_reactants = sum((k * v for k, v in reactants_coeffs.items()), Composition({}))
Expand All @@ -58,11 +56,11 @@ def __init__(self, reactants_coeffs, products_coeffs):
self._coeffs = []
self._els = []
self._all_comp = []
for c in set(list(reactants_coeffs) + list(products_coeffs)):
coeff = products_coeffs.get(c, 0) - reactants_coeffs.get(c, 0)
for key in {*reactants_coeffs, *products_coeffs}:
coeff = products_coeffs.get(key, 0) - reactants_coeffs.get(key, 0)

if abs(coeff) > self.TOLERANCE:
self._all_comp.append(c)
self._all_comp.append(key)
self._coeffs.append(coeff)

def calculate_energy(self, energies):
Expand Down
31 changes: 16 additions & 15 deletions tests/analysis/test_graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import unittest
import warnings
from glob import glob
from shutil import which

import networkx as nx
Expand Down Expand Up @@ -350,36 +351,37 @@ def test_mul(self):
@unittest.skipIf(pygraphviz is None or not (which("neato") and which("fdp")), "graphviz executables not present")
def test_draw(self):
# draw MoS2 graph
self.mos2_sg.draw_graph_to_file("MoS2_single.pdf", image_labels=True, hide_image_edges=False)
self.mos2_sg.draw_graph_to_file(f"{self.tmp_path}/MoS2_single.pdf", image_labels=True, hide_image_edges=False)
mos2_sg = self.mos2_sg * (9, 9, 1)
mos2_sg.draw_graph_to_file("MoS2.pdf", algo="neato")
mos2_sg.draw_graph_to_file(f"{self.tmp_path}/MoS2.pdf", algo="neato")

# draw MoS2 graph that's been successively multiplied
mos2_sg_2 = self.mos2_sg * (3, 3, 1)
mos2_sg_2 = mos2_sg_2 * (3, 3, 1)
mos2_sg_2.draw_graph_to_file("MoS2_twice_mul.pdf", algo="neato", hide_image_edges=True)
mos2_sg_2.draw_graph_to_file(f"{self.tmp_path}/MoS2_twice_mul.pdf", algo="neato", hide_image_edges=True)

# draw MoS2 graph that's generated from a pre-multiplied Structure
mos2_sg_premul = StructureGraph.with_local_env_strategy(self.structure * (3, 3, 1), MinimumDistanceNN())
mos2_sg_premul.draw_graph_to_file("MoS2_premul.pdf", algo="neato", hide_image_edges=True)
mos2_sg_premul.draw_graph_to_file(f"{self.tmp_path}/MoS2_premul.pdf", algo="neato", hide_image_edges=True)

# draw graph for a square lattice
self.square_sg.draw_graph_to_file("square_single.pdf", hide_image_edges=False)
self.square_sg.draw_graph_to_file(f"{self.tmp_path}/square_single.pdf", hide_image_edges=False)
square_sg = self.square_sg * (5, 5, 1)
square_sg.draw_graph_to_file("square.pdf", algo="neato", image_labels=True, node_labels=False)
square_sg.draw_graph_to_file(f"{self.tmp_path}/square.pdf", algo="neato", image_labels=True, node_labels=False)

# draw graph for a body-centered square lattice
self.bc_square_sg.draw_graph_to_file("bc_square_single.pdf", hide_image_edges=False)
self.bc_square_sg.draw_graph_to_file(f"{self.tmp_path}/bc_square_single.pdf", hide_image_edges=False)
bc_square_sg = self.bc_square_sg * (9, 9, 1)
bc_square_sg.draw_graph_to_file("bc_square.pdf", algo="neato", image_labels=False)
bc_square_sg.draw_graph_to_file(f"{self.tmp_path}/bc_square.pdf", algo="neato", image_labels=False)

# draw graph for a body-centered square lattice defined in an alternative way
self.bc_square_sg_r.draw_graph_to_file("bc_square_r_single.pdf", hide_image_edges=False)
self.bc_square_sg_r.draw_graph_to_file(f"{self.tmp_path}/bc_square_r_single.pdf", hide_image_edges=False)
bc_square_sg_r = self.bc_square_sg_r * (9, 9, 1)
bc_square_sg_r.draw_graph_to_file("bc_square_r.pdf", algo="neato", image_labels=False)
bc_square_sg_r.draw_graph_to_file(f"{self.tmp_path}/bc_square_r.pdf", algo="neato", image_labels=False)

# delete generated test files
test_files = (
# ensure PDF files were created
pdfs = {path.split("/") for path in glob(f"{self.tmp_path}/*.pdf")}
expected_pdfs = {
"bc_square_r_single.pdf",
"bc_square_r.pdf",
"bc_square_single.pdf",
Expand All @@ -390,9 +392,8 @@ def test_draw(self):
"MoS2.pdf",
"square_single.pdf",
"square.pdf",
)
for test_file in test_files:
os.remove(test_file)
}
assert pdfs == expected_pdfs

def test_to_from_dict(self):
d = self.mos2_sg.as_dict()
Expand Down

0 comments on commit e0638d4

Please sign in to comment.