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

add sasmol objects #61

Closed StevenCHowell closed 2 years ago

StevenCHowell commented 7 years ago

I added a __add__ method to the Molecule class to allow for adding sasmol objects together to create a separate sasmol object. Neither of the original objects are modified by this addition. I also created the __radd__ method to allow for summing sasmol objects to create a collection of many sasmol objects.

This code demonstrates this:

import numpy as np
import pandas as pd

import sas_modeling
from sasmol import system

x = np.arange(-110, 110)
y = np.arange(-110, 110)
grid_points = np.array(np.meshgrid(x, y)).T.reshape(-1, 2)

c = sas_modeling.geometric.Circle(10, center=[-40, -8])
c.in_or_out(grid_points)
c_mol = system.Molecule_Maker(len(c.in_points), name='CA', segname='C')
c_mol.coor()[0, :, :2] = c.in_points[:]

e = sas_modeling.geometric.Ellipse(35, 10, center=[30, -30], orientation=[-1, 2])
e.in_or_out(grid_points)
e_mol = system.Molecule_Maker(len(e.in_points), name='CA', segname='E')
e_mol.coor()[0, :, :2] = e.in_points[:]

s = sas_modeling.geometric.Square(30, center=[-40, 70], orientation=[-1, -5])

s.in_or_out(grid_points)
s_mol = system.Molecule_Maker(len(s.in_points), name='CA', segname='S')
s_mol.coor()[0, :, :2] = s.in_points[:]

ce_mol = c_mol + e_mol

ces_mol = sum([c_mol, e_mol, s_mol])

ce_mol is a combination of the circle and ellipse molecules. ces_mol is a combination of the circle, ellipse, and square molecules.

StevenCHowell commented 7 years ago

I have a few questions that came up as I looked at this code more closely. What are the use cases or purposes for the Atom and Molecule classes? What distinguishes these? I would expect a Molecule to be made of of several Atom objects; is this is the case? I expect that would drastically change the molecule interface to something like this:

mol_1.atom[0].coor()  # to get the coordinate for the first atom
mol_1.atom[:].coor()  # to get the coordinates for all the atoms

Is the atom class for single atoms and the molecule class for multiple atom constructions? Or are there situations when a single atom would be considered a molecule, that happens to only haves one atom?

I really like the Molecule_Maker class! I LOVE be able to define just the bits I care about, this is incredibly useful! I do wonder if this needs to be a separate class from Molecule. It may make sense for it to be a method called on an empty Molecule like this:

mol_1 = system.Molecule()
mol_1.create(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=' ')

This may depend on the answer to the earlier question about the purpose of the Molecule class. Another option to consider is to incorporate this into the Molecule __init__, having the code check for a pdb file name to load it, look for an input atom number to create the molecule, or fallback to creating an empty molecule.

StevenCHowell commented 7 years ago

Molecule_Maker does not function as I thought. I would like to chat about the design goals so I can fix this to fit with the overall design.

StevenCHowell commented 7 years ago

When initializing a Molecule, mol_1 = system.Molecule(), most of the molecule properties do not get defined. _natoms, _mass, _coor, _com, _conect do, but the others do not.

StevenCHowell commented 7 years ago

This is ready for review and comments. It includes the 4 main changes we discussed:

  1. Add field_definitions to pdb_io.py
  2. Add a creator method to the system.Atom class
  3. Add an append method to the system.Atom class for combining sasmol objects via obj_1.append(obj_2)
  4. Update the Atom.__add__ method to output a new sasmol object without modifying any of the input sasmol objects (this supports both obj_1 + obj_2 addition and sum([obj_1, obj_2, obj_3]) addition)

To verify the documentation is up to date, I added a if __name__ == "__main__": which tests that all the examples in the doc-strings actually run as described. They all pass.