Skip to content

Conversation

drroe
Copy link
Contributor

@drroe drroe commented Sep 17, 2020

When initially written, cpptraj expected molecules to be contiguous, i.e. all atoms in a given molecule are next to each other in the overall topology sequence. When this was not the case (due to e.g. some moiety later in the Topology sequence being bonded onto an earlier molecule) cpptraj would complain and just not determine molecule information, which would disable things like imaging by molecule etc.

This PR gives cpptraj the ability to handle non-contiguous molecules, by assuming molecules are composed of "segments" which are themselves contiguous. This requires the least amount of memory and code change to implement, and seems to work well in practice. Imaging by molecule is barely slower (1-2%), while unwrapping actually got a decent boost when rewritten (20%). When writing Amber topologies with non-contiguous molecules, try to be as true to the format as possible by writing the ATOMS_PER_MOLECULE field based on segments. I think this should be OK, but a warning is printed anyway.

The fixatomorder command can still be used to re-order molecules to be contiguous if desired.

@drroe drroe self-assigned this Sep 17, 2020
@drroe
Copy link
Contributor Author

drroe commented Sep 18, 2020

@hainm I may need your help fixing pytraj on this one. I've got a branch where I'm trying to fix this locally. I first tried to just comment out the Molecule stuff that was removed (BeginAtom(), EndAtom(), etc) figuring that's all low level stuff pytraj shouldn't need anyway, and it compiles, but some tests fail, e.g.:

run_simple_test.py::TestRunnable::test_other other stuff. throw all tests don't belong anywhere else here
PASSED
test_actionlist.py::TestActionList::test_6 PASSED
test_actionlist.py::TestActionList::test_combine_cpptraj_iterating_with_pytraj terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Fatal Python error: Aborted

Current thread 0x00007f31e49f6700 (most recent call first):
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/site-packages/pytraj-2.0.5.dev0-py3.8-linux-x86_64.egg/pytraj/analysis/rmsd.py", line 358 in rmsd
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/site-packages/pytraj-2.0.5.dev0-py3.8-linux-x86_64.egg/pytraj/utils/decorators.py", line 11 in inner
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/site-packages/pytraj-2.0.5.dev0-py3.8-linux-x86_64.egg/pytraj/analysis/rmsd.py", line 226 in rmsd_nofit
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/site-packages/pytraj-2.0.5.dev0-py3.8-linux-x86_64.egg/pytraj/utils/decorators.py", line 11 in inner

I don't know why add_frame() should be failing, so it must be something deeper in pytraj that I'm missing. You could probably track it down faster than I can which is why I'm pinging you. I'll hold off merging this PR for now until pytraj has a chance of working.

@hainm
Copy link
Contributor

hainm commented Sep 18, 2020

@drroe I will take a look. Cheers.

@drroe
Copy link
Contributor Author

drroe commented Sep 19, 2020

@hainm Some more info. If I compile libcpptraj with no optimizations the tests fail at a different point:

test_distance_based_mask.py::TestDistanceBasedMask::test_atom_distance PASSED
test_distance_based_mask.py::TestDistanceBasedMask::test_residue_distance PASSED
test_do.py::test_pytraj_do Fatal Python error: Segmentation fault

Thread 0x00007f5d23955700 (most recent call first):
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/site-packages/pytraj-2.0.5.dev0-py3.8-linux-x86_64.egg/pytraj/externals/wurlitzer.py", line 166 in forwarder
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/threading.py", line 870 in run
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/threading.py", line 932 in _bootstrap_inner
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/threading.py", line 890 in _bootstrap

Current thread 0x00007f5d3da7a700 (most recent call first):
  File "/home/droe/Programs/anaconda/3/envs/pytrajtest3/lib/python3.8/site-packages/pytraj-2.0.5.dev0-py3.8-linux-x86_64.egg/pytraj/utils/decorators.py", line 59 in _inner

Interestingly enough, if I run python test_do.py it completes successfully. The cpptraj branch is https://github.com/drroe/cpptraj/tree/contiguousMols and the pytraj branch is https://github.com/drroe/pytraj/tree/cpptrajMolUnit if you want to check them out.

@drroe
Copy link
Contributor Author

drroe commented Sep 19, 2020

@hainm I guess the problem is that pytraj will need to have Unit and Segment defined somehow so that molecules can continue to function; I can't just get away with commenting that stuff out.

