Add simple atomic distance analysis (#3654)#4105
Add simple atomic distance analysis (#3654)#4105richardjgowers merged 11 commits intoMDAnalysis:developfrom
Conversation
Linter Bot Results:Hi @xhgchen! Thanks for making this PR. We linted your code and found the following: Some issues were found with the formatting of your code.
Please have a look at the Please note: The |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## develop #4105 +/- ##
========================================
Coverage 93.59% 93.59%
========================================
Files 192 193 +1
Lines 25134 25156 +22
Branches 4056 4058 +2
========================================
+ Hits 23523 23546 +23
Misses 1092 1092
+ Partials 519 518 -1
... and 1 file with indirect coverage changes Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report in Codecov by Sentry. |
4d87b70 to
e575a99
Compare
| conditions (PBCs). The unitcell dimensions of the system must be | ||
| orthogonal or triclinic for the calculations with PBCs to work. |
There was a problem hiding this comment.
We don't need to mention what the unitcell must be here as we've previously enforced this
|
|
||
| import warnings | ||
| import logging | ||
| from .base import AnalysisBase |
There was a problem hiding this comment.
It might be cleaner to create a new file for this analysis class. It feels a little weird to import base into distances. Once you get circular imports things get confusing fast.
| self.results = np.zeros((self.n_frames, self._ag1.atoms.n_atoms)) | ||
|
|
||
| def _single_frame(self): | ||
| if (self._pbc): |
There was a problem hiding this comment.
a fun hack is to set a variable (box) to either .dimensions or None depending on self._pbc, then the call to calc_bonds can remain the same, and it's clearer what's happening (imho)
e.g.
box = self._ag1.dimensions if self._pbc else None
self.results = calc_bonds(self._ag1.positions, self._ag2.positions, box=box)| n_frames : int | ||
| Number of frames included in the analysis. | ||
| n_atoms : int | ||
| Number of atoms in each atom group. |
There was a problem hiding this comment.
I don't see where these variables are set?
There was a problem hiding this comment.
Thanks for all the feedback! I learned a lot working through it, and I have pushed some more commits.
I added those variables because other classes seemed to have them (in the docstring) and I used those as reference.
results refers to self.results in def _prepare(self) and def _single_frame(self)
n_frames is used to make the NumPy array in def _prepare(self)
n_atoms is used to check that ag1 and ag2 have the same number of atoms and in def _prepare(self) to make the NumPy array
Would it be better to remove some/all of them (from the docstring)?
| def ad_u(): | ||
| return MDAnalysis.Universe(GRO, XTC) |
There was a problem hiding this comment.
can we use a mda.Universe.empty() here to avoid having to read files for a test?
For its positions, you could either use a seeded random number, or just something like np.arange(natoms * 3).reshape(natoms, -1) to generate arbitrary coordinates
There was a problem hiding this comment.
So in order to do this, I had to change the dist() tests to use calc_bonds() instead because the Universe does not have resids
|
|
||
| @staticmethod | ||
| @pytest.fixture() | ||
| def expected_scipy(ad_ag1, ad_ag2): |
There was a problem hiding this comment.
I'm not sure we need a check against scipy, the check against dist is fine
| # non-pbc x, y, z distances | ||
| dist = np.abs(ad_ag1.positions - ad_ag2.positions) | ||
|
|
||
| # box size (lx, ly, lz) | ||
| box = ad_ag1.dimensions[:3] | ||
|
|
||
| # apply minimum image convention i.e. take box - dist | ||
| # when dist > box / 2 | ||
| dist = np.where(dist > box / 2, box - dist, dist) | ||
|
|
||
| # desired dist = sqrt((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2) | ||
| expected[i] = np.sqrt(np.square(dist).sum(axis=1)) |
There was a problem hiding this comment.
again just use dist here. we're not testing that our distance calculations work here (we do that elsewhere). We're testing that this class is correctly applying those functions.
e575a99 to
c3298f3
Compare
|
Now that all the checks have passed, @richardjgowers could you take a look at the new files when you get the chance? I would appreciate input on the file name as well. I was torn between |
|
Just updating the docs so they work properly :) This is the first time I have ever written docs, but it was fun. Edit: The 2 failing checks both seem to be from an issue uploading to Codecov. I would expect them to work with a re-run. Here is a direct link to the preview docs page for the new module: https://mdanalysis--4105.org.readthedocs.build/en/4105/documentation_pages/analysis/atomicdistances.html Edit 2: Very minor wording fix. Hopefully the checks will run correctly this time. |
* Resolves MDAnalysis#3654 * Add class `AtomicDistances` to `MDAnalysis.analysis.distances` to calculate the distances `|ag1[i] - ag2[i]|` for all `i` from `0` to `n_atoms - 1` for each frame over the trajectory * Allow periodic boundary conditions to be considered or ignored in class `AtomicDistances` by setting kwarg `pbc` to `True` or `False` * Add unit tests for class `AtomicDistances` to `test_distances.py`
* Add `atomicdistances.py` for class `AtomicDistances` * Add `test_atomicdistances.py` to test class `AtomicDistances` * Modify docs for clarity * Use `box` variable to handle PBCs in `AtomicDistances` for clarity * Remove file imports for tests and replace with mda.Universe.empty(), use calc_bonds() instead of dist() for corresponding tests b/c no resid * Remove unnecessary distance calculations in tests (SciPy, positions)
* Restore `distances.py` and `test_distances.py` to their original state
* Modify docs so they can build successfully * Change formatting and wording to look pleasant and consistent
* Add "the distances" before the math expression in first paragraph
4d68b34 to
0cdabcf
Compare
|
Since it has been a while since this was last reviewed, I was wondering when it might be looked at again? I realize that everyone is likely busy reviewing GSoC applications in addition to their other commitments and I am not in a hurry; it would just help me follow up more promptly when the time comes. Also, the last push was just to resolve conflicts. |
AtomicDistancestoMDAnalysis.analysis.distancesto calculate the distances|ag1[i] - ag2[i]|for allifrom0ton_atoms - 1for each frame over the trajectoryAtomicDistancesby setting kwargpbctoTrueorFalseAtomicDistancestotest_distances.pyThe class itself is inspired by this comment in #3310 mentioned in #3654. How would I go about crediting them if this PR gets approved? I changed the list to a NumPy array to improve performance and added the
pbckwarg, as outlined above.PR Checklist
📚 Documentation preview 📚: https://readthedocs-preview--4105.org.readthedocs.build/en/4105/