Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FormattedNumber and post Latex and HTML conversion #134

Merged
merged 38 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6451afd
remove unused parse_standard_exp_tr
jagerber48 Jan 21, 2024
be27537
latex output conversion
jagerber48 Jan 21, 2024
4fed95d
tests
jagerber48 Jan 21, 2024
fbe2206
ruff format
jagerber48 Jan 21, 2024
f7ad328
no \left or \right
jagerber48 Jan 22, 2024
8d4cf02
Remove old latex functionality
jagerber48 Jan 22, 2024
4c26d89
docstrings and minor reorganization
jagerber48 Jan 22, 2024
8679083
allowed-confusables
jagerber48 Jan 22, 2024
b77e140
typo
jagerber48 Jan 22, 2024
e09b366
documentation
jagerber48 Jan 22, 2024
9ca141a
docstring ruff formatting
jagerber48 Jan 23, 2024
1ed8e3f
add sciform_to_html and FormattedNumber
jagerber48 Jan 24, 2024
f60a710
surrounding $$
jagerber48 Jan 24, 2024
b5a3389
add strip_env_symbs flag
jagerber48 Jan 24, 2024
330f9fb
refactor conversion code and add ASCII conversion
jagerber48 Jan 25, 2024
046e606
ruff
jagerber48 Jan 25, 2024
bd37a8c
work on documentation
jagerber48 Jan 25, 2024
dd59969
fix unicode exp pattern regex
jagerber48 Jan 26, 2024
aa06c9b
update documentation
jagerber48 Jan 26, 2024
66298dd
_repr_html_ and _repr_latex_ to use as_html and as_latex (instead of …
jagerber48 Jan 26, 2024
a9e081c
consolidate output conversion tests
jagerber48 Jan 26, 2024
67c66c3
rename output conversion
jagerber48 Jan 26, 2024
bb8cca4
test latex/html repr
jagerber48 Jan 26, 2024
695e08b
test invalid cases
jagerber48 Jan 26, 2024
5671994
strip_math_mode rename and documentation
jagerber48 Jan 26, 2024
1e448b3
_repr_html_ and _repr_latex_ docs
jagerber48 Jan 26, 2024
770dc08
jupyter/IPython display example
jagerber48 Jan 26, 2024
b34bdbc
break out "examples" dependencies
jagerber48 Jan 26, 2024
d9b6870
sort autodoc members by source
jagerber48 Jan 26, 2024
d55674d
test left_pad_matching
jagerber48 Jan 26, 2024
18e916c
minor docs
jagerber48 Jan 26, 2024
49ed1c1
minor docs
jagerber48 Jan 26, 2024
1797a61
changelog
jagerber48 Jan 27, 2024
22f6c44
changelog
jagerber48 Jan 27, 2024
c6ca0c5
changelog
jagerber48 Jan 27, 2024
4f9747f
minor
jagerber48 Jan 27, 2024
0b9afda
minor
jagerber48 Jan 27, 2024
c155d5a
minor
jagerber48 Jan 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,40 @@ Unreleased
Added
^^^^^

* Added the ``FormattedNumber`` class.
This class is a subclass of ``str`` and is now returned by the
``Formatter`` instead of ``str``.
The ``FormattedNumber`` class allows post-conversion to ASCII, HTML,
and LaTeX formats.
[`#114 <https://github.com/jagerber48/sciform/issues/114>`_]
* Added separate flags for code coverage reports for each python
version.

Changed
^^^^^^^

* In addition to removing the ``latex`` option from the ``Formatter`` in
favor of the introduction of the ``FormattedNumber`` class, the
LaTeX conversion algorithm has been slightly modified.

* Left and right parentheses are no longer converted to ``"\left("``
and ``"\right)"`` due to introducing strange spacing issues.
See
`Spacing around \\left and \\right <https://tex.stackexchange.com/questions/2607/spacing-around-left-and-right>`_.
* Previously spaces within the ``sciform`` output were handled
inconsistently and occasionally required confusing extra handling.
Now any spaces in the input string are directly and explicitly
converted into math mode medium spaces: ``"\:"``.
* ``"μ"`` is now included in the math mode ``\text{}`` environment
and converted to ``"\textmu"``.

* **[BREAKING]** Renamed ``fill_char`` to ``left_pad_char``.
[`#126 <https://github.com/jagerber48/sciform/issues/126>`_]
* Slimmed down ``[dev]`` optional dependencies and created
``[examples]`` optional dependencies.
The former includes development tools, while the latter includes
the heavy-weight requirements needed to run all the examples,
including, e.g. ``jupyter``, ``scipy``, etc.

Fixed
^^^^^
Expand All @@ -28,6 +54,16 @@ Fixed
parentheses, e.g. ``"(1.2 ± 0.1)"``.
[`#130 <https://github.com/jagerber48/sciform/issues/130>`_]

Removed
^^^^^^^

* **[BREAKING]** Removed the ``latex`` option in favor of the
introduction of the ``FormattedNumber.as_latex()`` method.
This removal simplifies the formatting algorithm by separating LaTeX
formatting from other tasks like exponent string resolution.
The ``latex`` option also introduced a potential confusion with the
``superscript`` option, which had no effect when ``latex=True``.

----

0.32.3 (2024-01-11)
Expand Down
7 changes: 7 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@ Global Configuration
.. autofunction:: reset_global_defaults()

.. autoclass:: GlobalDefaultsContext()

Output Conversion
=================

.. autoclass:: sciform.formatter.FormattedNumber
:members:
:private-members:
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
todo_include_todos = True
todo_emit_warnings = True

autodoc_member_order = "bysource"

# For wrapping of text in tables
html_css_files = [
"css/custom.css",
Expand Down
54 changes: 7 additions & 47 deletions docs/source/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ mantissa ``m`` satisfies ``1 <= m < 10``.
>>> print(sform(123.456, 0.001))
(1.23456 ± 0.00001)e+02

Note that, for all exponent modes, the exponent integer is always
displayed with a sign symbol (+ or -) and is left padded with a zero so
that it is at least two digits wide.
There are no options to modify this behavior for standard exponent
display.
The :ref:`superscript` or :ref:`latex_format` options can be used as
alternatives.
By default the exponent is expressed using ASCII characters, e.g.
``e+02``.
The sign symbol is always included and the exponent value is left padded
so that it is at least two digits wide.
These behaviors for ASCII exponents cannot be modified.
However the :ref:`superscript` mode can be used to represent the
exponent using Unicode superscript characters.

.. _engineering:

Expand Down Expand Up @@ -567,46 +567,6 @@ superscript notation as opposed to e.g. ``e+02`` notation.
>>> print(sform(789))
7.89×10²

.. _latex_format:

Latex Format
============

The ``latex`` option can be chosen to convert strings into latex
parseable codes.

>>> sform = Formatter(
... exp_mode="scientific",
... exp_val=-1,
... upper_separator="_",
... latex=True,
... )
>>> print(sform(12345))
123\_450\times 10^{-1}
>>> sform = Formatter(
... exp_mode="percent",
... lower_separator="_",
... latex=True,
... )
>>> print(sform(0.12345678, 0.00000255))
\left(12.345\_678 \pm 0.000\_255\right)\%

The latex format makes the following changes:

* Convert standard exponent strings such as ``'e+02'`` into latex
superscript strings like ``'\times 10^{+2}``
* Replace ``'('`` and ``')'`` by latex size-aware delimiters
``'\left('`` and ``'\right)'``.
* Replace ``'±'`` by ``'\pm'``
* Replace ``'_'`` by ``'\_'``
* Replace ``'%'`` by ``'\%'``
* Exponent replacements such as ``'M'``, ``'Ki'``, or ``'ppb'`` and
non-finite numbers such as ``'nan'``, ``'NAN'``, ``'inf'``, and
``'INF'`` are wrapped in ``'\text{}'``.

Note that use of ``latex`` renders the use of the ``superscript``
option meaningless.

Include Exponent on nan and inf
===============================

Expand Down
102 changes: 100 additions & 2 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ package default settings):
'extra_parts_per_forms': {},
'capitalize': False,
'superscript': False,
'latex': False,
'nan_inf_exp': False,
'paren_uncertainty': False,
'pdg_sig_figs': False,
Expand Down Expand Up @@ -176,7 +175,6 @@ unchanged.
'extra_parts_per_forms': {},
'capitalize': False,
'superscript': False,
'latex': False,
'nan_inf_exp': False,
'paren_uncertainty': False,
'pdg_sig_figs': False,
Expand Down Expand Up @@ -218,6 +216,106 @@ If the user wishes to configure these options, but also use the
:ref:`FSML <fsml>`, then they must do so by modifying the global default
settings.

.. _output_conversion:

Output Conversion
=================

Typically the output of the :class:`Formatter` is used as a regular
python string.
However, the :class:`Formatter` actually returns a
:class:`FormattedNumber <formatter.FormattedNumber>` instance.
The :class:`FormattedNumber <formatter.FormattedNumber>` class
subclasses ``str`` and in many cases is used like a normal python
string.
However, the :class:`FormattedNumber <formatter.FormattedNumber>` class
exposes methods to convert the standard string representation into
LaTex, HTML, or ASCII representations.
The LaTeX and HTML representations may be useful when :mod:`sciform`
outputs are being used in contexts outside of e.g. text terminals such
as `Matplotlib <https://matplotlib.org/>`_ plots,
`Jupyter <https://jupyter.org/>`_ notebooks, or
`Quarto <https://quarto.org/>`_ documents which support richer display
functionality than Unicode text.
The ASCII representation may be useful if :mod:`sciform` outputs are
being used in contexts in which only ASCII, and not Unicode, text is
supported or preferred.

These conversions can be accessed via the
:meth:`as_latex() <formatter.FormattedNumber.as_latex>`,
:meth:`as_html() <formatter.FormattedNumber.as_html>`, and
:meth:`as_ascii() <formatter.FormattedNumber.as_ascii>` methods on the
:class:`FormattedNumber <formatter.FormattedNumber>` class.

>>> sform = Formatter(
... exp_mode="scientific",
... exp_val=-1,
... upper_separator="_",
... superscript=True,
... )
>>> formatted_str = sform(12345)
>>> print(f"{formatted_str} -> {formatted_str.as_latex()}")
123_450×10⁻¹ -> $123\_450\times10^{-1}$
>>> print(f"{formatted_str} -> {formatted_str.as_html()}")
123_450×10⁻¹ -> 123_450×10<sup>-1</sup>
>>> print(f"{formatted_str} -> {formatted_str.as_ascii()}")
123_450×10⁻¹ -> 123_450e-01

>>> sform = Formatter(
... exp_mode="percent",
... lower_separator="_",
... )
>>> formatted_str = sform(0.12345678, 0.00000255)
>>> print(f"{formatted_str} -> {formatted_str.as_latex()}")
(12.345_678 ± 0.000_255)% -> $(12.345\_678\:\pm\:0.000\_255)\%$
>>> print(f"{formatted_str} -> {formatted_str.as_html()}")
(12.345_678 ± 0.000_255)% -> (12.345_678 ± 0.000_255)%
>>> print(f"{formatted_str} -> {formatted_str.as_ascii()}")
(12.345_678 ± 0.000_255)% -> (12.345_678 +/- 0.000_255)%

>>> sform = Formatter(
... exp_mode="engineering",
... exp_format="prefix",
... ndigits=4
... )
>>> formatted_str = sform(314.159e-6, 2.71828e-6)
>>> print(f"{formatted_str} -> {formatted_str.as_latex()}")
(314.159 ± 2.718) μ -> $(314.159\:\pm\:2.718)\:\text{\textmu}$
>>> print(f"{formatted_str} -> {formatted_str.as_html()}")
(314.159 ± 2.718) μ -> (314.159 ± 2.718) μ
>>> print(f"{formatted_str} -> {formatted_str.as_ascii()}")
(314.159 ± 2.718) μ -> (314.159 +/- 2.718) u

The LaTeX enclosing ``"$"`` math environment symbols can be optionally
stripped:

>>> sform = Formatter(
... exp_mode="engineering",
... exp_format="prefix",
... ndigits=4
... )
>>> formatted_str = sform(314.159e-6, 2.71828e-6)
>>> print(f"{formatted_str} -> {formatted_str.as_latex(strip_math_mode=False)}")
(314.159 ± 2.718) μ -> $(314.159\:\pm\:2.718)\:\text{\textmu}$
>>> print(f"{formatted_str} -> {formatted_str.as_latex(strip_math_mode=True)}")
(314.159 ± 2.718) μ -> (314.159\:\pm\:2.718)\:\text{\textmu}

In addition to exposing
:meth:`as_latex() <formatter.FormattedNumber.as_latex>` and
:meth:`as_html() <formatter.FormattedNumber.as_html>`,
the :class:`FormattedNumber <formatter.FormattedNumber>` class defines
the aliases
:meth:`_repr_latex_() <formatter.FormattedNumber._repr_latex_>` and
:meth:`_repr_html_() <formatter.FormattedNumber._repr_html_>`.
The
`IPython display functions <https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#functions>`_
looks for these methods, and, if available, will use them to display
prettier representations of the class than the Unicode ``__repr__``
representation.

.. image:: ../../examples/outputs/jupyter_output.png
:width: 400

.. _dec_and_float:

Note on Decimals and Floats
Expand Down
50 changes: 50 additions & 0 deletions examples/jupyter_output_example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "ec4427f1-623b-4cd5-a077-63d5204cc7b0",
"metadata": {},
"outputs": [],
"source": [
"from sciform import Formatter\n",
"from IPython.display import display_latex, display_html\n",
"\n",
"sform = Formatter(exp_mode=\"scientific\", superscript=True)\n",
"val = sform(123456, 789)\n",
"\n",
"print('String:')\n",
"print(val)\n",
"print('\\nASCII:')\n",
"print(val.as_ascii())\n",
"print('\\nLatex:')\n",
"display_latex(val)\n",
"print('\\nHTML:')\n",
"display_html(val)\n",
"print('\\nDefault Display (HTML)')\n",
"display(val)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Binary file added examples/outputs/jupyter_output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions examples/requirements.txt

This file was deleted.

11 changes: 11 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,23 @@ dev = [
"sphinx-rtd-theme",
"sphinx-toolbox",
"numpy",
]
examples = [
"numpy",
"scipy",
"matplotlib",
"tabulate",
"jupyter",
]

[tool.setuptools.dynamic]
readme = {file = "README.rst"}

[tool.setuptools_scm]

[tool.ruff]
allowed-confusables = ["×"]

[tool.ruff.lint]
select = ['ALL']
ignore = [
Expand All @@ -57,8 +64,12 @@ ignore = [
'TD002',
'TD003',
'FIX002',
'RET504',
]

[tool.ruff.format]
docstring-code-format = true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I just learned about this option, I love it!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Batalex yes it's nice. I still use blackdoc to format code snippets in the .rst documentation files. Awaiting astral-sh/ruff#8237 so I can move entirely away from black and over to ruff.


[tool.ruff.per-file-ignores]
"tests/*.py" = ["D", "ANN", "PT"]
"examples/*.py" = ["D"]
Expand Down
Loading
Loading