blob: 6ef8c653541b301903a2f5282614301fe14e15e1 [file] [log] [blame]
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from argparse import ArgumentParser, FileType
from sys import modules, stderr
import datetime
import os
from pathlib import Path
import pac_utils
import pandas
import plotly.express
def main():
argparser = ArgumentParser(description=modules[__name__].__doc__)
argparser.add_argument(
'-s',
'--single',
help=
'Use to take a single voltage, current, power measurement of all rails',
action="store_true")
argparser.add_argument(
'-t',
'--time',
default=1,
help='Time to capture in seconds')
argparser.add_argument(
'-c',
'--config',
type=FileType('r'),
help='PAC address and configuration file used by servod')
argparser.add_argument(
'-O',
'--output',
nargs='?',
default=os.path.join('./Data', datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')),
help='Path for log files')
argparser.add_argument(
'-m',
'--mapping',
type=FileType('r'),
default='./GuybrushProto0_RailMapping.csv',
help='Rail hierachy mapping used to generate sunburst plot')
argparser.add_argument(
'-g',
'--gpio',
type=FileType('r'),
default='./guybrush_r0_pacs_mainsmt_gpio.csv',
help='PAC address to GPIO Rail mapping')
args = argparser.parse_args()
if not args.config:
print('PAC Configuration Required')
return False
# Store everything in output folder.
log_path = args.output
single_log_path = os.path.join(log_path, 'singleLog.csv')
time_log_path = os.path.join(log_path, 'timeLog.csv')
accumulator_log_path = os.path.join(log_path, 'accumulatorData.csv')
report_log_path = os.path.join(log_path, 'report.html')
Path(log_path).mkdir(parents=True, exist_ok=True)
# If single, take a single shot of these measurements then quit.
if args.single:
log = pac_utils.query_all(args.config.name, args.gpio.name)
log.to_csv(single_log_path)
return False
# Else we're going to take a time log.
# Record the sample and log to file.
(log, accumulator_log) = pac_utils.record(args.config.name,
rail=['all'],
record_length=args.time)
log.to_csv(time_log_path)
accumulator_log.to_csv(accumulator_log_path)
# Generate plots using plotly.
time_plot = plotly.express.line(log,
x='relativeTime',
y='power',
color='rail',
labels={
'power': 'Power (w)',
'relativeTime': 'Time (seconds)'
})
time_plot.update_layout(
title='Time Series',
xaxis_title='Time (Seconds)',
yaxis_title='Power (W)',
)
box_plot = plotly.express.box(log, y='power', x='rail')
box_plot.update_layout(title='Instaneous Measurement Statistics',
xaxis_title='Rail',
yaxis_title='Power (W)')
accumulator_log = accumulator_log.sort_values(by='Average Power (w)',
ascending=False)
summary_table = plotly.graph_objects.Figure(
data=[
plotly.graph_objects.Table(
header=dict(values=['Rail',
'Accumulation Time (s)',
'Sense Resistor (Ohm)',
'Average Power (W)'],
align='left'),
cells=dict(values=[
accumulator_log.Rail,
accumulator_log.tAccum.round(2), accumulator_log.rSense,
accumulator_log['Average Power (w)'].round(3)
], align='left'))
]
)
summary_table.update_layout(title='Accumulator Measurements')
if args.mapping is not None:
skip_sunplot = False
mapping = pandas.read_csv(args.mapping, skiprows=4)
accumulator_log = pandas.merge(accumulator_log, mapping, on='Rail')
star_plot = plotly.express.sunburst(accumulator_log,
names='Rail',
parents='Parent',
values='Average Power (w)',
title='Power Sunburst')
else:
print('Skipping Sunplot')
skip_sunplot = True
# Generate an HTML Report.
with open(report_log_path, 'w') as f:
f.write(summary_table.to_html(full_html=False, include_plotlyjs='cdn'))
if not skip_sunplot:
f.write(star_plot.to_html(full_html=False, include_plotlyjs='cdn'))
f.write(box_plot.to_html(full_html=False, include_plotlyjs='cdn'))
f.write(time_plot.to_html(full_html=False, include_plotlyjs='cdn'))
if __name__ == '__main__':
try:
main()
except Exception as exception:
print(str(exception), file=stderr)