Closed StevenCHowell closed 7 years ago
Here is the code I wrote to create a pdb (of atoms on a fcc) from scratch:
def create_fcc_pdb(n_atoms, pdb_name='', **kwargs):
"""
create a pdb using n_atoms on an fcc grid
"""
coor = fcc_coor(n_atoms, **kwargs)
index = np.arange(n_atoms) + 1
create = sasmol.SasMol(0)
create.setAtom(['ATOM'] * n_atoms)
create.setIndex(index)
create.setName(['Ar'] * n_atoms)
create.setLoc([' '] * n_atoms)
create.setResname(['VDW'] * n_atoms)
create.setChain(['X'] * n_atoms)
create.setResid(np.ones(n_atoms, dtype=np.int))
create.setRescode([' '] * n_atoms)
create.setCoor(coor.reshape(1, n_atoms, 3))
create.setOccupancy(['1.00'] * n_atoms)
create.setBeta(['0.00'] * n_atoms)
create.setSegname(['{:04d}'.format(i) for i in index])
create.setElement(['Ar'] * n_atoms)
create.setCharge([' '] * n_atoms)
if not pdb_name:
pdb_name = 'n()_fcc.pdb'.format(n_atoms)
create.write_pdb(pdb_name, 0, 'w')
This uses n_atoms
everywhere to make sure things have the same number of atoms, but if someone does this manually, creating each list/array/whatever separately, it could produce problems.
If something like this is not implemented, it would at least be helpful to users to have listed which sasmol properties are required to create a valid PDB.
Indeed, we will do this.
Add a Molecule_Template() class to system.py with optional arguments to fill in or dictate what one wants to fill in (either for each entry, or a pre-made list).
Added a new class to system.py
` class Molecule_Maker(Atom):
def __init__(self, natoms, atom='ATOM', index=None, name='C', loc=' ',
resname='DUM', chain='A', resid=None, rescode=' ', coor=None,
occupancy='0.00', beta='0.00', segname='DUM', element='C', charge=' ', **kwargs):
Atom.__init__(self)
self._atom = [atom for x in xrange(natoms)]
if index is not None:
self._index = index
else:
self._index = numpy.array([x+1 for x in xrange(natoms)],numpy.int)
self._name = [name for x in xrange(natoms)]
self._loc = [loc for x in xrange(natoms)]
self._resname = [resname for x in xrange(natoms)]
self._chain = [chain for x in xrange(natoms)]
if resid is not None:
self._resid = resid
else:
self._resid = numpy.array([x+1 for x in xrange(natoms)],numpy.int)
self._rescode = [rescode for x in xrange(natoms)]
if coor is not None:
self._coor = coor
else:
self._coor = numpy.zeros((1,natoms,3),numpy.float)
self._occupancy = [occupancy for x in xrange(natoms)]
self._beta = [beta for x in xrange(natoms)]
self._charge = [charge for x in xrange(natoms)]
self._segname = [segname for x in xrange(natoms)]
self._element = [element for x in xrange(natoms)]
`
which can be used to create a template molecule that is complete. Optional arguments allow for some flexibility in default inputs. Of course one can use sasmol setter methods to alter the default values.
` import sasmol.system as system mol = system.Molecule_Maker(108) # makes a default molecule with 108 atoms
mol = system.Molecule_Maker(108, name='Ar') # molecule with all atoms named Ar
mol = system.Molecue_Maker(108, coor=my_coor) # molecule with coordinates set with your array
(numpy.array((number_of_frames,number_of_atoms,3), numpy.float))
`
tests are needed. Will create a separate issue for this.
As far as combining two molecules, this does exist in subset (merge_two_molecules). Although, this needs to be thought through and refactored.
By the way @stvn66 a method already existed to aid you in the building of a fake molecule. That said, I will remove this method as it was ill-placed and now deprecated to the Molecule_Maker class.
it sasmol/pdbrx.py (or zazmol/topology.py)
def set_pdb_values(m, natoms, **kwargs):
In the past I wrote methods to:
I will upload the code I used for these tasks in the comments below.