Module redvox.api900.sensors.interleaved_channel
This module contains classes and methods for working with interleaved channels.
Expand source code
"""
This module contains classes and methods for working with interleaved channels.
"""
import typing
import numpy
import redvox.api900.constants as constants
import redvox.api900.exceptions as exceptions
import redvox.api900.lib.api900_pb2 as api900_pb2
import redvox.api900.migrations as migrations
import redvox.api900.reader_utils as reader_utils
import redvox.api900.stat_utils as stat_utils
# pylint: disable=R0902
class InterleavedChannel:
"""
This class represents an interleaved channel.
An interleaved channel contains multiple channel types in a single payload. This is useful for situations where
a sensor produces several values for a single timestamp. For example, a GPS will produce a LATITUDE, LONGITUDE,
ALTITUDE, and SPEED values with every update. An interleaved channel encodes all four of those channel types
into a single payload.
Every channel has a field channel_types that list the channel types contained within the payload. For a GPS sensor,
the channel_types array would look like [LATITUDE, LONGITUDE, ALTITUDE, SPEED]. The location of the channel type
in channel_types determines the offset into the payload and the length of channel_types determines the step size.
As such, this hypothetical GPS channel payload be encoded as:
[LAT0, LNG0, ALT0, SPD0, LAT1, LNG1, ALT1, SPD1, ..., LATn, LNGn, ALTn, SPDn]
This class provides methods for working with interleaved channels as well as accessing interleaved statistic values.
"""
def __init__(self, channel: typing.Optional[typing.Union[api900_pb2.EvenlySampledChannel,
api900_pb2.UnevenlySampledChannel]] = None):
"""
Initializes this interleaved channel object.
:param channel: Either a protobuf evenly or unevenly sampled channel.
note: value_means, value_medians, value_stds, and channel_type_index are only set during initialization or
when payload is altered
payload should only be altered by set_payload or set_deinterleaved_payload due to the extra data values that are
required to correctly set the protobuf_channel
"""
if channel is None:
self.protobuf_channel = None
self.sensor_name = None
self.channel_types = [0]
self.payload = [0]
self.metadata = []
self.value_means = []
self.value_stds = []
self.value_medians = []
self.channel_type_index = []
else:
self.protobuf_channel: typing.Union[api900_pb2.EvenlySampledChannel,
api900_pb2.UnevenlySampledChannel] = channel
"""Reference to the original protobuf channel"""
self.sensor_name: str = channel.sensor_name
"""Provided sensor name"""
self.channel_types: typing.List[
typing.Union[
api900_pb2.EvenlySampledChannel,
api900_pb2.UnevenlySampledChannel]] = reader_utils.repeated_to_list(channel.channel_types)
"""List of channel type constant enumerations"""
self.payload: numpy.ndarray = reader_utils.extract_payload(channel)
"""This channels payload as a numpy array of either floats or ints"""
self.metadata: typing.List[str] = reader_utils.repeated_to_list(channel.metadata)
"""This channels list of metadata"""
self.value_means: numpy.ndarray = reader_utils.repeated_to_array(channel.value_means)
"""Interleaved array of mean values"""
self.value_stds: numpy.ndarray = reader_utils.repeated_to_array(channel.value_stds)
"""Interleaved array of standard deviations of values"""
self.value_medians: numpy.ndarray = reader_utils.repeated_to_array(channel.value_medians)
"""Interleaves array of median values"""
self.channel_type_index: typing.Dict[api900_pb2.ChannelType, int] = {self.channel_types[i]: i for
i in
range(
len(
self.channel_types))}
"""Contains a mapping of channel type to index in channel_types array"""
def set_channel_types(self, types: typing.List[typing.Union[api900_pb2.EvenlySampledChannel,
api900_pb2.UnevenlySampledChannel]]):
"""
sets the channel_types to the list given
:param types: a list of channel types
"""
del self.protobuf_channel.channel_types[:]
for ctype in types:
self.protobuf_channel.channel_types.append(ctype)
self.channel_types = reader_utils.repeated_to_list(self.protobuf_channel.channel_types)
self.channel_type_index = {self.channel_types[i]: i for i in range(len(self.channel_types))}
def get_channel_type_names(self) -> typing.List[str]:
"""
Returns the list of channel_types as a list of names instead of enumeration constants.
:return: The list of channel_types as a list of names instead of enumeration constants.
"""
return list(map(reader_utils.channel_type_name_from_enum, self.channel_types))
def channel_index(self, channel_type: int) -> int:
"""
Returns the index of a channel type or -1 if it DNE.
:param channel_type: The channel type to search for.
:return: The index of the channel or -1 if it DNE.
"""
return self.channel_type_index[channel_type] if channel_type in self.channel_type_index else -1
def has_channel(self, channel_type: int) -> bool:
"""
Returns if channel type exists with in this channel.
:param channel_type: The channel type to search for.
:return: True if it exist, False otherwise.
"""
return channel_type in self.channel_type_index
def set_channel(self, channel: typing.Union[api900_pb2.EvenlySampledChannel,
api900_pb2.UnevenlySampledChannel]):
"""
Sets the protobuf channel
:param channel: protobuf channel
"""
self.protobuf_channel = channel
self.sensor_name = channel.sensor_name
self.channel_types = reader_utils.repeated_to_list(channel.channel_types)
self.payload = reader_utils.extract_payload(channel)
self.metadata = reader_utils.repeated_to_list(channel.metadata)
self.value_means = reader_utils.repeated_to_array(channel.value_means)
self.value_stds = reader_utils.repeated_to_array(channel.value_stds)
self.value_medians = reader_utils.repeated_to_array(channel.value_medians)
self.channel_type_index = {self.channel_types[i]: i for i in range(len(self.channel_types))}
def has_payload(self, channel_type: int) -> bool:
"""
Returns if channel contains a non-empty specified payload.
:param channel_type: The channel to check for a payload for.
:return: Whether this channel contains the specified payload.
"""
return self.has_channel(channel_type) and len(self.payload) > 0
def set_payload(self,
payload_values: typing.Union[numpy.ndarray, typing.List],
pl_type: constants.PayloadType,
should_compute_stats=True):
"""
sets the payload to an interleaved channel with step number of arrays interleaved together.
:param should_compute_stats: Whether the statistics should be computed or not (optional default to True)
:param payload_values: Interleaved payload values
:param pl_type: payload type
"""
# if len(payload_values) < 1:
# raise exceptions.ReaderException("Channel must not be empty and number of arrays must not be less than
# 1.")
# Convert to numpy array is necessary
payload_values = reader_utils.to_array(payload_values)
# clear all other payloads
self.protobuf_channel.byte_payload.ClearField("payload")
self.protobuf_channel.uint32_payload.ClearField("payload")
self.protobuf_channel.uint64_payload.ClearField("payload")
self.protobuf_channel.int32_payload.ClearField("payload")
self.protobuf_channel.int64_payload.ClearField("payload")
self.protobuf_channel.float32_payload.ClearField("payload")
self.protobuf_channel.float64_payload.ClearField("payload")
# set the payload based on the type of data
if pl_type == constants.PayloadType.BYTE_PAYLOAD:
self.protobuf_channel.byte_payload.payload = payload_values
elif pl_type == constants.PayloadType.UINT32_PAYLOAD:
self.protobuf_channel.uint32_payload.payload.extend(payload_values)
elif pl_type == constants.PayloadType.UINT64_PAYLOAD:
self.protobuf_channel.uint64_payload.payload.extend(payload_values)
elif pl_type == constants.PayloadType.INT32_PAYLOAD:
self.protobuf_channel.int32_payload.payload.extend(payload_values)
elif pl_type == constants.PayloadType.INT64_PAYLOAD:
self.protobuf_channel.int64_payload.payload.extend(payload_values)
elif pl_type == constants.PayloadType.FLOAT32_PAYLOAD:
self.protobuf_channel.float32_payload.payload.extend(payload_values)
elif pl_type == constants.PayloadType.FLOAT64_PAYLOAD:
self.protobuf_channel.float64_payload.payload.extend(payload_values)
else:
raise TypeError("Unknown payload type to set.")
if len(payload_values) < 1:
self.payload = payload_values
else:
self.payload = reader_utils.extract_payload(self.protobuf_channel)
# calculate the means, std devs, and medians
if should_compute_stats:
self.update_stats()
def set_interleaved_payload(self,
payloads: typing.List[typing.Union[typing.List, numpy.ndarray]],
pl_type: constants.PayloadType,
should_compute_stats: bool = True):
"""
Interleaves multiple payloads together and sets the interleaved payload.
:param payloads: Payloads of the same length to be interleaved.
:param pl_type: The payload type
:param should_compute_stats: Whether or not payload stats should be calculated.
"""
interleaved = reader_utils.interleave_arrays(list(map(reader_utils.to_array, payloads)))
self.set_payload(interleaved, pl_type, should_compute_stats)
def get_payload(self, channel_type: int) -> numpy.ndarray:
"""
Returns a deinterleaved payload of a given channel type or an empty array.
:param channel_type: The channel type to extract/deinterleave from the payload.
:return: A numpy array of floats or ints of a single channel type.
"""
idx = self.channel_index(channel_type)
if idx < 0:
return reader_utils.empty_array()
try:
payload: numpy.ndarray = reader_utils.deinterleave_array(self.payload, idx, len(self.channel_types))
return migrations.maybe_get_float(payload)
except exceptions.ReaderException:
return reader_utils.empty_array()
def get_payload_type(self) -> str:
"""
Returns the internal protobuf payload type.
:return: The internal protobuf payload type.
"""
return reader_utils.payload_type(self.protobuf_channel)
def get_multi_payload(self, channel_types: typing.List[int]) -> numpy.ndarray:
"""
Returns an interleaved payload with the given channel types.
:param channel_types: Channel types to interleave into a single payload.
:return: A numpy array of an interleaved payload.
"""
channel_types_len = len(channel_types)
if channel_types_len == 0:
return reader_utils.empty_array()
elif channel_types_len == 1:
return self.get_payload(channel_types[0])
payloads = list(map(self.get_payload, channel_types))
return reader_utils.interleave_arrays(payloads)
def get_value_mean(self, channel_type: int) -> float:
"""
Returns the mean value for a single channel type.
:param channel_type: The channel type to extract the mean from.
:return: The mean value.
"""
idx = self.channel_index(channel_type)
if idx < 0 or len(self.value_means) == 0:
raise exceptions.ReaderException("mean DNE, is the payload empty?")
return self.value_means[idx]
def get_value_std(self, channel_type: int) -> float:
"""
Returns the standard deviation value for a single channel type.
:param channel_type: The channel type to extract the std from.
:return: The standard deviation.
"""
idx = self.channel_index(channel_type)
if idx < 0 or len(self.value_stds) == 0:
raise exceptions.ReaderException("std DNE, is the payload empty?")
return self.value_stds[idx]
def get_value_median(self, channel_type: int) -> float:
"""
Returns the median value for a single channel type.
:param channel_type: The channel type to extract the median from.
:return:The median value.
"""
idx = self.channel_index(channel_type)
if idx < 0 or len(self.value_medians) == 0:
raise exceptions.ReaderException("median DNE, is the payload empty?")
return self.value_medians[idx]
def update_stats(self):
"""
updates mean, std and median for all values
"""
channel = self.payload
step = len(self.channel_types)
del self.protobuf_channel.value_means[:]
del self.protobuf_channel.value_stds[:]
del self.protobuf_channel.value_medians[:]
for i in range(step):
std, mean, median = stat_utils.calc_utils(reader_utils.deinterleave_array(channel, i, step))
self.protobuf_channel.value_means.append(mean)
self.protobuf_channel.value_stds.append(std)
self.protobuf_channel.value_medians.append(median)
self.value_stds = reader_utils.repeated_to_array(self.protobuf_channel.value_stds)
self.value_means = reader_utils.repeated_to_array(self.protobuf_channel.value_means)
self.value_medians = reader_utils.repeated_to_array(self.protobuf_channel.value_medians)
def set_sensor_name(self, name: str):
"""
sets the sensor name
:param name: name of sensor
"""
self.sensor_name = name
self.protobuf_channel.sensor_name = name
def set_metadata(self, data: typing.List[str]):
"""
sets the metadata
:param data: metadata as list of strings
"""
del self.protobuf_channel.metadata[:]
for meta in data:
self.protobuf_channel.metadata.append(meta)
self.metadata = reader_utils.repeated_to_list(self.protobuf_channel.metadata)
def metadata_as_dict(self) -> typing.Dict[str, str]:
"""
Returns any metadata as a dictionary of key-pair values.
:return: Any metadata as a dictionary of key-pair values.
"""
return reader_utils.get_metadata_as_dict(self.metadata)
def __str__(self) -> str:
"""
Returns a string representation of this interleaved channel.
:return: A string representation of this interleaved chanel.
"""
return "sensor_name: {}\n" \
"channel_types: {}\n" \
"len(payload): {}\n" \
"payload_type: {}".format(self.sensor_name,
list(map(
reader_utils.channel_type_name_from_enum,
self.channel_types)),
len(self.payload),
reader_utils.payload_type(
self.protobuf_channel))
Classes
class InterleavedChannel (channel: Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel, ForwardRef(None)] = None)
-
This class represents an interleaved channel.
An interleaved channel contains multiple channel types in a single payload. This is useful for situations where a sensor produces several values for a single timestamp. For example, a GPS will produce a LATITUDE, LONGITUDE, ALTITUDE, and SPEED values with every update. An interleaved channel encodes all four of those channel types into a single payload.
Every channel has a field channel_types that list the channel types contained within the payload. For a GPS sensor, the channel_types array would look like [LATITUDE, LONGITUDE, ALTITUDE, SPEED]. The location of the channel type in channel_types determines the offset into the payload and the length of channel_types determines the step size. As such, this hypothetical GPS channel payload be encoded as:
[LAT0, LNG0, ALT0, SPD0, LAT1, LNG1, ALT1, SPD1, …, LATn, LNGn, ALTn, SPDn]
This class provides methods for working with interleaved channels as well as accessing interleaved statistic values.
Initializes this interleaved channel object. :param channel: Either a protobuf evenly or unevenly sampled channel. note: value_means, value_medians, value_stds, and channel_type_index are only set during initialization or when payload is altered payload should only be altered by set_payload or set_deinterleaved_payload due to the extra data values that are required to correctly set the protobuf_channel
Expand source code
class InterleavedChannel: """ This class represents an interleaved channel. An interleaved channel contains multiple channel types in a single payload. This is useful for situations where a sensor produces several values for a single timestamp. For example, a GPS will produce a LATITUDE, LONGITUDE, ALTITUDE, and SPEED values with every update. An interleaved channel encodes all four of those channel types into a single payload. Every channel has a field channel_types that list the channel types contained within the payload. For a GPS sensor, the channel_types array would look like [LATITUDE, LONGITUDE, ALTITUDE, SPEED]. The location of the channel type in channel_types determines the offset into the payload and the length of channel_types determines the step size. As such, this hypothetical GPS channel payload be encoded as: [LAT0, LNG0, ALT0, SPD0, LAT1, LNG1, ALT1, SPD1, ..., LATn, LNGn, ALTn, SPDn] This class provides methods for working with interleaved channels as well as accessing interleaved statistic values. """ def __init__(self, channel: typing.Optional[typing.Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]] = None): """ Initializes this interleaved channel object. :param channel: Either a protobuf evenly or unevenly sampled channel. note: value_means, value_medians, value_stds, and channel_type_index are only set during initialization or when payload is altered payload should only be altered by set_payload or set_deinterleaved_payload due to the extra data values that are required to correctly set the protobuf_channel """ if channel is None: self.protobuf_channel = None self.sensor_name = None self.channel_types = [0] self.payload = [0] self.metadata = [] self.value_means = [] self.value_stds = [] self.value_medians = [] self.channel_type_index = [] else: self.protobuf_channel: typing.Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel] = channel """Reference to the original protobuf channel""" self.sensor_name: str = channel.sensor_name """Provided sensor name""" self.channel_types: typing.List[ typing.Union[ api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]] = reader_utils.repeated_to_list(channel.channel_types) """List of channel type constant enumerations""" self.payload: numpy.ndarray = reader_utils.extract_payload(channel) """This channels payload as a numpy array of either floats or ints""" self.metadata: typing.List[str] = reader_utils.repeated_to_list(channel.metadata) """This channels list of metadata""" self.value_means: numpy.ndarray = reader_utils.repeated_to_array(channel.value_means) """Interleaved array of mean values""" self.value_stds: numpy.ndarray = reader_utils.repeated_to_array(channel.value_stds) """Interleaved array of standard deviations of values""" self.value_medians: numpy.ndarray = reader_utils.repeated_to_array(channel.value_medians) """Interleaves array of median values""" self.channel_type_index: typing.Dict[api900_pb2.ChannelType, int] = {self.channel_types[i]: i for i in range( len( self.channel_types))} """Contains a mapping of channel type to index in channel_types array""" def set_channel_types(self, types: typing.List[typing.Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]]): """ sets the channel_types to the list given :param types: a list of channel types """ del self.protobuf_channel.channel_types[:] for ctype in types: self.protobuf_channel.channel_types.append(ctype) self.channel_types = reader_utils.repeated_to_list(self.protobuf_channel.channel_types) self.channel_type_index = {self.channel_types[i]: i for i in range(len(self.channel_types))} def get_channel_type_names(self) -> typing.List[str]: """ Returns the list of channel_types as a list of names instead of enumeration constants. :return: The list of channel_types as a list of names instead of enumeration constants. """ return list(map(reader_utils.channel_type_name_from_enum, self.channel_types)) def channel_index(self, channel_type: int) -> int: """ Returns the index of a channel type or -1 if it DNE. :param channel_type: The channel type to search for. :return: The index of the channel or -1 if it DNE. """ return self.channel_type_index[channel_type] if channel_type in self.channel_type_index else -1 def has_channel(self, channel_type: int) -> bool: """ Returns if channel type exists with in this channel. :param channel_type: The channel type to search for. :return: True if it exist, False otherwise. """ return channel_type in self.channel_type_index def set_channel(self, channel: typing.Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]): """ Sets the protobuf channel :param channel: protobuf channel """ self.protobuf_channel = channel self.sensor_name = channel.sensor_name self.channel_types = reader_utils.repeated_to_list(channel.channel_types) self.payload = reader_utils.extract_payload(channel) self.metadata = reader_utils.repeated_to_list(channel.metadata) self.value_means = reader_utils.repeated_to_array(channel.value_means) self.value_stds = reader_utils.repeated_to_array(channel.value_stds) self.value_medians = reader_utils.repeated_to_array(channel.value_medians) self.channel_type_index = {self.channel_types[i]: i for i in range(len(self.channel_types))} def has_payload(self, channel_type: int) -> bool: """ Returns if channel contains a non-empty specified payload. :param channel_type: The channel to check for a payload for. :return: Whether this channel contains the specified payload. """ return self.has_channel(channel_type) and len(self.payload) > 0 def set_payload(self, payload_values: typing.Union[numpy.ndarray, typing.List], pl_type: constants.PayloadType, should_compute_stats=True): """ sets the payload to an interleaved channel with step number of arrays interleaved together. :param should_compute_stats: Whether the statistics should be computed or not (optional default to True) :param payload_values: Interleaved payload values :param pl_type: payload type """ # if len(payload_values) < 1: # raise exceptions.ReaderException("Channel must not be empty and number of arrays must not be less than # 1.") # Convert to numpy array is necessary payload_values = reader_utils.to_array(payload_values) # clear all other payloads self.protobuf_channel.byte_payload.ClearField("payload") self.protobuf_channel.uint32_payload.ClearField("payload") self.protobuf_channel.uint64_payload.ClearField("payload") self.protobuf_channel.int32_payload.ClearField("payload") self.protobuf_channel.int64_payload.ClearField("payload") self.protobuf_channel.float32_payload.ClearField("payload") self.protobuf_channel.float64_payload.ClearField("payload") # set the payload based on the type of data if pl_type == constants.PayloadType.BYTE_PAYLOAD: self.protobuf_channel.byte_payload.payload = payload_values elif pl_type == constants.PayloadType.UINT32_PAYLOAD: self.protobuf_channel.uint32_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.UINT64_PAYLOAD: self.protobuf_channel.uint64_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.INT32_PAYLOAD: self.protobuf_channel.int32_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.INT64_PAYLOAD: self.protobuf_channel.int64_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.FLOAT32_PAYLOAD: self.protobuf_channel.float32_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.FLOAT64_PAYLOAD: self.protobuf_channel.float64_payload.payload.extend(payload_values) else: raise TypeError("Unknown payload type to set.") if len(payload_values) < 1: self.payload = payload_values else: self.payload = reader_utils.extract_payload(self.protobuf_channel) # calculate the means, std devs, and medians if should_compute_stats: self.update_stats() def set_interleaved_payload(self, payloads: typing.List[typing.Union[typing.List, numpy.ndarray]], pl_type: constants.PayloadType, should_compute_stats: bool = True): """ Interleaves multiple payloads together and sets the interleaved payload. :param payloads: Payloads of the same length to be interleaved. :param pl_type: The payload type :param should_compute_stats: Whether or not payload stats should be calculated. """ interleaved = reader_utils.interleave_arrays(list(map(reader_utils.to_array, payloads))) self.set_payload(interleaved, pl_type, should_compute_stats) def get_payload(self, channel_type: int) -> numpy.ndarray: """ Returns a deinterleaved payload of a given channel type or an empty array. :param channel_type: The channel type to extract/deinterleave from the payload. :return: A numpy array of floats or ints of a single channel type. """ idx = self.channel_index(channel_type) if idx < 0: return reader_utils.empty_array() try: payload: numpy.ndarray = reader_utils.deinterleave_array(self.payload, idx, len(self.channel_types)) return migrations.maybe_get_float(payload) except exceptions.ReaderException: return reader_utils.empty_array() def get_payload_type(self) -> str: """ Returns the internal protobuf payload type. :return: The internal protobuf payload type. """ return reader_utils.payload_type(self.protobuf_channel) def get_multi_payload(self, channel_types: typing.List[int]) -> numpy.ndarray: """ Returns an interleaved payload with the given channel types. :param channel_types: Channel types to interleave into a single payload. :return: A numpy array of an interleaved payload. """ channel_types_len = len(channel_types) if channel_types_len == 0: return reader_utils.empty_array() elif channel_types_len == 1: return self.get_payload(channel_types[0]) payloads = list(map(self.get_payload, channel_types)) return reader_utils.interleave_arrays(payloads) def get_value_mean(self, channel_type: int) -> float: """ Returns the mean value for a single channel type. :param channel_type: The channel type to extract the mean from. :return: The mean value. """ idx = self.channel_index(channel_type) if idx < 0 or len(self.value_means) == 0: raise exceptions.ReaderException("mean DNE, is the payload empty?") return self.value_means[idx] def get_value_std(self, channel_type: int) -> float: """ Returns the standard deviation value for a single channel type. :param channel_type: The channel type to extract the std from. :return: The standard deviation. """ idx = self.channel_index(channel_type) if idx < 0 or len(self.value_stds) == 0: raise exceptions.ReaderException("std DNE, is the payload empty?") return self.value_stds[idx] def get_value_median(self, channel_type: int) -> float: """ Returns the median value for a single channel type. :param channel_type: The channel type to extract the median from. :return:The median value. """ idx = self.channel_index(channel_type) if idx < 0 or len(self.value_medians) == 0: raise exceptions.ReaderException("median DNE, is the payload empty?") return self.value_medians[idx] def update_stats(self): """ updates mean, std and median for all values """ channel = self.payload step = len(self.channel_types) del self.protobuf_channel.value_means[:] del self.protobuf_channel.value_stds[:] del self.protobuf_channel.value_medians[:] for i in range(step): std, mean, median = stat_utils.calc_utils(reader_utils.deinterleave_array(channel, i, step)) self.protobuf_channel.value_means.append(mean) self.protobuf_channel.value_stds.append(std) self.protobuf_channel.value_medians.append(median) self.value_stds = reader_utils.repeated_to_array(self.protobuf_channel.value_stds) self.value_means = reader_utils.repeated_to_array(self.protobuf_channel.value_means) self.value_medians = reader_utils.repeated_to_array(self.protobuf_channel.value_medians) def set_sensor_name(self, name: str): """ sets the sensor name :param name: name of sensor """ self.sensor_name = name self.protobuf_channel.sensor_name = name def set_metadata(self, data: typing.List[str]): """ sets the metadata :param data: metadata as list of strings """ del self.protobuf_channel.metadata[:] for meta in data: self.protobuf_channel.metadata.append(meta) self.metadata = reader_utils.repeated_to_list(self.protobuf_channel.metadata) def metadata_as_dict(self) -> typing.Dict[str, str]: """ Returns any metadata as a dictionary of key-pair values. :return: Any metadata as a dictionary of key-pair values. """ return reader_utils.get_metadata_as_dict(self.metadata) def __str__(self) -> str: """ Returns a string representation of this interleaved channel. :return: A string representation of this interleaved chanel. """ return "sensor_name: {}\n" \ "channel_types: {}\n" \ "len(payload): {}\n" \ "payload_type: {}".format(self.sensor_name, list(map( reader_utils.channel_type_name_from_enum, self.channel_types)), len(self.payload), reader_utils.payload_type( self.protobuf_channel))
Subclasses
Methods
def channel_index(self, channel_type: int) ‑> int
-
Returns the index of a channel type or -1 if it DNE. :param channel_type: The channel type to search for. :return: The index of the channel or -1 if it DNE.
Expand source code
def channel_index(self, channel_type: int) -> int: """ Returns the index of a channel type or -1 if it DNE. :param channel_type: The channel type to search for. :return: The index of the channel or -1 if it DNE. """ return self.channel_type_index[channel_type] if channel_type in self.channel_type_index else -1
def get_channel_type_names(self) ‑> List[str]
-
Returns the list of channel_types as a list of names instead of enumeration constants. :return: The list of channel_types as a list of names instead of enumeration constants.
Expand source code
def get_channel_type_names(self) -> typing.List[str]: """ Returns the list of channel_types as a list of names instead of enumeration constants. :return: The list of channel_types as a list of names instead of enumeration constants. """ return list(map(reader_utils.channel_type_name_from_enum, self.channel_types))
def get_multi_payload(self, channel_types: List[int]) ‑> numpy.ndarray
-
Returns an interleaved payload with the given channel types. :param channel_types: Channel types to interleave into a single payload. :return: A numpy array of an interleaved payload.
Expand source code
def get_multi_payload(self, channel_types: typing.List[int]) -> numpy.ndarray: """ Returns an interleaved payload with the given channel types. :param channel_types: Channel types to interleave into a single payload. :return: A numpy array of an interleaved payload. """ channel_types_len = len(channel_types) if channel_types_len == 0: return reader_utils.empty_array() elif channel_types_len == 1: return self.get_payload(channel_types[0]) payloads = list(map(self.get_payload, channel_types)) return reader_utils.interleave_arrays(payloads)
def get_payload(self, channel_type: int) ‑> numpy.ndarray
-
Returns a deinterleaved payload of a given channel type or an empty array. :param channel_type: The channel type to extract/deinterleave from the payload. :return: A numpy array of floats or ints of a single channel type.
Expand source code
def get_payload(self, channel_type: int) -> numpy.ndarray: """ Returns a deinterleaved payload of a given channel type or an empty array. :param channel_type: The channel type to extract/deinterleave from the payload. :return: A numpy array of floats or ints of a single channel type. """ idx = self.channel_index(channel_type) if idx < 0: return reader_utils.empty_array() try: payload: numpy.ndarray = reader_utils.deinterleave_array(self.payload, idx, len(self.channel_types)) return migrations.maybe_get_float(payload) except exceptions.ReaderException: return reader_utils.empty_array()
def get_payload_type(self) ‑> str
-
Returns the internal protobuf payload type. :return: The internal protobuf payload type.
Expand source code
def get_payload_type(self) -> str: """ Returns the internal protobuf payload type. :return: The internal protobuf payload type. """ return reader_utils.payload_type(self.protobuf_channel)
def get_value_mean(self, channel_type: int) ‑> float
-
Returns the mean value for a single channel type. :param channel_type: The channel type to extract the mean from. :return: The mean value.
Expand source code
def get_value_mean(self, channel_type: int) -> float: """ Returns the mean value for a single channel type. :param channel_type: The channel type to extract the mean from. :return: The mean value. """ idx = self.channel_index(channel_type) if idx < 0 or len(self.value_means) == 0: raise exceptions.ReaderException("mean DNE, is the payload empty?") return self.value_means[idx]
def get_value_median(self, channel_type: int) ‑> float
-
Returns the median value for a single channel type. :param channel_type: The channel type to extract the median from. :return:The median value.
Expand source code
def get_value_median(self, channel_type: int) -> float: """ Returns the median value for a single channel type. :param channel_type: The channel type to extract the median from. :return:The median value. """ idx = self.channel_index(channel_type) if idx < 0 or len(self.value_medians) == 0: raise exceptions.ReaderException("median DNE, is the payload empty?") return self.value_medians[idx]
def get_value_std(self, channel_type: int) ‑> float
-
Returns the standard deviation value for a single channel type. :param channel_type: The channel type to extract the std from. :return: The standard deviation.
Expand source code
def get_value_std(self, channel_type: int) -> float: """ Returns the standard deviation value for a single channel type. :param channel_type: The channel type to extract the std from. :return: The standard deviation. """ idx = self.channel_index(channel_type) if idx < 0 or len(self.value_stds) == 0: raise exceptions.ReaderException("std DNE, is the payload empty?") return self.value_stds[idx]
def has_channel(self, channel_type: int) ‑> bool
-
Returns if channel type exists with in this channel. :param channel_type: The channel type to search for. :return: True if it exist, False otherwise.
Expand source code
def has_channel(self, channel_type: int) -> bool: """ Returns if channel type exists with in this channel. :param channel_type: The channel type to search for. :return: True if it exist, False otherwise. """ return channel_type in self.channel_type_index
def has_payload(self, channel_type: int) ‑> bool
-
Returns if channel contains a non-empty specified payload. :param channel_type: The channel to check for a payload for. :return: Whether this channel contains the specified payload.
Expand source code
def has_payload(self, channel_type: int) -> bool: """ Returns if channel contains a non-empty specified payload. :param channel_type: The channel to check for a payload for. :return: Whether this channel contains the specified payload. """ return self.has_channel(channel_type) and len(self.payload) > 0
def metadata_as_dict(self) ‑> Dict[str, str]
-
Returns any metadata as a dictionary of key-pair values. :return: Any metadata as a dictionary of key-pair values.
Expand source code
def metadata_as_dict(self) -> typing.Dict[str, str]: """ Returns any metadata as a dictionary of key-pair values. :return: Any metadata as a dictionary of key-pair values. """ return reader_utils.get_metadata_as_dict(self.metadata)
def set_channel(self, channel: Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel])
-
Sets the protobuf channel :param channel: protobuf channel
Expand source code
def set_channel(self, channel: typing.Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]): """ Sets the protobuf channel :param channel: protobuf channel """ self.protobuf_channel = channel self.sensor_name = channel.sensor_name self.channel_types = reader_utils.repeated_to_list(channel.channel_types) self.payload = reader_utils.extract_payload(channel) self.metadata = reader_utils.repeated_to_list(channel.metadata) self.value_means = reader_utils.repeated_to_array(channel.value_means) self.value_stds = reader_utils.repeated_to_array(channel.value_stds) self.value_medians = reader_utils.repeated_to_array(channel.value_medians) self.channel_type_index = {self.channel_types[i]: i for i in range(len(self.channel_types))}
def set_channel_types(self, types: List[Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]])
-
sets the channel_types to the list given :param types: a list of channel types
Expand source code
def set_channel_types(self, types: typing.List[typing.Union[api900_pb2.EvenlySampledChannel, api900_pb2.UnevenlySampledChannel]]): """ sets the channel_types to the list given :param types: a list of channel types """ del self.protobuf_channel.channel_types[:] for ctype in types: self.protobuf_channel.channel_types.append(ctype) self.channel_types = reader_utils.repeated_to_list(self.protobuf_channel.channel_types) self.channel_type_index = {self.channel_types[i]: i for i in range(len(self.channel_types))}
def set_interleaved_payload(self, payloads: List[Union[List, numpy.ndarray]], pl_type: PayloadType, should_compute_stats: bool = True)
-
Interleaves multiple payloads together and sets the interleaved payload. :param payloads: Payloads of the same length to be interleaved. :param pl_type: The payload type :param should_compute_stats: Whether or not payload stats should be calculated.
Expand source code
def set_interleaved_payload(self, payloads: typing.List[typing.Union[typing.List, numpy.ndarray]], pl_type: constants.PayloadType, should_compute_stats: bool = True): """ Interleaves multiple payloads together and sets the interleaved payload. :param payloads: Payloads of the same length to be interleaved. :param pl_type: The payload type :param should_compute_stats: Whether or not payload stats should be calculated. """ interleaved = reader_utils.interleave_arrays(list(map(reader_utils.to_array, payloads))) self.set_payload(interleaved, pl_type, should_compute_stats)
def set_metadata(self, data: List[str])
-
sets the metadata :param data: metadata as list of strings
Expand source code
def set_metadata(self, data: typing.List[str]): """ sets the metadata :param data: metadata as list of strings """ del self.protobuf_channel.metadata[:] for meta in data: self.protobuf_channel.metadata.append(meta) self.metadata = reader_utils.repeated_to_list(self.protobuf_channel.metadata)
def set_payload(self, payload_values: Union[List, numpy.ndarray], pl_type: PayloadType, should_compute_stats=True)
-
sets the payload to an interleaved channel with step number of arrays interleaved together. :param should_compute_stats: Whether the statistics should be computed or not (optional default to True) :param payload_values: Interleaved payload values :param pl_type: payload type
Expand source code
def set_payload(self, payload_values: typing.Union[numpy.ndarray, typing.List], pl_type: constants.PayloadType, should_compute_stats=True): """ sets the payload to an interleaved channel with step number of arrays interleaved together. :param should_compute_stats: Whether the statistics should be computed or not (optional default to True) :param payload_values: Interleaved payload values :param pl_type: payload type """ # if len(payload_values) < 1: # raise exceptions.ReaderException("Channel must not be empty and number of arrays must not be less than # 1.") # Convert to numpy array is necessary payload_values = reader_utils.to_array(payload_values) # clear all other payloads self.protobuf_channel.byte_payload.ClearField("payload") self.protobuf_channel.uint32_payload.ClearField("payload") self.protobuf_channel.uint64_payload.ClearField("payload") self.protobuf_channel.int32_payload.ClearField("payload") self.protobuf_channel.int64_payload.ClearField("payload") self.protobuf_channel.float32_payload.ClearField("payload") self.protobuf_channel.float64_payload.ClearField("payload") # set the payload based on the type of data if pl_type == constants.PayloadType.BYTE_PAYLOAD: self.protobuf_channel.byte_payload.payload = payload_values elif pl_type == constants.PayloadType.UINT32_PAYLOAD: self.protobuf_channel.uint32_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.UINT64_PAYLOAD: self.protobuf_channel.uint64_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.INT32_PAYLOAD: self.protobuf_channel.int32_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.INT64_PAYLOAD: self.protobuf_channel.int64_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.FLOAT32_PAYLOAD: self.protobuf_channel.float32_payload.payload.extend(payload_values) elif pl_type == constants.PayloadType.FLOAT64_PAYLOAD: self.protobuf_channel.float64_payload.payload.extend(payload_values) else: raise TypeError("Unknown payload type to set.") if len(payload_values) < 1: self.payload = payload_values else: self.payload = reader_utils.extract_payload(self.protobuf_channel) # calculate the means, std devs, and medians if should_compute_stats: self.update_stats()
def set_sensor_name(self, name: str)
-
sets the sensor name :param name: name of sensor
Expand source code
def set_sensor_name(self, name: str): """ sets the sensor name :param name: name of sensor """ self.sensor_name = name self.protobuf_channel.sensor_name = name
def update_stats(self)
-
updates mean, std and median for all values
Expand source code
def update_stats(self): """ updates mean, std and median for all values """ channel = self.payload step = len(self.channel_types) del self.protobuf_channel.value_means[:] del self.protobuf_channel.value_stds[:] del self.protobuf_channel.value_medians[:] for i in range(step): std, mean, median = stat_utils.calc_utils(reader_utils.deinterleave_array(channel, i, step)) self.protobuf_channel.value_means.append(mean) self.protobuf_channel.value_stds.append(std) self.protobuf_channel.value_medians.append(median) self.value_stds = reader_utils.repeated_to_array(self.protobuf_channel.value_stds) self.value_means = reader_utils.repeated_to_array(self.protobuf_channel.value_means) self.value_medians = reader_utils.repeated_to_array(self.protobuf_channel.value_medians)