API

Formatting

class sciform.Formatter(...)

Class to format value and value/uncertainty pairs.

Formatter is used to convert value and value/uncertainty pairs into formatted strings according to a variety of formatting options. See Formatting Options for more details on the available options. Any options which are not populated (not passed in or passed in the None value) will be populated at format time by the corresponding values in the globally configured default options. See Global Options for details about how to view and modify the global options. The user supplied options cannot be updated after the Formatter is constructed.

After initialization, the Formatter is used by passing in a value into the Formatter.

>>> from sciform import Formatter
>>> formatter = Formatter(exp_mode="engineering", round_mode="sig_fig", ndigits=4)
>>> print(formatter(12345.678))
12.35e+03

A value/uncertainty pair can also be passed into the Formatter.

>>> formatter = Formatter(
...     exp_mode="engineering",
...     round_mode="sig_fig",
...     ndigits=2,
...     superscript=True,
... )
>>> formatted = formatter(12345.678, 3.4)
>>> print(formatted)
(12.3457 ± 0.0034)×10³

Formatted input can also be passed into the formatter. For more details see Formatted Input.

>>> print(formatter("31.415 M"))
31×10⁶
>>> print(formatter("12345.678 +/- 3.4"))
(12.3457 ± 0.0034)×10³
>>> print(formatter("12345.678(3.4)"))
(12.3457 ± 0.0034)×10³

The returned object behaves like a str, but is, in fact, a FormattedNumber instance. The FormattedNumber is a subclass of str but provides methods for post-conversion into LaTeX, HTML, and ASCII formats.

>>> print(formatted.as_latex())
$(12.3457\:\pm\:0.0034)\times10^{3}$
>>> print(formatted.as_html())
(12.3457 ± 0.0034)×10<sup>3</sup>
>>> print(formatted.as_ascii())
(12.3457 +/- 0.0034)e+03

The formatting options input by the user can be checked by inspecting the input_options property

>>> print(formatter.input_options)
InputOptions(
 'exp_mode': 'engineering',
 'round_mode': 'sig_fig',
 'ndigits': 2,
 'superscript': True,
)

Only explicitly populated options appear in the string printout. However, populated and unpopulated parameters can be inspected by direct attribute access. Unpopulated parameters are None-valued.

>>> print(formatter.input_options.round_mode)
sig_fig
>>> print(formatter.input_options.exp_format)
None

The InputOptions.as_dict() method returns a dictionary of input options that can be passed back into a Formatter constructor as **kwargs, possibly after modification. Only explicitly populated options are included in this dictionary.

>>> print(formatter.input_options.as_dict())
{'exp_mode': 'engineering', 'round_mode': 'sig_fig', 'ndigits': 2, 'superscript': True}

Likewise, the result of populating the options with the global options can be previewed by inspecting the populated_options property.

>>> print(formatter.populated_options)
PopulatedOptions(
 'exp_mode': 'engineering',
 'exp_val': 'auto',
 'round_mode': 'sig_fig',
 'ndigits': 2,
 'upper_separator': '',
 'decimal_separator': '.',
 'lower_separator': '',
 'sign_mode': '-',
 'left_pad_char': ' ',
 'left_pad_dec_place': 0,
 'exp_format': 'standard',
 'extra_si_prefixes': {},
 'extra_parts_per_forms': {},
 'capitalize': False,
 'superscript': True,
 'nan_inf_exp': False,
 'paren_uncertainty': False,
 'left_pad_matching': False,
 'paren_uncertainty_trim': True,
 'pm_whitespace': True,
)
>>> print(formatter.populated_options.exp_format)
standard

The PopulatedOptions class also provides a PopulatedOptions.as_dict method which can be used to construct **kwargs to pass into new Formatter instances.

__init__(...)

Create a new Formatter.

