Première interface de visualisation : angulaire + vectorielle
This commit is contained in:
159
MLI_vectorielle.py
Normal file
159
MLI_vectorielle.py
Normal file
@@ -0,0 +1,159 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.widgets import Slider, Button
|
||||
|
||||
PI = np.pi
|
||||
|
||||
N_PTS = 400
|
||||
|
||||
class MLI_plot:
|
||||
"""Classe de graphique MLI"""
|
||||
|
||||
phase = 2*PI/3*np.array([0, 1, 2])
|
||||
phasor = np.linspace(0-phase, 2*PI-phase, N_PTS).T
|
||||
theta = phasor[0,:]
|
||||
|
||||
def __init__(self):
|
||||
# Attributs scalaires
|
||||
self.v_eff = 100
|
||||
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 = [
|
||||
plt.axes([0.1, 0.2, 0.40, 0.6]),
|
||||
plt.axes([0.45, 0.1, 0.55, 0.8]),
|
||||
plt.axes([0.01, 0.1, 0.03, 0.8]),
|
||||
plt.axes([0.1, 0.01, 0.8, 0.03])]
|
||||
self.amp_slider = Slider(
|
||||
ax=self.ax[2],
|
||||
label="Tension\nefficace",
|
||||
valmin=0,
|
||||
valmax=2*self.v_eff,
|
||||
valinit=self.v_eff,
|
||||
orientation="vertical"
|
||||
)
|
||||
self.phi_slider = Slider(
|
||||
ax=self.ax[3],
|
||||
label="Phase [°]",
|
||||
valmin=0,
|
||||
valmax=360,
|
||||
valinit=self.phi,
|
||||
orientation="horizontal"
|
||||
)
|
||||
self.amp_slider
|
||||
self.timegraph_plot = []
|
||||
self.vectorgraph_plot = []
|
||||
self.vectorgraph_arrow = []
|
||||
|
||||
# Tracé du graphique
|
||||
self.setup()
|
||||
self.update()
|
||||
|
||||
return
|
||||
|
||||
def setup(self):
|
||||
self.fig.subplots_adjust(left=0.25)
|
||||
self.setup_timegraph()
|
||||
self.setup_vectorgraph()
|
||||
|
||||
self.amp_slider.on_changed(self.update)
|
||||
self.phi_slider.on_changed(self.update)
|
||||
return
|
||||
|
||||
def setup_timegraph(self):
|
||||
self.timegraph_plot = [self.ax[0].plot(self.theta, self.v_ref[i])[0] for i in range(3)]
|
||||
|
||||
self.ax[0].grid()
|
||||
self.ax[0].set_xlim([0, 2*PI])
|
||||
self.ax[0].set_xticks([i*PI/6 for i in range(13)])
|
||||
self.ax[0].set_xticklabels([str(30*i)+"°" for i in range(13)])
|
||||
self.ax[0].set_xlabel("Angle")
|
||||
self.ax[0].set_ylim([-3*self.v_eff, +3*self.v_eff])
|
||||
self.ax[0].set_ylabel("Tension [V]")
|
||||
|
||||
self.timegraph_plot.append(
|
||||
self.ax[0].plot([self.phi*PI/180, self.phi*PI/180],
|
||||
self.ax[0].get_ylim(),
|
||||
'--r')[0]
|
||||
)
|
||||
self.timegraph_plot.append(
|
||||
self.ax[0].scatter(3*[self.phi*PI/180],
|
||||
[self.v_max*np.cos((self.phi-i*120)*PI/180) for i in range(3)],
|
||||
c=["C0", "C1", "C2"]))
|
||||
|
||||
return
|
||||
|
||||
def setup_vectorgraph(self):
|
||||
self.ax[1] = plt.subplot(122, polar=True)
|
||||
self.ax[1].set_rorigin(0)
|
||||
self.ax[1].set_ylim(0, 3*self.v_eff)
|
||||
|
||||
theta_ticks = np.arange(0, 360, 30)
|
||||
theta_labels = [str(t * (t<=180)
|
||||
+ (t-360) * (t>180)) + "°"
|
||||
for t in theta_ticks]
|
||||
self.ax[1].set_thetagrids(theta_ticks, labels=theta_labels)
|
||||
|
||||
self.vectorgraph_plot.append(self.ax[1].plot(self.theta, self.v_max*np.ones(self.theta.shape), 'r')[0])
|
||||
self.vectorgraph_arrow = [self.ax[1].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=(mpl.transforms.Affine2D().translate((self.phi+i*120)*PI/180, 0)
|
||||
+self.ax[1].transData)
|
||||
)
|
||||
for i in range(3)]
|
||||
return
|
||||
|
||||
def update(self, val=None):
|
||||
self.set_veff(self.amp_slider.val)
|
||||
self.phi = self.phi_slider.val
|
||||
self.update_timegraph()
|
||||
self.update_vectorgraph()
|
||||
return
|
||||
|
||||
def update_timegraph(self):
|
||||
self.timegraph_plot[0].set_ydata(self.v_ref[0])
|
||||
self.timegraph_plot[1].set_ydata(self.v_ref[1])
|
||||
self.timegraph_plot[2].set_ydata(self.v_ref[2])
|
||||
self.timegraph_plot[3].set_xdata(2*[self.phi*PI/180])
|
||||
self.timegraph_plot[4].set_offsets(
|
||||
np.array([3*[self.phi*PI/180],
|
||||
[self.v_max*np.cos((self.phi-i*120)*PI/180) for i in range(3)]]
|
||||
).T
|
||||
)
|
||||
return
|
||||
|
||||
def update_vectorgraph(self):
|
||||
self.vectorgraph_plot[0].set_ydata(self.v_max*np.ones(self.theta.shape))
|
||||
|
||||
for i, arrow in enumerate(self.vectorgraph_arrow):
|
||||
arrow.set_data(dy=self.v_max)
|
||||
arrow.set_transform(mpl.transforms.Affine2D().translate((self.phi+i*120)*PI/180, 0)
|
||||
+self.ax[1].transData)
|
||||
return
|
||||
|
||||
def reset(self, event=None):
|
||||
return
|
||||
|
||||
def set_veff(self, v_eff):
|
||||
self.v_eff = v_eff
|
||||
self.v_max = np.sqrt(2)*v_eff
|
||||
self.v_ref = self.v_max*np.cos(self.phasor)
|
||||
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)
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Execute when the module is not initialized from an import statement.
|
||||
plt.close('all')
|
||||
myMLI_plot = MLI_plot()
|
||||
Reference in New Issue
Block a user