I'm trying to make the chart with multiple parabolas. It's more of a help in mathematics.
I'm trying to make the chart with multiple parabolas. It's more of a help in mathematics.
Graphics in matplotlib require numeric series already filled in NumPy array -
So you can write a function that only cares about the mathematical part itself, taking an 'x' per input, and generating a 'y' that works at the desired intervals, and then it is easy to fill the numerical series with the numpy using your function. So, thinking of the function - you want periodic intervals to create "head-up parabolas" with a narrow aperture, and that below a certain threshold for the parabola values, the value of the function is constant.Interesting here is that the function then will not only get "x" and give you a "y" - it has configuration values - one way to do this is a function inside another - the outside receives the parameters of "threshold", "interval" and "aperture" - and the inside is a function that only receives an ordinate "x" and returns "y". This would not be "necessary" - you can do with a normal only function that receives x and the other three parameters - but then, you have to put some extra logic in the time to generate the values of "y" - since the ways of doing this with numpy usually takes only one parameter.
So let's have something of the form:
def parametrizar(periodo=100, limite=0, abertura=20):
def f_x(x):
# código que usa os 3 parâmetros acima para realmente calcular y
...
return resultado
return f_x
Now, as for the function itself - first the easiest to solve seems to be the "period" - just take the rest of the division of x for the desired period - but I realize that besides that it will be nice to have a shift too - then the first desired peak is "50" with a period of 200, we normalize these values - so that the center of the parabola is "50" and we take the rest of the division by "200" - doing step by step: >
def parametrizar(deslocamento=50, periodo=100, deslocamento_y=1, limite=0.0, abertura=6):
limite = float(limite)
def f_x(x):
# repete valores de x períodicamente:
x1 = x % periodo
# deixa que a abcissa seja '0' onde desejamos o pico
x2 = x1 - deslocamento
# escala o valor "x" antes de elevar ao quadrado de forma
# que os valores para "abertura" sejam mais razoaveis:
x3 = x2 / periodo
# calcula a parábola em si:
y = - abertura * (x3 * x3) + deslocamento_y
# limita os valores baixos ao patamar desejado:
if y < limite:
y = limite
return y
return f_x
And that works. Now just create an array with the numbers y, and use np.vectorize to apply the function - and the parameters can be modified until the final plot is appropriate for what you need:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 500,0.1, dtype=np.float64)
fx = parametrizar(abertura=30, limite=0.5)
y = np.vectorize(fx)(x)
plt.plot(x, y); plt.show()
To construct parabolas I like to use exponential function , basically its parable is a Gaussian function , why do I like exponential function (exp)
? simply because I can control where the parabola will be centered in addition to controlling the width of the window ... to demonstrate I've created a vector (dados)
size 1200
, in some positions I added "peaks"
dados = np.zeros(1200)
dados[70] = 0.9
dados[290] = 0.9
dados[505] = 0.9
dados[720] = 0.9
dados[1000] = 0.9
The rest of the vector is composed of zeros, plot of the vector dados
:
SonowIwanttoinsertaparabolaintoeachofthosepeaks...
Icreatedanauxiliaryvectortohelpmefindtherelativeexponentialvalueoftheparabola:
x=np.linspace(0,1,len(dados))
TheVectorisspacedby1
andhasthesamesizeastheinputvector,nowcomesthecoolpartofthegame,createtheparabolainthepositionsoftheaboveplotpeaks:
np.exp(-np.power(x-pos,float(2.))/(2*np.power(lenKernel,float(2.))))
TheabovefunctioncalculatesaGaussianfunction(parabola):
x=vetorauxiliarlenKernel=larguradajanelapos=posiçãoondeaparábolaserácentrada
Nowyoucanaddthisfunctiontoeverynecessarypeak,theoutputofmycodeproducesthefollowingplot:
Complete code:
import numpy as np
import matplotlib.pyplot as plt
dados = np.zeros(1200)
dados[70] = 0.9
dados[290] = 0.9
dados[505] = 0.9
dados[720] = 0.9
dados[1000] = 0.9
lenKernel =0.020
y=0;
x= np.linspace(0, 1, len(dados))
for i in [(70), (290), (505), (720), (1000)]:
pos=i/float(len(dados))
y=np.exp(-np.power(x - pos, float(2.)) / (2 * np.power(lenKernel, float(2.)))) + y
plt.plot(dados)
plt.plot(y)
plt.show()