Since we can iterate over the active_channel attribute of Instrument
more than once, make sure to cast the return value of filter() to a list
to avoid issues with python 3.
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Calling `Instrument.reset(kinds='some string')` leaves
`self.active_channels` as `[]` which is probably not the expected
behaviour. This is caused by the last nested `else` which refers to
the condition `if isinstance(kinds, basestring)` and might have been
overlooked because of having been confused with the top-level `else`.
Anyhow, an `else` does not seem to be needed there.
This bug illustrates the risk of having too many nested levels and
execution paths which also impact the readability of the code. We
modify the implementation to solve the bug on top of which we:
- Reduce the maximum order of nested levels from 4 to 3;
- Express more clearly the potential paths of execution
(less nested conditions);
- Replace unnecessary `for`-loops by list comprehensions,
removing the need for an initialisation of `active_channels`
and making clearer what each path of execution ends up with;
- Removed unnecessary `List` copies of `self.channels.values()`;
- Used the fact that the message of a `KeyError` is the unknown
key.
- Added values() and iter_values() methods. These return each row as a
named tuple, with channel labels as the field names.
- __cmp__ has been made more generic by checking wether other has
"value" attribute, rather than wether it is an instance of Measurment.
- MeasurementCsv no longer keeps an open handle to the file, and instead
re-opens the file each time it needs it. This removes the need for
managing the open handle, and alows parallel iterations over the
values (each iteration will have it's own read handle into the files).
In addition to a label constructed form the combination of site and
measurment type, channels had a name that was specified on creation.
This proven to be not particularly useful (there only being one instance
of the name being set to something materially different from the label);
and this has lead to channels being inconsistenly referenced (some times
a channel is identified by its label, and sometimes by the name).
This commit removes the name from __init__ arguments, and
InstrumentChannel.name is now an alias for InstrumentChannel.label.
Derived metrics may be calculated form data in raw output that is not
present in the resulting MeasurementCSV. This adds a method to provide
uniform access to raw artifacts generated by an instrument.
- Fix missing parameter in the documentation
- Clarify meaning of `sites` and `kinds` in the documentation.
- With the current implementation the `channels` argument is
useless: if `sites` and `kinds` are not also specified then all
channels are enabled anyway. Fix that by making those parameters
ignored when `channels` is provided.
- Add "unknown" measurement type to be used when the type of measurement
for a CSV column cannot be established.
- Make channels argument optional for MeasurementCsv.
- If channels for a MeasurementCsv have not been specified, attempt to
discover them from the CSV header. This will check if each entry in
the header ends with the name of a known MeasurementType prefixed with
a "_"; if so, it will assume the reset of the entry is the site.
Otherwise, the entire entry will be assumed to be the site and
"unknown" MeasurementType will be used.
Add time_us MeasurementType for time expressed in microseconds and
define conversions to/form time. This is a very common unit for low-level
operations, and it may be desirable to avoid converting large number of
metrics to floats in order to report as a "standard" type.
- Change MeasurementType to derive from object rather than tuple.
- There is now support for conversion from one MeasurementType to
another. A MeasurementType defines what it can be converted to and
how.
- `Instrument.channels` is a dictionary, we want the values not the
keys; this is provded by `list_channels`.
- `InstrumentChannel` objects do not have a `measure` attribute. Use
`kind` instead.
Prior to this commit, measurements to be collected were specified via
"sites" and "kinds" parameters. This has the limitation that if you
wanted measurments of kind X from site A and kind Y from site B, you'd
have to specify them as
reset(sites=['A', 'B'], kinds=['X', 'Y'])
Which would have the effect of also collecting measurments Y for site A
and measurments X for site B. This commit adds the option of specifying
individual channels, via thier labels, e.g.
reset(channels=['A_X', 'B_Y'])
so that only the channels you're interested in will be collected.
When add channel for power meter with specific order, it also imply the
order with corresponding fields in captured data. So later need read
back the index for channel and use it to reference power data.
So need use ordered dictionary object for channel.
Signed-off-by: Leo Yan <leo.yan@linaro.org>