Skip to content

Commit 3a24235

Browse files
curva_min e max de novo
1 parent 20e8059 commit 3a24235

File tree

8 files changed

+119
-91
lines changed

8 files changed

+119
-91
lines changed

LabIFSC2/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
MCSamples=100_000
99

10-
from ._arrays import arrayM, incertezas, linspaceM, nominais
10+
from ._arrays import (arrayM, curva_max, curva_min, incertezas, linspaceM,
11+
nominais)
1112
from ._medida import (Comparacao, Medida, alterar_monte_carlo_samples,
1213
comparar_medidas)
1314
from ._regressões import (regressao_exponencial, regressao_linear,

LabIFSC2/_arrays.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import numpy as np
66

77
from ._medida import Medida
8+
from ._regressões import Regressao
89
from ._tipagem_forte import obrigar_tipos
910

1011

@@ -55,6 +56,64 @@ def incertezas(arrayMedidas : np.ndarray,unidade:str) -> np.ndarray:
5556
else:
5657
return np.array([medida._incerteza.to(unidade).magnitude for medida in arrayMedidas],dtype=float)
5758

59+
@obrigar_tipos
60+
def _curva_min_max(arrayMedidas : np.ndarray| Regressao,op:str,unidade_y:str,sigmas:float | int) -> np.ndarray:
61+
if isinstance(arrayMedidas,np.ndarray):
62+
if not (isinstance(arrayMedidas[0],Medida)):
63+
raise TypeError('Os valores do array não são Medidas')
64+
elif op=='min':
65+
minima:np.ndarray=nominais(arrayMedidas,unidade_y)-sigmas*incertezas(arrayMedidas,unidade_y)
66+
return minima
67+
elif op=='max':
68+
maxima:np.ndarray=nominais(arrayMedidas,unidade_y)+sigmas*incertezas(arrayMedidas,unidade_y)
69+
return maxima
70+
else:
71+
if arrayMedidas._amostragem_pre_calculada is None:
72+
raise ValueError('A regressão não amostrada ainda')
73+
elif op=='min':
74+
resultado_min:np.ndarray=nominais(arrayMedidas._amostragem_pre_calculada,unidade_y)-sigmas*incertezas(arrayMedidas._amostragem_pre_calculada,unidade_y)
75+
return resultado_min
76+
elif op=='max':
77+
resultado_max:np.ndarray=nominais(arrayMedidas._amostragem_pre_calculada,unidade_y)+sigmas*incertezas(arrayMedidas._amostragem_pre_calculada,unidade_y)
78+
return resultado_max
79+
return np.array([])
80+
81+
@obrigar_tipos
82+
def curva_min(arrayMedidas:np.ndarray | Regressao,unidade_y:str,sigmas:float | int=2) -> np.ndarray:
83+
"""
84+
Calcula a curva mínima de uma série de medidas.
85+
86+
Args:
87+
arrayMedidas (np.ndarray | Regressao): Array de objetos Medida ou objeto Regressao.
88+
unidade_y (str): Unidade da variável dependente.
89+
sigmas (float | int): Número de sigmas para a curva mínima.
90+
91+
Returns:
92+
np.ndarray: Array de valores da curva mínima.
93+
94+
Raises:
95+
TypeError: Se algum dos valores no array não for um objeto Medida.
96+
"""
97+
resultado:np.ndarray= _curva_min_max(arrayMedidas,'min',unidade_y,sigmas)
98+
return resultado
99+
100+
def curva_max(arrayMedidas:np.ndarray | Regressao, unidade_y:str,sigmas:float | int=2) -> np.ndarray:
101+
"""
102+
Calcula a curva máxima de uma série de medidas.
103+
104+
Args:
105+
arrayMedidas (np.ndarray | Regressao): Array de objetos Medida ou objeto Regressao.
106+
unidade_y (str): Unidade da variável dependente.
107+
sigmas (float | int): Número de sigmas para a curva máxima.
108+
109+
Returns:
110+
np.ndarray: Array de valores da curva máxima.
111+
112+
Raises:
113+
TypeError: Se algum dos valores no array não for um objeto Medida.
114+
"""
115+
resultado:np.ndarray= _curva_min_max(arrayMedidas,'max',unidade_y,sigmas)
116+
return resultado
58117

59118
@obrigar_tipos
60119
def linspaceM(a:Real,b:Real,n : int,unidade:str,incertezas:Real) -> np.ndarray:

LabIFSC2/_regressões.py

Lines changed: 42 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from numpy import exp, log, power
1010
from numpy.polynomial import Polynomial
1111

12-
from ._arrays import arrayM, incertezas, nominais
1312
from ._medida import Medida, ureg
1413
from ._tipagem_forte import obrigar_tipos
1514

@@ -38,24 +37,22 @@ def _aplicar_funcao_sem_passar_pelo_sistema_de_unidades(
3837
def _forcar_troca_de_unidade(array_medidas:np.ndarray,unidade:str)-> np.ndarray:
3938
return np.array([Medida(med._nominal.magnitude,unidade,med._incerteza.magnitude,) for med in array_medidas])
4039

41-
class ABCRegressao(ABC):
40+
class Regressao(ABC):
4241

4342
def __init__(self)->None:
44-
self._amostragem_pre_calculada_nominal: np.ndarray = np.array([])
45-
self._amostragem_pre_calculada_incerteza: np.ndarray = np.array([])
43+
self._amostragem_pre_calculada: np.ndarray = np.array([])
4644
self._valores: Iterator = iter([])
47-
self._sigmas:float=2
4845

49-
def _retornar(self,y:np.ndarray|Medida,unidade_y:str)->np.ndarray|Medida:
50-
if isinstance(y,Medida): y=np.array([y])
51-
self._amostragem_pre_calculada_nominal=nominais(y,unidade_y)
52-
self._amostragem_pre_calculada_incerteza=incertezas(y,unidade_y)
53-
if y.size==1: y=y[0]
54-
return self._amostragem_pre_calculada_nominal
46+
def _retornar(self,y:np.ndarray,unidade_y:str)->np.ndarray:
47+
for y_medida in y:
48+
y_medida._histograma=None
49+
self._amostragem_pre_calculada=y
50+
51+
resultado:np.ndarray=np.array([x.nominal(unidade_y) for x in self._amostragem_pre_calculada],dtype=float)
52+
return resultado
5553

56-
def _verificar_tipo_de_x(self,x:np.ndarray|Medida)->None:
57-
if isinstance(x,np.ndarray):
58-
if not isinstance(x[0],Medida):
54+
def _verificar_tipo_de_x(self,x:np.ndarray)->None:
55+
if not isinstance(x[0],Medida):
5956
raise TypeError("x precisa ser um array de medidas ou uma medida \
6057
mesmo que com incerteza 0, pois precisamos das unidades")
6158
return None
@@ -64,7 +61,7 @@ def _verificar_tipo_de_x(self,x:np.ndarray|Medida)->None:
6461
def __repr__(self)->str:...
6562

6663
@abstractmethod
67-
def amostrar(self, x:np.ndarray|Medida,unidade_y:str) -> np.ndarray|Medida:...
64+
def amostrar(self, x:np.ndarray,unidade_y:str) -> np.ndarray:...
6865

6966
def __iter__(self)->Iterator[object]:
7067
return self._valores
@@ -84,43 +81,9 @@ def mudar_intervalo_de_confianca(self,sigmas:Real)->None:
8481

8582
self._sigmas=float(sigmas)
8683

87-
@property
88-
def curva_min(self)->np.ndarray:
89-
"""
90-
Calcula a curva mínima da regressão.
91-
A curva mínima é calculada subtraindo-se o produto dos sigmas pela incerteza da amostragem pré-calculada nominal.
92-
93-
Returns:
94-
np.ndarray: A curva mínima calculada.
95-
96-
Raises:
97-
ValueError: Se a amostragem pré-calculada nominal não estiver disponível.
98-
"""
9984

100-
if not self._amostragem_pre_calculada_nominal.size:
101-
raise ValueError('É necessário amostrar a regressão antes de calcular a curva min')
102-
y:np.ndarray=self._amostragem_pre_calculada_nominal-self._sigmas*self._amostragem_pre_calculada_incerteza
103-
return y
104-
105-
@property
106-
def curva_max(self)->np.ndarray:
107-
"""
108-
Calcula a curva máxima da regressão.
109-
A curva máxima é calculada somando o produto dos sigmas pela incerteza da amostragem pré-calculada nominal.
110-
111-
Returns:
112-
np.ndarray: A curva máxima calculada.
113-
114-
Raises:
115-
ValueError: Se a amostragem pré-calculada nominal não estiver disponível.
116-
"""
117-
if not self._amostragem_pre_calculada_incerteza.size:
118-
raise ValueError('É necessaŕio amostrar a regressão antes de calcular a curva min')
119-
y:np.ndarray=self._amostragem_pre_calculada_nominal+self._sigmas*self._amostragem_pre_calculada_incerteza
120-
return y
12185

122-
123-
class MPolinomio(ABCRegressao):
86+
class MPolinomio(Regressao):
12487
@obrigar_tipos
12588
def __init__(self,coeficientes:np.ndarray):
12689
if not (isinstance(coeficientes[0],Medida)):
@@ -133,22 +96,24 @@ def __init__(self,coeficientes:np.ndarray):
13396
self.grau=len(coeficientes)-1
13497

13598
@obrigar_tipos
136-
def amostrar(self:'MPolinomio', x:np.ndarray | Medida,unidade_y:str) -> np.ndarray | Medida:
99+
def amostrar(self:'MPolinomio', x:np.ndarray,unidade_y:str) -> np.ndarray:
137100
"""
138-
Gera uma amostra de valores y a partir de um conjunto de valores x utilizando os coeficientes do polinômio.
139-
101+
Calcula os valores de um polinômio para um conjunto de entradas x.
140102
Args:
141-
x (np.ndarray | Medida): Conjunto de valores de entrada.
142-
unidade_y (str): Unidade de medida para os valores de saída.
143-
103+
x (np.ndarray): Um array de valores nos quais o polinômio será avaliado.
104+
unidade_y (str): A unidade de medida para os valores calculados do polinômio.
144105
Returns:
145-
np.ndarray | Medida: Valores de saída calculados a partir do polinômio.
106+
np.ndarray: Um array contendo os valores calculados do polinômio nas unidades especificadas.
107+
Raises:
108+
TypeError: Se o tipo de `x` não for np.ndarray.
146109
"""
147110

111+
148112
self._verificar_tipo_de_x(x)
149-
y=Medida(0,unidade_y,0)
150-
for index,coef in enumerate(self._coeficientes):y+=coef*x**(self.grau-index)
151-
return self._retornar(y,unidade_y)
113+
y:Any=Medida(0,unidade_y,0)
114+
for index,coef in enumerate(self._coeficientes):y+=power(x,self.grau-index)*coef
115+
polinomio_calculado:np.ndarray=y
116+
return self._retornar(polinomio_calculado,unidade_y)
152117

153118
def __iter__(self) -> Iterator[Medida]:
154119
return iter(self._coeficientes)
@@ -158,7 +123,7 @@ def __repr__(self) -> str:
158123

159124

160125

161-
class MExponencial(ABCRegressao):
126+
class MExponencial(Regressao):
162127
'''Classe para modelar uma função exponencial
163128
y = a * base^(kx)
164129
'''
@@ -171,26 +136,26 @@ def __init__(self,a:Medida,k:Medida,base:Real):
171136
self._valores=iter((a,k,base))
172137

173138
@obrigar_tipos
174-
def amostrar(self:'MExponencial', x:np.ndarray|Medida,unidade_y:str)->np.ndarray|Medida:
139+
def amostrar(self:'MExponencial', x:np.ndarray,unidade_y:str)->np.ndarray:
175140
"""
176-
Gera uma amostra exponencial baseada nos parâmetros fornecidos.
177-
141+
Gera uma amostra de valores exponenciais com base nos parâmetros fornecidos.
178142
Args:
179-
x (np.ndarray | Medida): O valor ou array de valores para os quais a amostra será gerada.
180-
143+
x (np.ndarray): Um array de valores de entrada.
144+
unidade_y (str): A unidade dos valores de saída.
181145
Returns:
182-
np.ndarray | Medida: A amostra gerada, no mesmo formato do parâmetro de entrada `x`.
183-
146+
np.ndarray: Um array de valores calculados com base na função exponencial.
147+
Raises:
148+
TypeError: Se o tipo de `x` não for np.ndarray.
184149
"""
185150

186151
self._verificar_tipo_de_x(x)
187-
y:np.ndarray|Medida=np.power(float(self.base),(self.expoente*x))*self.cte_multiplicativa
152+
y:np.ndarray=np.power(float(self.base),(self.expoente*x))*self.cte_multiplicativa
188153
return self._retornar(y,unidade_y)
189154

190155
def __repr__(self)->str:
191156
return f'MExponencial(cte_multiplicativa={self.cte_multiplicativa},expoente={self.expoente},base={self.base})'
192157

193-
class MLeiDePotencia(ABCRegressao):
158+
class MLeiDePotencia(Regressao):
194159
@obrigar_tipos
195160
def __init__(self, a: Medida, n: Medida,y_unidade:pint.Quantity):
196161
super().__init__()
@@ -200,20 +165,19 @@ def __init__(self, a: Medida, n: Medida,y_unidade:pint.Quantity):
200165
self._y_unidade=y_unidade
201166

202167
@obrigar_tipos
203-
def amostrar(self:'MLeiDePotencia', x:np.ndarray|Medida,unidade_y:str) -> np.ndarray|Medida:
168+
def amostrar(self:'MLeiDePotencia', x:np.ndarray,unidade_y:str) -> np.ndarray:
204169
"""
205-
Amostra valores com base na lei de potência.
206-
170+
Amostra valores baseados na lei de potência.
207171
Args:
208-
x (np.ndarray | Medida): Valores de entrada para amostragem.
209-
unidade_y (str): Unidade da medida de saída.
210-
172+
x (np.ndarray): Array de valores de entrada.
173+
unidade_y (str): Unidade da variável dependente y.
211174
Returns:
212-
np.ndarray | Medida: Valores amostrados com a unidade especificada.
175+
np.ndarray: Array de valores amostrados com a unidade especificada.
176+
Raises:
177+
ValueError: Se a unidade de x não for compatível com a unidade esperada.
213178
"""
214179

215180
self._verificar_tipo_de_x(x)
216-
if isinstance(x,Medida):x=np.array([x])
217181
unidade_expoente=str((x[0]._nominal**self.potencia._nominal).units)
218182
x=_forcar_troca_de_unidade(x,'')
219183
expoente=x**self.potencia

tests/test_arrayM.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import numpy as np
22
import pytest
33

4-
from LabIFSC2 import Medida, arrayM, incertezas, linspaceM, nominais
4+
from LabIFSC2 import (Medida, arrayM, curva_max, curva_min, incertezas,
5+
linspaceM, nominais)
56

67

78
def test_nominal():
@@ -27,6 +28,15 @@ def test_incerteza_array():
2728
incertezas(np.arange(10),'')
2829

2930

31+
def test_curvamin():
32+
t=np.array([Medida(5,'',0.1),Medida(9,'',2),Medida(11,'',0.5)])
33+
curva_min(t,'')
34+
assert np.array_equal(curva_min(t,''),np.array([4.8,5,10]))
35+
assert np.array_equal(curva_min(t,'',3),np.array([4.7,3,9.5]))
36+
def test_curvamax():
37+
t=np.array([Medida(5,'',0.1),Medida(9,'',2),Medida(11,'',0.5)])
38+
assert np.array_equal(curva_max(t,''),np.array([5.2,13,12]))
39+
assert np.array_equal(curva_max(t,'',3),np.array([5.3,15,12.5]))
3040

3141

3242
def test_linspace():

tests/test_classe_para_regressoes.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ def test_call():
2121
with pytest.raises(TypeError):
2222
polinomio(0)
2323
pontos=lab.linspaceM(0,2,3,'',0)
24-
assert np.isclose(polinomio.amostrar(pontos[0],''), 3)
25-
assert np.isclose(polinomio.amostrar(pontos[1],''),6)
26-
assert np.isclose(polinomio.amostrar(pontos[2],''), 11)
24+
assert np.isclose(polinomio.amostrar(np.array([pontos[0]]),''), 3)
25+
assert np.isclose(polinomio.amostrar(np.array([pontos[1]]),''),6)
26+
assert np.isclose(polinomio.amostrar(np.array([pontos[2]]),''), 11)
2727

2828

2929

tests/test_doc_grafico_fitting.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def test_doc_grafico_fitting():
3131
print(time.time()-tempo)
3232
tempo=time.time()
3333
plt.fill_between(x=nominais(x,unidade_x),
34-
y1=fitting.curva_min,
35-
y2=fitting.curva_max,
34+
y1=curva_min(fitting,unidade_y),
35+
y2=curva_max(fitting,unidade_y),
3636
color='blue',alpha=0.3)
3737
print(time.time()-tempo)
3838
plt.legend()

tests/test_regressoes_exponenciais.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ def test_MExponencial_valores():
1919
def test_MExponencial_amostrar():
2020
a,k,base=lab.Medida(1,'',0.001),lab.Medida(3,'',0.01),np.exp(1)
2121
exponencial=lab._regressões.MExponencial(a,k,base)
22-
x=lab.Medida(2,'',0.1)
23-
exponencial.amostrar(x,'')
2422
x_array=lab.linspaceM(0,1,10,'',0.1)
2523
exponencial.amostrar(x_array,'')
2624

tests/test_regressoes_polinomiais.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,6 @@ def test_MPolinomio_call():
8383
coeficientes = np.array([Medida(2, '', 0.001), Medida(3, '', 0.001), Medida(4, '', 0.001)])
8484
polinomio = lab2._regressões.MPolinomio(coeficientes)
8585
polinomio_number=lambda x: 2*x**2+3*x+4
86-
# Teste de chamada com um número
87-
x = Medida(1, '', 0.001)
88-
resultado = polinomio.amostrar(x,'')
89-
np.isclose(resultado, polinomio_number(1), rtol=1e-3)
9086

9187
# Teste de chamada com um array
9288
x_array = np.array([Medida(1, '', 0.1), Medida(2, '', 0.1), Medida(3, '', 0.1)])

0 commit comments

Comments
 (0)