diff --git a/pyproject.toml b/pyproject.toml index 577ac85..9bf2a6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,13 +37,13 @@ classifiers = [ # note: maximal versions are just the latest versions to exist when compatibility checks were made, later versions may also work requires-python = ">=3.9" dependencies = [ - 'numpy >= 1.22.3, < 2.4', + 'numpy >= 1.26.1, < 2.4', 'scipy >= 1.1.0, < 1.17', 'tqdm >= 4.66', ] [project.optional-dependencies] -pyscf = ['pyscf >= 2.0.1, < 2.12'] +pyscf = ['pyscf >= 2.1.0, < 2.12'] qml = ['ase >= 3.22, < 3.27'] regression = ["scikit-learn >= 0.24.2, < 1.8"] wigner = ["sympy >= 1.5, < 1.15"] @@ -52,8 +52,10 @@ cell2mol = ["qstack[pyscf,cell2mol-itself]"] equio-itself = ["metatensor-core >= 0.1.8, == 0.1.*"] equio = ["qstack[pyscf,equio-itself]"] spahm = ["qstack[pyscf]"] +all = ["qstack[pyscf,qml,regression,wigner,equio,gmol,cell2mol]"] docs-build = ["sphinx", "sphinx-argparse", "sphinx-autobuild", "myst-parser", "furo"] -all = ["qstack[pyscf,qml,regression,wigner,equio,gmol]"] +lint = ["ruff"] +dev = ["qstack[all,docs-build,lint]"] [project.urls] Repository = "https://github.com/lcmd-epfl/Q-stack.git" diff --git a/qstack/__init__.py b/qstack/__init__.py index dec7a3c..e23b113 100644 --- a/qstack/__init__.py +++ b/qstack/__init__.py @@ -1,12 +1,17 @@ """Q-stack.""" +import sys +import warnings +import builtins from qstack import tools -#from qstack import compound # needs pyscf from qstack import constants from qstack import mathutils -#from qstack import fields # needs scipy, pyscf -#from qstack import basis_opt # needs pyscf, scipy -#from qstack import spahm # requires pyscf -#from qstack import orcaio # requires pyscf -#from qstack import qml # requires ase -#from qstack import regression # requires sklearn (scikit-learn as pip calls it) + + +if sys.version_info[1]<10: + warnings.warn('Redefining built-in function zip for compatibility', stacklevel=1) + _zip = builtins.zip + def zip_override(*iterables, strict=False): + """Override built-in zip for python<3.10 to ignore `strict` argument.""" + return _zip(*iterables) + builtins.zip = zip_override diff --git a/qstack/fields/decomposition.py b/qstack/fields/decomposition.py index 91ba4b2..40363a2 100644 --- a/qstack/fields/decomposition.py +++ b/qstack/fields/decomposition.py @@ -2,7 +2,7 @@ import numpy as np import scipy -from pyscf import scf +from pyscf import scf, gto from qstack import compound from . import moments @@ -59,10 +59,10 @@ def get_self_repulsion(mol_or_mf, dm): Returns: float: Self-repulsion energy (a.u). """ - try: - j, _k = mol_or_mf.get_jk() - except AttributeError: + if isinstance(mol_or_mf, gto.mole.Mole): j, _k = scf.hf.get_jk(mol_or_mf, dm) + else: + j, _k = mol_or_mf.get_jk() return np.einsum('ij,ij', j, dm) diff --git a/qstack/regression/local_kernels.py b/qstack/regression/local_kernels.py index c17b715..759a466 100644 --- a/qstack/regression/local_kernels.py +++ b/qstack/regression/local_kernels.py @@ -11,10 +11,10 @@ import ctypes import sysconfig import warnings -import itertools import numpy as np import sklearn.metrics.pairwise as _SKLEARN_PAIRWISE from qstack.regression import __path__ as REGMODULE_PATH +from qstack.tools import pairwise RAM_BATCHING_SIZE = 1024**3 * 5 # 5GiB @@ -66,7 +66,7 @@ def compute_distance_matrix(R1, R2): else: dists = np.zeros((batch_size, *R2.shape), dtype=dtype) batch_limits = np.minimum(np.arange(0, R1.shape[0]+batch_size, step=batch_size), R1.shape[0]) - for batch_start, batch_end in itertools.pairwise(batch_limits): + for batch_start, batch_end in pairwise(batch_limits): dists_view = dists[:batch_end-batch_start] R1_view = R1[batch_start:batch_end, None, ...] np.subtract(R1_view, R2[None,:], out=dists_view) diff --git a/qstack/reorder.py b/qstack/reorder.py index 5c50ba7..f270a7e 100644 --- a/qstack/reorder.py +++ b/qstack/reorder.py @@ -51,7 +51,7 @@ def _orca2gpr_idx(l_slices, m): idx[s] = np.concatenate((idx[s][::-2], idx[s][1::2])) signs = np.ones_like(idx) signs[np.where(np.abs(m)>=3)] = -1 # in pyscf order - signs[idx] = signs # in orca order + signs[idx] = np.copy(signs) # in orca order. copy for numpy < 2 return idx, signs diff --git a/qstack/spahm/rho/utils.py b/qstack/spahm/rho/utils.py index b0e7c9b..c87c2c5 100644 --- a/qstack/spahm/rho/utils.py +++ b/qstack/spahm/rho/utils.py @@ -52,8 +52,8 @@ def chsp_converter(chsp): if fname is None: return np.full(n, None, dtype=object) if os.path.isfile(fname): - chsp = np.loadtxt(fname, dtype=object, converters=chsp_converter, encoding=None) - if len(chsp)!=n: + chsp = np.loadtxt(fname, dtype=object, converters={0: chsp_converter}, encoding=None) + if chsp.shape != (n,): raise RuntimeError(f'Wrong length of the file {fname}') else: raise RuntimeError(f"{fname} can not be found") diff --git a/qstack/tools.py b/qstack/tools.py index 11e30bd..74df480 100644 --- a/qstack/tools.py +++ b/qstack/tools.py @@ -4,11 +4,25 @@ """ import os +import sys import time import resource import argparse -import itertools import numpy as np +from itertools import accumulate +if sys.version_info[1]>=10: + from itertools import pairwise +else: + def pairwise(iterable): + """Implement itertools.pairwise for python<3.10. + + Taken from https://docs.python.org/3/library/itertools.html#itertools.pairwise + """ + iterator = iter(iterable) + a = next(iterator, None) + for b in iterator: + yield a, b + a = b def unix_time_decorator(func): @@ -115,8 +129,8 @@ def slice_generator(iterable, inc=lambda x: x, i0=0): tuple: (element, slice) pairs for each element in the iterable. """ func = func=lambda total, elem: total+inc(elem) - starts = itertools.accumulate(iterable, func=func, initial=i0) - starts_ends = itertools.pairwise(starts) + starts = accumulate(iterable, func=func, initial=i0) + starts_ends = pairwise(starts) for elem, (start, end) in zip(iterable, starts_ends, strict=True): yield elem, np.s_[start:end] diff --git a/requirements.py3.11.txt b/requirements.py3.11.txt index cf14f79..b91ce11 100644 --- a/requirements.py3.11.txt +++ b/requirements.py3.11.txt @@ -1,18 +1,17 @@ attrs==21.4.0 -certifi==2021.10.8 h5py==3.11.0 iniconfig==1.1.1 -packaging==21.3 +packaging==25.0 pluggy==1.0.0 py==1.11.0 -pyparsing==3.0.6 +pyparsing==3.2.5 pyscf==2.5.0 pytest==6.2.5 numpy==2.3.* -scipy==1.10 +scipy==1.16.3 toml==0.10.2 -scikit-learn==1.5.0 -ase==3.22 -tqdm==4.66 -metatensor-core==0.1.8 -cell2mol @ git+https://github.com/lcmd-epfl/cell2mol.git@22473bbf12a013467137a55a63c88fbbdc95baa2 +scikit-learn==1.7.2 +ase==3.26 +tqdm==4.67 +metatensor-core==0.1.17 +cell2mol @ git+https://github.com/lcmd-epfl/cell2mol.git@40b3237 diff --git a/requirements.py3.13.txt b/requirements.py3.13.txt index 18459e4..2e89926 100644 --- a/requirements.py3.13.txt +++ b/requirements.py3.13.txt @@ -6,7 +6,7 @@ pyparsing==3.2.5 pyscf==2.11.0 pytest==8.4.2 numpy==2.3.* -scipy==1.16.2 +scipy==1.16.3 scikit-learn==1.7.2 ase==3.26 tqdm==4.67 diff --git a/requirements.py3.9.txt b/requirements.py3.9.txt index 7e0f371..d38561a 100644 --- a/requirements.py3.9.txt +++ b/requirements.py3.9.txt @@ -1,18 +1,16 @@ attrs==21.4.0 -certifi==2021.10.8 h5py==3.6.0 iniconfig==1.1.1 packaging==21.3 pluggy==1.0.0 py==1.11.0 pyparsing==3.0.6 -pyscf==2.0.1 +pyscf>=2.1 pytest==6.2.5 -numpy===1.22.3 +numpy>=1.26.1 scipy==1.10 toml==0.10.2 -scikit-learn==0.24.2 +scikit-learn==1.6.1 ase==3.22 -tqdm==4.66 +tqdm==4.67 metatensor-core==0.1.8 -cell2mol @ git+https://github.com/lcmd-epfl/cell2mol.git@22473bbf12a013467137a55a63c88fbbdc95baa2 diff --git a/setup.py b/setup.py index 0d090ec..20e5c56 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,8 @@ def get_git_version_hash(): except OSError: return VERSION + "+unknown" version = p.communicate()[0] + if not version.strip(): + return VERSION + "+unknown" print(version) return VERSION+'+'+version.strip().decode() diff --git a/tests/test_molden.py b/tests/test_molden.py index 8ea9554..01e0a47 100755 --- a/tests/test_molden.py +++ b/tests/test_molden.py @@ -2,7 +2,6 @@ import os import tempfile -import filecmp import numpy as np from qstack import compound from qstack.fields.density2file import coeffs_to_molden @@ -14,7 +13,13 @@ def test_molden(): c = np.load(path+'/data/H2O_dist.ccpvdz.ccpvdzjkfit.npy') tmpfile = tempfile.mktemp() + '.molden' coeffs_to_molden(auxmol, c, tmpfile) - assert (filecmp.cmp(path+'/data/H2O_dist.ccpvdz.ccpvdzjkfit.molden', tmpfile)) + with open(tmpfile) as f: + output = f.readlines() + output = ''.join(output[0:1]+output[2:]) + with open(path+'/data/H2O_dist.ccpvdz.ccpvdzjkfit.molden') as f: + output0 = f.readlines() + output0 = ''.join(output0[0:1]+output0[2:]) + assert np.all(output==output0) if __name__ == '__main__':