How to plot integration equation using Python? - python

I have a few of integration equations and need to convert it into Python. The problem is when I tried to plot a graph according to the equation, some of the plot is not same with the original one.
The first equation is the error probability of authentication in normal operation:
The second equation is the error probability of authentication under MIM attack:
The error probability can be calculated by:
It is noted that:
Supposedly, the graph (original) will be shown like this:
Pe^normal = blue lines
Pe^MIM = red lines
Differences between two error probabilities = green lines
I tried to code it into Python and this is my full codes:
import matplotlib.pyplot as plt
import math
import numpy as np
from scipy.special import iv,modstruve
x=np.arange(0.1,21,1)
x = np.array(x)
t = 0.9
y = (np.exp(t*x/2)*(iv(0, t*x/2) - modstruve(0,t*x/2))-1)/(np.exp(t*x)-1)
z = (np.exp((1-t**2)*x/2)*(iv(0, (1-t**2)*x/2) - modstruve(0,(1-t**2)*x/2))-1)/(np.exp((1-t**2)*x)-1)
z2= y+z
plt.plot(x, y,'o', color='red',label='Normal')
plt.plot(x, z2, '-', color='black', label='MIM')
plt.plot(x, z, marker='s', linestyle='--', color='g', label='DIFF')
plt.xlabel('Mean photon number N')
plt.ylabel('Error probabiity')
plt.scatter(x,y)
plt.text(10, 0.4, 't=0.9', size=12, ha='center', va='center')
plt.ylim([0, 0.5])
plt.xlim([0, 20])
plt.legend()
plt.show()
The graph produce from the code is:
It looks like that my plot is not same with the original one in terms N=0 of Pe^MIM (red line) and differences between two error probabilities (green line).
I hope that anyone may help me to solve this problem.
Thank you.

Related

get_points in sympy plot_implicit

I have been trying of solving an implicit equations using contour plot but I realized it was taking into account the singularities of my equation so I was obtaining wrong graphs. Because of this, I tried sympy.plot_implicit. Fortunately, it works properly but I have not found a proper way to set a label on the graphs produced by sympy.plot_implicit. For this aim, I need to obtain the points used by sympy.plot_implicit for producing its the graphs and use them into matplotlib. This way, I am obtainig correct solutions for my implicit equations and I can easily set labels for the graphs of the solutions. At this moment, I am facing many issues when I try to obtain the point from sympy.plot_implicit, I mean, when I only use sympy.plot there is not any problem but the issues appear when I use sympy.plot_implicit.
I have attached the code, thank you in advance.
Best
import matplotlib.pyplot as plt
import sympy as sp
from sympy.abc import x,y,z
def z(x, y):
return x - y
line = sp.plot(x**2,(x,-1,0), show=False)
#line = sp.plot_implicit(z(x, y), (x, 0, 1), (y, 0, 1), show=False)
x, y = line[0].get_points()
plt.plot(x, y)
plt.show()
You can use the move_sympyplot_to_axes function from Display two Sympy plots as two Matplotlib subplots, adapting one line as explained in its comments.
To get something in the legend, matplotlib's standard approach is to add a label to the specific element. In this case, the implicit area seems to be stored as a polygon inside ax.patches. Such a polygon will be shown as a colored rectangle in the legend. In order to get a line, a custom legend element could be created.
As in this case the solution is represented as a thin polygon and not as a line p1[0].get_points() doesn't work. However, you can extract the polygon's vertices from the matplotlib polygon patch:
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import sympy as sp
from sympy.abc import x, y, z
def move_sympyplot_to_axes(p, ax):
backend = p.backend(p)
backend.ax = ax
backend._process_series(backend.parent._series, ax, backend.parent)
backend.ax.spines['right'].set_color('none')
backend.ax.spines['top'].set_color('none')
backend.ax.spines['bottom'].set_position('zero')
plt.close(backend.fig)
def z(x, y):
return (x ** 2 + y ** 2 - 1) ** 3 - x ** 2 * y ** 3
p1 = sp.plot_implicit(z(x, y), (x, -1.5, 1.5), (y, -1.5, 1.5), show=False)
fig, ax = plt.subplots()
move_sympyplot_to_axes(p1, ax)
# ax.patches[0].set_label("my label")
handles = [Line2D([], [], color=ax.patches[0].get_facecolor())]
ax.legend(handles=handles, labels=["my label"], loc='upper left')
vertices = ax.patches[0].get_path().vertices
ax.plot(vertices[:, 0], vertices[:, 1], ls=':', color='gold', lw=10, alpha=0.5, zorder=0)
plt.show()

