1 #! /usr/bin/env python3
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 # This scripts plots graphs produced by our drift correction code.
9 # Install dependencies with:
10 # > pip install bokeh pandas
12 # Generate the csv data file with the DriftControllerGraphs log module:
13 # > MOZ_LOG=raw,sync,DriftControllerGraphs:5 \
14 # > MOZ_LOG_FILE=/tmp/driftcontrol.csv \
15 # > ./mach gtest '*AudioDrift*StepResponse'
17 # Generate the graphs with this script:
18 # > ./dom/media/driftcontrol/plot.py /tmp/driftcontrol.csv.moz_log
20 # The script should produce a file plot.html in the working directory and
21 # open it in the default browser.
24 from collections
import OrderedDict
27 from bokeh
.io
import output_file
, show
28 from bokeh
.layouts
import gridplot
29 from bokeh
.models
import TabPanel
, Tabs
30 from bokeh
.plotting
import figure
34 parser
= argparse
.ArgumentParser(
35 prog
="plot.py for DriftControllerGraphs",
36 description
="""Takes a csv file of DriftControllerGraphs data
37 (from a single DriftController instance) and plots
38 them into plot.html in the current working directory.
40 The easiest way to produce the data is with MOZ_LOG:
41 MOZ_LOG=raw,sync,DriftControllerGraphs:5 \
42 MOZ_LOG_FILE=/tmp/driftcontrol.csv \
43 ./mach gtest '*AudioDrift*StepResponse'""",
45 parser
.add_argument("csv_file", type=str)
46 args
= parser
.parse_args()
48 all_df
= pandas
.read_csv(args
.csv_file
)
50 # Filter on distinct ids to support multiple plotting sources
52 for id in list(OrderedDict
.fromkeys(all_df
["id"])):
53 df
= all_df
[all_df
["id"] == id]
56 buffering
= df
["buffering"]
57 avgbuffered
= df
["avgbuffered"]
58 desired
= df
["desired"]
59 buffersize
= df
["buffersize"]
60 inlatency
= df
["inlatency"]
61 outlatency
= df
["outlatency"]
62 inframesavg
= df
["inframesavg"]
63 outframesavg
= df
["outframesavg"]
65 outrate
= df
["outrate"]
66 steadystaterate
= df
["steadystaterate"]
67 nearthreshold
= df
["nearthreshold"]
68 corrected
= df
["corrected"]
69 hysteresiscorrected
= df
["hysteresiscorrected"]
70 configured
= df
["configured"]
72 output_file("plot.html")
75 # Variables with more variation are plotted after smoother variables
76 # because latter variables are drawn on top and so visibility of
77 # individual values in the variables with more variation is improved
78 # (when both variables are shown).
80 t
, inframesavg
, color
="violet", legend_label
="Average input packet size"
83 t
, outframesavg
, color
="purple", legend_label
="Average output packet size"
85 fig1
.line(t
, inlatency
, color
="hotpink", legend_label
="In latency")
86 fig1
.line(t
, outlatency
, color
="firebrick", legend_label
="Out latency")
87 fig1
.line(t
, desired
, color
="goldenrod", legend_label
="Desired buffering")
89 t
, avgbuffered
, color
="orangered", legend_label
="Average buffered estimate"
91 fig1
.line(t
, buffering
, color
="dodgerblue", legend_label
="Actual buffering")
92 fig1
.line(t
, buffersize
, color
="seagreen", legend_label
="Buffer size")
95 [d
- h
for (d
, h
) in zip(desired
, nearthreshold
)],
96 [d
+ h
for (d
, h
) in zip(desired
, nearthreshold
)],
99 legend_label
='"Near" band (won\'t reduce desired buffering outside)',
102 slowConvergenceSecs
= 30
103 adjustmentInterval
= 1
105 avgError
= avgbuffered
- desired
106 absAvgError
= [abs(e
) for e
in avgError
]
107 slow_offset
= [e
/ slowConvergenceSecs
- slowHysteresis
for e
in absAvgError
]
108 fast_offset
= [e
/ adjustmentInterval
for e
in absAvgError
]
109 low_offset
, high_offset
= zip(
111 (s
, f
) if e
>= 0 else (-f
, -s
)
112 for (e
, s
, f
) in zip(avgError
, slow_offset
, fast_offset
)
116 fig2
= figure(x_range
=fig1
.x_range
)
119 steadystaterate
+ low_offset
,
120 steadystaterate
+ high_offset
,
123 legend_label
="Deadband (won't change in rate within)",
125 fig2
.line(t
, inrate
, color
="hotpink", legend_label
="Nominal in sample rate")
126 fig2
.line(t
, outrate
, color
="firebrick", legend_label
="Nominal out sample rate")
131 legend_label
="Estimated in rate with drift",
134 t
, corrected
, color
="dodgerblue", legend_label
="Corrected in sample rate"
140 legend_label
="Hysteresis-corrected in sample rate",
143 t
, configured
, color
="goldenrod", legend_label
="Configured in sample rate"
146 fig1
.legend
.location
= "top_left"
147 fig2
.legend
.location
= "top_right"
148 for fig
in (fig1
, fig2
):
149 fig
.legend
.background_fill_alpha
= 0.6
150 fig
.legend
.click_policy
= "hide"
152 tabs
.append(TabPanel(child
=gridplot([[fig1
, fig2
]]), title
=str(id)))
154 show(Tabs(tabs
=tabs
))
157 if __name__
== "__main__":