Meu objetivo é ajustar a seguinte função aos meus dados:
def P(t, CP, Pan, tau):
P_val = CP + Pan / (1 + t / tau)
P_val = np.where(t >= 900, P_val - 0.8 * np.log(t / 900), P_val)
return P_val
e, em seguida, plotar esta função. No entanto, gostaria de usar duas cores diferentes para os casos t<900
e t>=900
. Assim, decidi plotar as duas partes da curva separadamente, como mostrado abaixo. No entanto, isso resultou em duas curvas com um pequeno espaço entre elas, mesmo ao tentar forçar explicitamente a incorporação de t=900
nas matrizes de tempo usadas para plotar as duas partes da curva. Algo como aqui:
Se forçarmos a inclusão de t=900
, o problema da lacuna pode ser resolvido, mas o resto se desfaz, e obtenho duas curvas plotadas:
Como devo resolver esse problema ou existe uma solução alternativa/outra abordagem (por exemplo, linhas multicoloridas) para obter uma curva contínua com duas cores diferentes, que eu possa usar aqui? De acordo com a documentação do Matplotlib , LineCollection
pode ser útil, mas infelizmente não me sinto confortável com isso matplotlib.collections
.
Aqui está meu código completo:
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
# Data
t2 = np.array([
80,
160,
200,
320,
400,
640,
800,
900,
1000,
1280,
2000,
])
P_t2 = np.array([
4.64,
3.97,
3.79,
3.48,
3.36,
3.18,
3.11,
3.08,
3.06,
3.01,
2.94,
])
t_min = 0
t_cutoff = 7500
mask = (t2 >= t_min) & (t2 <= t_cutoff)
t_filtered = t2[mask]
P_t_filtered = P_t2[mask]
def P(t, CP, Pan, tau):
P_val = CP + Pan / (1 + t / tau)
P_val = np.where(t >= 900, P_val - 0.8 * np.log(t / 900), P_val)
return P_val
initial_guesses = [3.0, 4.0, 50.0]
bounds = ([1.35, 0, 0], [np.inf, np.inf, np.inf])
popt2, pcov2 = curve_fit(P, t_filtered, P_t_filtered, p0=initial_guesses, bounds=bounds, maxfev=5000)
t_fit2 = np.linspace(1, max(t2), 500)
P_fit2 = P(t_fit2, *popt2)
t_fit2_middle = t_fit2[(t_fit2 >= 80) & (t_fit2 <= 900)]
t_fit2_middle = np.append(t_fit2_middle, 900) # include 900 explicitly
t_fit2_over = t_fit2[t_fit2 >= 900]
#t_fit2_over = np.append(t_fit2_over, 900) # include 900 explicitly
P_fit2_middle = P(t_fit2_middle, *popt2)
P_fit2_over1 = P(t_fit2_over, *popt2)
#plotting
plt.plot(t_fit2_middle, P_fit2_middle, color='green', linewidth=2)
plt.plot(t_fit2_over, P_fit2_over1, color='red', linewidth=2)
plt.fill_between(t_fit2_middle, 0, P_fit2_middle, color='green', alpha=0.3, hatch='//')
plt.fill_between(t_fit2_over, P_fit2_over1, color='red', alpha=0.3, hatch='//')
plt.xlim(1, 1250)
plt.ylim(0, 8)
plt.minorticks_on()
ax = plt.gca()
ax.tick_params(labelbottom=False, labelleft=False)
plt.tight_layout()
plt.show()
O problema ocorre na seguinte linha de código:
Isso faz com que o ponto de dados correspondente a 900 apareça no final da segunda parte em vez do início, resultando no gráfico "retornando" à coordenada x 900 na posição final. O problema pode ser resolvido modificando o código para:
O efeito é mostrado na figura abaixo: