blob: 84d3d7c3457f662c4d052c6f4f9bc5cf42ab73e7 [file] [log] [blame]
Marc Bonnicic093d562017-08-07 14:29:40 +01001# Copyright 2013-2015 ARM Limited
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15from __future__ import division
16from collections import defaultdict
17
Sergei Trofimovdd26b432017-09-07 11:13:34 +010018from devlib import DerivedMeasurements, DerivedMetric
19from devlib.instrument import MEASUREMENT_TYPES, InstrumentChannel
Marc Bonnicic093d562017-08-07 14:29:40 +010020
21
22class DerivedEnergyMeasurements(DerivedMeasurements):
23
24 @staticmethod
25 def process(measurements_csv):
26
27 should_calculate_energy = []
28 use_timestamp = False
29
30 # Determine sites to calculate energy for
31 channel_map = defaultdict(list)
32 for channel in measurements_csv.channels:
33 channel_map[channel].append(channel.kind)
34 for channel, kinds in channel_map.iteritems():
35 if 'power' in kinds and not 'energy' in kinds:
36 should_calculate_energy.append(channel.site)
37 if channel.site == 'timestamp':
38 use_timestamp = True
39 time_measurment = channel.measurement_type
40
41 if measurements_csv.sample_rate_hz is None and not use_timestamp:
42 msg = 'Timestamp data is unavailable, please provide a sample rate'
43 raise ValueError(msg)
44
45 if use_timestamp:
46 # Find index of timestamp column
47 ts_index = [i for i, chan in enumerate(measurements_csv.channels)
48 if chan.site == 'timestamp']
49 if len(ts_index) > 1:
50 raise ValueError('Multiple timestamps detected')
51 ts_index = ts_index[0]
52
53 row_ts = 0
54 last_ts = 0
55 energy_results = defaultdict(dict)
56 power_results = defaultdict(float)
57
58 # Process data
Sergei Trofimovdfd0b8e2017-08-21 11:01:42 +010059 for count, row in enumerate(measurements_csv.iter_measurements()):
Marc Bonnicic093d562017-08-07 14:29:40 +010060 if use_timestamp:
61 last_ts = row_ts
62 row_ts = time_measurment.convert(float(row[ts_index].value), 'time')
63 for entry in row:
64 channel = entry.channel
65 site = channel.site
66 if channel.kind == 'energy':
67 if count == 0:
68 energy_results[site]['start'] = entry.value
69 else:
70 energy_results[site]['end'] = entry.value
71
72 if channel.kind == 'power':
73 power_results[site] += entry.value
74
75 if site in should_calculate_energy:
76 if count == 0:
77 energy_results[site]['start'] = 0
78 energy_results[site]['end'] = 0
79 elif use_timestamp:
80 energy_results[site]['end'] += entry.value * (row_ts - last_ts)
81 else:
82 energy_results[site]['end'] += entry.value * (1 /
83 measurements_csv.sample_rate_hz)
84
85 # Calculate final measurements
86 derived_measurements = []
87 for site in energy_results:
88 total_energy = energy_results[site]['end'] - energy_results[site]['start']
Sergei Trofimovdd26b432017-09-07 11:13:34 +010089 name = '{}_total_energy'.format(site)
90 derived_measurements.append(DerivedMetric(name, total_energy, MEASUREMENT_TYPES['energy']))
Marc Bonnicic093d562017-08-07 14:29:40 +010091
92 for site in power_results:
93 power = power_results[site] / (count + 1) #pylint: disable=undefined-loop-variable
Sergei Trofimovdd26b432017-09-07 11:13:34 +010094 name = '{}_average_power'.format(site)
95 derived_measurements.append(DerivedMetric(name, power, MEASUREMENT_TYPES['power']))
Marc Bonnicic093d562017-08-07 14:29:40 +010096
97 return derived_measurements