sciform 0.38.1__tar.gz → 0.39.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sciform-0.38.1 → sciform-0.39.0}/CHANGELOG.rst +31 -3
- {sciform-0.38.1 → sciform-0.39.0}/PKG-INFO +3 -4
- {sciform-0.38.1 → sciform-0.39.0}/README.rst +2 -3
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/exp replacement.rst +1 -39
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/fsml.rst +4 -7
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/options.rst +16 -61
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/usage.rst +1 -7
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/api/formatter.py +3 -13
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/api/global_configuration.py +0 -4
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/exp_translations.py +0 -12
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/exponents.py +13 -35
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/numbers.py +6 -45
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/formatting/fsml.py +1 -6
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/formatting/number_formatting.py +7 -16
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/formatting/output_conversion.py +6 -17
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/formatting/parser.py +39 -63
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/finalized_options.py +0 -1
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/global_options.py +0 -1
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/input_options.py +0 -1
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/option_types.py +0 -4
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/populated_options.py +1 -3
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/validation.py +0 -7
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform.egg-info/PKG-INFO +3 -4
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_global_config.py +0 -8
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_options_printout.py +0 -3
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_output_conversion.py +0 -22
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_string_parser.py +0 -20
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_val_formatter.py +0 -6
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_val_fsml.py +0 -48
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_val_unc_formatter.py +0 -13
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/test_exp_translations.py +0 -3
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/test_exponent_utils.py +35 -123
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/test_number_utils.py +79 -382
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/test_invalid_options.py +0 -18
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/test_validation.py +0 -1
- {sciform-0.38.1 → sciform-0.39.0}/.github/workflows/python-package.yml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/.github/workflows/python-publish.yml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/.gitignore +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/.pre-commit-config.yaml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/.readthedocs.yaml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/CODE_OF_CONDUCT.rst +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/CONTRIBUTING.rst +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/LICENSE +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/coverage_feature.toml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/coverage_unit.toml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/Makefile +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/make.bat +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/requirements.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/_static/css/custom.css +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/api.rst +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/conf.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/examples.rst +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/index.rst +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/docs/source/project.rst +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/data/fit_data.json +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/fit_plot_no_sciform.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/fit_plot_with_sciform.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/jupyter_output_example.ipynb +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/outputs/fit_plot_no_sciform.png +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/outputs/fit_plot_no_sciform_table.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/outputs/fit_plot_with_sciform.png +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/outputs/fit_plot_with_sciform_table.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/examples/outputs/jupyter_output.png +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/pyproject.toml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/ruff.toml +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/setup.cfg +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/api/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/api/formatted_number.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/api/scinum.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/grouping.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/make_strings.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/format_utils/rounding.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/formatting/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform/options/conversion.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform.egg-info/SOURCES.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform.egg-info/dependency_links.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform.egg-info/requires.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/src/sciform.egg-info/top_level.txt +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_sci_num.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_separators.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/feature/test_val_unc_fsml.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/test_docstrings.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/__init__.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/test_grouping.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/test_make_strings.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/format_utils/test_rounding_utils.py +0 -0
- {sciform-0.38.1 → sciform-0.39.0}/tests/unit/test_options_strings.py +0 -0
@@ -9,14 +9,42 @@ Unreleased
|
|
9
9
|
----------
|
10
10
|
|
11
11
|
* Any unreleased changes can be viewed in the latest version
|
12
|
-
|
13
|
-
|
12
|
+
documentation
|
13
|
+
`changelog <https://sciform.readthedocs.io/en/latest/project.html#changelog>`_.
|
14
|
+
|
15
|
+
----
|
16
|
+
|
17
|
+
0.39.0 (2024-11-15)
|
18
|
+
-------------------
|
19
|
+
|
20
|
+
Removed
|
21
|
+
^^^^^^^
|
22
|
+
|
23
|
+
* Removed all support for base-2 formatting.
|
24
|
+
The ``sciform`` package will focus on base-10 scientific formatting,
|
25
|
+
more relevent for the physical sciences, unless there is demand for
|
26
|
+
base-2 or base-``n`` formatting.
|
27
|
+
We encourage users to consider the `prefixed <https://pypi.org/project/prefixed/>`_
|
28
|
+
package if they have requirements for base-2 formatting.
|
29
|
+
[`#201 <https://github.com/jagerber48/sciform/issues/201>`_]
|
30
|
+
|
31
|
+
----
|
32
|
+
|
33
|
+
0.38.2 (2024-11-02)
|
34
|
+
-------------------
|
35
|
+
|
36
|
+
Fixed
|
37
|
+
^^^^^
|
38
|
+
|
39
|
+
* Corrected a typo in a previous release.
|
40
|
+
|
41
|
+
----
|
14
42
|
|
15
43
|
0.38.1 (2024-11-02)
|
16
44
|
-------------------
|
17
45
|
|
18
46
|
Added
|
19
|
-
|
47
|
+
^^^^^
|
20
48
|
|
21
49
|
* Documented examples demonstrating the interplay between ``sciform``
|
22
50
|
formatting the ``decimal`` module configuration.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: sciform
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.39.0
|
4
4
|
Summary: A package for formatting numbers into scientific formatted strings.
|
5
5
|
Author-email: Justin Gerber <justin.gerber48@gmail.com>
|
6
6
|
Project-URL: homepage, https://github.com/jagerber48/sciform
|
@@ -90,10 +90,9 @@ Overview
|
|
90
90
|
|
91
91
|
``sciform`` is used to convert python numbers into strings according to
|
92
92
|
a variety of user-selected scientific formatting options including
|
93
|
-
|
93
|
+
fixed-point, scientific and engineering formats.
|
94
94
|
Where possible, formatting follows documented standards such as those
|
95
|
-
published by `BIPM <https://www.bipm.org/en/>`_
|
96
|
-
`IEC <https://iec.ch/homepage>`_.
|
95
|
+
published by `BIPM <https://www.bipm.org/en/>`_.
|
97
96
|
``sciform`` provides certain options, such as engineering notation,
|
98
97
|
well-controlled significant figure rounding, and separator customization
|
99
98
|
which are not provided by the python built-in
|
@@ -46,10 +46,9 @@ Overview
|
|
46
46
|
|
47
47
|
``sciform`` is used to convert python numbers into strings according to
|
48
48
|
a variety of user-selected scientific formatting options including
|
49
|
-
|
49
|
+
fixed-point, scientific and engineering formats.
|
50
50
|
Where possible, formatting follows documented standards such as those
|
51
|
-
published by `BIPM <https://www.bipm.org/en/>`_
|
52
|
-
`IEC <https://iec.ch/homepage>`_.
|
51
|
+
published by `BIPM <https://www.bipm.org/en/>`_.
|
53
52
|
``sciform`` provides certain options, such as engineering notation,
|
54
53
|
well-controlled significant figure rounding, and separator customization
|
55
54
|
which are not provided by the python built-in
|
@@ -6,14 +6,11 @@ Supported Exponent Replacements
|
|
6
6
|
:mod:`sciform` offers exponent replacement modes which provide
|
7
7
|
translations between exponent strings and conventional alphabetic
|
8
8
|
symbol representations.
|
9
|
-
For
|
9
|
+
For exponents in engineering formats, SI prefix translations are
|
10
10
|
available according to the
|
11
11
|
`SI prefixes <https://www.nist.gov/pml/owm/metric-si-prefixes>`_.
|
12
12
|
It is also possible to convert decimal exponents into
|
13
13
|
`parts-per notation <https://en.wikipedia.org/wiki/Parts-per_notation>`_.
|
14
|
-
For binary formats, the IEC prefix translations are available matched to
|
15
|
-
integer multiples of 10 according to the
|
16
|
-
`IEC prefixes <https://physics.nist.gov/cuu/Units/binary.html>`_.
|
17
14
|
|
18
15
|
SI Prefixes
|
19
16
|
-----------
|
@@ -161,38 +158,3 @@ override the standard mappings listed above.
|
|
161
158
|
33e-09
|
162
159
|
>>> print(formatter(33e-12))
|
163
160
|
33 ppb
|
164
|
-
|
165
|
-
IEC Prefixes
|
166
|
-
------------
|
167
|
-
|
168
|
-
.. list-table:: IEC Prefixes
|
169
|
-
:widths: 15, 15, 15
|
170
|
-
:header-rows: 1
|
171
|
-
|
172
|
-
* - Exponent Value
|
173
|
-
- Prefix Name
|
174
|
-
- Prefix
|
175
|
-
* - 2\ :sup:`+80`
|
176
|
-
- yobi
|
177
|
-
- Yi
|
178
|
-
* - 2\ :sup:`+70`
|
179
|
-
- zebi
|
180
|
-
- Zi
|
181
|
-
* - 2\ :sup:`+60`
|
182
|
-
- exi
|
183
|
-
- Ei
|
184
|
-
* - 2\ :sup:`+50`
|
185
|
-
- pebi
|
186
|
-
- Pi
|
187
|
-
* - 2\ :sup:`+40`
|
188
|
-
- tebi
|
189
|
-
- Ti
|
190
|
-
* - 2\ :sup:`+30`
|
191
|
-
- gibi
|
192
|
-
- Gi
|
193
|
-
* - 2\ :sup:`+20`
|
194
|
-
- mebi
|
195
|
-
- Mi
|
196
|
-
* - 2\ :sup:`+10`
|
197
|
-
- kibi
|
198
|
-
- Ki
|
@@ -26,7 +26,7 @@ The :mod:`sciform` format specification mini-language is given by::
|
|
26
26
|
round_mode ::= "!" | "."
|
27
27
|
special_round_mode ::= "A" | "P"
|
28
28
|
ndigits ::= [+-]?digit+
|
29
|
-
exp_mode ::= "f" | "F" | "%" | "e" | "E" | "r" | "R" |
|
29
|
+
exp_mode ::= "f" | "F" | "%" | "e" | "E" | "r" | "R" |
|
30
30
|
exp_val ::= [+-]?digit+
|
31
31
|
|
32
32
|
Below are two simple FSML usage examples.
|
@@ -74,8 +74,7 @@ Further details about the options can be found at
|
|
74
74
|
| (``'#'``)
|
75
75
|
- The alternate mode flag indicates to use
|
76
76
|
:ref:`engineering_shifted` mode when the exponent mode flag is
|
77
|
-
``'r'`` or ``'R'
|
78
|
-
exponent mode flag is ``'b'`` or ``'B'``.
|
77
|
+
``'r'`` or ``'R'``.
|
79
78
|
* - | left_pad_dec_place
|
80
79
|
| (``\d+``)
|
81
80
|
- Sets ``left_pad_dec_place`` to any non-negative integer.
|
@@ -93,8 +92,8 @@ Further details about the options can be found at
|
|
93
92
|
- Set ``round_mode`` to ``'all'`` or ``'pdg'``.
|
94
93
|
See :ref:`rounding`.
|
95
94
|
* - | exp_mode
|
96
|
-
| (``'f'``, ``'F'``, ``'%'``, ``'e'``, ``'E'``, ``'r'``,
|
97
|
-
``'
|
95
|
+
| (``'f'``, ``'F'``, ``'%'``, ``'e'``, ``'E'``, ``'r'``,
|
96
|
+
``'R'``)
|
98
97
|
- Sets ``exponent_mode``.
|
99
98
|
If this flag is capitalized then ``capitalize`` is set to
|
100
99
|
``True``.
|
@@ -106,8 +105,6 @@ Further details about the options can be found at
|
|
106
105
|
* ``'r'`` and ``'R'`` set :ref:`engineering` or
|
107
106
|
:ref:`engineering_shifted` exponent modes depending on if the
|
108
107
|
alternate mode flag is used..
|
109
|
-
* ``'b'`` and ``'B'`` set :ref:`binary` or :ref:`binary_iec`
|
110
|
-
exponent modes depending on if the alternate mode flag is used.
|
111
108
|
* - | exp_val
|
112
109
|
| (``x[+-]\d+``)
|
113
110
|
- Sets ``exp_val`` to an integer.
|
@@ -21,11 +21,11 @@ Exponent Mode
|
|
21
21
|
To display numbers across a wide range of magnitudes, scientific
|
22
22
|
formatting presents numbers in the form::
|
23
23
|
|
24
|
-
num = mantissa *
|
24
|
+
num = mantissa * 10**exp
|
25
25
|
|
26
|
-
Where exp is an integer
|
27
|
-
The different exponent modes control how ``mantissa
|
28
|
-
|
26
|
+
Where exp is an integer.
|
27
|
+
The different exponent modes control how ``mantissa`` and ``exp`` are
|
28
|
+
chosen for a given input number ``num``.
|
29
29
|
|
30
30
|
.. _fixed_point:
|
31
31
|
|
@@ -62,7 +62,7 @@ appended to the end of the formatted string.
|
|
62
62
|
Scientific Notation
|
63
63
|
-------------------
|
64
64
|
|
65
|
-
Scientific notation is used to display
|
65
|
+
Scientific notation is used to display numbers.
|
66
66
|
In scientific notation, the exponent is uniquely chosen so that the
|
67
67
|
mantissa ``m`` satisfies ``1 <= m < 10``.
|
68
68
|
|
@@ -120,36 +120,6 @@ the exponent is chosen so that the mantissa ``m`` satisfies
|
|
120
120
|
>>> print(formatter(123.456, 0.001))
|
121
121
|
(0.123456 ± 0.000001)e+03
|
122
122
|
|
123
|
-
.. _binary:
|
124
|
-
|
125
|
-
Binary
|
126
|
-
------
|
127
|
-
|
128
|
-
Binary formatting can be chosen to display a number in scientific
|
129
|
-
notation in base-2.
|
130
|
-
|
131
|
-
>>> formatter = Formatter(exp_mode="binary")
|
132
|
-
>>> print(formatter(256))
|
133
|
-
1b+08
|
134
|
-
|
135
|
-
Here ``b`` exponent symbol indicates base-2 instead of base-10.
|
136
|
-
For binary formatting, the mantissa ``m`` satisfies ``1 <= m < 2``.
|
137
|
-
|
138
|
-
.. _binary_iec:
|
139
|
-
|
140
|
-
Binary IEC
|
141
|
-
----------
|
142
|
-
|
143
|
-
Binary IEC mode is similar to engineering notation, except in base-2.
|
144
|
-
In this mode number are expressed in base-2 exponent notation, but the
|
145
|
-
exponent is constrained to be a multiple of 10, consistent with the
|
146
|
-
IEC binary prefixes.
|
147
|
-
The mantissa ``m`` satisfies ``1 <= m < 1024``.
|
148
|
-
|
149
|
-
>>> formatter = Formatter(exp_mode="binary_iec")
|
150
|
-
>>> print(formatter(2048))
|
151
|
-
2b+10
|
152
|
-
|
153
123
|
.. _fixed_exp:
|
154
124
|
|
155
125
|
Fixed Exponent
|
@@ -171,10 +141,8 @@ For fixed point and percent modes an explicit fixed exponent must equal
|
|
171
141
|
0.
|
172
142
|
For engineering and shifted engineering modes an explicit fixed exponent
|
173
143
|
must be an integer multiple of 3.
|
174
|
-
For binary IEC mode an explicit fixed exponent must be an integer
|
175
|
-
multiple of 10.
|
176
144
|
Because of this constrained behavior, it is recommended to only use a
|
177
|
-
fixed exponent with the scientific
|
145
|
+
fixed exponent with the scientific exponent mode.
|
178
146
|
|
179
147
|
.. _exp_str_replacement:
|
180
148
|
|
@@ -182,12 +150,11 @@ Exponent String Replacement
|
|
182
150
|
===========================
|
183
151
|
|
184
152
|
:mod:`sciform` provides a number of formatting options for replacing
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
IEC prefixes.
|
153
|
+
exponent strings such as ``'e-03'`` with conventional strings such as
|
154
|
+
``'m'`` (the SI prefix for milli) to succinctly communicate the order
|
155
|
+
of magnitude.
|
156
|
+
Exponent strings can be replaced with either SI prefixes or parts-per
|
157
|
+
identifiers.
|
191
158
|
See :ref:`exp_replacements` for all default supported
|
192
159
|
replacements.
|
193
160
|
Furthermore, it is possible to customize :class:`Formatter`
|
@@ -197,14 +164,6 @@ in addition to those provided by default.
|
|
197
164
|
>>> formatter = Formatter(exp_mode="engineering", exp_format="prefix")
|
198
165
|
>>> print(formatter(4242.13))
|
199
166
|
4.24213 k
|
200
|
-
>>> formatter = Formatter(
|
201
|
-
... exp_mode="binary_iec",
|
202
|
-
... round_mode="sig_fig",
|
203
|
-
... ndigits=4,
|
204
|
-
... exp_format="prefix",
|
205
|
-
... )
|
206
|
-
>>> print(formatter(1300))
|
207
|
-
1.270 Ki
|
208
167
|
>>> formatter = Formatter(exp_mode="engineering", exp_format="parts_per")
|
209
168
|
>>> print(formatter(12.3e-6))
|
210
169
|
12.3 ppm
|
@@ -217,11 +176,10 @@ Extra Exponent Replacements
|
|
217
176
|
In addition to the default
|
218
177
|
:ref:`exponent replacements <exp_replacements>`, The user can modify the
|
219
178
|
available exponent replacements using a number of options.
|
220
|
-
The SI prefix
|
221
|
-
using the ``extra_si_prefixes
|
222
|
-
|
223
|
-
|
224
|
-
corresponding to translated strings.
|
179
|
+
The SI prefix and parts-per replacements can be modified
|
180
|
+
using the ``extra_si_prefixes`` and ``extra_parts_per_forms`` options,
|
181
|
+
respectively, and passing in dictionaries with keys corresponding to
|
182
|
+
integer exponents and values corresponding to translated strings.
|
225
183
|
The entries in these dictionaries overwrite any default translation
|
226
184
|
mappings.
|
227
185
|
|
@@ -652,9 +610,6 @@ The capitalization of the exponent character can be controlled
|
|
652
610
|
>>> formatter = Formatter(exp_mode="scientific", capitalize=True)
|
653
611
|
>>> print(formatter(42))
|
654
612
|
4.2E+01
|
655
|
-
>>> formatter = Formatter(exp_mode="binary", capitalize=True)
|
656
|
-
>>> print(formatter(1024))
|
657
|
-
1B+10
|
658
613
|
|
659
614
|
The ``capitalize`` flag also controls the capitalization of ``nan`` and
|
660
615
|
``inf`` formatting:
|
@@ -705,7 +660,7 @@ Python supports ``'nan'``, ``'inf'``, and
|
|
705
660
|
and ``'-inf'`` or ``'NAN'``, ``'INF'``, and ``'-INF'``, respectively,
|
706
661
|
depending on ``capitalize``.
|
707
662
|
However, if ``nan_inf_exp=True`` (default ``False``), then, for
|
708
|
-
scientific, percent,
|
663
|
+
scientific, percent, and engineering exponent modes, these will
|
709
664
|
instead be formatted as, e.g. ``'(nan)e+00'``.
|
710
665
|
|
711
666
|
>>> formatter = Formatter(
|
@@ -238,9 +238,7 @@ exponents such as ``"n" -> "e-09"``.
|
|
238
238
|
These translations are performed by first checking the default SI
|
239
239
|
prefixes along with any global ``extra_si_prefixes``, then checking
|
240
240
|
the default parts-per forms along with any global
|
241
|
-
``extra_parts_per_forms
|
242
|
-
with any global ``extra_iec_prefixes``.
|
243
|
-
If an IEC prefix is detected then the exponent base is chosen to be 2.
|
241
|
+
``extra_parts_per_forms``.
|
244
242
|
if no valid translations are discovered or more than one valid
|
245
243
|
translation is discovered an exception is raised.
|
246
244
|
|
@@ -474,7 +472,6 @@ PopulatedOptions(
|
|
474
472
|
'left_pad_dec_place': 0,
|
475
473
|
'exp_format': 'standard',
|
476
474
|
'extra_si_prefixes': {},
|
477
|
-
'extra_iec_prefixes': {},
|
478
475
|
'extra_parts_per_forms': {},
|
479
476
|
'capitalize': False,
|
480
477
|
'superscript': False,
|
@@ -516,7 +513,6 @@ PopulatedOptions(
|
|
516
513
|
'left_pad_dec_place': 0,
|
517
514
|
'exp_format': 'standard',
|
518
515
|
'extra_si_prefixes': {},
|
519
|
-
'extra_iec_prefixes': {},
|
520
516
|
'extra_parts_per_forms': {},
|
521
517
|
'capitalize': False,
|
522
518
|
'superscript': False,
|
@@ -615,7 +611,6 @@ PopulatedOptions(
|
|
615
611
|
'left_pad_dec_place': 0,
|
616
612
|
'exp_format': 'standard',
|
617
613
|
'extra_si_prefixes': {},
|
618
|
-
'extra_iec_prefixes': {},
|
619
614
|
'extra_parts_per_forms': {},
|
620
615
|
'capitalize': False,
|
621
616
|
'superscript': True,
|
@@ -660,7 +655,6 @@ PopulatedOptions(
|
|
660
655
|
'left_pad_dec_place': 0,
|
661
656
|
'exp_format': 'standard',
|
662
657
|
'extra_si_prefixes': {},
|
663
|
-
'extra_iec_prefixes': {},
|
664
658
|
'extra_parts_per_forms': {},
|
665
659
|
'capitalize': False,
|
666
660
|
'superscript': True,
|
@@ -118,7 +118,6 @@ class Formatter:
|
|
118
118
|
'left_pad_dec_place': 0,
|
119
119
|
'exp_format': 'standard',
|
120
120
|
'extra_si_prefixes': {},
|
121
|
-
'extra_iec_prefixes': {},
|
122
121
|
'extra_parts_per_forms': {},
|
123
122
|
'capitalize': False,
|
124
123
|
'superscript': True,
|
@@ -153,7 +152,6 @@ class Formatter:
|
|
153
152
|
left_pad_dec_place: int | None = None,
|
154
153
|
exp_format: option_types.ExpFormat | None = None,
|
155
154
|
extra_si_prefixes: dict[int, str] | None = None,
|
156
|
-
extra_iec_prefixes: dict[int, str] | None = None,
|
157
155
|
extra_parts_per_forms: dict[int, str] | None = None,
|
158
156
|
capitalize: bool | None = None,
|
159
157
|
superscript: bool | None = None,
|
@@ -180,7 +178,6 @@ class Formatter:
|
|
180
178
|
* ``exp_val`` must be 0 for fixed point and percent modes
|
181
179
|
* ``exp_val`` must be a multiple of 3 for engineering and
|
182
180
|
shifted engineering modes
|
183
|
-
* ``exp_val`` must be a multiple of 10 for binary iec mode
|
184
181
|
|
185
182
|
* ``upper_separator`` may be any of ``['', ',', '.', ' ', '_']``
|
186
183
|
but must be different from ``decimal_separator``
|
@@ -189,13 +186,12 @@ class Formatter:
|
|
189
186
|
|
190
187
|
:param exp_mode: Specify the exponent formatting mode.
|
191
188
|
:type exp_mode: ``Literal['fixed_point', 'percent',
|
192
|
-
'scientific', 'engineering', 'engineering_shifted'
|
193
|
-
'binary_iec'] | None``
|
189
|
+
'scientific', 'engineering', 'engineering_shifted'] | None``
|
194
190
|
:param exp_val: Indicates how the exponent value should be
|
195
191
|
chosen. If an integer is specified, the value must be 0 for
|
196
192
|
fixed point and percent modes, an integer multiple of 3 for
|
197
|
-
engineering and engineering shifted modes
|
198
|
-
|
193
|
+
engineering and engineering shifted modes. Can be set to
|
194
|
+
``"auto"``.
|
199
195
|
:type exp_val: ``int | Literal['auto'] | None``
|
200
196
|
:param round_mode: Indicate how to round numbers during
|
201
197
|
formatting.
|
@@ -231,11 +227,6 @@ class Formatter:
|
|
231
227
|
values to si prefixes. Entries overwrite default values. A
|
232
228
|
value of ``None`` means that exponent will not be converted.
|
233
229
|
:type extra_si_prefixes: ``dict[int, Union[str, None]] | None``
|
234
|
-
:param extra_iec_prefixes: Dictionary mapping additional
|
235
|
-
exponent values to iec prefixes. Entries overwrite default
|
236
|
-
values. A value of ``None`` means that exponent will not be
|
237
|
-
converted.
|
238
|
-
:type extra_iec_prefixes: ``dict[int, Union[str, None]] | None``
|
239
230
|
:param extra_parts_per_forms: Dictionary mapping additional
|
240
231
|
exponent values to "parts-per" forms. Entries overwrite
|
241
232
|
default values. A value of ``None`` means that exponent will
|
@@ -297,7 +288,6 @@ class Formatter:
|
|
297
288
|
left_pad_dec_place=left_pad_dec_place,
|
298
289
|
exp_format=exp_format,
|
299
290
|
extra_si_prefixes=extra_si_prefixes,
|
300
|
-
extra_iec_prefixes=extra_iec_prefixes,
|
301
291
|
extra_parts_per_forms=extra_parts_per_forms,
|
302
292
|
capitalize=capitalize,
|
303
293
|
superscript=superscript,
|
@@ -38,7 +38,6 @@ def set_global_options( # noqa: PLR0913
|
|
38
38
|
left_pad_dec_place: int | None = None,
|
39
39
|
exp_format: option_types.ExpFormat | None = None,
|
40
40
|
extra_si_prefixes: dict[int, str] | None = None,
|
41
|
-
extra_iec_prefixes: dict[int, str] | None = None,
|
42
41
|
extra_parts_per_forms: dict[int, str] | None = None,
|
43
42
|
capitalize: bool | None = None,
|
44
43
|
superscript: bool | None = None,
|
@@ -69,7 +68,6 @@ def set_global_options( # noqa: PLR0913
|
|
69
68
|
left_pad_dec_place=left_pad_dec_place,
|
70
69
|
exp_format=exp_format,
|
71
70
|
extra_si_prefixes=extra_si_prefixes,
|
72
|
-
extra_iec_prefixes=extra_iec_prefixes,
|
73
71
|
extra_parts_per_forms=extra_parts_per_forms,
|
74
72
|
capitalize=capitalize,
|
75
73
|
superscript=superscript,
|
@@ -119,7 +117,6 @@ class GlobalOptionsContext:
|
|
119
117
|
left_pad_dec_place: int | None = None,
|
120
118
|
exp_format: option_types.ExpFormat | None = None,
|
121
119
|
extra_si_prefixes: dict[int, str] | None = None,
|
122
|
-
extra_iec_prefixes: dict[int, str] | None = None,
|
123
120
|
extra_parts_per_forms: dict[int, str] | None = None,
|
124
121
|
capitalize: bool | None = None,
|
125
122
|
superscript: bool | None = None,
|
@@ -145,7 +142,6 @@ class GlobalOptionsContext:
|
|
145
142
|
left_pad_dec_place=left_pad_dec_place,
|
146
143
|
exp_format=exp_format,
|
147
144
|
extra_si_prefixes=extra_si_prefixes,
|
148
|
-
extra_iec_prefixes=extra_iec_prefixes,
|
149
145
|
extra_parts_per_forms=extra_parts_per_forms,
|
150
146
|
capitalize=capitalize,
|
151
147
|
superscript=superscript,
|
@@ -2,15 +2,14 @@
|
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
-
from typing import TYPE_CHECKING
|
5
|
+
from typing import TYPE_CHECKING
|
6
6
|
|
7
7
|
from sciform.format_utils.exp_translations import (
|
8
|
-
val_to_iec_dict,
|
9
8
|
val_to_parts_per_dict,
|
10
9
|
val_to_si_dict,
|
11
10
|
)
|
12
11
|
from sciform.format_utils.numbers import (
|
13
|
-
|
12
|
+
get_mantissa_exp,
|
14
13
|
)
|
15
14
|
from sciform.options.option_types import (
|
16
15
|
ExpFormatEnum,
|
@@ -24,22 +23,13 @@ if TYPE_CHECKING: # pragma: no cover
|
|
24
23
|
|
25
24
|
def get_translation_dict(
|
26
25
|
exp_format: ExpFormatEnum,
|
27
|
-
base: Literal[10, 2],
|
28
26
|
extra_si_prefixes: dict[int, str],
|
29
|
-
extra_iec_prefixes: dict[int, str],
|
30
27
|
extra_parts_per_forms: dict[int, str],
|
31
28
|
) -> dict[int, str]:
|
32
29
|
"""Resolve dictionary of prefix translations."""
|
33
30
|
if exp_format is ExpFormatEnum.PREFIX:
|
34
|
-
|
35
|
-
|
36
|
-
translation_dict.update(extra_si_prefixes)
|
37
|
-
elif base == 2:
|
38
|
-
translation_dict = val_to_iec_dict.copy()
|
39
|
-
translation_dict.update(extra_iec_prefixes)
|
40
|
-
else:
|
41
|
-
msg = f"Unhandled base {base}"
|
42
|
-
raise ValueError(msg)
|
31
|
+
translation_dict = val_to_si_dict.copy()
|
32
|
+
translation_dict.update(extra_si_prefixes)
|
43
33
|
elif exp_format is ExpFormatEnum.PARTS_PER:
|
44
34
|
translation_dict = val_to_parts_per_dict.copy()
|
45
35
|
translation_dict.update(extra_parts_per_forms)
|
@@ -50,24 +40,21 @@ def get_translation_dict(
|
|
50
40
|
return translation_dict
|
51
41
|
|
52
42
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
def get_standard_exp_str(base: int, exp_val: int, *, capitalize: bool = False) -> str:
|
43
|
+
def get_standard_exp_str(exp_val: int, *, capitalize: bool = False) -> str:
|
57
44
|
"""Get standard (eg. 'e+02') exponent string."""
|
58
|
-
|
45
|
+
base_symbol = "e"
|
59
46
|
if capitalize:
|
60
|
-
|
61
|
-
return f"{
|
47
|
+
base_symbol = base_symbol.capitalize()
|
48
|
+
return f"{base_symbol}{exp_val:+03d}"
|
62
49
|
|
63
50
|
|
64
51
|
superscript_translate = str.maketrans("+-0123456789", "⁺⁻⁰¹²³⁴⁵⁶⁷⁸⁹")
|
65
52
|
|
66
53
|
|
67
|
-
def get_superscript_exp_str(
|
54
|
+
def get_superscript_exp_str(exp_val: int) -> str:
|
68
55
|
"""Get superscript (e.g. '×10⁺²') exponent string."""
|
69
56
|
exp_val_str = f"{exp_val}".translate(superscript_translate)
|
70
|
-
return f"×{
|
57
|
+
return f"×10{exp_val_str}"
|
71
58
|
|
72
59
|
|
73
60
|
def get_exp_str( # noqa: PLR0913
|
@@ -76,7 +63,6 @@ def get_exp_str( # noqa: PLR0913
|
|
76
63
|
exp_mode: ExpModeEnum,
|
77
64
|
exp_format: ExpFormatEnum,
|
78
65
|
extra_si_prefixes: dict[int, str],
|
79
|
-
extra_iec_prefixes: dict[int, str],
|
80
66
|
extra_parts_per_forms: dict[int, str],
|
81
67
|
capitalize: bool,
|
82
68
|
superscript: bool,
|
@@ -87,18 +73,10 @@ def get_exp_str( # noqa: PLR0913
|
|
87
73
|
if exp_mode is ExpModeEnum.PERCENT:
|
88
74
|
return "%"
|
89
75
|
|
90
|
-
if exp_mode is ExpModeEnum.BINARY or exp_mode is ExpModeEnum.BINARY_IEC:
|
91
|
-
base = 2
|
92
|
-
else:
|
93
|
-
base = 10
|
94
|
-
base = cast(Literal[10, 2], base)
|
95
|
-
|
96
76
|
if exp_format is ExpFormatEnum.PREFIX or exp_format is ExpFormatEnum.PARTS_PER:
|
97
77
|
translation_dict = get_translation_dict(
|
98
78
|
exp_format,
|
99
|
-
base,
|
100
79
|
extra_si_prefixes,
|
101
|
-
extra_iec_prefixes,
|
102
80
|
extra_parts_per_forms,
|
103
81
|
)
|
104
82
|
if (
|
@@ -110,9 +88,9 @@ def get_exp_str( # noqa: PLR0913
|
|
110
88
|
return exp_str
|
111
89
|
|
112
90
|
if superscript:
|
113
|
-
return get_superscript_exp_str(
|
91
|
+
return get_superscript_exp_str(exp_val)
|
114
92
|
|
115
|
-
return get_standard_exp_str(
|
93
|
+
return get_standard_exp_str(exp_val, capitalize=capitalize)
|
116
94
|
|
117
95
|
|
118
96
|
def get_val_unc_exp(
|
@@ -132,7 +110,7 @@ def get_val_unc_exp(
|
|
132
110
|
else:
|
133
111
|
exp_driver_val = unc
|
134
112
|
|
135
|
-
_, exp_val
|
113
|
+
_, exp_val = get_mantissa_exp(
|
136
114
|
exp_driver_val,
|
137
115
|
exp_mode=exp_mode,
|
138
116
|
input_exp=input_exp,
|
@@ -1,10 +1,9 @@
|
|
1
|
-
"""Utilities for parsing mantissa,
|
1
|
+
"""Utilities for parsing mantissa, and exp."""
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import re
|
6
6
|
from decimal import Decimal
|
7
|
-
from math import floor, log2
|
8
7
|
from typing import Literal
|
9
8
|
|
10
9
|
from sciform.formatting.parser import (
|
@@ -26,13 +25,6 @@ def get_top_dec_place(num: Decimal) -> int:
|
|
26
25
|
return len(digits) + exp - 1
|
27
26
|
|
28
27
|
|
29
|
-
def get_top_dec_place_binary(num: Decimal) -> int:
|
30
|
-
"""Get the decimal place of a decimal's most significant digit."""
|
31
|
-
if not num.is_finite() or num == 0:
|
32
|
-
return 0
|
33
|
-
return floor(log2(abs(num)))
|
34
|
-
|
35
|
-
|
36
28
|
def get_bottom_dec_place(num: Decimal) -> int:
|
37
29
|
"""Get the decimal place of a decimal's least significant digit."""
|
38
30
|
if not num.is_finite():
|
@@ -102,39 +94,12 @@ def get_engineering_exp(
|
|
102
94
|
return exp_val
|
103
95
|
|
104
96
|
|
105
|
-
def
|
106
|
-
num: Decimal,
|
107
|
-
input_exp: int | ExpValEnum,
|
108
|
-
*,
|
109
|
-
iec: bool = False,
|
110
|
-
) -> int:
|
111
|
-
"""Get the exponent for binary formatting modes."""
|
112
|
-
if input_exp is ExpValEnum.AUTO:
|
113
|
-
exp_val = get_top_dec_place_binary(num)
|
114
|
-
if iec:
|
115
|
-
exp_val = (exp_val // 10) * 10
|
116
|
-
else:
|
117
|
-
if iec and input_exp % 10 != 0:
|
118
|
-
msg = (
|
119
|
-
f"Exponent must be an integer multiple of 10 in binary IEC mode, not "
|
120
|
-
f"{input_exp}."
|
121
|
-
)
|
122
|
-
raise ValueError(msg)
|
123
|
-
exp_val = input_exp
|
124
|
-
return exp_val
|
125
|
-
|
126
|
-
|
127
|
-
def get_mantissa_exp_base(
|
97
|
+
def get_mantissa_exp(
|
128
98
|
num: Decimal,
|
129
99
|
exp_mode: ExpModeEnum,
|
130
100
|
input_exp: int | ExpValEnum,
|
131
|
-
) -> tuple[Decimal, int
|
132
|
-
"""Get mantissa
|
133
|
-
if exp_mode is ExpModeEnum.BINARY or exp_mode is ExpModeEnum.BINARY_IEC:
|
134
|
-
base = 2
|
135
|
-
else:
|
136
|
-
base = 10
|
137
|
-
|
101
|
+
) -> tuple[Decimal, int]:
|
102
|
+
"""Get mantissa and exponent for formatting a decimal number."""
|
138
103
|
if num == 0 or not num.is_finite():
|
139
104
|
mantissa = Decimal(num)
|
140
105
|
exp = 0 if input_exp is ExpValEnum.AUTO else input_exp
|
@@ -147,16 +112,12 @@ def get_mantissa_exp_base(
|
|
147
112
|
exp = get_engineering_exp(num, input_exp)
|
148
113
|
elif exp_mode is ExpModeEnum.ENGINEERING_SHIFTED:
|
149
114
|
exp = get_engineering_exp(num, input_exp, shifted=True)
|
150
|
-
elif exp_mode is ExpModeEnum.BINARY:
|
151
|
-
exp = get_binary_exp(num, input_exp)
|
152
|
-
elif exp_mode is ExpModeEnum.BINARY_IEC:
|
153
|
-
exp = get_binary_exp(num, input_exp, iec=True)
|
154
115
|
else:
|
155
116
|
msg = f"Unhandled exponent mode {exp_mode}."
|
156
117
|
raise ValueError(msg)
|
157
|
-
mantissa = num * Decimal(
|
118
|
+
mantissa = num * Decimal(10) ** Decimal(-exp)
|
158
119
|
mantissa = mantissa.normalize()
|
159
|
-
return mantissa, exp
|
120
|
+
return mantissa, exp
|
160
121
|
|
161
122
|
|
162
123
|
# language=pythonverboseregexp noqa: ERA001
|