Repository: MDAnalysis/mdanalysis (Python)

Issue:
Bug in conversion units of speed
## Expected behavior ##

When using ``MDAnalysis.units.convert`` to transform between different speed units, such as going from A/fs to A/ps, the conversion factor should be 1000 (and likewise for other conversion).


## Actual behavior ##

The unit conversions that involve conversion factors that deal with time units in the denominator (e.g A/ps to A/fs, A/ms to A/ps, ...) all yield the inverse of the correct conversion factor. 


## Code to reproduce the behavior ##

``` python
import MDAnalysis as mda
print(mda.units.convert(1, "A/fs", "A/ps")) # Gives 1e-3, should be 1e3

# The conversion between time and inverse time is inconsistent
# These yield the same number, and should be reciprocals

print(mda.units.convert(1, "fs", "ps"))
print(mda.units.convert(1, "A/fs", "A/ps"))

```

## Current version of MDAnalysis ##

- MDAnalysis version 2.9.0
- Python 3.12.9
- Linux OS



Discussion:
Hi! I would like to work on issue. Is this open?

@aditi25srivastava there's PR #5053, which is almost complete but the original author seems to not have been able to finish it. You could complete the PR and you would be co-credited with the original author @raulloiscuns . 
@orbeckst  Beckstein Thank you for the update! I’m interested in completing PR #5053 and happy to collaborate and co-credit with @raulloiscuns. Please assign the issue to me, and let me know if there are any specific guidelines or next steps you’d like me to follow. I’ll review the existing PR and start working on it right away.
No need to assign the issue to, you just create a PR that targets PR https://github.com/MDAnalysis/mdanalysis/pull/5053 . Once you have addressed the open comments pm #5053 , ask for a re-review by just pinging me on the PR.
okay!!




Patch:
diff --git a/package/AUTHORS b/package/AUTHORS
index 06aa44debfe..1cb4b5b5c39 100644
--- a/package/AUTHORS
+++ b/package/AUTHORS
@@ -262,6 +262,7 @@ Chronological list of authors
   - Sirsha Ganguly
   - Amruthesh Thirumalaiswamy
   - Ch Zhang
+  - Raúl Lois-Cuns  
 
 External code
 -------------
diff --git a/package/CHANGELOG b/package/CHANGELOG
index 3d69f1370c0..e1768284d03 100644
--- a/package/CHANGELOG
+++ b/package/CHANGELOG
@@ -16,16 +16,19 @@ The rules for this file:
 -------------------------------------------------------------------------------
 ??/??/?? IAlibay, orbeckst, BHM-Bob, TRY-ER, Abdulrahman-PROG, pbuslaev,
          yuxuanzhuang, yuyuan871111, tanishy7777, tulga-rdn, Gareth-elliott,
-         hmacdope, tylerjereddy, cbouy, talagayev, DrDomenicoMarson, amruthesht, 
-         p-j-smith, gitzhangch
-
+         hmacdope, tylerjereddy, cbouy, talagayev, DrDomenicoMarson, amruthesht,
+         p-j-smith, gitzhangch, raulloiscuns
 
  * 2.10.0
 
 Fixes
