def testNumpyDeepCopy(self): """ Check that deepcopy on numpy array does not strip units """ x = u.Quantity(np.zeros((2, 3)), u.nanometer) y = copy.deepcopy(x) self.assertTrue(np.all(x == y)) self.assertTrue(u.is_quantity(x)) self.assertTrue(u.is_quantity(y))
def testScalarQuantityConstructor(self): """ Tests creating a Quantity using the Quantity constructor """ self.assertTrue(u.is_quantity(u.Quantity(5, u.centimeters))) self.assertTrue(u.is_quantity(u.Quantity(5, u.centimeters**-1))) x = u.Quantity(value=5.0, unit=100.0 * u.meters) self.assertTrue(u.is_quantity(x)) self.assertEqual(x, 500 * u.meters)
def testCollectionQuantityOperations(self): """ Tests that Quantity collections behave correctly """ # Tests that __getitem__ returns a unit s = [1, 2, 3, 4] * u.angstroms self.assertTrue(u.is_quantity(s[0])) for i, val in enumerate(s): self.assertTrue(u.is_quantity(val)) self.assertEqual(val, (i+1) * u.angstroms) # Tests that __setitem__ fails when an incompatible type is added def fail(s): s[0] = 5 self.assertRaises(AttributeError, lambda: fail(s)) def fail(s): s[0] = 5 * u.joules self.assertRaises(TypeError, lambda: fail(s)) def fail(s): s[0] /= 10 * u.meters self.assertRaises(AttributeError, lambda: fail(s)) # Tests that __setitem__ converts to the unit of the container s[0] = 1 * u.nanometers self.assertEqual(s[0]._value, 10) # Tests standard unit conversions x = [1, 2, 3] * u.centimeters self.assertEqual(x / u.millimeters, [10, 20, 30]) # Test the construction of a container in which each element is a # Quantity, passed to the Quantity constructor x = u.Quantity([1*u.angstrom, 2*u.nanometer, 3*u.angstrom]) self.assertEqual(x._value, [1, 20, 3]) self.assertEqual(x.unit, u.angstrom) x = u.Quantity((1, 2, 3)) self.assertTrue(u.is_quantity(x)) self.assertTrue(x.unit.is_dimensionless()) x = u.Quantity(([1*u.angstrom, 2*u.nanometer, 3*u.angstrom], [1*u.angstrom, 4*u.nanometer, 3*u.angstrom])) self.assertEqual(x._value, ([1, 20, 3], [1, 40, 3])) self.assertEqual(x.unit, u.angstrom) self.assertTrue(u.is_quantity(u.Quantity([])))
def testScalarQuantityConstructor(self): """ Tests creating a Quantity using the Quantity constructor """ self.assertTrue(u.is_quantity(u.Quantity(5, u.centimeters))) self.assertTrue(u.is_quantity(u.Quantity(5, u.centimeters**-1))) x = u.Quantity(value=5.0, unit=100.0*u.meters) self.assertTrue(u.is_quantity(x)) self.assertEqual(x, 500*u.meters)
def testCollectionQuantities(self): """ Tests the use of collections as Quantity values """ s = [1, 2, 3] * u.centimeters self.assertEqual(str(s), '[1, 2, 3] cm') self.assertTrue(u.is_quantity(s)) s2 = s / u.millimeters self.assertEqual(s2, [10.0, 20.0, 30.0]) self.assertEqual(s2, s.value_in_unit(u.millimeters)) # Test 2-D list s = [[1, 2, 3], [4, 5, 6]] s *= u.centimeters self.assertTrue(u.is_quantity(s)) s2 = s / u.millimeters self.assertEqual(s2, [[10.0, 20.0, 30.0], [40.0, 50.0, 60.0]]) self.assertEqual(s.value_in_unit(u.millimeters), s2) # Test tuples s = (1, 2, 3) * u.centimeters self.assertTrue(u.is_quantity(s)) self.assertEqual(str(s), '(1, 2, 3) cm') s2 = s / u.millimeters self.assertEqual(s2, (10, 20, 30)) self.assertIsInstance(s2, tuple) self.assertEqual(s.value_in_unit(u.millimeters), s2) self.assertIsInstance(s.value_in_unit(u.millimeters), tuple) x = [1, 2, 3] * u.centimeters x *= u.meters self.assertEqual(x, [100, 200, 300] * u.centimeters**2)
def testAngleQuantities(self): """ Tests angle measurements """ self.assertEqual(1.0*u.radians / u.degrees, 180 / math.pi) self.assertTrue(u.is_quantity(1.0*u.radians)) self.assertTrue(u.is_quantity(1.0*u.degrees)) self.assertEqual((1.0*u.radians).in_units_of(u.degrees), (180 / math.pi)*u.degrees) self.assertEqual(90*u.degrees/u.radians, math.pi/2) q = 90 * u.degrees + 0.3 * u.radians self.assertEqual(q._value, 90 + 180*0.3/math.pi) self.assertEqual(q.unit, u.degrees)
def testAngleQuantities(self): """ Tests angle measurements """ self.assertEqual(1.0 * u.radians / u.degrees, 180 / math.pi) self.assertTrue(u.is_quantity(1.0 * u.radians)) self.assertTrue(u.is_quantity(1.0 * u.degrees)) self.assertEqual((1.0 * u.radians).in_units_of(u.degrees), (180 / math.pi) * u.degrees) self.assertEqual(90 * u.degrees / u.radians, math.pi / 2) q = 90 * u.degrees + 0.3 * u.radians self.assertEqual(q._value, 90 + 180 * 0.3 / math.pi) self.assertEqual(q.unit, u.degrees)
def _process_cmap(struct, force): """ Adds CMAPs to the structure """ # store the list of cmap types cmap_types = [] for ii in range(force.getNumMaps()): size, grid = force.getMapParameters(ii) # Future-proof in case units start getting added to these maps if u.is_quantity(grid): typ = CmapType(size, grid) else: typ = CmapType(size, grid*u.kilojoules_per_mole) cmap_types.append(typ) typ.grid = typ.grid.T.switch_range() typ.used = False # Add all cmaps for ii in range(force.getNumTorsions()): mapidx, ii, ij, ik, il, ji, jj, jk, jl = force.getTorsionParameters(ii) if ij != ji or ik != jj or il != jk: warnings.warn('Non-continuous CMAP torsions detected. Not ' 'supported.', OpenMMWarning) continue ai, aj, ak = struct.atoms[ii], struct.atoms[ij], struct.atoms[ik] al, am = struct.atoms[il], struct.atoms[jl] cmap_type = cmap_types[mapidx] cmap_type.used = True struct.cmaps.append(Cmap(ai, aj, ak, al, am, type=cmap_type)) for cmap_type in cmap_types: if cmap_type.used: struct.cmap_types.append(cmap_type) struct.cmap_types.claim()
def _initializeConstants(self, simulation): """ Initialize a set of constants required for the reports Parameters ---------- simulation : Simulation The simulation to generate a report for """ import simtk.openmm as mm system = simulation.system frclist = system.getForces() if self._temperature: # Compute the number of degrees of freedom. dof = 0 for i in range(system.getNumParticles()): if system.getParticleMass(i) > 0*u.dalton: dof += 3 dof -= system.getNumConstraints() if any(isinstance(frc, mm.CMMotionRemover) for frc in frclist): dof -= 3 self._dof = dof if self._density: if self._totalMass is None: # Compute the total system mass. self._totalMass = 0*u.dalton for i in range(system.getNumParticles()): self._totalMass += system.getParticleMass(i) elif not u.is_quantity(self._totalMass): self._totalMass = self._totalMass*u.dalton
def testDimensionless(self): """ Tests the properties of unit.dimensionless """ x = 5 * u.dimensionless y = u.Quantity(5, u.dimensionless) self.assertTrue(u.is_quantity(x)) self.assertTrue(u.is_quantity(y)) self.assertNotEqual(x, 5) self.assertNotEqual(y, 5) self.assertEqual(x, y) self.assertEqual(x.value_in_unit_system(u.si_unit_system), 5) self.assertEqual(x.value_in_unit_system(u.cgs_unit_system), 5) self.assertEqual(x.value_in_unit_system(u.md_unit_system), 5) x = u.Quantity(1.0, u.dimensionless) y = u.Quantity(1.0, u.dimensionless) self.assertIsNot(x, y) self.assertEqual(x, y)
def _process_cmap(struct, force): """ Adds CMAPs to the structure """ # store the list of cmap types cmap_types = [] for ii in range(force.getNumMaps()): size, grid = force.getMapParameters(ii) # Future-proof in case units start getting added to these maps if u.is_quantity(grid): typ = CmapType(size, grid) # pragma: no cover else: typ = CmapType(size, grid * u.kilojoules_per_mole) # pragma: no cover cmap_types.append(typ) typ.grid = typ.grid.T.switch_range() typ.used = False # Add all cmaps for ii in range(force.getNumTorsions()): mapidx, ii, ij, ik, il, ji, jj, jk, jl = force.getTorsionParameters(ii) if ij != ji or ik != jj or il != jk: warnings.warn( 'Non-continuous CMAP torsions detected. Not ' # pragma: no cover 'supported.', OpenMMWarning) continue # pragma: no cover ai, aj, ak = struct.atoms[ii], struct.atoms[ij], struct.atoms[ik] al, am = struct.atoms[il], struct.atoms[jl] cmap_type = cmap_types[mapidx] cmap_type.used = True struct.cmaps.append(Cmap(ai, aj, ak, al, am, type=cmap_type)) for cmap_type in cmap_types: if cmap_type.used: struct.cmap_types.append(cmap_type) struct.cmap_types.claim()
def _strip_units(obj): """ Strips units from the object and returns its value in the AKMA unit system. If it is a scalar, the original object is returned unchanged """ if u.is_quantity(obj): return obj.value_in_unit_system(u.akma_unit_system) return obj
def testNumpyFunctions(self): """ Tests various numpy attributes that they result in Quantities """ a = u.Quantity(np.arange(10), u.seconds) self.assertEqual(a.max(), 9*u.seconds) self.assertEqual(a.min(), 0*u.seconds) self.assertEqual(a.mean(), 4.5*u.seconds) self.assertAlmostEqualQuantities(a.std(), 2.8722813232690143*u.seconds) b = a.reshape((5, 2)) self.assertTrue(u.is_quantity(b))
def testNumpyDivision(self): """ Tests that division of numpy Quantities works correctly """ x = u.Quantity(np.asarray([1., 2.]), u.nanometers) y = u.Quantity(np.asarray([3., 4.]), u.picoseconds) xy = x / y self.assertTrue(u.is_quantity(xy)) self.assertEqual(xy.unit, u.nanometers/u.picoseconds) self.assertEqual(xy[0].value_in_unit(u.nanometers/u.picoseconds), 1/3) self.assertEqual(xy[1].value_in_unit(u.nanometers/u.picoseconds), 0.5)
def box_vectors_to_lengths_and_angles(a, b, c): """ This function takes the lengths of the unit cell vectors and the angles between them and returns 3 unit cell vectors satisfying those dimensions Parameters ---------- a : collection of 3 floats (or length Quantity) The first unit cell vector b : collection of 3 floats (or length Quantity) The second unit cell vector c : collection of 3 floats (or length Quantity) The third unit cell vector Returns ------- (a, b, c), (alpha, beta, gamma) Two tuples, the first is the 3 unit cell vector lengths as length-dimension Quantity objects and the second is the set of angles between the unit cell vectors as angle-dimension Quantity objects Notes ----- The unit cell lengths are assumed to be Angstroms if no explicit unit is given. """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) # Get the lengths la = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) lb = sqrt(b[0] * b[0] + b[1] * b[1] + b[2] * b[2]) lc = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]) # Angles alpha = acos((b[0] * c[0] + b[1] * c[1] + b[2] * c[2]) / (lb * lc)) beta = acos((a[0] * c[0] + a[1] * c[1] + a[2] * c[2]) / (la * lc)) gamma = acos((b[0] * a[0] + b[1] * a[1] + b[2] * a[2]) / (lb * la)) # Convert to degrees alpha *= RAD_TO_DEG beta *= RAD_TO_DEG gamma *= RAD_TO_DEG return (la, lb, lc) * u.angstroms, (alpha, beta, gamma) * u.degrees
def box_vectors_to_lengths_and_angles(a, b, c): """ This function takes the lengths of the unit cell vectors and the angles between them and returns 3 unit cell vectors satisfying those dimensions Parameters ---------- a : collection of 3 floats (or length Quantity) The first unit cell vector b : collection of 3 floats (or length Quantity) The second unit cell vector c : collection of 3 floats (or length Quantity) The third unit cell vector Returns ------- (a, b, c), (alpha, beta, gamma) Two tuples, the first is the 3 unit cell vector lengths as length-dimension Quantity objects and the second is the set of angles between the unit cell vectors as angle-dimension Quantity objects Notes ----- The unit cell lengths are assumed to be Angstroms if no explicit unit is given. """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) # Get the lengths la = sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) lb = sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]) lc = sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]) # Angles alpha = acos((b[0]*c[0] + b[1]*c[1] + b[2]*c[2]) / (lb*lc)) beta = acos((a[0]*c[0] + a[1]*c[1] + a[2]*c[2]) / (la*lc)) gamma = acos((b[0]*a[0] + b[1]*a[1] + b[2]*a[2]) / (lb*la)) # Convert to degrees alpha *= RAD_TO_DEG beta *= RAD_TO_DEG gamma *= RAD_TO_DEG return (la, lb, lc) * u.angstroms, (alpha, beta, gamma) * u.degrees
def testNumpyFunctions(self): """ Tests various numpy attributes that they result in Quantities """ a = u.Quantity(np.arange(10), u.seconds) self.assertEqual(a.max(), 9 * u.seconds) self.assertEqual(a.min(), 0 * u.seconds) self.assertEqual(a.mean(), 4.5 * u.seconds) self.assertAlmostEqualQuantities(a.std(), 2.8722813232690143 * u.seconds) b = a.reshape((5, 2)) self.assertTrue(u.is_quantity(b))
def testCollectionQuantityOperations(self): """ Tests that Quantity collections behave correctly """ # Tests that __getitem__ returns a unit s = [1, 2, 3, 4] * u.angstroms self.assertTrue(u.is_quantity(s[0])) for i, val in enumerate(s): self.assertTrue(u.is_quantity(val)) self.assertEqual(val, (i + 1) * u.angstroms) # Tests that __setitem__ fails when an incompatible type is added def fail(s): s[0] = 5 self.assertRaises(AttributeError, lambda: fail(s)) def fail(s): s[0] = 5 * u.joules self.assertRaises(TypeError, lambda: fail(s)) def fail(s): s[0] /= 10 * u.meters self.assertRaises(AttributeError, lambda: fail(s)) # Tests that __setitem__ converts to the unit of the container s[0] = 1 * u.nanometers self.assertEqual(s[0]._value, 10) # Tests standard unit conversions x = [1, 2, 3] * u.centimeters self.assertEqual(x / u.millimeters, [10, 20, 30]) # Test the construction of a container in which each element is a # Quantity, passed to the Quantity constructor x = u.Quantity([1 * u.angstrom, 2 * u.nanometer, 3 * u.angstrom]) self.assertEqual(x._value, [1, 20, 3]) self.assertEqual(x.unit, u.angstrom) x = u.Quantity((1, 2, 3)) self.assertTrue(u.is_quantity(x)) self.assertTrue(x.unit.is_dimensionless()) x = u.Quantity(([1 * u.angstrom, 2 * u.nanometer, 3 * u.angstrom], [1 * u.angstrom, 4 * u.nanometer, 3 * u.angstrom])) self.assertEqual(x._value, ([1, 20, 3], [1, 40, 3])) self.assertEqual(x.unit, u.angstrom) self.assertTrue(u.is_quantity(u.Quantity([])))
def testNumpyDivision(self): """ Tests that division of numpy Quantities works correctly """ x = u.Quantity(np.asarray([1., 2.]), u.nanometers) y = u.Quantity(np.asarray([3., 4.]), u.picoseconds) xy = x / y self.assertTrue(u.is_quantity(xy)) self.assertEqual(xy.unit, u.nanometers / u.picoseconds) self.assertEqual(xy[0].value_in_unit(u.nanometers / u.picoseconds), 1 / 3) self.assertEqual(xy[1].value_in_unit(u.nanometers / u.picoseconds), 0.5)
def reduce_box_vectors(a, b, c): """ This function puts three unit cell vectors in a reduced form where a is "mostly" in x, b is "mostly" in y, and c is "mostly" in z. This form is necessary for some programs (notably OpenMM and Gromacs) Parameters ---------- a : 3-element collection of float First unit cell vector b : 3-element collection of float Second unit cell vector c : 3-element collection of float Third unit cell vector Returns ------- red_a, red_b, red_c : Vec3, Vec3, Vec3 The reduced unit cell vectors in units of angstroms Notes ----- The implementation here is taken from the OpenMM Python application layer written by Peter Eastman """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) a = Vec3(*a) b = Vec3(*b) c = Vec3(*c) c = c - b * round(c[1] / b[1]) c = c - a * round(c[0] / a[0]) b = b - a * round(b[0] / a[0]) return a, b, c
def reduce_box_vectors(a, b, c): """ This function puts three unit cell vectors in a reduced form where a is "mostly" in x, b is "mostly" in y, and c is "mostly" in z. This form is necessary for some programs (notably OpenMM and Gromacs) Parameters ---------- a : 3-element collection of float First unit cell vector b : 3-element collection of float Second unit cell vector c : 3-element collection of float Third unit cell vector Returns ------- red_a, red_b, red_c : Vec3, Vec3, Vec3 The reduced unit cell vectors in units of angstroms Notes ----- The implementation here is taken from the OpenMM Python application layer written by Peter Eastman """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) a = Vec3(*a) b = Vec3(*b) c = Vec3(*c) c = c - b*round(c[1]/b[1]) c = c - a*round(c[0]/a[0]) b = b - a*round(b[0]/a[0]) return a, b, c
def add_temp0(self, stuff): """ The temperature to add to the current frame of the NetCDF file Parameters ---------- stuff : float or temperature Quantity The temperature to add to the current NetCDF file """ if u.is_quantity(stuff): stuff = stuff.value_in_unit(u.kelvin) self._ncfile.variables['temp0'][self._last_remd_frame] = float(stuff) self._last_remd_frame += 1 self.flush()
def add_time(self, stuff): """ Adds the time to the current frame of the NetCDF file Parameters ---------- stuff : float or time-dimension Quantity The time to add to the current frame """ if u.is_quantity(stuff): stuff = stuff.value_in_unit(u.picoseconds) self._ncfile.variables['time'][self._last_time_frame] = float(stuff) self._last_time_frame += 1 self.flush()
def set_box(a, b, c, alpha, beta, gamma): """ Sets the unit cell dimensions for the current system Parameters ---------- a : float Length of the first unit cell vector (can be a unit.Quantity object with dimension length). Unitless input is assumed to be in Angstroms b : float Length of the second unit cell vector (can be a unit.Quantity object with dimension length). Unitless input is assumed to be in Angstroms c : float Length of the third unit cell vector (can be a unit.Quantity object with dimension length). Unitless input is assumed to be in Angstroms alpha : float Angle between vectors b and c (can be a unit.Quantity object with dimension angle). Unitless input is assumed to be in Degrees. beta : float Angle between vectors a and c (can be a unit.Quantity object with dimension angle). Unitless input is assumed to be in Degrees. gamma : float Angle between vectors a and b (can be a unit.Quantity object with dimension angle). Unitless input is assumed to be in Degrees. """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) if u.is_quantity(alpha): alpha = alpha.value_in_unit(u.degrees) if u.is_quantity(beta): beta = beta.value_in_unit(u.degrees) if u.is_quantity(gamma): gamma = gamma.value_in_unit(u.degrees) _pys.set_box(a, b, c, alpha, beta, gamma)
def testUnitMathModule(self): """ Tests the unit_math functions on Quantity objects """ self.assertEqual(u.sqrt(1.0*u.kilogram*u.joule), 1.0*u.kilogram*u.meter/u.second) self.assertEqual(u.sqrt(1.0*u.kilogram*u.calorie), math.sqrt(4.184)*u.kilogram*u.meter/u.second) self.assertEqual(u.sqrt(9), 3) # Test on a scalar self.assertEqual(u.sin(90*u.degrees), 1) self.assertEqual(u.sin(math.pi/2*u.radians), 1) self.assertEqual(u.sin(math.pi/2), 1) self.assertEqual(u.cos(180*u.degrees), -1) self.assertEqual(u.cos(math.pi*u.radians), -1) self.assertEqual(u.cos(math.pi), -1) self.assertAlmostEqual(u.tan(45*u.degrees), 1) self.assertAlmostEqual(u.tan(math.pi/4*u.radians), 1) self.assertAlmostEqual(u.tan(math.pi/4), 1) acos = u.acos(1.0) asin = u.asin(1.0) atan = u.atan(1.0) self.assertTrue(u.is_quantity(acos)) self.assertTrue(u.is_quantity(asin)) self.assertTrue(u.is_quantity(atan)) self.assertEqual(acos.unit, u.radians) self.assertEqual(asin.unit, u.radians) self.assertEqual(atan.unit, u.radians) self.assertEqual(acos.value_in_unit(u.degrees), 0) self.assertEqual(acos / u.radians, 0) self.assertEqual(asin.value_in_unit(u.degrees), 90) self.assertEqual(asin / u.radians, math.pi/2) self.assertAlmostEqual(atan.value_in_unit(u.degrees), 45) self.assertAlmostEqual(atan / u.radians, math.pi/4) # Check some sequence maths seq = [1, 2, 3, 4] * u.meters self.assertEqual(u.sum(seq), 10*u.meters) self.assertEqual(u.dot(seq, seq), (1+4+9+16)*u.meters**2) self.assertEqual(u.norm(seq), math.sqrt(30)*u.meters)
def testUnitMathModule(self): """ Tests the unit_math functions on Quantity objects """ self.assertEqual(u.sqrt(1.0 * u.kilogram * u.joule), 1.0 * u.kilogram * u.meter / u.second) self.assertEqual(u.sqrt(1.0 * u.kilogram * u.calorie), math.sqrt(4.184) * u.kilogram * u.meter / u.second) self.assertEqual(u.sqrt(9), 3) # Test on a scalar self.assertEqual(u.sin(90 * u.degrees), 1) self.assertEqual(u.sin(math.pi / 2 * u.radians), 1) self.assertEqual(u.sin(math.pi / 2), 1) self.assertEqual(u.cos(180 * u.degrees), -1) self.assertEqual(u.cos(math.pi * u.radians), -1) self.assertEqual(u.cos(math.pi), -1) self.assertAlmostEqual(u.tan(45 * u.degrees), 1) self.assertAlmostEqual(u.tan(math.pi / 4 * u.radians), 1) self.assertAlmostEqual(u.tan(math.pi / 4), 1) acos = u.acos(1.0) asin = u.asin(1.0) atan = u.atan(1.0) self.assertTrue(u.is_quantity(acos)) self.assertTrue(u.is_quantity(asin)) self.assertTrue(u.is_quantity(atan)) self.assertEqual(acos.unit, u.radians) self.assertEqual(asin.unit, u.radians) self.assertEqual(atan.unit, u.radians) self.assertEqual(acos.value_in_unit(u.degrees), 0) self.assertEqual(acos / u.radians, 0) self.assertEqual(asin.value_in_unit(u.degrees), 90) self.assertEqual(asin / u.radians, math.pi / 2) self.assertAlmostEqual(atan.value_in_unit(u.degrees), 45) self.assertAlmostEqual(atan / u.radians, math.pi / 4) # Check some sequence maths seq = [1, 2, 3, 4] * u.meters self.assertEqual(u.sum(seq), 10 * u.meters) self.assertEqual(u.dot(seq, seq), (1 + 4 + 9 + 16) * u.meters**2) self.assertEqual(u.norm(seq), math.sqrt(30) * u.meters)
def testQuantityMaths(self): """ Tests dimensional analysis & maths on and b/w Quantity objects """ x = 1.3 * u.meters y = 75.2 * u.centimeters self.assertEqual((x + y) / u.meters, 2.052) self.assertEqual((x - y) / u.meters, 0.548) self.assertEqual(x / y, 1.3 / 0.752) self.assertEqual(x * y, 1.3 * 0.752 * u.meters**2) d1 = 2.0 * u.meters d2 = 2.0 * u.nanometers self.assertEqual(d1 + d2, (2 + 2e-9) * u.meters) self.assertAlmostEqual((d2 + d1 - (2e9 + 2) * u.nanometers)._value, 0, places=6) self.assertEqual(d1 + d1, 4.0 * u.meters) self.assertEqual(d1 - d1, 0.0 * u.meters) self.assertEqual(d1 / d1, 1.0) self.assertEqual(d1 * u.meters, 2.0 * u.meters**2) self.assertEqual(u.kilograms * (d1 / u.seconds) * (d1 / u.seconds), 4 * u.kilograms * u.meters**2 / u.seconds**2) self.assertEqual(u.kilograms * (d1 / u.seconds)**2, 4 * u.kilograms * u.meters**2 / u.seconds**2) self.assertEqual(d1**3, 8.0 * u.meters**3) x = d1**(3 / 2) self.assertAlmostEqual(x._value, math.sqrt(2)**3) self.assertEqual(x.unit, u.meters**(3 / 2)) self.assertAlmostEqual((d1**0.5)._value, math.sqrt(2)) self.assertEqual((d1**0.5).unit, u.meters**0.5) comp = (3.0 + 4.0j) * u.meters self.assertTrue(u.is_quantity(comp)) self.assertEqual(comp.unit, u.meters) self.assertEqual(str(comp), '(3+4j) m') self.assertEqual(comp + comp, (6.0 + 8.0j) * u.meters) self.assertEqual(comp - comp, 0 * u.meters) self.assertEqual(comp * comp, (3.0 + 4.0j)**2 * u.meters**2) self.assertAlmostEqual(abs(comp / comp), 1) self.assertAlmostEqual(1.5 * u.nanometers / u.meters, 1.5e-9, places=15) self.assertEqual((2.3 * u.meters)**2, 2.3**2 * u.meters**2) x = 4.3 * u.meters self.assertEqual(x / u.centimeters, 430) self.assertEqual(str(x / u.seconds), '4.3 m/s') self.assertEqual(str(8.4 / (4.2 * u.centimeters)), '2.0 /cm') x = 1.2 * u.meters self.assertEqual(x * 5, u.Quantity(6.0, u.meters))
def testQuantityMaths(self): """ Tests dimensional analysis & maths on and b/w Quantity objects """ x = 1.3 * u.meters y = 75.2 * u.centimeters self.assertEqual((x + y) / u.meters, 2.052) self.assertEqual((x - y) / u.meters, 0.548) self.assertEqual(x / y, 1.3 / 0.752) self.assertEqual(x * y, 1.3*0.752*u.meters**2) d1 = 2.0*u.meters d2 = 2.0*u.nanometers self.assertEqual(d1 + d2, (2+2e-9)*u.meters) self.assertAlmostEqual((d2+d1-(2e9+2)*u.nanometers)._value, 0, places=6) self.assertEqual(d1 + d1, 4.0*u.meters) self.assertEqual(d1 - d1, 0.0*u.meters) self.assertEqual(d1 / d1, 1.0) self.assertEqual(d1 * u.meters, 2.0*u.meters**2) self.assertEqual(u.kilograms*(d1/u.seconds)*(d1/u.seconds), 4*u.kilograms*u.meters**2/u.seconds**2) self.assertEqual(u.kilograms*(d1/u.seconds)**2, 4*u.kilograms*u.meters**2/u.seconds**2) self.assertEqual(d1**3, 8.0*u.meters**3) x = d1**(3/2) self.assertAlmostEqual(x._value, math.sqrt(2)**3) self.assertEqual(x.unit, u.meters**(3/2)) self.assertAlmostEqual((d1**0.5)._value, math.sqrt(2)) self.assertEqual((d1**0.5).unit, u.meters**0.5) comp = (3.0 + 4.0j) * u.meters self.assertTrue(u.is_quantity(comp)) self.assertEqual(comp.unit, u.meters) self.assertEqual(str(comp), '(3+4j) m') self.assertEqual(comp + comp, (6.0 + 8.0j)*u.meters) self.assertEqual(comp - comp, 0*u.meters) self.assertEqual(comp * comp, (3.0 + 4.0j)**2 * u.meters**2) self.assertAlmostEqual(abs(comp / comp), 1) self.assertAlmostEqual(1.5*u.nanometers / u.meters, 1.5e-9, places=15) self.assertEqual((2.3*u.meters)**2, 2.3**2*u.meters**2) x = 4.3 * u.meters self.assertEqual(x / u.centimeters, 430) self.assertEqual(str(x / u.seconds), '4.3 m/s') self.assertEqual(str(8.4 / (4.2*u.centimeters)), '2.0 /cm') x = 1.2 * u.meters self.assertEqual(x * 5, u.Quantity(6.0, u.meters))
def add_forces(self, stuff): """ Adds a new coordinate frame to the end of a NetCDF trajectory. This should only be called on objects created with the "open_new" constructor. Parameters ---------- stuff : iterable of floats or energy/distance Quantity This array of floats is converted into a numpy array of shape (natom, 3). It can be passed either in the 2-D format of [ [x1, y1, z1], [x2, y2, z2], ... ] or in the 1-D format of [x1, y1, z1, x2, y2, z2, ... ]. """ if u.is_quantity(stuff): stuff.value_in_unit(u.kilocalories_per_mole/u.angstroms) self._ncfile.variables['forces'][self._last_frc_frame] = \ np.reshape(stuff, (self.atom, 3)) self._last_frc_frame += 1 self.flush()
def add_velocities(self, stuff): """ Adds a new velocities frame to the end of a NetCDF trajectory. This should only be called on objects created with the "open_new" constructor. Parameters ---------- stuff : iterable of floats or distance/time Quantity This array of floats is converted into a numpy array of shape (natom, 3). It can be passed either in the 2-D format of [ [x1, y1, z1], [x2, y2, z2], ... ] or in the 1-D format of [x1, y1, z1, x2, y2, z2, ... ]. """ if u.is_quantity(stuff): stuff = stuff.value_in_unit(u.angstrom/u.picosecond) stuff = np.asarray(stuff) self._ncfile.variables['velocities'][self._last_vel_frame] = \ np.reshape(stuff, (self.atom, 3)) / self.velocity_scale self._last_vel_frame += 1 self.flush()
def testChemistryProblems(self): """ Tests some gen-chem applications with Quantity's """ def work(f, dx): return f * dx F = 1.0 * u.kilogram * u.meter / u.second**2 dx = 1.0 * u.meter self.assertEqual(work(F, dx), 1.0 * u.joule) self.assertEqual(F, 1.0 * u.newton) def ideal_gas_law(P, V, T): R = u.MOLAR_GAS_CONSTANT_R return (P * V / (R * T)).in_units_of(u.mole) T = (273.0 + 37.0) * u.kelvin P = (1.01325e5) * u.pascals r = 0.5e-6 * u.meters V = 4 / 3 * math.pi * r**3 n = ideal_gas_law(P, V, T) val = 4 / 3 * math.pi * 0.5e-6**3 * 1 self.assertAlmostEqualQuantities(P * V, val * u.atmospheres * u.meters**3) self.assertAlmostEqualQuantities(n, 2.05834818672e-17 * u.mole) self.assertAlmostEqualQuantities(V, 5.2359833333333e-19 * u.meters**3) self.assertEqual(str(T), '310.0 K') self.assertEqual(str(u.MOLAR_GAS_CONSTANT_R.format('%.4f')), '8.3145 J/(K mol)') self.assertTrue(u.is_quantity(V)) # Checks trouble with complicated unit conversion factors p1 = 1.0 * u.atmospheres p2 = p1.in_units_of(u.joules / u.nanometers**3) V = 2.4 * u.nanometers**3 beta = 4.e-4 * u.mole / u.joule x1 = beta * p1 * V y1 = x1 * u.AVOGADRO_CONSTANT_NA self.assertAlmostEqual(y1, 0.0585785776197) x2 = beta * p2 * V y2 = x2 * u.AVOGADRO_CONSTANT_NA self.assertAlmostEqual(y1, y2)
def testChemistryProblems(self): """ Tests some gen-chem applications with Quantity's """ def work(f, dx): return f * dx F = 1.0 * u.kilogram * u.meter / u.second**2 dx = 1.0 * u.meter self.assertEqual(work(F, dx), 1.0 * u.joule) self.assertEqual(F, 1.0 * u.newton) def ideal_gas_law(P, V, T): R = u.MOLAR_GAS_CONSTANT_R return (P * V / (R * T)).in_units_of(u.mole) T = (273.0 + 37.0) * u.kelvin P = (1.01325e5) * u.pascals r = 0.5e-6 * u.meters V = 4/3 * math.pi * r**3 n = ideal_gas_law(P, V, T) val = 4/3*math.pi*0.5e-6**3*1 self.assertAlmostEqualQuantities(P*V, val * u.atmospheres*u.meters**3) self.assertAlmostEqualQuantities(n, 2.05834818672e-17 * u.mole) self.assertAlmostEqualQuantities(V, 5.2359833333333e-19 * u.meters**3) self.assertEqual(str(T), '310.0 K') self.assertEqual(str(u.MOLAR_GAS_CONSTANT_R.format('%.4f')), '8.3145 J/(K mol)') self.assertTrue(u.is_quantity(V)) # Checks trouble with complicated unit conversion factors p1 = 1.0 * u.atmospheres p2 = p1.in_units_of(u.joules/u.nanometers**3) V = 2.4 * u.nanometers**3 beta = 4.e-4 * u.mole/u.joule x1 = beta * p1 * V y1 = x1 * u.AVOGADRO_CONSTANT_NA self.assertAlmostEqual(y1, 0.0585785776197) x2 = beta * p2 * V y2 = x2 * u.AVOGADRO_CONSTANT_NA self.assertAlmostEqual(y1, y2)
def set_positions(positions): """ Sets the particle positions of the active system from the passed list of positions. Supports both lists, numpy.ndarray and numpy.ndarray objects Parameters ---------- positions : array of float The atomic positions. They can have units of length. They can have the shapes (natom*3,) or (natom, 3) """ if u.is_quantity(positions): positions = positions.value_in_unit(u.angstroms) # Common input types will have an natom x 3 shape. I can call "flatten" on # numpy arrays to solve this quickly, but in cases where the coordinates # are given as a list (or tuple) of Vec3's (or tuples), this requires # separate handling positions = _np.array(positions, copy=False, subok=True) positions = positions.flatten() natom = _pys.natom() if len(positions) != natom * 3: raise ValueError('Positions array must have natom*3 elements') return _pys.set_positions(positions.tolist())
def coordinates(self, value): if u.is_quantity(value): value = value.value_in_unit(u.angstroms) self._values = np.array(value).flatten()
def testScalarQuantityMultiplyDivide(self): """ Tests creating a scalar Quantity object by * or / by a Unit """ self.assertTrue(u.is_quantity(5 * u.centimeters)) self.assertTrue(u.is_quantity(1 / u.centimeters)) self.assertTrue(u.is_quantity(10 * u.centimeters)) self.assertTrue(u.is_quantity(9.81 * u.meters / u.second**2))
def strip_units(x): if u.is_quantity(x): return x.value_in_unit_system(u.akma_unit_system) return x
def testIsQuantity(self): """ Tests if is_quantity can detect Quantities vs. scalars and units """ self.assertTrue(u.is_quantity(1/u.second)) self.assertFalse(u.is_quantity(u.second**-1)) self.assertTrue(u.is_quantity(10*u.meters)) self.assertFalse(u.is_quantity(10))
def velocities(self, value): if u.is_quantity(value): value = value.value_in_unit(u.angstroms/u.picosecond) self._values = np.array(value).flatten()
def box_lengths_and_angles_to_vectors(a, b, c, alpha, beta, gamma): """ This function takes the lengths of the unit cell vectors and the angles between them and returns 3 unit cell vectors satisfying those dimensions Parameters ---------- a : double (or length Quantity) Length of the first unit cell vector b : double (or length Quantity) Length of the second unit cell vector c : double (or length Quantity) Length of the third unit cell vector alpha : double (or angle Quantity) Angle between vectors b and c beta : double (or angle Quantity) Angle between vectors a and c gamma : double (or angle Quantity) Angle between vectors a and b Returns ------- list Quantity, list Quantity, list Quantity The 3, 3-element vectors as quantities with dimension length Notes ----- The unit cell lengths are assumed to be Angstroms if no explicit unit is given. The angles are assumed to be degrees """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) if u.is_quantity(alpha): alpha = alpha.value_in_unit(u.degrees) if u.is_quantity(beta): beta = beta.value_in_unit(u.degrees) if u.is_quantity(gamma): gamma = gamma.value_in_unit(u.degrees) if alpha <= 2 * pi and beta <= 2 * pi and gamma <= 2 * pi: warnings.warn('Strange unit cell vector angles detected. They ' 'appear to be in radians...') alpha *= DEG_TO_RAD beta *= DEG_TO_RAD gamma *= DEG_TO_RAD av = [a, 0.0, 0.0] bx = b * cos(gamma) by = b * sin(gamma) bv = [bx, by, 0.0] cx = c * cos(beta) cy = c * (cos(alpha) - cos(beta) * cos(gamma)) / sin(gamma) cz = sqrt(c * c - cx * cx - cy * cy) cv = [cx, cy, cz] # Make sure that any tiny components are exactly 0 if abs(bx) < TINY: bv[0] = 0 if abs(by) < TINY: bv[1] = 0 if abs(cx) < TINY: cv[0] = 0 if abs(cy) < TINY: cv[1] = 0 if abs(cz) < TINY: cv[2] = 0 return (av, bv, cv) * u.angstroms
def testIsQuantity(self): """ Tests if is_quantity can detect Quantities vs. scalars and units """ self.assertTrue(u.is_quantity(1 / u.second)) self.assertFalse(u.is_quantity(u.second**-1)) self.assertTrue(u.is_quantity(10 * u.meters)) self.assertFalse(u.is_quantity(10))
def testNumpyQuantity(self): """ Tests that numpy arrays can form Quantity values """ q = u.Quantity(np.array([1, 2, 3]), u.centimeters) self.assertTrue(u.is_quantity(q)) self.assertIsInstance(q._value, np.ndarray) self.assertTrue(np.all(q / u.millimeters == np.array([1, 2, 3])*10))
def box_lengths_and_angles_to_vectors(a, b, c, alpha, beta, gamma): """ This function takes the lengths of the unit cell vectors and the angles between them and returns 3 unit cell vectors satisfying those dimensions Parameters ---------- a : double (or length Quantity) Length of the first unit cell vector b : double (or length Quantity) Length of the second unit cell vector c : double (or length Quantity) Length of the third unit cell vector alpha : double (or angle Quantity) Angle between vectors b and c beta : double (or angle Quantity) Angle between vectors a and c gamma : double (or angle Quantity) Angle between vectors a and b Returns ------- list Quantity, list Quantity, list Quantity The 3, 3-element vectors as quantities with dimension length Notes ----- The unit cell lengths are assumed to be Angstroms if no explicit unit is given. The angles are assumed to be degrees """ if u.is_quantity(a): a = a.value_in_unit(u.angstroms) if u.is_quantity(b): b = b.value_in_unit(u.angstroms) if u.is_quantity(c): c = c.value_in_unit(u.angstroms) if u.is_quantity(alpha): alpha = alpha.value_in_unit(u.degrees) if u.is_quantity(beta): beta = beta.value_in_unit(u.degrees) if u.is_quantity(gamma): gamma = gamma.value_in_unit(u.degrees) if alpha <= 2*pi and beta <= 2*pi and gamma <= 2*pi: warnings.warn('Strange unit cell vector angles detected. They ' 'appear to be in radians...') alpha *= DEG_TO_RAD beta *= DEG_TO_RAD gamma *= DEG_TO_RAD av = [a, 0.0, 0.0] bx = b * cos(gamma) by = b * sin(gamma) bv = [bx, by, 0.0] cx = c * cos(beta) cy = c * (cos(alpha) - cos(beta)*cos(gamma)) / sin(gamma) cz = sqrt(c*c - cx*cx - cy*cy) cv = [cx, cy, cz] # Make sure that any tiny components are exactly 0 if abs(bx) < TINY: bv[0] = 0 if abs(by) < TINY: bv[1] = 0 if abs(cx) < TINY: cv[0] = 0 if abs(cy) < TINY: cv[1] = 0 if abs(cz) < TINY: cv[2] = 0 return (av, bv, cv) * u.angstroms
def strip_units(x, desired_units): if u.is_quantity(x): return x.value_in_unit(desired_units) return x
def testNumpyQuantity(self): """ Tests that numpy arrays can form Quantity values """ q = u.Quantity(np.array([1, 2, 3]), u.centimeters) self.assertTrue(u.is_quantity(q)) self.assertIsInstance(q._value, np.ndarray) self.assertTrue(np.all(q / u.millimeters == np.array([1, 2, 3]) * 10))
def velocities(self, value): if u.is_quantity(value): value = value.value_in_unit(u.angstroms / u.picosecond) self._values = np.array(value).flatten()