def main(): parser = ArgumentParser() parser.add_argument("file1", help="logfile containing the supermolecule") parser.add_argument("file2", help="logfile containing the first fragment") parser.add_argument("file3", help="logfile containing the second fragment") args = parser.parse_args() loglevel = logging.ERROR data1 = ccread(args.file1, loglevel=loglevel) data2 = ccread(args.file2, loglevel=loglevel) data3 = ccread(args.file3, loglevel=loglevel) fa = CDA(data1, None, loglevel) retval = fa.calculate([data2, data3]) if retval: print("Charge decomposition analysis of {}\n".format(args.file1)) if len(data1.homos) == 2: print("ALPHA SPIN:") print("===========") print(" MO# d b r s") print("-------------------------------------") for spin in range(len(data1.homos)): if spin == 1: print("\nBETA SPIN:") print("==========") for i in range(len(fa.donations[spin])): print("%4i: %7.3f %7.3f %7.3f %7.3f" % \ (i + 1, fa.donations[spin][i], fa.bdonations[spin][i], fa.repulsions[spin][i], fa.residuals[spin][i])) if i == data1.homos[spin]: print("------ H**O - LUMO gap ------") print("-------------------------------------") print(" T: %7.3f %7.3f %7.3f %7.3f" % \ (fa.donations[spin].sum(), fa.bdonations[spin].sum(), fa.repulsions[spin].sum(), fa.residuals[spin].sum()))
def __init__(self, output_path, cluster_label, partition_label, md_temp, grad_e_unit, grad_r_unit, md_iter=0, e_unit='kcal/mol', r_unit='Angstrom', theory='unknown'): self.output_path = output_path self.output_name = self.output_path.split('/')[-1].split('.')[0] self.cluster_label = cluster_label self.partition_label = partition_label self.partition_size = int(len(self.partition_label)) self.md_temp = md_temp self.md_iter = md_iter self.e_unit = e_unit self.r_unit = r_unit self.theory = theory self.cclib_data = ccread(self.output_path) self._get_gdml_data() self.E = convertor(self.E, 'eV', self.e_unit) self.G = convert_forces(self.G, grad_e_unit, grad_r_unit, self.e_unit, self.r_unit) self.F = np.negative(self.G)
def test_obtain_geometries(self): vibrations = self.vibrational_analysis.parse_vibrations() symbol_dict = { 17: "Cl", 9: "F", 8: "O", 7: "N", 6: "C", 1: "H", } atoms = [] parser = ccread(self.vibrational_analysis.log_file) for atom_num, coords in zip(parser.atomnos, parser.atomcoords[-1]): atoms.append(Atom(symbol=symbol_dict[atom_num], position=coords)) test_pre_geometry = Atoms(atoms) test_post_geometry = test_pre_geometry.copy() for vib, displacement in vibrations: if vib < 0: test_post_geometry.arrays["positions"] -= displacement pre_geometry, post_geometry = self.vibrational_analysis.obtain_geometries( ) for i, positions in enumerate(test_pre_geometry.arrays["positions"]): for j, x in enumerate(positions): self.assertEqual(x, pre_geometry.arrays["positions"][i][j]) for i, positions in enumerate(test_post_geometry.arrays["positions"]): for j, x in enumerate(positions): self.assertEqual(x, post_geometry.arrays["positions"][i][j])
def verify_rotor(self, path): "This could be extrapolated to the general calculators class...?" parser = ccread(path) smallest = max(parser.scfenergies) + 1 results = [] for i in parser.scfenergies: if i < smallest: smallest = i else: results.append(smallest) smallest = max(parser.scfenergies) + 1 # adding the last one which should be a converged geometry results.append(smallest) if ((results[0] - results[-1] < 1e-5) and # The energy difference is less than 1e-5 eV (((parser.converged_geometries[0] - parser.converged_geometries[i]) **2).mean() < 0.01) ): # the RMSE between initial and final geometries is less than 1% return True else: return False
def __cclibparse(self): self.logger.info("Using cclib to parse input; it may take a while...") zmat = ZMatrix() try: fh = ccread(self.fn) except NameError: return None except IndexError: return None except AttributeError: self.logger.warn( "There is a bug in cclib preventing it from functionging with pybel." ) return None if not fh: return None try: for i in range(0, len(fh.atomnos)): zmat += Atom(fh.atomnos[i], fh.atomcoords[-1][i]) except AttributeError as msg: self.logger.error("Error parsing input %s" % str(msg)) return None # if self.opts.project: # zmat.toZaxis() # elif self.opts.sortaxis: # zmat.sort(self.opts.sortaxis) self.zmat = zmat self.ccparsed = fh self.logger.info('Found: %s' % self.zmat.get_chemical_formula()) if hasattr(fh, 'homos') and hasattr(fh, 'moenergies'): self.logger.info('H**O/LUMO (eV): %0.4f/%0.4f' % (fh.moenergies[0][fh.homos[0]], fh.moenergies[0][fh.homos[0] + 1])) return True
def parse_file(file_path): logfile_type = ccopen(file_path) if logfile_type is not None: try: parsed_data = ccread(file_path) parsed_data.listify() res = {"success": True, "attributes": {}} for x in parsed_data._attributes: try: val = getattr(parsed_data, x) res["attributes"][x] = val except Exception as e: pass if ob_import is True: inchi = get_InChI(res["attributes"]) if inchi is not None: res["InChI"] = inchi except: res = {"success": False} else: res = {"success": False} if res["success"]: make_chemical_formula(res) res["xyz_data"] = XYZ_data(res["attributes"]) return res
def test_symms_benzene(self): """ Do the carbons in benzene ring get assigned with roughly equal charges? Discrepancy between carbons do exist in this test due to grid coarseness and limited size of the grid. One can do a larger test, for example, using 160x170x80 size grid to obtain [5.63728706, 5.89862956, 5.73956182, 5.63728706, 5.73963179, 5.8996759]. In comparison, `bader`, which is implemented by Henkelman group which proposed the algorithm, reports [5.947370, 6.032509, 5.873431, 5.947370, 5.873431, 6.033485]. `bader` uses fuzzy boundaries which result in slightly higher carbon charges. """ benzenepath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "benzene.out") data = ccread(benzenepath) vol = volume.read_from_cube( os.path.join(os.path.dirname(os.path.realpath(__file__)), "benzene.cube")) assert_allclose(vol.origin, numpy.array([-4.1805, -4.498006, -2.116709]), atol=1e-3) analysis = Bader(data, vol) analysis.calculate() self.assertAlmostEqual(analysis.fragcharges[0:6].max(), analysis.fragcharges[0:6].min(), delta=0.5)
def _cclibparse(self): self.logger.info("Using cclib to parse input; it may take a while...") zmat = ZMatrix() try: fh = ccread(self.fn) except NameError: return None except IndexError: return None if not fh: return None try: for i in range(0, len(fh.atomnos)): zmat += Atom(fh.atomnos[i], fh.atomcoords[-1][i]) except AttributeError as msg: self.logger.error("Error parsing input %s" % str(msg)) return None # if self.opts.project: # zmat.toZaxis() # elif self.opts.sortaxis: # zmat.sort(self.opts.sortaxis) self.zmat = zmat self.ccparsed = fh self.logger.info('Found: %s' % self.zmat.get_chemical_formula()) if hasattr(fh, 'homos') and hasattr(fh, 'moenergies'): self.logger.info('H**O/LUMO (eV): %0.4f/%0.4f' % (fh.moenergies[0][fh.homos[0]],fh.moenergies[0][fh.homos[0]+1]) ) return True
def parse(self, molecule_name=None): if molecule_name == None: self.data, self.logfile = getdatafile(Psi4, "basicPsi4-1.2.1", ["water_mp2.out"]) else: self.data = ccread( os.path.join(os.path.dirname(os.path.realpath(__file__)), molecule_name + ".out"))
def ccmae(): filename = filedialog.askopenfilename() data = ccread(filename) all = sortmols(data) la = [] lb = [] for s in all: la.append(mae(s, gla)) lb.append(mae(s, glb)) return la, lb
def ccpmae(): filename = filedialog.askopenfilename() data = ccread(filename) all = sortmols(data) x = 0 for s in all: print( str(x) + ": \n\tLa: " + str(mae(s, gla)) + "\n\tLb: " + str(mae(s, glb))) x += 1
def test_chgsum_hf(self): """Does the sum of charges equate to the number of electrons for a simple molecule?""" hfpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "hf.out") data = ccread(hfpath) vol = volume.Volume((-6, -6, -6), (6, 6, 6), (0.2, 0.2, 0.2)) analysis = Bader(data, vol) analysis.calculate() self.assertAlmostEqual(numpy.sum(analysis.fragcharges), 10, delta=1)
def atom_types(input_file): """ Return a list of all atom types in the right order. The list will look like: ['C', 'H', 'H', 'H', 'C', 'N', 'P'] """ file = ccread(input_file) atoms = file.atomnos.tolist() periodic_table = PeriodicTable() atom_list = [periodic_table.element[i] for i in atoms] return atom_list
def list_elements(input_file): """ Return a list of all unique elements used in the computation. The list will look like: ['C', 'H', 'N', 'P'] """ file = ccread(input_file) atoms = dict.fromkeys(file.atomnos.tolist()) periodic_table = PeriodicTable() atom_list = [periodic_table.element[i] for i in atoms] return atom_list
def test_chgsum_h2(self): """ Are Hirshfeld charges for hydrogen atoms in nonpolar H2 small as expected? """ h2path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "h2.out") data = ccread(h2path) vol = volume.Volume((-3, -3, -3), (3, 3, 3), (0.1, 0.1, 0.1)) analysis = Hirshfeld(data, vol, os.path.dirname(os.path.realpath(__file__))) analysis.calculate() self.assertAlmostEqual(numpy.sum(analysis.fragcharges), 0, delta=1e-2) self.assertAlmostEqual(analysis.fragcharges[0], analysis.fragcharges[1], delta=1e-6)
def IRC_coordinates_from_input(input_file): """Return a table of coordinates with all last geometries (converged or not) from an IRC.""" file = ccread(input_file, optdone_as_list=True) new_indexes = [ x for x, y in enumerate(file.optstatus) if y & file.OPT_NEW > 0 ] # new_indexes finishes with 0, so has to finish with -1 for the last index. last_indexes = [ x - 1 for x in new_indexes[1:len(new_indexes)] + [new_indexes[0]] ] # file.atomcoords is an ndarray, so can be accessed with a list! coordinates = file.atomcoords[last_indexes] return coordinates.tolist()
def get_coordinates(self): """Extract coordinates from output file.""" # Log start logging.info("Extracting coordinates for job %s", str(self.job_id)) # Get into working directory os.chdir(self.path) # Parse file with cclib data = ccread(self.filenames["output"], loglevel=logging.WARNING) # Return the first coordinates, since it is a single point return data.atomcoords[0]
def parse_vibrations(self): """ This method obtains the vibrations from the log file of interest using cclib. It then creates a zipped list with the vibrational frequencies and their corresponding displacements. """ assert os.path.exists(self.log_file) log_file_info = ccread(self.log_file) self.vibrations = zip(log_file_info.vibfreqs, log_file_info.vibdisps) return self.vibrations
def get_energy(self): """Extract energy from output file.""" # Log start logger = logging.getLogger() logger.info("Extracting energy " + str(self.job_id)) # Get into working directory os.chdir(self.path) # Parse file with cclib data = ccread(self.output_filename) # Return the energy return data.scfenergies[0]
def get_coordinates(self): """Extract coordinates from output file.""" # Log start logger = logging.getLogger() logger.info("Extracting coordinates " + str(self.job_id)) # Get into working directory os.chdir(self.path) # Parse file with cclib data = ccread(self.output_filename) # Return the first coordinates, since it is a single point return data.atomcoords[0]
def get_qmdata(self, file_path=None): "A helper function to fill in the qmdata using CCLib" parser = ccread(file_path) atoms = read_gaussian_out(file_path) self.groundStateDegeneracy = parser.mult self.atomNumbers = atoms.numbers self.atomCoords = (atoms.arrays["positions"], "angstrom") self.stericEnergy = None # Need to fix this self.molecularMass = (parser.atommasses.sum(), "amu") self.energy = (atoms.get_potential_energy(), "eV/molecule") self.atomicNumbers = parser.atomnos self.rotationalConstants = ([], "cm^-1") # Need to fix this self.frequencies = (parser.vibfreqs, "cm^-1") self.source = None self.method = parser.metadata["functional"]
def get_qmdata(self, file_path=None): "A helper function to fill in the qmdata using CCLib" parser = ccread(file_path) self.groundStateDegeneracy = parser.mult self.atomNumbers = parser.atomnos self.numberOfAtoms = len(parser.atomnos) self.atomCoords = (parser.atomcoords[-1], "angstrom") self.stericEnergy = None # Need to fix this self.molecularMass = (parser.atommasses.sum(), "amu") self.energy = (parser.scfenergies[-1], "eV/molecule") self.atomicNumbers = parser.atomnos self.rotationalConstants = ([], "cm^-1") # Need to fix this self.frequencies = (parser.vibfreqs, "cm^-1") self.source = "AutoTST" self.method = parser.metadata["functional"]
def get_qmdata(self, file_path=None): "A helper function to fill in the qmdata using CCLib" parser = ccread(file_path, loglevel=logging.ERROR) self.ground_state_degeneracy = parser.mult self.atom_numbers = parser.atomnos self.number_of_atoms = len(parser.atomnos) self.atom_coords = (parser.atomcoords[-1], "angstrom") self.steric_energy = None # Need to fix this self.molecular_mass = (parser.atommasses.sum(), "amu") self.energy = (parser.scfenergies[-1], "eV/molecule") self.atomic_numbers = parser.atomnos self.rotational_constants = ([], "cm^-1") # Need to fix this self.frequencies = (parser.vibfreqs, "cm^-1") self.source = "AutoTST" self.method = parser.metadata["functional"]
def obtain_geometries(self): """ This method obtains the previbrational geometry (the geometry returned by a quantum optimizer), and the postvibrational geometry. Variables: - ts (TS): A transition state object of interest - vibrations (list): a list of the vibrations and their corresponding displacements in XYZ coords. Often from `parse_vibrations` Returns: - pre_geometry (ASEAtoms): an ASEAtoms object containing the geometry before applying the vibrations - post_geometry (ASEAtoms): an ASEAtoms object containing the geometry after applying the vibrations """ assert isinstance(self.ts, TS) symbol_dict = { 17: "Cl", 9: "F", 8: "O", 7: "N", 6: "C", 1: "H", } atoms = [] parser = ccread(self.log_file, loglevel=logging.ERROR) for atom_num, coords in zip(parser.atomnos, parser.atomcoords[-1]): atoms.append(Atom(symbol=symbol_dict[atom_num], position=coords)) self.ts._ase_molecule = Atoms(atoms) self.ts.update_coords_from("ase") self.pre_geometry = self.ts.ase_molecule.copy() self.post_geometry = self.ts.ase_molecule.copy() for vib, displacements in self.vibrations: if vib < 0: # Finding the imaginary frequency self.post_geometry.arrays["positions"] -= displacements return self.pre_geometry, self.post_geometry
def test_chgsum_co(self): """ Are Hirshfeld charges for carbon monoxide reported as expected? Note. Table 1 in doi:10.1007/BF01113058 reports Hirshfeld charge for Carbon atom as 0.06 when STO-3G basis set was used and 0.14 when 6-311G** basis set was used. Here, Psi4 calculation was done using STO-3G. """ copath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "co.out") data = ccread(copath) vol = volume.read_from_cube( os.path.join(os.path.dirname(os.path.realpath(__file__)), "co.cube") ) analysis = Hirshfeld(data, vol, os.path.dirname(os.path.realpath(__file__))) analysis.calculate() self.assertAlmostEqual(numpy.sum(analysis.fragcharges), 0, delta=1e-2) assert_allclose(analysis.fragcharges, [ 0.10590126, -0.11277786], atol=1e-3)
def gen_spectra(file_name, name, units='eV', thresh=9): data = ccread(file_name) energies, intensities = convertor(data.etenergies, 'cm-1', units), data.etoscs #intensities = abs(intensities) #print(len(energies)) #energies, intensities = energies[intensities > 10**-thresh], intensities[intensities > 10**-thresh] #print(len(energies)) #energies, intensities = energies[intensities > 10**-8], intensities[intensities > 10**-8] #print(len(energies)) #energies, intensities = energies[intensities > 10**-7], intensities[intensities > 10**-7] #print(len(energies)) #energies, intensities = energies[intensities > 10**-6], intensities[intensities > 10**-6] #print(len(energies)) #energies, intensities = energies[intensities > 10**-5], intensities[intensities > 10**-5] #print(len(energies)) #energies, intensities = energies[energies < 3*10**4], intensities[energies < 3*10**4] #print(len(energies)) s = Spectra(energies, intensities, name) return s
def read_log(self, file_path=None): """ A helper method that allows one to easily parse log files """ symbol_dict = { 35: "Br", 17: "Cl", 9: "F", 8: "O", 7: "N", 6: "C", 1: "H", } atoms = [] parser = ccread(file_path) for atom_num, coords in zip(parser.atomnos, parser.atomcoords[-1]): atoms.append(Atom(symbol=symbol_dict[atom_num], position=coords)) return Atoms(atoms)
def read_from(infile): """Read from a file""" try: data = ccread(infile) # Hack: cclib doesn't have an easy way to access atom names lines = data.writexyz().splitlines() except AttributeError as e: # Attempt to read as an XYZ file with open(infile) as f: lines = f.readlines() # Strip off length if provided if lines[0].strip().isdigit(): lines = lines[2:] geom = [] for line in lines: if line.strip() == '': continue atom, x, y, z = line.split()[:4] geom.append([atom, [float(x), float(y), float(z)]]) return Molecule(geom)
def gen_spectra(file_name, name, thresh=9): data = ccread(file_name) energies, intensities = convertor(data.etenergies, 'cm-1', 'eV'), data.etoscs #intensities = abs(intensities) #print(len(energies)) #energies, intensities = energies[intensities > 10**-thresh], intensities[intensities > 10**-thresh] #print(len(energies)) #energies, intensities = energies[intensities > 10**-8], intensities[intensities > 10**-8] #print(len(energies)) #energies, intensities = energies[intensities > 10**-7], intensities[intensities > 10**-7] #print(len(energies)) #energies, intensities = energies[intensities > 10**-6], intensities[intensities > 10**-6] #print(len(energies)) #energies, intensities = energies[intensities > 10**-5], intensities[intensities > 10**-5] #print(len(energies)) #energies, intensities = energies[energies < 3*10**4], intensities[energies < 3*10**4] #print(len(energies)) s = Spectra(energies, intensities, name) return s
def get_energies(self): """ Retrieve HF energies plus thermochemical corrections :return: """ # Log start logging.info("Extracting energies from %s", self.name) # Get into working directory os.chdir(self.path) # Parse file with cclib data = ccread(self.filenames["output"], loglevel=logging.WARNING) # Return the parsed energies as a dictionary energies = dict.fromkeys(["scfenergy", "enthalpy", "freeenergy"]) energies["scfenergy"] = data.scfenergies[-1] energies["enthalpy"] = data.enthalpy energies["freeenergy"] = data.freeenergy return energies
def parse_vibrations(self, log_file=None): """ This method obtains the vibrations from the log file of interest using cclib. It then creates a zipped list with the vibrational frequencies and their corresponding displacements. Variables: - log_file (str): the log file you want to obtain vibrations from. Often found from `get_log_file` Returns: - vibrations (list): a list of the vibrations and their corresponding displacements in XYZ coordinates """ if not log_file: log_file = self.log_file assert os.path.exists(log_file), "Log file provided does not exist" log_file_info = ccread(log_file) vibrations = list(zip(log_file_info.vibfreqs, log_file_info.vibdisps)) return vibrations
def ccget(): """Parse files with cclib based on command line arguments.""" # Parse the arguments and pass them to ccget, but print help information # and exit if it fails. try: optlist, arglist = getopt.getopt(sys.argv[1:], OPTS_SHORT, OPTS_LONG) except getopt.GetoptError: print(MSG_USAGE_LONG) sys.exit(1) future = False showattr = False cjsonfile = False multifile = False verbose = False full = False for opt, arg in optlist: if opt in ("-h", "--help"): print(MSG_USAGE_LONG) sys.exit() if opt in ("-l", "--list"): showattr = True if opt in ("-j", "--json"): cjsonfile = True if opt in ("-m", "--multi"): multifile = True if opt in ("-v", "--verbose"): verbose = True if opt in ("-u", "--future"): future = True if opt in ("-f", "--full"): full = True # Toggle full print behaviour for numpy arrays. if full: numpy.set_printoptions(threshold=numpy.nan) # We need at least one attribute and the filename, so two arguments, or # just one filename if we want to list attributes that can be extracted. # In multifile mode, we generally want at least two filenames, so the # expected number of arguments is a bit different. if not multifile: correct_number = (not showattr and len(arglist) > 1) or (showattr and len(arglist) > 0) else: correct_number = (not showattr and len(arglist) > 2) or (showattr and len(arglist) > 1) if not correct_number: print("The number of arguments does not seem to be correct.") print(MSG_USAGE) sys.exit(1) # Figure out which are the attribute names and which are the filenames or links. # Note that in Linux, the shell expands wild cards, but not so in Windows, # so try to do that here using glob. attrnames = [] filenames = [] for arg in arglist: if arg in ccData._attrlist: attrnames.append(arg) elif URL_PATTERN.match(arg) or os.path.isfile(arg): filenames.append(arg) else: wildcardmatches = glob.glob(arg) if wildcardmatches: filenames.extend(wildcardmatches) else: print("%s is neither a filename nor an attribute name." % arg) print(MSG_USAGE) sys.exit(1) # Since there is some ambiguity to the correct number of arguments, check # that there is at least one filename (or two in multifile mode), and also # at least one attribute to parse if the -l option was not passed. if len(filenames) == 0: print("No logfiles given") sys.exit(1) if multifile and len(filenames) == 1: print("Expecting at least two logfiles in multifile mode") sys.exit(1) if not showattr and len(attrnames) == 0: print("No attributes given") sys.exit(1) # This should be sufficient to correctly handle multiple files, that is to # run the loop below only once with all logfiles in the variable `filename`. # Although, perhaps it would be clearer to abstract the contents of the loop # into another function. if multifile: filenames = [filenames] # Now parse each file and print out the requested attributes. for filename in filenames: if multifile: name = ", ".join(filename[:-1]) + " and " + filename[-1] else: name = filename # The keyword dictionary are not used so much. but could be useful for # passing options downstream. For example, we might use --future for # triggering experimental or alternative behavior (as with optdone). kwargs = {} if verbose: kwargs['verbose'] = True kwargs['loglevel'] = logging.INFO else: kwargs['verbose'] = False kwargs['loglevel'] = logging.ERROR if future: kwargs['future'] = True if cjsonfile: kwargs['cjson'] = True print("Attempting to read %s" % name) data = ccread(filename, **kwargs) if data == None: print("Cannot figure out the format of '%s'" % name) print( "Report this to the cclib development team if you think it is an error." ) print("\n" + MSG_USAGE) sys.exit() if showattr: print("cclib can parse the following attributes from %s:" % name) if cjsonfile: for key in data: print(key) break for attr in data._attrlist: if hasattr(data, attr): print(" %s" % attr) else: invalid = False for attr in attrnames: if cjsonfile: if attr in data: print("%s:\n%s" % (attr, data[attr])) continue else: if hasattr(data, attr): print(attr) attr_val = getattr(data, attr) # List of attributes to be printed with new lines if attr in data._listsofarrays and full: for val in attr_val: print(val) else: print(attr_val) continue print("Could not parse %s from this file." % attr) invalid = True if invalid: print(MSG_USAGE_LONG)
def ccget(): """Parse files with cclib based on command line arguments.""" import argparse parser = argparse.ArgumentParser() parser.add_argument( "attribute_or_compchemlogfile", nargs="+", help="one or more attributes to be parsed from one ore more logfiles", ) group = parser.add_mutually_exclusive_group() group.add_argument( "--list", "-l", action="store_true", help="print a list of attributes available in each file", ) group.add_argument( "--json", "-j", action="store_true", help="the given logfile is in CJSON format", ) group.add_argument( "--multi", "-m", action="store_true", help="parse multiple input files as one input stream", ) parser.add_argument( "--verbose", "-v", action="store_true", help="more verbose parsing output (only errors by default)", ) parser.add_argument( "--future", "-u", action="store_true", help="use experimental features (currently optdone_as_list)", ) parser.add_argument( "--full", "-f", action="store_true", help="toggle full print behaviour for attributes", ) args = parser.parse_args() arglist = args.attribute_or_compchemlogfile showattr = args.list cjsonfile = args.json multifile = args.multi verbose = args.verbose future = args.future full = args.full # Toggle full print behaviour for numpy arrays. if full: numpy.set_printoptions(threshold=numpy.nan) # We need at least one attribute and the filename, so two arguments, or # just one filename if we want to list attributes that can be extracted. # In multifile mode, we generally want at least two filenames, so the # expected number of arguments is a bit different. if not multifile: correct_number = (not showattr and len(arglist) > 1) or (showattr and len(arglist) > 0) else: correct_number = (not showattr and len(arglist) > 2) or (showattr and len(arglist) > 1) if not correct_number: print("The number of arguments does not seem to be correct.") parser.print_usage() parser.exit(1) # Figure out which are the attribute names and which are the filenames or links. # Note that in Linux, the shell expands wild cards, but not so in Windows, # so try to do that here using glob. attrnames = [] filenames = [] for arg in arglist: if arg in ccData._attrlist: attrnames.append(arg) elif URL_PATTERN.match(arg) or os.path.isfile(arg): filenames.append(arg) else: wildcardmatches = glob.glob(arg) if wildcardmatches: filenames.extend(wildcardmatches) else: print("%s is neither a filename nor an attribute name." % arg) parser.print_usage() parser.exit(1) # Since there is some ambiguity to the correct number of arguments, check # that there is at least one filename (or two in multifile mode), and also # at least one attribute to parse if the -l option was not passed. if len(filenames) == 0: print("No logfiles given") parser.exit(1) if multifile and len(filenames) == 1: print("Expecting at least two logfiles in multifile mode") parser.exit(1) if not showattr and len(attrnames) == 0: print("No attributes given") parser.exit(1) # This should be sufficient to correctly handle multiple files, that is to # run the loop below only once with all logfiles in the variable `filename`. # Although, perhaps it would be clearer to abstract the contents of the loop # into another function. if multifile: filenames = [filenames] # Now parse each file and print out the requested attributes. for filename in filenames: if multifile: name = ", ".join(filename[:-1]) + " and " + filename[-1] else: name = filename # The keyword dictionary are not used so much. but could be useful for # passing options downstream. For example, we might use --future for # triggering experimental or alternative behavior (as with optdone). kwargs = {} if verbose: kwargs['verbose'] = True kwargs['loglevel'] = logging.INFO else: kwargs['verbose'] = False kwargs['loglevel'] = logging.ERROR if future: kwargs['future'] = True if cjsonfile: kwargs['cjson'] = True print("Attempting to read %s" % name) data = ccread(filename, **kwargs) if data is None: print("Cannot figure out the format of '%s'" % name) print("Report this to the cclib development team if you think it is an error.") print("\n" + parser.format_usage()) parser.exit(1) if showattr: print("cclib can parse the following attributes from %s:" % name) if cjsonfile: for key in data: print(key) break for attr in data._attrlist: if hasattr(data, attr): print(" %s" % attr) else: invalid = False for attr in attrnames: if cjsonfile: if attr in data: print("%s:\n%s" % (attr, data[attr])) continue else: if hasattr(data, attr): print(attr) attr_val = getattr(data, attr) # List of attributes to be printed with new lines if attr in data._listsofarrays and full: for val in attr_val: pprint(val) else: pprint(attr_val) continue print("Could not parse %s from this file." % attr) invalid = True if invalid: parser.print_help()
def ccget(): """Parse files with cclib based on command line arguments.""" # Parse the arguments and pass them to ccget, but print help information # and exit if it fails. try: optlist, arglist = getopt.getopt(sys.argv[1:], OPTS_SHORT, OPTS_LONG) except getopt.GetoptError: print(MSG_USAGE_LONG) sys.exit(1) future = False showattr = False cjsonfile = False multifile = False verbose = False full = False for opt, arg in optlist: if opt in ("-h", "--help"): print(MSG_USAGE_LONG) sys.exit() if opt in ("-l", "--list"): showattr = True if opt in ("-j", "--json"): cjsonfile = True if opt in ("-m", "--multi"): multifile = True if opt in ("-v", "--verbose"): verbose = True if opt in ("-u", "--future"): future = True if opt in ("-f", "--full"): full = True # Toggle full print behaviour for numpy arrays. if full: numpy.set_printoptions(threshold=numpy.nan) # We need at least one attribute and the filename, so two arguments, or # just one filename if we want to list attributes that can be extracted. # In multifile mode, we generally want at least two filenames, so the # expected number of arguments is a bit different. if not multifile: correct_number = (not showattr and len(arglist) > 1) or (showattr and len(arglist) > 0) else: correct_number = (not showattr and len(arglist) > 2) or (showattr and len(arglist) > 1) if not correct_number: print("The number of arguments does not seem to be correct.") print(MSG_USAGE) sys.exit(1) # Figure out which are the attribute names and which are the filenames or links. # Note that in Linux, the shell expands wild cards, but not so in Windows, # so try to do that here using glob. attrnames = [] filenames = [] for arg in arglist: if arg in ccData._attrlist: attrnames.append(arg) elif URL_PATTERN.match(arg) or os.path.isfile(arg): filenames.append(arg) else: wildcardmatches = glob.glob(arg) if wildcardmatches: filenames.extend(wildcardmatches) else: print("%s is neither a filename nor an attribute name." % arg) print(MSG_USAGE) sys.exit(1) # Since there is some ambiguity to the correct number of arguments, check # that there is at least one filename (or two in multifile mode), and also # at least one attribute to parse if the -l option was not passed. if len(filenames) == 0: print("No logfiles given") sys.exit(1) if multifile and len(filenames) == 1: print("Expecting at least two logfiles in multifile mode") sys.exit(1) if not showattr and len(attrnames) == 0: print("No attributes given") sys.exit(1) # This should be sufficient to correctly handle multiple files, that is to # run the loop below only once with all logfiles in the variable `filename`. # Although, perhaps it would be clearer to abstract the contents of the loop # into another function. if multifile: filenames = [filenames] # Now parse each file and print out the requested attributes. for filename in filenames: if multifile: name = ", ".join(filename[:-1]) + " and " + filename[-1] else: name = filename # The keyword dictionary are not used so much. but could be useful for # passing options downstream. For example, we might use --future for # triggering experimental or alternative behavior (as with optdone). kwargs = {} if verbose: kwargs['verbose'] = True kwargs['loglevel'] = logging.INFO else: kwargs['verbose'] = False kwargs['loglevel'] = logging.ERROR if future: kwargs['future'] = True if cjsonfile: kwargs['cjson'] = True print("Attempting to read %s" % name) data = ccread(filename, **kwargs) if data == None: print("Cannot figure out the format of '%s'" % name) print("Report this to the cclib development team if you think it is an error.") print("\n" + MSG_USAGE) sys.exit() if showattr: print("cclib can parse the following attributes from %s:" % name) if cjsonfile: for key in data: print(key) break for attr in data._attrlist: if hasattr(data, attr): print(" %s" % attr) else: invalid = False for attr in attrnames: if cjsonfile: if attr in data: print("%s:\n%s" % (attr, data[attr])) continue else: if hasattr(data, attr): print(attr) attr_val = getattr(data, attr) # List of attributes to be printed with new lines if attr in data._listsofarrays and full: for val in attr_val: print(val) else: print(attr_val) continue print("Could not parse %s from this file." % attr) invalid = True if invalid: print(MSG_USAGE_LONG)
if matches_scf: time_scf_cpu, time_scf_wall = [float(time) for time in matches_scf[0]] times_scf_cpu.append(time_scf_cpu) times_scf_wall.append(time_scf_wall) matches_grad = re_time_grad.findall(line) if matches_grad: time_grad_cpu, time_grad_wall = [float(time) for time in matches_grad[0]] times_grad_cpu.append(time_grad_cpu) times_grad_wall.append(time_grad_wall) times_scf = np.array([times_scf_cpu, times_scf_wall]) times_grad = np.array([times_grad_cpu, times_grad_wall]) couldnt_parse = False try: data = ccread(outputfilename) natom = data.natom nsteps = (6 * natom) + 1 nsteps_current = times_grad.shape[1] pct = 100 * (nsteps_current / nsteps) except StopIteration: couldnt_parse = True nsteps = -1 nsteps_current = -1 pct = -1 nsteps_remaining = nsteps - nsteps_current print('=' * 78) print(outputfilename) print('-' * 78) if couldnt_parse: