madscatt / zazmol

Library for defining molecular objects to create simulation and analysis programs To install: python setup.py install dependencies: numpy, mocker
GNU General Public License v3.0
0 stars 2 forks source link

It would be useful to have a method for populating raw sasmol objects and combining sasmol objects #6

Closed StevenCHowell closed 7 years ago

StevenCHowell commented 7 years ago

In the past I wrote methods to:

  1. Combine 2 sasmol objects into a single sasmol object
  2. Create a sasmol object from scratch These were not intuitive and it would be nice if these were integrated into the package. For both of these, creating a method to do this would provide a good place to check that the number of items in the different fields match, and also auto-populate the combined fields, e.g., segnames auto populates from the combined/created segname list.

I will upload the code I used for these tasks in the comments below.

StevenCHowell commented 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.

StevenCHowell commented 7 years ago

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.

madscatt commented 7 years ago

Indeed, we will do this.

madscatt commented 7 years ago

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).

madscatt commented 7 years ago

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

NOTE you coor array is the proper numpy dimensions

  (numpy.array((number_of_frames,number_of_atoms,3), numpy.float))

`

tests are needed. Will create a separate issue for this.

madscatt commented 7 years ago

As far as combining two molecules, this does exist in subset (merge_two_molecules). Although, this needs to be thought through and refactored.

madscatt commented 7 years ago

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):