Commit 3f746eb1 authored by Hafiz Emin Kosar's avatar Hafiz Emin Kosar
Browse files

- figsizes can be changed in notebooks now

parent cc8ecfbc
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University # Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget %matplotlib widget
from ient_nb.ient_signals import * from ient_nb.ient_signals import *
from src.laplace.laplace_plot import pzPoint, pzPlot from src.laplace.laplace_plot import pzPoint, pzPlot
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec import matplotlib.gridspec as gridspec
import numpy as np import numpy as np
t = np.linspace(-6,6,1024) t = np.linspace(-6,6,1024)
f = np.linspace(-6,6,1024) f = np.linspace(-6,6,1024)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<div> <div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;"> <img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div> </div>
# Laplace-Transformation # Laplace-Transformation
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen. Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Interaktive Demo ## Interaktive Demo
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
In der interaktiven Demo kann eine Laplace-Übertragungsfunktion vom Typ In der interaktiven Demo kann eine Laplace-Übertragungsfunktion vom Typ
$$ $$
H(p) = H_0 \frac{ H(p) = H_0 \frac{
\prod\limits_{q=1}^Q \left( p-p_{\mathrm{N},q} \right) \prod\limits_{q=1}^Q \left( p-p_{\mathrm{N},q} \right)
}{ }{
\prod\limits_{r=1}^R \left( p-p_{\mathrm{P},r} \right) \prod\limits_{r=1}^R \left( p-p_{\mathrm{P},r} \right)
} }
$$ $$
mit $Q$ Nullstellen $p_{\mathrm{N},q}$ und $R$ Polstellen $p_{\mathrm{P},r}$ betrachtet und verändert werden. Dargestellt ist ein Pol-/Nullstellendiagramm, sowie die zugehörige Impulsantwort und Übertragungsfunktion. mit $Q$ Nullstellen $p_{\mathrm{N},q}$ und $R$ Polstellen $p_{\mathrm{P},r}$ betrachtet und verändert werden. Dargestellt ist ein Pol-/Nullstellendiagramm, sowie die zugehörige Impulsantwort und Übertragungsfunktion.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
pzp = pzPlot() fig = plt.figure(figsize=(10, 10/16*9))
pzp = pzPlot(fig)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Anleitung ### Anleitung
Es können vier verschiedene Filter (Butterworth, Sprungfunktion, Sinus und Cosinus) voreingestellt werden. Über den Schieberegler kann der Wert für $H_0$ angepasst werden. Wird der Butterworthfilter gewählt, ist hier der Grad $P$ einstellbar. Es können vier verschiedene Filter (Butterworth, Sprungfunktion, Sinus und Cosinus) voreingestellt werden. Über den Schieberegler kann der Wert für $H_0$ angepasst werden. Wird der Butterworthfilter gewählt, ist hier der Grad $P$ einstellbar.
Bei *Modus* kann die Position des Konvergenzbereichs geändert werden, indem die entsprechende Option eingestellt und im Pol-/Nullstellendiagramm auf den Bereich geklickt wird, der der neue Konvergenzbereich sein soll. Bei *Modus* kann die Position des Konvergenzbereichs geändert werden, indem die entsprechende Option eingestellt und im Pol-/Nullstellendiagramm auf den Bereich geklickt wird, der der neue Konvergenzbereich sein soll.
Ähnlich können auch Pol- und Nullstellen hinzugefügt oder gelöscht werden. Bei *Typ* wird eingestellt, ob es sich um eine Pol- oder Nullstelle handeln soll und unter *Modus* wird dann *hinzufügen* oder *löschen* ausgewählt. Durch Klicken im Pol-/Nullstellendiagramm können nun Pol- und Nullstellen hinzugefügt oder gelöscht werden. Entsprechend ändern sich dann auch die zugehörige Impulsantwort und Übertragungsfunktion. Ähnlich können auch Pol- und Nullstellen hinzugefügt oder gelöscht werden. Bei *Typ* wird eingestellt, ob es sich um eine Pol- oder Nullstelle handeln soll und unter *Modus* wird dann *hinzufügen* oder *löschen* ausgewählt. Durch Klicken im Pol-/Nullstellendiagramm können nun Pol- und Nullstellen hinzugefügt oder gelöscht werden. Entsprechend ändern sich dann auch die zugehörige Impulsantwort und Übertragungsfunktion.
### Aufgaben ### Aufgaben
* Teste verschiedene Einstellungen und ihre Auswirkungen auf Impulsantwort und Übertragungsfunktion. Welche Auswirkung hat das Ändern von $H_0$? Wie sehen die voreingestellten Funktionen aus? * Teste verschiedene Einstellungen und ihre Auswirkungen auf Impulsantwort und Übertragungsfunktion. Welche Auswirkung hat das Ändern von $H_0$? Wie sehen die voreingestellten Funktionen aus?
* Entferne alle Pole und Nullstellen. Wie sieht die Impulsantwort aus? Welche Auswirkung hat das Ändern von $H_0$? * Entferne alle Pole und Nullstellen. Wie sieht die Impulsantwort aus? Welche Auswirkung hat das Ändern von $H_0$?
* Erstelle eine Polstelle auf der imaginären Achse. Welche Auswirkung hat diese auf die Übertragungsfunktion? * Erstelle eine Polstelle auf der imaginären Achse. Welche Auswirkung hat diese auf die Übertragungsfunktion?
* Erstelle ein Pol-/Nullstellendiagram mit mehreren möglichen Polstellen. Ändere den Konvergenzbereich. Wann existiert eine Übertragungsfunktion? * Erstelle ein Pol-/Nullstellendiagram mit mehreren möglichen Polstellen. Ändere den Konvergenzbereich. Wann existiert eine Übertragungsfunktion?
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT). This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT).
Please attribute the work as follows: Please attribute the work as follows:
*Emin Kosar, Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2019, Institut für Nachrichtentechnik, RWTH Aachen University. *Emin Kosar, Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2019, Institut für Nachrichtentechnik, RWTH Aachen University.
......
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University # Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget %matplotlib widget
from ient_nb.ient_signals import * from ient_nb.ient_signals import *
from ient_nb.ient_plots import * from ient_nb.ient_plots import *
from ient_nb.ient_transforms import * from ient_nb.ient_transforms import *
from src.z_transform.z_transform import zPlot from src.z_transform.z_transform import zPlot
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec import matplotlib.gridspec as gridspec
import numpy as np import numpy as np
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<div> <div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;"> <img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div> </div>
# z-Transformation # z-Transformation
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen. Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### plotting pole zero plot in z-plane ### plotting pole zero plot in z-plane
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
n = np.linspace(-5, 5, 11) n = np.linspace(-5, 5, 11)
pp = np.array([0.5, 2]); pz = np.array([0]) pp = np.array([0.5, 2]); pz = np.array([0])
roc = np.array([0.5, 2]) roc = np.array([0.5, 2])
#roc = np.array([-b, np.inf]) #roc = np.array([-b, np.inf])
fig, axs = plt.subplots(1, 2) fig, axs = plt.subplots(1, 2, figsize=(8, 8/ient_fig_aspect))
ax = axs[0] ax = axs[0]
ax.set_aspect('equal', adjustable='datalim')
zroc = ient_plot_zroc(ax, roc) zroc = ient_plot_zroc(ax, roc)
ax.plot(np.real(pp), np.imag(pp), **ient_style_poles); ax.plot(np.real(pp), -np.imag(pp), **ient_style_poles) ax.plot(np.real(pp), np.imag(pp), **ient_style_poles); ax.plot(np.real(pp), -np.imag(pp), **ient_style_poles)
ax.plot(np.real(pz), np.imag(pz), **ient_style_zeros); ax.plot(np.real(pz), -np.imag(pz), **ient_style_zeros) ax.plot(np.real(pz), np.imag(pz), **ient_style_zeros); ax.plot(np.real(pz), -np.imag(pz), **ient_style_zeros)
ax.set_xlabel(r'$\rightarrow \mathrm{Re}$'); ax.set_ylabel(r'$\uparrow \mathrm{Im}$'); ax.set_xlabel(r'$\rightarrow \mathrm{Re}$'); ax.set_ylabel(r'$\uparrow \mathrm{Im}$');
ax.set_xlim(np.min(n), np.max(n)); ax.set_ylim(ax.get_xlim()); ient_grid(ax); ient_axis(ax) ax.set_xlim(np.min(n), np.max(n)); ax.set_ylim(ax.get_xlim()); ient_grid(ax); ient_axis(ax)
ax = axs[1] ax = axs[1]
h_n = ient_iz_ht(n, 1, pp, pz, roc= roc) h_n = ient_iz_ht(n, 1, pp, pz, roc= roc)
ax.set_xlabel(r'$\rightarrow \mathrm{n}$'); ax.set_ylabel(r'$\uparrow \mathrm{h(n)}$'); ax.set_xlabel(r'$\rightarrow \mathrm{n}$'); ax.set_ylabel(r'$\uparrow \mathrm{h(n)}$');
ax.set_xlim(np.min(n), np.max(n)); ient_update_ylim(ax, h_n, 0.19, 1e05); ient_grid(ax); ient_axis(ax) ax.set_xlim(np.min(n), np.max(n)); ient_update_ylim(ax, h_n, 0.19, 1e05); ient_grid(ax); ient_axis(ax)
ient_stem(ax, n, np.real(h_n)) ient_stem(ax, n, np.real(h_n))
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Interaktive Demo ## Interaktive Demo
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
zp = zPlot() fig = plt.figure(figsize=(10, 10/16*9))
zp = zPlot(fig)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Anleitung ### Anleitung
Es können vier verschiedene Filter (Butterworth, Sprungfunktion, Sinus und Cosinus) voreingestellt werden. Über den Schieberegler kann der Wert für $H_0$ angepasst werden. Wird der Butterworthfilter gewählt, ist hier der Grad $P$ einstellbar. Es können vier verschiedene Filter (Butterworth, Sprungfunktion, Sinus und Cosinus) voreingestellt werden. Über den Schieberegler kann der Wert für $H_0$ angepasst werden. Wird der Butterworthfilter gewählt, ist hier der Grad $P$ einstellbar.
Bei *Modus* kann die Position des Konvergenzbereichs geändert werden, indem die entsprechende Option eingestellt und im Pol-/Nullstellendiagramm auf den Bereich geklickt wird, der der neue Konvergenzbereich sein soll. Bei *Modus* kann die Position des Konvergenzbereichs geändert werden, indem die entsprechende Option eingestellt und im Pol-/Nullstellendiagramm auf den Bereich geklickt wird, der der neue Konvergenzbereich sein soll.
Ähnlich können auch Pol- und Nullstellen hinzugefügt oder gelöscht werden. Bei *Typ* wird eingestellt, ob es sich um eine Pol- oder Nullstelle handeln soll und unter *Modus* wird dann *hinzufügen* oder *löschen* ausgewählt. Durch Klicken im Pol-/Nullstellendiagramm können nun Pol- und Nullstellen hinzugefügt oder gelöscht werden. Entsprechend ändern sich dann auch die zugehörige Impulsantwort und Übertragungsfunktion. Ähnlich können auch Pol- und Nullstellen hinzugefügt oder gelöscht werden. Bei *Typ* wird eingestellt, ob es sich um eine Pol- oder Nullstelle handeln soll und unter *Modus* wird dann *hinzufügen* oder *löschen* ausgewählt. Durch Klicken im Pol-/Nullstellendiagramm können nun Pol- und Nullstellen hinzugefügt oder gelöscht werden. Entsprechend ändern sich dann auch die zugehörige Impulsantwort und Übertragungsfunktion.
### Aufgaben ### Aufgaben
* Teste verschiedene Einstellungen und ihre Auswirkungen auf Impulsantwort und Übertragungsfunktion. Welche Auswirkung hat das Ändern von $H_0$? Wie sehen die voreingestellten Funktionen aus? * Teste verschiedene Einstellungen und ihre Auswirkungen auf Impulsantwort und Übertragungsfunktion. Welche Auswirkung hat das Ändern von $H_0$? Wie sehen die voreingestellten Funktionen aus?
* Entferne alle Pole und Nullstellen. Wie sieht die Impulsantwort aus? Welche Auswirkung hat das Ändern von $H_0$? * Entferne alle Pole und Nullstellen. Wie sieht die Impulsantwort aus? Welche Auswirkung hat das Ändern von $H_0$?
* Erstelle eine Polstelle auf der imaginären Achse. Welche Auswirkung hat diese auf die Übertragungsfunktion? * Erstelle eine Polstelle auf der imaginären Achse. Welche Auswirkung hat diese auf die Übertragungsfunktion?
* Erstelle ein Pol-/Nullstellendiagram mit mehreren möglichen Polstellen. Ändere den Konvergenzbereich. Wann existiert eine Übertragungsfunktion? * Erstelle ein Pol-/Nullstellendiagram mit mehreren möglichen Polstellen. Ändere den Konvergenzbereich. Wann existiert eine Übertragungsfunktion?
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT). This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT).
Please attribute the work as follows: Please attribute the work as follows:
*Emin Kosar, Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2019, Institut für Nachrichtentechnik, RWTH Aachen University. *Emin Kosar, Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2019, Institut für Nachrichtentechnik, RWTH Aachen University.
......
...@@ -32,7 +32,7 @@ class pzPlot(): ...@@ -32,7 +32,7 @@ class pzPlot():
fig = None fig = None
ax = None ax = None
handles = {'ph': None, 'axh': None, 'pH': None, 'axH': None} handles = {'ph': None, 'axh': None, 'pH': None, 'axH': None}
filter_types = {'Manuell' : 'man', 'Butterworth' : 'butr', 'Sprungfunktion' : 'unit', filter_types = {'Manuell' : 'man', 'Butterworth' : 'butr', 'Sprungfunktion' : 'unit',
'Sinus' : 'sin', 'Cosinus' : 'cos'} 'Sinus' : 'sin', 'Cosinus' : 'cos'}
mode = 'p' mode = 'p'
mode_types = {'Polstelle': 'p', 'Nullstelle': 'z'} mode_types = {'Polstelle': 'p', 'Nullstelle': 'z'}
...@@ -44,7 +44,7 @@ class pzPlot(): ...@@ -44,7 +44,7 @@ class pzPlot():
P = 1 # no of poles for butterworth filter P = 1 # no of poles for butterworth filter
def __init__(self, pp=np.array([0]), pz=np.array([]), ord_p=np.array([1]), ord_z=np.array([])): def __init__(self, fig, pp=np.array([0]), pz=np.array([]), ord_p=np.array([1]), ord_z=np.array([])):
self.H0 = 1 self.H0 = 1
self.filter = 'unit' self.filter = 'unit'
...@@ -57,7 +57,7 @@ class pzPlot(): ...@@ -57,7 +57,7 @@ class pzPlot():
self.t = np.linspace(-6, 6, num=self.length) self.t = np.linspace(-6, 6, num=self.length)
self.f = np.linspace(-6, 6, num=self.length) self.f = np.linspace(-6, 6, num=self.length)
self.open_figure() self.open_figure(fig)
# Poles # Poles
...@@ -83,9 +83,8 @@ class pzPlot(): ...@@ -83,9 +83,8 @@ class pzPlot():
self.update_roc(1) self.update_roc(1)
def open_figure(self): def open_figure(self, fig):
fig = plt.figure(figsize=(8, 8))
gs = gridspec.GridSpec(2, 2) gs = gridspec.GridSpec(2, 2)
# First axis for plotting s and h # First axis for plotting s and h
...@@ -100,6 +99,7 @@ class pzPlot(): ...@@ -100,6 +99,7 @@ class pzPlot():
self.fig = fig self.fig = fig
self.ax = ax self.ax = ax
self.ax.set_title('Pol- /Nullstellen Diagramm', fontsize='12') self.ax.set_title('Pol- /Nullstellen Diagramm', fontsize='12')
self.ax.set_aspect('equal', adjustable='datalim')
def onclick(event): def onclick(event):
if self.action == 'add' and event.key == 'shift': if self.action == 'add' and event.key == 'shift':
...@@ -126,7 +126,7 @@ class pzPlot(): ...@@ -126,7 +126,7 @@ class pzPlot():
self.handles['axh'].set_title('Impulsantwort', fontsize='12') self.handles['axh'].set_title('Impulsantwort', fontsize='12')
self.handles['axh'].set_xlabel(r'$\rightarrow t$') self.handles['axh'].set_xlabel(r'$\rightarrow t$')
self.handles['axh'].set_ylabel(r'$\uparrow h(t)$') self.handles['axh'].set_ylabel(r'$\uparrow h(t)$')
self.pbzErrortxt = self.handles['axh'].text(-7, 3.25, self.pbzErrortxt = self.handles['axh'].text(-.6, .0125,
'Zählergrad größer als Nennergrad. \nKeine Partialbruchzerlegung möglich!', 'Zählergrad größer als Nennergrad. \nKeine Partialbruchzerlegung möglich!',
fontsize=12, color='rot', visible=False, bbox=ient_wbbox) fontsize=12, color='rot', visible=False, bbox=ient_wbbox)
self.handles['lineh'], = self.handles['axh'].plot(self.t, self.t) self.handles['lineh'], = self.handles['axh'].plot(self.t, self.t)
...@@ -145,7 +145,7 @@ class pzPlot(): ...@@ -145,7 +145,7 @@ class pzPlot():
self.fig.canvas.layout.height = '600px' self.fig.canvas.layout.height = '600px'
fig.tight_layout(); fig.tight_layout();
#plt.subplots_adjust(wspace=.25) #plt.subplots_adjust(wspace=.25)
# Widgets # Widgets
self.w_filter_type = interactive(self.update_filter,filtr=widgets.Dropdown(options=list(self.filter_types.keys()), value="Sprungfunktion", description='Filter')) self.w_filter_type = interactive(self.update_filter,filtr=widgets.Dropdown(options=list(self.filter_types.keys()), value="Sprungfunktion", description='Filter'))
self.w_action_type = interactive(self.update_action,action=widgets.Dropdown(options=list(self.action_types.keys()),value="Hinzufügen", description='Modus', disabled=True)) self.w_action_type = interactive(self.update_action,action=widgets.Dropdown(options=list(self.action_types.keys()),value="Hinzufügen", description='Modus', disabled=True))
...@@ -360,9 +360,9 @@ class pzPlot(): ...@@ -360,9 +360,9 @@ class pzPlot():
def update_widgets(filtr): def update_widgets(filtr):
if filtr == "Manuell": if filtr == "Manuell":
b = False b = False
else: else:
b = True b = True
self.w_action_type.children[0].disabled = b self.w_action_type.children[0].disabled = b
self.w_point_type.children[0].disabled = b self.w_point_type.children[0].disabled = b
......
...@@ -42,7 +42,7 @@ class zPlot(): ...@@ -42,7 +42,7 @@ class zPlot():
H = None H = None
Hlog = None Hlog = None
def __init__(self, pp=np.array([0]), pz=np.array([]), ord_p=np.array([1]), ord_z=np.array([])): def __init__(self, fig, pp=np.array([0]), pz=np.array([]), ord_p=np.array([1]), ord_z=np.array([])):
self.H0 = 1 self.H0 = 1
#self.filter = 'unit' #self.filter = 'unit'
...@@ -53,7 +53,7 @@ class zPlot(): ...@@ -53,7 +53,7 @@ class zPlot():
self.n = np.linspace(-15, 15, num=self.length) self.n = np.linspace(-15, 15, num=self.length)
self.f = np.linspace(-15, 15, num=1024) self.f = np.linspace(-15, 15, num=1024)
self.open_figure() self.open_figure(fig)
# Poles # Poles
return return
...@@ -78,9 +78,8 @@ class zPlot(): ...@@ -78,9 +78,8 @@ class zPlot():
self.update_roc(1) self.update_roc(1)
def open_figure(self): def open_figure(self, fig):
fig = plt.figure(figsize=(8, 8))
gs = gridspec.GridSpec(2, 2) gs = gridspec.GridSpec(2, 2)
# First axis for plotting s and h # First axis for plotting s and h
...@@ -138,9 +137,7 @@ class zPlot(): ...@@ -138,9 +137,7 @@ class zPlot():
# initial dirac plot # initial dirac plot
(self.cp, self.cn) = ient_plot_dirac(self.handles['axh'], [-1, 1], [-1, 1], 'rwth') (self.cp, self.cn) = ient_plot_dirac(self.handles['axh'], [-1, 1], [-1, 1], 'rwth')
ient_dirac_set_data((self.cp, self.cn), [], []) ient_dirac_set_data((self.cp, self.cn), [], [])
self.fig.canvas.layout.height = '600px'
fig.tight_layout(); fig.tight_layout();
# plt.subplots_adjust(wspace=.25)
# Widgets # Widgets
self.w_filter_type = interactive(self.update_filter, self.w_filter_type = interactive(self.update_filter,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment