Skip to content

Commit

Permalink
curva_min e max de novo
Browse files Browse the repository at this point in the history
  • Loading branch information
viniciusdutra314 committed Jan 25, 2025
1 parent 20e8059 commit 3a24235
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 91 deletions.
3 changes: 2 additions & 1 deletion LabIFSC2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

MCSamples=100_000

from ._arrays import arrayM, incertezas, linspaceM, nominais
from ._arrays import (arrayM, curva_max, curva_min, incertezas, linspaceM,
nominais)
from ._medida import (Comparacao, Medida, alterar_monte_carlo_samples,
comparar_medidas)
from ._regressões import (regressao_exponencial, regressao_linear,
Expand Down
59 changes: 59 additions & 0 deletions LabIFSC2/_arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import numpy as np

from ._medida import Medida
from ._regressões import Regressao
from ._tipagem_forte import obrigar_tipos


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

@obrigar_tipos
def _curva_min_max(arrayMedidas : np.ndarray| Regressao,op:str,unidade_y:str,sigmas:float | int) -> np.ndarray:
if isinstance(arrayMedidas,np.ndarray):
if not (isinstance(arrayMedidas[0],Medida)):
raise TypeError('Os valores do array não são Medidas')
elif op=='min':
minima:np.ndarray=nominais(arrayMedidas,unidade_y)-sigmas*incertezas(arrayMedidas,unidade_y)
return minima
elif op=='max':
maxima:np.ndarray=nominais(arrayMedidas,unidade_y)+sigmas*incertezas(arrayMedidas,unidade_y)
return maxima
else:
if arrayMedidas._amostragem_pre_calculada is None:
raise ValueError('A regressão não amostrada ainda')
elif op=='min':
resultado_min:np.ndarray=nominais(arrayMedidas._amostragem_pre_calculada,unidade_y)-sigmas*incertezas(arrayMedidas._amostragem_pre_calculada,unidade_y)
return resultado_min
elif op=='max':
resultado_max:np.ndarray=nominais(arrayMedidas._amostragem_pre_calculada,unidade_y)+sigmas*incertezas(arrayMedidas._amostragem_pre_calculada,unidade_y)
return resultado_max
return np.array([])

@obrigar_tipos
def curva_min(arrayMedidas:np.ndarray | Regressao,unidade_y:str,sigmas:float | int=2) -> np.ndarray:
"""
Calcula a curva mínima de uma série de medidas.
Args:
arrayMedidas (np.ndarray | Regressao): Array de objetos Medida ou objeto Regressao.
unidade_y (str): Unidade da variável dependente.
sigmas (float | int): Número de sigmas para a curva mínima.
Returns:
np.ndarray: Array de valores da curva mínima.
Raises:
TypeError: Se algum dos valores no array não for um objeto Medida.
"""
resultado:np.ndarray= _curva_min_max(arrayMedidas,'min',unidade_y,sigmas)
return resultado

def curva_max(arrayMedidas:np.ndarray | Regressao, unidade_y:str,sigmas:float | int=2) -> np.ndarray:
"""
Calcula a curva máxima de uma série de medidas.
Args:
arrayMedidas (np.ndarray | Regressao): Array de objetos Medida ou objeto Regressao.
unidade_y (str): Unidade da variável dependente.
sigmas (float | int): Número de sigmas para a curva máxima.
Returns:
np.ndarray: Array de valores da curva máxima.
Raises:
TypeError: Se algum dos valores no array não for um objeto Medida.
"""
resultado:np.ndarray= _curva_min_max(arrayMedidas,'max',unidade_y,sigmas)
return resultado

@obrigar_tipos
def linspaceM(a:Real,b:Real,n : int,unidade:str,incertezas:Real) -> np.ndarray:
Expand Down
120 changes: 42 additions & 78 deletions LabIFSC2/_regressões.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from numpy import exp, log, power
from numpy.polynomial import Polynomial

from ._arrays import arrayM, incertezas, nominais
from ._medida import Medida, ureg
from ._tipagem_forte import obrigar_tipos

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

class ABCRegressao(ABC):
class Regressao(ABC):

def __init__(self)->None:
self._amostragem_pre_calculada_nominal: np.ndarray = np.array([])
self._amostragem_pre_calculada_incerteza: np.ndarray = np.array([])
self._amostragem_pre_calculada: np.ndarray = np.array([])
self._valores: Iterator = iter([])
self._sigmas:float=2

def _retornar(self,y:np.ndarray|Medida,unidade_y:str)->np.ndarray|Medida:
if isinstance(y,Medida): y=np.array([y])
self._amostragem_pre_calculada_nominal=nominais(y,unidade_y)
self._amostragem_pre_calculada_incerteza=incertezas(y,unidade_y)
if y.size==1: y=y[0]
return self._amostragem_pre_calculada_nominal
def _retornar(self,y:np.ndarray,unidade_y:str)->np.ndarray:
for y_medida in y:
y_medida._histograma=None
self._amostragem_pre_calculada=y

resultado:np.ndarray=np.array([x.nominal(unidade_y) for x in self._amostragem_pre_calculada],dtype=float)
return resultado

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

@abstractmethod
def amostrar(self, x:np.ndarray|Medida,unidade_y:str) -> np.ndarray|Medida:...
def amostrar(self, x:np.ndarray,unidade_y:str) -> np.ndarray:...

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

self._sigmas=float(sigmas)

@property
def curva_min(self)->np.ndarray:
"""
Calcula a curva mínima da regressão.
A curva mínima é calculada subtraindo-se o produto dos sigmas pela incerteza da amostragem pré-calculada nominal.
Returns:
np.ndarray: A curva mínima calculada.
Raises:
ValueError: Se a amostragem pré-calculada nominal não estiver disponível.
"""

if not self._amostragem_pre_calculada_nominal.size:
raise ValueError('É necessário amostrar a regressão antes de calcular a curva min')
y:np.ndarray=self._amostragem_pre_calculada_nominal-self._sigmas*self._amostragem_pre_calculada_incerteza
return y

@property
def curva_max(self)->np.ndarray:
"""
Calcula a curva máxima da regressão.
A curva máxima é calculada somando o produto dos sigmas pela incerteza da amostragem pré-calculada nominal.
Returns:
np.ndarray: A curva máxima calculada.
Raises:
ValueError: Se a amostragem pré-calculada nominal não estiver disponível.
"""
if not self._amostragem_pre_calculada_incerteza.size:
raise ValueError('É necessaŕio amostrar a regressão antes de calcular a curva min')
y:np.ndarray=self._amostragem_pre_calculada_nominal+self._sigmas*self._amostragem_pre_calculada_incerteza
return y


class MPolinomio(ABCRegressao):
class MPolinomio(Regressao):
@obrigar_tipos
def __init__(self,coeficientes:np.ndarray):
if not (isinstance(coeficientes[0],Medida)):
Expand All @@ -133,22 +96,24 @@ def __init__(self,coeficientes:np.ndarray):
self.grau=len(coeficientes)-1

@obrigar_tipos
def amostrar(self:'MPolinomio', x:np.ndarray | Medida,unidade_y:str) -> np.ndarray | Medida:
def amostrar(self:'MPolinomio', x:np.ndarray,unidade_y:str) -> np.ndarray:
"""
Gera uma amostra de valores y a partir de um conjunto de valores x utilizando os coeficientes do polinômio.
Calcula os valores de um polinômio para um conjunto de entradas x.
Args:
x (np.ndarray | Medida): Conjunto de valores de entrada.
unidade_y (str): Unidade de medida para os valores de saída.
x (np.ndarray): Um array de valores nos quais o polinômio será avaliado.
unidade_y (str): A unidade de medida para os valores calculados do polinômio.
Returns:
np.ndarray | Medida: Valores de saída calculados a partir do polinômio.
np.ndarray: Um array contendo os valores calculados do polinômio nas unidades especificadas.
Raises:
TypeError: Se o tipo de `x` não for np.ndarray.
"""


self._verificar_tipo_de_x(x)
y=Medida(0,unidade_y,0)
for index,coef in enumerate(self._coeficientes):y+=coef*x**(self.grau-index)
return self._retornar(y,unidade_y)
y:Any=Medida(0,unidade_y,0)
for index,coef in enumerate(self._coeficientes):y+=power(x,self.grau-index)*coef
polinomio_calculado:np.ndarray=y
return self._retornar(polinomio_calculado,unidade_y)

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



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

@obrigar_tipos
def amostrar(self:'MExponencial', x:np.ndarray|Medida,unidade_y:str)->np.ndarray|Medida:
def amostrar(self:'MExponencial', x:np.ndarray,unidade_y:str)->np.ndarray:
"""
Gera uma amostra exponencial baseada nos parâmetros fornecidos.
Gera uma amostra de valores exponenciais com base nos parâmetros fornecidos.
Args:
x (np.ndarray | Medida): O valor ou array de valores para os quais a amostra será gerada.
x (np.ndarray): Um array de valores de entrada.
unidade_y (str): A unidade dos valores de saída.
Returns:
np.ndarray | Medida: A amostra gerada, no mesmo formato do parâmetro de entrada `x`.
np.ndarray: Um array de valores calculados com base na função exponencial.
Raises:
TypeError: Se o tipo de `x` não for np.ndarray.
"""

self._verificar_tipo_de_x(x)
y:np.ndarray|Medida=np.power(float(self.base),(self.expoente*x))*self.cte_multiplicativa
y:np.ndarray=np.power(float(self.base),(self.expoente*x))*self.cte_multiplicativa
return self._retornar(y,unidade_y)

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

class MLeiDePotencia(ABCRegressao):
class MLeiDePotencia(Regressao):
@obrigar_tipos
def __init__(self, a: Medida, n: Medida,y_unidade:pint.Quantity):
super().__init__()
Expand All @@ -200,20 +165,19 @@ def __init__(self, a: Medida, n: Medida,y_unidade:pint.Quantity):
self._y_unidade=y_unidade

@obrigar_tipos
def amostrar(self:'MLeiDePotencia', x:np.ndarray|Medida,unidade_y:str) -> np.ndarray|Medida:
def amostrar(self:'MLeiDePotencia', x:np.ndarray,unidade_y:str) -> np.ndarray:
"""
Amostra valores com base na lei de potência.
Amostra valores baseados na lei de potência.
Args:
x (np.ndarray | Medida): Valores de entrada para amostragem.
unidade_y (str): Unidade da medida de saída.
x (np.ndarray): Array de valores de entrada.
unidade_y (str): Unidade da variável dependente y.
Returns:
np.ndarray | Medida: Valores amostrados com a unidade especificada.
np.ndarray: Array de valores amostrados com a unidade especificada.
Raises:
ValueError: Se a unidade de x não for compatível com a unidade esperada.
"""

self._verificar_tipo_de_x(x)
if isinstance(x,Medida):x=np.array([x])
unidade_expoente=str((x[0]._nominal**self.potencia._nominal).units)
x=_forcar_troca_de_unidade(x,'')
expoente=x**self.potencia
Expand Down
12 changes: 11 additions & 1 deletion tests/test_arrayM.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import numpy as np
import pytest

from LabIFSC2 import Medida, arrayM, incertezas, linspaceM, nominais
from LabIFSC2 import (Medida, arrayM, curva_max, curva_min, incertezas,
linspaceM, nominais)


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


def test_curvamin():
t=np.array([Medida(5,'',0.1),Medida(9,'',2),Medida(11,'',0.5)])
curva_min(t,'')
assert np.array_equal(curva_min(t,''),np.array([4.8,5,10]))
assert np.array_equal(curva_min(t,'',3),np.array([4.7,3,9.5]))
def test_curvamax():
t=np.array([Medida(5,'',0.1),Medida(9,'',2),Medida(11,'',0.5)])
assert np.array_equal(curva_max(t,''),np.array([5.2,13,12]))
assert np.array_equal(curva_max(t,'',3),np.array([5.3,15,12.5]))


def test_linspace():
Expand Down
6 changes: 3 additions & 3 deletions tests/test_classe_para_regressoes.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ def test_call():
with pytest.raises(TypeError):
polinomio(0)
pontos=lab.linspaceM(0,2,3,'',0)
assert np.isclose(polinomio.amostrar(pontos[0],''), 3)
assert np.isclose(polinomio.amostrar(pontos[1],''),6)
assert np.isclose(polinomio.amostrar(pontos[2],''), 11)
assert np.isclose(polinomio.amostrar(np.array([pontos[0]]),''), 3)
assert np.isclose(polinomio.amostrar(np.array([pontos[1]]),''),6)
assert np.isclose(polinomio.amostrar(np.array([pontos[2]]),''), 11)



Expand Down
4 changes: 2 additions & 2 deletions tests/test_doc_grafico_fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def test_doc_grafico_fitting():
print(time.time()-tempo)
tempo=time.time()
plt.fill_between(x=nominais(x,unidade_x),
y1=fitting.curva_min,
y2=fitting.curva_max,
y1=curva_min(fitting,unidade_y),
y2=curva_max(fitting,unidade_y),
color='blue',alpha=0.3)
print(time.time()-tempo)
plt.legend()
Expand Down
2 changes: 0 additions & 2 deletions tests/test_regressoes_exponenciais.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ def test_MExponencial_valores():
def test_MExponencial_amostrar():
a,k,base=lab.Medida(1,'',0.001),lab.Medida(3,'',0.01),np.exp(1)
exponencial=lab._regressões.MExponencial(a,k,base)
x=lab.Medida(2,'',0.1)
exponencial.amostrar(x,'')
x_array=lab.linspaceM(0,1,10,'',0.1)
exponencial.amostrar(x_array,'')

Expand Down
4 changes: 0 additions & 4 deletions tests/test_regressoes_polinomiais.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,6 @@ def test_MPolinomio_call():
coeficientes = np.array([Medida(2, '', 0.001), Medida(3, '', 0.001), Medida(4, '', 0.001)])
polinomio = lab2._regressões.MPolinomio(coeficientes)
polinomio_number=lambda x: 2*x**2+3*x+4
# Teste de chamada com um número
x = Medida(1, '', 0.001)
resultado = polinomio.amostrar(x,'')
np.isclose(resultado, polinomio_number(1), rtol=1e-3)

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

0 comments on commit 3a24235

Please sign in to comment.