Skip to content

Commit ea55e27

Browse files
author
Xing Han Lu
authored
Merge pull request #594 from plotly/add-skrf-time-gating
Add scikit-rf's time gating demo (#minor) Former-commit-id: a6328ac
2 parents 879c754 + 8434415 commit ea55e27

21 files changed

Lines changed: 14518 additions & 0 deletions

apps/dash-time-gating/Procfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: gunicorn app:server

apps/dash-time-gating/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Time Gating with Scikit-RF
2+
3+
*Originally published [here](https://github.com/scikit-rf/dash-apps).*
4+
5+
Apply Time-gating to any network.
6+
7+
![](./time_gate.png)

apps/dash-time-gating/app.py

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
import dash
2+
import dash_core_components as dcc
3+
import dash_html_components as html
4+
from dash.dependencies import Input, Output, State
5+
import plotly.graph_objects as go
6+
import numpy as np
7+
8+
9+
import skrf as rf
10+
from skrf.time import detect_span
11+
12+
13+
external_stylesheets = [
14+
"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css",
15+
"https://codepen.io/chriddyp/pen/bWLwgP.css",
16+
]
17+
18+
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
19+
server = app.server
20+
21+
22+
""" FYI The device under test was made with this
23+
24+
air = rf.air
25+
air.npoints =1001
26+
dut = air.shunt_delay_load(.2,180)**\
27+
air.line(100)**\
28+
air.shunt_delay_load(.4,100)**\
29+
air.line(4000)**\
30+
air.shunt(air.load(.7))**\
31+
air.line(1000)**\
32+
air.impedance_mismatch(1,3)
33+
#**air.short()
34+
dut.add_noise_polar(.01,3e-5)
35+
"""
36+
dut = rf.Network("dut.s2p")
37+
38+
39+
# pull out some frequency info to set slider bounds on center/span
40+
freq = dut.frequency
41+
dt = freq.t_ns[1] - freq.t_ns[0]
42+
t_max = freq.t_ns.max()
43+
44+
45+
######## ## the APP
46+
app.layout = html.Div(
47+
className="page",
48+
children=[
49+
html.Div(
50+
className="sub_page",
51+
children=[
52+
# html.Div(className='col-2'),
53+
html.Div(
54+
children=[
55+
html.H3(
56+
className="product",
57+
children=[
58+
"Time Gating",
59+
html.A(
60+
href="http://www.plotly.com",
61+
children=[
62+
html.Img(
63+
src=app.get_asset_url("dash.png"),
64+
style={"height": "50px", "float": "right"},
65+
)
66+
],
67+
),
68+
html.A(
69+
href="http://www.scikit-rf.org",
70+
children=[
71+
html.Img(
72+
src=app.get_asset_url(
73+
"powered_by_skrf.png"
74+
),
75+
style={"height": "50px", "float": "right"},
76+
),
77+
],
78+
),
79+
],
80+
),
81+
html.Div(
82+
className="row",
83+
children=[
84+
html.Div(
85+
className="col-4",
86+
children=[
87+
html.Span(
88+
children=[
89+
html.Label(
90+
"S-parameter: ", className="inline"
91+
),
92+
dcc.RadioItems(
93+
id="sparam-radio",
94+
options=[
95+
{
96+
"label": "S11",
97+
"value": "s11",
98+
},
99+
{
100+
"label": "S21",
101+
"value": "s21",
102+
},
103+
{
104+
"label": "S12",
105+
"value": "s12",
106+
},
107+
{
108+
"label": "S22",
109+
"value": "s22",
110+
},
111+
],
112+
value="s11",
113+
labelStyle={
114+
"display": "inline-block",
115+
"margin": "6px",
116+
},
117+
),
118+
]
119+
),
120+
html.Label("Window Type: "),
121+
dcc.Dropdown(
122+
id="window-dropdown",
123+
options=[
124+
{"label": "kaiser", "value": "kaiser"},
125+
{"label": "boxcar", "value": "boxcar"},
126+
{
127+
"label": "hamming",
128+
"value": "hamming",
129+
},
130+
],
131+
value="hamming",
132+
),
133+
html.Label("Mode: ", className="inline"),
134+
dcc.RadioItems(
135+
className="inline",
136+
id="mode-radio",
137+
options=[
138+
{"label": "pass", "value": "bandpass"},
139+
{"label": "stop", "value": "bandstop"},
140+
],
141+
value="bandpass",
142+
labelStyle={
143+
"display": "inline-block",
144+
"margin": "6px",
145+
},
146+
),
147+
],
148+
),
149+
html.Div(
150+
className="col",
151+
children=[
152+
html.Button(
153+
id="autogate-button", children="AutoGate"
154+
),
155+
html.Label("Center Frequency(ns)"),
156+
dcc.Slider(
157+
id="center-slider",
158+
min=-t_max,
159+
max=t_max,
160+
value=0,
161+
step=dt * 10,
162+
marks={
163+
str(int(x)): str(int(x))
164+
for x in np.linspace(-t_max, t_max, 13)
165+
},
166+
),
167+
html.Label("Span Frequency(ns)"),
168+
dcc.Slider(
169+
id="span-slider",
170+
min=0,
171+
max=t_max,
172+
value=10,
173+
step=dt * 10,
174+
marks={
175+
str(int(x)): str(int(x))
176+
for x in np.linspace(-t_max, t_max, 13)
177+
},
178+
),
179+
],
180+
),
181+
],
182+
),
183+
html.Div(
184+
[
185+
dcc.Graph(
186+
id="time-graph", figure={"layout": {"height": 300}}
187+
),
188+
dcc.Graph(
189+
id="freq-graph", figure={"layout": {"height": 400}}
190+
),
191+
]
192+
),
193+
]
194+
),
195+
],
196+
)
197+
],
198+
)
199+
200+
201+
@app.callback(
202+
Output("time-graph", "figure"),
203+
Output("freq-graph", "figure"),
204+
Input("sparam-radio", "value"),
205+
Input("center-slider", "value"),
206+
Input("span-slider", "value"),
207+
Input("window-dropdown", "value"),
208+
Input("mode-radio", "value"),
209+
)
210+
def update_figure(sparam, center, span, window, mode):
211+
"""
212+
Update figures given a change in s-parameter of interest, or
213+
gate parameters
214+
"""
215+
216+
if window == "kaiser":
217+
window = ("kaiser", 6)
218+
oneport = dut.__getattribute__(sparam)
219+
gated = oneport.time_gate(center=center, span=span, window=window, mode=mode)
220+
221+
# time
222+
time_fig = go.Figure()
223+
time_fig.add_trace(
224+
go.Line(
225+
x=freq.t_ns, y=oneport.s_time_db.flatten(), line_color="#204a87", name="OG"
226+
)
227+
)
228+
229+
time_fig.add_trace(go.Line(x=freq.t_ns, y=gated.s_time_db.flatten(), name="gated"))
230+
dat = oneport.s_time_db.flatten()
231+
span_height = (dat.min() * 1.5, dat.max() * 0.5)
232+
time_fig.update_layout(
233+
shapes=[
234+
dict(
235+
type="rect",
236+
xref="x",
237+
yref="y",
238+
x0=center - span / 2,
239+
y0=span_height[0],
240+
x1=center + span / 2,
241+
y1=span_height[1],
242+
fillcolor="lightgray",
243+
opacity=0.8,
244+
line_width=0,
245+
layer="below",
246+
)
247+
]
248+
)
249+
250+
time_fig.update_layout(
251+
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
252+
margin=dict(l=20, r=20, t=40, b=20),
253+
title="Time Domain",
254+
xaxis_title="Time (ns)",
255+
yaxis_title="Magnitude (dB)",
256+
yaxis_range=(-80, 0),
257+
)
258+
259+
# frequency
260+
freq_fig = go.Figure()
261+
freq_fig.add_trace(
262+
go.Line(
263+
x=freq.f_scaled, y=oneport.s_db.flatten(), name="OG", line_color="#204a87"
264+
)
265+
)
266+
267+
freq_fig.add_trace(go.Line(x=freq.f_scaled, y=gated.s_db.flatten(), name="gated"))
268+
269+
freq_fig.update_layout(
270+
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
271+
margin=dict(l=20, r=20, t=40, b=20),
272+
title="Frequency",
273+
xaxis_title="Frequency (%s)" % dut.frequency.unit,
274+
yaxis_title="Magnitude (dB)",
275+
yaxis_range=(-60, 10),
276+
)
277+
return time_fig, freq_fig
278+
279+
280+
@app.callback(
281+
Output("center-slider", "value"),
282+
Output("span-slider", "value"),
283+
Input("autogate-button", "n_clicks"),
284+
Input("sparam-radio", "value"),
285+
)
286+
def autogate(autogate, sparam):
287+
"""
288+
Autogate chooses center/span values based on basic peak search
289+
"""
290+
oneport = dut.__getattribute__(sparam)
291+
n = oneport.s_time_mag.argmax()
292+
center = oneport.frequency.t_ns[n]
293+
span = detect_span(oneport)
294+
return center, span
295+
296+
297+
if __name__ == "__main__":
298+
app.run_server(debug=True)

0 commit comments

Comments
 (0)