@hainm
Copy link
Contributor

hainm commented Sep 21, 2020

I have not checked the code in detail yet but I got segmentation fault with this simple code:

import pytraj as pt

traj = pt.load("tz2.nc", "tz2.parm7")
pt.autoimage(traj)

@hainm
Copy link
Contributor

hainm commented Sep 21, 2020

@drroe I've tracked down and this line of code caused the segmentation fault: https://github.com/drroe/pytraj/blob/30fb774d117d4cd5792c36af405282c93a8fbe6c/pytraj/analysis/c_action/c_action.pyx#L207

any idea why?

@hainm
Copy link
Contributor

hainm commented Sep 21, 2020

By the way, here is how pytraj do the setup before calling the compute function:

https://github.com/drroe/pytraj/blob/30fb774d117d4cd5792c36af405282c93a8fbe6c/pytraj/analysis/c_action/c_action.pyx#L152

@drroe
Copy link
Contributor Author

drroe commented Sep 22, 2020

@hainm so the issue is that cpptraj now allows molecules to be made up of 1 or more contiguous segments; so there is no longer things like BeginAtom() and EndAtom(), but a Unit that has 1 or more segments, each with their own begin and end. This is why all the begin and end atom stuff is commented out here: drroe/pytraj@1b56994

However, I think that internally breaks how pytraj does things with molecules, for example here: https://github.com/drroe/pytraj/blob/1b5699449c8c92ae620483b9ac3e93c7ce8b1a3b/pytraj/topology/topology.pyx#L304-L306

Essentially pytraj needs to be updated to handle the new molecule bookkeeping in cpptraj, and I'm not sure what the best way to do it is. I think that adding a call to the Topology::DetermineMolecules() function here can replace the start_new_mol stuff above it, but then anything in pytraj that uses molecule stuff (like the stuff referred to above) needs to be updated as well. I don't know if the best option is to cdef the Unit and Segment classes or what.

@hainm
Copy link
Contributor

hainm commented Sep 22, 2020

@drroe I don't think that relates to the segmentation fault.
In my example (silly me), I was trying to do autoimage for a dry system (tz2.nc and tz2.parm7).

import pytraj as pt

traj = pt.load("tz2.nc", "tz2.parm7")
pt.autoimage(traj)

@hainm
Copy link
Contributor

hainm commented Sep 22, 2020

For updating pytraj, I will do the cleanup.

@hainm
Copy link
Contributor

hainm commented Sep 22, 2020

I see the issue now. Currently, pytraj only checks for ERR status from cpptraj. https://github.com/drroe/pytraj/blob/30fb774d117d4cd5792c36af405282c93a8fbe6c/pytraj/analysis/c_action/c_action.pyx#L178

pytraj should check SKIP status. (so pytraj would raise RuntimeError if the code is trying to do autoimage for dry tz2 system).

@hainm
Copy link
Contributor

hainm commented Sep 23, 2020

@drroe Please try out my branch: https://github.com/hainm/pytraj/tree/cpptrajMolUnit

Essentially pytraj needs to be updated to handle the new molecule bookkeeping in cpptraj, and I'm not sure what the best way to do it is. I think that adding a call to the Topology::DetermineMolecules() function here can replace the start_new_mol stuff above it, but then anything in pytraj that uses molecule stuff (like the stuff referred to above) needs to be updated as well. I don't know if the best option is to cdef the Unit and Segment classes or what.

I don't know how to make pytraj work correctly based on your suggestion.
Here is the simple test:

import pytraj as pt
from pytraj.testing import assert_equal_topology


def test():
    top = pt.load_topology('data/tz2.ortho.parm7')
    top2 = top.__class__()
    d = top.to_dict()
    top2.__setstate__(d)
    print(top.n_mols, top2.n_mols)
    assert top.n_mols == top2.n_mols

test()

The aim of the test is to convert cpptraj's Topology object to python's dict for serialization. I got more number of molecules after deserializing the data.

@hainm hainm mentioned this pull request Sep 23, 2020
@hainm
Copy link
Contributor

hainm commented Sep 23, 2020

I don't know how to make pytraj work correctly based on your suggestion.

Scratch that. I misunderstood your comment. Fixed now.

@drroe drroe merged commit 7f02a2b into Amber-MD:master Sep 23, 2020
@drroe drroe deleted the contiguousMols branch September 23, 2020 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants