');
37 | });
38 |
39 | // define the behavior of the button when it's clicked
40 | $('.copybutton').toggle(
41 | function() {
42 | var button = $(this);
43 | button.parent().find('.go, .gp, .gt').hide();
44 | button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
45 | button.css('text-decoration', 'line-through');
46 | button.attr('title', show_text);
47 | },
48 | function() {
49 | var button = $(this);
50 | button.parent().find('.go, .gp, .gt').show();
51 | button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
52 | button.css('text-decoration', 'none');
53 | button.attr('title', hide_text);
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/doc/_static/custom.css:
--------------------------------------------------------------------------------
1 | @import url("default.css");
2 |
3 | div.sphinxsidebar {
4 | top: 15px;
5 | width: 230px;
6 | font-size: 100%;
7 | line-height: 120%;
8 | }
9 |
10 | div.sphinxsidebar #searchbox input[type="text"] {
11 | width: 160px;
12 | }
13 |
14 | div.sphinxsidebar #searchbox input[type="submit"] {
15 | width: 40px;
16 | }
17 |
18 | img {
19 | margin: 10px;
20 | }
21 |
22 | div.body {
23 | min-height:800px; /* Be sure there's room for the sidebar. */
24 | }
25 |
--------------------------------------------------------------------------------
/doc/_static/favicon-160x160.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/favicon-160x160.png
--------------------------------------------------------------------------------
/doc/_static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/favicon-16x16.png
--------------------------------------------------------------------------------
/doc/_static/favicon-196x196.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/favicon-196x196.png
--------------------------------------------------------------------------------
/doc/_static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/favicon-32x32.png
--------------------------------------------------------------------------------
/doc/_static/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/favicon-96x96.png
--------------------------------------------------------------------------------
/doc/_static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/favicon.ico
--------------------------------------------------------------------------------
/doc/_static/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
43 |
45 |
46 |
48 | image/svg+xml
49 |
51 |
52 |
53 |
54 |
55 |
57 |
61 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
126 |
130 |
136 |
142 |
148 |
154 |
160 |
166 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/doc/_static/hspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kdavies4/natu/f91e7c4be59bf96ff0c069d009307b0aebc09a63/doc/_static/hspace.png
--------------------------------------------------------------------------------
/doc/_static/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
17 |
18 |
20 | image/svg+xml
21 |
23 |
24 |
25 |
26 |
27 |
29 |
33 |
40 |
44 |
48 |
52 |
56 |
60 |
64 |
68 |
72 |
76 |
80 |
84 |
88 |
92 |
93 |
97 |
102 |
107 |
112 |
117 |
122 |
127 |
132 |
133 | natu
146 |
147 |
148 |
--------------------------------------------------------------------------------
/doc/_templates/api.html:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/doc/_templates/definitions.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/doc/_templates/download.html:
--------------------------------------------------------------------------------
1 | Download
2 |
7 |
--------------------------------------------------------------------------------
/doc/_templates/globaltoc.html:
--------------------------------------------------------------------------------
1 | {#
2 | basic/globaltoc.html
3 | ~~~~~~~~~~~~~~~~~~~~
4 |
5 | Sphinx sidebar template: global table of contents.
6 |
7 | :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
8 | :license: BSD, see LICENSE for details.
9 | #}
10 |
11 | {{ toctree(includehidden=True) }}
12 |
--------------------------------------------------------------------------------
/doc/_templates/info.html:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/doc/_templates/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "!layout.html" %}
2 |
3 | {%- block extrahead %}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ super() }}
13 | {% endblock %}
14 |
--------------------------------------------------------------------------------
/doc/_templates/links.html:
--------------------------------------------------------------------------------
1 | Useful Links
2 |
8 |
--------------------------------------------------------------------------------
/doc/_templates/search.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% set title = _('Search') %}
3 | {% set script_files = script_files + ['_static/searchtools.js'] %}
4 | {% block body %}
5 | {{ _('Search') }}
6 |
7 | {% trans %}Enter search terms or a module, class, or function name.
8 | Note that the search function
9 | will automatically search for all of the words. Pages containing fewer
10 | words won't appear in the results.{% endtrans %}
11 |
12 |
17 | {% if search_performed %}
18 | {{ _('Search Results') }}
19 | {% if not search_results %}
20 | {{ _('Your search did not match any results.') }}
21 | {% endif %}
22 | {% endif %}
23 |
24 | {% if search_results %}
25 |
26 | {% for href, caption, context in search_results %}
27 | {{ caption }}
28 | {{ context|e }}
29 |
30 | {% endfor %}
31 |
32 | {% endif %}
33 |
34 | {% endblock %}
35 | {% block footer %}
36 | {{ super() }}
37 |
38 | {% endblock %}
39 |
--------------------------------------------------------------------------------
/doc/_templates/searchbox.html:
--------------------------------------------------------------------------------
1 | {#
2 | basic/searchbox.html
3 | ~~~~~~~~~~~~~~~~~~~~
4 |
5 | Sphinx sidebar template: quick search box.
6 |
7 | :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
8 | :license: BSD, see LICENSE for details.
9 | #}
10 | {%- if pagename != "search" %}
11 |
22 |
23 | {%- endif %}
24 |
--------------------------------------------------------------------------------
/doc/_templates/user.html:
--------------------------------------------------------------------------------
1 | {# From basic/globaltoc.html
2 |
3 | Sphinx sidebar template: global table of contents.
4 |
5 | :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
6 | :license: BSD, see LICENSE for details.
7 | #}
8 |
9 | {{ toctree(includehidden=True) }}
10 |
--------------------------------------------------------------------------------
/doc/api.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | API
4 | ===
5 |
6 | The following modules are documented for those who wish to extend natu,
7 | understand its internal design, or interface with it at a low level:
8 |
9 | - :mod:`natu.core` - Core classes of natu
10 | - :mod:`natu.exponents` - Class with methods to represent and operate on the
11 | product of factors with exponents
12 | - :mod:`natu.util` - General supporting functions
13 |
--------------------------------------------------------------------------------
/doc/changes.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | .. include:: ../CHANGES.txt
4 |
--------------------------------------------------------------------------------
/doc/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """natu documentation build configuration file, created by
3 | sphinx-quickstart on Mon Oct 15 09:06:21 2012.
4 |
5 | This file is execfile()d with the current directory set to its containing dir.
6 |
7 | Note that not all possible configuration values are present in this
8 | autogenerated file.
9 |
10 | All configuration values have a default; values that are commented out serve to
11 | show the default.
12 | """
13 |
14 | # Standard pylint settings for this project:
15 | # pylint: disable=I0011, C0302, C0325, R0903, R0904, R0912, R0913, R0914, R0915,
16 | # pylint: disable=I0011, W0141, W0142
17 |
18 | # Other:
19 | # pylint: disable=I0011, C0103, W0621, W0622
20 |
21 |
22 | def skip(app, what, name, obj, skip, options):
23 | """Include otherwise hidden methods.
24 | """
25 | # pylint: disable=I0011, W0613
26 | if name in ["__call__", "__contains__", "__getitem__", "__len__"]:
27 | return False
28 | return skip
29 |
30 |
31 | def setup(app):
32 | """Add roles and javascripts.
33 | """
34 | app.connect("autodoc-skip-member", skip)
35 | app.add_javascript('copybutton.js')
36 | app.add_javascript('analytics.js')
37 |
38 | # -- General configuration -----------------------------------------------
39 |
40 | # Add any Sphinx extension module names here, as strings. They can be extensions
41 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
42 | extensions = ['sphinx.ext.autodoc',
43 | 'sphinx.ext.doctest',
44 | 'sphinx.ext.pngmath',
45 | 'sphinx.ext.intersphinx',
46 | 'sphinx.ext.inheritance_diagram',
47 | 'sphinx.ext.graphviz',
48 | 'matplotlib.sphinxext.plot_directive'
49 | ]
50 | # Note: sphinx.ext.autosummary produces a table, but I'd rather have a bulleted
51 | # list.
52 |
53 | # Mappings to other packages
54 | # TODO: Fix numpy link.
55 | intersphinx_mapping = {
56 | 'python': ('https://docs.python.org/', None),
57 | 'numpy': ('http://docs.scipy.org/doc/numpy/', None),
58 | }
59 |
60 | # Add any paths that contain templates here, relative to this directory.
61 | templates_path = ['_templates']
62 |
63 | # The suffix of source filenames.
64 | source_suffix = '.rst'
65 |
66 | # The master toctree document.
67 | master_doc = 'index'
68 |
69 | # General information about the project.
70 | project = 'natu'
71 | copyright = ('2013-2014, Kevin Davies, Hawaii Natural Energy Institute and '
72 | 'Georgia Tech Research Corporation')
73 |
74 | # The version info for the project you're documenting, acts as replacement for
75 | # |version| and |release|, also used in various other places throughout the
76 | # built documents.
77 | #
78 | # The short X.Y version.
79 | import natu
80 | version = natu.__version__
81 | if not version:
82 | version = ''
83 | # The full version, including alpha/beta/rc tags.
84 | release = version
85 |
86 | # List of documents that shouldn't be included in the build.
87 | exclude_patterns = []
88 |
89 | # The name of the Pygments (syntax highlighting) style to use.
90 | pygments_style = 'sphinx'
91 |
92 | # -- Options for HTML output ---------------------------------------------
93 |
94 | # The theme to use for HTML and HTML Help pages. See the documentation for a
95 | # list of builtin themes.
96 | html_theme = 'default'
97 |
98 | html_theme_options = {
99 | 'stickysidebar': True,
100 | 'sidebarbgcolor': '#888888',
101 | 'sidebartextcolor': 'white',
102 | 'sidebarlinkcolor': 'white',
103 | }
104 |
105 | # The name for this set of Sphinx documents. If None, it defaults to
106 | # " v documentation".
107 | html_title = "Natural units in Python"
108 |
109 | # A shorter title for the navigation bar. Default is the same as html_title.
110 | version_str = " v%s" % version if version else ''
111 | html_short_title = project + version_str + " documentation"
112 |
113 | # The name of an image file (relative to this directory) to place at the top of
114 | # the sidebar.
115 | html_logo = '_static/logo.svg'
116 |
117 | # The name of an image file (within the static path) to use as favicon of the
118 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
119 | # pixels large.
120 | html_favicon = '_static/favicon.ico'
121 |
122 | # Add any paths that contain custom static files (such as style sheets) here,
123 | # relative to this directory. They are copied after the builtin static files, so
124 | # a file named "default.css" will overwrite the builtin "default.css".
125 | html_static_path = ['_static']
126 | html_style = 'custom.css'
127 |
128 | # List of paths that contain extra files not directly related to the
129 | # documentation
130 | html_extra_path = ['extra']
131 |
132 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
133 | # using the given strftime format.
134 | html_last_updated_fmt = '%b %d, %Y'
135 |
136 | # If true, SmartyPants will be used to convert quotes and dashes to
137 | # typographically correct entities.
138 | html_use_smartypants = True
139 |
140 | # Custom sidebar templates, maps document names to template names.
141 | html_sidebars = {'**': ['info.html', 'definitions.html', 'user.html',
142 | 'api.html', 'links.html', 'searchbox.html',
143 | 'download.html']}
144 |
145 | # If true, links to the reST sources are added to the pages.
146 | html_show_sourcelink = False
147 |
148 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
149 | html_show_sphinx = False
150 |
151 | # If true, an OpenSearch description file will be output, and all pages will
152 | # contain a tag referring to it. The value of this option must be the
153 | # base URL from which the finished HTML is served.
154 | html_use_opensearch = 'False'
155 |
156 | # Output file base name for HTML help builder.
157 | htmlhelp_basename = 'natuDoc'
158 |
159 | math_output = 'MathML'
160 |
--------------------------------------------------------------------------------
/doc/credits.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | .. include:: ../CREDITS.txt
4 |
--------------------------------------------------------------------------------
/doc/definitions.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | Definition files
4 | ================
5 |
6 | natu's constants and units are defined in INI_ files. Four files are loaded by
7 | default:
8 |
9 | .. toctree::
10 |
11 | base-ini
12 | derived-ini
13 | BIPM-ini
14 | other-ini
15 |
16 | Other files can be added by appending the :attr:`definitions` list in
17 | :mod:`natu.config`. The files are processed sequentially, and the definitions
18 | of symbols can reference previous symbols. These constants, functions, and
19 | classes are defined before the first file:
20 |
21 | - *pi*
22 | - :func:`~math.exp`
23 | - :func:`~math.log`
24 | - :func:`~math.log10`
25 | - :func:`sqrt`
26 | - :class:`~natu.core.Quantity`
27 | - :class:`~natu.core.ScalarUnit`
28 |
29 | The INI_ format is very similar to the tables in the pages for the files listed
30 | above. An equals sign separates the first two columns ("Symbol" and
31 | "Expression"), a comma starts the "Prefixable" column, and a semicolon starts
32 | the last column ("Name & notes").
33 |
34 | The "Prefixable" column may be *True*, *False*, or empty. A unit has a *True*
35 | or a *False* "Prefixable" entry. If a unit is prefixable, `SI prefixes`_ are
36 | added upon access. A constant has an empty "Prefixable" entry. Constants are
37 | never prefixable.
38 |
39 | Single-character `SI prefixes`_ take precedence over the two-character prefix
40 | 'da' (`deca `_). As a hypothetical
41 | example, if a unit with name and symbol 'am' is defined, 'dam' will refer to the
42 | deciam, not the decametre_. Also, non-prefixed units override the prefixed
43 | ones. For example, if a unit named 'dam' is established, it will override the
44 | decametre_ (and deciam), which has the same symbol.
45 |
46 | The "Name & notes" column is ignored. It is only included for reference.
47 |
48 | Some units such as `degC `_ and `Np
49 | `_ are not simple scaling factors. The
50 | "Expression" entry of these units contains a tuple with two functions. The
51 | first function maps a number to a quantity. The second function is its inverse.
52 | These are the first two arguments to construct a lambda unit
53 | (:class:`~natu.core.LambdaUnit`).
54 |
55 | `SI prefixes`_ can be applied to previous symbols except in the definition of
56 | lambda units.
57 |
58 | The sections of the INI_ files are only for organization (though required). The
59 | submodules of :mod:`natu.groups` do not rely on the sections. The dimensions of
60 | the derived constants and units are calculated and used instead.
61 |
62 | .. warning:: Be sure that you use definition files from a trusted source.
63 | Parts of the files are processed using :func:`eval`, which is susceptible to
64 | malicious code.
65 |
66 |
67 | .. _INI: http://en.wikipedia.org/wiki/INI_file
68 | .. _SI prefixes: http://en.wikipedia.org/wiki/Metric_prefix
69 | .. _decametre: http://en.wikipedia.org/wiki/Decametre
70 |
--------------------------------------------------------------------------------
/doc/derived-ini.rst:
--------------------------------------------------------------------------------
1 | Derived constants and units (derived.ini_)
2 | ==========================================
3 |
4 | The table below lists the contents of the derived.ini_ file. It contains
5 | constants and units that are derived from the base physical constants.
6 |
7 | The definitions depend on the following items:
8 |
9 | - Mathematical constants: *pi*
10 | - Base constants: *R_inf*, *c*, *k_J*, *R_K*, *k_F*, *R*, and *k_Aprime*
11 |
12 | ============ =========================== ========== ============
13 | Symbol Expression Prefixable Name & notes
14 | ============ =========================== ========== ============
15 | ------ Derived physical constants and intermediate units ------
16 | ----------------------------------------------------------------
17 | *Phi_0* ``1/k_J`` `magnetic flux quantum `_
18 | *G_0* ``2/R_K`` `conductance quantum `_
19 | *e* ``Phi_0*G_0`` `elementary charge `_ (aka Hartree unit of charge)
20 | *h* ``2*e*Phi_0`` `Planck constant `_
21 | *N_A* ``k_F/e`` `Avogadro constant `_
22 | *k_B* ``R/N_A`` `Boltzmann constant `_
23 | cyc ``k_Aprime*c/R_K`` *False* cycle (aka circle, revolution, `turn `_) (a unit---not a constant---but useful below)
24 | *c_1* ``2*pi*h*c**2/cyc**3`` `first radiation constant `_
25 | *c_2* ``h*c/k_B`` `second radiation constant `_
26 | *c_3_f* ``2.821439372122079*c/c_2`` `Wien frequency displacement constant `_ (the number is *x*, where exp(*x*)*(3 - *x*) = 3)
27 | *c_3_lambda* ``c_2/4.965114231744276`` `Wien wavelength displacement constant `_ (the number is *x*, where exp(*x*)*(5 - *x*) = 5)
28 | *sigma* ``c_1/15*(pi/c_2)**4`` `Stefan-Boltzmann constant `_ (aka Stefan's constant)
29 | *Ry* ``h*c*R_inf`` `Rydberg energy `_
30 | *Ha* ``2*Ry`` `Hartree energy `_ (aka hartree)
31 | *T_H* ``Ha/k_B`` Hartree temperature
32 | ============ =========================== ========== ============
33 |
34 | Since angle is explicit, it appears in several of the constants:
35 |
36 | - *Phi_0* ≈ 2.068×10\ :superscript:`-15` Wb [#f1]_
37 | - *G_0* ≈ 7.748×10\ :superscript:`-5` S cyc [#f2]_
38 | - *h* ≈ 6.626×10\ :superscript:`-34` J Hz\ :superscript:`-1` [#f1]_
39 | - *c_1* ≈ 3.742×10\ :superscript:`-16` W m\ :superscript:`2` cyc\ :superscript:`-4` [#f2]_
40 | - *c_2* ≈ 1.438×10\ :superscript:`-2` m K cyc\ :superscript:`-1` [#f2]_
41 | - *c_3_f* ≈ 5.879×10\ :superscript:`10` Hz K\ :superscript:`-1` [#f1]_
42 | - *c_3_lambda* ≈ 2.898×10\ :superscript:`-3` K m cyc\ :superscript:`-1` [#f2]_
43 |
44 | The definition of the `Planck constant`_ implies that
45 | *h*\*cyc ≈ 6.626×10\ :superscript:`-34` J (the traditional expression of
46 | *h*) and *h*\*rad ≈ 1.05457×10\ :superscript:`-34` J (the traditional
47 | expression of *ħ*). Note that the cycle (cyc) is not an abbreviation for cycles
48 | per second as it became in the `MKS system of units
49 | `_. It is a unit of angle.
50 |
51 |
52 | .. _derived.ini: https://github.com/kdavies4/natu/blob/master/natu/config/derived.ini
53 | .. _Planck constant: http://en.wikipedia.org/wiki/Planck_constant
54 |
55 | .. rubric:: References
56 |
57 | .. [NIST2014] National Institute of Science and Technology, "Fundamental
58 | Physical Constants: Complete Listing,"
59 | http://physics.nist.gov/constants, accessed 2014.
60 |
61 | .. rubric:: Footnotes
62 |
63 | .. [#f1] See the `BIPM units `_ regarding the weber (Wb) and the
64 | hertz (Hz).
65 | .. [#f2] Traditionally, angle is dropped [NIST2014]_.
66 |
--------------------------------------------------------------------------------
/doc/extra/googledadb6c37b51fb2dc.html:
--------------------------------------------------------------------------------
1 | google-site-verification: googledadb6c37b51fb2dc.html
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | ########
2 | natu
3 | ########
4 |
5 | **Natural units in Python**
6 |
7 | .. warning:: This project is currently in a pre-release state. It will be
8 | officially released once the unit tests are complete.
9 |
10 | natu is a free, open-source package to represent physical quantities. There are
11 | `many Python packages that deal with units and quantities `_, but
12 | natu is uniquely system-independent. The units are derived from physical
13 | constants with adjustable values and dimensions. The value of a unit is
14 | factored into a quantity so that the quantity is not "in" any particular unit.
15 | This has the following advantages:
16 |
17 | - **Flexible**: Different unit systems, including `natural units`_ (hence the
18 | name "natu"), can be represented by simply adjusting the `base physical
19 | constants `_.
20 | - **Simple**: Unit conversion is inherent. This results in quick computations
21 | and a small code base (about 1500 lines). By default, dimensions and display
22 | units are tracked to catch errors and for string formatting. This can be
23 | disabled to nearly eliminate the computational overhead while still providing
24 | the core features.
25 | - **Intuitive**: Each unit is a fixed quantity that is treated as a
26 | mathematical entity. A variable quantity is expressed as the product of a
27 | number and a unit, as stated in [BIPM2006]_.
28 | - **Representative**: The design reflects the way modern units are defined.
29 | Standards organizations such as NIST_ assign values to universal physical
30 | constants so that the values of units can be determined by physical
31 | experiments instead of prototypes.
32 | - **Scalable**: The values of the base physical constants can scaled to prevent
33 | exponent overflow, regardless of the units used [Davies2012]_, [#f1]_.
34 |
35 | natu incorporates some of the best features of the `existing packages
36 | `_:
37 |
38 | - Units with offsets and even nonlinear functions are supported. For example:
39 |
40 | >>> from natu.units import degC, K
41 | >>> 0*degC + 100*K
42 | 100.0 degC
43 |
44 | >>> from natu.units import dB
45 | >>> (10/dB + 10/dB)*dB # Multiply by adding logarithms.
46 | 100.0
47 |
48 | - Prefixes are automatically applied. For example:
49 |
50 | >>> from natu.units import km, m
51 | >>> km/m
52 | 1000
53 |
54 | - Display units are simplified using `coherent relations`_ automatically
55 | gathered from the unit definitions:
56 |
57 | >>> from natu.units import kg, m, s
58 | >>> 1*kg*m**2/s**2
59 | 1.0 J
60 |
61 | - Units are automatically sorted into convenient submodules such as
62 | :mod:`natu.groups.length`.
63 |
64 | - Nearly 40 physical constants are included. For example:
65 |
66 | >>> from natu.groups.constants import c
67 | >>> c
68 | 299792458.0 m/s
69 |
70 | - Additional constants and units can be easily added to the `definition files
71 | `_ or defined in code.
72 |
73 | - There are drop-in, quantity-aware replacements for :mod:`math` and
74 | :mod:`numpy`. Quantities can be used in NumPy_ arrays or vice versa (see
75 | `here
76 | `_).
77 |
78 | - There are no dependencies except for the :mod:`numpy` replacements (previous
79 | feature).
80 |
81 | - Units can have fractional powers. For example:
82 |
83 | >>> from fractions import Fraction
84 | >>> m**Fraction(1, 2)
85 | ScalarUnit m(1/2) with dimension L(1/2) (not prefixable)
86 |
87 | - Units and quantities can be formatted for HTML, LaTeX_, Unicode_, and
88 | Modelica_. For example:
89 |
90 | >>> '{:H}'.format(10*m**2)
91 | '10.0 m2 '
92 |
93 | This renders in HTML as 10.0 m\ :sup:`2`\ .
94 |
95 | - Rationalized and unrationalized unit systems are supported.
96 |
97 |
98 | Please `see the tutorial
99 | `_
100 | for more examples. The links in the sidebar give the `installation instructions
101 | `_ and more information.
102 |
103 | **License terms and development**
104 |
105 | natu is published under a `BSD-compatible license `_. Please
106 | share any improvements you make, preferably as a pull request to the ``master``
107 | branch of the `GitHub repository`_. There are useful development scripts in
108 | the `hooks folder `_. If
109 | you find a bug, have a suggestion, or just want to leave a comment, please `open
110 | an issue `_.
111 |
112 | .. toctree::
113 | :hidden:
114 |
115 | natu.config
116 | natu.groups
117 | natu.math
118 | natu.numpy
119 | natu.units
120 |
121 |
122 | .. _natural units: http://en.wikipedia.org/wiki/Natural_units
123 | .. _GitHub repository: https://github.com/kdavies4/natu
124 | .. _NIST: http://www.nist.gov/
125 | .. _BIPM: http://www.bipm.org/
126 | .. _Celsius: http://en.wikipedia.org/wiki/Celsius
127 | .. _decibel: http://en.wikipedia.org/wiki/Decibel
128 | .. _coherent relations: http://en.wikipedia.org/wiki/Coherence_(units_of_measurement)
129 | .. _NumPy: http://www.numpy.org/
130 | .. _statcoulomb: http://en.wikipedia.org/wiki/Statcoulomb
131 | .. _Unicode: https://en.wikipedia.org/wiki/Unicode
132 | .. _LaTeX: http://www.latex-project.org/
133 | .. _Modelica: https://www.modelica.org/documents/ModelicaSpec33Revision1.pdf
134 |
135 | .. rubric:: References
136 |
137 | .. [Davies2012] K. Davies and C. Paredis, "`Natural Unit Representation in
138 | Modelica
139 | `_,"
140 | in Modelica Conference (Munich, Germany), Modelica Assoc.,
141 | Sep. 2012.
142 | .. [BIPM2006] International Bureau of Weights and Measures (BIPM),
143 | "`The International System of Units (SI)
144 | `_,"
145 | 8th ed., 2006.
146 |
147 | .. rubric:: Footnotes
148 |
149 | .. [#f1] Post by C. Bruns at
150 | http://stackoverflow.com/questions/2125076/unit-conversion-in-python
151 | (Feb. 5, 2010):
152 |
153 | "Units are NOT necessarily stored in terms of SI units internally. This
154 | is very important for me, because one important application area for us is
155 | at the molecular scale. Using SI units internally can lead to exponent
156 | overflow in commonly used molecular force calculations."
157 |
--------------------------------------------------------------------------------
/doc/install.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | Installation
4 | ============
5 |
6 | The easiest way to install natu_ is to use pip_::
7 |
8 | > pip install natu
9 |
10 | On Linux, it may be necessary to have root privileges::
11 |
12 | $ sudo pip install natu
13 |
14 | Another way is to download and extract a copy of the package from the sidebar on
15 | the left. Run the following command from the base folder::
16 |
17 | > python setup.py install
18 |
19 | Or, on Linux::
20 |
21 | $ sudo python setup.py install
22 |
23 |
24 | .. _natu: index.html
25 | .. _pip: https://pypi.python.org/pypi/pip
26 |
--------------------------------------------------------------------------------
/doc/license.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | License
4 | =======
5 |
6 | .. include:: ../LICENSE.txt
7 |
--------------------------------------------------------------------------------
/doc/long-description.txt:
--------------------------------------------------------------------------------
1 | ########
2 | natu
3 | ########
4 |
5 | **Natural units in Python**
6 |
7 | .. warning:: This project is currently in a pre-release state. It will be
8 | officially released once the unit tests are complete.
9 |
10 | natu_ is a free, open-source package to represent physical quantities. There
11 | are `many Python packages that deal with units and quantities
12 | `_, but natu_ is uniquely
13 | system-independent. The units are derived from physical constants with
14 | adjustable values and dimensions. The value of a unit is factored into a
15 | quantity so that the quantity is not "in" any particular unit. This has the
16 | following advantages:
17 |
18 | - **Flexible**: Different unit systems, including `natural units`_ (hence the
19 | name "natu"), can be represented by simply adjusting the `base physical
20 | constants `_.
21 | - **Simple**: Unit conversion is inherent. This results in quick computations
22 | and a small code base (about 1500 lines). By default, dimensions and display
23 | units are tracked to catch errors and for string formatting. This can be
24 | disabled to nearly eliminate the computational overhead while still providing
25 | the core features.
26 | - **Intuitive**: Each unit is a fixed quantity that is treated as a
27 | mathematical entity. A variable quantity is expressed as the product of a
28 | number and a unit, as stated by BIPM_.
29 | - **Representative**: The design reflects the way modern units are defined.
30 | Standards organizations such as NIST_ assign values to universal physical
31 | constants so that the values of units can be determined by physical
32 | experiments instead of prototypes.
33 | - **Scalable**: The values of the base physical constants can scaled to prevent
34 | exponent overflow, regardless of the units used.
35 |
36 | For example, you can do this:
37 |
38 | >>> from natu.units import degC, K
39 | >>> 0*degC + 100*K
40 | 100.0 degC
41 |
42 | Please see `the main website`_ and `the tutorial
43 | `_
44 | for more examples.
45 |
46 | Installation
47 | ~~~~~~~~~~~~
48 |
49 | The easiest way to install natu_ is to use pip_::
50 |
51 | > pip install natu
52 |
53 | On Linux, it may be necessary to have root privileges::
54 |
55 | $ sudo pip install natu
56 |
57 | License terms and development
58 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59 |
60 | natu_ is published under a `BSD-compatible license
61 | `_. Please share any
62 | improvements you make, preferably as a pull request to the ``master`` branch of
63 | the `GitHub repository`_. There are useful development scripts in the `hooks
64 | folder `_. If you find a
65 | bug, have a suggestion, or just want to leave a comment, please `open an issue
66 | `_.
67 |
68 |
69 | .. _natural units: http://en.wikipedia.org/wiki/Natural_units
70 | .. _Python Standard Library: https://docs.python.org/3/library/
71 | .. _GitHub repository: https://github.com/kdavies4/natu
72 | .. _NIST: http://www.nist.gov/
73 | .. _BIPM: http://www.bipm.org/
74 | .. _pip: https://pypi.python.org/pypi/pip
75 | .. _degree Celsius (degC): http://en.wikipedia.org/wiki/Celsius
76 | .. _decibel (dB): http://en.wikipedia.org/wiki/Decibel
77 | .. _coherent relations: http://en.wikipedia.org/wiki/Coherence_(units_of_measurement)
78 | .. _statcoulomb: http://en.wikipedia.org/wiki/Statcoulomb
79 | .. _math: https://docs.python.org/3/library/math.html
80 | .. _numpy: http://numpy.scipy.org/
81 | .. _the main website: http://kdavies4.github.io/natu/
82 |
--------------------------------------------------------------------------------
/doc/make.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Clean, build, and release the HTML documentation for natu.
3 | """
4 |
5 | # Standard pylint settings for this project:
6 | # pylint: disable=I0011, C0302, C0325, R0903, R0904, R0912, R0913, R0914, R0915,
7 | # pylint: disable=I0011, W0141, W0142
8 |
9 | # Other:
10 | # pylint: disable=I0011, C0103, E0611, F0401, W0621
11 |
12 | import os
13 | import shutil
14 | import sys
15 |
16 | from sh import git, python, sphinx_build, ErrorReturnCode_1, ErrorReturnCode_128
17 | from glob import glob
18 | from collections import namedtuple
19 |
20 | from natu import util
21 | from natu import groups
22 |
23 | BUILD_DIR = 'build/html'
24 |
25 | # Template for automatic Sphinx documentation of a module
26 | TEMPLATE = """:orphan:
27 |
28 | :mod:`{package}`
29 | {underline}
30 |
31 | .. automodule:: {package}
32 | :members:
33 | :undoc-members:
34 | :show-inheritance:"""
35 |
36 | def update_groups():
37 | """Update the Sphinx ReST files for the submodules of natu.groups.
38 | """
39 |
40 | # Remove the existing files.
41 | files = glob('natu.groups.*.rst')
42 | for f in files:
43 | os.remove(f)
44 |
45 | # Create new files.
46 | packages = util.list_packages(groups)
47 | packages.remove('natu.groups')
48 |
49 | for package in packages:
50 | with open("%s.rst" % package, 'w') as f:
51 | f.write(TEMPLATE.format(package=package,
52 | underline='='*(len(package) + 7)))
53 |
54 | def html():
55 | """Build/make the HTML documentation.
56 | """
57 |
58 | # Update the download link.
59 | try:
60 | commit = git('rev-list', '--tags', '--max-count=1').stdout.rstrip()
61 | lastversion = git.describe('--tags', commit).stdout.rstrip()
62 | # This is simpler but doesn't always return the latest tag:
63 | # lastversion = git.describe('--tag', abbrev=0).stdout.rstrip()
64 | except ErrorReturnCode_128:
65 | pass # No tags recorded; leave download link as is
66 | else:
67 | date = git.log('-1', lastversion,
68 | date='short', format='%ad').stdout[8:18]
69 | rpls = [(r'(natu)-.*(\.tar)', r'\1-%s\2' % lastversion[1:]),
70 | (r'(Latest version \().*(\))',
71 | r'\1%s, %s\2' % (lastversion, date)),
72 | ]
73 | util.replace('_templates/download.html', rpls)
74 |
75 | # Update the Sphinx ReST files for the submodules of natu.groups.
76 | update_groups()
77 |
78 | # Build the documentation.
79 | make_dirs()
80 | sphinx = sphinx_build.bake(b='html', d='build/doctrees')
81 | print(sphinx('.', BUILD_DIR))
82 |
83 | # Spellcheck.
84 | if util.yes("Do you want to spellcheck the HTML documentation (y/n)?"):
85 | spellcheck()
86 |
87 |
88 | def clean():
89 | """Clean/remove the built documentation.
90 | """
91 | shutil.rmtree('build', ignore_errors=True)
92 |
93 |
94 | def make_dirs():
95 | """Create the directories required to build the documentation.
96 | """
97 |
98 | # Create regular directories.
99 | build_dirs = ['build/doctrees', 'build/html']
100 | for d in build_dirs:
101 | try:
102 | os.makedirs(d)
103 | except OSError:
104 | pass
105 |
106 | def release():
107 | """Release/publish the documentation to the webpage.
108 | """
109 | # Save the current state.
110 | branch = git('rev-parse', '--abbrev-ref', 'HEAD').stdout.rstrip()
111 | git.stash('save', "Work in progress while updating gh-pages branch")
112 |
113 | # Check out the gh-pages branch.
114 | try:
115 | git.checkout('gh-pages')
116 | except ErrorReturnCode_128: # Create the branch if necessary.
117 | git.checkout('-b', 'gh-pages')
118 |
119 | # Remove the existing files in the base folder.
120 | extensions = ['*.html', '*.inv']
121 | fnames = util.multiglob('..', extensions)
122 | for fname in fnames:
123 | os.remove(fname)
124 |
125 | # Copy the new files to the base folder.
126 | fnames = util.multiglob(BUILD_DIR, extensions)
127 | for fname in fnames:
128 | shutil.copy(fname, '..')
129 |
130 | # Track the new files.
131 | fnames = util.multiglob('..', extensions)
132 | git.add(*fnames)
133 |
134 | # Copy but rename the folders referenced in the HTML files.
135 | # Github only recognizes images, stylesheets, and javascripts as folders.
136 | folders = [('_images', 'images'),
137 | ('_static', 'javascripts'),
138 | ]
139 | for (src, dst) in folders:
140 | dst = os.path.join('..', dst)
141 | # Remove the existing folder.
142 | shutil.rmtree(dst, ignore_errors=True)
143 | # Copy the new folder.
144 | shutil.copytree(os.path.join(BUILD_DIR, src), dst)
145 | # Track the new folder.
146 | git.add(dst)
147 | # Update the HTML files to reference the new folder names.
148 | html_fnames = glob(os.path.join('..', '*.html'))
149 | util.replace(html_fnames, folders)
150 |
151 | # Update the sitemap.
152 | print(python('sitemap_gen.py', config="sitemap_conf.xml"))
153 |
154 | # Commit the changes.
155 | try:
156 | git.commit('-a', m="Rebuilt documentation")
157 | except ErrorReturnCode_1:
158 | pass # No changes to commit
159 |
160 | # If desired, rebase and push the changes to origin.
161 | print("The gh-pages branch has been updated and is currently checked out.")
162 | if util.yes("Do you want to rebase it and push the changes to "
163 | "origin (y/n)?"):
164 | git.rebase('-i', 'origin/gh-pages')
165 | git.push.origin('gh-pages')
166 |
167 | # Return to the original state.
168 | git.checkout(branch)
169 | try:
170 | git.stash.pop()
171 | except ErrorReturnCode_1:
172 | pass # No stash was necessary in the first place.
173 | print("Now back on " + branch)
174 |
175 |
176 | def spellcheck():
177 | """Spellcheck the HTML docs.
178 | """
179 | # Options
180 | wordfile = os.path.abspath('natu.pws') # Name of custom word file
181 | html_files = glob('build/html/*.html') # Names of the HTML files
182 |
183 | print("If there are misspellings, fix them in the Python or ReST "
184 | "source---not just in the HTML files.")
185 |
186 | # Remove unused words from the custom word file.
187 | def read(fname):
188 | """Read all text from a file."""
189 | with open(fname, 'r') as f:
190 | return f.read()
191 | html = "".join(map(read, html_files))
192 | with open(wordfile, 'r') as f:
193 | head = f.readline()
194 | lines = f.readlines()
195 | with open(wordfile, 'w') as f:
196 | f.write(head)
197 | for line in lines:
198 | if html.find(line.rstrip('\n').rstrip('\r')) != -1:
199 | f.write(line)
200 |
201 | # Check the spelling.
202 | for page in html_files:
203 | if os.system('aspell --dont-backup --personal={0} '
204 | '-c {1}'.format(wordfile, page)):
205 | raise SystemError("aspell (http://aspell.net/) must be installed.")
206 |
207 |
208 | Action = namedtuple("Action", ['f', 'description'])
209 | ACTIONS = {'clean' : Action(clean, "Clean/remove the built documentation."),
210 | 'build' : Action(html, "Build/make the HTML documentation."),
211 | 'html' : Action(html, "Build/make the HTML documentation."),
212 | 'release' : Action(release, ("Release/publish the documentation to "
213 | "the webpage.")),
214 | }
215 |
216 |
217 | def funcs_str():
218 | """Return a string listing the valid functions and their descriptions.
219 | """
220 | return "\n".join([" %s: %s" % (action.ljust(10), function.description)
221 | for (action, function) in ACTIONS.items()])
222 |
223 |
224 | # Main
225 | if len(sys.argv) != 2:
226 | raise SystemExit("Exactly one argument is required; valid args are\n"
227 | + funcs_str())
228 | ACTION = sys.argv[1]
229 | try:
230 | ACTIONS[ACTION].f()
231 | except KeyError:
232 | raise SystemExit("Do not know how to handle %s; valid args are\n%s"
233 | % (ACTION, funcs_str()))
234 |
--------------------------------------------------------------------------------
/doc/natu.config.rst:
--------------------------------------------------------------------------------
1 | :mod:`natu.config`
2 | ==================
3 |
4 | .. automodule:: natu.config
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/doc/natu.core.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.core`
4 | ================
5 |
6 | .. automodule:: natu.core
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
10 |
--------------------------------------------------------------------------------
/doc/natu.exponents.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.exponents`
4 | =====================
5 |
6 | .. automodule:: natu.exponents
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
10 |
--------------------------------------------------------------------------------
/doc/natu.groups.acceleration.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.acceleration`
4 | ===============================
5 |
6 | .. automodule:: natu.groups.acceleration
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.amount.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.amount`
4 | =========================
5 |
6 | .. automodule:: natu.groups.amount
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.angle.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.angle`
4 | ========================
5 |
6 | .. automodule:: natu.groups.angle
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.area.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.area`
4 | =======================
5 |
6 | .. automodule:: natu.groups.area
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.charge.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.charge`
4 | =========================
5 |
6 | .. automodule:: natu.groups.charge
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.conductance.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.conductance`
4 | ==============================
5 |
6 | .. automodule:: natu.groups.conductance
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.constants.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.constants`
4 | ============================
5 |
6 | .. automodule:: natu.groups.constants
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.current.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.current`
4 | ==========================
5 |
6 | .. automodule:: natu.groups.current
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.dimensionless.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.dimensionless`
4 | ================================
5 |
6 | .. automodule:: natu.groups.dimensionless
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.energy.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.energy`
4 | =========================
5 |
6 | .. automodule:: natu.groups.energy
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.force.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.force`
4 | ========================
5 |
6 | .. automodule:: natu.groups.force
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.frequency.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.frequency`
4 | ============================
5 |
6 | .. automodule:: natu.groups.frequency
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.length.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.length`
4 | =========================
5 |
6 | .. automodule:: natu.groups.length
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.magnetic_flux.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.magnetic_flux`
4 | ================================
5 |
6 | .. automodule:: natu.groups.magnetic_flux
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.magnetic_flux_density.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.magnetic_flux_density`
4 | ========================================
5 |
6 | .. automodule:: natu.groups.magnetic_flux_density
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.mass.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.mass`
4 | =======================
5 |
6 | .. automodule:: natu.groups.mass
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.potential.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.potential`
4 | ============================
5 |
6 | .. automodule:: natu.groups.potential
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.power.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.power`
4 | ========================
5 |
6 | .. automodule:: natu.groups.power
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.pressure.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.pressure`
4 | ===========================
5 |
6 | .. automodule:: natu.groups.pressure
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.resistance.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.resistance`
4 | =============================
5 |
6 | .. automodule:: natu.groups.resistance
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.rst:
--------------------------------------------------------------------------------
1 | :mod:`natu.groups`
2 | ==================
3 |
4 | .. automodule:: natu.groups
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/doc/natu.groups.si.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.si`
4 | =====================
5 |
6 | .. automodule:: natu.groups.si
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.temperature.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.temperature`
4 | ==============================
5 |
6 | .. automodule:: natu.groups.temperature
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.time.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.time`
4 | =======================
5 |
6 | .. automodule:: natu.groups.time
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.velocity.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.velocity`
4 | ===========================
5 |
6 | .. automodule:: natu.groups.velocity
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.groups.volume.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.groups.volume`
4 | =========================
5 |
6 | .. automodule:: natu.groups.volume
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
--------------------------------------------------------------------------------
/doc/natu.math.rst:
--------------------------------------------------------------------------------
1 | :mod:`natu.math`
2 | ================
3 |
4 | .. automodule:: natu.math
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/doc/natu.numpy.rst:
--------------------------------------------------------------------------------
1 | :mod:`natu.numpy`
2 | =================
3 |
4 | .. automodule:: natu.numpy
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/doc/natu.pws:
--------------------------------------------------------------------------------
1 | personal_ws-1.1 en 286
2 | banananana
3 | atm
4 | wildcard
5 | statA
6 | der
7 | statC
8 | sin
9 | paren
10 | tonumber
11 | atanh
12 | u'Exiting
13 | sudo
14 | rpl
15 | oersted
16 | input
17 | HNEI
18 | dalton
19 | katal
20 | statT
21 | radian
22 | statV
23 | cdyn
24 | isinf
25 | div
26 | NumPy
27 | numpy
28 | baryed
29 | abohm
30 | versa
31 | decaampere
32 | src
33 | metres
34 | args
35 | fname
36 | luminance
37 | deca
38 | atan
39 | arcsec
40 | DimPy
41 | config
42 | torr
43 | sievert
44 | cyc
45 | str
46 | NumericalUnits
47 | tanh
48 | asin
49 | trunc
50 | franklin
51 | degC
52 | Modelica
53 | degF
54 | erf
55 | siemens
56 | asinh
57 | Aprime
58 | degR
59 | scimath
60 | SciMath
61 | isnan
62 | acos
63 | unutbu
64 | stattesla
65 | steradian
66 | dyn
67 | esu
68 | arctanh
69 | pathnames
70 | kcal
71 | GTRC
72 | centimetre
73 | circ
74 | gradian
75 | von
76 | txt
77 | searchbox
78 | Bruns
79 | exp
80 | toquantity
81 | submodules
82 | erfc
83 | ScalarUnit
84 | abfarad
85 | natu
86 | tuples
87 | sinh
88 | gui
89 | fromstr
90 | henry
91 | phot
92 | dest
93 | prefixable
94 | sympy
95 | nbsp
96 | kilometres
97 | unicode
98 | kat
99 | multiglob
100 | UnitsModule
101 | ini
102 | stilb
103 | abvolt
104 | litre
105 | Unum
106 | barad
107 | arcsinh
108 | lbf
109 | fmod
110 | PyPI
111 | subpackages
112 | bary
113 | Redistributions
114 | Scalable
115 | dimensioned
116 | ba
117 | bb
118 | rpls
119 | bd
120 | len
121 | dimensionally
122 | cd
123 | indexable
124 | ce
125 | da
126 | illuminance
127 | weber
128 | acosh
129 | de
130 | df
131 | au
132 | Bq
133 | eb
134 | html
135 | thermochemical
136 | ec
137 | barie
138 | cP
139 | eval
140 | fb
141 | fabs
142 | kPa
143 | dm
144 | Stoney
145 | Wien
146 | statampere
147 | fe
148 | dyne
149 | quicknew
150 | arcdegree
151 | fm
152 | eV
153 | kwds
154 | hm
155 | dirname
156 | kA
157 | statWb
158 | mho
159 | mmHg
160 | Gy
161 | io
162 | CoherentRelations
163 | radians
164 | udunitspy
165 | Paredis
166 | Versioning
167 | maxwell
168 | ltypes
169 | decametre
170 | lm
171 | ln
172 | nd
173 | util
174 | statcoulomb
175 | Oe
176 | mod
177 | barrie
178 | pc
179 | nm
180 | abcoloumb
181 | lx
182 | ly
183 | np
184 | lumen
185 | deciam
186 | ph
187 | modf
188 | mol
189 | Pag
190 | ns
191 | Mx
192 | google
193 | copysign
194 | os
195 | arcsecond
196 | sb
197 | getitem
198 | nmi
199 | filenames
200 | abA
201 | darcy
202 | abc
203 | abC
204 | si
205 | py
206 | LaTeX
207 | lux
208 | abF
209 | th
210 | iterable
211 | abH
212 | metre
213 | baryd
214 | permittivity
215 | barye
216 | sp
217 | sr
218 | arccosh
219 | googledadb
220 | candela
221 | Sv
222 | Wb
223 | mul
224 | Instantiation
225 | abV
226 | Wh
227 | submodule
228 | tuple
229 | statvolt
230 | unrationalized
231 | frexp
232 | UnitExponents
233 | millimetre
234 | magnetron
235 | num
236 | arcmin
237 | classmethod
238 | GitHub
239 | tesla
240 | Szdori
241 | ala
242 | NIST
243 | bel
244 | abhenry
245 | kwargs
246 | expm
247 | ppb
248 | Filename
249 | isfinite
250 | denom
251 | expr
252 | hypot
253 | Aring
254 | dname
255 | fnames
256 | pre
257 | MERCHANTABILITY
258 | daA
259 | lgamma
260 | ppq
261 | ceil
262 | LambdaUnit
263 | ppt
264 | statweber
265 | hartree
266 | API
267 | astropy
268 | fsum
269 | gauss
270 | arcminute
271 | Klitzing
272 | BIPM
273 | blockquote
274 | Biot
275 | DimObject
276 | CFR
277 | invertible
278 | dde
279 | Sep
280 | ldexp
281 | sqrt
282 | neper
283 | ded
284 | CGS
285 | abampere
286 | psig
287 | pathname
288 |
--------------------------------------------------------------------------------
/doc/natu.units.rst:
--------------------------------------------------------------------------------
1 | :mod:`natu.units`
2 | =================
3 |
4 | .. automodule:: natu.units
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/doc/natu.util.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | :mod:`natu.util`
4 | ================
5 |
6 | .. automodule:: natu.util
7 | :members:
8 | :undoc-members:
9 | :show-inheritance:
10 |
--------------------------------------------------------------------------------
/doc/seealso.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | See also
4 | ========
5 |
6 | Here is a list of Python_ packages that deal with units and quantities, besides
7 | natu_:
8 |
9 | - `astropy.units `_
10 | - `Buckingham `_
11 | - `DimPy `_
12 | - `Magnitude `_
13 | - `NumericalUnits `_
14 | - `Pint `_
15 | - `Python-quantities `_
16 | - `Scalar `_
17 | - `Scientific.Physics.PhysicalQuantities `_
18 | - `SciMath `_
19 | - `sympy.physics.units `_
20 | - `udunitspy `_
21 | - `Units `_
22 | - `Unum `_
23 |
24 |
25 | .. _Python: http://www.python.org/
26 | .. _natu: index.html
27 |
--------------------------------------------------------------------------------
/doc/usermodules.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 | User modules
4 | ============
5 |
6 | The following modules help to perform calculations on physical quantities:
7 |
8 | - :mod:`natu.config` - Configuration settings for :mod:`natu`
9 | - :mod:`natu.units` - Module with all units from the `definition files
10 | `_
11 | - :mod:`natu.groups` - Modules with selected groups of units
12 | - :mod:`natu.math` - `Python math`_, adapted for use with physical quantities
13 | - :mod:`natu.numpy` - :mod:`numpy`, adapted for use with physical quantities
14 |
15 |
16 | .. _Python math: https://docs.python.org/3/library/math.html
17 |
--------------------------------------------------------------------------------
/examples/custom.ini:
--------------------------------------------------------------------------------
1 | ; Custom units
2 | ; ============
3 | ;
4 | ; This units definition file contains an example of a scalar unit. For more
5 | ; details, please see https://kdavies4.github.com/natu/definitions.html.
6 | ;
7 | ; The definitions below depend on the following items:
8 | ;
9 | ; - SI_ units from [BIPM2006]_
10 | ;
11 | ; ====== ========== ========== ============
12 | ; Symbol Expression Prefixable Name & notes
13 | ; ====== ========== ========== ============
14 | [Time]
15 | shake = 10*ns , False ; `shake `_
16 | ; ====== ========== ========== ============
17 | ;
18 | ; .. _SI: http://en.wikipedia.org/wiki/International_System_of_Units
19 | ;
20 | ; .. rubric:: References
21 | ;
22 | ; .. [BIPM2006] International Bureau of Weights and Measures (BIPM),
23 | ; "`The International System of Units (SI)
24 | ; `_,"
25 | ; 8th ed., 2006.
26 |
--------------------------------------------------------------------------------
/hooks/README.md:
--------------------------------------------------------------------------------
1 | This folder contains scripts that help with the development and release of natu.
2 |
3 | The [pre-commit script](pre-commit) prevents commits if there are errors in the
4 | Python source or there are filenames with non-ASCII characters. It also adds
5 | an "UNRELEASED" markdown file in the base folder if there is no version marked
6 | in [natu/__init__.py](../natu/__init__.py).
7 |
8 | The [post-checkout script](post-checkout) removes byte-compiled Python files
9 | (*.pyc) when switching branches. Since the source may change when upon
10 | checkout, the *.pyc files should be recompiled to prevent confusion.
11 |
12 | Other scripts ([code.sh](code.sh), [doc.sh](doc.sh), etc.) are linked to [git]
13 | via aliases.
14 |
15 | #### Installation
16 |
17 | Copy [pre-commit](pre-commit) and [post-checkout](post-checkout) to
18 | *.git/hooks/*.
19 |
20 | Add to *.git/config*:
21 |
22 | [alias]
23 | cloc = !bash `git rev-parse --show-toplevel`/hooks/cloc.sh
24 | diff-ini = !bash `git rev-parse --show-toplevel`/hooks/diff-ini.sh
25 | pylint = !bash `git rev-parse --show-toplevel`/hooks/pylint.sh
26 | doc = !bash `git rev-parse --show-toplevel`/hooks/doc.sh
27 | code = !bash `git rev-parse --show-toplevel`/hooks/code.sh
28 |
29 | #### Usage
30 |
31 | ##### For source code:
32 |
33 | To clean/remove the built code (alias for `setup.py clean --all`):
34 |
35 | git code clean
36 |
37 | To build/make a distributable copy and run tests:
38 |
39 | git code build
40 |
41 | To release/upload a version to [PyPI]\:
42 |
43 | git code release
44 |
45 | ##### For documentation:
46 |
47 | To clean/remove the built documentation:
48 |
49 | git doc clean
50 |
51 | To build/make the HTML documentation, with an option to rebuild the static
52 | images and spellcheck the pages:
53 |
54 | git doc build
55 |
56 | To release/publish the documentation to the [GitHub webpage]\:
57 |
58 | git doc release
59 |
60 | ##### Other:
61 |
62 | To compare the \*.ini files to their ReST tables in the documentation:
63 |
64 | git diff-ini
65 |
66 | To run [pylint](http://www.pylint.org/) on all of the source files:
67 |
68 | git pylint
69 |
70 | To count the number of lines of code:
71 |
72 | git cloc
73 |
74 | #### Development workflow
75 |
76 | All releases and updates are on the `master` branch. During the build process,
77 | (`git code build`), releases are tagged as "v*major*.*minor*.*micro*", where
78 | *major*, *minor*, and *micro* are the integer parts of the version number. The
79 | unreleased updates have an "UNRELEASED.md" file in the base folder with the
80 | commit date/time and the author.
81 |
82 | The version number is recorded in [natu/__init__.py](../natu/__init__.py). It
83 | is *None* for unreleased copies. When the documentation is built
84 | (`git doc build`), the download link and text is updated with information from
85 | the last tag, which corresponds to the last release.
86 |
87 |
88 | [git]: http://git-scm.com/
89 | [GitHub webpage]: kdavies4.github.io/natu/
90 | [PyPI]: https://pypi.python.org/pypi/natu
91 |
--------------------------------------------------------------------------------
/hooks/cloc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Count the number of lines of code in the project.
3 |
4 | perl hooks/cloc.pl natu
5 |
--------------------------------------------------------------------------------
/hooks/code.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Script to clean, build, and release the natu code.
3 | """
4 |
5 | # pylint: disable=I0011, C0103, C0325, E0611
6 |
7 | import sys
8 | import os
9 |
10 | from time import strftime
11 | from collections import namedtuple
12 | from docutils.core import publish_string
13 | from sh import bash, git, python, python3, rm
14 | from natu import util
15 |
16 | setup = python.bake('setup.py')
17 |
18 | def build():
19 | """Build the code to prepare for release.
20 | """
21 |
22 | # Check that long-description.txt is a valid ReST file (otherwise, the PyPI
23 | # page won't display correctly).
24 | readme = 'doc/long-description.txt'
25 | error_start = 'Docutils System Messages\n'
26 | with open(readme, 'r') as rstfile:
27 | parsed = publish_string(rstfile.read())
28 | if error_start in parsed:
29 | print("Errors in " + readme)
30 | util.delayed_exit()
31 |
32 | # Run other setup tests.
33 | if setup.check('-rms').exit_code:
34 | print("The setup.py check failed.")
35 | util.delayed_exit()
36 |
37 | # Get the new version number.
38 | commit = git('rev-list', '--tags', '--max-count=1').stdout.rstrip()
39 | lastversion = git.describe('--tags', commit).stdout.rstrip().lstrip('v')
40 | # This is simpler but doesn't always return the latest tag:
41 | # lastversion = git.describe('--tag', abbrev=0).stdout.rstrip()
42 | version = raw_input("Enter the version number (last was %s): "
43 | % lastversion)
44 |
45 | # Tag the version (will prompt for message).
46 | git.tag('-af', 'v' + version)
47 |
48 | # Update the version number.
49 | # In CHANGES.txt:
50 | date = strftime('%Y-%-m-%-d')
51 | rpls = [(r'TBD.*( -- Updates:)',
52 | r'v{v}_ ({d})\1'.format(v=version, d=date)),
53 | (r'v%s_ \(.+\)( -- Updates:)' % version,
54 | r'v{v}_ ({d})\1'.format(v=version, d=date)),
55 | (r'(.. _)vx\.x\.x(.+)vx\.x\.x(\.zip)',
56 | r'\1v{v}\2v{v}\3'.format(v=version))]
57 | util.replace('CHANGES.txt', rpls)
58 | # Note that versioneer automatically handles the version number in
59 | # natu/__init__.py.
60 |
61 | # Build, install, and test the code.
62 | setup.build()
63 | os.system('sudo python setup.py install')
64 | os.system('sudo python3 setup.py install')
65 | os.system('python setup.py test')
66 | os.system('python3 setup.py test')
67 |
68 | # Create a tarball and zip (*.tar.gz and *.zip).
69 | setup.sdist(formats='gztar,zip')
70 |
71 | def clean():
72 | """Clean/remove the built code.
73 | """
74 | setup.clean('--all')
75 | rm('-rf', "natu.egg-info")
76 |
77 |
78 | def release():
79 | """Release/publish the code.
80 | """
81 |
82 | # Rebase and push the master with tags to origin.
83 | print("Here are the remaining TODO items:")
84 | print(bash('TODO.sh'))
85 | print()
86 | if not util.yes("Do you still want to rebase and push the master with tags "
87 | "to origin (y/n)?"):
88 | util.delayed_exit()
89 | git.rebase('-i', 'origin/master')
90 | git.push('--tags', 'origin', 'master')
91 |
92 | # Upload to PyPI.
93 | if not util.yes("Do you want to upload to PyPI (this is permanent!) "
94 | "(y/n)?"):
95 | util.delayed_exit()
96 | setup.sdist.upload()
97 |
98 | # Reset the version number.
99 | # In CHANGES.txt:
100 | newheading = ('TBD (in `GitHub `_ '
101 | 'only) -- Updates:')
102 | newlink = ('.. _vx.x.x: '
103 | 'https://github.com/kdavies4/natu/archive/vx.x.x.zip')
104 | rpls = [(r'(`_\.)',
105 | r'\1\n\n' + newheading),
106 | (r'(Initial release\n\n\n)',
107 | r'\1%s\n' % newlink)]
108 | util.replace('CHANGES.txt', rpls)
109 | # Note that versioneer automatically handles the version number in
110 | # natu/__init__.py.
111 |
112 | Action = namedtuple("Action", ['f', 'description'])
113 | ACTIONS = {'clean' : Action(clean, "Clean/remove the built code."),
114 | 'build' : Action(build, "Build the code to prepare for release."),
115 | 'release' : Action(release, "Release the code."),
116 | }
117 |
118 |
119 | def funcs_str():
120 | """Return a string listing the valid functions and their descriptions.
121 | """
122 | return "\n".join([" %s: %s" % (arg.ljust(8), function.description)
123 | for (arg, function) in ACTIONS.items()])
124 |
125 |
126 | # Main
127 | if len(sys.argv) != 2:
128 | raise SystemExit("Exactly one argument is required; valid args are\n"
129 | + funcs_str())
130 | ACTION = sys.argv[1]
131 | try:
132 | ACTIONS[ACTION].f()
133 | except KeyError:
134 | raise SystemExit("Do not know how to handle %s; valid args are\n%s"
135 | % (ACTION, funcs_str()))
136 |
--------------------------------------------------------------------------------
/hooks/code.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Run commands related to source code.
3 |
4 | python hooks/code.py $1
--------------------------------------------------------------------------------
/hooks/diff-ini.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Compare the \*-ini.rst files in the documenation to the corresponding \*.ini
3 | # source files.
4 | #
5 | # If an argument is given, it is taken as the base filename to compare (without
6 | # .ini or -ini.rst). If no argument is given, then all of the files are
7 | # compared.
8 | #
9 | # This requires Meld (http://meldmerge.org/).
10 |
11 | if [[ $1 == '' ]]; then
12 | (cd doc
13 | for f in *-ini.rst; do
14 | meld ../natu/config/${f:0:${#f}-8}.ini $f
15 | done
16 | )
17 | else
18 | meld natu/config/$1.ini doc/$1-ini.rst
19 | fi
20 |
--------------------------------------------------------------------------------
/hooks/doc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Run commands related to the documentation.
3 |
4 | (cd doc
5 | python make.py $1
6 | )
--------------------------------------------------------------------------------
/hooks/post-checkout:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Delete .pyc files from the project
4 | # http://codeinthehole.com/writing/a-useful-git-post-checkout-hook-for-python-repos/
5 | # Go to the root of the project
6 | cd ./$(git rev-parse --show-cdup)
7 | # Find and delete all *.pyc files
8 | NUM_PYC_FILES=$( find . -name "*.pyc" | wc -l | tr -d ' ' )
9 | if [ $NUM_PYC_FILES -gt 0 ]; then
10 | find . -name "*.pyc" -delete
11 | echo "Deleted $NUM_PYC_FILES .pyc files"
12 | fi
--------------------------------------------------------------------------------
/hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # ------------------------------------------------------------------------------
4 | # Check for errors in the Python code.
5 | # Based on http://www.sitepoint.com/git-hooks-fun-profit/
6 | git diff --cached --name-status --diff-filter=ACMR | while read STATUS FILE; do
7 | if [[ ${FILE: -3} == ".py" ]]; then
8 | python -m py_compile "$FILE" 1> /dev/null
9 | if [ $? -ne 0 ]; then
10 | echo "Aborting commit due to errors in Python code" >&2
11 | exit 1
12 | fi
13 | fi
14 | done
15 |
16 | #-------------------------------------------------------------------------------
17 | # Check for file names with non-ASCII characters.
18 | # From pre-commit.sample
19 |
20 | if git rev-parse --verify HEAD >/dev/null 2>&1
21 | then
22 | against=HEAD
23 | else
24 | # Initial commit: diff against an empty tree object
25 | against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
26 | fi
27 |
28 | # If you want to allow non-ascii filenames, set this variable to true.
29 | allownonascii=$(git config hooks.allownonascii)
30 |
31 | # Cross platform projects tend to avoid non-ascii filenames; prevent
32 | # them from being added to the repository. We exploit the fact that the
33 | # printable range starts at the space character and ends with tilde.
34 | if [ "$allownonascii" != "true" ] &&
35 | # Note that the use of brackets around a tr range is ok here, (it's
36 | # even required, for portability to Solaris 10's /usr/bin/tr), since
37 | # the square bracket bytes happen to fall in the designated range.
38 | test "$(git diff --cached --name-only --diff-filter=A -z $against |
39 | LC_ALL=C tr -d '[ -~]\0')"
40 | then
41 | echo "Error: Attempt to add a non-ascii file name."
42 | echo
43 | echo "This can cause problems if you want to work"
44 | echo "with people on other platforms."
45 | echo
46 | echo "To be portable it is advisable to rename the file ..."
47 | echo
48 | echo "If you know what you are doing you can disable this"
49 | echo "check using:"
50 | echo
51 | echo " git config hooks.allownonascii true"
52 | echo
53 | exit 1
54 | fi
55 |
--------------------------------------------------------------------------------
/hooks/pylint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Run pylint on the source files.
3 | #
4 | # The standard/project-wide pylint disable settings are not included here but
5 | # rather in each file so that https://landscape.io respects them.
6 |
7 | for f in $(find natu -name '*.py'); do
8 | pylint -r n --msg-template='{line}: [{msg_id}({symbol}), {obj}] {msg}' -f colorized $f
9 | done
10 |
--------------------------------------------------------------------------------
/natu/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Natural units in Python
3 | """
4 | __author__ = "Kevin Davies"
5 | __email__ = "kdavies4@gmail.com"
6 | __copyright__ = ("Copyright 2013-2014, Kevin Davies, Hawaii Natural Energy "
7 | "Institute, and Georgia Tech Research Corporation")
8 | __license__ = "BSD-compatible (see LICENSE.txt)"
9 |
10 | from ._version import get_versions
11 | __version__ = get_versions()['version']
12 | del get_versions
--------------------------------------------------------------------------------
/natu/_decorators.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Decorators to update the functions of Python math and Numpy umath
3 | """
4 |
5 | # pylint: disable=I0011, C0103, C0111, E0611, E1101, W0141, W0142, W0621
6 |
7 | from sys import version
8 | from .core import (Quantity, ScalarUnit, assert_homogeneous, homogeneous,
9 | merge, value, dimensionless_value)
10 | from .units import rad
11 |
12 | # TODO: Combine some of these once Python can propagate a function's signature
13 | # up through a decorator (PEP 362?).
14 |
15 | # functools
16 | # ---------
17 |
18 | if version >= '3':
19 | from functools import wraps
20 | else:
21 | # Python2's functools.wraps requires that all of the attributes are
22 | # present. We need "except AttributeError: pass" to wrap numpy ufuncs,
23 | # since they don't have __module__.
24 |
25 | from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES, partial
26 |
27 | # The following two functions are from Python 3.2
28 | # (http://hg.python.org/cpython/file/3.2/Lib/functools.py).
29 |
30 | def update_wrapper(wrapper, wrapped,
31 | assigned=WRAPPER_ASSIGNMENTS,
32 | updated=WRAPPER_UPDATES):
33 | """Update a wrapper function to look like the wrapped function.
34 |
35 | **Parameters:**
36 |
37 | - :func:`wrapper`: function to be updated
38 |
39 | - :func:`wrapped`: original function
40 |
41 | - *assigned*: tuple naming the attributes assigned directly from
42 | :func:`wrapped` to :func:`wrapper`
43 |
44 | *assigned* defaults to :const:`functools.WRAPPER_ASSIGNMENTS`.
45 |
46 | - *updated*: tuple naming the attributes of :func:`wrapper` that are
47 | updated with the corresponding attribute from :func:`wrapped`
48 |
49 | *updated* defaults to :const:`functools.WRAPPER_UPDATES`.
50 | """
51 | wrapper.__wrapped__ = wrapped
52 | for attr in assigned:
53 | try:
54 | value = getattr(wrapped, attr)
55 | except AttributeError:
56 | pass
57 | else:
58 | setattr(wrapper, attr, value)
59 | for attr in updated:
60 | getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
61 |
62 | # Return the wrapper so this can be used as a decorator via partial().
63 | return wrapper
64 |
65 | def wraps(wrapped,
66 | assigned=WRAPPER_ASSIGNMENTS,
67 | updated=WRAPPER_UPDATES):
68 | """Apply :func:`update_wrapper` to a wrapper function.
69 |
70 | This decorator factory returns a decorator that invokes
71 | :func:`update_wrapper` with the decorated function as the wrapper
72 | argument and the arguments to this function as the remaining arguments.
73 | Default arguments are as for :func:`update_wrapper`. This is a
74 | convenience function to simplify applying :func:`partial` to
75 | :func:`update_wrapper`.
76 | """
77 | return partial(update_wrapper, wrapped=wrapped,
78 | assigned=assigned, updated=updated)
79 |
80 | # Standard functions
81 | # ------------------
82 |
83 | def merge_raise(value, prototype, power):
84 | """Same as :func:`~natu.core.merge`, but raise the dimension and display
85 | unit to *power*
86 | """
87 | try:
88 | dimension = prototype.dimension
89 | except AttributeError:
90 | return value
91 | try:
92 | prefixable = prototype.prefixable
93 | except AttributeError:
94 | return Quantity(value, power*dimension, power*prototype.display_unit)
95 | return ScalarUnit(value, power*dimension, power*prototype.display_unit,
96 | prefixable)
97 |
98 | # Elementary wrappers
99 | # -------------------
100 |
101 | def arg_x(func):
102 | """Decorate a function to accept *x* as a keyword argument.
103 | """
104 | @wraps(func)
105 | def wrapped(x):
106 | return func(x)
107 | return wrapped
108 |
109 | def arg_xi(func):
110 | """Decorate a function to accept *x* and *i* as keyword arguments.
111 | """
112 | @wraps(func)
113 | def wrapped(x, i):
114 | return func(x, i)
115 | return wrapped
116 |
117 | def arg_yx(func):
118 | """Decorate a function to accept *y* and *x* as keyword arguments.
119 | """
120 | @wraps(func)
121 | def wrapped(y, x):
122 | return func(y, x)
123 | return wrapped
124 |
125 | def change_doc(func, doc=None):
126 | """Update the docstring of a function.
127 |
128 | Wrap the function if the docstring is not writeable.
129 | """
130 | if doc is None:
131 | return func
132 | try:
133 | func.__doc__ = doc
134 | except AttributeError:
135 | @wraps(func)
136 | def wrapped(x):
137 | """Pass-through function of x"""
138 | return func(x)
139 | wrapped.__doc__ = doc
140 | return wrapped
141 | return func
142 |
143 | def copy_props(func):
144 | """Decorate a function to return a :class:`~natu.core.ScalarUnit` or
145 | :class:`~natu.core.Quantity` instance that matches the first argument except
146 | for the computed value.
147 | """
148 | @wraps(func)
149 | def wrapped(x, *args, **kwargs):
150 | try:
151 | value = x._value
152 | except AttributeError:
153 | return func(x, *args, **kwargs) # Pass-through
154 | return merge(func(value, *args, **kwargs), x)
155 |
156 | wrapped.__doc__ += (
157 | "\nThe properties of the first term (:attr:`dimension`, \n"
158 | "\n:attr:`display_unit`, etc.) are copied to the result.\n")
159 | return wrapped
160 |
161 | def dimensionless(func):
162 | """Decorate a function to accept a number or a dimensionless quantity.
163 |
164 | If the quantity is not dimensionless, a TypeError is raised.
165 | """
166 | @wraps(func)
167 | def wrapped(*args):
168 | return func(*map(dimensionless_value, args))
169 |
170 | return wrapped
171 |
172 | def dimensionless_implicit(func):
173 | """Decorate a function to give a special :class:`TypeError` message about
174 | dimensionality.
175 |
176 | This is triggered when a quantity is cast as a :class:`float` or
177 | :class:`int` but it is not dimensionless.
178 | """
179 | @wraps(func)
180 | def wrapped(*args):
181 | try:
182 | return func(*args)
183 | except TypeError:
184 | raise TypeError("The quantity must be dimensionless.")
185 |
186 | return wrapped
187 |
188 | # Compound wrappers
189 | # -----------------
190 |
191 | def dimensionless_copy_props(func, doc=None):
192 | """Wrap a function to accept dimensionless quantities and pass the
193 | dimension, display unit, etc. Change the docstring to *doc*.
194 | """
195 | return change_doc(arg_x(copy_props(dimensionless_implicit(func))), doc)
196 |
197 | def trig(func, doc=None):
198 | """Wrap a trigonometric function that accepts angle in radians to accept
199 | angle as a quantity.
200 | """
201 | @wraps(func)
202 | def wrapped(theta):
203 | try:
204 | return func(theta / rad)
205 | except TypeError:
206 | raise TypeError("The argument must be an angle or zero.")
207 |
208 | return change_doc(wrapped, doc)
209 |
210 | def inv_trig(func, doc=None):
211 | """Wrap an inverse trigonometric function that returns angle in radians to
212 | return angle as a quantity.
213 | """
214 | @wraps(func)
215 | def wrapped(x):
216 | return func(x) * rad
217 |
218 | return change_doc(wrapped, doc)
219 |
220 | def inv_trig_yx(func, doc=None):
221 | """Wrap a dual-input inverse trigonometric function that returns angle in
222 | radians to return angle as a quantity.
223 | """
224 | # Note that *args isn't used because the variables wouldn't be labeled in
225 | # the documentation.
226 | @arg_yx
227 | @homogeneous
228 | @wraps(func)
229 | def wrapped(y, x):
230 | return func(y, x) * rad
231 |
232 | return change_doc(wrapped, doc)
233 |
234 | def homogeneous_copy_props(func):
235 | """Wrap a function to use the :attr:`value` of quantities and pass the
236 | dimension, display unit, etc. of the first argument. Check that the
237 | quantities have the same dimension.
238 | """
239 | return copy_props(homogeneous(func))
240 |
241 | def homogeneous_copy_props_iter(func):
242 | """Decorate a function to use the values of an iterable of quantities and
243 | pass the dimension, display unit, etc. of the first quantity.
244 | """
245 | @wraps(func)
246 | def wrapped(x):
247 | assert_homogeneous(*x)
248 | return merge(func(map(value, x)), x[0])
249 |
250 | return wrapped
251 |
252 | def use_value(func, doc=None):
253 | """Wrap a function to use the value of a quantity.
254 | """
255 | @wraps(func)
256 | def wrapped(x):
257 | return func(value(x))
258 |
259 | return change_doc(wrapped, doc)
260 |
261 | def use_value_copy_props(func, doc):
262 | """Wrap a function to use the :attr:`value` of a quantity and pass the
263 | dimension, display unit, etc. Change the docstring to *doc*.
264 | """
265 | return change_doc(arg_x(copy_props(use_value(func))), doc)
266 |
267 | def use_value_raise(func, y=None):
268 | """Wrap a function to use the value of a quantity and raise the dimension
269 | and display unit to a power.
270 |
271 | If the power (*y*) is not given as an argument to this wrapper, then it is
272 | an argument to the function itself.
273 | """
274 | @wraps(func)
275 | def wrapped(x, y):
276 | return merge_raise(func(value(x), y), x, y)
277 |
278 | @wraps(func)
279 | def wrapped_fixed(x):
280 | return merge_raise(func(value(x)), x, y)
281 |
282 | return wrapped if y is None else wrapped_fixed
283 |
284 | def use_values_copy_props(func, doc=None):
285 | """Decorate a function to use the values of two quantities and pass the
286 | properties (:attr:`dimension`, :attr:`display`, etc.) of the first.
287 | """
288 | @copy_props
289 | @wraps(func)
290 | def wrapped(x, y):
291 | return func(value(x), value(y))
292 |
293 | return change_doc(wrapped, doc)
294 |
295 | def use_values_copy_props_xi(func, doc=None):
296 | """Wrap a function to use the :attr:`value` of quantities and pass the
297 | dimension, display unit, etc. of the first argument. Change the docstring
298 | to *doc*.
299 | """
300 | return change_doc(arg_xi(use_values_copy_props(func)), doc)
301 |
--------------------------------------------------------------------------------
/natu/_prefixes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Contains *PREFIXES*, a dictionary of SI prefixes
3 | """
4 | # [BIPM2006]: International Bureau of Weights and Measures (BIPM), "The
5 | # International System of Units (SI)," 8th ed., 2006.
6 |
7 | # [BIPM2006, Table 5]
8 | PREFIXES = dict(Y=1e24, # yotta
9 | Z=1e21, # zetta
10 | E=1e18, # exa
11 | P=1e15, # peta
12 | T=1e12, # tera
13 | G=1e9, # giga
14 | M=1e6, # mega
15 | k=1e3, # kilo
16 | h=100, # hecto
17 | da=10, # deca
18 | d=0.1, # deci
19 | c=0.01, # centi
20 | m=1e-3, # milli
21 | u=1e-6, # micro
22 | n=1e-9, # nano
23 | p=1e-12, # pico
24 | f=1e-15, # femto
25 | a=1e-18, # atto
26 | z=1e-21, # zepto
27 | y=1e-24) # yocto
28 |
--------------------------------------------------------------------------------
/natu/_version.py:
--------------------------------------------------------------------------------
1 |
2 | # This file helps to compute a version number in source trees obtained from
3 | # git-archive tarball (such as those provided by githubs download-from-tag
4 | # feature). Distribution tarballs (built by setup.py sdist) and build
5 | # directories (produced by setup.py build) will contain a much shorter file
6 | # that just contains the computed version number.
7 |
8 | # This file is released into the public domain. Generated by
9 | # versioneer-0.12 (https://github.com/warner/python-versioneer)
10 |
11 | # these strings will be replaced by git during git-archive
12 | git_refnames = " (HEAD -> master, tag: v0.1.2)"
13 | git_full = "f91e7c4be59bf96ff0c069d009307b0aebc09a63"
14 |
15 | # these strings are filled in when 'setup.py versioneer' creates _version.py
16 | tag_prefix = "v"
17 | parentdir_prefix = "natu-"
18 | versionfile_source = "natu/_version.py"
19 |
20 | import os, sys, re, subprocess, errno
21 |
22 | def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
23 | assert isinstance(commands, list)
24 | p = None
25 | for c in commands:
26 | try:
27 | # remember shell=False, so use git.cmd on windows, not just git
28 | p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
29 | stderr=(subprocess.PIPE if hide_stderr
30 | else None))
31 | break
32 | except EnvironmentError:
33 | e = sys.exc_info()[1]
34 | if e.errno == errno.ENOENT:
35 | continue
36 | if verbose:
37 | print("unable to run %s" % args[0])
38 | print(e)
39 | return None
40 | else:
41 | if verbose:
42 | print("unable to find command, tried %s" % (commands,))
43 | return None
44 | stdout = p.communicate()[0].strip()
45 | if sys.version >= '3':
46 | stdout = stdout.decode()
47 | if p.returncode != 0:
48 | if verbose:
49 | print("unable to run %s (error)" % args[0])
50 | return None
51 | return stdout
52 |
53 |
54 | def versions_from_parentdir(parentdir_prefix, root, verbose=False):
55 | # Source tarballs conventionally unpack into a directory that includes
56 | # both the project name and a version string.
57 | dirname = os.path.basename(root)
58 | if not dirname.startswith(parentdir_prefix):
59 | if verbose:
60 | print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" %
61 | (root, dirname, parentdir_prefix))
62 | return None
63 | return {"version": dirname[len(parentdir_prefix):], "full": ""}
64 |
65 | def git_get_keywords(versionfile_abs):
66 | # the code embedded in _version.py can just fetch the value of these
67 | # keywords. When used from setup.py, we don't want to import _version.py,
68 | # so we do it with a regexp instead. This function is not used from
69 | # _version.py.
70 | keywords = {}
71 | try:
72 | f = open(versionfile_abs,"r")
73 | for line in f.readlines():
74 | if line.strip().startswith("git_refnames ="):
75 | mo = re.search(r'=\s*"(.*)"', line)
76 | if mo:
77 | keywords["refnames"] = mo.group(1)
78 | if line.strip().startswith("git_full ="):
79 | mo = re.search(r'=\s*"(.*)"', line)
80 | if mo:
81 | keywords["full"] = mo.group(1)
82 | f.close()
83 | except EnvironmentError:
84 | pass
85 | return keywords
86 |
87 | def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
88 | if not keywords:
89 | return {} # keyword-finding function failed to find keywords
90 | refnames = keywords["refnames"].strip()
91 | if refnames.startswith("$Format"):
92 | if verbose:
93 | print("keywords are unexpanded, not using")
94 | return {} # unexpanded, so not in an unpacked git-archive tarball
95 | refs = set([r.strip() for r in refnames.strip("()").split(",")])
96 | # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
97 | # just "foo-1.0". If we see a "tag: " prefix, prefer those.
98 | TAG = "tag: "
99 | tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
100 | if not tags:
101 | # Either we're using git < 1.8.3, or there really are no tags. We use
102 | # a heuristic: assume all version tags have a digit. The old git %d
103 | # expansion behaves like git log --decorate=short and strips out the
104 | # refs/heads/ and refs/tags/ prefixes that would let us distinguish
105 | # between branches and tags. By ignoring refnames without digits, we
106 | # filter out many common branch names like "release" and
107 | # "stabilization", as well as "HEAD" and "master".
108 | tags = set([r for r in refs if re.search(r'\d', r)])
109 | if verbose:
110 | print("discarding '%s', no digits" % ",".join(refs-tags))
111 | if verbose:
112 | print("likely tags: %s" % ",".join(sorted(tags)))
113 | for ref in sorted(tags):
114 | # sorting will prefer e.g. "2.0" over "2.0rc1"
115 | if ref.startswith(tag_prefix):
116 | r = ref[len(tag_prefix):]
117 | if verbose:
118 | print("picking %s" % r)
119 | return { "version": r,
120 | "full": keywords["full"].strip() }
121 | # no suitable tags, so we use the full revision id
122 | if verbose:
123 | print("no suitable tags, using full revision id")
124 | return { "version": keywords["full"].strip(),
125 | "full": keywords["full"].strip() }
126 |
127 |
128 | def git_versions_from_vcs(tag_prefix, root, verbose=False):
129 | # this runs 'git' from the root of the source tree. This only gets called
130 | # if the git-archive 'subst' keywords were *not* expanded, and
131 | # _version.py hasn't already been rewritten with a short version string,
132 | # meaning we're inside a checked out source tree.
133 |
134 | if not os.path.exists(os.path.join(root, ".git")):
135 | if verbose:
136 | print("no .git in %s" % root)
137 | return {}
138 |
139 | GITS = ["git"]
140 | if sys.platform == "win32":
141 | GITS = ["git.cmd", "git.exe"]
142 | stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
143 | cwd=root)
144 | if stdout is None:
145 | return {}
146 | if not stdout.startswith(tag_prefix):
147 | if verbose:
148 | print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix))
149 | return {}
150 | tag = stdout[len(tag_prefix):]
151 | stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
152 | if stdout is None:
153 | return {}
154 | full = stdout.strip()
155 | if tag.endswith("-dirty"):
156 | full += "-dirty"
157 | return {"version": tag, "full": full}
158 |
159 |
160 | def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
161 | # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
162 | # __file__, we can work backwards from there to the root. Some
163 | # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
164 | # case we can only use expanded keywords.
165 |
166 | keywords = { "refnames": git_refnames, "full": git_full }
167 | ver = git_versions_from_keywords(keywords, tag_prefix, verbose)
168 | if ver:
169 | return ver
170 |
171 | try:
172 | root = os.path.abspath(__file__)
173 | # versionfile_source is the relative path from the top of the source
174 | # tree (where the .git directory might live) to this file. Invert
175 | # this to find the root from __file__.
176 | for i in range(len(versionfile_source.split(os.sep))):
177 | root = os.path.dirname(root)
178 | except NameError:
179 | return default
180 |
181 | return (git_versions_from_vcs(tag_prefix, root, verbose)
182 | or versions_from_parentdir(parentdir_prefix, root, verbose)
183 | or default)
184 |
--------------------------------------------------------------------------------
/natu/config/BIPM.ini:
--------------------------------------------------------------------------------
1 | ; BIPM units
2 | ; ==========
3 | ;
4 | ; This file implements the definitions from [BIPM2006]_, including the System
5 | ; International (SI_) units and some non-SI units.
6 | ;
7 | ; For the full documentation, please see
8 | ; https://kdavies4.github.com/natu/BIPM-ini.html.
9 | ;
10 | ; This file depends on the following items:
11 | ;
12 | ; - Classes: :class:`~natu.core.ScalarUnit`
13 | ; - Functions: :func:`math.exp`, :func:`math.log`, and :func:`math.log10`
14 | ; - Mathematical constants: *pi*
15 | ; - Base physical constants: *R_inf*, *c*, *k_J*, *R_K*, *k_F*, and *R*
16 | ; - Units: cyc
17 | ;
18 | ; ======= =================================================== ========== ============
19 | ; Symbol Expression Prefixable Name & notes
20 | ; ======= =================================================== ========== ============
21 | [Mathematical relations]
22 | rad = cyc/(2*pi) , True ; `radian `_
23 | [Empirical relations]
24 | m = 10973731.568539*cyc/R_inf , True ; `metre `_
25 | s = 299792458*m/c , True ; `second `_
26 | Wb = 483597.870e9/k_J , True ; `weber `_
27 | S = 25812.8074434/(R_K*cyc) , True ; `siemens `_ (aka mho)
28 | mol = 96485.3365*Wb*cyc*S/k_F , True ; `mole `_
29 | K = 8.3144621*(Wb*cyc)**2*S/(s*mol*R) , True ; `kelvin `_
30 | [Units decoupled from the base constants]
31 | cd = ScalarUnit(1, 'J') , True ; `candela `_ (decoupled by the `luminosity function `_)
32 | [Remaining SI base units (BIPM2006_, Table 1) and intermediate units]
33 | Hz = cyc/s , True ; `hertz `_
34 | V = Wb*Hz , True ; `volt `_
35 | A = V*S , True ; `ampere `_
36 | C = A*s , True ; `coulomb `_
37 | J = V*C , True ; `joule `_
38 | Gy = m**2/s**2 , True ; `gray `_
39 | kg = J/Gy , False ; `kilogram `_
40 | g = kg/1000 , True ; `gram `_ (included for prefixes other than k)
41 | [Remaining coherent derived SI units (BIPM2006_, Table 3)]
42 | sr = rad**2 , True ; `steradian `_
43 | lm = cd*sr , True ; `lumen `_
44 | W = J/s , True ; `watt `_
45 | N = J/m , True ; `newton `_
46 | Pa = N/m**2 , True ; `pascal `_
47 | T = Wb/m**2 , True ; `tesla `_
48 | lx = lm/m**2 , True ; `lux `_
49 | F = s*S , True ; `farad `_
50 | ohm = S**-1 , True ; `ohm `_
51 | H = s/S , True ; `henry `_
52 | kat = mol/s , True ; `katal `_
53 | Sv = Gy , True ; `sievert `_
54 | Bq = s**-1 , True ; `becquerel `_
55 | degC = (lambda n: (n + 273.15)*K, lambda T: T/K - 273.15), True ; `degree Celsius `_
56 | [Non-SI units accepted for use with SI (BIPM2006_, Table 6)]
57 | min = 60*s , False ; `minute `_
58 | hr = 60*min , False ; `hour `_
59 | d = 24*hr , False ; `day `_
60 | deg = cyc/360 , False ; `degree `_ (aka degree of arc, arc degree, or arcdegree)
61 | arcmin = deg/60 , False ; `arcminute `_
62 | arcsec = arcmin/60 , False ; `arcsecond `_
63 | ha = hm**2 , False ; `hectare `_
64 | L = dm**3 , True ; `litre `_
65 | t = Mg , False ; `tonne `_
66 | [Other non-SI units (BIPM2006_, Table 8)]
67 | g_0 = 9.80665*m/s**2 ; `standard gravity `_
68 | cc = cm**3 , False ; `cubic centimetre `_
69 | Hg = 13.5951*g*g_0/cc ; force per volume of `mercury `_ under `standard gravity`_
70 | mmHg = mm*Hg , False ; `millimetre of mercury `_
71 | bar = 100*kPa , True ; `bar `_
72 | b = 100*fm**2 , False ; `barn `_
73 | angstrom = 0.1*nm , False ; `angstrom `_
74 | nmi = 1852*m , False ; `nautical mile `_
75 | kn = nmi/hr , False ; `knot `_
76 | Np = (exp, log) , False ; `neper `_ (in terms of amplitude ratio, not power ratio)
77 | B = (lambda n: 10**n, log10) , True ; bel (in terms of power ratio, not amplitude ratio)
78 | dB = dB , False ; `decibel `_ (explicitly included with prefix)
79 | [Non-SI units associated with CGS and CGS-Gaussian system of units (BIPM2006_, Table 9)]
80 | cm = cm , False ; `centimetre `_ [not included in Table 9, but explicitly provided since CGS base unit]
81 | Gal = cm/s**2 , True ; `gal `_ (unit of acceleration)
82 | dyn = g*Gal , True ; `dyne `_ (unit of force)
83 | erg = dyn*cm , True ; `erg `_ (unit of energy)
84 | Ba = dyn/cm**2 , True ; `barye `_ (aka barad, barrie, bary, baryd, baryed, or barie; unit of pressure) [#f2]_
85 | P = Ba*s , True ; `poise `_ (unit of dynamic viscosity)
86 | St = cm**2/s , True ; `stokes `_ (aka stoke; unit of kinematic viscosity)
87 | sb = cd/cm**2 , True ; `stilb `_ (unit of luminance)
88 | ph = sb*sr , True ; `phot `_ (unit of illuminance)
89 | abA = daA , True ; `abampere `_ (aka decaampere or Biot (Bi)) [#f2]_
90 | Mx = erg/(abA*cyc) , True ; `maxwell `_ (unit of magnetic flux)
91 | Gs = Mx/cm**2 , True ; `gauss `_ (unit of magnetic flux density)
92 | pole = 4*pi*Mx , False ; unit pole [#f2]_
93 | Oe = dyn/pole , True ; `oersted `_ (unit of the auxiliary magnetic field)
94 | ; ======= =================================================== ========== ============
95 | ;
96 | ; .. _SI: http://en.wikipedia.org/wiki/International_System_of_Units
97 | ;
98 | ; .. rubric:: References
99 | ;
100 | ; .. [BIPM2006] International Bureau of Weights and Measures (BIPM),
101 | ; "`The International System of Units (SI)
102 | ; `_,"
103 | ; 8th ed., 2006.
104 |
--------------------------------------------------------------------------------
/natu/config/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | r"""Configuration settings
4 |
5 | This module contains the following settings (defaults in parentheses):
6 |
7 | - *definitions* (`base-SI.ini `_, `derived.ini
8 | `_, `BIPM.ini `_, and `other.ini
9 | `_ from the installation directory) - List of files that
10 | define the constants and units
11 |
12 | - *use_quantities* (*True*) - *True* to use quantities to track dimensions and
13 | display units
14 |
15 | If *use_quantities* is *False*, then the constants and scalar units are
16 | :class:`float` instances rather than :class:`~natu.core.Quantity` and
17 | :class:`~natu.core.ScalarUnit` instances. This reduces the computational
18 | overhead of the :mod:`natu` module to nearly zero while still allowing
19 | variables to be specified using various units. However, this disables
20 | dimension checking and the string formatting of quantities as the product
21 | of a number and a unit, so it is probably best to leave *use_quantities*
22 | set to *True* until you have validated your unit-dependent code.
23 |
24 | - *simplification_level* (2) - Number of non-minimizing substitutions that can
25 | be made in seeking the best display unit
26 |
27 | A higher number increases the likelihood that the simplest display unit
28 | will be found, but it also increases the time required to process
29 | :func:`str`, :func:`print`, :func:`format`, and related functions.
30 |
31 | - *default_format* ('') - Default format for printing units and dimensions
32 |
33 | For a list and description of valid values, see the Formatting section of
34 | :class:`~natu.exponents.Exponents`. Regardless of this setting, units and
35 | dimensions must be entered using the format accepted by
36 | :meth:`~natu.exponents.Exponents.from_str`.
37 |
38 | - *unit_replacements*
39 | (in HTML ('H' format code):
40 | 'deg' → '°',
41 | 'ohm' → 'Ω', and
42 | 'angstrom' → 'Å';
43 | in LaTeX_ ('L' format code):
44 | 'deg' → '^{\\circ}',
45 | 'ohm' → '\\Omega', and
46 | 'angstrom' → '\\AA';
47 | in Unicode_ ('U' format code):
48 | 'deg' → '°',
49 | 'ohm' → 'Ω', and
50 | 'angstrom' → 'Å'): Dictionary of special replacements for formatting a unit
51 | string
52 |
53 | Each key is a format code and each value is a list of tuples of 1) the
54 | string to be replaced and 2) the string that it should be replaced with.
55 |
56 | Import this module and change these settings as desired before importing any
57 | other :mod:`natu` submodules.
58 |
59 | **Examples:**
60 |
61 | To turn off unit simplification:
62 |
63 | >>> from natu import config
64 | >>> config.simplification_level = 0
65 |
66 | or to append a custom file of unit definitions:
67 |
68 | >>> config.definitions.append('custom.ini')
69 |
70 | Then use the rest of :mod:`natu`, for instance
71 |
72 | >>> from natu.units import *
73 |
74 | .. testcleanup::
75 | >>> print(kg/m/s)
76 | kg/(m*s)
77 |
78 |
79 | .. _Unicode: https://en.wikipedia.org/wiki/Unicode
80 | .. _LaTeX: http://www.latex-project.org/
81 | """
82 | # pylint: disable=I0011, C0103
83 |
84 | # List of unit definition files
85 | from os import path
86 | dname = path.dirname(__file__)
87 | definitions = [path.join(dname, fname) for fname in
88 | ['base-SI.ini', 'derived.ini', 'BIPM.ini', 'other.ini']]
89 | del path, dname
90 |
91 | # True to track dimensions and display units:
92 | use_quantities = True
93 |
94 | # Number of non-minimizing substitutions that can be made in seeking the
95 | # best display unit:
96 | simplification_level = 1
97 |
98 | # Default format for printing units and dimensions
99 | default_format = ''
100 |
101 | # Dictionary of special replacements for formatting a unit string
102 | unit_replacements = {'H': # In HTML:
103 | [('deg', '°'),
104 | ('ohm', 'Ω'),
105 | ('angstrom', 'Å')],
106 | 'L': # In LaTeX:
107 | [('deg', r'^{\circ}'),
108 | ('ohm', r'\Omega'),
109 | ('angstrom', r'\AA')],
110 | 'U': # In Unicode:
111 | [('deg', u'°'),
112 | ('ohm', u'Ω'),
113 | ('angstrom', u'Å')],
114 | }
115 |
--------------------------------------------------------------------------------
/natu/config/base-EMU.ini:
--------------------------------------------------------------------------------
1 | ; Base physical constants
2 | ; =======================
3 | ;
4 | ; This file establishes the physical constants which are used to derive all
5 | ; other constants and units. These base constants may be adjusted to establish
6 | ; various systems of units. The values in the `original version of this file
7 | ; `_
8 | ; are for the electromagnetic units (EMU), a subsystem of the `CGS units`_.
9 | ;
10 | ; For the full documentation, please see
11 | ; https://kdavies4.github.com/natu/base-ini.html.
12 | ;
13 | ; This file depends on the following items, which are automatically provided:
14 | ;
15 | ; - Classes: :class:`~natu.core.Quantity`
16 | ; - Mathematical constants: *pi*
17 | ;
18 | ; ======= ============================================================= ============
19 | ; Symbol Expression Name & notes
20 | ; ======= ============================================================= ============
21 | [Base physical constants]
22 | R_inf = Quantity(109737.31568539*2*pi, 'A/L', 'cyc/cm') ; `Rydberg constant `_
23 | c = Quantity(29979245800, 'L/T', 'cm/s') ; `speed of light `_ (aka Planck, Stoney, or natural unit of velocity)
24 | k_J = Quantity(4835978.70*2*pi, 'A*T/(L(3/2)*M(1/2))', '1/Mx') ; `Josephson constant `_
25 | R_K = Quantity(25812.8074434e9/(2*pi), 'L/(A*T)', 'cm/(s*cyc)') ; `von Klitzing constant `_
26 | k_F = Quantity(9648.53365, 'L(1/2)*M(1/2)/N', 'abC*s/(cm*mol)')*c ; `Faraday constant `_
27 | R = Quantity(8.3144621e7, 'L2*M/(N*T2*Theta)', 'erg/(mol*K)') ; `gas constant `_
28 | k_Aprime = Quantity(2*pi, 'A', 'cyc')*R_K/c ; modified Ampere constant (k_A*cyc/alpha)
29 | [Settings]
30 | rational = False ; *True* if the unit system is rationalized
31 | ; ======= ============================================================= ============
32 | ;
33 | ; _CGS units: https://en.wikipedia.org/wiki/CGS
34 |
--------------------------------------------------------------------------------
/natu/config/base-ESU.ini:
--------------------------------------------------------------------------------
1 | ; Base physical constants
2 | ; =======================
3 | ;
4 | ; This file establishes the physical constants which are used to derive all
5 | ; other constants and units. These base constants may be adjusted to establish
6 | ; various systems of units. The values in the `original version of this file
7 | ; `_
8 | ; are for the `electrostatic units (ESU)`_ or `Gaussian units`_. To use
9 | ; `Lorentz-Heaviside units`_, set *rational* = True.
10 | ;
11 | ; For the full documentation, please see
12 | ; https://kdavies4.github.com/natu/base-ini.html.
13 | ;
14 | ; This file depends on the following items, which are automatically provided:
15 | ;
16 | ; - Classes: :class:`~natu.core.Quantity`
17 | ; - Mathematical constants: *pi*
18 | ;
19 | ; ======= ===================================================================== ============
20 | ; Symbol Expression Name & notes
21 | ; ======= ===================================================================== ============
22 | [Base physical constants]
23 | R_inf = Quantity(109737.31568539*2*pi, 'A/L', 'cyc/cm') ; `Rydberg constant `_
24 | c = Quantity(29979245800, 'L/T', 'cm/s') ; `speed of light `_ (aka Planck, Stoney, or natural unit of velocity)
25 | k_J = Quantity(4835978.70*2*pi, 'A*T/(L(3/2)*M(1/2))', 's/(statT*cm3)')*c ; `Josephson constant `_
26 | R_K = Quantity(25812.8074434e9/(2*pi), 'L/(A*T)', 'cm/(s*cyc)')/c**2 ; `von Klitzing constant `_
27 | k_F = Quantity(9648.53365, 'M(1/2)*L(1/2)/N', 'g(1/2)*cm(1/2)/mol')*c ; `Faraday constant `_
28 | R = Quantity(8.3144621e7, 'L2*M/(N*T2*Theta)', 'erg/(mol*K)') ; `gas constant `_
29 | k_Aprime = Quantity(2*pi, 'A', 'cyc')*R_K/c ; modified Ampere constant (k_A*cyc/alpha)
30 | [Settings]
31 | rational = False ; *True* if the unit system is rationalized
32 | ; ======= ===================================================================== ============
33 | ;
34 | ; _electrostatic units (ESU): https://en.wikipedia.org/wiki/Electrostatic_units
35 | ; _Gaussian units: https://en.wikipedia.org/wiki/Gaussian_units
36 | ; _Lorentz-Heaviside units: https://en.wikipedia.org/wiki/Lorentz%E2%80%93Heaviside_units
37 |
--------------------------------------------------------------------------------
/natu/config/base-Hartree.ini:
--------------------------------------------------------------------------------
1 | ; Base physical constants
2 | ; =======================
3 | ;
4 | ; This file establishes the physical constants which are used to derive all
5 | ; other constants and units. These base constants may be adjusted to establish
6 | ; various systems of units. The values in the `original version of this file
7 | ; `_
8 | ; are for the `Hartree unit system`_, with the addition of
9 | ; :math:`k_\mathrm{F} = 1` to define the mole (mol).
10 | ;
11 | ; For the full documentation, please see
12 | ; https://kdavies4.github.com/natu/base-ini.html.
13 | ;
14 | ; This file depends on the following items, which are automatically provided:
15 | ;
16 | ; - Mathematical constants: *pi*
17 | ;
18 | ; ======= =============================== ============
19 | ; Symbol Expression Name & notes
20 | ; ======= =============================== ============
21 | [Base physical constants]
22 | R_inf = 299792458e-7*pi/25812.8074434 ; `Rydberg constant `_
23 | c = 1/(2*R_inf) ; `speed of light `_ (aka Planck, Stoney, or natural unit of velocity)
24 | k_J = 2 ; `Josephson constant `_
25 | R_K = 1 ; `von Klitzing constant `_
26 | k_F = 1 ; `Faraday constant `_
27 | R = k_F ; `gas constant `_
28 | k_Aprime = 2*pi*R_K/c ; modified Ampere constant (k_A*cyc/alpha)
29 | [Settings]
30 | rational = False ; *True* if the unit system is rationalized
31 | ; ======= =============================== ============
32 | ;
33 | ; _Hartree unit system: https://en.wikipedia.org/wiki/Atomic_units
34 |
--------------------------------------------------------------------------------
/natu/config/base-Planck.ini:
--------------------------------------------------------------------------------
1 | ; Base physical constants
2 | ; =======================
3 | ;
4 | ; This file establishes the physical constants which are used to derive all
5 | ; other constants and units. These base constants may be adjusted to establish
6 | ; various systems of units. The values in the `original version of this file
7 | ; `_
8 | ; are for the `Planck unit system`_, with the addition of
9 | ; :math:`k_\mathrm{F} = 1` to define the mole (mol). The values are based
10 | ; on the assumption that the units are rationalized (*rational* = *True*).
11 | ;
12 | ; For the full documentation, please see
13 | ; https://kdavies4.github.com/natu/base-ini.html.
14 | ;
15 | ; This file depends on the following items, which are automatically provided:
16 | ;
17 | ; - Mathematical constants: *pi*
18 | ; - Functions: :func:`math.sqrt`
19 | ;
20 | ; ======= ===================================================================================================== ============
21 | ; Symbol Expression Name & notes
22 | ; ======= ===================================================================================================== ============
23 | [Base physical constants]
24 | G = 1 ; `gravitational constant `_
25 | c = 1 ; `speed of light `_ (aka Planck, Stoney, or natural unit of velocity)
26 | k_J = 1 ; `Josephson constant `_
27 | R_K = sqrt(25812.8074434/(2*299792458*1e-7))/(pi*k_J) ; `von Klitzing constant `_
28 | k_F = 1 ; `Faraday constant `_
29 | R = k_F*k_J*R_K*sqrt(pi) ; `gas constant `_
30 | k_Aprime = 2*(pi*k_J*R_K)**2/c ; modified Ampere constant (k_A*cyc/alpha)
31 | [Empirical]
32 | R_inf = 10973731.568539*k_J*c**2*sqrt(k_Aprime*6.67384e-11/(G*R_K*25812.8074434*299792458**3))/483597.870e9 ; `Rydberg constant `_
33 | [Derived]
34 | l_P = sqrt(k_Aprime*G/2)/(c*k_J*R_K*pi) ; `Planck length `_
35 | M_P = l_P*c**2/G ; `Planck mass `_
36 | t_P = l_P/c ; `Planck time `_
37 | E_P = M_P*c**2 ; `Planck energy `_
38 | T_P = E_P*k_F*k_J*R_K*sqrt(pi)/R ; `Planck temperature `_
39 | [Settings]
40 | rational = True ; *True* if the unit system is rationalized
41 | ; ======= ===================================================================================================== ============
42 | ;
43 | ; _Planck unit system: https://en.wikipedia.org/wiki/Planck_units
44 |
--------------------------------------------------------------------------------
/natu/config/base-SI.ini:
--------------------------------------------------------------------------------
1 | ; Base physical constants
2 | ; =======================
3 | ;
4 | ; This file establishes the physical constants which are used to derive all
5 | ; other constants and units. These base constants may be adjusted to establish
6 | ; various systems of units. The values in the `original version of this file
7 | ; `_ are
8 | ; for the `International System of Units (SI)`_.
9 | ;
10 | ; For the full documentation, please see
11 | ; https://kdavies4.github.com/natu/base-ini.html.
12 | ;
13 | ; This file depends on the following items, which are automatically provided:
14 | ;
15 | ; - Classes: :class:`~natu.core.Quantity`
16 | ; - Mathematical constants: *pi*
17 | ;
18 | ; ======= ========================================================== ============
19 | ; Symbol Expression Name & notes
20 | ; ======= ========================================================== ============
21 | [Base physical constants]
22 | R_inf = Quantity(10973731.568539*2*pi, 'A/L', 'cyc/m') ; `Rydberg constant `_
23 | c = Quantity(299792458, 'L/T', 'm/s') ; `speed of light `_ (aka Planck, Stoney, or natural unit of velocity)
24 | k_J = Quantity(483597.870e9*2*pi, 'A*I*T2/(L2*M)', '1/Wb') ; `Josephson constant `_
25 | R_K = Quantity(25812.8074434/(2*pi), 'L2*M/(A*I2*T3)', 'Wb/C') ; `von Klitzing constant `_
26 | k_F = Quantity(96485.3365, 'I*T/N', 'C/mol') ; `Faraday constant `_
27 | R = Quantity(8.3144621, 'L2*M/(N*T2*Theta)', 'J/(mol*K)') ; `gas constant `_
28 | k_Aprime = Quantity(2*pi, 'A', 'rad')*R_K/c ; modified Ampere constant (k_A*cyc/alpha)
29 | [Settings]
30 | rational = True ; *True* if the unit system is rationalized
31 | ; ======= ========================================================== ============
32 | ;
33 | ; _International System of Units (SI): https://en.wikipedia.org/wiki/SI
34 |
--------------------------------------------------------------------------------
/natu/config/derived.ini:
--------------------------------------------------------------------------------
1 | ; Derived physical constants
2 | ; ==========================
3 | ;
4 | ; This file defines physical constants that are derived from the base units and
5 | ; physical constants.
6 | ;
7 | ; For the full documentation, please see
8 | ; https://kdavies4.github.com/natu/derived-ini.html.
9 | ;
10 | ; This file depends on the following items:
11 | ;
12 | ; - Mathematical constants: *pi*
13 | ; - Base physical constants: *R_inf*, *c*, *k_J*, *R_K*, *k_F*, *R*, and
14 | ; *k_Aprime*
15 | ;
16 | ; ========= ========================= ========== ============
17 | ; Symbol Expression Prefixable Name & notes
18 | ; ========= ========================= ========== ============
19 | [Derived physical constants and intermediate units]
20 | Phi_0 = 1/k_J ; `magnetic flux quantum `_
21 | G_0 = 2/R_K ; `conductance quantum `_
22 | e = Phi_0*G_0 ; `elementary charge `_ (aka Hartree unit of charge)
23 | h = 2*e*Phi_0 ; `Planck constant `_
24 | N_A = k_F/e ; `Avogadro constant `_
25 | k_B = R/N_A ; `Boltzmann constant `_
26 | cyc = k_Aprime*c/R_K , False ; cycle (aka circle, revolution, `turn `_) (a unit---not a constant---but useful below)
27 | c_1 = 2*pi*h*c**2/cyc**3 ; `first radiation constant `_
28 | c_2 = h*c/k_B ; `second radiation constant `_
29 | c_3_f = 2.821439372122079*c/c_2 ; `Wien frequency displacement constant `_ (the number is x, where exp(x)*(3 - x) = 3)
30 | c_3_lambda = c_2/4.965114231744276 ; `Wien wavelength displacement constant `_ (the number is x, where exp(x)*(5 - x) = 5)
31 | sigma = c_1/15*(pi/c_2)**4 ; `Stefan-Boltzmann constant `_ (aka Stefan's constant)
32 | Ry = h*c*R_inf ; `Rydberg energy `_
33 | Ha = 2*Ry ; `Hartree energy `_ (aka hartree)
34 | T_H = Ha/k_B ; Hartree temperature
35 | ; ========= ========================= ========== ============
36 |
--------------------------------------------------------------------------------
/natu/groups/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | r"""Modules with selected groups of units
3 |
4 | The :mod:`~natu.groups.si` module includes all of the base and derived `SI
5 | units`_. The :mod:`~natu.groups.constants` module contains all constants
6 | (physical quantities which are not units). These modules contain all of the
7 | constants and units with the indicated dimension:
8 |
9 | - :mod:`~natu.groups.acceleration`
10 | - :mod:`~natu.groups.amount`
11 | - :mod:`~natu.groups.angle`
12 | - :mod:`~natu.groups.area`
13 | - :mod:`~natu.groups.charge`
14 | - :mod:`~natu.groups.conductance`
15 | - :mod:`~natu.groups.current`
16 | - :mod:`~natu.groups.dimensionless`
17 | - :mod:`~natu.groups.energy`
18 | - :mod:`~natu.groups.force`
19 | - :mod:`~natu.groups.frequency`
20 | - :mod:`~natu.groups.length`
21 | - :mod:`~natu.groups.magnetic_flux`
22 | - :mod:`~natu.groups.magnetic_flux_density`
23 | - :mod:`~natu.groups.mass`
24 | - :mod:`~natu.groups.potential`
25 | - :mod:`~natu.groups.power`
26 | - :mod:`~natu.groups.pressure`
27 | - :mod:`~natu.groups.resistance`
28 | - :mod:`~natu.groups.temperature`
29 | - :mod:`~natu.groups.time`
30 | - :mod:`~natu.groups.velocity`
31 | - :mod:`~natu.groups.volume`
32 |
33 | These modules require that the `SI units`_ are defined in the selected INI_
34 | files. `BIPM.ini `_ contains those definitions, and it is loaded
35 | by default.
36 |
37 | Each module can only be reloaded once.\ [#f1]_
38 |
39 |
40 | .. _SI units: http://en.wikipedia.org/wiki/International_System_of_Units
41 | .. _INI: http://en.wikipedia.org/wiki/INI_file
42 |
43 | .. rubric:: Footnotes
44 |
45 | .. [#f1] This is typical in Python. From :func:`imp.reload`:
46 |
47 | "In many cases, however, extension modules are not designed to be initialized
48 | more than once, and may fail in arbitrary ways when reloaded."
49 | """
50 | __author__ = "Kevin Davies"
51 | __email__ = "kdavies4@gmail.com"
52 | __copyright__ = ("Copyright 2013-2014, Kevin Davies, Hawaii Natural Energy "
53 | "Institute, and Georgia Tech Research Corporation")
54 | __license__ = "BSD-compatible (see LICENSE.txt)"
55 |
56 | import sys
57 |
58 | from textwrap import fill
59 | from ..core import DimObject, UnitsModule, Unit
60 |
61 | DOC_LINE_LENGTH = 74
62 |
63 | def _update_module(name, units, dimension=None):
64 | """Update the module with name *name* (:class`str`) to contain the units in
65 | :class:`dict` *units*, optionally filtered to those with
66 | :class:`~natu.exponents.Exponents` *dimension*.
67 |
68 | If *dimension* is *None*, all units are included.
69 | """
70 | # Retrieve the module.
71 | module = sys.modules[name]
72 |
73 | # Get the units and note the contents.
74 | if dimension is None:
75 | module.__doc__ += "\nContents:\n"
76 | else:
77 | units = {symbol: unit for symbol, unit in units.items()
78 | if symbol != 'coherent_relations'
79 | and isinstance(unit, DimObject)
80 | and unit.dimension == dimension}
81 | module.__doc__ += "\nDefault contents:\n"
82 | module.__doc__ += fill(", ".join(sorted(units)), DOC_LINE_LENGTH)
83 |
84 | # Note the prefixable units, if any.
85 | prefixable = [symbol for symbol, unit in units.items()
86 | if isinstance(unit, Unit) and unit.prefixable]
87 | if prefixable:
88 | module.__doc__ += "\n\nPrefixable subset:\n"
89 | module.__doc__ += fill(", ".join(sorted(prefixable)), DOC_LINE_LENGTH)
90 |
91 | # Update the module.
92 | sys.modules[name] = UnitsModule(module, units)
93 |
--------------------------------------------------------------------------------
/natu/groups/acceleration.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of acceleration, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, g_0
8 |
9 | _update_module(__name__, _units, g_0.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/amount.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for amounts of substance, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, mol
8 |
9 | _update_module(__name__, _units, mol.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/angle.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of angle, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, rad
8 |
9 | _update_module(__name__, _units, rad.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/area.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of area, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, m
8 |
9 | _update_module(__name__, _units, (m ** 2).dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/charge.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of charge, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, C
8 |
9 | _update_module(__name__, _units, C.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/conductance.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of electrical conductance, with support for
3 | prefixes
4 | """
5 | # pylint: disable=I0011, E0611
6 |
7 | from . import _update_module
8 | from ..units import _units, S
9 |
10 | _update_module(__name__, _units, S.dimension)
11 |
--------------------------------------------------------------------------------
/natu/groups/constants.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for physical constants, with support for prefixes
3 | """
4 | # pylint: disable=I0011, C0103, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units
8 | from ..core import Quantity, Unit
9 |
10 | # Constants are quantities but not units.
11 | units = {symbol: quantity for symbol, quantity in _units.items()
12 | if isinstance(quantity, Quantity) and not isinstance(quantity, Unit)}
13 | try:
14 | units.update({'k_A': _units['k_A']}) # Ampere's constant is a ScalarUnit.
15 | except KeyError:
16 | pass
17 |
18 | _update_module(__name__, units)
19 |
--------------------------------------------------------------------------------
/natu/groups/current.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of electrical current, with support for
3 | prefixes
4 | """
5 | # pylint: disable=I0011, E0611
6 |
7 | from . import _update_module
8 | from ..units import _units, A
9 |
10 | _update_module(__name__, _units, A.dimension)
11 |
--------------------------------------------------------------------------------
/natu/groups/dimensionless.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for dimensionless units
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units
8 |
9 | _update_module(__name__, _units, {})
10 |
--------------------------------------------------------------------------------
/natu/groups/energy.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of energy, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, J
8 |
9 | _update_module(__name__, _units, J.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/force.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of force, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, N
8 |
9 | _update_module(__name__, _units, N.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/frequency.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of frequency, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, Hz
8 |
9 | _update_module(__name__, _units, Hz.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/length.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of length, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from natu.groups import _update_module
7 | from ..units import _units, m
8 |
9 | _update_module(__name__, _units, m.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/magnetic_flux.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of magnetic flux, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, Wb
8 |
9 | _update_module(__name__, _units, Wb.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/magnetic_flux_density.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of magnetic flux density, with support for
3 | prefixes
4 | """
5 | # pylint: disable=I0011, E0611
6 |
7 | from . import _update_module
8 | from ..units import _units, T
9 |
10 | _update_module(__name__, _units, T.dimension)
11 |
--------------------------------------------------------------------------------
/natu/groups/mass.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of mass, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, kg
8 |
9 | _update_module(__name__, _units, kg.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/potential.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of electrical potential, with support for
3 | prefixes
4 | """
5 | # pylint: disable=I0011, E0611
6 |
7 | from . import _update_module
8 | from ..units import _units, V
9 |
10 | _update_module(__name__, _units, V.dimension)
11 |
--------------------------------------------------------------------------------
/natu/groups/power.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of power, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, W
8 |
9 | _update_module(__name__, _units, W.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/pressure.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of pressure, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, Pa
8 |
9 | _update_module(__name__, _units, Pa.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/resistance.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of electrical resistance, with support for
3 | prefixes
4 | """
5 | # pylint: disable=I0011, E0611
6 |
7 | from . import _update_module
8 | from ..units import _units, ohm
9 |
10 | _update_module(__name__, _units, ohm.dimension)
11 |
--------------------------------------------------------------------------------
/natu/groups/si.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for the `SI units`_
3 |
4 |
5 | .. _SI units: http://en.wikipedia.org/wiki/International_System_of_Units
6 | """
7 | # pylint: disable=I0011, C0103, E0611
8 |
9 | from . import _update_module
10 | from ..units import _units
11 |
12 | # [BIPM2006, Table 1]: SI base units
13 | # g is included so that it can be used with other prefixes than k.
14 | units = {symbol: _units[symbol] for symbol in 'm kg g s A K mol cd'.split()}
15 |
16 | # [BIPM2006, Table 3]: Coherent derived units in SI with special names and
17 | # symbols
18 | units.update({symbol: _units[symbol] for symbol in
19 | ('rad sr Hz N Pa J W C V F ohm S Wb T H degC lm lx Bq Gy '
20 | 'Sv kat'.split())})
21 |
22 | _update_module(__name__, units)
23 |
--------------------------------------------------------------------------------
/natu/groups/temperature.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of temperature, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, K
8 |
9 | _update_module(__name__, _units, K.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/time.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of time, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, s
8 |
9 | _update_module(__name__, _units, s.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/velocity.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of velocity, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, c
8 |
9 | _update_module(__name__, _units, c.dimension)
10 |
--------------------------------------------------------------------------------
/natu/groups/volume.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Aliases for constants and units of volume, with support for prefixes
3 | """
4 | # pylint: disable=I0011, E0611
5 |
6 | from . import _update_module
7 | from ..units import _units, m
8 |
9 | _update_module(__name__, _units, (m ** 3).dimension)
10 |
--------------------------------------------------------------------------------
/natu/math.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """`Python math`_, adapted for use with physical quantities
3 |
4 | Many of the functions only accept dimensionless quantities, and they operate on
5 | the underlying values---not the values as represented in a particular display
6 | unit. To operate on values in a display unit would be to favor a particular
7 | unit, which is against the `design of the package `_.
8 |
9 | The constants (*pi*, *e*) are exactly as they are in `Python math`_.
10 |
11 | These functions accept floats, integers, and dimensionless quantities:
12 |
13 | - Number-theoretic and representation functions: :func:`factorial`,
14 | :func:`frexp`, :func:`modf`, and :func:`trunc`
15 | - Power and logarithmic functions: :func:`exp`, :func:`expm1`, :func:`log10`,
16 | :func:`log1p`, and :func:`log`
17 | - Hyperbolic functions: :func:`acosh`, :func:`asinh`, :func:`atanh`,
18 | :func:`cosh`, :func:`sinh`, and :func:`tanh`
19 | - Special functions: :func:`erf`, :func:`erfc`, :func:`gamma`, and
20 | :func:`lgamma`
21 |
22 | They are the same as those from `Python math`_, except the documentation of
23 | :func:`acosh`, :func:`asinh`, and :func:`atanh` has been corrected (see
24 | http://bugs.python.org/issue21902). The functions cast quantities cast as
25 | floats and return floats, except for :func:`factorial`, which casts quantities
26 | as integers and returns integers.
27 |
28 | All of the other functions (below) are different than those in `Python math`_.
29 |
30 | These functions accept angle as a quantity:
31 |
32 | - :func:`cos`, :func:`sin`, and :func:`tan`
33 |
34 | They return floats (as in `Python math`_).
35 |
36 | These functions accept floats, integers, and dimensionless quantities:
37 |
38 | - :func:`acos`, :func:`asin`, :func:`atan`, and :func:`atan2`
39 |
40 | They return angles as quantities.
41 |
42 | :func:`atan2` accepts accept floats, integers, and quantities of the same
43 | dimension. It returns angle as a quantity.
44 |
45 | These functions are no longer applicable and have been deleted since angle is a
46 | quantity:
47 |
48 | - :func:`degrees` and :func:`radians`
49 |
50 | These functions accept floats, integers, and dimensionless quantities:
51 |
52 | - :func:`ceil` and :func:`floor`
53 |
54 | If the input is a float or an integer, the output is a float. If the input is
55 | a :class:`~natu.core.Quantity` or a :class:`~natu.core.ScalarUnit`, the result
56 | is the same and has the same :attr:`dimension`, :attr:`display`, etc.
57 |
58 | These functions accept floats, integers, and quantities:
59 |
60 | - :func:`fabs` and :func:`copysign`
61 |
62 | If the input is a float or an integer, the output is a float. If the input is a
63 | :class:`~natu.core.Quantity` or a :class:`~natu.core.ScalarUnit`, the result is
64 | of the same type and has the same :attr:`dimension`, :attr:`display`, etc. (of
65 | the first argument in the case of :func:`copysign`).
66 |
67 | These functions also accept floats, integers, and quantities:
68 |
69 | - :func:`ldexp`, :func:`pow`, and :func:`sqrt`
70 |
71 | If the input is an float or an integer, the output is a float. If the input is
72 | a :class:`~natu.core.Quantity` or a :class:`~natu.core.ScalarUnit`, the result
73 | is the same. The dimensions and display units are handled according to the
74 | power.
75 |
76 | :func:`fmod` accepts floats, integers, and quantities of the same dimension.
77 | The output is always a float.
78 |
79 | These functions also accept floats, integers, and quantities of the same
80 | dimension:
81 |
82 | - :func:`fsum` and :func:`hypot`
83 |
84 | The display unit (and :attr:`prefixable` attribute, if applicable) of the first
85 | argument or entry is propagated to the output.
86 |
87 | These functions accept floats or quantities:
88 |
89 | - :func:`isinf`, :func:`isfinite` (only available in Python >= 3.2), and
90 | :func:`isnan`
91 |
92 | Only the value of a quantity is used; dimension and display unit are ignored.
93 |
94 |
95 | .. _Python math: https://docs.python.org/3/library/math.html
96 | """
97 | # pylint: disable=I0011, C0103, E0601, W0401, W0614, W0622
98 |
99 | from __future__ import absolute_import
100 |
101 | from math import *
102 | from fractions import Fraction
103 | from . import _decorators as decor
104 |
105 | # Number-theoretic and representation functions
106 | # ---------------------------------------------
107 | ceil = decor.dimensionless_copy_props(
108 | ceil,
109 | """Return the ceiling of x as a float or quantity.
110 |
111 | This is the smallest integral value >= x.""")
112 |
113 | floor = decor.dimensionless_copy_props(
114 | floor,
115 | """Return the floor of x as a float or quantity.
116 |
117 | This is the largest integral value <= x.""")
118 |
119 | copysign = decor.use_values_copy_props(copysign)
120 |
121 | fabs = decor.use_value_copy_props(
122 | fabs,
123 | "Return the absolute value of the float or quantity x.")
124 |
125 | fmod = decor.homogeneous(fmod)
126 |
127 | fsum = decor.homogeneous_copy_props_iter(fsum)
128 |
129 | try:
130 | isinfinite = decor.use_value(isinfinite) # This wasn't defined until v3.2.
131 | except NameError:
132 | pass
133 |
134 | isinf = decor.use_value(
135 | isinf,
136 | "Check if float or quantity x is infinite (positive or negative).")
137 |
138 | isnan = decor.use_value(
139 | isnan,
140 | "Check if float or quantity x is not a number (NaN).")
141 |
142 | ldexp = decor.use_values_copy_props_xi(
143 | ldexp,
144 | "Return x * (2**i), where x is a float or a quantity.")
145 |
146 | # factorial, frexp, modf, and trunc are ok as they are.
147 |
148 | # Power and logarithmic functions
149 | # -------------------------------
150 | pow = decor.use_value_raise(pow)
151 | sqrt = decor.use_value_raise(sqrt, Fraction(1, 2))
152 | # exp, expm1, log, log1p, and log10 are ok as they are.
153 |
154 | # Trigonometric functions
155 | # -----------------------
156 | acos = decor.inv_trig(acos, "Return the arc cosine of x as an angle.")
157 | asin = decor.inv_trig(asin, "Return the arc sine of x as an angle.")
158 | atan = decor.inv_trig(atan, "Return the arc tangent of x as an angle.")
159 | atan2 = decor.inv_trig_yx(
160 | atan2,
161 | """Return the arc tangent of y/x as an angle.
162 |
163 | Unlike atan(y/x), the signs of both x and y are considered.""")
164 | cos = decor.trig(cos, "Return the cosine of theta (an angle).")
165 | sin = decor.trig(sin, "Return the sine of theta (an angle).")
166 | tan = decor.trig(tan, "Return the tangent of theta (an angle).")
167 | hypot = decor.homogeneous_copy_props(hypot)
168 |
169 | # Angular conversion
170 | # ------------------
171 | del degrees, radians # These aren't needed since angle is a quantity.
172 |
173 | # Hyperbolic functions
174 | # --------------------
175 | acosh = decor.change_doc(acosh, "Return the inverse hyperbolic cosine of x.")
176 | asinh = decor.change_doc(asinh, "Return the inverse hyperbolic sine of x.")
177 | atanh = decor.change_doc(atanh, "Return the inverse hyperbolic tangent of x.")
178 | # cosh, sinh, and tanh are ok as they are.
179 |
180 | # Special functions
181 | # -----------------
182 | # erf, erfc, gamma, and lgamma are ok as they are.
183 |
184 | del absolute_import, Fraction, decor
185 |
--------------------------------------------------------------------------------
/natu/numpy.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """:mod:`numpy`, adapted for use with physical quantities
3 |
4 | Many of the functions only accept dimensionless quantities, and they operate on
5 | the underlying values---not the values as represented in a particular display
6 | unit. To operate on values in a display unit would be to favor a particular
7 | unit, which is against the `design of the package `_.
8 |
9 | The constants (*pi*, *e*) are exactly as they are in :mod:`numpy`.
10 |
11 | These functions accept floats, integers, and dimensionless quantities:
12 |
13 | - Hyperbolic functions: :func:`arccosh`, :func:`arcsinh`, :func:`arctanh`,
14 | :func:`cosh`, :func:`sinh`, and :func:`tanh`
15 |
16 | They functions are the same as those from :mod:`numpy`. The functions cast
17 | quantities cast as floats and return floats.
18 |
19 | These functions accept angle as a quantity:
20 |
21 | - :func:`cos`, :func:`sin`, and :func:`tan`
22 |
23 | These functions accept floats, integers, and dimensionless quantities:
24 |
25 | - :func:`acos`, :func:`asin`, :func:`atan`, and :func:`atan2`
26 |
27 | They return angles as quantities.
28 |
29 | These functions are no longer applicable and have been deleted since angle is a
30 | quantity:
31 |
32 | - :func:`degrees`, :func:`radians`, :func:`rad2deg`, and :func:`deg2rad`
33 |
34 | All other functions are directly imported from :mod:`numpy`. However, some of
35 | these need to be adapted (`Issue #7
36 | `_).
37 | """
38 |
39 | from __future__ import absolute_import
40 |
41 | import numpy as np
42 |
43 | from numpy import *
44 | from . import _decorators as decor
45 |
46 | # TODO: Update numpy.info for the modified functions.
47 |
48 | # Trigonometric functions
49 | # -----------------------
50 |
51 | cos = decor.trig(cos)
52 | sin = decor.trig(sin)
53 | tan = decor.trig(tan)
54 | arccos = decor.inv_trig(arccos)
55 | arcsin = decor.inv_trig(arcsin)
56 | arctan = decor.inv_trig(arctan)
57 | #arctan2 = decor.inv_trig_yx( # TODO fix
58 | # arctan2,
59 | # """Return the arc tangent of y/x as an angle.
60 | #
61 | # Unlike atan(y/x), the signs of both x and y are considered.""")
62 | #hypot = decor.homogeneous_copy_props(hypot) # TODO fix
63 |
64 | # These aren't needed since angle is a quantity:
65 | del degrees, radians, rad2deg, deg2rad
66 |
67 | #'unwrap'
68 |
69 | # Hyperbolic functions
70 | # --------------------
71 |
72 | arccosh = decor.dimensionless(arccosh)
73 | arcsinh = decor.dimensionless(arcsinh)
74 | arctanh = decor.dimensionless(arctanh)
75 | cosh = decor.dimensionless(cosh)
76 | sinh = decor.dimensionless(sinh)
77 | tanh = decor.dimensionless(tanh)
78 |
79 | # TODO: Support the functions below.
80 | # The ones as strings are from numpy.core.umath.
81 | # The ones as comments are from elsewhere in numpy.
82 | # Both can be imported from the base of the numpy module.
83 |
84 | # Rounding
85 | # --------
86 |
87 | # around
88 | # round_
89 | #'rint'
90 | # fix
91 | #'floor'
92 | #'ceil'
93 | #'trunc'
94 |
95 | # Sums, products, differences
96 | # ---------------------------
97 | # prod
98 | # sum
99 | # nansum
100 | # cumprod
101 | # cumsum
102 | # diff
103 | # ediff1d
104 | # gradient
105 | # cross # should introduce a factor of 1/cyc
106 | # trapz
107 |
108 | # Exponents and logarithms
109 | # ------------------------
110 |
111 | #'exp'
112 | #'expm1'
113 | #'exp2'
114 | #'log'
115 | #'log10'
116 | #'log2'
117 | #'log1p'
118 | #'logaddexp'
119 | #'logaddexp2'
120 |
121 | # Other special functions
122 | # -----------------------
123 | # IO
124 | # sinc
125 |
126 | # Floating point routines
127 | # -----------------------
128 | #'signbit'
129 | #'copysign'
130 | #'frexp'
131 | #'ldexp'
132 |
133 | # Arithmetic operations
134 | # ---------------------
135 | #'add'
136 | #'reciprocal'
137 | #'negative'
138 | #'multiply'
139 | #'divide'
140 | #'power'
141 | #'subtract'
142 | #'true_divide'
143 | #'floor_divide'
144 | #'fmod'
145 | #'mod'
146 | #'modf'
147 | #'remainder'
148 |
149 | # Handling complex numbers
150 | # ------------------------
151 | # angle
152 | # real
153 | # imag
154 | #'conj'
155 |
156 | # Miscellaneous
157 | # -------------
158 | max = decor.copy_props(np.max) # TODO: assert homogeneous
159 | min = decor.copy_props(np.min) # TODO: assert homogeneous
160 | abs = decor.copy_props(np.abs)
161 |
162 | # convolve
163 | # clip
164 | from fractions import Fraction
165 | sqrt = decor.use_value_raise(np.sqrt, Fraction(1, 2))
166 | #'square'
167 | #'absolute'
168 | #'fabs'
169 | #'sign'
170 | #'maximum'
171 | #'minimum'
172 | #'fmax'
173 | #'fmin'
174 | # nan_to_num
175 | # real_if_close
176 | # interp
177 |
178 | # Not on webpage:
179 | #'bitwise_and' # broken
180 | #'bitwise_or' # broken
181 | #'bitwise_xor' # broken
182 | #'conjugate' # broken
183 | #'equal' # works as is
184 | #'euler_gamma'
185 | #'frompyfunc'
186 | #'geterrobj'
187 | #'greater'
188 | #'greater_equal'
189 | #'invert'
190 | #'isfinite' # broken
191 | #'isinf' # broken
192 | #'isnan' # broken
193 | #'left_shift'
194 | #'less'
195 | #'less_equal'
196 | #'logical_and'
197 | #'logical_not'
198 | #'logical_or'
199 | #'logical_xor'
200 | #'nextafter'
201 | #'not_equal'
202 | #'right_shift'
203 | #'seterrobj'
204 | #'spacing'
205 |
206 | del decor, np
207 |
--------------------------------------------------------------------------------
/natu/units.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | r"""Module with all units from the `definition files`_ listed in
3 | :attr:`natu.config.definitions`
4 |
5 | This module cannot be reloaded. This prevents conflicts that could arise if the
6 | units were redefined with different `base constants `_.
7 |
8 |
9 | .. _definition files: definitions.html
10 | """
11 | __author__ = "Kevin Davies"
12 | __email__ = "kdavies4@gmail.com"
13 | __copyright__ = ("Copyright 2013-2014, Kevin Davies, Hawaii Natural Energy "
14 | "Institute, and Georgia Tech Research Corporation")
15 | __license__ = "BSD-compatible (see LICENSE.txt)"
16 |
17 | if __name__ == '__main__':
18 | # Test the contents of this file.
19 | import doctest
20 | doctest.testmod()
21 | else:
22 | # Replace the module with a UnitsModule for dynamic unit prefixing.
23 | from sys import modules
24 | from .core import UnitsModule
25 | from .config import definitions
26 | modules[__name__] = UnitsModule(modules[__name__], definitions)
27 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """Set up the natu package.
3 |
4 | See README.md for instructions.
5 | """
6 |
7 | # pylint: disable=C0103
8 |
9 | import re
10 | import versioneer
11 |
12 | from os import path
13 | from setuptools import setup
14 |
15 | here = path.abspath(path.dirname(__file__))
16 |
17 | versioneer.VCS = 'git'
18 | versioneer.versionfile_source = 'natu/_version.py'
19 | versioneer.versionfile_build = 'natu/_version.py'
20 | versioneer.tag_prefix = 'v' # Tags are like 1.2.0
21 | versioneer.parentdir_prefix = 'natu-'
22 | version = versioneer.get_version()
23 |
24 | with open(path.join(here, 'doc/long-description.txt')) as f:
25 | long_description = f.read()
26 |
27 | setup(name='natu',
28 | version=version,
29 | cmdclass=versioneer.get_cmdclass(),
30 | description="Natural units in Python",
31 | long_description=long_description,
32 | author='Kevin Davies',
33 | author_email='kdavies4@gmail.com',
34 | license='BSD-compatible (see LICENSE.txt)',
35 | keywords=('quantity calculus quantities unit conversion natural SI CGS '
36 | 'Planck Hartree'),
37 | url='http://kdavies4.github.io/natu/',
38 | download_url=('https://github.com/kdavies4/natu/archive/v%s.zip'
39 | % version if version else ''),
40 | classifiers=[
41 | 'Development Status :: 3 - Alpha',
42 | 'Intended Audience :: Science/Research',
43 | 'Intended Audience :: Education',
44 | 'Topic :: Scientific/Engineering',
45 | 'Topic :: Software Development :: Quality Assurance',
46 | 'License :: OSI Approved :: BSD License',
47 | 'Programming Language :: Python :: 2.7',
48 | 'Programming Language :: Python :: 3.2',
49 | 'Programming Language :: Python :: 3.3',
50 | 'Programming Language :: Python :: 3.4',
51 | 'Operating System :: POSIX :: Linux',
52 | 'Operating System :: Microsoft :: Windows',
53 | ],
54 | provides=['natu'],
55 | packages=['natu', 'natu.config', 'natu.groups'],
56 | package_data={'natu.config': ['*.ini']},
57 | platforms='any',
58 | zip_safe=False, # because ini files must be accessed
59 | test_suite = 'tests.test_suite',
60 | )
61 |
--------------------------------------------------------------------------------
/tests/available_imports_test.py:
--------------------------------------------------------------------------------
1 | # Standard Library imports
2 | import unittest
3 |
4 | # Enthought Library imports
5 | from traits.testing.api import doctest_for_module
6 |
7 | geo_imports = [
8 | 'GPA', 'GPa', 'Gpa', 'MPA', 'MPa', 'MPa_per_100f', 'MPa_per_100ft',
9 | 'MPa_per_f', 'MPa_per_ft', 'MPa_per_m', 'Mpa', 'N', 'ampere', 'api',
10 | 'apsi', 'atto', 'bar', 'bars', 'becquerel', 'candela', 'centi', 'copy',
11 | 'coulomb', 'cubic_centimeter', 'cubic_foot', 'cubic_meter', 'deci', 'deka',
12 | 'dimensionless', 'exa', 'farad', 'femto', 'foot', 'frac', 'fraction',
13 | 'fractional', 'g_ft_per_cc_s', 'g_km_per_cc_s', 'gapi', 'giga', 'gpa',
14 | 'grams', 'gray', 'hecto', 'henry', 'hertz', 'inch', 'joule', 'katal',
15 | 'kbar', 'kbars', 'kilo', 'kilobar', 'kilogram', 'kilometers', 'lb',
16 | 'lb_per_gal', 'lb_per_gallon', 'lbf', 'lbs', 'liter', 'lumen', 'lux', 'm',
17 | 'mS', 'mSiemen', 'mega', 'meter', 'mho', 'micro', 'microsecond', 'milli',
18 | 'millivolts', 'mmho', 'mole', 'mpa', 'mv', 'nano', 'newton', 'none', 'ohm',
19 | 'ohm_m', 'ohm_meter', 'ohmm', 'ohms', 'ohms_per_m', 'ohms_per_meter',
20 | 'parts_per_million', 'parts_per_one', 'pascal', 'pct', 'percent',
21 | 'percentage', 'peta', 'pico', 'pounds_per_square_inch', 'ppg', 'ppm',
22 | 'psi', 'psi_per_f', 'psi_per_ft', 'psig', 'radian', 'ratio', 'second',
23 | 'siemen', 'siemens', 'siemens_per_m', 'siemens_per_meter', 'sievert',
24 | 'steradian', 'tera', 'tesla', 'unit', 'us_fluid_gallon', 'us_per_ft', 'v',
25 | 'volt', 'volts', 'watt', 'weber', 'yocto', 'yotta', 'zepto', 'zetta'
26 | ]
27 |
28 | def write_geo_err_msg(name):
29 | """write the message describing the import not found in geo_units"""
30 | msg = """Could not find previously available import '{0}' in
31 | scimath.units.geo_units module. Check to ensure that '{0}' is
32 | available as an import from scimath.units.geounits."""
33 | return msg.format(name)
34 |
35 | class GeoUnitsImportsTestCase(unittest.TestCase):
36 | """ When geo_units was initially set up, many units were defined there
37 | which should have been defined elsewhere and imported to geo_units, causing
38 | some problems later when things like "psi" could not be imported from
39 | scimath.units.pressure but were instead found in
40 | scimath.units.geo_units. In Dec 2011, the units were reorganized to make
41 | units available in their expected location. This test was set up to ensure
42 | that not code that imported a unit from geo_units would break in the
43 | reorganization.
44 |
45 | """
46 | def test_geo_imports(self):
47 | """ Test whether everything that was availabile in geo_units still is available.
48 | """
49 | from scimath.units import geo_units
50 |
51 | available_now = geo_units.__dict__
52 |
53 | for name in geo_imports:
54 | self.assertIn(name, available_now, msg=write_geo_err_msg(name))
55 |
56 | if __name__ == '__main__':
57 | unittest.main()
58 |
--------------------------------------------------------------------------------
/tests/function_signature_test_case.py:
--------------------------------------------------------------------------------
1 | # Standard Library imports
2 | import unittest
3 |
4 | # Enthought Library imports
5 | from traits.testing.api import doctest_for_module
6 |
7 | # Numerical modeling library imports
8 | from scimath.units import function_signature
9 | from scimath.units.function_signature import (
10 | function_arguments, def_signature, call_signature,
11 | )
12 |
13 | class FunctionArgumentsDocTestCase(doctest_for_module(function_signature)):
14 | pass
15 |
16 | class FunctionArgumentsTestCase(unittest.TestCase):
17 |
18 | ############################################################################
19 | # TestCase interface.
20 | ############################################################################
21 |
22 | def setUp(self):
23 | unittest.TestCase.setUp(self)
24 |
25 | def tearDown(self):
26 | unittest.TestCase.tearDown(self)
27 |
28 |
29 | ############################################################################
30 | # FunctionArgumentsTestCase interface.
31 | ############################################################################
32 |
33 | def test_single(self):
34 | """ Does a function with a single positional argument work?
35 | """
36 | def func(value):
37 | pass
38 | args, kw, arg_ordered = function_arguments(func)
39 | self.assertEqual(args,('value',))
40 | self.assertEqual(kw,{})
41 | self.assertEqual(arg_ordered,('value',))
42 |
43 | def test_multiple(self):
44 | """ Does a function with multiple positional argument work?
45 | """
46 | def func(a,b,c):
47 | pass
48 | args, kw, arg_ordered = function_arguments(func)
49 | self.assertEqual(args,('a','b','c'))
50 | self.assertEqual(kw,{})
51 | self.assertEqual(arg_ordered,('a','b','c'))
52 |
53 | def test_single_kw(self):
54 | """ Does a function with a single keyword argument work?
55 | """
56 | def func(a=1):
57 | pass
58 | args, kw, arg_ordered = function_arguments(func)
59 | self.assertEqual(args,())
60 | self.assertEqual(kw,{'a':1})
61 | self.assertEqual(arg_ordered,('a',))
62 |
63 | def test_multiple_kw(self):
64 | """ Does a function with multiple keyword arguments work?
65 | """
66 | def func(a=1,b=2):
67 | pass
68 | args, kw, arg_ordered = function_arguments(func)
69 | self.assertEqual(args,())
70 | self.assertEqual(kw,{'a':1,'b':2})
71 | self.assertEqual(arg_ordered,('a','b'))
72 |
73 | def test_single_arg_and_kw(self):
74 | """ Does a function with one positional and one keyword arg work?
75 | """
76 | def func(a, b=1):
77 | pass
78 | args, kw, arg_ordered = function_arguments(func)
79 | self.assertEqual(args,('a',))
80 | self.assertEqual(kw,{'b':1})
81 | self.assertEqual(arg_ordered,('a','b'))
82 |
83 | def test_multiple_arg_and_kw(self):
84 | """ Does a function with two positional and two keyword arg work?
85 | """
86 | def func(a, b, c=1,d=2):
87 | pass
88 | args, kw, arg_ordered = function_arguments(func)
89 | self.assertEqual(args,('a','b'))
90 | self.assertEqual(kw,{'c':1,'d':2})
91 | self.assertEqual(arg_ordered,('a','b','c','d'))
92 |
93 |
94 | class DefSignatureTestCase(unittest.TestCase):
95 |
96 | ############################################################################
97 | # TestCase interface.
98 | ############################################################################
99 |
100 | def setUp(self):
101 | unittest.TestCase.setUp(self)
102 |
103 | def tearDown(self):
104 | unittest.TestCase.tearDown(self)
105 |
106 |
107 | ############################################################################
108 | # FunctionArgumentsTestCase interface.
109 | ############################################################################
110 |
111 | def test_kw(self):
112 | """ Does a function with a keyword and positional argument work?
113 | """
114 | def func(a,b=1):
115 | pass
116 | res = def_signature(func)
117 | self.assertEqual(res, 'def func(a, b=1):')
118 |
119 | def test_kw_with_list_argument(self):
120 | """ Does a function with a keyword argument as a list work?
121 | """
122 | def func(a,b=[]):
123 | pass
124 | res = def_signature(func)
125 | self.assertEqual(res, 'def func(a, b=[]):')
126 |
127 | class CallSignatureTestCase(unittest.TestCase):
128 |
129 | ############################################################################
130 | # TestCase interface.
131 | ############################################################################
132 |
133 | def setUp(self):
134 | unittest.TestCase.setUp(self)
135 |
136 | def tearDown(self):
137 | unittest.TestCase.tearDown(self)
138 |
139 |
140 | ############################################################################
141 | # FunctionArgumentsTestCase interface.
142 | ############################################################################
143 |
144 | def test_kw(self):
145 | """ Does a function with a keyword and positional argument work?
146 | """
147 | def func(a,b=1):
148 | pass
149 | res = call_signature(func)
150 | self.assertEqual(res, 'func(a, b)')
151 |
152 | def test_kw_with_list_argument(self):
153 | """ Does a function with a keyword argument as a list work?
154 | """
155 | def func(a,b=[]):
156 | pass
157 | res = call_signature(func)
158 | self.assertEqual(res, 'func(a, b)')
159 |
160 |
161 | # Some functions to test on.
162 | def just_args(x, y):
163 | pass
164 |
165 | def just_kwds(y=1, x=2):
166 | pass
167 |
168 | def args_and_kwds(x, z=1, y=2):
169 | pass
170 |
171 |
172 | class FunctionSignatureTestCase(unittest.TestCase):
173 |
174 | def test_just_args(self):
175 | self.assertEquals(def_signature(just_args), "def just_args(x, y):")
176 |
177 | def test_just_kwds(self):
178 | self.assertEquals(def_signature(just_kwds), "def just_kwds(y=1, x=2):")
179 |
180 | def test_args_and_kwds(self):
181 | self.assertEquals(def_signature(args_and_kwds), "def args_and_kwds(x, z=1, y=2):")
182 |
183 | if __name__ == '__main__':
184 | unittest.main()
185 |
--------------------------------------------------------------------------------
/tests/meta_quantity_test_case.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | #
3 | # Copyright (c) 2006 by Enthought, Inc.
4 | # All rights reserved.
5 | #
6 | # Author: Greg Rogers
7 | #
8 | #-----------------------------------------------------------------------------
9 |
10 | from unittest import TestCase
11 |
12 | from traits.api import TraitError
13 |
14 | from scimath.units.api import MetaQuantity
15 |
16 |
17 | class TraitsTestCase(TestCase):
18 |
19 | def test_metaquantity(self):
20 | mq = MetaQuantity( name='vp', units='km/s', family_name='pvelocity')
21 |
22 | self.failUnlessEqual( mq.name, 'vp' )
23 | self.failUnlessEqual( mq.units.label, 'km/s' )
24 | self.failUnlessEqual( mq.family_name, 'pvelocity' )
25 | return
26 |
27 | def test_metaquantity_compatible_family_change(self):
28 | mq = MetaQuantity( name='vp', units='km/s', family_name='pvelocity')
29 |
30 | mq.name = 'vs'
31 | mq.family_name = 'svelocity'
32 | self.failUnlessEqual( mq.name, 'vs' )
33 | self.failUnlessEqual( mq.units.label, 'km/s' )
34 | self.failUnlessEqual( mq.family_name, 'svelocity' )
35 | return
36 |
37 | def test_metaquantity_compatible_units_change(self):
38 | mq = MetaQuantity( name='vp', units='km/s', family_name='pvelocity')
39 |
40 | mq.units = 'ft/s'
41 | self.failUnlessEqual( mq.name, 'vp' )
42 | self.failUnlessEqual( mq.units.label, 'ft/s' )
43 | self.failUnlessEqual( mq.family_name, 'pvelocity' )
44 | return
45 |
46 | def test_metaquantity_incompatible_units_change(self):
47 | mq = MetaQuantity( name='vp', units='km/s', family_name='pvelocity')
48 |
49 | self.failUnlessRaises(TraitError, setattr, mq, 'units', 'hours')
50 |
51 | self.failUnlessEqual( mq.name, 'vp' )
52 | self.failUnlessEqual( mq.units.label, 'km/s' )
53 | self.failUnlessEqual( mq.family_name, 'pvelocity' )
54 | return
55 |
56 | def test_metaquantity_incompatible_family_change(self):
57 | mq = MetaQuantity( name='vp', units='km/s', family_name='pvelocity')
58 |
59 | mq.family_name = 'time'
60 |
61 | self.failUnlessEqual( mq.name, 'vp' )
62 | self.failUnlessEqual( mq.units.label, 'msec' )
63 | self.failUnlessEqual( mq.family_name, 'time' )
64 | return
65 |
66 | def ui_simple(self):
67 | mq = MetaQuantity()
68 | mq.configure_traits(kind='modal')
69 | print '\n'
70 | mq.print_traits()
71 | return
72 |
73 | ### EOF
74 |
--------------------------------------------------------------------------------
/tests/test_dimensions.py:
--------------------------------------------------------------------------------
1 |
2 | from unittest import TestCase
3 |
4 | from scimath.physical_quantities.dimensions import Dimensions, Dim
5 |
6 | class DimensionsTest(TestCase):
7 | def setUp(self):
8 | self.dimensionless = Dimensions({})
9 | self.length = Dimensions({"length": 1.0})
10 | self.mass = Dimensions({"mass": 1.0, 'time': 0.0})
11 | self.time = Dimensions({"time": 1.0})
12 | self.acceleration = Dimensions({"length": 1.0, "time": -2.0})
13 | self.force = Dimensions({"mass": 1.0, "length": 1.0, "time": -2.0})
14 | self.also_force = Dimensions({"mass": 1.0, "length": 1.0,
15 | "time": -2.0})
16 |
17 | # Tests for basic initialization
18 | def test_setup_simple(self):
19 | assert self.length.dimension_dict == {"length": 1.0}
20 |
21 | def test_setup_remove_dimensions(self):
22 | assert self.mass.dimension_dict == {"mass": 1.0}
23 |
24 | # Tests for expansion property
25 | def test_expansion_dimensionless(self):
26 | assert self.dimensionless.expansion == "dimensionless"
27 |
28 | def test_expansion_simple(self):
29 | assert self.length.expansion == "length"
30 |
31 | def test_expansion_complex(self):
32 | assert self.force.expansion == "length*mass*time**-2"
33 |
34 | def test_expansion_expression(self):
35 | velocity = self.length/self.time
36 | assert velocity.expansion == "length*time**-1"
37 |
38 | def test_expansion_complete_cancellation(self):
39 | dimensionless = self.force/self.force
40 | assert dimensionless.expansion == "dimensionless"
41 |
42 | # Tests for __str__ method
43 | def test_str_dimensionless(self):
44 | assert str(self.dimensionless) == "dimensionless"
45 |
46 | def test_str_simple(self):
47 | assert str(self.length) == "length"
48 |
49 | def test_str_complex(self):
50 | assert str(self.force) == "length*mass*time**-2"
51 |
52 | def test_str_expression(self):
53 | velocity = self.length/self.time
54 | assert str(velocity) == "length*time**-1"
55 |
56 | # Tests for equality and inequality
57 | def test_equality(self):
58 | assert self.force == self.also_force
59 |
60 | def test_inequality(self):
61 | assert self.force != self.acceleration
62 |
63 | # Tests for hashing
64 | def test_hash(self):
65 | assert hash(self.force) == hash(self.also_force)
66 |
67 | def test_not_hash(self):
68 | # there is a very small chance that this will fail when it should not
69 | # because of a hash collision
70 | assert hash(self.force) != hash(self.acceleration)
71 |
72 | # Tests for arithmetic operations
73 | def test_mul(self):
74 | force = self.acceleration*self.mass
75 | assert force.dimension_dict == {"length": 1.0, "time": -2.0, "mass": 1.0}
76 |
77 | def test_div(self):
78 | velocity = self.length/self.time
79 | assert velocity.dimension_dict == {"length": 1.0, "time": -1.0}
80 |
81 | def test_pow(self):
82 | area = self.length**2
83 | assert area.dimension_dict == {"length": 2.0}
84 |
85 | def test_cancellation(self):
86 | acceleration = self.force*self.time/self.mass
87 | assert acceleration.dimension_dict == {"length": 1.0, "time": -1.0}
88 |
89 | def test_complete_cancellation(self):
90 | dimensionless = self.force/self.force
91 | assert dimensionless.dimension_dict == {}
92 |
--------------------------------------------------------------------------------
/tests/test_quantity_type.py:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | #
3 | # Copyright (c) 2008 by Enthought, Inc.
4 | # All rights reserved.
5 | #
6 | # Author: Corran Webster
7 | #
8 | #-----------------------------------------------------------------------------
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/test_utils.py:
--------------------------------------------------------------------------------
1 |
2 | from unittest import TestCase
3 |
4 | from scimath.physical_quantities.util import dict_add, dict_sub, dict_mul, \
5 | dict_div, format_expansion, unicode_powers, tex_powers, name_powers
6 |
7 |
8 | class DictArithmeticTest(TestCase):
9 | def test_add(self):
10 | a = {'a': 3.0, 'b': -4.0, 'd': 2.0}
11 | b = {'a': 1.5, 'c': 12.0, 'd': -2.0}
12 | assert dict_add(a, b) == {'a': 4.5, 'b': -4.0, 'c': 12.0}
13 |
14 | def test_sub(self):
15 | a = {'a': 3.0, 'b': -4.0, 'd': 2.0}
16 | b = {'a': 1.5, 'c': 12.0, 'd': 2.0}
17 | assert dict_sub(a, b) == {'a': 1.5, 'b': -4.0, 'c': -12.0}
18 |
19 | def test_mul(self):
20 | a = {'a': 2.0, 'b': -4.0}
21 | n = 1.5
22 | assert dict_mul(a, n) == {'a': 3.0, 'b': -6.0}
23 |
24 | def test_zero_mul(self):
25 | a = {'a': 2.0, 'b': -4.0}
26 | n = 0.0
27 | assert dict_mul(a, n) == {}
28 |
29 | def test_div(self):
30 | a = {'a': 2.0, 'b': -4.0}
31 | n = 0.5
32 | assert dict_div(a, n) == {'a': 4.0, 'b': -8.0}
33 |
34 |
35 | class FormatTest(TestCase):
36 | def setUp(self):
37 | self.coulomb = {"A": 1.0, 's': 1.0}
38 | self.joule = {"kg": 1.0, "m": 2.0, "s": -2.0}
39 | self.volt = {"kg": 1.0, "m": 2.0, "s": -3.0, "A": -1.0}
40 | self.hertz = {"s": -1.0}
41 | self.ohm = {u"\u2126": 1.0}
42 | self.siemens = {u"\u2126": -1.0}
43 |
44 | def test_python_defaults(self):
45 | assert format_expansion(self.volt) == "A**-1*kg*m**2*s**-3"
46 |
47 | def test_python_division(self):
48 | assert format_expansion(self.volt, div=True) == "kg*m**2/(A*s**3)"
49 |
50 | def test_python_division_simple_denominator(self):
51 | assert format_expansion(self.joule, div=True) == "kg*m**2/s**2"
52 |
53 | def test_python_division_no_denominator(self):
54 | assert format_expansion(self.coulomb, div=True) == "A*s"
55 |
56 | def test_python_division_no_numerator_simple_denominator(self):
57 | assert format_expansion(self.hertz, div=True) == "1/s"
58 |
59 | def test_python_division_no_numerator_no_denominator(self):
60 | assert format_expansion({}, div=True) == "1"
61 |
62 | def test_python_rational_power(self):
63 | assert format_expansion({'m': 0.5}) == "m**0.5"
64 |
65 | def test_unicode(self):
66 | assert format_expansion(self.volt, mul=" ",
67 | pow_func=unicode_powers) == u"A\u207B\u00B9 kg m\u00B2 s\u207B\u00B3"
68 |
69 | def test_unicode_symbol(self):
70 | assert format_expansion(self.volt, mul=" ",
71 | pow_func=unicode_powers) == u"A\u207B\u00B9 kg m\u00B2 s\u207B\u00B3"
72 |
73 | def test_unicode_division(self):
74 | assert format_expansion(self.volt, mul=" ", div=True,
75 | pow_func=unicode_powers) == u"kg m\u00B2/(A s\u00B3)"
76 |
77 | def test_unicode_division_simple_denominator(self):
78 | assert format_expansion(self.joule, mul=" ", div=True,
79 | pow_func=unicode_powers) == u"kg m\u00B2/s\u00B2"
80 |
81 | def test_unicode_division_no_denominator(self):
82 | assert format_expansion(self.coulomb, mul=" ", div=True,
83 | pow_func=unicode_powers) == u"A s"
84 |
85 | def test_unicode_symbol(self):
86 | assert format_expansion(self.siemens, mul=" ",
87 | pow_func=unicode_powers) == u"\u2126\u207B\u00B9"
88 |
89 | def test_unicode_symbol_division(self):
90 | assert format_expansion(self.siemens, mul=" ", div=True,
91 | pow_func=unicode_powers) == u"1/\u2126"
92 |
93 | def test_unicode_rational_power(self):
94 | assert format_expansion({'m': 0.5}, mul=" ",
95 | pow_func=unicode_powers) == u"m^0.5"
96 |
97 | def test_TeX_defaults(self):
98 | assert format_expansion(self.volt, mul="\/",
99 | pow_func=tex_powers) == "A^{-1}\/kg\/m^{2}\/s^{-3}"
100 |
101 | def test_TeX_division(self):
102 | assert format_expansion(self.volt, mul="\/", div=True,
103 | pow_func=tex_powers) == "kg\/m^{2}/(A\/s^{3})"
104 |
105 | def test_TeX_division_simple_denominator(self):
106 | assert format_expansion(self.joule, mul="\/", div=True,
107 | pow_func=tex_powers) == "kg\/m^{2}/s^{2}"
108 |
109 | def test_TeX_division_no_denominator(self):
110 | assert format_expansion(self.coulomb, mul="\/", div=True,
111 | pow_func=tex_powers) == "A\/s"
112 |
113 | def test_TeX_division_no_numerator_simple_denominator(self):
114 | assert format_expansion(self.hertz, mul="\/", div=True,
115 | pow_func=tex_powers) == "1/s"
116 |
117 | def test_unicode_rational_power(self):
118 | assert format_expansion({'m': 0.5}, mul="\/",
119 | pow_func=tex_powers) == "m^{0.5}"
120 |
121 | def test_name_defaults(self):
122 | assert format_expansion(self.volt, mul=" ", empty_numerator="1",
123 | div_symbol=" per ", group_symbols=("", ""),
124 | pow_func=name_powers) == "A to the -1 kg square m s to the -3"
125 |
126 | def test_name_division(self):
127 | assert format_expansion(self.volt, mul=" ", empty_numerator="1",
128 | div_symbol=" per ", group_symbols=("", ""),
129 | div=True,
130 | pow_func=name_powers) == "kg square m per A cubic s"
131 |
132 | def test_name_division_no_numerator_simple_denominator(self):
133 | assert format_expansion(self.hertz, mul=" ", empty_numerator="",
134 | div_symbol=" per ", group_symbols=("", ""),
135 | div=True,
136 | pow_func=name_powers) == " per s"
137 |
--------------------------------------------------------------------------------
/tests/unit_scalar_test_case.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from traits.testing.api import doctest_for_module
3 |
4 | import scimath.units.unit_scalar as unit_scalar
5 | from scimath.units.unit_scalar import UnitScalar
6 | from scimath.units.length import m
7 | from scimath.units.unit import unit
8 |
9 |
10 | from nose.tools import assert_equal, assert_is_instance
11 |
12 | class UnitScalarDocTestCase(doctest_for_module(unit_scalar)):
13 | pass
14 |
15 |
16 | def test_offset_unit_computations():
17 | """ Executing some basic computations with a basic custom unit with offset.
18 | """
19 | my_u = unit(12, m.derivation, 14)
20 | s1 = UnitScalar(3, units=my_u)
21 | s2 = UnitScalar(5, units=my_u)
22 | s3 = s1+s2
23 | assert_equal(s3,UnitScalar(8, units=my_u))
24 |
25 |
26 |
27 | if __name__ == '__main__':
28 | import sys
29 | unittest.main(argv=sys.argv)
30 |
--------------------------------------------------------------------------------
/tests/units_dimensionless_test.py:
--------------------------------------------------------------------------------
1 | from numpy.testing import assert_equal
2 | from scimath.units.unit_scalar import UnitScalar
3 | from scimath.units.unit import dimensionless
4 |
5 | def dimensionless_test():
6 | """
7 | Test the modification to the division, multiplication and pow
8 | such that a dimensionless quantity formed by is indeed dimensionless
9 | """
10 |
11 |
12 | a = UnitScalar(1.0, units = 'm')
13 | b = UnitScalar(2.0, units = 'mm')
14 | d = UnitScalar(2.0, units = 'm**(-1)')
15 |
16 | c = a/b
17 | e = b*d
18 |
19 | f= UnitScalar(2.0, units = dimensionless)
20 | g = f**2
21 |
22 | assert_equal(c.units,dimensionless)
23 | assert_equal(e.units,dimensionless)
24 | assert_equal(g.units,dimensionless)
25 |
26 |
--------------------------------------------------------------------------------