Skip to content

Commit

Permalink
Bugfix/parts per zero exp (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
jagerber48 authored Jan 21, 2024
2 parents 7df43d0 + bdcc7a0 commit c2f0f13
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 57 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,8 @@ jobs:
pytest --cov --doctest-glob="*.rst"
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: ${{ matrix.python-version }}
fail_ci_if_error: true
verbose: true
14 changes: 14 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,26 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.
Unreleased
----------

Added
^^^^^

* Added separate flags for code coverage reports for each python
version.

Changed
^^^^^^^

* **[BREAKING]** Renamed ``fill_char`` to ``left_pad_char``.
[`#126 <https://github.com/jagerber48/sciform/issues/126>`_]

Fixed
^^^^^

* Fixed a bug where value/uncertainty pairs formatted in the
``"parts_per"`` format with zero exponent would appear with redundant
parentheses, e.g. ``"(1.2 ± 0.1)"``.
[`#130 <https://github.com/jagerber48/sciform/issues/130>`_]

----

0.32.3 (2024-01-11)
Expand Down
51 changes: 18 additions & 33 deletions src/sciform/format_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from sciform.modes import (
AutoDigits,
AutoExpVal,
ExpDriver,
ExpFormatEnum,
ExpModeEnum,
RoundModeEnum,
Expand Down Expand Up @@ -420,32 +419,25 @@ def get_val_unc_exp(
unc: Decimal,
exp_mode: ExpModeEnum,
input_exp: int,
) -> tuple[int, ExpDriver]:
) -> int:
"""Get exponent for value/uncertainty formatting."""
if val.is_finite() and unc.is_finite():
if abs(val) >= unc:
exp_driver_type = ExpDriver.VAL
exp_driver_val = val
else:
exp_driver_type = ExpDriver.UNC
exp_driver_val = unc
elif val.is_finite():
exp_driver_type = ExpDriver.VAL
else:
exp_driver_type = ExpDriver.UNC

if exp_driver_type is ExpDriver.VAL:
exp_driver_val = val
elif exp_driver_type is ExpDriver.UNC:
else:
exp_driver_val = unc
else: # pragma: no cover
raise ValueError

_, exp_val, _ = get_mantissa_exp_base(
exp_driver_val,
exp_mode=exp_mode,
input_exp=input_exp,
)

return exp_val, exp_driver_type
return exp_val


def get_val_unc_top_digit(
Expand All @@ -469,11 +461,10 @@ def get_val_unc_top_digit(
return new_top_digit


def get_val_unc_mantissa_exp_strs(
def get_val_unc_mantissa_strs(
val_mantissa_exp_str: str,
unc_mantissa_exp_str: str,
exp_driver_type: ExpDriver,
) -> tuple[str, str, str]:
) -> tuple[str, str]:
"""Break val/unc mantissa/exp strings into mantissa strings and an exp string."""
# Optional parentheses needed to handle (nan)e+00 case
mantissa_exp_pattern = re.compile(
Expand All @@ -485,15 +476,7 @@ def get_val_unc_mantissa_exp_strs(
unc_match = mantissa_exp_pattern.match(unc_mantissa_exp_str)
unc_mantissa_str = unc_match.group("mantissa_str")

if exp_driver_type is ExpDriver.VAL:
exp_str = val_match.group("exp_str")
elif exp_driver_type is ExpDriver.UNC:
exp_str = unc_match.group("exp_str")
else:
msg = f"Invalid exp_driver_type: {exp_driver_type}."
raise ValueError(msg)

return val_mantissa_str, unc_mantissa_str, exp_str
return val_mantissa_str, unc_mantissa_str


def construct_val_unc_str( # noqa: PLR0913
Expand Down Expand Up @@ -573,14 +556,16 @@ def construct_val_unc_exp_str( # noqa: PLR0913
extra_parts_per_forms=extra_parts_per_forms,
)

"""
"1234(12)" val_unc_str along with exp_str "k" will be formatted as
"1234(12) k whereas 1234(12) with exp_str "e+03" will be
formatted as (1234(12))e+03.
"1234 ± 12" will be formatted with parentheses as "(1234 ± 12) k" or
"(1234 ± 12)e+03"
"""
if paren_uncertainty and not re.match(r"^[eEbB][+-]\d+$", exp_str):
if exp_str == "":
val_unc_exp_str = f"{val_unc_str}{exp_str}"
elif paren_uncertainty and not re.match(r"^[eEbB][+-]\d+$", exp_str):
"""
"1234(12)" val_unc_str along with exp_str "k" will be formatted as
"1234(12) k whereas 1234(12) with exp_str "e+03" will be
formatted as (1234(12))e+03.
"1234 ± 12" will be formatted with parentheses as "(1234 ± 12) k" or
"(1234 ± 12)e+03"
"""
val_unc_exp_str = f"{val_unc_str}{exp_str}"
else:
val_unc_exp_str = f"({val_unc_str}){exp_str}"
Expand Down
9 changes: 4 additions & 5 deletions src/sciform/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
get_mantissa_exp_base,
get_round_digit,
get_val_unc_exp,
get_val_unc_mantissa_exp_strs,
get_val_unc_mantissa_strs,
get_val_unc_top_digit,
latex_translate,
round_val_unc,
Expand Down Expand Up @@ -205,7 +205,7 @@ def format_val_unc(val: Decimal, unc: Decimal, options: RenderedOptions) -> str:
use_pdg_sig_figs=options.pdg_sig_figs,
)

exp_val, exp_driver_type = get_val_unc_exp(
exp_val = get_val_unc_exp(
val_rounded,
unc_rounded,
options.exp_mode,
Expand Down Expand Up @@ -265,10 +265,9 @@ def format_val_unc(val: Decimal, unc: Decimal, options: RenderedOptions) -> str:
val_mantissa_exp_str = format_num(val_rounded, val_format_options)
unc_mantissa_exp_str = format_num(unc_rounded, unc_format_options)

(val_mantissa_str, unc_mantissa_str, exp_str) = get_val_unc_mantissa_exp_strs(
val_mantissa_str, unc_mantissa_str = get_val_unc_mantissa_strs(
val_mantissa_exp_str,
unc_mantissa_exp_str,
exp_driver_type,
)

val_unc_str = construct_val_unc_str(
Expand All @@ -283,7 +282,7 @@ def format_val_unc(val: Decimal, unc: Decimal, options: RenderedOptions) -> str:
paren_uncertainty_separators=options.paren_uncertainty_separators,
)

if exp_str is not None:
if val.is_finite() or unc.is_finite() or options.nan_inf_exp:
val_unc_exp_str = construct_val_unc_exp_str(
val_unc_str=val_unc_str,
exp_val=exp_val,
Expand Down
7 changes: 0 additions & 7 deletions src/sciform/modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,6 @@ class ExpFormatEnum(str, Enum):
PARTS_PER = "parts_per"


class ExpDriver(Enum):
"""Exponent drive Enum. Used for value/uncertainty formatting."""

VAL = "val"
UNC = "unc"


T = TypeVar("T", bound=Enum)


Expand Down
10 changes: 0 additions & 10 deletions tests/test_invalid_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
get_sign_str,
get_top_digit,
get_top_digit_binary,
get_val_unc_mantissa_exp_strs,
parse_standard_exp_str,
)
from sciform.formatting import format_non_finite
Expand Down Expand Up @@ -248,12 +247,3 @@ def test_mode_str_to_enum_fail(self):
"eng",
modes.ExpModeEnum,
)

def test_get_val_unc_mantissa_exp_str_invalid_driver(self):
self.assertRaises(
ValueError,
get_val_unc_mantissa_exp_strs,
"e+00",
"e+00",
"val",
)
12 changes: 12 additions & 0 deletions tests/test_val_unc_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,18 @@ def test_prefix(self):
),
],
),
(
(1.23, 0.1),
[
(
Formatter(
exp_mode="scientific",
exp_format="parts_per",
),
"1.2 ± 0.1",
),
],
),
]

self.run_val_unc_formatter_cases(cases_list)
Expand Down

0 comments on commit c2f0f13

Please sign in to comment.