-
Notifications
You must be signed in to change notification settings - Fork 824
Description
Expected behaviour
ag.center(weights=None).dtype should equal ag.center(weights=np.ones(len(ag))).dtype
Actual behaviour
If weights.dtype is of higher precision than ag.positions.dtype, the resulting dtype is that of weights.
Code to reproduce the behaviour
import numpy as np
import MDAnalysis as mda
from MDAnalysisTests.datafiles import PSF, DCD
u = mda.Universe(PSF, DCD)
ag = u.atoms
print(ag.center(weights=None).dtype) # prints dtype('float32')
print(ag.center(weights=np.ones(len(ag))).dtype) # prints dtype('float64')Current version of MDAnalysis
0.18.1-dev
Root of the problem
The line causing the problem is this one:
return np.average(coords, weights=weights, axis=0)
According to the numpy docs:
The return type is
Floatifais of integer type, otherwise it is of the same type asa.
The problem here is that np.average() doesn't behave the way the numpy docs claim it should. I already opened an issue for this.
Other affected methods
center_of_geometry(): returns array ofdtype=np.float32center_of_mass(): returns array ofdtype=np.float64
I see no reason why those methods should return arrays with different precisions.
Proposed solution
One could argue that the dtype of ag.center(...) should always be that of ag.positions since it computes a coordinate.
However, if we enforce that, tests for methods such as center_of_mass() fail. In fact, I fear that methods using center() might loose too much precision if the result of center() is in single precision.
I'd personally opt for always returning double precision, which could be enforced by promoting the weights if required. The part of the code computing the results if the compound parameter is not 'group' could also easily be promoted to double precision.