def write_to_file(self, filename): """Write the molecular geometry to a file. The file format is inferred from the extensions. Currently supported formats are: ``*.xyz``, ``*.cml`` Argument: | ``filename`` -- a filename """ # TODO: give all file format writers the same API if filename.endswith('.cml'): from molmod.io import dump_cml dump_cml(filename, [self]) elif filename.endswith('.xyz'): from molmod.io import XYZWriter symbols = [] for n in self.numbers: atom = periodic[n] if atom is None: symbols.append("X") else: symbols.append(atom.symbol) xyz_writer = XYZWriter(filename, symbols) xyz_writer.dump(self.title, self.coordinates) del xyz_writer else: raise ValueError("Could not determine file format for %s." % filename)
def test_md_water32_full(): dump = False ff = get_ff_water32(True, True, True, True) pos = ff.system.pos.copy() grad = np.zeros(pos.shape) h = 1.0 * femtosecond mass = np.array([periodic[n].mass for n in ff.system.numbers]).reshape( (-1, 1)) # init ff.update_pos(pos) epot = ff.compute(grad) temp = 300 vel = np.random.normal(0, 1, pos.shape) * np.sqrt( (2 * boltzmann * temp) / mass) velh = vel + (-0.5 * h) * grad / mass # prop cqs = [] if dump: symbols = [system.get_ffatype(i) for i in xrange(system.natom)] xyz_writer = XYZWriter('traj.xyz', symbols) for i in xrange(100): pos += velh * h ff.update_pos(pos) grad[:] = 0.0 epot = ff.compute(grad) if dump: xyz_writer.dump('i = %i energy = %.10f' % (i, epot), pos) tmp = (-0.5 * h) * grad / mass vel = velh + tmp ekin = 0.5 * (mass * vel * vel).sum() cqs.append(ekin + epot) velh = vel + tmp cqs = np.array(cqs) assert cqs.std() < 5e-3
def test_md_water32_full(): dump = False ff = get_ff_water32(True, True, True, True) pos = ff.system.pos.copy() grad = np.zeros(pos.shape) h = 1.0*femtosecond mass = np.array([periodic[n].mass for n in ff.system.numbers]).reshape((-1,1)) # init ff.update_pos(pos) epot = ff.compute(grad) temp = 300 vel = np.random.normal(0, 1, pos.shape)*np.sqrt((2*boltzmann*temp)/mass) velh = vel + (-0.5*h)*grad/mass # prop cqs = [] if dump: symbols = [system.get_ffatype(i) for i in xrange(system.natom)] xyz_writer = XYZWriter('traj.xyz', symbols) for i in xrange(100): pos += velh*h ff.update_pos(pos) grad[:] = 0.0 epot = ff.compute(grad) if dump: xyz_writer.dump('i = %i energy = %.10f' % (i, epot), pos) tmp = (-0.5*h)*grad/mass vel = velh + tmp ekin = 0.5*(mass*vel*vel).sum() cqs.append(ekin + epot) velh = vel + tmp cqs = np.array(cqs) assert cqs.std() < 5e-3
def to_file(self, fn): """Write the system to a file **Arguments:** fn The file to write to. Supported formats are: chk Internal human-readable checkpoint format. This format includes all the information of a system object. All data are stored in atomic units. h5 Internal binary checkpoint format. This format includes all the information of a system object. All data are stored in atomic units. xyz A simple file with atomic positions and elements. Coordinates are written in Angstroms. """ if fn.endswith('.chk'): from molmod.io import dump_chk dump_chk( fn, { 'numbers': self.numbers, 'pos': self.pos, 'ffatypes': self.ffatypes, 'ffatype_ids': self.ffatype_ids, 'scopes': self.scopes, 'scope_ids': self.scope_ids, 'bonds': self.bonds, 'rvecs': self.cell.rvecs, 'charges': self.charges, 'radii': self.radii, 'valence_charges': self.valence_charges, 'dipoles': self.dipoles, 'radii2': self.radii2, 'masses': self.masses, }) elif fn.endswith('.h5'): with h5.File(fn, 'w') as f: self.to_hdf5(f) elif fn.endswith('.xyz'): from molmod.io import XYZWriter from molmod.periodic import periodic xyz_writer = XYZWriter(fn, [periodic[n].symbol for n in self.numbers]) xyz_writer.dump(str(self), self.pos) else: raise NotImplementedError( 'The extension of %s does not correspond to any known format.' % fn) if log.do_high: with log.section('SYS'): log('Wrote system to %s.' % fn)
def write_to_xyz(self, fn_xyz): """Write a trajectory file based on the ``frames`` list. Argument: | ``fn_xyz`` -- The filename for the trajectory. """ w = XYZWriter(fn_xyz, self.system.symbols) for i, frame in enumerate(self.frames): w.dump("Frame %i" % i, frame.pos)
def dump_modes_xyz(nma, indexes=0, prefix="mode", amplitude=5.0*angstrom, frames=36): """Write XYZ trajectory file(s) that vizualize internal mode(s) Arguments: | nma -- an object that specifies the normal modes, several formats are supported: (i) a Tamkin NMA object, (ii) a 3-tuple with reference coordinates, mass-unweighted mode(s) and atom numbers or (iii) a 4-tuple with reference coordinates, mass- weighted mode(s), atom numbers and a masses3 vector. the latter is a vector with 3*N elements containing the masses of the atoms in groups of three. Optional arguments: | indexes -- the index or a list of indexes of modes that must be written to trajectory files [default=0] | prefix -- a prefix used for the output files. the generated trajectory filenames have the format prefix.index.xyz [default="mode"] | amplitude -- the amplitude of the normal mode vibration in atomic untis [default=5*angstrom] | frames -- the number of frames written to the trajectory file [default=36] """ if isinstance(nma, NMA): coordinates = nma.coordinates modes = nma.modes numbers = nma.numbers masses3 = nma.masses3 elif hasattr(nma, "__len__") and len(nma)==3: coordinates, modes, numbers = nma masses3 = None elif hasattr(nma, "__len__") and len(nma)==4: coordinates, modes, numbers, masses3 = nma else: raise TypeError("Could not understand first argument. Check documentation.") if not hasattr(indexes, "__len__"): indexes = [indexes] if len(modes.shape) == 1: modes = modes.reshape((-1,1)) symbols = [periodic[n].symbol for n in numbers] for index in indexes: filename = "%s.%i.xyz" % (prefix, index) mode = modes[:,index] if masses3 is not None: mode /= np.sqrt(masses3) mode /= np.linalg.norm(mode) xyz_writer = XYZWriter(filename, symbols) for frame in xrange(frames): factor = amplitude*np.sin(2*np.pi*float(frame)/frames) xyz_writer.dump("frame %i" % frame, coordinates + factor*mode.reshape((-1,3))) del xyz_writer
def to_file(self, fn): """Write the system to a file **Arguments:** fn The file to write to. Supported formats are: chk Internal human-readable checkpoint format. This format includes all the information of a system object. All data are stored in atomic units. h5 Internal binary checkpoint format. This format includes all the information of a system object. All data are stored in atomic units. xyz A simple file with atomic positions and elements. Coordinates are written in Angstroms. """ if fn.endswith('.chk'): from molmod.io import dump_chk dump_chk(fn, { 'numbers': self.numbers, 'pos': self.pos, 'ffatypes': self.ffatypes, 'ffatype_ids': self.ffatype_ids, 'scopes': self.scopes, 'scope_ids': self.scope_ids, 'bonds': self.bonds, 'rvecs': self.cell.rvecs, 'charges': self.charges, 'radii': self.radii, 'valence_charges': self.valence_charges, 'dipoles': self.dipoles, 'radii2': self.radii2, 'masses': self.masses, }) elif fn.endswith('.h5'): with h5.File(fn, 'w') as f: self.to_hdf5(f) elif fn.endswith('.xyz'): from molmod.io import XYZWriter from molmod.periodic import periodic xyz_writer = XYZWriter(fn, [periodic[n].symbol for n in self.numbers]) xyz_writer.dump(str(self), self.pos) else: raise NotImplementedError('The extension of %s does not correspond to any known format.' % fn) if log.do_high: with log.section('SYS'): log('Wrote system to %s.' % fn)
class XYZWriter(Hook): def __init__(self, fn_xyz, select=None, start=0, step=1): """ **Argument:** fn_xyz A filename to write the XYZ trajectory too. **Optional arguments:** select A list of atom indexes that should be written to the trajectory output. If not given, all atoms are included. start The first iteration at which this hook should be called. step The hook will be called every `step` iterations. """ self.fn_xyz = fn_xyz self.select = select self.xyz_writer = None Hook.__init__(self, start, step) def __call__(self, iterative): from molmod import angstrom if self.xyz_writer is None: from molmod.periodic import periodic from molmod.io import XYZWriter numbers = iterative.ff.system.numbers if self.select is None: symbols = [periodic[n].symbol for n in numbers] else: symbols = [periodic[numbers[i]].symbol for i in self.select] self.xyz_writer = XYZWriter(self.fn_xyz, symbols) rvecs = iterative.ff.system.cell.rvecs.copy() rvecs_string = " ".join( [str(x[0] / angstrom) for x in rvecs.reshape((-1, 1))]) title = '%7i E_pot = %.10f %s' % (iterative.counter, iterative.epot, rvecs_string) if self.select is None: pos = iterative.ff.system.pos else: pos = iterative.ff.system.pos[self.select] self.xyz_writer.dump(title, pos)
def tracks_to_xyz(prefix, destination, symbols, sub=slice(None), file_unit=angstrom, atom_indexes=None, unit_cell_iter=None, groups=None): """Converts a set of tracks into an xyz file.""" if atom_indexes is None: atom_indexes = range(len(symbols)) else: atom_indexes = list(atom_indexes) if groups is not None: # reduce the groups to the selected atoms and use the index of the # reduced set. reverse_indexes = dict((atom_index, counter) for counter, atom_index in enumerate(atom_indexes)) new_groups = [] for group in groups: new_group = [] for atom_index in group: new_index = reverse_indexes.get(atom_index) if new_index is not None: new_group.append(new_index) if len(new_group) > 0: new_groups.append(new_group) groups = new_groups symbols = [symbols[index] for index in atom_indexes] filenames = [] for index in atom_indexes: for c in 'xyz': filenames.append("%s.%07i.%s" % (prefix, index, c)) f = file(destination, 'w') xyz_writer = XYZWriter(f, symbols, file_unit=file_unit) dtype = numpy.dtype([("cor", float, (len(atom_indexes), 3))]) mtr = MultiTracksReader(filenames, dtype, sub=sub) for row in mtr: coordinates = row["cor"] if unit_cell_iter is not None: try: uc = unit_cell_iter.next() except StopIteration: raise ValueError("Not enough frames in the unit cell tracks.") if groups is None: coordinates -= numpy.dot(uc.matrix, numpy.floor(numpy.dot(uc.reciprocal, coordinates.transpose()))).transpose() else: for group in groups: center = coordinates[group].mean(axis=0) coordinates[group] -= numpy.dot(uc.matrix, numpy.floor(numpy.dot(uc.reciprocal, center))) xyz_writer.dump("None", coordinates) f.close()
class XYZWriter(Hook): def __init__(self, fn_xyz, select=None, start=0, step=1): """ **Argument:** fn_xyz A filename to write the XYZ trajectory too. **Optional arguments:** select A list of atom indexes that should be written to the trajectory output. If not given, all atoms are included. start The first iteration at which this hook should be called. step The hook will be called every `step` iterations. """ self.fn_xyz = fn_xyz self.select = select self.xyz_writer = None Hook.__init__(self, start, step) def __call__(self, iterative): from molmod import angstrom if self.xyz_writer is None: from molmod.periodic import periodic from molmod.io import XYZWriter numbers = iterative.ff.system.numbers if self.select is None: symbols = [periodic[n].symbol for n in numbers] else: symbols = [periodic[numbers[i]].symbol for i in self.select] self.xyz_writer = XYZWriter(self.fn_xyz, symbols) rvecs = iterative.ff.system.cell.rvecs.copy() rvecs_string = " ".join([str(x[0]) for x in rvecs.reshape((-1,1))]) title = '%7i E_pot = %.10f %s' % (iterative.counter, iterative.epot, rvecs_string) if self.select is None: pos = iterative.ff.system.pos else: pos = iterative.ff.system.pos[self.select] self.xyz_writer.dump(title, pos)
def __call__(self, iterative): from molmod import angstrom if self.xyz_writer is None: from molmod.periodic import periodic from molmod.io import XYZWriter numbers = iterative.ff.system.numbers if self.select is None: symbols = [periodic[n].symbol for n in numbers] else: symbols = [periodic[numbers[i]].symbol for i in self.select] self.xyz_writer = XYZWriter(self.fn_xyz, symbols) rvecs = iterative.ff.system.cell.rvecs.copy() rvecs_string = " ".join([str(x[0]/angstrom) for x in rvecs.reshape((-1,1))]) title = '%7i E_pot = %.10f %s' % (iterative.counter, iterative.epot, rvecs_string) if self.select is None: pos = iterative.ff.system.pos else: pos = iterative.ff.system.pos[self.select] self.xyz_writer.dump(title, pos)
def __call__(self, iterative): from molmod import angstrom if self.xyz_writer is None: from molmod.periodic import periodic from molmod.io import XYZWriter numbers = iterative.ff.system.numbers if self.select is None: symbols = [periodic[n].symbol for n in numbers] else: symbols = [periodic[numbers[i]].symbol for i in self.select] self.xyz_writer = XYZWriter(self.fn_xyz, symbols) rvecs = iterative.ff.system.cell.rvecs.copy() rvecs_string = " ".join([str(x[0]) for x in rvecs.reshape((-1,1))]) title = '%7i E_pot = %.10f %s' % (iterative.counter, iterative.epot, rvecs_string) if self.select is None: pos = iterative.ff.system.pos else: pos = iterative.ff.system.pos[self.select] self.xyz_writer.dump(title, pos)