Ran update_copyright.py
[hooke.git] / hooke / util / si.py
index ebb3c1927fa1983efde21bedbc2006aa8c62e797..6108b9fd1efb1f1f0270f6ade2fc9c48a548949d 100644 (file)
-# Copyright\r
-\r
-"""Define functions for handling numbers in SI notation.\r
-\r
-Notes\r
------\r
-To output a scale, choose any value on the axis and find the\r
-multiplier and prefix for it.  Use those to format the rest of the\r
-scale.  As values can span several orders of magnitude, you have\r
-to decide what units to use.\r
-\r
->>> xs = (985e-12, 1e-9, 112358e-12)\r
-\r
-Get the power from the first (or last, or middle, ...) value\r
-\r
->>> p = get_power(xs[0])\r
->>> for x in xs:\r
-...     print ppSI(x, decimals=2, power=p)\r
-985.00 p\r
-1000.00 p\r
-112358.00 p\r
->>> print prefix_from_value(xs[0]) + 'N'\r
-pN\r
-"""\r
-\r
-import math\r
-from numpy import isnan\r
-import re\r
-\r
-\r
-PREFIX = {\r
-    24: 'Y',\r
-    21: 'Z',\r
-    18: 'E',\r
-    15: 'P',\r
-    12: 'T',\r
-    9: 'G',\r
-    6: 'M',\r
-    3: 'k',\r
-    0: '',\r
-    -3: 'm',\r
-    -6: u'\u00B5',\r
-    -9: 'n',\r
-    -12: 'p',\r
-    -15: 'f',\r
-    -18: 'a',\r
-    -21: 'z',\r
-    -24: 'y',\r
-    }\r
-"""A dictionary of SI prefixes from 10**24 to 10**-24.\r
-\r
-Examples\r
---------\r
->>> PREFIX[0]\r
-''\r
->>> PREFIX[6]\r
-'M'\r
->>> PREFIX[-9]\r
-'n'\r
-"""\r
-\r
-_DATA_LABEL_REGEXP = re.compile('^([^(]*[^ ]) ?\(([^)]*)\)$')\r
-"""Used by :func:`data_label_unit`.\r
-"""\r
-\r
-\r
-def ppSI(value, unit='', decimals=None, power=None, pad=False):\r
-    """Pretty-print `value` in SI notation.\r
-\r
-    The current implementation ignores `pad` if `decimals` is `None`.\r
-\r
-    Examples\r
-    --------\r
-    >>> x = math.pi * 1e-8\r
-    >>> print ppSI(x, 'N')\r
-    31.415927 nN\r
-    >>> print ppSI(x, 'N', 3)\r
-    31.416 nN\r
-    >>> print ppSI(x, 'N', 4, power=-12)\r
-    31415.9265 pN\r
-    >>> print ppSI(x, 'N', 5, pad=True)\r
-       31.41593 nN\r
-\r
-    If you want the decimal indented by six spaces with `decimal=2`,\r
-    `pad` should be the sum of\r
-\r
-    * 6 (places before the decimal point)\r
-    * 1 (length of the decimal point)\r
-    * 2 (places after the decimal point)\r
-\r
-    >>> print ppSI(-x, 'N', 2, pad=(6+1+2))\r
-       -31.42 nN\r
-    """\r
-    if value == 0:\r
-        return '0'\r
-    if isnan(value):\r
-        return 'NaN'\r
-\r
-    if power == None:  # auto-detect power\r
-        power = get_power(value)\r
-\r
-    if decimals == None:\r
-        format = lambda n: '%f' % n\r
-    else:\r
-        if pad == False:  # no padding\r
-            format = lambda n: '%.*f' % (decimals, n)            \r
-        else:\r
-            if pad == True:  # auto-generate pad\r
-                # 1 for ' ', 1 for '-', 3 for number, 1 for '.', and decimals.\r
-                pad = 6 + decimals\r
-            format = lambda n: '%*.*f' % (pad, decimals, n)\r
-    return '%s %s%s' % (format(value / pow(10,power)), PREFIX[power], unit)\r
-\r
-\r
-def get_power(value):\r
-    """Return the SI power for which `0 <= |value|/10**pow < 1000`. \r
-    \r
-    Exampes\r
-    -------\r
-    >>> get_power(0)\r
-    0\r
-    >>> get_power(123)\r
-    0\r
-    >>> get_power(-123)\r
-    0\r
-    >>> get_power(1e8)\r
-    6\r
-    >>> get_power(1e-16)\r
-    -18\r
-    """\r
-    if value != 0 and not isnan(value):\r
-        # get log10(|value|)\r
-        value_temp = math.floor(math.log10(math.fabs(value)))\r
-        # reduce the log10 to a multiple of 3\r
-        return int(value_temp - (value_temp % 3))\r
-    else:\r
-        return 0\r
-\r
-def prefix_from_value(value):\r
-    """Determine the SI power of `value` and return its prefix.\r
-\r
-    Examples\r
-    --------\r
-    >>> prefix_from_value(0)\r
-    ''\r
-    >>> prefix_from_value(1e10)\r
-    'G'\r
-    """\r
-    return PREFIX[get_power(value)]\r
-\r
-def split_data_label(label):\r
-    """Split `curve.data[i].info['name']` labels into `(name, unit)`.\r
-\r
-    Examples\r
-    --------\r
-    >>> split_data_label('z piezo (m)')\r
-    ('z piezo', 'm')\r
-    >>> split_data_label('deflection (N)')\r
-    ('deflection', 'N')\r
-    """\r
-    m = _DATA_LABEL_REGEXP.match(label)\r
-    assert m != None, label\r
-    return m.groups()\r
+# Copyright (C) 2010 Massimo Sandal <devicerandom@gmail.com>
+#                    Rolf Schmidt <rschmidt@alcor.concordia.ca>
+#                    W. Trevor King <wking@drexel.edu>
+#
+# This file is part of Hooke.
+#
+# Hooke is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# Hooke 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 Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Hooke.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+"""Define functions for handling numbers in SI notation.
+
+Notes
+-----
+To output a scale, choose any value on the axis and find the
+multiplier and prefix for it.  Use those to format the rest of the
+scale.  As values can span several orders of magnitude, you have
+to decide what units to use.
+
+>>> xs = (985e-12, 1e-9, 112358e-12)
+
+Get the power from the first (or last, or middle, ...) value
+
+>>> p = get_power(xs[0])
+>>> for x in xs:
+...     print ppSI(x, decimals=2, power=p)
+985.00 p
+1000.00 p
+112358.00 p
+>>> print prefix_from_value(xs[0]) + 'N'
+pN
+"""
+
+import math
+from numpy import isnan
+import re
+
+
+PREFIX = {
+    24: 'Y',
+    21: 'Z',
+    18: 'E',
+    15: 'P',
+    12: 'T',
+    9: 'G',
+    6: 'M',
+    3: 'k',
+    0: '',
+    -3: 'm',
+    -6: u'\u00B5',
+    -9: 'n',
+    -12: 'p',
+    -15: 'f',
+    -18: 'a',
+    -21: 'z',
+    -24: 'y',
+    }
+"""A dictionary of SI prefixes from 10**24 to 10**-24.
+
+Examples
+--------
+>>> PREFIX[0]
+''
+>>> PREFIX[6]
+'M'
+>>> PREFIX[-9]
+'n'
+"""
+
+_DATA_LABEL_REGEXP = re.compile('^([^(]*[^ ]) ?\(([^)]*)\)$')
+"""Used by :func:`data_label_unit`.
+"""
+
+
+def ppSI(value, unit='', decimals=None, power=None, pad=False):
+    """Pretty-print `value` in SI notation.
+
+    The current implementation ignores `pad` if `decimals` is `None`.
+
+    Examples
+    --------
+    >>> x = math.pi * 1e-8
+    >>> print ppSI(x, 'N')
+    31.415927 nN
+    >>> print ppSI(x, 'N', 3)
+    31.416 nN
+    >>> print ppSI(x, 'N', 4, power=-12)
+    31415.9265 pN
+    >>> print ppSI(x, 'N', 5, pad=True)
+       31.41593 nN
+
+    If you want the decimal indented by six spaces with `decimal=2`,
+    `pad` should be the sum of
+
+    * 6 (places before the decimal point)
+    * 1 (length of the decimal point)
+    * 2 (places after the decimal point)
+
+    >>> print ppSI(-x, 'N', 2, pad=(6+1+2))
+       -31.42 nN
+    """
+    if value == 0:
+        return '0'
+    if isnan(value):
+        return 'NaN'
+
+    if power == None:  # auto-detect power
+        power = get_power(value)
+
+    if decimals == None:
+        format = lambda n: '%f' % n
+    else:
+        if pad == False:  # no padding
+            format = lambda n: '%.*f' % (decimals, n)            
+        else:
+            if pad == True:  # auto-generate pad
+                # 1 for ' ', 1 for '-', 3 for number, 1 for '.', and decimals.
+                pad = 6 + decimals
+            format = lambda n: '%*.*f' % (pad, decimals, n)
+    return '%s %s%s' % (format(value / pow(10,power)), PREFIX[power], unit)
+
+
+def get_power(value):
+    """Return the SI power for which `0 <= |value|/10**pow < 1000`. 
+    
+    Exampes
+    -------
+    >>> get_power(0)
+    0
+    >>> get_power(123)
+    0
+    >>> get_power(-123)
+    0
+    >>> get_power(1e8)
+    6
+    >>> get_power(1e-16)
+    -18
+    """
+    if value != 0 and not isnan(value):
+        # get log10(|value|)
+        value_temp = math.floor(math.log10(math.fabs(value)))
+        # reduce the log10 to a multiple of 3
+        return int(value_temp - (value_temp % 3))
+    else:
+        return 0
+
+def prefix_from_value(value):
+    """Determine the SI power of `value` and return its prefix.
+
+    Examples
+    --------
+    >>> prefix_from_value(0)
+    ''
+    >>> prefix_from_value(1e10)
+    'G'
+    """
+    return PREFIX[get_power(value)]
+
+def split_data_label(label):
+    """Split `curve.data[i].info['name']` labels into `(name, unit)`.
+
+    Examples
+    --------
+    >>> split_data_label('z piezo (m)')
+    ('z piezo', 'm')
+    >>> split_data_label('deflection (N)')
+    ('deflection', 'N')
+    """
+    m = _DATA_LABEL_REGEXP.match(label)
+    assert m != None, label
+    return m.groups()