The following checks are performed when creating a new Formatter object:

  • If round_mode is "sig_fig" then ndigits >= 1.

  • exp_val must be consistent with the exponent mode. If exp_val is specified (i.e. not None) and exp_val is not "auto" then

    • exp_val must be 0 for fixed point and percent modes

    • exp_val must be a multiple of 3 for engineering and shifted engineering modes

  • upper_separator may be any of ['', ',', '.', ' ', '_'] but must be different from decimal_separator

  • decimal_separator may be any of ['.', ',']

  • lower_separator may be any of ['', ' ', '_']

Parameters:
  • exp_mode (Literal['fixed_point', 'percent', 'scientific', 'engineering', 'engineering_shifted'] | None) – Specify the exponent formatting mode.

  • exp_val (int | Literal['auto'] | None) – Indicates how the exponent value should be chosen. If an integer is specified, the value must be 0 for fixed point and percent modes, an integer multiple of 3 for engineering and engineering shifted modes. Can be set to "auto".

  • round_mode (Literal['sig_fig', 'dec_place', 'all', 'pdg'] | None) – Indicate how to round numbers during formatting.

  • ndigits (int | None) – Specifies how many digits to use for significant figure or digits-past-the-decimal rounding.

  • upper_separator (Literal['', ',', '.', ' ', '_'] | None) – Separator character to be used to group digits above the decimal symbol.

  • decimal_separator (Literal['.', ','] | None) – Separator character to be used as the decimal symbol. Note that decimal_separator cannot be the same as upper_separator

  • lower_separator (Literal['', ' ', '_'] | None) – Separator character to be used to group digits below the decimal symbol.

  • sign_mode (Literal['-', '+', ' '] | None) – Indicate sign symbol behavior.

  • left_pad_char (Literal[' ', '0', 0] | None) – Indicate whether to pad with zeros or spaces.

  • left_pad_dec_place (int | None) – Positive int indicating the decimal place to which the string will be left padded before the sign symbol. 0 corresponds to the ones place, 1 corresponds to the tens place etc. E.g. left_pad_dec_place=4 will convert 12 into 00012.

  • exp_format (Literal['standard', 'prefix', 'parts_per'] | None) – Indicate how exponents should be presented.

  • extra_si_prefixes (dict[int, Union[str, None]] | None) – Dictionary mapping additional exponent values to si prefixes. Entries overwrite default values. A value of None means that exponent will not be converted.

  • extra_parts_per_forms (dict[int, Union[str, None]] | None) – Dictionary mapping additional exponent values to “parts-per” forms. Entries overwrite default values. A value of None means that exponent will not be converted.

  • capitalize (bool | None) – Flag indicating whether the exponentiation symbol should be upper- or lower-case.

  • superscript (bool | None) – Flag indicating if the exponent string should be converted into superscript notation. E.g. '1.23e+02' is converted to '1.23×10²'

  • nan_inf_exp (bool | None) – Flag indicating whether non-finite numbers such as float('nan') or float('inf') should be formatted with exponent symbols when exponent modes including exponent symbols are selected.

  • paren_uncertainty (bool | None) – Flag indicating if parentheses uncertainty mode (e.g. 12.34(82) instead of 12.34 ± 0.82) should be used.

  • left_pad_matching (bool | None) – Flag indicating if the value or uncertainty should be left padded to ensure they are both left padded to the same digits place.

  • paren_uncertainty_trim (bool | None) – Flag indicating if digit and separator characters to the left of the most significant digit of the uncertainty should be stripped from the uncertainty in parentheses uncertainty mode. E.g. expressing 123.456_78 ± 0.001_23 as 123.456_78(0.001_23) or 123.456_78(123).

  • pm_whitespace (bool | None) – Flag indicating if there should be whitespace surrounding the '±' symbols when formatting. E.g. 123.4±2.3 compared to 123.4 ± 2.3.

  • add_c_prefix (bool | None) – (default None is like False) If True, adds {-2: 'c'} to extra_si_prefixes.

  • add_small_si_prefixes (bool | None) – (default None is like False) If True, adds {-2: 'c', -1: 'd', +1: 'da', +2: 'h'} to extra_si_prefixes.

  • add_ppth_form (bool | None) – (default None is like False) if True, adds {-3: 'ppth'} to extra_parts_per_forms.

