Source code for BioSimSpace.Types._time

######################################################################
# BioSimSpace: Making biomolecular simulation a breeze!
#
# Copyright: 2017-2024
#
# Authors: Lester Hedges <lester.hedges@gmail.com>
#
# BioSimSpace is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BioSimSpace is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BioSimSpace. If not, see <http://www.gnu.org/licenses/>.
#####################################################################

"""A time type."""

__author__ = "Lester Hedges"
__email__ = "lester.hedges@gmail.com"

__all__ = ["Time"]

from sire.legacy import Units as _SireUnits

from ._type import Type as _Type


[docs] class Time(_Type): """A time type.""" # A list of the supported Sire unit names. _sire_units = [ "day", "hour", "minute", "second", "millisecond", "nanosecond", "picosecond", "femtosecond", ] # Dictionary of allowed units. _supported_units = { "DAY": _SireUnits.day, "HOUR": _SireUnits.hour, "MINUTE": _SireUnits.minute, "SECOND": _SireUnits.second, "MILLISECOND": _SireUnits.millisecond, "NANOSECOND": _SireUnits.nanosecond, "PICOSECOND": _SireUnits.picosecond, "FEMTOSECOND": _SireUnits.femtosecond, } # Map unit abbreviations to the full name. _abbreviations = { "HR": "HOUR", "MIN": "MINUTE", "SEC": "SECOND", "MS": "MILLISECOND", "NS": "NANOSECOND", "PS": "PICOSECOND", "FS": "FEMTOSECOND", } # Print formatting. _print_format = { "DAY": "day", "HOUR": "hour", "MINUTE": "min", "SECOND": "sec", "MILLISECOND": "ms", "NANOSECOND": "ns", "PICOSECOND": "ps", "FEMTOSECOND": "fs", } # Documentation strings. _doc_strings = { "DAY": "A time in days.", "HOUR": "A time in hours.", "MINUTE": "A time in minutes.", "SECOND": "A time in seconds.", "MILLISECOND": "A time in milliseconds.", "NANOSECOND": "A time in nanoseconds.", "PICOSECOND": "A time in picoseconds.", "FEMTOSECOND": "A time in femtoseconds.", } # Null type unit for avoiding issue printing configargparse help. _default_unit = "NANOSECOND" # The dimension mask. _dimensions = tuple(list(_supported_units.values())[0].dimensions())
[docs] def __init__(self, *args): """ Constructor. ``*args`` can be a value and unit, or a string representation of the time, e.g. "0.2 fs". Parameters ---------- value : float The value. unit : str The unit. string : str A string representation of the time. Examples -------- Create an object representing a time of 17.3 femtoseconds then print the time in nanoseconds. >>> import BioSimSpace as BSS >>> time = BSS.Types.Time(17.3, "fs") >>> print(time.nanoseconds()) The same as above, except passing a string representation of the time to the constructor. >>> import BioSimSpace as BSS >>> time = BSS.Types.Time("17.3 fs") >>> print(time.nanoseconds()) The string matching is extremeley flexible, so all of the following would be valid arguments: "17.3 fs", "17.3 femtoseconds", "1.73e1 fs". """ # Call the base class constructor. super().__init__(*args)
def __str__(self): """Return a human readable string representation of the object.""" abbrev = self._print_format[self._unit] if self._value != 1: if abbrev[-1] != "s": abbrev = abbrev + "s" if abs(self._value) > 1e4 or abs(self._value) < 1e-4: return "%.4e %s" % (self._value, abbrev) else: return "%5.4f %s" % (self._value, abbrev)
[docs] def days(self): """ Return the time in days. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in days. """ return Time( (self._value * self._supported_units[self._unit]).to(_SireUnits.day), "DAY" )
[docs] def hours(self): """ Return the time in hours. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in hours. """ return Time( (self._value * self._supported_units[self._unit]).to(_SireUnits.hour), "HOUR", )
[docs] def minutes(self): """ Return the time in minutes. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in minutes. """ return Time( (self._value * self._supported_units[self._unit]).to(_SireUnits.minute), "MINUTE", )
[docs] def seconds(self): """ Return the time in seconds. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in seconds. """ return Time( (self._value * self._supported_units[self._unit]).to(_SireUnits.second), "SECOND", )
[docs] def milliseconds(self): """ Return the time in milliseconds. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in milliseconds. """ return Time( (self._value * self._supported_units[self._unit]).to( _SireUnits.millisecond ), "MILLISECOND", )
[docs] def nanoseconds(self): """ Return the time in nanoseconds. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in nanoseconds. """ return Time( (self._value * self._supported_units[self._unit]).to(_SireUnits.nanosecond), "NANOSECOND", )
[docs] def picoseconds(self): """ Return the time in picoseconds. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in picoseconds. """ return Time( (self._value * self._supported_units[self._unit]).to(_SireUnits.picosecond), "PICOSECOND", )
[docs] def femtoseconds(self): """ Return the time in femtoseconds. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in femtoseconds. """ return Time( (self._value * self._supported_units[self._unit]).to( _SireUnits.femtosecond ), "FEMTOSECOND", )
def _to_default_unit(self, mag=None): """ Internal method to return an object of the same type in the default unit. Parameters ---------- mag : float The value (optional). Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in the default unit of picoseconds. """ if mag is None: return self.picoseconds() else: return Time(mag, "PICOSECOND") def _convert_to(self, unit): """ Return the time in a different unit. Parameters ---------- unit : str The unit to convert to. Returns ------- time : :class:`Time <BioSimSpace.Types.Time>` The time in the specified unit. """ if unit == "DAY": return self.days() elif unit == "HOUR": return self.hours() elif unit == "MINUTE": return self.minutes() elif unit == "SECOND": return self.seconds() elif unit == "MILLISECOND": return self.milliseconds() elif unit == "NANOSECOND": return self.nanoseconds() elif unit == "PICOSECOND": return self.picoseconds() elif unit == "FEMTOSECOND": return self.femtoseconds() else: raise ValueError( "Supported units are: '%s'" % list(self._supported_units.keys()) ) @classmethod def _validate_unit(cls, unit): """Validate that the unit are supported.""" # Strip whitespace and convert to upper case. unit = unit.replace(" ", "").upper() # Check that the unit is supported. if unit in cls._supported_units: return unit elif unit[:-1] in cls._supported_units: return unit[:-1] elif unit in cls._abbreviations: return cls._abbreviations[unit] elif unit[:-1] in cls._abbreviations: return cls._abbreviations[unit[:-1]] else: raise ValueError( "Supported units are: '%s'" % list(cls._supported_units.keys()) ) @staticmethod def _to_sire_format(unit): """ Reformat the unit string so it adheres to the Sire unit formatting. Parameters ---------- unit : str A string representation of the unit. Returns ------- sire_unit : str The unit string in Sire compatible format. """ unit = unit.replace("days", "day") unit = unit.replace("seconds", "second") unit = unit.replace("secs", "second") # Convert powers. (Just 2nd and third for now.) unit = unit.replace("day2", "(day*day)") unit = unit.replace("day3", "(day*day*day)") unit = unit.replace("day-1", "(1/day)") unit = unit.replace("day-2", "(1/(day*day))") unit = unit.replace("day-3", "(1/(day*day*day))") unit = unit.replace("hour2", "(hour*hour)") unit = unit.replace("hour3", "(hour*hour*hour)") unit = unit.replace("hour-1", "(1/hour)") unit = unit.replace("hour-2", "(1/(hour*hour))") unit = unit.replace("hour-3", "(1/(hour*hour*hour))") unit = unit.replace("minute2", "(minute*minute)") unit = unit.replace("minute3", "(minute*minute*minute)") unit = unit.replace("minute-1", "(1/minute)") unit = unit.replace("minute-2", "(1/(minute*minute))") unit = unit.replace("minute-3", "(1/(minute*minute*minute))") unit = unit.replace("femtosecond2", "(femtosecond*femtosecond)") unit = unit.replace("femtosecond3", "(femtosecond*femtosecond*femtosecond)") unit = unit.replace("femtosecond-1", "(1/femtosecond)") unit = unit.replace("femtosecond-2", "(1/(femtosecond*femtosecond))") unit = unit.replace( "femtosecond-3", "(1/(femtosecond*femtosecond*femtosecond))" ) unit = unit.replace("picosecond2", "(picosecond*picosecond)") unit = unit.replace("picosecond3", "(picosecond*picosecond*picosecond)") unit = unit.replace("picosecond-1", "(1/picosecond)") unit = unit.replace("picosecond-2", "(1/(picosecond*picosecond))") unit = unit.replace("picosecond-3", "(1/(picosecond*picosecond*picosecond))") unit = unit.replace("nanosecond2", "(nanosecond*nanosecond)") unit = unit.replace("nanosecond3", "(nanosecond*nanosecond*nanosecond)") unit = unit.replace("nanosecond-1", "(1/nanosecond)") unit = unit.replace("nanosecond-2", "(1/(nanosecond*nanosecond))") unit = unit.replace("nanosecond-3", "(1/(nanosecond*nanosecond*nanosecond))") unit = unit.replace("millisecond2", "(millisecond*millisecond)") unit = unit.replace("millisecond3", "(millisecond*millisecond*millisecond)") unit = unit.replace("millisecond-1", "(1/millisecond)") unit = unit.replace("millisecond-2", "(1/(millisecond*millisecond))") unit = unit.replace( "millisecond-3", "(1/(millisecond*millisecond*millisecond))" ) unit = unit.replace("second2", "(second*second)") unit = unit.replace("second3", "(second*second*second)") unit = unit.replace("second-1", "(1/second)") unit = unit.replace("second-2", "(1/(second*second))") unit = unit.replace("second-3", "(1/(second*second*second))") return unit