How to add addnotation for each point in matplotlib?

I have that code:
for i, j in aa:
plt.plot([xc[i], xc[j]], [yc[i], yc[j]], c='g', zorder=0)
plt.plot(xc[0], yc[0], c='r', marker='s')
plt.scatter(xc[1:], yc[1:],c='b')
And It generate this:
I need to add notation to each point. It shoud be it Y axix value. For example extreme right point is "1". It's possible to do that in simple way in this case? I found only help for totaly different cases and I can't implement it in my example.
import numpy as np
import matplotlib.pyplot as plt
#dummy data
aa = np.arange(10).reshape(5,2)
xc = np.random.rand(10)
yc = np.random.rand(10)
for i, j in aa:
plt.plot([xc[i], xc[j]], [yc[i], yc[j]], c='g', zorder=0)
plt.plot(xc[0], yc[0], c='r', marker='s')
plt.scatter(xc[1:], yc[1:],c='b')
# annotate each datapoint with its y-value, rounded to two decimals.
for x,y in zip(xc, yc):
plt.annotate('{:.2f}'.format(y), xy=[x,y])

Q: how to calculate a slope with measurments error in python?

I don't know much in python or math for that matter but I need to use it for an assignment. I am trying to calculate the slope of a graph and I need to include the error (STD) in the calculation.
Lets say I calculated y for x (the results are shown in the code), and lets say every measurement has a +-2 error (STD), I found how to show it on the graph but didn't found how to include it in the calculation, so right now the STD is 0 and R^2 is 1 which obviously is wrong
How do I calculate and show the inaccuracy of the results?
from matplotlib import pyplot as plt
import numpy as np
from scipy.stats import linregress
x = [1,2,3,4,5,6,7,8,9]
y = [1,2,3,4,5,6,7,8,9]
std = [2,2,2,2,2,2,2,2,2]
plt.errorbar(x, y, yerr=std, fmt='o', color='cadetblue', ecolor='red')
coef = np.polyfit(x,y,1)
poly1d_fn = np.poly1d(coef)
plt.plot(x, poly1d_fn(x), '--k', label='linear fit')
plt.legend(loc='upper left', fontsize=10)
plt.grid(color='black', linestyle='-', linewidth=0.1)
linregress(x,y)
thanks

Fit histogram log scale python

I need to fit a curve with my histogram in python. I did this before with normal histograms, this time I am trying to do the same with a logarithmic plot in x.
This is my code:
import numpy as np
import matplotlib.pyplot as plt
//radius is my np.array
Rmin = min(radius)
Rmax = max(radius)
logmin = np.log(Rmin)
logmax = np.log(Rmax)
bins = 10**(np.arange(logmin,logmax,0.1))
plt.figure()
plt.xscale("log")
plt.hist(radius, bins, color = 'red')
plt.show()
This is showing a gaussian distribution. I am trying to fit a curve with it and what I did is computing the following before the show() command.
(mu, sigma) = np.log(norm.fit((radius)))
y = (mlab.normpdf(np.log(bins), mu, sigma))
plt.plot(bins, y, 'b--', linewidth=2)
My result is a very flattened curve with respect to my distribution.
Can someone help me?
I can not add the whole array r(50000 points), therefore I have added a picture showing my result. See image