__call__(value: Number, uncertainty: Number | None = None, /) FormattedNumber

Format a value or value/uncertainty pair.

Inputs may be str, int, float, or Decimal. float inputs are first converted to str to retrieve the shortest round-trippable decimal representation of the float. For more details see Float Issues. Decimal inputs are normalized upon input. That is, Decimal("1.000") is treated the same as Decimal("1"). Formatted input strings are also accepted. See Formatted Input.

Parameters:
  • value (Decimal | float | int | str) – Value to be formatted.

  • uncertainty (Decimal | float | int | str | None) – Optional uncertainty to be formatted.

property input_options: InputOptions

Return user input options as InputOptions instance.

property populated_options: PopulatedOptions

Return fully populated options as PopulatedOptions instance.

populated_options is re-calculated from input_options and the global options each time it is accessed so that it always reflects the current global options.

class sciform.SciNum(value: Number, uncertainty: Number | None = None, /)

Single number, or number and uncertainty, to be used with FSML.

SciNum objects represent single numbers, or number/uncertainty pairs to be formatted using the sciform format specification mini-language for scientific formatting of numbers. Any options not configured by the format specification will be populated with global default settings at format time.

>>> from sciform import SciNum
>>> num = SciNum(12345.54321)
>>> print(f"{num:!3f}")
12300
>>> print(f"{num:+2.3R}")
+ 12.346E+03
>>> num = SciNum(123456.654321, 0.0234)
>>> print(f"{num:#!2r()}")
0.123456654(23)e+06

Inputs may be str, int, float, or Decimal. float inputs are first converted to str to retrieve the shortest round-trippable decimal representation of the float. For more details see Float Issues. Decimal inputs are normalized upon input. That is, Decimal("1.000") is treated the same as Decimal("1"). Formatted input strings are also accepted. See Formatted Input.

>>> print(f'{SciNum("3.1415e+05"):#!2rp}')
0.31 M
>>> print(f'{SciNum("123456.654321 +/- 0.0234"):!2()}')
123456.654(23)
>>> print(f'{SciNum("123456.654321(23400)"):!2()}')
123456.654(23)
Variables:
  • value – The value to be formatted

  • uncertainty – The optional uncertainty to be formatted

class sciform.FormattedNumber

Representation of a formatted value of value/uncertainty pair.

The FormattedNumber class is returned by sciform formatting methods. In most cases it behaves like a regular python string, but it provides functionality for post-converting the string to various other formats such as latex or html. This allows the formatted number to be displayed in a range of contexts other than e.g. text terminals.

The FormattedNumber class should never be instantiated directly.

as_str() str

Return the string representation of the formatted number.

as_ascii() str

Return the ascii representation of the formatted number.

as_html() str

Return the html representation of the formatted number.

as_latex(*, strip_math_mode: bool = False) str

Return the latex representation of the formatted number.

_repr_html_() str

Hook for HTML display.

_repr_latex_() str

Hook for LaTeX display.

value

The value that was formatted to generate the FormattedNumber.

uncertainty

The uncertainty that was formatted to generate the FormattedNumber.

populated_options

Record of the PopulatedOptions used to generate the FormattedNumber.

Options

class sciform.InputOptions

Dataclass storing user input.

Stores the user input to Formatter, so any keyword arguments that can be passed into Formatter are stored in InputOptions. Any unpopulated options retain the None value. At format time the InputOptions are populated and replaced by a PopulatedOptions instance which necessarily has all attributes populated with meaningful values.

InputOptions instances should only be accessed via the Formatter.input_options() property. They should not be instantiated directly.

>>> from sciform import Formatter
>>> formatter = Formatter(
...     exp_mode="engineering",
...     round_mode="sig_fig",
...     ndigits=2,
...     superscript=True,
... )
>>> print(formatter.input_options.round_mode)
sig_fig
>>> print(formatter.input_options.exp_format)
None
>>> print(formatter.input_options)
InputOptions(
 'exp_mode': 'engineering',
 'round_mode': 'sig_fig',
 'ndigits': 2,
 'superscript': True,
)
>>> print(formatter.input_options.as_dict())
{'exp_mode': 'engineering', 'round_mode': 'sig_fig', 'ndigits': 2, 'superscript': True}
as_dict() dict[str, Any]

