Coverage for /Users/Newville/Codes/xraylarch/larch/utils/gformat.py: 65%
49 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
1from math import log10
3def getfloat_attr(obj, attr, length=11):
4 """Format an attribute of an object for printing."""
5 val = getattr(obj, attr, None)
6 if val is None:
7 return 'unknown'
8 if isinstance(val, int):
9 return f'{val}'
10 if isinstance(val, float):
11 return gformat(val, length=length).strip()
12 return repr(val)
15def gformat(val, length=11):
16 """Format a number with '%g'-like format.
18 Except that:
19 a) the length of the output string will be of the requested length.
20 b) positive numbers will have a leading blank.
21 b) the precision will be as high as possible.
22 c) trailing zeros will not be trimmed.
24 The precision will typically be ``length-7``.
26 Parameters
27 ----------
28 val : float
29 Value to be formatted.
30 length : int, optional
31 Length of output string (default is 11).
33 Returns
34 -------
35 str
36 String of specified length.
38 Notes
39 ------
40 Positive values will have leading blank.
42 """
45 if val is None or isinstance(val, bool):
46 return f'{repr(val):>{length}s}'
47 try:
48 expon = int(log10(abs(val)))
49 except (OverflowError, ValueError):
50 expon = 0
51 length = max(length, 7)
52 form = 'e'
53 prec = length - 7
54 ab_expon = abs(expon)
55 if ab_expon > 99:
56 prec -= 1
57 elif ((expon >= 0 and expon < (prec+4))
58 or (expon <= -1 and -expon < (prec-2))
59 or (expon <= -1 and prec < 5 and abs(expon)<3 )):
60 form = 'f'
61 prec += 4
62 if expon > 0:
63 prec -= expon
65 def fmt(val, length, prec, form):
66 out = f'{val:{length}.{prec}{form}}'
67 if form == 'e' and 'e+0' in out or 'e-0' in out:
68 out = f'{val:{length+1}.{prec+1}{form}}'.replace('e-0', 'e-').replace('e+0', 'e+')
69 return out
71 prec += 1
72 out = '_'*(length+2)
73 while len(out) > length:
74 prec -= 1
75 out = fmt(val, length, prec, form)
76 if '_' in out:
77 out = fmt(val, length, prec, form)
78 while len(out) < length:
79 prec += 1
80 out = fmt(val, length, prec, form)
81 return out
83def test_gformat():
84 for x in range(-10, 12):
85 for a in [0.2124312134, 0.54364253, 0.812312, .96341312124, 1.028456789]:
86 v = a*(10**(x))
87 print(f" :{gformat(v, length=13):s}::{gformat(v, length=12):s}::{gformat(v, length=11):s}::{gformat(v, length=10):s}::{gformat(v, length=9):s}::{gformat(v, length=8):s}:")