blob: 84d3d7c3457f662c4d052c6f4f9bc5cf42ab73e7 [file] [log] [blame]
# Copyright 2013-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from __future__ import division
from collections import defaultdict
from devlib import DerivedMeasurements, DerivedMetric
from devlib.instrument import MEASUREMENT_TYPES, InstrumentChannel
class DerivedEnergyMeasurements(DerivedMeasurements):
@staticmethod
def process(measurements_csv):
should_calculate_energy = []
use_timestamp = False
# Determine sites to calculate energy for
channel_map = defaultdict(list)
for channel in measurements_csv.channels:
channel_map[channel].append(channel.kind)
for channel, kinds in channel_map.iteritems():
if 'power' in kinds and not 'energy' in kinds:
should_calculate_energy.append(channel.site)
if channel.site == 'timestamp':
use_timestamp = True
time_measurment = channel.measurement_type
if measurements_csv.sample_rate_hz is None and not use_timestamp:
msg = 'Timestamp data is unavailable, please provide a sample rate'
raise ValueError(msg)
if use_timestamp:
# Find index of timestamp column
ts_index = [i for i, chan in enumerate(measurements_csv.channels)
if chan.site == 'timestamp']
if len(ts_index) > 1:
raise ValueError('Multiple timestamps detected')
ts_index = ts_index[0]
row_ts = 0
last_ts = 0
energy_results = defaultdict(dict)
power_results = defaultdict(float)
# Process data
for count, row in enumerate(measurements_csv.iter_measurements()):
if use_timestamp:
last_ts = row_ts
row_ts = time_measurment.convert(float(row[ts_index].value), 'time')
for entry in row:
channel = entry.channel
site = channel.site
if channel.kind == 'energy':
if count == 0:
energy_results[site]['start'] = entry.value
else:
energy_results[site]['end'] = entry.value
if channel.kind == 'power':
power_results[site] += entry.value
if site in should_calculate_energy:
if count == 0:
energy_results[site]['start'] = 0
energy_results[site]['end'] = 0
elif use_timestamp:
energy_results[site]['end'] += entry.value * (row_ts - last_ts)
else:
energy_results[site]['end'] += entry.value * (1 /
measurements_csv.sample_rate_hz)
# Calculate final measurements
derived_measurements = []
for site in energy_results:
total_energy = energy_results[site]['end'] - energy_results[site]['start']
name = '{}_total_energy'.format(site)
derived_measurements.append(DerivedMetric(name, total_energy, MEASUREMENT_TYPES['energy']))
for site in power_results:
power = power_results[site] / (count + 1) #pylint: disable=undefined-loop-variable
name = '{}_average_power'.format(site)
derived_measurements.append(DerivedMetric(name, power, MEASUREMENT_TYPES['power']))
return derived_measurements