def test_copyfilesfromcalcloc(self): fw1 = Firework([CopyVaspOutputs(calc_dir=self.plain_outdir), PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([CopyVaspOutputs(calc_dir=self.relax2_outdir), PassCalcLocs(name="fw2")], name="fw2") fw3 = Firework([CopyFilesFromCalcLoc(calc_loc="fw1", filenames=["POSCAR"], name_prepend="", name_append="_0"), CopyFilesFromCalcLoc(calc_loc="fw2", filenames=["POSCAR"], name_prepend="", name_append="_1"), PassCalcLocs(name="fw3")], name="fw3", parents=[fw1, fw2]) fw4 = Firework([PassCalcLocs(name="fw4")], name="fw4", parents=fw3) wf = Workflow([fw1, fw2, fw3, fw4]) self.lp.add_wf(wf) rapidfire(self.lp) fw4 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw4"})[0]) calc_locs = fw4.spec["calc_locs"] self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR_0")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR_1"))
def test_copyfilesfromcalcloc(self): fw1 = Firework( [ CopyVaspOutputs(calc_dir=self.plain_outdir), PassCalcLocs(name="fw1") ], name="fw1", ) fw2 = Firework( [ CopyVaspOutputs(calc_dir=self.relax2_outdir), PassCalcLocs(name="fw2") ], name="fw2", ) fw3 = Firework( [ CopyFilesFromCalcLoc( calc_loc="fw1", filenames=["POSCAR"], name_prepend="", name_append="_0", ), CopyFilesFromCalcLoc( calc_loc="fw2", filenames=["POSCAR"], name_prepend="", name_append="_1", ), PassCalcLocs(name="fw3"), ], name="fw3", parents=[fw1, fw2], ) fw4 = Firework([PassCalcLocs(name="fw4")], name="fw4", parents=fw3) wf = Workflow([fw1, fw2, fw3, fw4]) self.lp.add_wf(wf) rapidfire(self.lp) fw4 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw4"})[0]) calc_locs = fw4.spec["calc_locs"] self.assertTrue( os.path.exists( get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR_0")) self.assertTrue( os.path.exists( get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR_1"))
def test_cleanupfiles_calc_loc(self): # will test deleting files from previous folder fw1 = Firework( [ CreateFolder(folder_name="to_remove.relax0"), CreateFolder(folder_name="to_remove.relax1"), CreateFolder(folder_name="dont_remove.relax0"), CreateFolder(folder_name="shouldnt_touch"), PassCalcLocs(name="fw1"), ], name="fw1", ) fw2 = Firework( [ DeleteFilesPrevFolder(files=["to_remove*", "dont_remove"], calc_loc=True), PassCalcLocs(name="fw2"), ], name="fw2", parents=fw1, ) wf = Workflow([fw1, fw2]) self.lp.add_wf(wf) rapidfire(self.lp) fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0]) calc_locs = fw2.spec["calc_locs"] self.assertTrue( os.path.exists( os.path.join( get_calc_loc("fw1", calc_locs)["path"], "dont_remove.relax0"))) self.assertTrue( os.path.exists( os.path.join( get_calc_loc("fw1", calc_locs)["path"], "shouldnt_touch"))) self.assertFalse( os.path.exists( os.path.join( get_calc_loc("fw1", calc_locs)["path"], "to_remove.relax0"))) self.assertFalse( os.path.exists( os.path.join( get_calc_loc("fw1", calc_locs)["path"], "to_remove.relax1")))
def run_task(self, fw_spec): # get the directory that contains the dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the calc directory logger.info("PARSING DIRECTORY: {} USING DRONE: {}".format( calc_dir, self["drone"].__class__.__name__)) # get the database connection db_file = env_chk(self.get("db_file"), fw_spec) drone = self["drone"].__class__() task_doc = drone.assimilate(calc_dir) if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb_str = self["mmdb"] modname, classname = mmdb_str.strip().rsplit(".", 1) cls_ = load_class(modname, classname) db = cls_.from_db_file(db_file) # insert the task document t_id = db.insert(task_doc) logger.info(f"Finished parsing with task_id: {t_id}") return FWAction( stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=(task_doc["state"] != "successful"), )
def run_task(self, fw_spec): calc_loc = get_calc_loc( self["calc_loc"], fw_spec["calc_locs"]) if self.get("calc_loc") else {} # determine what files need to be copied files_to_copy = None if not "$ALL" in self.get("additional_files", []): files_to_copy = [ 'INCAR', 'POSCAR', 'KPOINTS', 'POTCAR', 'OUTCAR', 'vasprun.xml' ] if self.get("additional_files"): files_to_copy.extend(self["additional_files"]) # decide between poscar and contcar contcar_to_poscar = self.get("contcar_to_poscar", True) if contcar_to_poscar and "CONTCAR" not in files_to_copy: files_to_copy.append("CONTCAR") files_to_copy = [f for f in files_to_copy if f != 'POSCAR'] # remove POSCAR # setup the copy self.setup_copy(self.get("calc_dir", None), filesystem=self.get("filesystem", None), files_to_copy=files_to_copy, from_path_dict=calc_loc) # do the copying self.copy_files()
def run_task(self, fw_spec): # get the directory that contains the dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the calc directory logger.info("PARSING DIRECTORY: {} USING DRONE: {}".format( calc_dir, self['drone'].__class__.__name__)) # get the database connection db_file = env_chk(self.get('db_file'), fw_spec) drone = self['drone'].__class__() task_doc = drone.assimilate(calc_dir) if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb_str = self["mmdb"] modname, classname = mmdb_str.strip().rsplit(".", 1) cls_ = load_class(modname, classname) db = cls_.from_db_file(db_file) # insert the task document t_id = db.insert(task_doc) logger.info("Finished parsing with task_id: {}".format(t_id)) return FWAction(stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=(task_doc["state"] != "successful"))
def run_task(self, fw_spec): calc_loc = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"]) if self.get( "calc_loc") else {} # determine what files need to be copied files_to_copy = None if not "$ALL" in self.get("additional_files", []): files_to_copy = ['INCAR', 'POSCAR', 'KPOINTS', 'POTCAR', 'OUTCAR', 'vasprun.xml'] if self.get("additional_files"): files_to_copy.extend(self["additional_files"]) # decide between poscar and contcar contcar_to_poscar = self.get("contcar_to_poscar", True) if contcar_to_poscar and "CONTCAR" not in files_to_copy: files_to_copy.append("CONTCAR") files_to_copy = [f for f in files_to_copy if f != 'POSCAR'] # remove POSCAR # setup the copy self.setup_copy(self.get("calc_dir", None), filesystem=self.get("filesystem", None), files_to_copy=files_to_copy, from_path_dict=calc_loc) # do the copying self.copy_files()
def run_task(self, fw_spec): calc_loc = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"]) if self.get("calc_loc") else {} exclude_files = self.get("exclude_files", []) self.setup_copy(self.get("calc_dir", None), filesystem=self.get("filesystem", None), exclude_files=exclude_files, from_path_dict=calc_loc) self.copy_files()
def run_task(self, fw_spec): # get the directory that contains the QChem dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] input_file = self.get("input_file", "mol.qin") output_file = self.get("output_file", "mol.qout") multirun = self.get("multirun", False) # parse the QChem directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) additional_fields = self.get("additional_fields", []) drone = QChemDrone(additional_fields=additional_fields) # assimilate (i.e., parse) task_doc = drone.assimilate( path=calc_dir, input_file=input_file, output_file=output_file, multirun=multirun) if "tags" in fw_spec: task_doc.update({"tags": fw_spec["tags"]}) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update({self.get("fw_spec_field"): fw_spec.get(self.get("fw_spec_field"))}) # Update fw_spec with final/optimized structure update_spec = {} if task_doc.get("output").get("optimized_molecule"): update_spec["prev_calc_molecule"] = task_doc["output"]["optimized_molecule"] update_spec["prev_calc_mulliken"] = task_doc["output"]["mulliken"] if "RESP" in task_doc["output"]: update_spec["prev_calc_resp"] = task_doc["output"]["RESP"] elif "ESP" in task_doc["output"]: update_spec["prev_calc_esp"] = task_doc["output"]["ESP"] # get the database connection db_file = env_chk(self.get("db_file"), fw_spec) # db insertion or taskdoc dump if not db_file: with open(os.path.join(calc_dir, "task.json"), "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = QChemCalcDb.from_db_file(db_file, admin=True) t_id = mmdb.insert(task_doc) logger.info("Finished parsing with task_id: {}".format(t_id)) return FWAction( stored_data={"task_id": task_doc.get("task_id", None)}, update_spec=update_spec)
def run_task(self, fw_spec): files_to_copy = [ "POSCAR", "INCAR", "KPOINTS", "vasprun.xml", "OUTCAR", "POTCAR" ] files_to_copy_add = [ "POSCAR", "INCAR", "KPOINTS", "vasprun.xml", "OUTCAR", "INPCAR", "EIGENVAL" ] path_dict = dict() calc_loc_equi = get_calc_loc("equi nscf", fw_spec["calc_locs"]) path_dict["equi"] = calc_loc_equi["path"] calc_loc_05 = get_calc_loc("0.5per nscf", fw_spec["calc_locs"]) path_dict["0.5per"] = calc_loc_05["path"] calc_loc_10 = get_calc_loc("1.0per nscf", fw_spec["calc_locs"]) path_dict["1.0per"] = calc_loc_10["path"] calc_loc_dielect = get_calc_loc("dielectric", fw_spec["calc_locs"]) path_dict["dielect"] = calc_loc_dielect["path"] calc_loc_elastic = get_calc_loc("elastic", fw_spec["calc_locs"]) path_dict["elastic"] = calc_loc_elastic["path"] calc_loc_CBM = get_calc_loc("CBM", fw_spec["calc_locs"]) path_dict["CBM"] = calc_loc_CBM["path"] calc_loc_VBM = get_calc_loc("VBM", fw_spec["calc_locs"]) path_dict["VBM"] = calc_loc_VBM["path"] try: calc_loc_CSB = get_calc_loc("CSB", fw_spec["calc_locs"]) except ValueError as err: print(err) else: path_dict["CSB"] = calc_loc_CSB["path"] try: calc_loc_VSB = get_calc_loc("VSB", fw_spec["calc_locs"]) except ValueError as err: print(err) else: path_dict["VSB"] = calc_loc_VSB["path"] curr_dir = os.getcwd() for key, path in path_dict.items(): new_dir = os.path.join(curr_dir, key) os.makedirs(new_dir) if key not in ["CBM", "VBM", "CSB", "VSB"]: copy = CopyFiles(from_dir=path, to_dir=new_dir, files_to_copy=files_to_copy) copy.run_task(fw_spec) else: copy = CopyFiles(from_dir=path, to_dir=new_dir, files_to_copy=files_to_copy_add) copy.run_task(fw_spec)
def run_task(self, fw_spec): # get the directory that contains the VASP dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the VASP directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = VaspDrone(additional_fields=self.get("additional_fields"), parse_dos=self.get("parse_dos", False), bandstructure_mode=self.get("bandstructure_mode", False)) # assimilate (i.e., parse) task_doc = drone.assimilate(calc_dir) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) # get the database connection db_file = env_chk(self.get('db_file'), fw_spec) # db insertion or taskdoc dump if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = VaspMDCalcDb.from_db_file(db_file, admin=True) # prevent duplicate insertion mmdb.db.tasks.find_one_and_delete({ 'formula_pretty': task_doc['formula_pretty'], 'task_label': task_doc['task_label'] }) t_id = mmdb.insert_task( task_doc, parse_dos=self.get("parse_dos", False), parse_bs=bool(self.get("bandstructure_mode", False)), md_structures=self.get("md_structures", True)) logger.info("Finished parsing with task_id: {}".format(t_id)) if self.get("defuse_unsuccessful", True): defuse_children = (task_doc["state"] != "successful") else: defuse_children = False return FWAction(stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=defuse_children)
def run_task(self, fw_spec): # get the directory that contains the VASP dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the VASP directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = VaspDrone(additional_fields=self.get("additional_fields"), parse_dos=self.get("parse_dos", False), compress_dos=1, bandstructure_mode=self.get("bandstructure_mode", False), compress_bs=1) # assimilate (i.e., parse) task_doc = drone.assimilate(calc_dir) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) # get the database connection db_file = env_chk(self.get('db_file'), fw_spec) # db insertion or taskdoc dump if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = VaspCalcDb.from_db_file(db_file, admin=True) t_id = mmdb.insert_task(task_doc, parse_dos=self.get("parse_dos", False), parse_bs=bool( self.get("bandstructure_mode", False))) logger.info("Finished parsing with task_id: {}".format(t_id)) defuse_children = False if task_doc["state"] != "successful": if self.get("defuse_unsuccessful", DEFUSE_UNSUCCESSFUL) is True: defuse_children = True elif self.get("defuse_unsuccessful", DEFUSE_UNSUCCESSFUL).lower() \ == "fizzle": raise RuntimeError( "VaspToDb indicates that job is not successful " "(perhaps your job did not converge within the " "limit of electronic/ionic iterations)!") return FWAction(stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=defuse_children)
def run_task(self, fw_spec): files_to_copy = [ "POSCAR-unitcell", "INCAR", "vasprun.xml", "FORCE_CONSTANTS", "band.yaml" ] path_dict = dict() calc_loc_orig = get_calc_loc("orig phonon band", fw_spec["calc_locs"]) path_dict["orig"] = calc_loc_orig["path"] calc_loc_minus = get_calc_loc("minus phonon band", fw_spec["calc_locs"]) path_dict["minus"] = calc_loc_minus["path"] calc_loc_plus = get_calc_loc("plus phonon band", fw_spec["calc_locs"]) path_dict["plus"] = calc_loc_plus["path"] curr_dir = os.getcwd() for key, path in path_dict.items(): new_dir = os.path.join(curr_dir, key) os.makedirs(new_dir) copy = CopyFiles(from_dir=path, to_dir=new_dir, files_to_copy=files_to_copy) copy.run_task(fw_spec) phonons = {} for vol in ("orig", "plus", "minus"): (Keylist, Coordslist, prims, transmat) = get_highsympath("%s/POSCAR-unitcell" % vol) phonon = phonopy.load( supercell_matrix=self.get("supercell"), primitive_matrix=transmat, unitcell_filename="%s/POSCAR-unitcell" % vol, calculator="vasp", is_nac=False, force_constants_filename="%s/FORCE_CONSTANTS" % vol) phonons[vol] = phonon gruneisen = PhonopyGruneisen(phonons["orig"], phonons["plus"], phonons["minus"]) bands = get_band_qpoints([np.array(Coordslist)], 51) gruneisen.set_band_structure(bands) gruneisen.write_yaml_band_structure()
def run_task(self, fw_spec): calc_loc = get_calc_loc( self["calc_loc"], fw_spec["calc_locs"]) if self.get("calc_loc") else {} exclude_files = self.get("exclude_files", []) self.setup_copy(self.get("calc_dir", None), filesystem=self.get("filesystem", None), exclude_files=exclude_files, from_path_dict=calc_loc) self.copy_files()
def test_cleanupfiles(self): fw1 = Firework([CreateFolder(folder_name="to_remove.relax0"), CreateFolder(folder_name="to_remove.relax1"), CreateFolder(folder_name="dont_remove.relax0"), CreateFolder(folder_name="shouldnt_touch"), DeleteFiles(files=["to_remove*", "dont_remove"]), PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([PassCalcLocs(name="fw2")], name="fw2", parents=fw1) wf = Workflow([fw1, fw2]) self.lp.add_wf(wf) rapidfire(self.lp) fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0]) calc_locs = fw2.spec["calc_locs"] self.assertTrue(os.path.exists(os.path.join(get_calc_loc("fw1", calc_locs)["path"], "dont_remove.relax0"))) self.assertTrue(os.path.exists(os.path.join(get_calc_loc("fw1", calc_locs)["path"], "shouldnt_touch"))) self.assertFalse(os.path.exists(os.path.join(get_calc_loc("fw1", calc_locs)["path"], "to_remove.relax0"))) self.assertFalse(os.path.exists(os.path.join(get_calc_loc("fw1", calc_locs)["path"], "to_remove.relax1")))
def test_passcalclocs(self): fw1 = Firework([PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([PassCalcLocs(name="fw2")], name="fw2", parents=fw1) fw3 = Firework([PassCalcLocs(name="fw3")], name="fw3", parents=fw2) wf = Workflow([fw1, fw2, fw3]) self.lp.add_wf(wf) rapidfire(self.lp) fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0]) fw3 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw3"})[0]) self.assertEqual(len(fw2.spec["calc_locs"]), 1) self.assertEqual(len(fw3.spec["calc_locs"]), 2) self.assertEqual(fw3.spec["calc_locs"][0]["name"], "fw1") self.assertEqual(fw3.spec["calc_locs"][1]["name"], "fw2") self.assertNotEqual(fw3.spec["calc_locs"][0]["path"], fw3.spec["calc_locs"][1]["path"]) calc_locs = fw3.spec["calc_locs"] self.assertEqual(get_calc_loc("fw1", calc_locs), calc_locs[0]) self.assertEqual(get_calc_loc("fw2", calc_locs), calc_locs[1]) self.assertEqual(get_calc_loc(True, calc_locs), calc_locs[1])
def run_task(self, fw_spec): calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] logger.info("PARSING DIRECTORY: {}".format(calc_dir)) db_file = env_chk(self.get('db_file'), fw_spec) cluster_dict = None tags = Tags.from_file(filename="feff.inp") if "RECIPROCAL" not in tags: cluster_dict = Atoms.cluster_from_file("feff.inp").as_dict() doc = { "input_parameters": tags.as_dict(), "cluster": cluster_dict, "structure": self["structure"].as_dict(), "absorbing_atom": self["absorbing_atom"], "spectrum_type": self["spectrum_type"], "spectrum": np.loadtxt(os.path.join(calc_dir, self["output_file"])).tolist(), "edge": self.get("edge", None), "metadata": self.get("metadata", None), "dir_name": os.path.abspath(os.getcwd()), "last_updated": datetime.utcnow() } if not db_file: with open("feff_task.json", "w") as f: f.write(json.dumps(doc, default=DATETIME_HANDLER)) else: db = FeffCalcDb.from_db_file(db_file, admin=True) db.insert(doc) logger.info("Finished parsing the spectrum") return FWAction(stored_data={"task_id": doc.get("task_id", None)})
def test_passcalclocs(self): fw1 = Firework([PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([PassCalcLocs(name="fw2")], name="fw2", parents=fw1) fw3 = Firework([PassCalcLocs(name="fw3")], name="fw3", parents=fw2) wf = Workflow([fw1, fw2, fw3]) self.lp.add_wf(wf) rapidfire(self.lp) fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0]) fw3 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw3"})[0]) self.assertEqual(len(fw2.spec["calc_locs"]), 1) self.assertEqual(len(fw3.spec["calc_locs"]), 2) self.assertEqual(fw3.spec["calc_locs"][0]["name"], "fw1") self.assertEqual(fw3.spec["calc_locs"][1]["name"], "fw2") self.assertNotEqual(fw3.spec["calc_locs"][0]["path"], fw3.spec["calc_locs"][1]["path"]) calc_locs = fw3.spec["calc_locs"] self.assertEqual(get_calc_loc("fw1", calc_locs), calc_locs[0]) self.assertEqual(get_calc_loc("fw2", calc_locs), calc_locs[1]) self.assertEqual(get_calc_loc(True, calc_locs), calc_locs[1])
def run_task(self, fw_spec): # get the directory that contains the QChem dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] input_file = self.get("input_file", "mol.qin") output_file = self.get("output_file", "mol.qout") multirun = self.get("multirun", False) # parse the QChem directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = QChemDrone(additional_fields=self.get("additional_fields")) # assimilate (i.e., parse) task_doc = drone.assimilate( path=calc_dir, input_file=input_file, output_file=output_file, multirun=multirun) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) # Update fw_spec with final/optimized structure update_spec = {} if task_doc.get("output").get("optimized_molecule"): update_spec["prev_calc_molecule"] = task_doc["output"][ "optimized_molecule"] # get the database connection db_file = env_chk(self.get("db_file"), fw_spec) # db insertion or taskdoc dump if not db_file: with open(os.path.join(calc_dir, "task.json"), "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = QChemCalcDb.from_db_file(db_file, admin=True) t_id = mmdb.insert(task_doc) logger.info("Finished parsing with task_id: {}".format(t_id)) return FWAction( stored_data={"task_id": task_doc.get("task_id", None)}, update_spec=update_spec)
def test_getinterpolatedposcar(self): nimages = 5 this_image = 1 autosort_tol = 0.5 fw1 = Firework([CopyVaspOutputs(calc_dir=self.static_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([CopyVaspOutputs(calc_dir=self.opt_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw2")], name="fw2") fw3 = Firework([GetInterpolatedPOSCAR(start="fw1", end="fw2", this_image=this_image, nimages=nimages, autosort_tol=autosort_tol), PassCalcLocs(name="fw3")], name="fw3", parents=[fw1, fw2]) fw4 = Firework([PassCalcLocs(name="fw4")], name="fw4", parents=fw3) wf = Workflow([fw1, fw2, fw3, fw4]) self.lp.add_wf(wf) rapidfire(self.lp) fw4 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw4"})[0]) calc_locs = fw4.spec["calc_locs"] self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1")) struct_start = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0") struct_end = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1") struct_inter = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR") structs = struct_start.interpolate(struct_end, nimages, interpolate_lattices=True, autosort_tol=autosort_tol) # Check x of 1st site. self.assertAlmostEqual(structs[this_image][1].coords[0], struct_inter[1].coords[0]) # Check c lattice parameter self.assertAlmostEqual(structs[this_image].lattice.abc[0], struct_inter.lattice.abc[0])
def test_getinterpolatedposcar(self): nimages = 5 this_image = 1 autosort_tol = 0.5 fw1 = Firework([CopyVaspOutputs(calc_dir=self.static_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw1")], name="fw1") fw2 = Firework([CopyVaspOutputs(calc_dir=self.opt_outdir, contcar_to_poscar=False, additional_files=["CONTCAR"]), PassCalcLocs(name="fw2")], name="fw2") fw3 = Firework([GetInterpolatedPOSCAR(start="fw1", end="fw2", this_image=this_image, nimages=nimages, autosort_tol=autosort_tol), PassCalcLocs(name="fw3")], name="fw3", parents=[fw1, fw2]) fw4 = Firework([PassCalcLocs(name="fw4")], name="fw4", parents=fw3) wf = Workflow([fw1, fw2, fw3, fw4]) self.lp.add_wf(wf) rapidfire(self.lp) fw4 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw4"})[0]) calc_locs = fw4.spec["calc_locs"] self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0")) self.assertTrue(os.path.exists(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1")) struct_start = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_0") struct_end = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/interpolate/CONTCAR_1") struct_inter = Structure.from_file(get_calc_loc("fw3", calc_locs)["path"] + "/POSCAR") structs = struct_start.interpolate(struct_end, nimages, interpolate_lattices=True, autosort_tol=autosort_tol) # Check x of 1st site. self.assertAlmostEqual(structs[this_image][1].coords[0], struct_inter[1].coords[0]) # Check c lattice parameter self.assertAlmostEqual(structs[this_image].lattice.abc[0], struct_inter.lattice.abc[0])
def test_createfolder(self): folder_name = "test_folder" fw1 = Firework([CreateFolder(folder_name=folder_name, change_dir=False), PassCalcLocs(name="fw1")], name="fw3") fw2 = Firework([PassCalcLocs(name="fw2")], name="fw2", parents=fw1) wf = Workflow([fw1, fw2]) self.lp.add_wf(wf) rapidfire(self.lp) fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0]) calc_locs = fw2.spec["calc_locs"] self.assertTrue(os.path.exists(get_calc_loc("fw1", calc_locs)["path"] + "/" + folder_name))
def run_task(self, fw_spec): lammps_input = self["lammps_input"] diffusion_params = self.get("diffusion_params", {}) # get the directory that contains the LAMMPS dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) d = {} d["dir_name"] = os.path.abspath(os.getcwd()) d["last_updated"] = datetime.today() d["input"] = lammps_input.as_dict() log_file = lammps_input.config_dict["log"] if isinstance(lammps_input.config_dict["dump"], list): dump_file = lammps_input.config_dict["dump"][0].split()[4] else: dump_file = lammps_input.config_dict["dump"].split()[4] is_forcefield = hasattr(lammps_input.lammps_data, "bonds_data") lammpsrun = LammpsRun(lammps_input.data_filename, dump_file, log_file, is_forcefield=is_forcefield) d["natoms"] = lammpsrun.natoms d["nmols"] = lammpsrun.nmols d["box_lengths"] = lammpsrun.box_lengths d["mol_masses"] = lammpsrun.mol_masses d["mol_config"] = lammpsrun.mol_config if diffusion_params: diffusion_analyzer = lammpsrun.get_diffusion_analyzer(**diffusion_params) d["analysis"]["diffusion"] = diffusion_analyzer.get_summary_dict() db_file = env_chk(self.get('db_file'), fw_spec) # db insertion if not db_file: with open("task.json", "w") as f: f.write(json.dumps(d, default=DATETIME_HANDLER)) else: mmdb = LammpsCalcDb.from_db_file(db_file) # insert the task document t_id = mmdb.insert(d) logger.info("Finished parsing with task_id: {}".format(t_id)) return FWAction(stored_data={"task_id": d.get("task_id", None)})
def run_task(self, fw_spec): # get the directory that contains the LAMMPS run parse. calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the directory logger.info(f"PARSING DIRECTORY: {calc_dir}") drone = LammpsDrone( additional_fields=self.get("additional_fields"), diffusion_params=self.get("diffusion_params", None), ) task_doc = drone.assimilate( calc_dir, input_filename=self["input_filename"], log_filename=self.get("log_filename", "log.lammps"), is_forcefield=self.get("is_forcefield", False), data_filename=self.get("data_filename", None), dump_files=self.get("dump_filenames", None), ) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) db_file = env_chk(self.get("db_file"), fw_spec) # db insertion if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = LammpsCalcDb.from_db_file(db_file) # insert the task document t_id = mmdb.insert(task_doc) logger.info(f"Finished parsing with task_id: {t_id}") return FWAction(stored_data={"task_id": task_doc.get("task_id", None)})
def test_createfolder(self): folder_name = "test_folder" fw1 = Firework([ CreateFolder(folder_name=folder_name, change_dir=False), PassCalcLocs(name="fw1") ], name="fw3") fw2 = Firework([PassCalcLocs(name="fw2")], name="fw2", parents=fw1) wf = Workflow([fw1, fw2]) self.lp.add_wf(wf) rapidfire(self.lp) fw2 = self.lp.get_fw_by_id(self.lp.get_fw_ids({"name": "fw2"})[0]) calc_locs = fw2.spec["calc_locs"] self.assertTrue( os.path.exists( get_calc_loc("fw1", calc_locs)["path"] + "/" + folder_name))
def run_task(self, fw_spec): calc_loc = get_calc_loc( self["calc_loc"], fw_spec["calc_locs"]) if self.get("calc_loc") else {} filepath = calc_loc['path'] C = Electron() C.Get_bandstru(filepath) if self["bnd_name"] == "CBM": coord = C.engband.get_cbm()['kpoint'].frac_coords bnd_num = np.min(C.engband.get_cbm()['band_index'][Spin.up]) + 1 elif self["bnd_name"] == "VBM": coord = C.engband.get_vbm()['kpoint'].frac_coords bnd_num = np.max(C.engband.get_vbm()['band_index'][Spin.up]) + 1 elif self["bnd_name"] == "CSB": C.Get_SB() if hasattr(C, 'CSB'): coord = C.engband.kpoints[C.CSB.pos["kptindex"]].frac_coords bnd_num = np.min( C.engband.get_cbm()['band_index'][Spin.up]) + 1 else: return FWAction(exit=True) elif self["bnd_name"] == "VSB": C.Get_SB() if hasattr(C, 'VSB'): coord = C.engband.kpoints[C.VSB.pos["kptindex"]].frac_coords bnd_num = np.max( C.engband.get_vbm()['band_index'][Spin.up]) + 1 else: return FWAction(exit=True) else: raise ValueError("Must specify bnd_name") lattice = C.engband.structure.lattice.matrix Write_INPCAR(coord, self["step_size"], bnd_num, "V", lattice) EMC = EffectMass() inpcar_fh = open('INPCAR', 'r') (kpt, stepsize, band, prg, basis) = EMC.parse_inpcar(inpcar_fh) EMC.get_kpointsfile(kpt, stepsize, prg, basis)
def run_task(self, fw_spec): # get the directory that contains the LAMMPS run parse. calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = LammpsDrone(additional_fields=self.get("additional_fields"), diffusion_params=self.get("diffusion_params", None)) task_doc = drone.assimilate(calc_dir, input_filename=self["input_filename"], log_filename=self.get("log_filename", "log.lammps"), is_forcefield=self.get("is_forcefield", False), data_filename=self.get("data_filename", None), dump_files=self.get("dump_filenames", None)) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) db_file = env_chk(self.get('db_file'), fw_spec) # db insertion if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = LammpsCalcDb.from_db_file(db_file) # insert the task document t_id = mmdb.insert(task_doc) logger.info("Finished parsing with task_id: {}".format(t_id)) return FWAction(stored_data={"task_id": task_doc.get("task_id", None)})
def run_task(self, fw_spec): calc_loc = (get_calc_loc(self["calc_loc"], fw_spec["calc_locs"]) if self.get("calc_loc") else {}) # determine what files need to be copied files_to_copy = None if "$ALL" not in self.get("additional_files", []): files_to_copy = [ "INCAR", "POSCAR", "KPOINTS", "POTCAR", "OUTCAR", "vasprun.xml", ] if self.get("additional_files"): files_to_copy.extend(self["additional_files"]) if self.get("potcar_spec", False): files_to_copy.remove("POTCAR") files_to_copy.append("POTCAR.spec") # decide between poscar and contcar contcar_to_poscar = self.get("contcar_to_poscar", True) if contcar_to_poscar and "CONTCAR" not in files_to_copy: files_to_copy.append("CONTCAR") files_to_copy = [f for f in files_to_copy if f != "POSCAR"] # remove POSCAR # setup the copy self.setup_copy( self.get("calc_dir", None), filesystem=self.get("filesystem", None), files_to_copy=files_to_copy, from_path_dict=calc_loc, ) # do the copying self.copy_files()
def run_task(self, fw_spec): calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] logger.info("PARSING DIRECTORY: {}".format(calc_dir)) db_file = env_chk(self.get('db_file'), fw_spec) cluster_dict = None tags = Tags.from_file(filename="feff.inp") if "RECIPROCAL" not in tags: cluster_dict = Atoms.cluster_from_file("feff.inp").as_dict() doc = {"input_parameters": tags.as_dict(), "cluster": cluster_dict, "structure": self["structure"].as_dict(), "absorbing_atom": self["absorbing_atom"], "spectrum_type": self["spectrum_type"], "spectrum": np.loadtxt(os.path.join(calc_dir, self["output_file"])).tolist(), "edge": self.get("edge", None), "metadata": self.get("metadata", None), "dir_name": os.path.abspath(os.getcwd()), "last_updated": datetime.utcnow()} if not db_file: with open("feff_task.json", "w") as f: f.write(json.dumps(doc, default=DATETIME_HANDLER)) else: db = FeffCalcDb.from_db_file(db_file, admin=True) db.insert(doc) logger.info("Finished parsing the spectrum") return FWAction(stored_data={"task_id": doc.get("task_id", None)})
def run_task(self, fw_spec): # get the directory that contains the VASP dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the VASP directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = VaspDrone(additional_fields=self.get("additional_fields"), parse_dos=self.get("parse_dos", False), bandstructure_mode=self.get("bandstructure_mode", False), parse_chgcar=self.get("parse_chgcar", False), parse_aeccar=self.get("parse_aeccar", False)) # assimilate (i.e., parse) task_doc = drone.assimilate(calc_dir) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) # get the database connection db_file = env_chk(self.get('db_file'), fw_spec) # db insertion or taskdoc dump if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = VaspCalcDb.from_db_file(db_file, admin=True) t_id = mmdb.insert_task( task_doc, use_gridfs=self.get("parse_dos", False) or bool(self.get("bandstructure_mode", False)) or self.get("parse_chgcar", False) or self.get("parse_aeccar", False)) logger.info("Finished parsing with task_id: {}".format(t_id)) defuse_children = False if task_doc["state"] != "successful": defuse_unsuccessful = self.get("defuse_unsuccessful", DEFUSE_UNSUCCESSFUL) if defuse_unsuccessful is True: defuse_children = True elif defuse_unsuccessful is False: pass elif defuse_unsuccessful == "fizzle": raise RuntimeError( "VaspToDb indicates that job is not successful " "(perhaps your job did not converge within the " "limit of electronic/ionic iterations)!") else: raise RuntimeError("Unknown option for defuse_unsuccessful: " "{}".format(defuse_unsuccessful)) task_fields_to_push = self.get("task_fields_to_push", None) update_spec = {} if task_fields_to_push: if isinstance(task_fields_to_push, dict): for key, path_in_task_doc in task_fields_to_push.items(): if has(task_doc, path_in_task_doc): update_spec[key] = get(task_doc, path_in_task_doc) else: logger.warn( "Could not find {} in task document. Unable to push to next firetask/firework" .format(path_in_task_doc)) else: raise RuntimeError( "Inappropriate type {} for task_fields_to_push. It must be a " "dictionary of format: {key: path} where key refers to a field " "in the spec and path is a full mongo-style path to a " "field in the task document".format( type(task_fields_to_push))) return FWAction(stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=defuse_children, update_spec=update_spec)
def run_task(self, fw_spec): # get the directory that contains the QChem dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] input_file = self.get("input_file", "mol.qin") output_file = self.get("output_file", "mol.qout") multirun = self.get("multirun", False) # parse the QChem directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = QChemDrone(additional_fields=self.get("additional_fields")) # assimilate (i.e., parse) task_doc = drone.assimilate(path=calc_dir, input_file=input_file, output_file=output_file, multirun=multirun) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) # Update fw_spec with final/optimized structure update_spec = {} if task_doc.get("output").get("optimized_molecule"): update_spec["prev_calc_molecule"] = task_doc["output"][ "optimized_molecule"] # get the database connection db_file = env_chk(self.get("db_file"), fw_spec) # db insertion or taskdoc dump if not db_file: with open(os.path.join(calc_dir, "task.json"), "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = QChemCalcDb.from_db_file(db_file, admin=True) t_id = mmdb.insert(task_doc) logger.info("Finished parsing with task_id: {}".format(t_id)) defuse_children = False if task_doc["state"] != "successful": defuse_unsuccessful = self.get("defuse_unsuccessful", DEFUSE_UNSUCCESSFUL) if defuse_unsuccessful is True: defuse_children = True elif defuse_unsuccessful is False: pass elif defuse_unsuccessful == "fizzle": raise RuntimeError( "QChemToDb indicates that job is not successful " "(perhaps your job did not converge within the " "limit of electronic iterations)!") else: raise RuntimeError("Unknown option for defuse_unsuccessful: " "{}".format(defuse_unsuccessful)) return FWAction(stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=defuse_children, update_spec=update_spec)
def run_task(self, fw_spec): # get the directory that contains the VASP dir to parse calc_dir = os.getcwd() if "calc_dir" in self: calc_dir = self["calc_dir"] elif self.get("calc_loc"): calc_dir = get_calc_loc(self["calc_loc"], fw_spec["calc_locs"])["path"] # parse the VASP directory logger.info("PARSING DIRECTORY: {}".format(calc_dir)) drone = VaspDrone(additional_fields=self.get("additional_fields"), parse_dos=self.get("parse_dos", False), bandstructure_mode=self.get("bandstructure_mode", False), parse_chgcar=self.get("parse_chgcar", False), parse_aeccar=self.get("parse_aeccar", False)) # assimilate (i.e., parse) task_doc = drone.assimilate(calc_dir) # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) # get the database connection db_file = env_chk(self.get('db_file'), fw_spec) # db insertion or taskdoc dump if not db_file: with open("task.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: mmdb = VaspCalcDb.from_db_file(db_file, admin=True) t_id = mmdb.insert_task( task_doc, use_gridfs=self.get("parse_dos", False) or bool(self.get("bandstructure_mode", False)) or self.get("parse_chgcar", False) or self.get("parse_aeccar", False)) logger.info("Finished parsing with task_id: {}".format(t_id)) defuse_children = False if task_doc["state"] != "successful": defuse_unsuccessful = self.get("defuse_unsuccessful", DEFUSE_UNSUCCESSFUL) if defuse_unsuccessful is True: defuse_children = True elif defuse_unsuccessful is False: pass elif defuse_unsuccessful == "fizzle": raise RuntimeError( "VaspToDb indicates that job is not successful " "(perhaps your job did not converge within the " "limit of electronic/ionic iterations)!") else: raise RuntimeError("Unknown option for defuse_unsuccessful: " "{}".format(defuse_unsuccessful)) task_fields_to_push = self.get("task_fields_to_push", None) update_spec = {} if task_fields_to_push: if isinstance(task_fields_to_push, dict): for key, path_in_task_doc in task_fields_to_push.items(): if has(task_doc, path_in_task_doc): update_spec[key] = get(task_doc, path_in_task_doc) else: logger.warn("Could not find {} in task document. Unable to push to next firetask/firework".format(path_in_task_doc)) else: raise RuntimeError("Inappropriate type {} for task_fields_to_push. It must be a " "dictionary of format: {key: path} where key refers to a field " "in the spec and path is a full mongo-style path to a " "field in the task document".format(type(task_fields_to_push))) return FWAction(stored_data={"task_id": task_doc.get("task_id", None)}, defuse_children=defuse_children, update_spec=update_spec)
def run_task(self, fw_spec): vasp_calc_dir = self.get("calc_dir", None) vasp_calc_loc = ( get_calc_loc(self["calc_loc"], fw_spec["calc_locs"]) if self.get("calc_loc") else {} ) # get the directory that contains the Lobster dir to parse current_dir = os.getcwd() # parse the Lobster directory logger.info("PARSING DIRECTORY: {}".format(current_dir)) task_doc = {} struct = Structure.from_file(self._find_gz_file("POSCAR")) Lobsterout_here = Lobsterout(self._find_gz_file("lobsterout")) task_doc["output"] = Lobsterout_here.get_doc() Lobsterin_here = Lobsterin.from_file(self._find_gz_file("lobsterin")) task_doc["input"] = Lobsterin_here try: Lobsterin_orig = Lobsterin.from_file(self._find_gz_file("lobsterin.orig")) task_doc["orig_input"] = Lobsterin_orig except ValueError: pass # save custodian details if os.path.exists("custodian.json"): task_doc["custodian"] = loadfn("custodian.json") additional_fields = self.get("additional_fields", {}) if additional_fields: task_doc.update(additional_fields) task_doc.update(get_meta_from_structure(struct)) if vasp_calc_dir != None: task_doc["vasp_dir_name"] = vasp_calc_dir else: task_doc["vasp_dir_name"] = vasp_calc_loc["path"] task_doc["dir_name"] = current_dir # Check for additional keys to set based on the fw_spec if self.get("fw_spec_field"): task_doc.update(fw_spec[self.get("fw_spec_field")]) task_doc["state"] = "successful" task_doc = jsanitize(task_doc) # get the database connection db_file = env_chk(self.get("db_file"), fw_spec) # db insertion or taskdoc dump if not db_file: with open("task_lobster.json", "w") as f: f.write(json.dumps(task_doc, default=DATETIME_HANDLER)) else: db = VaspCalcDb.from_db_file(db_file, admin=True) db.collection = db.db["lobster"] additional_outputs = self.get("additional_outputs", None) if additional_outputs: for filename in additional_outputs: fs_id = None if os.path.isfile(filename): fs_id = put_file_in_gridfs( filename, db, collection_name="lobster_files", compress=True ) elif os.path.isfile(filename + ".gz"): fs_id = put_file_in_gridfs( filename + ".gz", db, collection_name="lobster_files", compress=False, compression_type="zlib", ) if fs_id: key_name = filename.split(".")[0].lower() + "_id" task_doc[key_name] = fs_id db.insert(task_doc) return FWAction()