@@ -820,7 +820,7 @@ def get_str(self, sort_keys: bool = False, pretty: bool = False) -> str:
820
820
return str (tabulate ([[line [0 ], "=" , line [1 ]] for line in lines ], tablefmt = "plain" ))
821
821
return str_delimited (lines , None , " = " ) + "\n "
822
822
823
- def write_file (self , filename : PathLike ):
823
+ def write_file (self , filename : PathLike ) -> None :
824
824
"""Write Incar to a file.
825
825
826
826
Args:
@@ -1950,7 +1950,7 @@ def hash_sha256_from_file(self) -> str | None:
1950
1950
@property
1951
1951
def sha256_computed_file_hash (self ) -> str :
1952
1952
"""Computes a SHA256 hash of the PotcarSingle EXCLUDING lines starting with 'SHA256' and 'COPYR'."""
1953
- # we have to remove lines with the hash itself and the copyright
1953
+ # We have to remove lines with the hash itself and the copyright
1954
1954
# notice to get the correct hash.
1955
1955
potcar_list = self .data .split ("\n " )
1956
1956
potcar_to_hash = [line for line in potcar_list if not line .strip ().startswith (("SHA256" , "COPYR" ))]
@@ -1971,9 +1971,9 @@ def md5_header_hash(self) -> str:
1971
1971
"""MD5 hash of the metadata defining the PotcarSingle."""
1972
1972
hash_str = ""
1973
1973
for k , v in self .keywords .items ():
1974
- # for newer POTCARS we have to exclude 'SHA256' and 'COPYR lines
1974
+ # For newer POTCARS we have to exclude 'SHA256' and 'COPYR lines
1975
1975
# since they were not used in the initial hashing
1976
- if k in ( "nentries" , "Orbitals" , "SHA256" , "COPYR" ) :
1976
+ if k in { "nentries" , "Orbitals" , "SHA256" , "COPYR" } :
1977
1977
continue
1978
1978
hash_str += f"{ k } "
1979
1979
if isinstance (v , (bool , int )):
@@ -2140,12 +2140,11 @@ def data_stats(data_list: Sequence) -> dict:
2140
2140
data_match_tol : float = 1e-6
2141
2141
for ref_psp in possible_potcar_matches :
2142
2142
key_match = all (
2143
- set (ref_psp ["keywords" ][key ]) == set (self ._summary_stats ["keywords" ][key ]) # type: ignore
2144
- for key in ["header" , "data" ]
2143
+ set (ref_psp ["keywords" ][key ]) == set (self ._summary_stats ["keywords" ][key ]) for key in ["header" , "data" ]
2145
2144
)
2146
2145
2147
2146
data_diff = [
2148
- abs (ref_psp ["stats" ][key ][stat ] - self ._summary_stats ["stats" ][key ][stat ]) # type: ignore
2147
+ abs (ref_psp ["stats" ][key ][stat ] - self ._summary_stats ["stats" ][key ][stat ])
2149
2148
for stat in ["MEAN" , "ABSMEAN" , "VAR" , "MIN" , "MAX" ]
2150
2149
for key in ["header" , "data" ]
2151
2150
]
@@ -2174,7 +2173,7 @@ def copy(self) -> PotcarSingle:
2174
2173
return PotcarSingle (self .data , symbol = self .symbol )
2175
2174
2176
2175
@classmethod
2177
- def from_file (cls , filename : str ) -> Self :
2176
+ def from_file (cls , filename : PathLike ) -> Self :
2178
2177
"""Read PotcarSingle from file.
2179
2178
2180
2179
Args:
@@ -2193,11 +2192,15 @@ def from_file(cls, filename: str) -> Self:
2193
2192
except UnicodeDecodeError :
2194
2193
warnings .warn ("POTCAR contains invalid unicode errors. We will attempt to read it by ignoring errors." )
2195
2194
2196
- with codecs .open (filename , "r" , encoding = "utf-8" , errors = "ignore" ) as file :
2195
+ with codecs .open (str ( filename ) , "r" , encoding = "utf-8" , errors = "ignore" ) as file :
2197
2196
return cls (file .read (), symbol = symbol or None )
2198
2197
2199
2198
@classmethod
2200
- def from_symbol_and_functional (cls , symbol : str , functional : str | None = None ) -> Self :
2199
+ def from_symbol_and_functional (
2200
+ cls ,
2201
+ symbol : str ,
2202
+ functional : str | None = None ,
2203
+ ) -> Self :
2201
2204
"""Make a PotcarSingle from a symbol and functional.
2202
2205
2203
2206
Args:
@@ -2259,7 +2262,9 @@ def verify_potcar(self) -> tuple[bool, bool]:
2259
2262
return has_sha256 , hash_is_valid
2260
2263
2261
2264
def identify_potcar (
2262
- self , mode : Literal ["data" , "file" ] = "data" , data_tol : float = 1e-6
2265
+ self ,
2266
+ mode : Literal ["data" , "file" ] = "data" ,
2267
+ data_tol : float = 1e-6 ,
2263
2268
) -> tuple [list [str ], list [str ]]:
2264
2269
"""
2265
2270
Identify the symbol and compatible functionals associated with this PotcarSingle.
@@ -2294,12 +2299,11 @@ def identify_potcar(
2294
2299
continue
2295
2300
2296
2301
key_match = all (
2297
- set (ref_psp ["keywords" ][key ]) == set (self ._summary_stats ["keywords" ][key ]) # type: ignore[index]
2298
- for key in check_modes
2302
+ set (ref_psp ["keywords" ][key ]) == set (self ._summary_stats ["keywords" ][key ]) for key in check_modes
2299
2303
)
2300
2304
2301
2305
data_diff = [
2302
- abs (ref_psp ["stats" ][key ][stat ] - self ._summary_stats ["stats" ][key ][stat ]) # type: ignore[index]
2306
+ abs (ref_psp ["stats" ][key ][stat ] - self ._summary_stats ["stats" ][key ][stat ])
2303
2307
for stat in ["MEAN" , "ABSMEAN" , "VAR" , "MIN" , "MAX" ]
2304
2308
for key in check_modes
2305
2309
]
@@ -2325,13 +2329,13 @@ def identify_potcar_hash_based(
2325
2329
"""
2326
2330
Identify the symbol and compatible functionals associated with this PotcarSingle.
2327
2331
2328
- This method checks the md5 hash of either the POTCAR metadadata (PotcarSingle.md5_header_hash)
2332
+ This method checks the MD5 hash of either the POTCAR metadadata (PotcarSingle.md5_header_hash)
2329
2333
or the entire POTCAR file (PotcarSingle.md5_computed_file_hash) against a database
2330
2334
of hashes for POTCARs distributed with VASP 5.4.4.
2331
2335
2332
2336
Args:
2333
- mode (' data' | ' file' ): ' data' mode checks the hash of the POTCAR metadata in self.keywords,
2334
- while ' file' mode checks the hash of the entire POTCAR file.
2337
+ mode (" data" | " file" ): " data" mode checks the hash of the POTCAR metadata in self.keywords,
2338
+ while " file" mode checks the hash of the entire POTCAR file.
2335
2339
2336
2340
Returns:
2337
2341
symbol (list): List of symbols associated with the PotcarSingle
@@ -2435,7 +2439,7 @@ def identify_potcar_hash_based(
2435
2439
raise ValueError (f"Bad { mode = } . Choose 'data' or 'file'." )
2436
2440
2437
2441
if identity := hash_db .get (potcar_hash ):
2438
- # convert the potcar_functionals from the .json dict into the functional
2442
+ # Convert the potcar_functionals from the .json dict into the functional
2439
2443
# keys that pymatgen uses
2440
2444
potcar_functionals = [* {mapping_dict [i ]["pymatgen_key" ] for i in identity ["potcar_functionals" ]}]
2441
2445
@@ -2449,7 +2453,7 @@ def _gen_potcar_summary_stats(
2449
2453
summary_stats_filename : str | None = POTCAR_STATS_PATH ,
2450
2454
):
2451
2455
"""
2452
- Regenerates the reference data in potcar-summary-stats.json.bz2 used to validate POTCARs
2456
+ Regenerate the reference data in potcar-summary-stats.json.bz2 used to validate POTCARs
2453
2457
by comparing header values and several statistics of copyrighted POTCAR data without
2454
2458
having to record the POTCAR data itself.
2455
2459
@@ -2598,25 +2602,27 @@ def from_file(cls, filename: PathLike) -> Self:
2598
2602
"""
2599
2603
with zopen (filename , mode = "rt" ) as file :
2600
2604
fdata = file .read ()
2601
- potcar = cls ()
2602
2605
2603
- functionals = []
2606
+ potcar = cls ()
2607
+ functionals : list [str | None ] = []
2604
2608
for psingle_str in fdata .split ("End of Dataset" ):
2605
2609
if p_strip := psingle_str .strip ():
2606
2610
psingle = PotcarSingle (p_strip + "\n End of Dataset\n " )
2607
2611
potcar .append (psingle )
2608
2612
functionals .append (psingle .functional )
2613
+
2609
2614
if len (set (functionals )) != 1 :
2610
2615
raise ValueError ("File contains incompatible functionals!" )
2616
+
2611
2617
potcar .functional = functionals [0 ]
2612
2618
return potcar
2613
2619
2614
- def write_file (self , filename : str ) -> None :
2620
+ def write_file (self , filename : PathLike ) -> None :
2615
2621
"""
2616
2622
Write Potcar to a file.
2617
2623
2618
2624
Args:
2619
- filename (str ): filename to write to.
2625
+ filename (PathLike ): filename to write to.
2620
2626
"""
2621
2627
with zopen (filename , mode = "wt" ) as file :
2622
2628
file .write (str (self ))
@@ -2626,7 +2632,7 @@ def set_symbols(
2626
2632
symbols : Sequence [str ],
2627
2633
functional : str | None = None ,
2628
2634
sym_potcar_map : dict [str , str ] | None = None ,
2629
- ):
2635
+ ) -> None :
2630
2636
"""
2631
2637
Initialize the POTCAR from a set of symbols. Currently, the POTCARs can
2632
2638
be fetched from a location specified in .pmgrc.yaml. Use pmg config
@@ -2666,7 +2672,7 @@ def __init__(
2666
2672
** kwargs ,
2667
2673
) -> None :
2668
2674
"""
2669
- Initializes a VaspInput object with the given input files.
2675
+ Initialize a VaspInput object with the given input files.
2670
2676
2671
2677
Args:
2672
2678
incar (Incar): The Incar object.
@@ -2689,7 +2695,7 @@ def __str__(self) -> str:
2689
2695
output .extend ((key , str (val ), "" ))
2690
2696
return "\n " .join (output )
2691
2697
2692
- def as_dict (self ):
2698
+ def as_dict (self ) -> dict :
2693
2699
"""MSONable dict."""
2694
2700
dct = {key : val .as_dict () for key , val in self .items ()}
2695
2701
dct ["@module" ] = type (self ).__module__
@@ -2713,35 +2719,44 @@ def from_dict(cls, dct: dict) -> Self:
2713
2719
sub_dct ["optional_files" ][key ] = MontyDecoder ().process_decoded (val )
2714
2720
return cls (** sub_dct ) # type: ignore[arg-type]
2715
2721
2716
- def write_input (self , output_dir = "." , make_dir_if_not_present = True ):
2722
+ def write_input (
2723
+ self ,
2724
+ output_dir : PathLike = "." ,
2725
+ make_dir_if_not_present : bool = True ,
2726
+ ) -> None :
2717
2727
"""
2718
- Write VASP input to a directory.
2728
+ Write VASP inputs to a directory.
2719
2729
2720
2730
Args:
2721
- output_dir (str ): Directory to write to. Defaults to current
2722
- directory (".").
2731
+ output_dir (PathLike ): Directory to write to.
2732
+ Defaults to current directory (".").
2723
2733
make_dir_if_not_present (bool): Create the directory if not
2724
2734
present. Defaults to True.
2725
2735
"""
2726
- if make_dir_if_not_present :
2727
- os .makedirs (output_dir , exist_ok = True )
2728
- for k , v in self .items ():
2729
- if v is not None :
2730
- with zopen (os .path .join (output_dir , k ), mode = "wt" ) as file :
2731
- file .write (str (v ))
2736
+ if not os .path .isdir (output_dir ) and make_dir_if_not_present :
2737
+ os .makedirs (output_dir )
2738
+
2739
+ for key , value in self .items ():
2740
+ if value is not None :
2741
+ with zopen (os .path .join (output_dir , key ), mode = "wt" ) as file :
2742
+ file .write (str (value ))
2732
2743
2733
2744
@classmethod
2734
- def from_directory (cls , input_dir : str , optional_files : dict | None = None ) -> Self :
2745
+ def from_directory (
2746
+ cls ,
2747
+ input_dir : PathLike ,
2748
+ optional_files : dict | None = None ,
2749
+ ) -> Self :
2735
2750
"""
2736
- Read in a set of VASP input from a directory. Note that only the
2751
+ Read in a set of VASP inputs from a directory. Note that only the
2737
2752
standard INCAR, POSCAR, POTCAR and KPOINTS files are read unless
2738
2753
optional_filenames is specified.
2739
2754
2740
2755
Args:
2741
- input_dir (str ): Directory to read VASP input from.
2742
- optional_files (dict): Optional files to read in as well as a
2743
- dict of {filename: Object type}. Object type must have a
2744
- static method from_file .
2756
+ input_dir (PathLike ): Directory to read VASP input from.
2757
+ optional_files (dict): Optional files to read in as a
2758
+ dict of {filename: Object type}. Objects must have
2759
+ from_file method.
2745
2760
"""
2746
2761
sub_dct = {}
2747
2762
for fname , ftype in [
@@ -2762,7 +2777,7 @@ def from_directory(cls, input_dir: str, optional_files: dict | None = None) -> S
2762
2777
2763
2778
return cls (** sub_dct )
2764
2779
2765
- def copy (self , deep : bool = True ):
2780
+ def copy (self , deep : bool = True ) -> VaspInput :
2766
2781
"""Deep copy of VaspInput."""
2767
2782
if deep :
2768
2783
return self .from_dict (self .as_dict ())
0 commit comments