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

1from math import log10 

2 

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) 

13 

14 

15def gformat(val, length=11): 

16 """Format a number with '%g'-like format. 

17 

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. 

23 

24 The precision will typically be ``length-7``. 

25 

26 Parameters 

27 ---------- 

28 val : float 

29 Value to be formatted. 

30 length : int, optional 

31 Length of output string (default is 11). 

32 

33 Returns 

34 ------- 

35 str 

36 String of specified length. 

37 

38 Notes 

39 ------ 

40 Positive values will have leading blank. 

41 

42 """ 

43 

44 

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 

64 

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 

70 

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 

82 

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}:")