diff --git a/README.rst b/README.rst index 695d701..591c38e 100644 --- a/README.rst +++ b/README.rst @@ -99,7 +99,7 @@ Note: on using virtual environments on your own machine, we recommend to use Min and update the file so that you at least have the following environment variables : - - MAPI_KEY=the_key_obtained_from_materialsproject + - PMG_MAPI_KEY=the_key_obtained_from_materialsproject - PMG_VASP_PSP_DIR=path_to_vasp_potcar_files diff --git a/dev_scripts/grain_boundary.py b/dev_scripts/grain_boundary.py index ec97965..c1477c9 100644 --- a/dev_scripts/grain_boundary.py +++ b/dev_scripts/grain_boundary.py @@ -21,7 +21,7 @@ def get_grain_boundary_interface(structure=None, tilt: tilt in degrees """ - structure = get_struct_from_mp(structure, MAPI_KEY="") + structure = get_struct_from_mp(structure, PMG_MAPI_KEY="") sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() structure = structure_conventional.copy() diff --git a/dev_scripts/hetero_interface.py b/dev_scripts/hetero_interface.py index 488f8ff..1e6b2ce 100644 --- a/dev_scripts/hetero_interface.py +++ b/dev_scripts/hetero_interface.py @@ -211,12 +211,12 @@ def get_matching_lattices(iface1, iface2, max_area=100, # structure from materials project, use your own key - # gaas = get_struct_from_mp('GaAs', MAPI_KEY="") + # gaas = get_struct_from_mp('GaAs', PMG_MAPI_KEY="") # sa_gaas = SpacegroupAnalyzer(gaas) # gaas_cvn = sa_gaas.get_conventional_standard_structure() # gaas_cvn.to(fmt='poscar', filename='POSCAR_GaAs.vasp') - # cdte = get_struct_from_mp('CdTe', MAPI_KEY="") + # cdte = get_struct_from_mp('CdTe', PMG_MAPI_KEY="") # sa_cdte = SpacegroupAnalyzer(cdte) # cdte_cvn = sa_cdte.get_conventional_standard_structure() # cdte_cvn.to(fmt='poscar', filename='POSCAR_CdTe.vasp') diff --git a/dev_scripts/ligand_workflow.py b/dev_scripts/ligand_workflow.py index 6cd7dd3..2b8a58a 100644 --- a/dev_scripts/ligand_workflow.py +++ b/dev_scripts/ligand_workflow.py @@ -183,7 +183,7 @@ def get_measurement_task(structure, sol_add={}): bulk_fireworks = [] bulk_firetasks = [] # pull from matproj, use your own key - bulk = get_struct_from_mp('PbS', MAPI_KEY="") + bulk = get_struct_from_mp('PbS', PMG_MAPI_KEY="") # primitive --> conventional cell sa = SpacegroupAnalyzer(bulk) structure_conventional = sa.get_conventional_standard_structure() diff --git a/examples/CdS_mp-2469_primitive.cif b/examples/CdS_mp-2469_primitive.cif new file mode 100644 index 0000000..68fd8ed --- /dev/null +++ b/examples/CdS_mp-2469_primitive.cif @@ -0,0 +1,28 @@ +# generated using pymatgen +data_CdS +_symmetry_space_group_name_H-M 'P 1' +_cell_length_a 4.20080401 +_cell_length_b 4.20080401 +_cell_length_c 4.20080401 +_cell_angle_alpha 60.00000000 +_cell_angle_beta 60.00000000 +_cell_angle_gamma 60.00000000 +_symmetry_Int_Tables_number 1 +_chemical_formula_structural CdS +_chemical_formula_sum 'Cd1 S1' +_cell_volume 52.41821899 +_cell_formula_units_Z 1 +loop_ + _symmetry_equiv_pos_site_id + _symmetry_equiv_pos_as_xyz + 1 'x, y, z' +loop_ + _atom_site_type_symbol + _atom_site_label + _atom_site_symmetry_multiplicity + _atom_site_fract_x + _atom_site_fract_y + _atom_site_fract_z + _atom_site_occupancy + Cd Cd0 1 0.00000000 0.00000000 0.00000000 1 + S S1 1 0.75000000 0.75000000 0.75000000 1 diff --git a/examples/GaTe_mp-10009_primitive.cif b/examples/GaTe_mp-10009_primitive.cif new file mode 100644 index 0000000..81463c1 --- /dev/null +++ b/examples/GaTe_mp-10009_primitive.cif @@ -0,0 +1,34 @@ +# generated using pymatgen +data_GaTe +_symmetry_space_group_name_H-M 'P 1' +_cell_length_a 4.13459973 +_cell_length_b 4.13459973 +_cell_length_c 18.42557000 +_cell_angle_alpha 90.00000000 +_cell_angle_beta 90.00000000 +_cell_angle_gamma 120.00000000 +_symmetry_Int_Tables_number 1 +_chemical_formula_structural GaTe +_chemical_formula_sum 'Ga4 Te4' +_cell_volume 272.78375687 +_cell_formula_units_Z 4 +loop_ + _symmetry_equiv_pos_site_id + _symmetry_equiv_pos_as_xyz + 1 'x, y, z' +loop_ + _atom_site_type_symbol + _atom_site_label + _atom_site_symmetry_multiplicity + _atom_site_fract_x + _atom_site_fract_y + _atom_site_fract_z + _atom_site_occupancy + Ga Ga0 1 0.66666667 0.33333333 0.68295900 1 + Ga Ga1 1 0.33333333 0.66666667 0.18295900 1 + Ga Ga2 1 0.33333333 0.66666667 0.31704100 1 + Ga Ga3 1 0.66666667 0.33333333 0.81704100 1 + Te Te4 1 0.66666667 0.33333333 0.38620400 1 + Te Te5 1 0.33333333 0.66666667 0.88620400 1 + Te Te6 1 0.33333333 0.66666667 0.61379600 1 + Te Te7 1 0.66666667 0.33333333 0.11379600 1 diff --git a/examples/create_interface.py b/examples/create_interface.py index b944b9d..bc6a77e 100644 --- a/examples/create_interface.py +++ b/examples/create_interface.py @@ -13,7 +13,7 @@ Note: Before using the script, make sure that you do have a valid api key obtained from the materialsproject website. -Use that to set the MAPI_KEY variable below +Use that to set the PMG_MAPI_KEY variable below """ from pymatgen.core import Molecule, Structure @@ -23,7 +23,7 @@ if __name__ == '__main__': # PbS 100 surface with single hydrazine as ligand - # strt=get_struct_from_mp("PbS",MAPI_KEY=MAPI_KEY) + # strt=get_struct_from_mp("PbS",PMG_MAPI_KEY=PMG_MAPI_KEY) # using smiles_to_xyz.py you can obtain molecule xyz # using openbabel. # example structure files are provided and set in dev_scripts diff --git a/examples/hetero_interface.py b/examples/hetero_interface.py index 83059a6..7502dcf 100644 --- a/examples/hetero_interface.py +++ b/examples/hetero_interface.py @@ -17,12 +17,14 @@ from mpinterfaces.interface import Interface from mpinterfaces.transformations import * from mpinterfaces.utils import * +from mpinterfaces.old_transformations import generate_all_configs separation = 3 # in angstroms nlayers_2d = 2 nlayers_substrate = 2 -substrate_bulk = Structure.from_file('POSCAR_substrate') +#substrate_bulk = Structure.from_file('POSCAR_substrate') +substrate_bulk = Structure.from_file('CdS_mp-2469_primitive.cif') # substrate_bulk = get_struct_from_mp('Ag') sa_sub = SpacegroupAnalyzer(substrate_bulk) substrate_bulk = sa_sub.get_conventional_standard_structure() @@ -32,7 +34,9 @@ min_vac=25, primitive=False, from_ase=True) # substrate_slab = slab_from_file([0,0,1], 'POSCAR_substrate') -mat2d_slab = slab_from_file([0, 0, 1], 'POSCAR_2D') +#mat2d_slab = slab_from_file([0, 0, 1], 'POSCAR_2D') +mat2d_slab = slab_from_file([0, 0, 1], 'GaTe_mp-10009_primitive.cif') + # get the in-plane lattice aligned slabs # substrate_slab.to(fmt='poscar', filename='POSCAR_substrate_slab.vasp') mat2d_slab.to(fmt='poscar', filename='POSCAR_mat2d_slab.vasp') diff --git a/examples/naf.yaml b/examples/naf.yaml index 3c510fe..4f882a4 100644 --- a/examples/naf.yaml +++ b/examples/naf.yaml @@ -6,9 +6,9 @@ FORMULA: NaF # below # if no poscar file is provided, structure will be # downloaded from the materialsproject database -# note: must set MAPI_KEY evironment variable to +# note: must set PMG_MAPI_KEY evironment variable to # your key for obtaining data from materialproject -# export MAPI_KEY="key_value" +# export PMG_MAPI_KEY="key_value" #------------------------------------------------ INCAR: NSW: 0 diff --git a/examples/nanoparticle.py b/examples/nanoparticle.py index 50447f2..e8199c7 100644 --- a/examples/nanoparticle.py +++ b/examples/nanoparticle.py @@ -29,7 +29,7 @@ # ----------------------------------- # caution: set the structure wrt which the the miller indices are # specified. use your own key -structure = get_struct_from_mp('PbS', MAPI_KEY="") +structure = get_struct_from_mp('PbS', PMG_MAPI_KEY="") # primitive ---> conventional cell sa = SpacegroupAnalyzer(structure) structure_conventional = sa.get_conventional_standard_structure() diff --git a/examples/vasp_jobs.py b/examples/vasp_jobs.py index e876a07..6baa6c3 100644 --- a/examples/vasp_jobs.py +++ b/examples/vasp_jobs.py @@ -23,9 +23,9 @@ from mpinterfaces.interface import Interface from mpinterfaces.utils import get_run_cmmnd -MAPI_KEY = os.environ.get("MAPI_KEY", "") +PMG_MAPI_KEY = os.environ.get("PMG_MAPI_KEY", "") # get structure from materialsproject, use your own key -strt = get_struct_from_mp('PbS', MAPI_KEY=MAPI_KEY) +strt = get_struct_from_mp('PbS', PMG_MAPI_KEY=PMG_MAPI_KEY) # convert from fcc primitive to conventional cell # the conventional unit cell is used to create the slab # this is important becasue the hkl specification for the required slab diff --git a/mpinterfaces/__init__.py b/mpinterfaces/__init__.py index 67e773e..88e5206 100644 --- a/mpinterfaces/__init__.py +++ b/mpinterfaces/__init__.py @@ -9,45 +9,35 @@ import operator import warnings -from pymatgen.ext.matproj import MPRester - -from monty.serialization import loadfn - __author__ = "Kiran Mathew, Joshua J. Gabriel, Michael Ashton, " \ "Arunima K. Singh, Joshua T. Paul, Seve G. Monahan, " \ "Richard G. Hennig" __date__ = "March 3 2017" __version__ = "1.7.0" -PACKAGE_PATH = os.path.dirname(__file__) +PACKAGE_PATH = os.path.dirname(os.path.abspath(__file__)) -try: - MPINT_CONFIG = loadfn(os.path.join(PACKAGE_PATH, 'mpint_config.yaml')) -except: - MPINT_CONFIG = {} - warnings.warn('mpint_config.yaml file not configured.') +from .config_loader import CONFIG +from pymatgen.ext.matproj import MPRester -# set environ variables for MAPI_KEY and VASP_PSP_DIR -if MPINT_CONFIG.get('potentials', ''): - os.environ['PMG_VASP_PSP_DIR'] = MPINT_CONFIG.get('potentials', '') -MP_API = MPINT_CONFIG.get('mp_api', '') -if MP_API: - os.environ['MAPI_KEY'] = MP_API +# First, correctly fetch PMG_MAPI_KEY using .get() to handle cases where it might not be set +PMG_MAPI_KEY = CONFIG.get('PMG_MAPI_KEY') -MPR = MPRester(MP_API) -USERNAME = MPINT_CONFIG.get('username', None) -VASP_STD_BIN = MPINT_CONFIG.get('normal_binary', None) -VASP_TWOD_BIN = MPINT_CONFIG.get('twod_binary', None) -VDW_KERNEL = MPINT_CONFIG.get('vdw_kernel', None) -VASP_PSP = MPINT_CONFIG.get('potentials', None) -QUEUE_SYSTEM = MPINT_CONFIG.get('queue_system', None) -QUEUE_TEMPLATE = MPINT_CONFIG.get('queue_template', None) +MPR = MPRester(PMG_MAPI_KEY) + +# Other configurations +USERNAME = CONFIG.get('username') +VASP_STD_BIN = CONFIG.get('normal_binary') +VASP_TWOD_BIN = CONFIG.get('twod_binary') +VDW_KERNEL = CONFIG.get('vdw_kernel') +VASP_PSP = CONFIG.get('potentials') +QUEUE_SYSTEM = CONFIG.get('queue_system') +QUEUE_TEMPLATE = CONFIG.get('queue_template') if not QUEUE_SYSTEM: QUEUE_SYSTEM = 'slurm' - - -def get_struct_from_mp(formula, MAPI_KEY="", all_structs=False): + +def get_struct_from_mp(formula, PMG_MAPI_KEY="", all_structs=False): """ fetches the structure corresponding to the given formula from the materialsproject database. @@ -59,12 +49,12 @@ def get_struct_from_mp(formula, MAPI_KEY="", all_structs=False): this function returns the one with the lowest energy above the hull unless all_structs is set to True """ - if not MAPI_KEY: - MAPI_KEY = os.environ.get("MAPI_KEY", "") - if not MAPI_KEY: + if not PMG_MAPI_KEY: + PMG_MAPI_KEY = os.environ.get("PMG_MAPI_KEY", "") + if not PMG_MAPI_KEY: print('API key not provided') print( - 'get API KEY from materialsproject and set it to the MAPI_KEY environment variable. aborting ... ') + 'get API KEY from materialsproject and set it to the PMG_MAPI_KEY environment variable. aborting ... ') sys.exit() with MPR as m: data = m.get_data(formula) diff --git a/mpinterfaces/calibrate.py b/mpinterfaces/calibrate.py index cd98118..8b6f5b6 100644 --- a/mpinterfaces/calibrate.py +++ b/mpinterfaces/calibrate.py @@ -35,7 +35,7 @@ import numpy as np -from pymatgen import Lattice +from pymatgen.core import Lattice from pymatgen.core.structure import Structure from pymatgen.core.surface import SlabGenerator from pymatgen.io.vasp.inputs import Incar, Poscar diff --git a/mpinterfaces/config_loader.py b/mpinterfaces/config_loader.py new file mode 100644 index 0000000..062a593 --- /dev/null +++ b/mpinterfaces/config_loader.py @@ -0,0 +1,32 @@ +import os +from monty.serialization import loadfn + +def load_configurations(): + expected_keys = [ + 'PMG_MAPI_KEY', 'PMG_VASP_PSP_DIR', 'username', 'normal_binary', + 'twod_binary', 'vdw_kernel', 'potentials', 'queue_system', 'queue_template' + ] + configurations = {} + + # Attempt to load from .pmgrc.yaml + pmgrc_path = os.path.join(os.path.expanduser('~'), '.pmgrc.yaml') + if os.path.isfile(pmgrc_path): + try: + pmgrc_config = loadfn(pmgrc_path) + for key in expected_keys: + configurations[key] = pmgrc_config.get(key) + except Exception as e: + print(f"Error loading configurations from {pmgrc_path}: {e}") + + # Override with environment variables or set to None if not found + for key in expected_keys: + configurations[key] = os.getenv(key.upper(), configurations.get(key)) + + # Ensure all expected keys are present, even if as None + for key in expected_keys: + if key not in configurations: + configurations[key] = None + + return configurations + +CONFIG = load_configurations() diff --git a/mpinterfaces/mat2d/__init__.py b/mpinterfaces/mat2d/__init__.py index abbf2dd..6b3a4e1 100644 --- a/mpinterfaces/mat2d/__init__.py +++ b/mpinterfaces/mat2d/__init__.py @@ -1,6 +1,8 @@ -from mpinterfaces import MPINT_CONFIG, VASP_PSP, VASP_STD_BIN, VASP_TWOD_BIN, \ - USERNAME, VDW_KERNEL, QUEUE_SYSTEM, MPR - +from mpinterfaces import ( + VASP_PSP, VASP_STD_BIN, VASP_TWOD_BIN, + USERNAME, VDW_KERNEL, QUEUE_SYSTEM, + QUEUE_TEMPLATE, MPR +) __author__ = "Michael Ashton, Joshua J. Gabriel, Joshua T. Paul, " \ "Seve G. Monahan" __version__ = "1.7.0" diff --git a/mpinterfaces/mat2d/electronic_structure/tests/test_electronic_structure.py b/mpinterfaces/mat2d/electronic_structure/tests/test_electronic_structure.py index 97d7d49..57ca10b 100644 --- a/mpinterfaces/mat2d/electronic_structure/tests/test_electronic_structure.py +++ b/mpinterfaces/mat2d/electronic_structure/tests/test_electronic_structure.py @@ -1,7 +1,11 @@ import os import unittest -from mpinterfaces import MPINT_CONFIG +from mpinterfaces import ( + VASP_PSP, VASP_STD_BIN, VASP_TWOD_BIN, + USERNAME, VDW_KERNEL, QUEUE_SYSTEM, + QUEUE_TEMPLATE, MPR +) from mpinterfaces.mat2d.electronic_structure import * from mpinterfaces.mat2d.electronic_structure.analysis import get_band_edges, \ get_fermi_velocities, plot_band_alignments, plot_band_structure, \ diff --git a/mpinterfaces/mat2d/friction/tests/test_friction.py b/mpinterfaces/mat2d/friction/tests/test_friction.py index 4004864..309b317 100644 --- a/mpinterfaces/mat2d/friction/tests/test_friction.py +++ b/mpinterfaces/mat2d/friction/tests/test_friction.py @@ -1,7 +1,12 @@ import os import unittest -from mpinterfaces import MPINT_CONFIG +from mpinterfaces import ( + VASP_PSP, VASP_STD_BIN, VASP_TWOD_BIN, + USERNAME, VDW_KERNEL, QUEUE_SYSTEM, + QUEUE_TEMPLATE, MPR +) +from mpinterfaces.config_loader import CONFIG from mpinterfaces.mat2d.friction import * from mpinterfaces.mat2d.friction.analysis import get_basin_and_peak_locations, \ get_mu_vs_F_N diff --git a/mpinterfaces/mat2d/pourbaix/tests/test_pourbaix.py b/mpinterfaces/mat2d/pourbaix/tests/test_pourbaix.py index 0cdd395..b1ead70 100644 --- a/mpinterfaces/mat2d/pourbaix/tests/test_pourbaix.py +++ b/mpinterfaces/mat2d/pourbaix/tests/test_pourbaix.py @@ -3,7 +3,7 @@ from monty.serialization import loadfn -from mpinterfaces import MP_API +from mpinterfaces import PMG_MAPI_KEY from mpinterfaces.mat2d.pourbaix import * from mpinterfaces.mat2d.stability.startup import INCAR_DICT @@ -32,7 +32,7 @@ def test_get_experimental_formation_energies(self): for elt in control_energies: self.assertEqual(test_energies[elt], control_energies[elt]) - @unittest.skipIf(MP_API == None, "API key not set") + @unittest.skipIf(PMG_MAPI_KEY == None, "API key not set") # def test_relax_references_for_Mo_and_S(self): # os.chdir(ROOT) # relax_references(['Mo_pv', 'S'], incar_dict=INCAR_DICT, submit=False) diff --git a/mpinterfaces/mat2d/stability/tests/test_stability.py b/mpinterfaces/mat2d/stability/tests/test_stability.py index e2a227f..b791866 100644 --- a/mpinterfaces/mat2d/stability/tests/test_stability.py +++ b/mpinterfaces/mat2d/stability/tests/test_stability.py @@ -1,7 +1,7 @@ import os import unittest -from mpinterfaces import MP_API +from mpinterfaces import PMG_MAPI_KEY from mpinterfaces.mat2d.stability import * from mpinterfaces.mat2d.stability.analysis import get_competing_phases, \ get_hull_distance @@ -30,13 +30,13 @@ def test_relax_creates_files(self): class AnalysisTest(unittest.TestCase): - @unittest.skipIf(not MP_API, "API key not set") + @unittest.skipIf(not PMG_MAPI_KEY, "API key not set") def test_get_hull_distance_for_BiTeCl(self): os.chdir(ROOT) os.chdir('BiTeCl') self.assertEqual(get_hull_distance(), 0.10335952666666692) - @unittest.skipIf(not MP_API, "API key not set") + @unittest.skipIf(not PMG_MAPI_KEY, "API key not set") def test_get_competing_phases_for_BiTeCl(self): os.chdir(ROOT) os.chdir('BiTeCl') diff --git a/mpinterfaces/scripts/mpint b/mpinterfaces/scripts/mpint index 4abe28a..e3618e5 100755 --- a/mpinterfaces/scripts/mpint +++ b/mpinterfaces/scripts/mpint @@ -40,7 +40,7 @@ sh.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(sh) -MAPI_KEY = os.environ.get("MAPI_KEY", "") +PMG_MAPI_KEY = os.environ.get("PMG_MAPI_KEY", "") def process_dir(val): @@ -93,8 +93,8 @@ class mpint(object): def get_struct(self): if self.formula: - if MAPI_KEY: - strt = get_struct_from_mp(self.formula, MAPI_KEY=MAPI_KEY) + if PMG_MAPI_KEY: + strt = get_struct_from_mp(self.formula, PMG_MAPI_KEY=PMG_MAPI_KEY) sa = SpacegroupAnalyzer(strt) structure_conventional = sa.get_conventional_standard_structure() strt = structure_conventional.copy() @@ -105,7 +105,7 @@ class mpint(object): else: print( - 'get API KEY from materialsproject and set it to the MAPI_KEY environment variable') + 'get API KEY from materialsproject and set it to the PMG_MAPI_KEY environment variable') sys.exit() else: strt = None diff --git a/mpinterfaces/utils.py b/mpinterfaces/utils.py index 2227c05..2fe7dbd 100644 --- a/mpinterfaces/utils.py +++ b/mpinterfaces/utils.py @@ -31,7 +31,7 @@ from monty.serialization import loadfn, dumpfn from pymatgen.core.sites import PeriodicSite -from pymatgen import Structure, Lattice, Element +from pymatgen.core.structure import Structure, Lattice, Element from pymatgen.core.surface import Slab, SlabGenerator from pymatgen.io.ase import AseAtomsAdaptor from pymatgen.io.vasp.inputs import Poscar @@ -109,7 +109,7 @@ def slab_from_file(hkl, filename): hkl, Structure.from_sites(slab_input, to_unit_cell=True), shift=0, - scale_factor=np.eye(3, dtype=np.int), + scale_factor=np.eye(3, dtype=int), site_properties=slab_input.site_properties)