Skip to content

Commit 62b50fb

Browse files
authored
Better flag masks repr (#454)
1 parent 15eeb44 commit 62b50fb

File tree

1 file changed

+50
-15
lines changed

1 file changed

+50
-15
lines changed

cf_xarray/formatting.py

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from functools import partial
33
from typing import Dict, Hashable, Iterable, List
44

5+
import numpy as np
6+
57
STAR = " * "
68
TAB = len(STAR) * " "
79

@@ -147,6 +149,21 @@ def _maybe_panel(textgen, title: str, rich: bool):
147149
return title + ":\n" + text
148150

149151

152+
def find_set_bits(mask, value, repeated_masks):
153+
bitpos = np.arange(8)[::-1]
154+
if mask not in repeated_masks:
155+
if value == 0:
156+
return [-1]
157+
elif value is not None:
158+
return [int(np.log2(value))]
159+
else:
160+
return [int(np.log2(mask))]
161+
else:
162+
allset = bitpos[np.unpackbits(np.uint8(mask)) == 1]
163+
setbits = bitpos[np.unpackbits(np.uint8(mask & value)) == 1]
164+
return [b if abs(b) in setbits else -b for b in allset]
165+
166+
150167
def _format_flags(accessor, rich):
151168
from .accessor import create_flag_dict
152169

@@ -165,6 +182,28 @@ def _format_flags(accessor, rich):
165182
# for f, (m, _) in flag_dict.items()
166183
# if m is not None and m not in repeated_masks
167184
# ]
185+
bit_text = []
186+
value_text = []
187+
for key, (mask, value) in flag_dict.items():
188+
if mask is None:
189+
bit_text.append("✗" if rich else "")
190+
value_text.append(str(value))
191+
continue
192+
bits = find_set_bits(mask, value, repeated_masks)
193+
bitstring = ["."] * 8
194+
if bits == [-1]:
195+
continue
196+
else:
197+
for b in bits:
198+
bitstring[abs(b)] = _format_cf_name("1" if b >= 0 else "0", rich)
199+
text = "".join(bitstring[::-1])
200+
value_text.append(
201+
f"{mask} & {value}"
202+
if key in excl_flags and value is not None
203+
else str(mask)
204+
)
205+
bit_text.append(text if rich else f" / Bit: {text}")
206+
168207
if rich:
169208
from rich import box
170209
from rich.table import Table
@@ -179,29 +218,25 @@ def _format_flags(accessor, rich):
179218

180219
table.add_column("Meaning", justify="left")
181220
table.add_column("Value", justify="right")
182-
table.add_column("Bit?", justify="center")
221+
table.add_column("Bits", justify="center")
183222

184-
for key, (mask, value) in flag_dict.items():
223+
for val, bit, (key, (mask, value)) in zip(
224+
value_text, bit_text, flag_dict.items()
225+
):
185226
table.add_row(
186227
_format_cf_name(key, rich),
187-
str(value) if key in excl_flags else str(mask),
188-
"✗" if key in excl_flags else "✓",
228+
val,
229+
bit,
189230
)
190231

191232
return table
192233

193234
else:
194-
rows = [
195-
f"{TAB}{_format_cf_name(key, rich)}: " f"{_format_varname(value, rich)}"
196-
for key, (mask, value) in flag_dict.items()
197-
if key in excl_flags
198-
]
199-
200-
rows += [
201-
f"{TAB}{_format_cf_name(key, rich)}: " f"Bit {_format_varname(mask, rich)}"
202-
for key, (mask, value) in flag_dict.items()
203-
if key not in excl_flags
204-
]
235+
rows = []
236+
for val, bit, (key, (mask, value)) in zip(
237+
value_text, bit_text, flag_dict.items()
238+
):
239+
rows.append(f"{TAB}{_format_cf_name(key, rich)}: {TAB} {val} {bit}")
205240
return _print_rows("Flag Meanings", rows, rich)
206241

207242

0 commit comments

Comments
 (0)