| commit | author | age | ||
| 91fb15 | 1 | from . import Exceptions |
| 5288d6 | 2 | from math import floor, log10 |
| d89217 | 3 | |
| 7b5760 | 4 | STRING = 1 |
| SP | 5 | FLOAT = 2 |
| 6 | ||
| 7 | ||
| 8 | class Variable: | |
| 7e7033 | 9 | def __init__(self, value=None, formatting=None): |
| 993a25 | 10 | self.formatted_value = None |
| 7b5760 | 11 | try: |
| SP | 12 | self.value = float(value) |
| 7e7033 | 13 | self.type = FLOAT |
| 7b5760 | 14 | except (ValueError, TypeError): |
| SP | 15 | self.type = STRING |
| 08b2a2 | 16 | self.value = value |
| SP | 17 | self.formatted_value = value |
| 7b5760 | 18 | if formatting is not None: |
| 33c054 | 19 | self.format_float(formatting) |
| 7b5760 | 20 | self.formatting = formatting |
| 08b2a2 | 21 | |
| SP | 22 | def is_float(self): |
| ce4fc9 | 23 | if self.type == FLOAT: |
| 08b2a2 | 24 | return True |
| SP | 25 | else: |
| 26 | return False | |
| 7b5760 | 27 | |
| 33c054 | 28 | def format_float(self, formatting=None): |
| 993a25 | 29 | if formatting is None: |
| SP | 30 | formatting = self.formatting |
| 31 | formatter = FormatterFactory.get_formatter(formatting) | |
| 32 | self.formatted_value = formatter.getValue(self.value) | |
| 7b5760 | 33 | |
| da1010 | 34 | def format_as_tex(self, formatting=None, glyph=None, unit=None, dollar="$"): |
| 993a25 | 35 | if formatting is None: |
| SP | 36 | formatting = self.formatting |
| 04ee9d | 37 | formatter = FormatterFactory.get_formatter(formatting) |
| da1010 | 38 | if formatting.split()[0] == "prefix": |
| SP | 39 | leading_space = "" |
| 40 | else: | |
| 41 | leading_space = "~" | |
| 5bc997 | 42 | if formatting == "str" or formatting == "string": |
| 04ee9d | 43 | return formatter.toFormat(self.value) |
| 08b2a2 | 44 | elif glyph is None and unit is None: |
| da1010 | 45 | return ("{}{}{}{}").format( |
| SP | 46 | dollar, formatter.toFormat(self.value), leading_space, dollar |
| 08b2a2 | 47 | ) |
| da1010 | 48 | elif glyph is None and unit is not None: |
| SP | 49 | return ("{}{}{}\mathrm{{{}}}{}{}").format( |
| 50 | dollar, formatter.toFormat(self.value), leading_space, unit, dollar | |
| 51 | ) | |
| 52 | elif glyph is not None and unit is None: | |
| 53 | return ("{}{}={}{}{}").format( | |
| 54 | dollar, glyph, formatter.toFormat(self.value), leading_space, dollar | |
| 55 | ) | |
| 56 | else: | |
| 57 | return ("{}{}={}{}\mathrm{{{}}}{}").format( | |
| 58 | dollar, | |
| 59 | glyph, | |
| 60 | formatter.toFormat(self.value), | |
| 61 | leading_space, | |
| 62 | unit, | |
| 63 | dollar, | |
| 64 | ) | |
| 7b5760 | 65 | |
| SP | 66 | def get_formatted_value(self): |
| 993a25 | 67 | return self.formatted_value |
| 08b2a2 | 68 | # if self.type != STRING else self.value |
| 7b5760 | 69 | |
| ef19a9 | 70 | def __str__(self): |
| SP | 71 | return str(self.format_as_tex()) |
| 72 | ||
| 78d798 | 73 | def __repr__(self): |
| SP | 74 | return self.__str__() |
| 75 | ||
| 7b5760 | 76 | |
| d89217 | 77 | class FormatterFactory: |
| 404823 | 78 | @staticmethod |
| SP | 79 | def get_formatter(formatstring): |
| 80 | spl = formatstring.split() | |
| 81 | type = spl[0] | |
| 82 | arglist = spl[1:] | |
| 83 | ||
| 5bc997 | 84 | if type == "sci" or type == "scientific": |
| d89217 | 85 | return SciFloatFormatter(arglist) |
| 5bc997 | 86 | elif type == "str" or type == "string": |
| 993a25 | 87 | return StringFormatter() |
| 5bc997 | 88 | elif type == "eng" or type == "engineering": |
| 993a25 | 89 | return EngFloatFormatter(arglist) |
| 5bc997 | 90 | elif type == "prefix": |
| SP | 91 | return PrefixFloatFormatter(arglist) |
| 92 | elif type == "dec" or type == "decimal": | |
| da1010 | 93 | return EngFloatFormatter(arglist) # fallback to engineering |
| 404823 | 94 | else: |
| SP | 95 | return None |
| 5288d6 | 96 | |
| SP | 97 | @staticmethod |
| 98 | def fexp(f): | |
| 99 | return int(floor(log10(abs(f)))) if f != 0 else 0 | |
| 100 | ||
| 101 | @staticmethod | |
| 102 | def fman(f): | |
| 7b5760 | 103 | return f / 10 ** FormatterFactory.fexp(f) |
| 993a25 | 104 | |
| SP | 105 | |
| 106 | class StringFormatter(FormatterFactory): | |
| 107 | def __init__(self): | |
| 108 | pass | |
| 109 | ||
| 110 | def toFormat(self, string): | |
| 111 | return string | |
| 112 | ||
| 113 | def getValue(self, string): | |
| 114 | return string | |
| 404823 | 115 | |
| SP | 116 | |
| d89217 | 117 | class SciFloatFormatter(FormatterFactory): |
| SP | 118 | def __init__(self, formatparameters): |
| 404823 | 119 | if len(formatparameters) != 1: |
| 91fb15 | 120 | raise Exceptions.WrongParameters("Sci format accept only one argument") |
| 404823 | 121 | self.precision = int(formatparameters[0]) |
| SP | 122 | |
| 123 | def toFormat(self, num): | |
| 124 | try: | |
| 125 | num = float(num) | |
| 126 | except ValueError: | |
| 127 | raise ValueError | |
| 128 | except TypeError: | |
| 129 | raise ValueError | |
| 130 | ||
| 7b5760 | 131 | exp = self.fexp(num) |
| SP | 132 | man = self.fman(num) |
| 78d798 | 133 | if exp == 0: |
| 08b2a2 | 134 | return ( |
| SP | 135 | ("{:." + str(self.precision - 1) + "f}").format(man).replace(".", ",\!") |
| 136 | ) | |
| 78d798 | 137 | else: |
| 08b2a2 | 138 | return ( |
| SP | 139 | ("{:." + str(self.precision - 1) + "f} \cdot 10^{{{}}}") |
| 140 | .format(man, int(exp)) | |
| 141 | .replace(".", ",\!") | |
| 78d798 | 142 | ) |
| d89217 | 143 | |
| 33c054 | 144 | def getValue(self, num): |
| SP | 145 | exp = self.fexp(num) |
| 146 | man = self.fman(num) | |
| 78d798 | 147 | man = ("{:." + str(self.precision - 1) + "f}e{}").format(man, int(exp)) |
| 33c054 | 148 | return float(man) |
| d89217 | 149 | |
| 78d798 | 150 | |
| ce4fc9 | 151 | class EngFloatFormatter(FormatterFactory): |
| d89217 | 152 | def __init__(self, formatparameters): |
| SP | 153 | if len(formatparameters) != 1: |
| 154 | raise Exceptions.WrongParameters("Eng format accept only one argument") | |
| 155 | self.precision = int(formatparameters[0]) | |
| 156 | ||
| ce4fc9 | 157 | def realign3(self, exp, man): |
| SP | 158 | mul = exp % 3 |
| 159 | man = man * 10 ** mul | |
| 160 | exp = exp - mul | |
| 161 | return (exp, man) | |
| 162 | ||
| d89217 | 163 | def toFormat(self, num): |
| SP | 164 | try: |
| 165 | num = float(num) | |
| ce4fc9 | 166 | except ValueError: |
| d89217 | 167 | raise ValueError |
| ce4fc9 | 168 | except TypeError: |
| SP | 169 | raise ValueError |
| 5288d6 | 170 | |
| ce4fc9 | 171 | exp = self.fexp(num) |
| SP | 172 | man = self.fman(num) |
| 173 | (exp, man) = self.realign3(exp, man) | |
| 174 | if exp == 0: | |
| 175 | return ( | |
| 176 | ("{:." + str(self.precision - 1) + "f}").format(man).replace(".", ",\!") | |
| 177 | ) | |
| 178 | else: | |
| 179 | return ( | |
| 180 | ("{:." + str(self.precision - 1) + "f} \cdot 10^{{{}}}") | |
| 181 | .format(man, int(exp)) | |
| 182 | .replace(".", ",\!") | |
| 183 | ) | |
| 184 | ||
| 185 | def getValue(self, num): | |
| 186 | exp = self.fexp(num) | |
| 187 | man = self.fman(num) | |
| 188 | man = ("{:." + str(self.precision - 1) + "f}e{}").format(man, int(exp)) | |
| 189 | return float(man) | |
| 190 | ||
| 191 | ||
| 5bc997 | 192 | class PrefixFloatFormatter(EngFloatFormatter): |
| ce4fc9 | 193 | def __init__(self, formatparameters): |
| SP | 194 | if len(formatparameters) != 1: |
| 195 | raise Exceptions.WrongParameters("Dec format accept only one argument") | |
| 196 | self.precision = int(formatparameters[0]) | |
| 197 | ||
| 198 | def exp2prefix(self, exp): | |
| 199 | prefixes = { | |
| 200 | "24": "Y", | |
| 201 | "21": "Z", | |
| 202 | "18": "E", | |
| 203 | "15": "P", | |
| 204 | "12": "T", | |
| 205 | "9": "G", | |
| 206 | "6": "M", | |
| 207 | "3": "k", | |
| 208 | "-3": "m", | |
| da1010 | 209 | "-6": "\\upmu", |
| SP | 210 | "-9": "n", |
| 211 | "-12": "p", | |
| 212 | "-15": "f", | |
| 213 | "-18": "a", | |
| 214 | "-21": "z", | |
| 215 | "-24": "y", | |
| ce4fc9 | 216 | } |
| SP | 217 | try: |
| 218 | prefix = prefixes[str(exp)] | |
| 219 | except KeyError: | |
| da1010 | 220 | raise Exceptions.PrefixError( |
| SP | 221 | "Could not change exponent " + str(exp) + " into prefix form!" |
| 222 | ) | |
| ce4fc9 | 223 | return prefix |
| SP | 224 | |
| 225 | def toFormat(self, num): | |
| 226 | try: | |
| 227 | num = float(num) | |
| 228 | except ValueError: | |
| 229 | raise ValueError | |
| 230 | except TypeError: | |
| 231 | raise ValueError | |
| 232 | ||
| 233 | exp = self.fexp(num) | |
| 234 | man = self.fman(num) | |
| 235 | (exp, man) = self.realign3(exp, man) | |
| 236 | if exp == 0: | |
| 237 | return ( | |
| da1010 | 238 | ("{:." + str(self.precision - 1) + "f}~").format(man).replace(".", ",\!") |
| ce4fc9 | 239 | ) |
| SP | 240 | else: |
| 241 | prefix = self.exp2prefix(exp) | |
| 242 | return ( | |
| 243 | ("{:." + str(self.precision - 1) + "f}~\mathrm{{{}}}") | |
| 244 | .format(man, prefix) | |
| 245 | .replace(".", ",\!") | |
| 246 | ) | |