Is it possible to generate proper Root Locus Plots with Python 3? - python-3.x

I am trying to generate root locus plots via Python 3, but the graphs that Python produces don't seem to be complete.
Here is the system to be implemented for the Root Locus;
Here is my code for the Root Locus plot;
import numpy as np
from matplotlib import pyplot as plt
import control
%matplotlib
G = control.TransferFunction((1, 1.5), (1, 11, 10, 0))
rlist, klist = control.rlocus(G)
plt.show()
And here is the graph I get;
But from the textbook I'm using, this is the plot that they have;
Is there a way to get Python to provide a plot which is closer the actual solution, or is this the best approximation possible with Python right now?

Try this,
import numpy as np
from matplotlib import pyplot as plt
import control
G = control.TransferFunction((1, 1.5), (1, 11, 10, 0))
rlist, klist = control.rlocus(G, kvect=np.linspace(100.0, -100.0, num=1000))
plt.show()
Output:
You can choose a more optimal kvect range depending on your transfer function.
kvect (list or ndarray, optional) – List of gains to use in computing diagram
Source: control.root_locus Documentation

Related

Nyquist Plot using Python with certain parameters

I am trying to draw the Nyquist plot using python but I have no clue what all parameters are required by python to do plot that curve.
Here is a glimpse of the parameters that I have:
Channel_ID,Step_ID,Cycle_ID,Test_Time,EIS_Test_ID,EIS_Data_Point,Frequency,Zmod,Zphz,Zreal,Zimg,OCV,AC_Amp_RMS
4,7,1,36966.3072,0,0,200015.6,0.4933,70.9969,0.1606,0.4664,3.6231,0.35
4,7,1,36966.3072,0,1,158953.1,0.412,70.8901,0.1349,0.3893,3.6231,0.35
4,7,1,36966.3072,0,2,126234.4,0.3437,70.7115,0.1135,0.3244,3.6231,0.35
4,7,1,36966.3072,0,3,100265.6,0.2869,70.6312,0.0951,0.2706,3.6231,0.35
4,7,1,36966.3072,0,4,79640.63,0.2364,70.2418,0.0799,0.2224,3.6231,0.35
and above are the values to those parameters.
Based on the above parameters that are
Test_Time, Frequency, Zmod, Zphz, Zreal, Zimg, OCV, AC_Amp_RMS where Zmod is the absolute value of Zreal and Zimg, I need to draw a Nyquist plot. I have no clue how these parameters could be used for the plot.
PS: I tried to plot the curve by making use of the real and imaginary part that is Zimg and Zreal
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
train_df = pd.read_csv("above_data_with_around_100_rows.csv")
plt.figure()
plt.plot(train_df["Zreal"], train_df["Zimg"], "b")
plt.plot(train_df["Zreal"], -train_df["Zimg"], "r")
plt.show()
Can this be the useful for Nyquist plot?

Python matplotlib custom colorbar for plotted lines with manually assigned colors

I'm trying to define a colorbar for the following type of plot.
import matplotlib.pyplot as plt
import numpy as np
for i in np.arange(0,10,0.1):
plt.plot(range(10),np.ones(10)*i,c=[i/10.,0.5,0.25])
plt.show()
This is just a simplified version of my actual data, but basically, I'd like a series of lines plotted and colored by another variable with a colorbar key. This is easy to do in scatter, but I can't get scatter to plot connected lines. Points are too clunky. I know this sounds like basic stuff, but I'm having a helluva time finding a simple solution ... what obvious solution am I missing?
You can build a custom color map and a mappable from it, then pass to colorbar:
from matplotlib.cm import ScalarMappable
from matplotlib.colors import Normalize
import matplotlib.colors as mcolors
color_list = [(i/10, 0.5,0.25) for i in np.arange(0,10,0.1)]
cmap = mcolors.LinearSegmentedColormap.from_list("my_colormap", color_list)
cmappable = ScalarMappable(norm=Normalize(0,10), cmap=cmap)
plt.figure(figsize=(10,10))
for j,i in enumerate(np.arange(0,10,0.1)):
plt.plot(range(10),np.ones(10)*i,c=color_list[j])
plt.colorbar(cmappable)
plt.show()
Output:

How to set figure size in lmplot seaborn? [duplicate]

How do I change the size of my image so it's suitable for printing?
For example, I'd like to use to A4 paper, whose dimensions are 11.7 inches by 8.27 inches in landscape orientation.
You can also set figure size by passing dictionary to rc parameter with key 'figure.figsize' in seaborn set method:
import seaborn as sns
sns.set(rc={'figure.figsize':(11.7,8.27)})
Other alternative may be to use figure.figsize of rcParams to set figure size as below:
from matplotlib import rcParams
# figure size in inches
rcParams['figure.figsize'] = 11.7,8.27
More details can be found in matplotlib documentation
You need to create the matplotlib Figure and Axes objects ahead of time, specifying how big the figure is:
from matplotlib import pyplot
import seaborn
import mylib
a4_dims = (11.7, 8.27)
df = mylib.load_data()
fig, ax = pyplot.subplots(figsize=a4_dims)
seaborn.violinplot(ax=ax, data=df, **violin_options)
Note that if you are trying to pass to a "figure level" method in seaborn (for example lmplot, catplot / factorplot, jointplot) you can and should specify this within the arguments using height and aspect.
sns.catplot(data=df, x='xvar', y='yvar',
hue='hue_bar', height=8.27, aspect=11.7/8.27)
See https://github.com/mwaskom/seaborn/issues/488 and Plotting with seaborn using the matplotlib object-oriented interface for more details on the fact that figure level methods do not obey axes specifications.
first import matplotlib and use it to set the size of the figure
from matplotlib import pyplot as plt
import seaborn as sns
plt.figure(figsize=(15,8))
ax = sns.barplot(x="Word", y="Frequency", data=boxdata)
You can set the context to be poster or manually set fig_size.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
np.random.seed(0)
n, p = 40, 8
d = np.random.normal(0, 2, (n, p))
d += np.log(np.arange(1, p + 1)) * -5 + 10
# plot
sns.set_style('ticks')
fig, ax = plt.subplots()
# the size of A4 paper
fig.set_size_inches(11.7, 8.27)
sns.violinplot(data=d, inner="points", ax=ax)
sns.despine()
fig.savefig('example.png')
This can be done using:
plt.figure(figsize=(15,8))
sns.kdeplot(data,shade=True)
In addition to elz answer regarding "figure level" methods that return multi-plot grid objects it is possible to set the figure height and width explicitly (that is without using aspect ratio) using the following approach:
import seaborn as sns
g = sns.catplot(data=df, x='xvar', y='yvar', hue='hue_bar')
g.fig.set_figwidth(8.27)
g.fig.set_figheight(11.7)
This shall also work.
from matplotlib import pyplot as plt
import seaborn as sns
plt.figure(figsize=(15,16))
sns.countplot(data=yourdata, ...)
For my plot (a sns factorplot) the proposed answer didn't works fine.
Thus I use
plt.gcf().set_size_inches(11.7, 8.27)
Just after the plot with seaborn (so no need to pass an ax to seaborn or to change the rc settings).
See How to change the image size for seaborn.objects for a solution with the new seaborn.objects interface from seaborn v0.12, which is not the same as seaborn axes-level or figure-level plots.
Adjusting the size of the plot depends if the plot is a figure-level plot like seaborn.displot, or an axes-level plot like seaborn.histplot. This answer applies to any figure or axes level plots.
See the the seaborn API reference
seaborn is a high-level API for matplotlib, so seaborn works with matplotlib methods
Tested in python 3.8.12, matplotlib 3.4.3, seaborn 0.11.2
Imports and Data
import seaborn as sns
import matplotlib.pyplot as plt
# load data
df = sns.load_dataset('penguins')
sns.displot
The size of a figure-level plot can be adjusted with the height and/or aspect parameters
Additionally, the dpi of the figure can be set by accessing the fig object and using .set_dpi()
p = sns.displot(data=df, x='flipper_length_mm', stat='density', height=4, aspect=1.5)
p.fig.set_dpi(100)
Without p.fig.set_dpi(100)
With p.fig.set_dpi(100)
sns.histplot
The size of an axes-level plot can be adjusted with figsize and/or dpi
# create figure and axes
fig, ax = plt.subplots(figsize=(6, 5), dpi=100)
# plot to the existing fig, by using ax=ax
p = sns.histplot(data=df, x='flipper_length_mm', stat='density', ax=ax)
Without dpi=100
With dpi=100
# Sets the figure size temporarily but has to be set again the next plot
plt.figure(figsize=(18,18))
sns.barplot(x=housing.ocean_proximity, y=housing.median_house_value)
plt.show()
Some tried out ways:
import seaborn as sns
import matplotlib.pyplot as plt
ax, fig = plt.subplots(figsize=[15,7])
sns.boxplot(x="feature1", y="feature2",data=df) # where df would be your dataframe
or
import seaborn as sns
import matplotlib.pyplot as plt
plt.figure(figsize=[15,7])
sns.boxplot(x="feature1", y="feature2",data=df) # where df would be your dataframe
The top answers by Paul H and J. Li do not work for all types of seaborn figures. For the FacetGrid type (for instance sns.lmplot()), use the size and aspect parameter.
Size changes both the height and width, maintaining the aspect ratio.
Aspect only changes the width, keeping the height constant.
You can always get your desired size by playing with these two parameters.
Credit: https://stackoverflow.com/a/28765059/3901029