Plotting confidence and prediction intervals with repeated entries

I have a correlation plot for two variables, the predictor variable (temperature) on the x-axis, and the response variable (density) on the y-axis. My best fit least squares regression line is a 2nd order polynomial. I would like to also plot confidence and prediction intervals. The method described in this answer seems perfect. However, my dataset (n=2340) has repeated entries for many (x,y) pairs. My resulting plot looks like this:
Here is my relevant code (slightly modified from linked answer above):
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.sandbox.regression.predstd import wls_prediction_std
import statsmodels.formula.api as smf
from statsmodels.stats.outliers_influence import summary_table
d = {'temp': x, 'dens': y}
df = pd.DataFrame(data=d)
x = df.temp
y = df.dens
plt.figure(figsize=(6 * 1.618, 6))
plt.scatter(x,y, s=10, alpha=0.3)
plt.xlabel('temp')
plt.ylabel('density')
# points linearly spaced for predictor variable
x1 = pd.DataFrame({'temp': np.linspace(df.temp.min(), df.temp.max(), 100)})
# 2nd order polynomial
poly_2 = smf.ols(formula='dens ~ 1 + temp + I(temp ** 2.0)', data=df).fit()
# this correctly plots my single 2nd-order poly best-fit line:
plt.plot(x1.temp, poly_2.predict(x1), 'g-', label='Poly n=2 $R^2$=%.2f' % poly_2.rsquared,
alpha=0.9)
prstd, iv_l, iv_u = wls_prediction_std(poly_2)
st, data, ss2 = summary_table(poly_2, alpha=0.05)
fittedvalues = data[:,2]
predict_mean_se = data[:,3]
predict_mean_ci_low, predict_mean_ci_upp = data[:,4:6].T
predict_ci_low, predict_ci_upp = data[:,6:8].T
# check we got the right things
print np.max(np.abs(poly_2.fittedvalues - fittedvalues))
print np.max(np.abs(iv_l - predict_ci_low))
print np.max(np.abs(iv_u - predict_ci_upp))
plt.plot(x, y, 'o')
plt.plot(x, fittedvalues, '-', lw=2)
plt.plot(x, predict_ci_low, 'r--', lw=2)
plt.plot(x, predict_ci_upp, 'r--', lw=2)
plt.plot(x, predict_mean_ci_low, 'r--', lw=2)
plt.plot(x, predict_mean_ci_upp, 'r--', lw=2)
The print statements evaluate to 0.0, as expected.
However, I need single lines for the polynomial best fit line, and the confidence and prediction intervals (rather than the multiple lines I currently have in my plot). Any ideas?
Update:
Following first answer from #kpie, I ordered my confidence and prediction interval arrays according to temperature:
data_intervals = {'temp': x, 'predict_low': predict_ci_low, 'predict_upp': predict_ci_upp, 'conf_low': predict_mean_ci_low, 'conf_high': predict_mean_ci_upp}
df_intervals = pd.DataFrame(data=data_intervals)
df_intervals_sort = df_intervals.sort(columns='temp')
This achieved desired results:
You need to order your predict values based on temperature. I think*
So to get nice curvy lines you will have to use numpy.polynomial.polynomial.polyfit This will return a list of coefficients. You will have to split the x and y data into 2 lists so it fits in the function.
You can then plot this function with:
def strPolynomialFromArray(coeffs):
return("".join([str(k)+"*x**"+str(n)+"+" for n,k in enumerate(coeffs)])[0:-1])
from numpy import *
from matplotlib.pyplot import *
x = linespace(-15,45,300) # your smooth line will be made of 300 smooth pieces
y = exec(strPolynomialFromArray(numpy.polynomial.polynomial.polyfit(xs,ys,degree)))
plt.plot(x , y)
You can look more into plotting smooth lines here just remember all lines are linear splines, becasue continuous curvature is irrational.
I believe that the polynomial fitting is done with least squares fitting (process described here)
Good Luck!

Categories

Resources