Return a dict representation of the InputOptions.

This dict can be passed into Formatter as **kwargs, possibly after modification. This allows for the possibility of constructing new Formatter instances based on old ones. Only explicitly populated attributes are included in the returned dictionary.

class sciform.PopulatedOptions

Dataclass storing fully populated formatting options.

User input options during Formatter initialization are stored in InputOptions instances. But InputOptions instances don’t necessarily have all options populated as required for the formatting algorithm. At formatting time the unpopulated options are populated from the global options. The new resulting options object with all options populated is a PopulatedOptions instances. Note that the global options are stored as a PopulatedOptions instance.

PopulatedOptions instances should only be accessed via the Formatter.populated_options() property. They should not be instantiated directly.

>>> from sciform import Formatter
>>> formatter = Formatter(
...     exp_mode="engineering",
...     round_mode="sig_fig",
...     ndigits=2,
...     superscript=True,
... )
>>> print(formatter.populated_options.round_mode)
sig_fig
>>> print(formatter.populated_options.exp_format)
standard
>>> print(formatter.populated_options)
PopulatedOptions(
 'exp_mode': 'engineering',
 'exp_val': 'auto',
 'round_mode': 'sig_fig',
 'ndigits': 2,
 'upper_separator': '',
 'decimal_separator': '.',
 'lower_separator': '',
 'sign_mode': '-',
 'left_pad_char': ' ',
 'left_pad_dec_place': 0,
 'exp_format': 'standard',
 'extra_si_prefixes': {},
 'extra_parts_per_forms': {},
 'capitalize': False,
 'superscript': True,
 'nan_inf_exp': False,
 'paren_uncertainty': False,
 'left_pad_matching': False,
 'paren_uncertainty_trim': True,
 'pm_whitespace': True,
)
>>> print(formatter.populated_options.as_dict())
{'exp_mode': 'engineering', 'exp_val': 'auto', 'round_mode': 'sig_fig', 'ndigits': 2, 'upper_separator': '', 'decimal_separator': '.', 'lower_separator': '', 'sign_mode': '-', 'left_pad_char': ' ', 'left_pad_dec_place': 0, 'exp_format': 'standard', 'extra_si_prefixes': {}, 'extra_parts_per_forms': {}, 'capitalize': False, 'superscript': True, 'nan_inf_exp': False, 'paren_uncertainty': False, 'left_pad_matching': False, 'paren_uncertainty_trim': True, 'pm_whitespace': True}

Note that PopulatedOptions lacks the add_c_prefix, add_small_si_prefixes and add_ppth_form options present in InputOptions. These options are helper functions which modify the corresponding exponent replacement dictionaries.

>>> formatter = Formatter(
...     exp_mode="engineering",
...     exp_format="prefix",
...     add_c_prefix=True,
... )
>>> print(formatter.input_options)
InputOptions(
 'exp_mode': 'engineering',
 'exp_format': 'prefix',
 'add_c_prefix': True,
)
>>> print(formatter.input_options.extra_si_prefixes)
None
>>> print(formatter.populated_options.extra_si_prefixes)
{-2: 'c'}
as_dict() dict[str, Any]

Return a dict representation of the PopulatedOptions.

This dict can be passed into Formatter as **kwargs, possibly after modification. This allows for the possibility of constructing new Formatter instances based on old ones.

Global Configuration

sciform.get_default_global_options() PopulatedOptions

Return the package default global options.

sciform.get_global_options() PopulatedOptions

Return the current global options.

sciform.set_global_options(...)

Configure the global options.

Accepts the same keyword arguments as Formatter.

sciform.reset_global_options() None

Reset global options to sciform package defaults.

class sciform.GlobalOptionsContext(...)

Temporarily update global options.

New global options are applied when the context is entered and the original global settings are re-applied when the context is exited. Accepts the same keyword arguments as Formatter.