├── .gitattributes ├── .gitignore ├── .travis.yml ├── CHANGES.txt ├── CREDITS.txt ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── TODO.sh ├── doc ├── .natu.pws ├── BIPM-ini.rst ├── README.md ├── _static │ ├── analytics.js │ ├── copybutton.js │ ├── custom.css │ ├── favicon-160x160.png │ ├── favicon-16x16.png │ ├── favicon-196x196.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── favicon.svg │ ├── hspace.png │ └── logo.svg ├── _templates │ ├── api.html │ ├── definitions.html │ ├── download.html │ ├── globaltoc.html │ ├── info.html │ ├── layout.html │ ├── links.html │ ├── search.html │ ├── searchbox.html │ └── user.html ├── api.rst ├── base-ini.rst ├── changes.rst ├── conf.py ├── credits.rst ├── definitions.rst ├── derived-ini.rst ├── extra │ └── googledadb6c37b51fb2dc.html ├── index.rst ├── install.rst ├── license.rst ├── long-description.txt ├── make.py ├── natu.config.rst ├── natu.core.rst ├── natu.exponents.rst ├── natu.groups.acceleration.rst ├── natu.groups.amount.rst ├── natu.groups.angle.rst ├── natu.groups.area.rst ├── natu.groups.charge.rst ├── natu.groups.conductance.rst ├── natu.groups.constants.rst ├── natu.groups.current.rst ├── natu.groups.dimensionless.rst ├── natu.groups.energy.rst ├── natu.groups.force.rst ├── natu.groups.frequency.rst ├── natu.groups.length.rst ├── natu.groups.magnetic_flux.rst ├── natu.groups.magnetic_flux_density.rst ├── natu.groups.mass.rst ├── natu.groups.potential.rst ├── natu.groups.power.rst ├── natu.groups.pressure.rst ├── natu.groups.resistance.rst ├── natu.groups.rst ├── natu.groups.si.rst ├── natu.groups.temperature.rst ├── natu.groups.time.rst ├── natu.groups.velocity.rst ├── natu.groups.volume.rst ├── natu.math.rst ├── natu.numpy.rst ├── natu.pws ├── natu.units.rst ├── natu.util.rst ├── other-ini.rst ├── seealso.rst └── usermodules.rst ├── examples ├── custom.ini └── tutorial.ipynb ├── hooks ├── README.md ├── cloc.pl ├── cloc.sh ├── code.py ├── code.sh ├── diff-ini.sh ├── doc.sh ├── post-checkout ├── pre-commit └── pylint.sh ├── natu ├── __init__.py ├── _decorators.py ├── _prefixes.py ├── _version.py ├── config │ ├── BIPM.ini │ ├── __init__.py │ ├── base-EMU.ini │ ├── base-ESU.ini │ ├── base-Hartree.ini │ ├── base-Planck.ini │ ├── base-SI.ini │ ├── derived.ini │ └── other.ini ├── core.py ├── exponents.py ├── groups │ ├── __init__.py │ ├── acceleration.py │ ├── amount.py │ ├── angle.py │ ├── area.py │ ├── charge.py │ ├── conductance.py │ ├── constants.py │ ├── current.py │ ├── dimensionless.py │ ├── energy.py │ ├── force.py │ ├── frequency.py │ ├── length.py │ ├── magnetic_flux.py │ ├── magnetic_flux_density.py │ ├── mass.py │ ├── potential.py │ ├── power.py │ ├── pressure.py │ ├── resistance.py │ ├── si.py │ ├── temperature.py │ ├── time.py │ ├── velocity.py │ └── volume.py ├── math.py ├── numpy.py ├── units.py └── util.py ├── setup.py ├── tests ├── __init__.py ├── available_imports_test.py ├── function_signature_test_case.py ├── has_units_test_case.py ├── meta_quantity_test_case.py ├── test_dimensions.py ├── test_quantity_type.py ├── test_units.py ├── test_utils.py ├── unit_array_test_case.py ├── unit_manipulation_test_case.py ├── unit_scalar_test_case.py ├── units_dimensionless_test.py └── units_test_case.py └── versioneer.py /.gitattributes: -------------------------------------------------------------------------------- 1 | natu/_version.py export-subst 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.pyc 3 | build/ 4 | 5 | # Generated files 6 | dist/ 7 | MANIFEST 8 | doc/examples 9 | *.egg-info 10 | .fuse_hidden* 11 | 12 | # Backup files 13 | .ipynb_checkpoints -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - '2.7' 5 | - '3.4' 6 | 7 | # Use conda since Travis CI doesn't ahve good support for scipy in Python 3. 8 | before_install: 9 | - sudo apt-get update 10 | - if [[ $TRAVIS_PYTHON_VERSION == 2* ]]; then 11 | wget http://repo.continuum.io/miniconda/Miniconda-3.5.5-Linux-x86_64.sh -O miniconda.sh; 12 | sudo apt-get install python-qt4; 13 | else 14 | wget http://repo.continuum.io/miniconda/Miniconda3-3.5.5-Linux-x86_64.sh -O miniconda.sh; 15 | sudo apt-get install python-qt4; 16 | fi 17 | - bash miniconda.sh -b -p $HOME/miniconda 18 | - export PATH="$HOME/miniconda/bin:$PATH" 19 | - hash -r 20 | - conda config --set always_yes yes --set changeps1 no 21 | - conda update conda 22 | - conda info -a # Useful for debugging issues with conda 23 | - conda create -n test-environment setuptools numpy 24 | # 7/2/14: python=3.4 doesn't work, but conda currently defaults to 3.4.1 25 | # anyway if version 3 is installed (see conda info above) and 2.7.7 otherwise. 26 | - source activate test-environment 27 | 28 | install: 29 | - python setup.py install 30 | 31 | script: 32 | - python setup.py test 33 | 34 | after_success: 35 | - coveralls 36 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | Change log 2 | ========== 3 | 4 | The releases are numbered according to the `Semantic Versioning Specification`_. 5 | 6 | v0.1.0-a1_ (2014-8-8) -- Updates: 7 | 8 | - Fixed tests (still need to add more tests) 9 | 10 | v0.1.0-a_ (2014-8-7) -- Initial pre-release 11 | 12 | 13 | .. _v0.1.0-a1: https://github.com/kdavies4/natu/archive/v0.1.0-a1.zip 14 | .. _v0.1.0-a: https://github.com/kdavies4/natu/archive/v0.1.0-a.zip 15 | 16 | .. _Semantic Versioning Specification: http://semver.org 17 | -------------------------------------------------------------------------------- /CREDITS.txt: -------------------------------------------------------------------------------- 1 | Credits 2 | ======= 3 | 4 | natu_ was written by `Kevin Davies`_. Some aspects of the project were inspired 5 | by or copied from these packages: 6 | 7 | - `Pint `_ (`BSD license 8 | `_): 9 | 10 | - Copied and modified some of the functions for string formatting 11 | - Used the idea of unit definition files 12 | - Copied some of the unit definitions 13 | 14 | - `SciMath `_ (`BSD 15 | license 16 | `_): 17 | 18 | - Adapted the approach for tracking dimensions 19 | - Copied some of the unit definitions 20 | 21 | The logo was copied and modified from `an image of the electron shell transitions 22 | of hydrogen `_ by 23 | `Szdori `_ (Mar. 19 24 | 2009). 25 | 26 | :func:`natu.util.list_packages` is based on `unutbu 27 | `_'s `post on Stack Overflow 28 | `_ (Nov. 10 2009). 29 | 30 | If you use natu_ or concepts from it in shared work, please cite the following: 31 | 32 | K. Davies and C. Paredis, "`Natural Unit Representation in 33 | Modelica `_," 34 | in Modelica Conference (Munich, Germany), Modelica Assoc., 35 | Sep. 2012. 36 | 37 | 38 | .. _natu: index.html 39 | .. _Kevin Davies: http://www.hnei.hawaii.edu/staff/kevin-davies 40 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014, Kevin Davies, Hawaii Natural Energy Institute (HNEI), 2 | and Georgia Tech Research Corporation (GTRC). 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | * Neither the name of Georgia Tech Research Corporation nor the names of 14 | its contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | * This software is controlled under the jurisdiction of the United States 17 | Department of Commerce and subject to Export Administration Regulations. 18 | By downloading or using the Software, you are agreeing to comply with 19 | U. S. export controls. Diversion contrary to law is prohibited. The 20 | software cannot be exported or reexported to sanctioned countries that 21 | are controlled for Anti-Terrorism (15 CFR Part 738 Supplement 1) or to 22 | denied parties, http://beta-www.bis.doc.gov/index.php/policy-guidance/lists-of-parties-of-concern. 23 | EAR99 items cannot be exported or reexported to Iraq for a military 24 | purpose or to a military end-user (15 CFR Part 746.3). Export and 25 | reexport include any release of technology to a foreign national within 26 | the United States. Technology is released for export when it is 27 | available to foreign nationals for visual inspection, when technology is 28 | exchanged orally or when technology is made available by practice or 29 | application under the guidance of persons with knowledge of the 30 | technology. 31 | 32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 | DISCLAIMED. IN NO EVENT SHALL GEORGIA TECH RESEARCH CORPORATION BE LIABLE FOR 36 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 39 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include *.md 3 | include *.txt 4 | include *.sh 5 | include natu/config/*.ini 6 | 7 | # Files to build the documentation 8 | include doc/*.md 9 | include doc/*.pws 10 | include doc/*.py 11 | include doc/*.rst 12 | include doc/*.txt 13 | include doc/_static/* 14 | include doc/_templates/* 15 | include doc/extra/* 16 | 17 | # Test scripts and data files 18 | include tests/* 19 | 20 | # For version labeling 21 | include versioneer.py 22 | include natu/_version.py 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | natu 2 | ==== 3 | 4 | **Natural units in Python** 5 | 6 | **Warning:** This project is currently in a pre-release state. It will be 7 | officially released once the unit tests are complete. 8 | 9 | [natu] is a free, open-source package to represent physical quantities. There are 10 | [many Python packages that deal with units and quantities](http://kdavies4.github.io/natu/seealso.html), 11 | but [natu] is uniquely system-independent. The units are derived from physical 12 | constants with adjustable values and dimensions. The value of a unit is 13 | factored into a quantity so that the quantity is not "in" any particular unit. 14 | This has the following advantages: 15 | 16 | - **Flexible**: Different unit systems, including [natural units] (hence the 17 | name "natu"), can be represented by simply adjusting the 18 | [base physical constants]. 19 | - **Simple**: Unit conversion is inherent. This results in quick computations 20 | and a small code base (about 1500 lines). By default, dimensions and display 21 | units are tracked to catch errors and for string formatting. This can be 22 | disabled to nearly eliminate the computational overhead while still providing 23 | the core features. 24 | - **Intuitive**: Each unit is a fixed quantity that is treated as a mathematical 25 | entity. A variable quantity is expressed as the product of a number and a 26 | unit, as stated by [BIPM]. 27 | - **Representative**: The design reflects the way modern units are defined. 28 | Standards organizations such as [NIST] assign values to universal physical 29 | constants so that the values of units can be determined by physical 30 | experiments instead of prototypes. 31 | - **Scalable**: The values of the base physical constants can scaled to prevent 32 | exponent overflow, regardless of the units used. 33 | 34 | 35 | For example, you can do this: 36 | 37 | >>> from natu.units import degC, K 38 | >>> 0*degC + 100*K 39 | 100.0 degC 40 | 41 | Please 42 | [see the tutorial](http://nbviewer.ipython.org/github/kdavies4/natu/blob/master/examples/tutorial.ipynb) 43 | for more examples and [visit the main website][natu] for the full documentation. 44 | 45 | #### Installation 46 | 47 | The easiest way is to install [natu] is to use [pip]: 48 | 49 | > pip install natu 50 | 51 | On Linux, it may be necessary to have root privileges: 52 | 53 | $ sudo pip install natu 54 | 55 | #### License terms and development 56 | 57 | [natu] is published under a [BSD-compatible license](LICENSE.txt). Please 58 | share any improvements you make, preferably as a pull request to the ``master`` 59 | branch of the [GitHub repository]. There are useful development scripts in the 60 | [hooks folder](hooks). If you find a bug, have a suggestion, or just want to 61 | leave a comment, please 62 | [open an issue](https://github.com/kdavies4/natu/issues/new). 63 | 64 | [![Build Status](https://travis-ci.org/kdavies4/natu.svg?branch=travis)](https://travis-ci.org/kdavies4/natu) 65 | ![ ](doc/_static/hspace.png) 66 | [![Code Health](https://landscape.io/github/kdavies4/natu/master/landscape.png)](https://landscape.io/github/kdavies4/natu) 67 | 68 | 69 | [natu]: http://kdavies4.github.io/natu 70 | [base physical constants]: http://kdavies4.github.io/natu/base-ini.html 71 | [natural units]: http://en.wikipedia.org/wiki/Natural_units 72 | [Python Standard Library]: https://docs.python.org/3/library/ 73 | [GitHub repository]: https://github.com/kdavies4/natu 74 | [NIST]: http://www.nist.gov/ 75 | [BIPM]: http://www.bipm.org/ 76 | [pip]: https://pypi.python.org/pypi/pip 77 | [pip]: https://pypi.python.org/pypi/pip 78 | [degree Celsius (degC)]: http://en.wikipedia.org/wiki/Celsius 79 | [decibel (dB)]: http://en.wikipedia.org/wiki/Decibel 80 | [coherent relations]: http://en.wikipedia.org/wiki/Coherence_(units_of_measurement) 81 | [statcoulomb]: http://en.wikipedia.org/wiki/Statcoulomb 82 | [math]: https://docs.python.org/3/library/math.html 83 | [numpy]: http://numpy.scipy.org/ 84 | [PyPI page]: http://pypi.python.org/pypi/natu 85 | [natu.groups]: http://kdavies4.github.io/natu/natu.groups.html 86 | -------------------------------------------------------------------------------- /TODO.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # List the TODO tags in various project files. 3 | 4 | locations=".travis.yml "$(find . \( -name '*.py' -or -name '*.sh' -or -name '*.md' -or -name '*.rst' -or -name '*.txt' -or -name '*.ini' -or -name '*.ipynb' \) ! \( -name code.py -or -name 'TODO*' -or -name 'UNRELEASED*' -or -path '*dist*' -or -path '*build*' -or -path '*egg*' -or -path '*-checkpoint.ipynb' \)) 5 | 6 | grep TODO $locations -n --colour=always | 7 | sed -re 's/^([^:]+:[^:]+):(\x1b\[m\x1b\[K)[[:space:]]*(.*)/\1\x01\2\3/' | 8 | column -s $'\x01' -t 9 | # The sed part removes the leading whitespace. 10 | echo 11 | echo See also the issues at https://github.com/kdavies4/natu/issues. 12 | -------------------------------------------------------------------------------- /doc/.natu.pws: -------------------------------------------------------------------------------- 1 | personal_ws-1.1 en 276 2 | banananana 3 | atm 4 | statA 5 | der 6 | statC 7 | sin 8 | paren 9 | tonumber 10 | atanh 11 | DimensionedObject 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 | baryed 28 | abohm 29 | decaampere 30 | src 31 | args 32 | fname 33 | luminance 34 | deca 35 | atan 36 | arcsec 37 | DimPy 38 | config 39 | torr 40 | sievert 41 | cyc 42 | str 43 | NumericalUnits 44 | tanh 45 | asin 46 | trunc 47 | franklin 48 | degC 49 | Modelica 50 | degF 51 | erf 52 | siemens 53 | asinh 54 | Aprime 55 | degR 56 | SciMath 57 | scimath 58 | isnan 59 | acos 60 | unutbu 61 | stattesla 62 | steradian 63 | dyn 64 | esu 65 | arctanh 66 | pathnames 67 | kcal 68 | GTRC 69 | centimetre 70 | circ 71 | gradian 72 | von 73 | txt 74 | searchbox 75 | Bruns 76 | exp 77 | toquantity 78 | submodules 79 | erfc 80 | ScalarUnit 81 | abfarad 82 | natu 83 | tuples 84 | sinh 85 | gui 86 | fromstr 87 | henry 88 | phot 89 | dest 90 | prefixable 91 | sympy 92 | nbsp 93 | kilometres 94 | unicode 95 | kat 96 | multiglob 97 | UnitsModule 98 | ini 99 | stilb 100 | abvolt 101 | Unum 102 | barad 103 | arcsinh 104 | lbf 105 | fmod 106 | PyPI 107 | subpackages 108 | bary 109 | Redistributions 110 | dimensioned 111 | ba 112 | bb 113 | rpls 114 | bd 115 | dimensionally 116 | cd 117 | indexable 118 | ce 119 | da 120 | illuminance 121 | weber 122 | acosh 123 | de 124 | df 125 | au 126 | Bq 127 | eb 128 | html 129 | thermochemical 130 | ec 131 | barie 132 | cP 133 | fb 134 | fabs 135 | kPa 136 | dm 137 | fc 138 | Stoney 139 | Wien 140 | statampere 141 | fe 142 | dyne 143 | fm 144 | unitspace 145 | eV 146 | kwds 147 | hm 148 | kA 149 | statWb 150 | mho 151 | mmHg 152 | Gy 153 | io 154 | fromQuantity 155 | CoherentRelations 156 | Scalability 157 | radians 158 | udunitspy 159 | Paredis 160 | Versioning 161 | maxwell 162 | ltypes 163 | decametre 164 | lm 165 | ln 166 | nd 167 | util 168 | statcoulomb 169 | Oe 170 | mod 171 | barrie 172 | pc 173 | nm 174 | abcoloumb 175 | lx 176 | ly 177 | np 178 | lumen 179 | deciam 180 | ph 181 | modf 182 | mol 183 | Pag 184 | ns 185 | Mx 186 | google 187 | copysign 188 | arcsecond 189 | sb 190 | getitem 191 | nmi 192 | filenames 193 | abA 194 | abC 195 | abc 196 | si 197 | darcy 198 | py 199 | LaTeX 200 | lux 201 | abF 202 | th 203 | CompoundUnit 204 | iterable 205 | abH 206 | metre 207 | baryd 208 | permittivity 209 | barye 210 | sp 211 | sr 212 | arccosh 213 | googledadb 214 | candela 215 | Wb 216 | Sv 217 | mul 218 | Instantiation 219 | abV 220 | Wh 221 | submodule 222 | tuple 223 | statvolt 224 | unrationalized 225 | frexp 226 | magnetron 227 | num 228 | arcmin 229 | classmethod 230 | GitHub 231 | tesla 232 | Szdori 233 | ala 234 | NIST 235 | bel 236 | abhenry 237 | kwargs 238 | expm 239 | ppb 240 | Filename 241 | isfinite 242 | denom 243 | expr 244 | hypot 245 | fnames 246 | pre 247 | MERCHANTABILITY 248 | lgamma 249 | daA 250 | ppq 251 | ceil 252 | LambdaUnit 253 | ppt 254 | statweber 255 | hartree 256 | API 257 | astropy 258 | fsum 259 | gauss 260 | arcminute 261 | Klitzing 262 | BIPM 263 | blockquote 264 | Biot 265 | CFR 266 | invertible 267 | dde 268 | Sep 269 | ldexp 270 | sqrt 271 | CompoundDimension 272 | neper 273 | ded 274 | CGS 275 | abampere 276 | psig 277 | pathname 278 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | Documentation for natu 2 | ---------------------- 3 | 4 | This is the top-level build directory for natu documention. All of the 5 | documentation is written using [Sphinx], a [Python] documentation system based 6 | on [reST]. This folder contains: 7 | - [make.py](make.py) - Script to clean, build, and release the HTML docs 8 | - [conf.py](conf.py) - The [Sphinx] configuration 9 | - [index.rst](index.rst) - The top-level source document 10 | - [loadres.rst](loadres.rst) - Documentation for the **loadres** script 11 | - other \*.rst files - Placeholders to automatically generate the documentation 12 | - [extra](extra) - Additional files added to the base folder of the built 13 | documentation 14 | - [_static](_static) - Folder of static files used by [Sphinx] 15 | - [_templates](_templates) - Folder of HTML templates used by [Sphinx] 16 | - [.natu.pws](.natu.pws) - [aspell] dictionary of additional natu words used 17 | in spellchecking the HTML documentation 18 | 19 | To build the documentation, install [Sphinx] and run the following command in 20 | this directory: 21 | 22 | python make.py html 23 | 24 | The top file of the results will be build/html/index.html. 25 | 26 | 27 | [Sphinx]: http://sphinx-doc.org/ 28 | [Python]: http://www.python.org 29 | [reST]: http://docutils.sourceforge.net/rst.html 30 | [aspell]: http://aspell.net/ 31 | -------------------------------------------------------------------------------- /doc/_static/analytics.js: -------------------------------------------------------------------------------- 1 | // Google Analytics script 2 | 3 | var _gaq = _gaq || []; 4 | _gaq.push(['_setAccount', 'UA-36494731-3']); 5 | _gaq.push(['_trackPageview']); 6 | 7 | (function() { 8 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 9 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 10 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 11 | })(); 12 | -------------------------------------------------------------------------------- /doc/_static/copybutton.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | /* Add a [>>>] button on the top-right corner of code samples to hide 3 | * the >>> and ... prompts and the output and thus make the code 4 | * copyable. */ 5 | var div = $('.highlight-python .highlight,' + 6 | '.highlight-python3 .highlight') 7 | var pre = div.find('pre'); 8 | 9 | // get the styles from the current theme 10 | pre.parent().parent().css('position', 'relative'); 11 | var hide_text = 'Hide the prompts and output'; 12 | var show_text = 'Show the prompts and output'; 13 | var border_width = pre.css('border-top-width'); 14 | var border_style = pre.css('border-top-style'); 15 | var border_color = pre.css('border-top-color'); 16 | var button_styles = { 17 | 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0', 18 | 'border-color': border_color, 'border-style': border_style, 19 | 'border-width': border_width, 'color': border_color, 'text-size': '75%', 20 | 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em' 21 | } 22 | 23 | // create and add the button to all the code blocks that contain >>> 24 | div.each(function(index) { 25 | var jthis = $(this); 26 | if (jthis.find('.gp').length > 0) { 27 | var button = $('>>>'); 28 | button.css(button_styles) 29 | button.attr('title', hide_text); 30 | jthis.prepend(button); 31 | } 32 | // tracebacks (.gt) contain bare text elements that need to be 33 | // wrapped in a span to work with .nextUntil() (see later) 34 | jthis.find('pre:has(.gt)').contents().filter(function() { 35 | return ((this.nodeType == 3) && (this.data.trim().length > 0)); 36 | }).wrap(''); 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 |

API

2 |
    3 | 8 |
9 | -------------------------------------------------------------------------------- /doc/_templates/definitions.html: -------------------------------------------------------------------------------- 1 |

Definition Files

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 |

{{ _('Table of Contents') }}

11 | {{ toctree(includehidden=True) }} 12 | -------------------------------------------------------------------------------- /doc/_templates/info.html: -------------------------------------------------------------------------------- 1 |

Project Info

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 |
13 | 14 | 15 | 16 |
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 |

User Modules

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 | --------------------------------------------------------------------------------