Source code for toyplot.units

# Copyright 2014, Sandia Corporation. Under the terms of Contract
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain
# rights in this software.

"""Functionality for performing unit conversions.
"""

from __future__ import division

import numbers
import re
import six

[docs]def convert(value, target, default=None, reference=None): """Convert quantities using real-world units. Supported unit abbreviations include: centimeter, centimeters, cm, decimeter, decimeters, dm, in, inch, inches, m, meter, meters, mm, millimeter, millimeters, pc, pica, picas, point, points, pt, pixel, pixels, and px. Relative quantities can be specified using %. Parameters ---------- value: number, string or (number, string) tuple Value to be converted. The value may be a number (in which case the `default` parameter must specify the default unit of measure), a string containing a number and unit abbreviation, or a (value, units) tuple. target: string Unit of measure to convert to. default: optional string Default unit of measure to use when `value` is a plain number, or when `reference` has been specified. reference: optional number When the caller specifies a relative measure using % as the unit abbreviation, the returned value will equal `value` * 0.01 * `reference`. Note that the reference *must* be specified in `target` units. Returns ------- Returns `value` converted to the `target` units, as a floating point number. """ if isinstance(value, numbers.Number): if value == 0: return 0 if default is None: raise ValueError("Value doesn't contain units, and no default units specified.") value = (value, default) elif isinstance(value, six.string_types): if value == "0": return 0 value, units = re.match(r"([^a-zA-Z%]+)([a-zA-Z%]+)\Z", value).groups() value = (float(value), units) if not isinstance(value, tuple): raise ValueError("Value must be a number, string or (number, string) tuple.") if not len(value) == 2: raise ValueError("Value must be a number, string or (number, string) tuple.") if not isinstance(value[0], numbers.Number): raise ValueError("Value must be a number, string or (number, string) tuple.") if not isinstance(value[1], six.string_types): raise ValueError("Value must be a number, string or (number, string) tuple.") value, units = value units = units.lower() if units == "%": if reference is None: raise ValueError("Relative values require a reference.") return value * 0.01 * reference if units not in convert._conversions: raise ValueError("Unknown unit of measure: %s" % units) target = target.lower() if target not in convert._conversions: raise ValueError("Unknown unit of measure: %s" % target) return value * convert._conversions[units] / convert._conversions[target]
convert._conversions = { "centimeter": 28.3464567, "centimeters": 28.3464567, "cm": 28.3464567, "decimeter": 283.464567, "decimeters": 283.464567, "dm": 283.464567, "in": 72.0, "inch": 72.0, "inches": 72.0, "m": 2834.64567, "meter": 2834.64567, "meters": 2834.64567, "millimeter": 2.83464567, "millimeters": 2.83464567, "mm": 2.83464567, "pc": 12.0, "pica": 12.0, "picas": 12.0, "pixel": 72.0 / 96.0, "pixels": 72.0 / 96.0, "point": 1.0, "points": 1.0, "pt": 1.0, "px": 72.0 / 96.0, }