Matplotlib.plot not found

I installed Matplotlib via Anaconda from here: https://anaconda.org/conda-forge/matplotlib
I used the very first command in Anaconda prompt.
But when I tried to plot from python (Spyder) as the following, I get the message:
ModuleNotFoundError: No module named 'matplotlib.plot'
import numpy as np
import matplotlib.plot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.plot(x,y)
I have installed numpy, pandas and such using the same method and they work well.
How can I fix this?
Thank you so much.
matplotlib.pyplot is a state-based interface to matplotlib. pyplot is mainly intended for interactive plots and simple cases of programmatic plot generation. Therefore, whenever trying to work with graphs and what is commonly known and informally often referred as matplotlib you should import matplotlib.pyplot as plt:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.plot(x,y)

Matplotlib function visualtization changing with precision

So I was trying to map out some math functions in 3d using matplotlib when I noticed something... The 3d plot suddenly changed (more like broke) when I tried to fix a previous issue wherein I was encountering some 'missing surface' - a gap in the plot. The main question is this -- Is the 3d plot not showing the two peaks on higher precision due to some inherent computing limitations of Axes3d or some other reason? Also a secondary question -- Why am I encountering 'missing surfaces' near +1.25 and -1.25 in lower precision plot?
I have tried googling for it and referred a few posts but nothing came ot except more questions.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
X=np.arange(-2,+2,0.025)
## Use np.arange(-5,+5,0.25) to experience the 'surface loss' I mention but otherwise correct 2 spike plot at each of (0,-1) and (0,+1) for both X and Y
Y=np.arange(-2,+2,0.025)
X,Y=np.meshgrid(X,Y)
R=1+X**2-Y**2
S=R**2+4*(X**2)*(Y**2)
Z=R/S
fig=plt.figure()
ax=Axes3D(fig)
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=cm.viridis,norm=mpl.colors.Normalize(vmin=-1.,vmax=1.))
##NORMALIZE Was essential to get the proper color range
plt.show()
plt.savefig('art3d.jpeg',bbox_inches='tight')
plt.savefig('art3d.svg',bbox_inches='tight')
The ideal result should be like this (shows the func and the plot)
https://i.stack.imgur.com/kVnYc.png
The two plots I'm getting could be seen when the code is run as I can't seem to add images presumably because of low reputation :(
Any and all help is appreciated.Thanks in advance.
First note that the function in use is different from the wolfram alpha output. So let's use the function shown in the screenshot. Then you can limit the data to the range you want to show.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
X = np.arange(-2,+2,0.025)
Y=np.arange(-2,+2,0.025)
X,Y=np.meshgrid(X,Y)
Z = -2*X*Y / ((2*X*Y)**2 + (X**2 - Y**2 + 1)**2)
Z[(Z < -1)] = -1
Z[(Z > 1)] = 1
fig=plt.figure()
ax=Axes3D(fig)
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=cm.viridis,norm=mpl.colors.Normalize(vmin=-1.,vmax=1.))
plt.show()

Resources