+ * Fix incorrect conversion factors for speed units A/fs, A/us, A/ms
+   in MDAnalysis.units (Issue #5051, PR #5053)
+ * `analysis.polymer.sort_backbone` is now working for discontinuous polymers
+   and does not result in an infinite loop (Issue #5112, PR #5113)
  * Fix atom selection parsing to allow escaping keywords with a backslash
    (Issue #5111, PR #5119)
- * Fix DCDWriter to correctly write unit cell angles as cosines following 
+ * Fix DCDWriter to correctly write unit cell angles as cosines following
    NAMD/VMD convention (Issue #5069)
  * Fixed an integer overflow in large DCD file seeks on Windows
    (Issue #4879, PR #5086)
@@ -37,19 +40,19 @@ Fixes
  * Fixes bug in `analysis/gnm.py`: `closeContactGNMAnalysis`: correct the
    `residue_index_map` generation when selection is not `protein`.
    (Issue #4924, PR #4961)
- * Reads `segids` column in `PDBParser` from 73-76 instead of 67-76 to 
-   align the standard of a PDBReader (e.g., Chimera, CHARMM, Gemmi). 
+ * Reads `segids` column in `PDBParser` from 73-76 instead of 67-76 to
+   align the standard of a PDBReader (e.g., Chimera, CHARMM, Gemmi).
    (Issue #4948, PR #5001)
  * Fixes the benchmark `SimpleRmsBench` in `benchmarks/analysis/rms.py`
    by changing the way weights for RMSD are calculated, instead of
    directly passing them. (Issue #3520, PR #5006)
- * `analysis.polymer.sort_backbone` is now working for discontinuous polymers
-    and does not result in an infinite loop (Issue #5112, PR #5113)
 
 Enhancements
- * Improved performance of `analysis.rdf.InterRDF_s` > 20-fold  
+ * Add conversion factor for speed unit A/ns and additional representations (Å/fs, A/µs,
+   Å/μs, Å/ms) (PR #5053)
+ * Improved performance of `analysis.rdf.InterRDF_s` > 20-fold
    by using vectorized NumPy calculations. (Issue #5067, PR #5073)
- * Parallelize `analysis.rdf.InterRDF` and `analysis.rdf.InterRDF` (Issue #4675)   
+ * Parallelize `analysis.rdf.InterRDF` and `analysis.rdf.InterRDF` (Issue #4675)
  * Support for Python 3.14 was added (PR #5121).
  * Added support for reading and processing streamed data in `coordinates.base`
    with new `StreamFrameIteratorSliced` and `StreamReaderBase` (Issue #4827, PR #4923)
@@ -68,13 +71,13 @@ Enhancements
  * Improve parsing of topology information from LAMMPS dump files to allow
    reading of mass, charge and element attributes. (Issue #3449, PR #4995)
  * Added timestep support for XDR writers and readers (Issue #4905, PR #4908)
- * New feature in `Universe`: `set_groups`. This function allows updating 
-   `_topology`, `residues` (ResidueGroup), `segments` (SegmentGroup) in 
-   the `Universe` using user-provided atomwise `resids` and/or `segids`. 
-   (Issue #4948 #2874, PR #4965)   
- * Adds an argument `force_chainids_to_segids` in `PDBParser`: this will 
-   force the use of ChainID as the segID when reading PDB (it is helpful 
-   if the segment IDs (segids) are partially missing in the PDB file). 
+ * New feature in `Universe`: `set_groups`. This function allows updating
+   `_topology`, `residues` (ResidueGroup), `segments` (SegmentGroup) in
+   the `Universe` using user-provided atomwise `resids` and/or `segids`.
+   (Issue #4948 #2874, PR #4965)
+ * Adds an argument `force_chainids_to_segids` in `PDBParser`: this will
+   force the use of ChainID as the segID when reading PDB (it is helpful
+   if the segment IDs (segids) are partially missing in the PDB file).
    (Issue #4948 #2874, PR #4965)
  * Enables parallelization for analysis.lineardensity.LinearDensity
    (Issue #4678, PR #5007)
@@ -84,18 +87,19 @@ Enhancements
    so that it gets passed through from the calling functions and classes
    (PR #5038)
  * Moved distopia checking function to common import location in
-   MDAnalysisTest.util (PR #5038)  
+   MDAnalysisTest.util (PR #5038)
  * Enables parallelization for `analysis.polymer.PersistenceLength` (Issue #4671, PR #5074)
 
 
 Changes
+ * Output precision for LAMMPS Data files set to 10 decimals (PR #5053)
  * Support for Python 3.10 was removed, in line with SPEC0 (PR #5121).
  * Refactored the RDKit converter code to move the inferring code in a separate
    `RDKitInferring` module. The bond order and charges inferrer has been move to
    an `MDAnalysisInferrer` dataclass in there. (PR #4305)
  * Removed undocumented and unused attribute
    `analysis.lineardensity.LinearDensity.totalmass` (PR #5007)
- * Remove `default` channel from RTD conda env. (Issue # 5036, PR # 5037)   
+ * Remove `default` channel from RTD conda env. (Issue # 5036, PR # 5037)
 
 
 Deprecations
@@ -119,7 +123,7 @@ Fixes
    the function to prevent shared state. (Issue #4655)
 
 Enhancements
- * Improve distopia backend support in line with new functionality available 
+ * Improve distopia backend support in line with new functionality available
    in distopia >= 0.3.1 (PR #4734)
  * Addition of 'water' token for water selection (Issue #4839)
  * Enables parallelization for analysis.density.DensityAnalysis
@@ -145,7 +149,7 @@ Changes
 
 11/11/24 IAlibay, HeetVekariya, marinegor, lilyminium, RMeli,
          ljwoods2, aditya292002, pstaerk, PicoCentauri, BFedder,
-         tyler.je.reddy, SampurnaM, leonwehrhan, kainszs, orionarcher, 
+         tyler.je.reddy, SampurnaM, leonwehrhan, kainszs, orionarcher,
          yuxuanzhuang, PythonFZ, laksh-krishna-sharma, orbeckst, MattTDavies,
          talagayev, aya9aladdin
 
@@ -211,7 +215,7 @@ Enhancements
  * Explicitly mark `analysis.pca.PCA` as not parallelizable (Issue #4680)
  * Enables parallelization for analysis.bat.BAT (Issue #4663)
  * Enable parallelization for analysis.dihedrals.{Dihedral,Ramachandran,Janin}
-   (Issue #4673) 
+   (Issue #4673)
  * Enables parallelization for analysis.dssp.dssp.DSSP (Issue #4674)
  * Enables parallelization for analysis.hydrogenbonds.hbond_analysis.HydrogenBondAnalysis (Issue #4664)
  * Improve error message for `AtomGroup.unwrap()` when bonds are not present.(Issue #4436, PR #4642)
@@ -244,9 +248,9 @@ Changes
  * As per NEP29, the minimum version of numpy has been raised to 1.23.
    We have opted to pin to 1.23.2 to ensure the same minimum numpy version
    is used from python 3.9 to 3.11 (Issue #4401, PR #4402)
- * updated tests that used assert_almost_equal(..., decimal={N}) with 
+ * updated tests that used assert_almost_equal(..., decimal={N}) with
    equivalent assert_allclose(...  rtol=0, atol=1.5e-{N}) (issue modernize
-   testing code #3743, PR Replaced numpy.testing.assert_almost_equal to 
+   testing code #3743, PR Replaced numpy.testing.assert_almost_equal to
    numpy.testing.assert_allclose #4438)
 
 Deprecations
@@ -278,8 +282,8 @@ Deprecations
    (PR #4403)
 
 
-12/26/23 IAlibay, ianmkenney, PicoCentauri, pgbarletta, p-j-smith, 
-         richardjgowers, lilyminium, ALescoulie, hmacdope, HeetVekariya, 
+12/26/23 IAlibay, ianmkenney, PicoCentauri, pgbarletta, p-j-smith,
+         richardjgowers, lilyminium, ALescoulie, hmacdope, HeetVekariya,
          JoStoe, jennaswa, ljwoods2
 
  * 2.7.0
@@ -297,7 +301,7 @@ Fixes
     RMSD of None
   * Fixes hydrogenbonds tutorial path to point to hbonds (Issue #4285, PR #4286)
   * Fix atom charge reading in PDBQT parser (Issue #4282, PR #4283)
-  * Fix doctests failing from separated blocks of imports and 
+  * Fix doctests failing from separated blocks of imports and
     execution and incorrectly formatted test output (Issue #3925, PR #4366)
 
 Enhancements
@@ -313,8 +317,8 @@ Enhancements
   * Added a warning about charge neutrality to the documentation of
     `DielectricConstant` (Issue #4262, PR #4263)
   * Add support for reading chainID info from prmtop amber topologies (PR #4007)
-  * Add support for reading chainID info from GROMACS TPR topologies 
-    (Issue #3994, PR #4281)  
+  * Add support for reading chainID info from GROMACS TPR topologies
+    (Issue #3994, PR #4281)
   * Add support for reading chainID info from Autodock PDBQT files (Issue #4207,
     PR #4284)
 
@@ -328,7 +332,7 @@ Changes
     replacing the now deprecated `xdrlib` core Python library
     (PR #4271)
   * ConverterBase class moved from coordinates/base.py to converters/base.py (Issue #3404)
-  * Results for WatsonCrickDist nucleic acids analysis are now stored in 
+  * Results for WatsonCrickDist nucleic acids analysis are now stored in
     `analysis.nucleicacids.WatsonCrickDist.results.distances` (Issue #3720, PR #3735)
 
 Deprecations
@@ -345,7 +349,7 @@ Deprecations
     in favor of using `ResidueGroup`: using `List[Residue]` will be removed in release
     3.0.0; instead use a `ResidueGroup` (Issue #3720, PR #3735)
   * In `nucleicacids.WatsonCrickDist` the result `results.pair_distances` was
-    deprecated and will be removed in 3.0.0; use `results.distances` (Issue #3720, 
+    deprecated and will be removed in 3.0.0; use `results.distances` (Issue #3720,
     PR #3735)
 
 
@@ -397,7 +401,7 @@ Changes
     of NEP29 (PR #4108).
   * Removed `-ffast-math` compiler flag to avoid potentially incorrect
     floating point results in MDAnalysis *and* other codes when
-    MDAnalysis shared libraries are loaded --- see 
+    MDAnalysis shared libraries are loaded --- see
     https://moyix.blogspot.com/2022/09/someones-been-messing-with-my-subnormals.html
     (Issues #3821, #4211)
   * Atom ID representation order updated to match that of associated
@@ -428,7 +432,7 @@ Deprecations
     32 bit compatible versions. (Issue #3858, PR #4176)
 
 
-05/28/23 IAlibay, pgbarletta, mglagolev, hmacdope, manuel.nuno.melo, chrispfae, 
+05/28/23 IAlibay, pgbarletta, mglagolev, hmacdope, manuel.nuno.melo, chrispfae,
          ooprathamm, MeetB7, BFedder, v-parmar, MoSchaeffler, jbarnoud, jandom,
          xhgchen, jaclark5, DrDomenicoMarson, AHMED-salah00, schlaicha,
          SophiaRuan, g2707, p-j-smith, tylerjereddy, xiki-tempula, richardjgowers,
@@ -492,13 +496,13 @@ Enhancements
   * Add distopia distance calculation library bindings as a selectable backend
     for `calc_bonds` in `MDA.lib.distances`. (Issue #3783, PR #3914)
   * AuxReaders are now pickle-able and copy-able (Issue #1785, PR #3887)
-  * Add pickling support for Atom, Residue, Segment, ResidueGroup 
+  * Add pickling support for Atom, Residue, Segment, ResidueGroup
     and SegmentGroup. (PR #3953)
 
 Changes
   * As per NEP29 the minimum supported Python version has been raised to 3.9
     (PR #4115).
-  * einsum method for Einstein summation convention introduced to increase 
+  * einsum method for Einstein summation convention introduced to increase
     performance (Issue #2063, PR #4089)
   * Add progress bars to track the progress of _conclude() functions
     (_conclude_simple() and _conclude_fft()) in msd.py (Issue #4070, PR #4072)
@@ -558,16 +562,16 @@ Fixes
  * 2.4.0
 
 Fixes
-  * Update hbond analysis doc string to use exclusive bound language 
+  * Update hbond analysis doc string to use exclusive bound language
     (Issue #3847)
   * XTC and TRR readers now fail with IOError when a status except EOK (=0) is
     detected on reading a frame instead of silently continuing
   * Consolidate license files across MDAnalysis library packages (PR #3939)
   * Kwargs passed through to `MemoryReader` when using `transfer_to_memory()`
     and `in_memory=True`.
-  * NoDataError raised on empty atomgroup provided to `DCDReader.timeseries` 
+  * NoDataError raised on empty atomgroup provided to `DCDReader.timeseries`
     was changed to ValueError (see #3901). A matching ValueError was added to
-    `MemoryReader.timeseries`(PR #3890). 
+    `MemoryReader.timeseries`(PR #3890).
   * Removes ``pbc`` kwarg from ``AtomGroup.wrap`` (Issue #3909)
   * LAMMPSDump Reader translates the box to the origin (#3741)
   * hbond analysis: access hbonds results through new results member in count_by_ids() and count_by_type()
@@ -575,7 +579,7 @@ Fixes
     behaviour for cutoff values < -1 (PR # 3749)
   * Fixes distances.between not always returning AtomGroup (Issue #3794)
   * Upgrade to chemfiles 0.10.3 (Issue #3798)
-  * fixes guessed_attributes and read_attributes methods of the Topology class, as 
+  * fixes guessed_attributes and read_attributes methods of the Topology class, as
     those methods were giving unexpected results for some topology attributes
     (e.g. bonds, angles) (PR #3779).
 
@@ -584,12 +588,12 @@ Enhancements
     (Issue #3841, PR #3842)
   * MDAnalysis now follows PEP621 (PR #3528)
   * Added a reader for GROMACS TNG files based on PyTNG (PR #3765,
-    Issue #3237, partially addressing Issue #865) 
-  * Added ability for hbond analysis to use types when resnames are not 
+    Issue #3237, partially addressing Issue #865)
+  * Added ability for hbond analysis to use types when resnames are not
     present (Issue #3847)
   * Added explanatory warnings when hbond analysis doesn't find any hbonds
     (Issue #3847)
-  * Improve C content of libxdr Cython, add `read_direct` methods to read 
+  * Improve C content of libxdr Cython, add `read_direct` methods to read
     coordinates, velocities and forces directly into memoryviews of `Timestep`
     attributes, make `TRR` timestep have positions, velocities and forces on
     `__init__`. (Issue #3891 PR  #3892).
@@ -597,11 +601,11 @@ Enhancements
   * The timeseries method for exporting coordinates from multiple frames to a
     NumPy array was added to ProtoReader (PR #3890)
   * MDAnalysis now officially supports py3.11 (Issue #3878)
-  * LAMMPSDump Reader optionally unwraps trajectories with image flags upon 
+  * LAMMPSDump Reader optionally unwraps trajectories with image flags upon
     loading (Issue #3843)
   * LAMMPSDump Reader now imports velocities and forces (Issue #3843)
   * Minimum NumPy version for py3.11 is now set to 1.23.2.
-  * Added decorator to check for an empty atom group, applied in topological 
+  * Added decorator to check for an empty atom group, applied in topological
     attributes(Issue #3837)
   * AuxReaders now have a memory_limit parameter to control when memory usage
     warnings are issued. (PR # 3749)
diff --git a/package/MDAnalysis/coordinates/LAMMPS.py b/package/MDAnalysis/coordinates/LAMMPS.py
index df570af724f..6e0043321d3 100644
--- a/package/MDAnalysis/coordinates/LAMMPS.py
+++ b/package/MDAnalysis/coordinates/LAMMPS.py
@@ -26,8 +26,8 @@
 ===============================================================================
 
 Classes to read and write LAMMPS_ DCD binary trajectories, LAMMPS DATA files
-and LAMMPS dump files.  Trajectories can be read regardless of system-endianness
-as this is auto-detected.
+and LAMMPS dump files.  Trajectories can be read regardless of
+system-endianness as this is auto-detected.
 
 LAMMPS can `write DCD`_ trajectories but unlike a `CHARMM trajectory`_
 (which is often called a DCD even though CHARMM itself calls them
@@ -81,7 +81,7 @@
 data file,
 
    >>> import MDAnalysis
-   >>> from MDAnalysis.tests.datafiles import LAMMPSdata2, LAMMPSdcd2 
+   >>> from MDAnalysis.tests.datafiles import LAMMPSdata2, LAMMPSdcd2
    >>> u = MDAnalysis.Universe(LAMMPSdata2, LAMMPSdcd2, format="LAMMPS",
    ...                          lengthunit="nm", timeunit="ns")
    >>> take_this_frame = False
@@ -107,7 +107,8 @@
 
 .. _LAMMPS: https://www.lammps.org/
 .. _write DCD: https://docs.lammps.org/dump.html
-.. _CHARMM trajectory: http://www.charmm.org/documentation/c36b1/dynamc.html#%20Trajectory
+.. _CHARMM trajectory:
+   http://www.charmm.org/documentation/c36b1/dynamc.html#%20Trajectory
 .. _AKMA: http://www.charmm.org/documentation/c36b1/usage.html#%20AKMA
 .. _units real: https://docs.lammps.org/units.html
 .. _units command: https://docs.lammps.org/units.html
@@ -180,9 +181,8 @@ def __init__(self, *args, **kwargs):
             try:
                 if units.unit_types[unit] != unit_type:
                     raise TypeError(
-                        "LAMMPS DCDWriter: wrong unit {0!r} for unit type {1!r}".format(
-                            unit, unit_type
-                        )
+                        f"LAMMPS DCDWriter: wrong unit {unit} for "
+                        f"unit type {unit_type}"
                     )
             except KeyError:
                 errmsg = f"LAMMPS DCDWriter: unknown unit {unit}"
@@ -216,14 +216,11 @@ def __init__(self, dcdfilename, **kwargs):
             try:
                 if units.unit_types[unit] != unit_type:
                     raise TypeError(
-                        "LAMMPS DCDReader: wrong unit {0!r} for unit type {1!r}".format(
-                            unit, unit_type
-                        )
+                        f"LAMMPS DCDReader: wrong unit {unit} for "
+                        f"unit type {unit_type}"
                     )
             except KeyError:
-                raise ValueError(
-                    "LAMMPS DCDReader: unknown unit {0!r}".format(unit)
-                )
+                raise ValueError(f"LAMMPS DCDReader: unknown unit {unit}")
         super(DCDReader, self).__init__(dcdfilename, **kwargs)
 
 
@@ -344,7 +341,7 @@ def _write_atoms(self, atoms, data):
                 x, y, z = coords
                 self.f.write(
                     f"{index:d} {moltag:d} {atype:d} {charge:f}"
-                    f" {x:f} {y:f} {z:f}\n"
+                    f" {x:.10f} {y:.10f} {z:.10f}\n"
                 )
         else:
             for index, moltag, atype, coords in zip(
@@ -352,7 +349,7 @@ def _write_atoms(self, atoms, data):
             ):
                 x, y, z = coords
                 self.f.write(
-                    f"{index:d} {moltag:d} {atype:d}" f" {x:f} {y:f} {z:f}\n"
+                    f"{index:d} {moltag:d} {atype:d} {x:.10f} {y:.10f} {z:.10f}\n"
                 )
 
     def _write_velocities(self, atoms):
@@ -365,7 +362,7 @@ def _write_velocities(self, atoms):
         )
         for index, vel in zip(indices, velocities):
             self.f.write(
-                "{i:d} {x:f} {y:f} {z:f}\n".format(
+                "{i:d} {x:.10f} {y:.10f} {z:.10f}\n".format(
                     i=index, x=vel[0], y=vel[1], z=vel[2]
                 )
             )
@@ -613,7 +610,8 @@ class DumpReader(base.ReaderBase):
         <https://docs.lammps.org/read_data.html>`__  in the lammps
         documentation for more information.
     **kwargs
-       Other keyword arguments used in :class:`~MDAnalysis.coordinates.base.ReaderBase`
+       Other keyword arguments used in
+       :class:`~MDAnalysis.coordinates.base.ReaderBase`
 
 
     .. versionchanged:: 2.8.0
@@ -832,9 +830,8 @@ def _read_next_timestep(self):
                 raise ValueError("No coordinate information detected")
         elif not self.lammps_coordinate_convention in convention_to_col_ix:
             raise ValueError(
-                f"No coordinates following convention "
-                "{self.lammps_coordinate_convention} found in "
-                "timestep"
+                "No coordinates following convention "
+                f"{self.lammps_coordinate_convention} found in timestep"
             )
 
         coord_cols = convention_to_col_ix[self.lammps_coordinate_convention]
diff --git a/package/MDAnalysis/units.py b/package/MDAnalysis/units.py
index 4f186521190..d52e46d86c1 100644
--- a/package/MDAnalysis/units.py
+++ b/package/MDAnalysis/units.py
@@ -193,8 +193,8 @@ def __getitem__(self, key):
 #       test_units:TestConstants.constants_reference !
 
 #: Values of physical constants are taken from `CODATA 2010 at NIST`_. The
-#: thermochemical calorie is defined in the `ISO 80000-5:2007`_ standard
-#: and is also listed in the `NIST Guide to SI: Appendix B.8: Factors for Units`_.
+#: thermochemical calorie is defined in the `ISO 80000-5:2007`_ standard and
+#: is also listed in the `NIST Guide to SI: Appendix B.8: Factors for Units`_.
 #:
 #: .. _`CODATA 2010 at NIST`:
 #:    http://physics.nist.gov/cuu/Constants/
@@ -215,7 +215,8 @@ def __getitem__(self, key):
 )
 
 #: The basic unit of *length* in MDAnalysis is the Angstrom.
-#: Conversion factors between the base unit and other lengthUnits *x* are stored.
+#: Conversion factors between the base unit and other lengthUnits *x* are
+#: stored.
 #: Conversions follow `L/x = L/Angstrom * lengthUnit_factor[x]`.
 #: *x* can be *nm*/*nanometer* or *fm*.
 lengthUnit_factor = {
@@ -301,23 +302,32 @@ def __getitem__(self, key):
     "\u212b/ps": 1.0,
     "Angstrom/picosecond": 1.0,
     "angstrom/picosecond": 1.0,  # 1
-    "Angstrom/fs": 1.0 * 1e3,
-    "Angstrom/femtosecond": 1.0 * 1e3,
-    "angstrom/femtosecond": 1.0 * 1e3,
-    "angstrom/fs": 1.0 * 1e3,
-    "A/fs": 1.0 * 1e3,
-    "Angstrom/ms": 1.0 * 1e-9,
-    "Angstrom/millisecond": 1.0 * 1e-9,
-    "angstrom/millisecond": 1.0 * 1e-9,
-    "angstrom/ms": 1.0 * 1e-9,
-    "A/ms": 1.0 * 1e-9,
-    "Angstrom/us": 1.0 * 1e-6,
-    "angstrom/us": 1.0 * 1e-6,
-    "A/us": 1.0 * 1e-6,
-    "Angstrom/microsecond": 1.0 * 1e-6,
-    "angstrom/microsecond": 1.0 * 1e-6,
-    "Angstrom/\u03BCs": 1.0 * 1e-6,
-    "angstrom/\u03BCs": 1.0 * 1e-6,
+    "Angstrom/fs": 1.0 * 1e-3,
+    "Angstrom/femtosecond": 1.0 * 1e-3,
+    "angstrom/femtosecond": 1.0 * 1e-3,
+    "angstrom/fs": 1.0 * 1e-3,
+    "A/fs": 1.0 * 1e-3,
+    "\u212b/fs": 1.0 * 1e-3,
+    "Angstrom/ns": 1.0 * 1e3,
+    "A/ns": 1.0 * 1e3,
+    "\u212b/ns": 1.0 * 1e3,
+    "Angstrom/nanosecond": 1.0 * 1e3,
+    "angstrom/nanosecond": 1.0 * 1e3,
+    "Angstrom/us": 1.0 * 1e6,
+    "angstrom/us": 1.0 * 1e6,
+    "A/us": 1.0 * 1e6,
+    "A/\u03BCs": 1.0 * 1e6,
+    "\u212b/\u03BCs": 1.0 * 1e6,
+    "Angstrom/microsecond": 1.0 * 1e6,
+    "angstrom/microsecond": 1.0 * 1e6,
+    "Angstrom/\u03BCs": 1.0 * 1e6,
+    "angstrom/\u03BCs": 1.0 * 1e6,
+    "Angstrom/ms": 1.0 * 1e9,
+    "Angstrom/millisecond": 1.0 * 1e9,
+    "angstrom/millisecond": 1.0 * 1e9,
+    "angstrom/ms": 1.0 * 1e9,
+    "A/ms": 1.0 * 1e9,
+    "\u212b/ms": 1.0 * 1e9,
     "Angstrom/AKMA": 4.888821e-2,
     "A/AKMA": 4.888821e-2,
     "nm/ps": 0.1,
@@ -354,11 +364,12 @@ def __getitem__(self, key):
 #: *elementary_charge* in :data:`constants`.
 #: The `conversion factor to Amber charge units`_ is 18.2223.
 #:
-#: .. _`conversion factor to Amber charge units`: https://ambermd.org/FileFormats.php#parm.dat
+#: .. _`conversion factor to Amber charge units`:
+#:    https://ambermd.org/FileFormats.php#parm.dat
 #:
 #: .. versionchanged:: 0.9.0
-#:    Use CODATA 2010 value for *elementary charge*, which differs from the previously used value
-#:    *e* =  1.602176487 x 10**(-19) C by 7.8000000e-27 C.
+#:    Use CODATA 2010 value for *elementary charge*, which differs from the previously
+#:    used value *e* =  1.602176487 x 10**(-19) C by 7.8000000e-27 C.
 chargeUnit_factor = {
     "e": 1.0,
     "Amber": 18.2223,  # https://ambermd.org/FileFormats.php#parm.dat


Test patch:
diff --git a/testsuite/MDAnalysisTests/coordinates/reference.py b/testsuite/MDAnalysisTests/coordinates/reference.py
index 8d43a9f925b..5f74a64dd04 100644
--- a/testsuite/MDAnalysisTests/coordinates/reference.py
+++ b/testsuite/MDAnalysisTests/coordinates/reference.py
@@ -232,7 +232,7 @@ class RefLAMMPSData(object):
         [11.89985657, 48.4455719, 19.09719849], dtype=np.float32
     )
     vel_atom1 = np.array(
-        [-0.005667593, 0.00791380978, -0.00300779533], dtype=np.float32
+        [-5667.59300232, 7913.80977631, -3007.79533386], dtype=np.float32
     )
     dimensions = np.array(
         [55.42282867, 55.42282867, 55.42282867, 90.0, 90.0, 90.0],
@@ -260,7 +260,7 @@ class RefLAMMPSDataMini(object):
         [11.89985657, 48.4455719, 19.09719849], dtype=np.float32
     )
     vel_atom1 = np.array(
-        [-0.005667593, 0.00791380978, -0.00300779533], dtype=np.float32
+        [-5667.59300232, 7913.80977631, -3007.79533386], dtype=np.float32
     )
     dimensions = np.array(
         [60.0, 50.0, 30.0, 90.0, 90.0, 90.0], dtype=np.float32
diff --git a/testsuite/MDAnalysisTests/utils/test_units.py b/testsuite/MDAnalysisTests/utils/test_units.py
index 8121188c1c6..dad63d6b11c 100644
--- a/testsuite/MDAnalysisTests/utils/test_units.py
+++ b/testsuite/MDAnalysisTests/utils/test_units.py
@@ -88,6 +88,7 @@ def _assert_almost_equal_convert(value, u1, u2, ref):
         (
             (nm, "nm", "A", A),
             (A, "Angstrom", "nm", nm),
+            (A, "\u212b", "nm", nm),
         ),
     )
     def test_length(self, quantity, unit1, unit2, ref):
@@ -102,6 +103,8 @@ def test_length(self, quantity, unit1, unit2, ref):
             (1, "ms", "ps", 1e9),
             (1, "ps", "us", 1e-6),
             (1, "us", "ps", 1e6),
+            (1, "\u03BCs", "ps", 1e6),
+            (1, "fs", "ns", 1e-6),
         ),
     )
     def test_time(self, quantity, unit1, unit2, ref):
@@ -134,9 +137,17 @@ def test_force(self, quantity, unit1, unit2, ref):
             (1, "A/ps", "m/s", 1e-10 / 1e-12),
             (1, "A/ps", "nm/ps", 0.1),
             (1, "A/ps", "pm/ps", 1e2),
-            (1, "A/ms", "A/ps", 1e9),
-            (1, "A/us", "A/ps", 1e6),
-            (1, "A/fs", "A/ps", 1e-3),
+            (1, "A/ms", "A/ps", 1e-9),
+            (1, "A/us", "A/ps", 1e-6),
+            (1, "A/\u03BCs", "A/ps", 1e-6),
+            (1, "\u212b/\u03BCs", "A/ps", 1e-6),
+            (1, "A/fs", "A/ps", 1e3),
+            (1, "A/ps", "A/fs", 1e-3),
+            (1, "A/ns", "A/ms", 1e6),
+            (1, "\u212b/ns", "A/ms", 1e6),
+            (1, "A/ps", "A/ps", 1.0),
+            (1, "nm/ns", "pm/ps", 1.0),
+            (1, "m/s", "A/fs", 1e-5),
             (1, "A/AKMA", "A/ps", 1 / 4.888821e-2),
         ),
     )