-
Notifications
You must be signed in to change notification settings - Fork 764
Fixes #5170: Improve msd_type parsing #5173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #5173 +/- ##
===========================================
+ Coverage 92.72% 92.73% +0.01%
===========================================
Files 180 180
Lines 22472 22473 +1
Branches 3188 3189 +1
===========================================
+ Hits 20837 20841 +4
+ Misses 1177 1175 -2
+ Partials 458 457 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
package/MDAnalysis/analysis/msd.py
Outdated
| # Validate type first | ||
| if not isinstance(self.msd_type, str): | ||
| raise TypeError("msd_type must be a string") | ||
|
|
||
| # strip whitespace + lowercase | ||
| self.msd_type = self.msd_type.strip().lower() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added these lines in msd.py , they do -
- Explicitly checks that
msd_typeis a string to avoid unexpected AttributeErrors. - Uses
.strip().lower()to handle inputs with leading/trailing whitespace
(e.g. " xy ", " Xz "), while preserving existing case-insensitive behavior.
| def test_msd_type_whitespace(self, u, SELECTION): | ||
| m = MSD(u, SELECTION, msd_type=" xy ", fft=False) | ||
| assert m.dim_fac == 2 | ||
| assert m._dim == [0, 1] | ||
|
|
||
| def test_msd_type_uppercase(self, u, SELECTION): | ||
| m = MSD(u, SELECTION, msd_type=" Xz ", fft=False) | ||
| assert m.dim_fac == 2 | ||
| assert m._dim == [0, 2] | ||
|
|
||
| def test_msd_type_nonstring(self, u, SELECTION): | ||
| with pytest.raises(TypeError): | ||
| MSD(u, SELECTION, msd_type=123, fft=False) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added tests covering msd_type input handling in EinsteinMSD:
- whitespace handling (e.g. " xy ")
- case-insensitive parsing (existing behavior)
- non-string inputs raising
TypeError
|
@Dreamstick9 thank you for pointing this out ! Since the use of
|
|
One more thing I noticed in test_msd.py: test_msd_type_whitespace_around_valid_value expects a ValueError for " xy ". Since the PR goal is to support whitespace, shouldn't this test expect success instead of an error? Currently, this test will likely fail because the code raises a KeyError (due to the unstripped string) rather than the expected ValueError. |
|
This is intentional. As discussed in #5170, we decided not to silently normalize whitespace. Inputs like |
IAlibay
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per the associated issue, the enhancement by adding extra checks is likely uncessary.
My proposal would be to move the lower() call to line 388 instead when we set self._dim and then add an AttributeError to the except.
|
@IAlibay Thanks for the clarification. |
IAlibay
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add your handle to the changelog please.
package/MDAnalysis/analysis/msd.py
Outdated
| try: | ||
| self._dim = keys[self.msd_type] | ||
| self._dim = keys[self.msd_type.lower()] | ||
| except AttributeError: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't double except here, just do the one exception message and add the word "string" in the message.
| def test_msd_type_uppercase(self, u, SELECTION): | ||
| m = MSD(u, SELECTION, msd_type="Xz", fft=False) | ||
| assert m.dim_fac == 2 | ||
| assert m._dim == [0, 2] | ||
|
|
||
| def test_msd_type_nonstring(self, u, SELECTION): | ||
| with pytest.raises(TypeError): | ||
| MSD(u, SELECTION, msd_type=123, fft=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just make these extra parameters of the test_msdtype_error method above.
package/MDAnalysis/analysis/msd.py
Outdated
| "xy, xz, yz, x, y, z".format(self.msd_type) | ||
| self._dim = keys[self.msd_type.lower()] | ||
| except (AttributeError, KeyError): | ||
| raise TypeError( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| raise TypeError( | |
| raise ValueError( |
Keep the value error, it's an error in the input value.
package/MDAnalysis/analysis/msd.py
Outdated
| self._dim = keys[self.msd_type.lower()] | ||
| except (AttributeError, KeyError): | ||
| raise TypeError( | ||
| "msd_type must be a string and one of: xyz, xy, xz, yz, x, y, z" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "msd_type must be a string and one of: xyz, xy, xz, yz, x, y, z" | |
| f"Invalid msd_type {msd_type} must be a string and one of: xyz, xy, xz, yz, x, y, z" |
Keep the parameter exposed in the error message.
| @pytest.mark.parametrize( | ||
| "msd_type, exc", | ||
| [ | ||
| ("Xz", None), # valid, mixed case. | ||
| (123, TypeError), # non-string. | ||
| ], | ||
| ) | ||
| def test_msdtype_error(self, u, SELECTION, msd_type, exc): | ||
| if exc is None: | ||
| m = MSD(u, SELECTION, msd_type=msd_type, fft=False) | ||
| assert m.dim_fac == 2 | ||
| assert m._dim == [0, 2] | ||
| else: | ||
| with pytest.raises(exc): | ||
| MSD(u, SELECTION, msd_type=msd_type, fft=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't do this, keep all the old parameters ("foo", "bar", etc...) and solely check for the ValueError to be raised, just like the old test.
| ], | ||
| ) | ||
| def test_msdtype_error(self, u, SELECTION, msd_type, exc): | ||
| if exc is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't do this, keep this solely to checking for an error being raised with bad inputs.

This PR implements enhancement proposed in issue #5170
Summary
EinsteinMSD currently lowercases the msd_type string but does not:
What This PR Does?
.strip()before.lower()to handle inputs like " xy ".All tests pass locally
📚 Documentation preview 📚: https://mdanalysis--5173.org.readthedocs.build/en/5173/