def generate_doc(self, dir_name, lmps_input, log, dumps): """ Args: dir_name (str): path to the run dir. lmps_input (LammpsInput/LammpsInputSet): log (LammpsLog): dumps ([(filename, LammpsDump)]): list of (dump filename, dump) tuples Returns: dict """ try: fullpath = os.path.abspath(dir_name) if self.use_full_uri: fullpath = get_uri(dir_name) d = {k: v for k, v in self.additional_fields.items()} d["schema"] = {"code": "atomate", "version": LammpsDrone.__version__} d["completed_at"] = str(datetime.fromtimestamp(os.path.getmtime(log.log_file))) d["dir_name"] = fullpath d["last_updated"] = datetime.utcnow() d["input"] = lmps_input.as_dict() d["output"] = {"log": log.as_dict()} d["output"]["dumps"] = dict([(dump_fname, dmp.as_dict()) for dump_fname, dmp in dumps]) return d except: import traceback logger.error(traceback.format_exc()) logger.error("Error in " + os.path.abspath(dir_name) + ".\n" + traceback.format_exc()) return None
def post_process(self, dir_name, d): """ Post-processing for various files other than the vasprun.xml and OUTCAR. Looks for files: transformations.json and custodian.json. Modify this if other output files need to be processed. Args: dir_name: The dir_name. d: Current doc generated. """ logger.info("Post-processing dir:{}".format(dir_name)) fullpath = os.path.abspath(dir_name) # VASP input generated by pymatgen's alchemy has a transformations.json file that tracks # the origin of a particular structure. If such a file is found, it is inserted into the # task doc as d["transformations"] transformations = {} filenames = glob.glob(os.path.join(fullpath, "transformations.json*")) if len(filenames) >= 1: with zopen(filenames[0], "rt") as f: transformations = json.load(f) try: m = re.match("(\d+)-ICSD", transformations["history"][0]["source"]) if m: d["icsd_id"] = int(m.group(1)) except Exception as ex: logger.warning("Cannot parse ICSD from transformations file.") pass else: logger.warning("Transformations file does not exist.") other_parameters = transformations.get("other_parameters") new_tags = None if other_parameters: # We don't want to leave tags or authors in the # transformations file because they'd be copied into # every structure generated after this one. new_tags = other_parameters.pop("tags", None) new_author = other_parameters.pop("author", None) if new_author: d["author"] = new_author if not other_parameters: # if dict is now empty remove it transformations.pop("other_parameters") d["transformations"] = transformations # Calculations done using custodian has a custodian.json, # which tracks the jobs performed and any errors detected and fixed. # This is useful for tracking what has actually be done to get a # result. If such a file is found, it is inserted into the task doc # as d["custodian"] filenames = glob.glob(os.path.join(fullpath, "custodian.json*")) if len(filenames) >= 1: with zopen(filenames[0], "rt") as f: d["custodian"] = json.load(f) # Convert to full uri path. if self.use_full_uri: d["dir_name"] = get_uri(dir_name) if new_tags: d["tags"] = new_tags # Calculations using custodian generate a *.orig file for the inputs # This is useful to know how the calculation originally started # if such files are found they are inserted into orig_inputs filenames = glob.glob(os.path.join(fullpath, "*.orig*")) if len(filenames) >= 1: d["orig_inputs"] = {} for f in filenames: if "INCAR.orig" in f: d["orig_inputs"]["incar"] = Incar.from_file(f).as_dict() if "POTCAR.orig" in f: d["orig_inputs"]["potcar"] = Potcar.from_file(f).as_dict() if "KPOINTS.orig" in f: d["orig_inputs"]["kpoints"] = Kpoints.from_file(f).as_dict() if "POSCAR.orig" in f: d["orig_inputs"]["poscar"] = Poscar.from_file(f).as_dict() logger.info("Post-processed " + fullpath)
def test_get_uri(self): self.assertTrue(MODULE_DIR in get_uri(MODULE_DIR))