1- from math import floor , ceil , trunc , log , log10 , sqrt
1+ import logging
2+ from math import floor , ceil , trunc , log , log10 , sqrt , cos , sin , tan
23from numbers import Number
34
5+ logger = logging .getLogger (__name__ )
6+
7+ try :
8+ import numpy
9+ except ImportError :
10+ numpy = None
11+ logger .warning (
12+ 'Faild to import numpy; sqrt, sin, cos, tan and numpy.ndarray list method wont function' )
13+
14+
15+ def skipif (condition , message ):
16+ def decorator (fnc ):
17+ def wrapper (* args , ** kwargs ):
18+ if condition :
19+ return fnc (* args , ** kwargs )
20+ else :
21+ logger .info (message )
22+ pass
23+ return wrapper
24+ return decorator
25+
26+
427class LabFloatError (Exception ):
528 def __init__ (self , * args ):
629 if args :
730 if args [0 ] == 0 :
8- self .message = "Essa operação não é suportado nesta classe, apenas as operações mencionadas na apostila de Laboratório de Física 2 do IFSC ."
31+ self .message = "This operation is not supported ."
932 elif args [0 ] == 1 :
10- self .message = "Too many args in list, expected '[...,[val,err],...]' got '{0}'" .format (args [1 ])
11- elif isinstance (args [0 ],str ):
12- self .message = "{0}{1}" .format (args [0 ],args [1 ])
33+ self .message = "Too many arguments, expected '(val,err)' or '([(val,err),...])' , got: '{0}'" .format (
34+ args [1 ])
35+ elif args [0 ] == 2 :
36+ self .message = "Mean list and Uncertainty list must have the same size, expected: '[[val1,val2,...,valn],[err1,err2,...,errn]]' , got: '{0}'" .format (
37+ args [1 :])
38+ elif args [0 ] == 3 :
39+ self .message = "Uncertanty or mean list missing, expected: '[[val1,val2,...,valn],[err1,err2,...,errn],...]' , got: '{0}'" .format (
40+ args [1 ])
41+ elif args [0 ] == 4 :
42+ self .message = "Too many arguments, expected: '(precision)' or '(mean precision,err precision)' , got: '{0}'" .format (
43+ args [1 ])
44+ elif isinstance (args [0 ], str ):
45+ self .message = "{0}{1}" .format (args [0 ], args [1 :])
46+ else :
47+ self .message = None
1348 else :
1449 self .message = None
1550
1651 def __str__ (self ):
1752 if self .message :
18- return '{0}' . format ( self .message )
53+ return self .message
1954 else :
20- return 'LabFloatError has been raised'
55+ return 'A generic LabFloatError has been raised'
56+
2157
2258class labfloat :
59+ def __new__ (cls , * args , ** kwargs ):
60+ listlabfloat = kwargs .get ('list' , [])
61+ if args :
62+ if numpy :
63+ if isinstance (args [0 ], (list , numpy .ndarray )):
64+ listlabfloat = args
65+ else :
66+ if isinstance (args [0 ], list ):
67+ listlabfloat = args
68+ if listlabfloat != []:
69+ if len (listlabfloat ) % 2 == 0 :
70+ return cls .list (listlabfloat )
71+ else :
72+ raise LabFloatError (3 , listlabfloat )
73+
74+ return object .__new__ (cls )
75+
2376 def __init__ (self , * args , ** kwargs ):
24- mean = kwargs .get ('mean' ,0.0 )
25- uncertainty = kwargs .get ('uncertainty' ,0.0 )
77+ mean = kwargs .get ('mean' , 0.0 )
78+ uncertainty = kwargs .get ('uncertainty' , 0.0 )
2679
2780 if args :
2881 if len (args ) == 1 :
2982 mean = args [0 ]
3083 elif len (args ) == 2 :
3184 mean = args [0 ]
3285 uncertainty = args [1 ]
33- else :
34- raise LabFloatError ("Too many arguments, expected (val,err) or ([(val,err),...]), got: " , args )
86+ elif len ( args ) > 2 :
87+ raise LabFloatError (1 , args )
3588
3689 self .mean = float (mean )
3790 self .uncertainty = abs (float (uncertainty ))
3891
3992 @classmethod
40- def list (cls ,listargs ):
93+ def list (cls , listargs ):
4194 listlabfloat = []
42- for j in range (len (listargs )):
43- if len (listargs [j ]) == 2 :
44- listlabfloat += [cls (listargs [j ][0 ],listargs [j ][1 ])]
45- elif len (listargs [j ]) == 1 :
46- listlabfloat += [cls (listargs [j ][0 ])]
47- elif len (listargs [j ]) > 2 :
48- raise LabFloatError (1 ,listargs [j ])
95+ for j in range (0 , len (listargs ), 2 ):
96+ if len (listargs [j ]) == len (listargs [j + 1 ]):
97+ colum = []
98+ for k in range (len (listargs [j ])):
99+ colum += [cls (listargs [j ][k ], listargs [j + 1 ][k ])]
100+ listlabfloat += [colum ]
101+ else :
102+ raise LabFloatError (2 , listargs [j ], listargs [j + 1 ])
103+ if len (listlabfloat ) == 1 :
104+ listlabfloat = listlabfloat [0 ]
49105 return (listlabfloat )
50106
51107 def format (self ):
@@ -55,7 +111,7 @@ def format(self):
55111 r = - len (su ) + 1
56112 m = round (self .mean , r )
57113 u = round (self .uncertainty , r )
58- return ((m ,u ))
114+ return ((m , u ))
59115 else :
60116 r = - i
61117 r += 1
@@ -65,32 +121,29 @@ def format(self):
65121 elif su [j + 1 ] == "9" and r > 0 :
66122 m = round (self .mean , r - 1 )
67123 u = round (self .uncertainty , r )
68- return ((m ,u ))
124+ return ((m , u ))
69125 elif su [j ] != "." :
70126 m = round (self .mean , r )
71127 u = round (self .uncertainty , r )
72- return ((m ,u ))
128+ return ((m , u ))
73129
74130 m = round (self .mean , r )
75131 u = round (self .uncertainty , r )
76- return ((m ,u ))
132+ return ((m , u ))
77133
78134 def split (self ):
79- if self .uncertainty == 0 :
80- return (["{:g}" .format (self .mean )])
81- else :
82- m , u = self .format ()
83- return (["{:g}" .format (m ),"{:g}" .format (u )])
84-
85- def tex (self ,* args ,** kwargs ):
135+ m , u = self .format ()
136+ return (["{:g}" .format (m ), "{:g}" .format (u )])
137+
138+ def tex (self , * args , ** kwargs ):
86139 precision = kwargs .get ('precision' )
87140 if args :
88141 if len (args ) == 2 :
89142 precision = args
90143 elif len (args ) > 2 :
91- raise LabFloatError ("Too many arguments, expected: (precision) or (mean precision,err precision) got: " , args )
144+ raise LabFloatError (4 , args )
92145 else :
93- precision = [args [0 ],args [0 ]]
146+ precision = [args [0 ], args [0 ]]
94147
95148 if self .uncertainty == 0 :
96149 if precision :
@@ -106,7 +159,7 @@ def tex(self,*args,**kwargs):
106159 return ("{0}" .format (m ))
107160 else :
108161 if precision :
109- precision = (str (precision [0 ]),str (precision [1 ]))
162+ precision = (str (precision [0 ]), str (precision [1 ]))
110163 m , u = self .format ()
111164 m = eval ("'{:." + precision [0 ]+ "e}'.format(m)" )
112165 u = eval ("'{:." + precision [1 ]+ "e}'.format(u)" )
@@ -125,17 +178,13 @@ def tex(self,*args,**kwargs):
125178 return (r"({0}\, \pm \,{1})" .format (m , u ))
126179
127180 def __str__ (self ):
128- val = self .split ()
129- if len (val ) == 1 :
130- return ("{0}" .format (val [0 ]))
131- else :
132- return ("({0} ± {1})" .format (* val ))
181+ return ("({0} ± {1})" .format (* self .split ()))
133182
134183 def __repr__ (self ):
135184 return self .__str__ ()
136-
185+
137186 def __getitem__ (self , idx ):
138- vals = [self .mean ,self .uncertainty ]
187+ vals = [self .mean , self .uncertainty ]
139188 return vals [idx ]
140189
141190 def __pos__ (self ):
@@ -171,25 +220,25 @@ def __ne__(self, other):
171220 if isinstance (other , Number ):
172221 return abs (self .mean - other ) > 3 * self .uncertainty
173222
174- def __lt__ (self ,other ):
223+ def __lt__ (self , other ):
175224 if isinstance (other , labfloat ):
176225 return self .mean + self .uncertainty < other .mean - other .uncertainty
177226 if isinstance (other , Number ):
178227 return self .mean + self .uncertainty < other
179228
180- def __gt__ (self ,other ):
229+ def __gt__ (self , other ):
181230 if isinstance (other , labfloat ):
182231 return self .mean - self .uncertainty > other .mean + other .uncertainty
183232 if isinstance (other , Number ):
184233 return self .mean - self .uncertainty > other
185234
186- def __le__ (self ,other ):
235+ def __le__ (self , other ):
187236 if isinstance (other , labfloat ):
188237 return self .mean + self .uncertainty <= other .mean + other .uncertainty
189238 if isinstance (other , Number ):
190239 return self .mean + self .uncertainty <= other
191240
192- def __ge__ (self ,other ):
241+ def __ge__ (self , other ):
193242 if isinstance (other , labfloat ):
194243 return self .mean - self .uncertainty >= other .mean - other .uncertainty
195244 if isinstance (other , Number ):
@@ -236,7 +285,7 @@ def __imul__(self, other):
236285
237286 def __div__ (self , other ):
238287 if isinstance (other , labfloat ):
239- return labfloat (self .mean / other .mean , sqrt ((self .uncertainty / other .mean ) ** 2 + (self .mean * other .uncertainty / (other .mean ** 2 )) ** 2 ))
288+ return labfloat (self .mean / other .mean , sqrt ((self .uncertainty / other .mean ) ** 2 + (self .mean * other .uncertainty / (other .mean ** 2 )) ** 2 ))
240289 if isinstance (other , Number ):
241290 return labfloat (self .mean / other , abs (self .uncertainty / other ))
242291
@@ -251,7 +300,7 @@ def __itruediv__(self, other):
251300
252301 def __rdiv__ (self , other ):
253302 if isinstance (other , labfloat ):
254- return labfloat (other .mean / self .mean , sqrt ((other .uncertainty / self .mean ) ** 2 + (other .mean * self .uncertainty / (self .mean ** 2 )) ** 2 ))
303+ return labfloat (other .mean / self .mean , sqrt ((other .uncertainty / self .mean ) ** 2 + (other .mean * self .uncertainty / (self .mean ** 2 )) ** 2 ))
255304 if isinstance (other , Number ):
256305 return labfloat (other / self .mean , abs (other * self .uncertainty / self .mean ** 2 ))
257306
@@ -273,6 +322,22 @@ def __rpow__(self, other):
273322 def __ipow__ (self , other ):
274323 return self .__pow__ (other )
275324
325+ @skipif (numpy , "The sqrt() method is not supported without numpy" )
326+ def sqrt (self ):
327+ return self .__pow__ (0.5 )
328+
329+ @skipif (numpy , "The cos() method is not supported without numpy" )
330+ def cos (self ):
331+ return labfloat (cos (self .mean ), abs (- (sin (self .mean )) * self .uncertainty ))
332+
333+ @skipif (numpy , "The sin() method is not supported without numpy" )
334+ def sin (self ):
335+ return labfloat (sin (self .mean ), abs (cos (self .mean ) * self .uncertainty ))
336+
337+ @skipif (numpy , "The tan() method is not supported without numpy" )
338+ def tan (self ):
339+ return labfloat (tan (self .mean ), sqrt ((cos (self .mean ) ** - 4 ) * self .uncertainty ** 2 ))
340+
276341 def __int__ (self ):
277342 return int (self .mean )
278343
@@ -286,4 +351,4 @@ def __oct__(self):
286351 return oct (self .mean )
287352
288353 def __hex__ (self ):
289- return hex (self .mean )
354+ return hex (self .mean )
0 commit comments