|
|
|
@ -3,7 +3,7 @@ |
|
|
|
|
import numpy as np |
|
|
|
|
import matplotlib as mpl |
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
from matplotlib.widgets import Slider, Button |
|
|
|
|
from matplotlib.widgets import Slider, Button, CheckButtons |
|
|
|
|
from matplotlib.axes import Axes |
|
|
|
|
from matplotlib.projections.polar import PolarAxes |
|
|
|
|
|
|
|
|
@ -19,8 +19,8 @@ class TriPlot_TimeAxe(Axes): |
|
|
|
|
phasor = np.linspace(0-phase, 2*PI-phase, N_PTS).T |
|
|
|
|
theta = phasor[0,:] |
|
|
|
|
|
|
|
|
|
def __init__(self, v_max, phi, fig, rect): |
|
|
|
|
Axes.__init__(self, fig, rect) |
|
|
|
|
def __init__(self, v_max, phi, fig, rect, *args, **kwargs): |
|
|
|
|
Axes.__init__(self, fig, rect, *args, **kwargs) |
|
|
|
|
self.timegraph_plot = [] |
|
|
|
|
self.v_max = v_max |
|
|
|
|
self.phi = phi |
|
|
|
@ -36,7 +36,7 @@ class TriPlot_TimeAxe(Axes): |
|
|
|
|
self.set_xticks([i*PI/6 for i in range(13)]) |
|
|
|
|
self.set_xticklabels([str(30*i)+"°" for i in range(13)]) |
|
|
|
|
self.set_xlabel("Phase") |
|
|
|
|
self.set_ylim([-2.2*self.v_max, +2.2*self.v_max]) |
|
|
|
|
self.set_ylim([-1.6*self.v_max, +1.6*self.v_max]) |
|
|
|
|
self.set_ylabel("Tension [V]") |
|
|
|
|
|
|
|
|
|
self.timegraph_plot.append( |
|
|
|
@ -72,6 +72,9 @@ class TriPlot_TimeAxe(Axes): |
|
|
|
|
self.phi = phi |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def set_parameters(self, p): |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TriPlot_VectAxe(PolarAxes): |
|
|
|
|
"""Classe d'axe vectoriel""" |
|
|
|
@ -80,19 +83,20 @@ class TriPlot_VectAxe(PolarAxes): |
|
|
|
|
phasor = np.linspace(0-phase, 2*PI-phase, N_PTS).T |
|
|
|
|
theta = phasor[0,:] |
|
|
|
|
|
|
|
|
|
def __init__(self, v_max, phi, fig, rect): |
|
|
|
|
PolarAxes.__init__(self, fig, rect) |
|
|
|
|
def __init__(self, v_max, phi, fig, rect, *args, **kwargs): |
|
|
|
|
PolarAxes.__init__(self, fig, rect, *args, **kwargs) |
|
|
|
|
self.plot_list = [] |
|
|
|
|
self.arrow_list = [] |
|
|
|
|
self.v_max = v_max |
|
|
|
|
self.phi = phi |
|
|
|
|
self.v_ref = np.zeros(self.phasor.shape) |
|
|
|
|
self.parameters = {"projection": False} |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def setup(self): |
|
|
|
|
self.get_figure().add_axes(self) |
|
|
|
|
self.set_rorigin(0) |
|
|
|
|
self.set_ylim(0, 2.2*self.v_max) |
|
|
|
|
self.set_ylim(0, 1.6*self.v_max) |
|
|
|
|
|
|
|
|
|
theta_ticks = np.arange(0, 360, 30) |
|
|
|
|
theta_labels = [str(t * (t<=180) |
|
|
|
@ -105,8 +109,20 @@ class TriPlot_VectAxe(PolarAxes): |
|
|
|
|
self.theta, self.v_max*np.ones(self.theta.shape), 'r' |
|
|
|
|
)[0] |
|
|
|
|
) |
|
|
|
|
for i in range(3): |
|
|
|
|
self.plot_list.append( |
|
|
|
|
self.plot( |
|
|
|
|
[(self.phi-i*120)*PI/180, |
|
|
|
|
PI*(1-np.sign(np.cos((self.phi-i*120)*PI/180)))], |
|
|
|
|
[self.v_max, |
|
|
|
|
self.v_max*np.abs(np.cos((self.phi-i*120)*PI/180))], |
|
|
|
|
ls = ':', |
|
|
|
|
visible=self.parameters["projection"] |
|
|
|
|
)[0] |
|
|
|
|
) |
|
|
|
|
self.arrow_list = [ |
|
|
|
|
self.arrow(0, 0, 0, self.v_max, |
|
|
|
|
self.arrow(0, 0, |
|
|
|
|
0, self.v_max, |
|
|
|
|
lw=2, head_width=0.05, head_length=self.v_max/15, |
|
|
|
|
color="C"+str(i), length_includes_head=True, |
|
|
|
|
transform=( |
|
|
|
@ -116,7 +132,26 @@ class TriPlot_VectAxe(PolarAxes): |
|
|
|
|
+ self.transData |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
for i in range(3)] |
|
|
|
|
for i in range(3) |
|
|
|
|
] + [ |
|
|
|
|
self.arrow(0, 0, |
|
|
|
|
0, self.v_max*np.abs(np.cos((self.phi-i*120)*PI/180)), |
|
|
|
|
lw=1, head_width=0.05, head_length=self.v_max/15, |
|
|
|
|
color="C"+str(i), length_includes_head=True, |
|
|
|
|
transform=( |
|
|
|
|
mpl.transforms.Affine2D().translate( |
|
|
|
|
PI*(1-np.sign( |
|
|
|
|
np.cos((self.phi-i*120)*PI/180) |
|
|
|
|
) |
|
|
|
|
)/2, |
|
|
|
|
0 |
|
|
|
|
) |
|
|
|
|
+ self.transData |
|
|
|
|
), |
|
|
|
|
visible=self.parameters["projection"] |
|
|
|
|
) |
|
|
|
|
for i in range(3) |
|
|
|
|
] |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def refresh(self): |
|
|
|
@ -125,13 +160,33 @@ class TriPlot_VectAxe(PolarAxes): |
|
|
|
|
self.theta.shape |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
for i, plot in enumerate(self.plot_list[1:4]): |
|
|
|
|
plot.set_visible(self.parameters.get("projection")) |
|
|
|
|
plot.set_xdata( |
|
|
|
|
[(self.phi-i*120)*PI/180, |
|
|
|
|
PI*(1-np.sign(np.cos((self.phi-i*120)*PI/180)))/2] |
|
|
|
|
) |
|
|
|
|
plot.set_ydata( |
|
|
|
|
[self.v_max, |
|
|
|
|
self.v_max*np.abs(np.cos((self.phi-i*120)*PI/180))] |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
for i, arrow in enumerate(self.arrow_list): |
|
|
|
|
arrow.set_data(dy=self.v_max) |
|
|
|
|
arrow.set_transform( |
|
|
|
|
for i in range(3): |
|
|
|
|
self.arrow_list[i].set_data(dy=self.v_max) |
|
|
|
|
self.arrow_list[i].set_transform( |
|
|
|
|
mpl.transforms.Affine2D().translate( |
|
|
|
|
(self.phi-i*120)*PI/180, 0) |
|
|
|
|
+ self.transData |
|
|
|
|
) |
|
|
|
|
for i in range(3, 6): |
|
|
|
|
self.arrow_list[i].set_visible(self.parameters["projection"]) |
|
|
|
|
self.arrow_list[i].set_data( |
|
|
|
|
dy=self.v_max*np.abs(np.cos((self.phi-i*120)*PI/180)) |
|
|
|
|
) |
|
|
|
|
self.arrow_list[i].set_transform( |
|
|
|
|
mpl.transforms.Affine2D().translate( |
|
|
|
|
(self.phi-i*120)*PI/180, 0 |
|
|
|
|
) |
|
|
|
|
PI*(1-np.sign(np.cos((self.phi-i*120)*PI/180)))/2, 0) |
|
|
|
|
+ self.transData |
|
|
|
|
) |
|
|
|
|
return |
|
|
|
@ -144,6 +199,10 @@ class TriPlot_VectAxe(PolarAxes): |
|
|
|
|
def set_phi(self, phi): |
|
|
|
|
self.phi = phi |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def set_parameters(self, p): |
|
|
|
|
self.parameters["projection"] = p.get("projection", False) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TriPlot: |
|
|
|
@ -155,38 +214,47 @@ class TriPlot: |
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
|
# Attributs scalaires |
|
|
|
|
self.v_eff = 100 |
|
|
|
|
self.v_eff = 220 |
|
|
|
|
self.v_max = np.sqrt(2)*self.v_eff |
|
|
|
|
self.v_ref = np.zeros(self.phasor.shape) |
|
|
|
|
self.phi = 30 |
|
|
|
|
|
|
|
|
|
# Attributs graphiques |
|
|
|
|
self.fig = plt.figure() |
|
|
|
|
self.ax = [ |
|
|
|
|
TriPlot_TimeAxe(self.v_max, self.phi, self.fig, [0.1, 0.2, 0.4, 0.6]), |
|
|
|
|
TriPlot_VectAxe(self.v_max, self.phi, self.fig, [0.5, 0.2, 0.5, 0.6]), |
|
|
|
|
plt.axes([0.01, 0.1, 0.03, 0.8]), |
|
|
|
|
plt.axes([0.1, 0.01, 0.8, 0.03])] |
|
|
|
|
self.timeaxe = TriPlot_TimeAxe(self.v_max, self.phi, |
|
|
|
|
self.fig, [0.1, 0.2, 0.4, 0.6]) |
|
|
|
|
self.vectaxe = TriPlot_VectAxe(self.v_max, self.phi, |
|
|
|
|
self.fig, [0.5, 0.2, 0.5, 0.6]) |
|
|
|
|
self.axes = [self.timeaxe, self.vectaxe] |
|
|
|
|
self.amp_slider = Slider( |
|
|
|
|
ax=self.ax[2], |
|
|
|
|
ax=plt.axes([0.01, 0.1, 0.03, 0.8]), |
|
|
|
|
label="Tension\nefficace", |
|
|
|
|
valmin=0, |
|
|
|
|
valmax=2*self.v_eff, |
|
|
|
|
valmax=1.5*self.v_eff, |
|
|
|
|
valinit=self.v_eff, |
|
|
|
|
orientation="vertical" |
|
|
|
|
) |
|
|
|
|
self.phi_slider = Slider( |
|
|
|
|
ax=self.ax[3], |
|
|
|
|
ax=plt.axes([0.1, 0.01, 0.8, 0.03]), |
|
|
|
|
label="Phase [°]", |
|
|
|
|
valmin=0, |
|
|
|
|
valmax=360, |
|
|
|
|
valinit=self.phi, |
|
|
|
|
orientation="horizontal" |
|
|
|
|
) |
|
|
|
|
self.amp_slider |
|
|
|
|
self.vectorgraph_plot = [] |
|
|
|
|
self.vectorgraph_arrow = [] |
|
|
|
|
|
|
|
|
|
self.reset_button = Button( |
|
|
|
|
ax=plt.axes([0.95, 0.01, 0.03, 0.03]), |
|
|
|
|
label='Reset', |
|
|
|
|
hovercolor='0.975' |
|
|
|
|
) |
|
|
|
|
self.parameters_check = CheckButtons( |
|
|
|
|
ax=plt.axes([0.9, 0.8, 0.1, 0.2]), |
|
|
|
|
labels=["Projection"] |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
self.sliders = [self.amp_slider, self.phi_slider] |
|
|
|
|
self.parameters = {} |
|
|
|
|
|
|
|
|
|
# Tracé du graphique |
|
|
|
|
self.setup() |
|
|
|
|
self.refresh() |
|
|
|
@ -194,42 +262,50 @@ class TriPlot: |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def setup(self): |
|
|
|
|
self.fig.subplots_adjust(left=0.25) |
|
|
|
|
self.ax[0].setup() |
|
|
|
|
self.ax[1].setup() |
|
|
|
|
|
|
|
|
|
self.amp_slider.on_changed(self.refresh) |
|
|
|
|
self.phi_slider.on_changed(self.refresh) |
|
|
|
|
for axe in self.axes: |
|
|
|
|
axe.setup() |
|
|
|
|
for slider in self.sliders: |
|
|
|
|
slider.on_changed(self.refresh) |
|
|
|
|
self.reset_button.on_clicked(self.reset) |
|
|
|
|
self.parameters_check.on_clicked(self.refresh) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def refresh(self, val=None): |
|
|
|
|
self.set_veff(self.amp_slider.val) |
|
|
|
|
self.set_phi(self.phi_slider.val) |
|
|
|
|
self.ax[0].refresh() |
|
|
|
|
self.ax[1].refresh() |
|
|
|
|
self.set_parameters(self.parameters_check.get_status()) |
|
|
|
|
for axe in self.axes: |
|
|
|
|
axe.refresh() |
|
|
|
|
self.fig.canvas.draw() |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def reset(self, event=None): |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def set_veff(self, v_eff): |
|
|
|
|
self.set_vmax(np.sqrt(2)*v_eff) |
|
|
|
|
for slider in self.sliders: |
|
|
|
|
slider.reset() |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def set_vmax(self, v_max): |
|
|
|
|
self.v_max = v_max |
|
|
|
|
self.v_eff = v_max/np.sqrt(2) |
|
|
|
|
self.v_ref = self.v_max*np.cos(self.phasor) |
|
|
|
|
for axe in self.axes: |
|
|
|
|
axe.set_vmax(self.v_max) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
self.ax[0].set_vmax(self.v_max) |
|
|
|
|
self.ax[1].set_vmax(self.v_max) |
|
|
|
|
|
|
|
|
|
def set_veff(self, v_eff): |
|
|
|
|
self.set_vmax(np.sqrt(2)*v_eff) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def set_phi(self, phi): |
|
|
|
|
self.phi = phi |
|
|
|
|
self.ax[0].set_phi(self.phi) |
|
|
|
|
self.ax[1].set_phi(self.phi) |
|
|
|
|
for axe in self.axes: |
|
|
|
|
axe.set_phi(self.phi) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def set_parameters(self, p): |
|
|
|
|
self.parameters["projection"] = p[0] |
|
|
|
|
for axe in self.axes: |
|
|
|
|
axe.set_parameters(self.parameters) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|