class TestSymgroupCycles(unittest.TestCase): def setUp(self): self._geometry = Geometry( positions=[[0.506643354, -1.227657970, 0.000000000], [1.303068499, 0.000000000, 0.000000000], [0.506643354, 1.227657970, 0.000000000], [-0.926250976, 0.939345948, 0.000000000], [-0.926250976, -0.939345948, 0.000000000]], # name='test', symbols=['C', 'C', 'C', 'C', 'C'], connectivity_thresh=1.5, ) def test_symmetry_measure(self): measure = self._geometry.get_symmetry_measure('C5') self.assertAlmostEqual(measure, 0.8247502, places=6) measure = self._geometry.get_symmetry_measure('C2') self.assertAlmostEqual(measure, 0.0, places=6) measure = self._geometry.get_symmetry_measure('C3') self.assertAlmostEqual(measure, 33.482451, places=6) #def test_symmetry_measure_permutation(self): # measure = self._geometry.get_symmetry_measure('C5', fix_permutation=True) # self.assertAlmostEqual(measure, 0.8247502, places=6) def test_symmetry_nearest(self): nearest = self._geometry.get_symmetry_nearest_structure( 'C5').get_positions() # print(nearest) reference = [[4.05078542e-01, -1.24670356e+00, 0.00000000e+00], [1.31086170e+00, -1.33226763e-16, 0.00000000e+00], [4.05078542e-01, 1.24670356e+00, 0.00000000e+00], [-1.06050939e+00, 7.70505174e-01, 0.00000000e+00], [-1.06050939e+00, -7.70505174e-01, 0.00000000e+00]] testing.assert_array_almost_equal(nearest, reference, decimal=6)
def get_reference_structure(label, central_atom=0): global ideal_structures from cosymlib.molecule.geometry import Geometry if ideal_structures is None: file_path = os.path.dirname( os.path.abspath(__file__)) + '/ideal_structures_center.yaml' with open(file_path, 'r') as stream: ideal_structures = yaml.load(stream, Loader=yaml.FullLoader) try: if central_atom == 0: coordinates = ideal_structures[label][:-1] # coordinates = resize_structure(ideal_structures[label][:-1]) return Geometry(positions=coordinates, name=label, symbols=['L'] * len(coordinates), connectivity=[]) else: coordinates = ideal_structures[label] # coordinates = resize_structure(ideal_structures[label], center=ideal_structures[label][-1]) return Geometry(positions=coordinates, name=label, symbols=['L'] * (len(coordinates) - 1) + ['M'], connectivity=[]) except KeyError as e: raise Exception('Shape reference label "{}" not found!'.format( e.args[0]))
def setUp(self): self._geometry = Geometry( positions=[[0.506643354, -1.227657970, 0.000000000], [1.303068499, 0.000000000, 0.000000000], [0.506643354, 1.227657970, 0.000000000], [-0.926250976, 0.939345948, 0.000000000], [-0.926250976, -0.939345948, 0.000000000]], # name='test', symbols=['C', 'C', 'C', 'C', 'C'], connectivity_thresh=1.5, )
def get_geometry_from_file_cor(file_name, read_multiple=False): """ Reads a Conquest formatted file and the geometry of all structures in it :param file_name: file name :param read_multiple: read multiple files if available :return: list of Geometry objects """ input_molecule = [[], []] geometries = [] with open(file_name, mode='r') as lines: for idl, line in enumerate(lines): if line.lstrip().startswith(comment_line): pass elif line.strip() == '': warnings.warn('Line {} is empty'.format(idl + 1), errors.EmptyLineWarning) else: try: float(line.split()[1]) if len(line.split()) == 4: input_molecule[0].append(line.split()[0]) input_molecule[1].append(line.split()[1:]) elif len(line.split()) == 5: input_molecule[0].append(line.split()[0]) input_molecule[1].append(line.split()[1:-1]) else: float(line.split()[2]) except (ValueError, IndexError): if input_molecule[0]: geometries.append( Geometry(symbols=input_molecule[0], positions=input_molecule[1], name=name)) input_molecule = [[], []] name = line.replace('**FRAG**', '')[:-1] name = name.replace(' ', '') geometries.append( Geometry(symbols=input_molecule[0], positions=input_molecule[1], name=name)) if not read_multiple: return geometries[0] # Check if all geometries are of the same vertices check_geometries_vertices(geometries, file_name) return geometries
def get_shape_structure(self, shape_label, central_atom=0, fix_permutation=False): from cosymlib.molecule.geometry import Geometry structure_coordinates = self._shape.structure( shape_label, central_atom=central_atom, fix_permutation=fix_permutation) return Geometry(symbols=self.get_symbols(), positions=structure_coordinates, name=self.name + '_structure')
def get_geometry_from_file_ref(file_name, read_multiple=False): """ Reads a Conquest formatted file and the geometry of all structures in it :param file_name: file name :param read_multiple: read all geometries inside the file :return: list of Geometry objects """ input_molecule = [] structures = [] with open(file_name, mode='r') as lines: lines.readline() lines.readline() name = lines.readline().split()[0] for line in lines: if line.lstrip().startswith(comment_line): pass # elif line.strip() == '': # warnings.warn('Line {} is empty'.format(idl + 1), custom_errors.EmptyLineWarning) else: try: if len(line.split()) > 3: float(line.split()[1]) input_molecule.append(line.split()[1:]) else: float(line.split()[0]) input_molecule.append(line.split()) except (ValueError, IndexError): if input_molecule: structures.append( Geometry(positions=input_molecule, name=name)) input_molecule = [] name = line.split()[0] structures.append(Geometry(positions=input_molecule, name=name)) if read_multiple is False: return structures[0] return structures
def get_geometry_from_file_pdb(file_name, read_multiple=False): """ Reads a Conquest formatted file and the geometry of all structures in it :param file_name: file name :param read_multiple: read multiple files if available :return: list of Geometry objects """ file_txt = open(file_name, mode='r').read() index_list = [] for i in re.finditer('TITLE', file_txt): index_list.append(i.start()) index_list.append(len(file_txt)) geometries = [] for i in range(len(index_list) - 1): mol_section = file_txt[index_list[i]:index_list[i + 1]] coordinates = [] symbols = [] connect = [] name = '' for line in mol_section.split('\n'): if line.find('TITLE') > -1: name = ' '.join(line.split()[1:]) if line.find('HETATM') > -1 or line.find('ATOM') > -1: coordinates.append([float(num) for num in line.split()[4:7]]) symbols.append(line.split()[2]) if line.find('CONECT') > -1: connect.append([int(num) for num in line.split()[1:]]) if line.find('TER') > -1 or line.find('END') > -1: break connectivity = [] for atom in connect: for j in atom[1:]: connectivity.append((atom[0], j)) geometries.append( Geometry(symbols=symbols, positions=coordinates, name=name, connectivity=connectivity)) if read_multiple is False: return geometries[0] return geometries
def get_symmetry_nearest_structure(self, label, central_atom=0, center=None, multi=1): """ Returns the nearest ideal structure :param label: symmetry point group :type label: str :param central_atom: central atom position (0 if no central atom) :type central_atom: int :param center: center of the measure in Cartesian coordinates :type center: list :return: The structure :rtype: Geometry """ return Geometry(symbols=self.get_symbols(), positions=self._symmetry.nearest_structure(label), name=self.name + '_nearest')
def get_geometry_from_file_xyz(file_name, read_multiple=False): """ Reads a XYZ file and returns the geometry of all structures in it :param file_name: file name :param read_multiple: read multiple files if available :return: list of Geometry objects """ input_molecule = [[], []] geometries = [] n_atoms = None n_atoms_line = 1 no_title_structures = 1 with open(file_name, mode='r') as lines: for idl, line in enumerate(lines): if line.lstrip().startswith(comment_line): pass elif line.strip() == '': warnings.warn('Line {} is empty'.format(idl + 1), errors.EmptyLineWarning) else: try: float(line.split()[1]) input_molecule[0].append(line.split()[0]) input_molecule[1].append(line.split()[1:]) except (IndexError, ValueError): if input_molecule[0]: if len(input_molecule[0]) != n_atoms: warnings.warn( 'Number of atoms in line {} and number ' 'of atoms provided are not equal'.format( n_atoms_line), errors.MissingAtomWarning) if name == '': name = no_name(file_name, no_title_structures) no_title_structures += 1 geometries.append( Geometry(symbols=input_molecule[0], positions=input_molecule[1], name=name)) n_atoms = None name = '' input_molecule = [[], []] if n_atoms is None: n_atoms = int(line.split()[0]) n_atoms_line = idl + 1 else: name = line.split()[0] if len(input_molecule[0]) != n_atoms: warnings.warn( 'Number of atoms in line {} and number ' 'of atoms provided are not equal'.format(n_atoms_line), errors.MissingAtomWarning) if name == '': name = no_name(file_name, no_title_structures) geometries.append( Geometry(symbols=input_molecule[0], positions=input_molecule[1], name=name)) if not read_multiple: return geometries[0] # Check if all geometries are of the same vertices check_geometries_vertices(geometries, file_name) return geometries
def get_molecule_from_file_molden(file_name, read_multiple=False): key_list = [ 'Charge', 'Multiplicity', 'Atomic numbers', 'Current cartesian coordinates', 'Shell type', 'Number of primitives per shell', 'Shell to atom map', 'Primitive exponents', 'Contraction coefficients', 'P(S=P) Contraction coefficients', 'Alpha MO coefficients', 'Beta MO coefficients', 'MO Energies' ] type_list = {'s': '0', 'p': '1', 'd': '2', 'f': '3', 'sp': '-1'} input_molecule = {key: [] for key in key_list} read_molden = False read_coordinates = False read_basis = False read_coefficients = False occupation = {'Alpha': [], 'Beta': []} with open(file_name, mode='r') as lines: lines.readline() lines.readline() name = file_name.split('.')[0] for line in _non_blank_lines(lines): if '[' in line: pass elif read_molden: if '======= END OF MOLDEN-FORMAT MOLECULAR ORBITALS =======' in line: break if read_coordinates: input_molecule['Atomic numbers'].append(line.split()[2]) input_molecule['Current cartesian coordinates'].append( line.split()[3:]) if read_basis: try: number = float(line.split()[0].replace('D', 'E')) if number - int(number) != 0.: input_molecule['Primitive exponents'].append( line.split()[0].replace('D', 'E')) input_molecule['Contraction coefficients'].append( line.split()[1].replace('D', 'E')) if len(line.split()) > 2: input_molecule[ 'P(S=P) Contraction coefficients'].append( line.split()[2].replace('D', 'E')) else: input_molecule[ 'P(S=P) Contraction coefficients'].append( 0.) else: atom = line.split()[0] except ValueError: input_molecule['Shell to atom map'].append(atom) input_molecule['Shell type'].append( type_list[line.split()[0].lower()]) input_molecule[ 'Number of primitives per shell'].append( line.split()[1]) if read_coefficients: if 'Sym' in line: pass else: if 'Ene' in line: input_molecule['MO Energies'].append( float(re.split('[= ]', line)[-1])) elif 'Spin' in line: spin = re.split('[= ]', line)[-1] input_molecule[spin + ' MO coefficients'].append( []) elif 'Occup' in line: occupation[spin].append( int(float(line.split('=')[-1]))) else: input_molecule[spin + ' MO coefficients'][-1].append( line.split()[1]) if '[Atoms]' in line: read_molden = True read_coordinates = True if 'AU' in line: bohr_to_angstrom = 0.529177249 else: bohr_to_angstrom = 1 elif '[GTO]' in line: read_coordinates = False read_basis = True elif '[MO]' in line: read_basis = False read_coefficients = True elif '[5D]' in line: input_molecule['Shell type'] = [ x.replace('2', '-2') for x in input_molecule['Shell type'] ] elif '[7F]' in line: input_molecule['Shell type'] = [ x.replace('3', '-3') for x in input_molecule['Shell type'] ] coordinates = np.array(input_molecule['Current cartesian coordinates'], dtype=float).reshape(-1, 3) * bohr_to_angstrom total_n_electrons = 0 symbols = [] for atom_number in input_molecule['Atomic numbers']: total_n_electrons += int(atom_number) symbols.append(atomic_number_to_element(atom_number)) new_occupation = [] if len(occupation['Beta']) == 0: if 2 not in occupation['Alpha']: occupation['Beta'] = occupation['Alpha'] else: for occup in occupation['Alpha']: new_occupation.append(occup // 2) if occup == 2: occupation['Beta'].append(1) else: occupation['Beta'].append(0) occupation['Alpha'] = new_occupation n_electrons = sum(occupation['Alpha'] + occupation['Beta']) input_molecule['Multiplicity'].append( sum(occupation['Alpha']) - sum(occupation['Beta']) + 1) input_molecule['Charge'].append(int(total_n_electrons - n_electrons)) basis = basis_format( basis_set_name='UNKNOWN', atomic_numbers=input_molecule['Atomic numbers'], atomic_symbols=symbols, shell_type=input_molecule['Shell type'], n_primitives=input_molecule['Number of primitives per shell'], atom_map=input_molecule['Shell to atom map'], p_exponents=input_molecule['Primitive exponents'], c_coefficients=input_molecule['Contraction coefficients'], p_c_coefficients=input_molecule['P(S=P) Contraction coefficients']) geometry = Geometry(symbols=symbols, positions=coordinates, name=name) Ca = np.array(input_molecule['Alpha MO coefficients'], dtype=float) if input_molecule['Beta MO coefficients']: Cb = np.array(input_molecule['Beta MO coefficients'], dtype=float) else: Cb = [] warnings.warn('Beta energies not implemented yet') ee = ElectronicStructure( basis=basis, orbital_coefficients=[Ca, Cb], # charge=input_molecule['Charge'][0], multiplicity=input_molecule['Multiplicity'][0], alpha_energies=input_molecule['MO Energies'], beta_energies=[], alpha_occupancy=occupation['Alpha'], beta_occupancy=occupation['Beta']) if read_multiple: return [Molecule(geometry, ee)] return Molecule(geometry, ee)
def get_molecule_from_file_fchk(file_name, read_multiple=False): key_list = [ 'Charge', 'Multiplicity', 'Number of alpha electrons', 'Number of beta electrons', 'Atomic numbers', 'Current cartesian coordinates', 'Shell type', 'Number of primitives per shell', 'Shell to atom map', 'Primitive exponents', 'Contraction coefficients', 'P(S=P) Contraction coefficients', 'Alpha Orbital Energies', 'Beta Orbital Energies', 'Alpha MO coefficients', 'Beta MO coefficients' ] input_molecule = [[] for _ in range(len(key_list))] read = False with open(file_name, mode='r') as lines: name = lines.readline().split()[0] #.strip('\n') line = lines.readline().split() basis_set = line[-1] if 'R' in line[1]: del key_list[-1] n = 1 options = True for line in lines: if read: try: float(line.split()[0]) input_molecule[n].append(line.split()) except ValueError: read = False for idn, key in enumerate(key_list): if key in line: if n == len(key_list) - 1: break if options and idn != 4: input_molecule[idn].append(int(line.split()[-1])) n = idn break else: options = False if n == idn: n += 1 else: n = idn read = True break for n in range(4, len(input_molecule)): input_molecule[n] = reformat_input(input_molecule[n]) bohr_to_angstrom = 0.529177249 coordinates = np.array(input_molecule[5], dtype=float).reshape( -1, 3) * bohr_to_angstrom atomic_number = [int(num) for num in input_molecule[4]] symbols = [] for number in atomic_number: symbols.append(atomic_number_to_element(number)) basis = basis_format(basis_set_name=basis_set, atomic_numbers=atomic_number, atomic_symbols=symbols, shell_type=input_molecule[6], n_primitives=input_molecule[7], atom_map=input_molecule[8], p_exponents=input_molecule[9], c_coefficients=input_molecule[10], p_c_coefficients=input_molecule[11]) geometry = Geometry(symbols=symbols, positions=coordinates, name=name) alpha_energies = np.array(input_molecule[12], dtype=float).tolist() if input_molecule[13]: beta_energies = np.array(input_molecule[13], dtype=float).tolist() else: beta_energies = [] Ca = np.array(input_molecule[14], dtype=float).reshape( -1, int(np.sqrt(len(input_molecule[14])))) if input_molecule[15]: Cb = np.array(input_molecule[15], dtype=float).reshape( -1, int(np.sqrt(len(input_molecule[15])))) else: Cb = [] electronic_structure = ElectronicStructure( basis=basis, orbital_coefficients=[Ca, Cb], # charge=input_molecule[0][0], multiplicity=input_molecule[1][0], alpha_energies=alpha_energies, beta_energies=beta_energies, alpha_occupancy=[1] * int(input_molecule[2][0]), beta_occupancy=[1] * int(input_molecule[3][0])) if read_multiple: return [Molecule(geometry, electronic_structure)] return Molecule(geometry, electronic_structure)
def print_minimum_distortion_path_shape(self, shape_label1, shape_label2, central_atom=0, min_dev=None, max_dev=None, min_gco=None, max_gco=None, num_points=20, output=None): """ Print the minimum distortion path :param shape_label1: First reference shape label :type shape_label1: str :param shape_label2: Second reference shape label :type shape_label2: str :param central_atom: Position of the central atom :type central_atom: int :param min_dev: :type min_dev: float :param max_dev: :type max_dev: float :param min_gco: :type min_gco: float :param max_gco: :type max_gco: float :param num_points: Number of points :type num_points: int :param output1: Display hook :type output1: hook """ if output is not None: output_name, file_extension = os.path.splitext(output.name) output1 = open(output_name + '_pth.csv', 'w') output2 = open(output_name + '_pth.xyz', 'w') output3 = output else: output1 = sys.stdout output2 = sys.stdout output3 = sys.stdout csm, devpath, gen_coord = self.get_path_parameters(shape_label1, shape_label2, central_atom=central_atom) txt_params = '' if min_dev is not None: txt_params = 'Deviation threshold to calculate Path deviation function: ' \ '{:2.1f}% - {:2.1f}%\n'.format(min_dev, max_dev) if min_gco is not None: txt_params += 'Deviation threshold to calculate Generalized Coordinate: ' \ '{:2.1f}% - {:2.1f}%\n'.format(min_gco, max_gco) txt_params += '\n' txt_params += '{:9} '.format('structure'.upper()) for csm_label in list(csm.keys()): txt_params += '{:^8} '.format(csm_label) txt_params += '{:^8} {:^8}'.format('DevPath', 'GenCoord') txt_params += '\n' if min_gco is not None and min_dev is not None: filter_mask = [min_dev <= dv <= max_dev and min_gco <= gc <= max_gco for dv, gc in zip(devpath, gen_coord)] elif min_gco is not None: filter_mask = [min_gco <= gc <= max_gco for gc in gen_coord] elif min_dev is not None: filter_mask = [min_dev <= dv <= max_dev for dv in devpath] else: filter_mask = [True for _ in range(len(self._molecules))] for idx, molecule in enumerate(self._molecules): if not filter_mask[idx]: continue txt_params += '{:9} '.format(molecule.name.strip()) for label in list(csm.keys()): txt_params += '{:^8.3f} '.format(csm[label][idx]) txt_params += '{:^8.1f} {:^8.1f}'.format(devpath[idx], gen_coord[idx]) txt_params += '\n' # self.print_shape_measure() txt_params += 'skipped {} structure/s\n\n'.format(filter_mask.count(False)) output3.write(txt_params) if isinstance(shape_label1, Geometry): label1_name = shape_label1.name else: label1_name = shape_label1 if isinstance(shape_label2, Geometry): label2_name = shape_label2.name else: label2_name = shape_label2 path = get_shape_path(shape_label1, shape_label2, num_points) txt_path = 'Minimum distortion path\n' txt_path += ' {:^6} {:^6}\n'.format(label1_name, label2_name) for idx, value in enumerate(path[0]): txt_path += '{:6.3f} {:6.3f}'.format(path[0][idx], path[1][idx]) txt_path += '\n' txt_path += '\n' output1.write(txt_path) test_structures = [] for ids, structure in enumerate(path[2]): test_structures.append(Geometry(symbols=['' for _ in range(len(structure))], positions=structure, name='map_structure{}'.format(ids))) output2.write(file_io.get_file_xyz_txt(test_structures)) if output1 is sys.stdout: plt.plot(path[0], path[1], 'k', linewidth=2.0) plt.scatter(np.array(csm[label1_name])[filter_mask], np.array(csm[label2_name])[filter_mask], linewidths=0.01) plt.xlabel(label1_name) plt.ylabel(label2_name) plt.show()
def get_nm_vibration_path(geometry, normal_mode, points=10, backward=False, k=1.5): nm_np_matrix = np.array(normal_mode) geom_np = np.array(geometry) if backward: x = np.linspace(-k, k, points) else: x = np.linspace(k/points, k, points) structures_path = [] for dx in x: structures_path.append(geom_np + dx*nm_np_matrix) return structures_path molecule = read_generic_structure_file('sf6.fchk') freq, nm_martices = read_normal_modes_gaussian('../old_examples/sf6_freq.out') k_points = 1.5 points = 10 n_freq = 1 path = get_nm_vibration_path(molecule.geometry.get_positions(), nm_martices[n_freq - 1], k=k_points) x = np.linspace(k_points/points, k_points, points) output = open('sf6_freq{}.xyz'.format(n_freq), 'w') for ids, structure in enumerate(path): xi = '{:.2f}'.format(x[ids]).replace('.', '') txt = get_file_xyz_txt(Geometry(structure, symbols=molecule.geometry.get_symbols(), name='freq : ' + str(freq[0]) + ' ' + str(xi))) output.write(txt)