def test_unevenly_sampled_channel_int64_payload(self):
     correct = [1, 2, 3, 4, 5]
     unevenly_sampled_channel = mock.set_payload(
         self.unevenly_sampled_channel, numpy.int64, correct)
     self.assertArraysEqual(
         reader_utils.extract_payload(unevenly_sampled_channel),
         numpy.array(correct))
 def test_evenly_sampled_channel_float64_payload(self):
     correct = [1.0, 2.0, 3.0, 4.0, 5.0]
     evenly_sampled_channel = mock.set_payload(self.evenly_sampled_channel,
                                               numpy.float64, correct)
     self.assertArraysEqual(
         reader_utils.extract_payload(evenly_sampled_channel),
         numpy.array(correct))
 def test_evenly_sampled_channel_uint32_payload(self):
     correct = [1, 2, 3, 4, 5]
     evenly_sampled_channel = mock.set_payload(self.evenly_sampled_channel,
                                               numpy.uint32, correct)
     self.assertArraysEqual(
         reader_utils.extract_payload(evenly_sampled_channel),
         numpy.array(correct))
def time_sync_data_from_raw_packet(
        packet: Union[RedvoxPacketM, RedvoxPacket]) -> TimeSyncData:
    """
    :param packet: data packet to get time sync data from
    :return: TimeSyncData object from data packet
    """
    tsd: TimeSyncData
    if isinstance(packet, RedvoxPacketM):
        exchanges: List[float] = reduce(
            lambda acc, ex: acc + [ex.a1, ex.a2, ex.a3, ex.b1, ex.b2, ex.b3],
            packet.timing_information.synch_exchanges, [])
        tsd = TimeSyncData(
            packet.station_information.id, packet.sensors.audio.sample_rate,
            len(packet.sensors.audio.samples.values),
            packet.timing_information.app_start_mach_timestamp,
            packet.timing_information.server_acquisition_arrival_timestamp,
            packet.timing_information.packet_start_mach_timestamp,
            packet.timing_information.packet_end_mach_timestamp, exchanges,
            packet.timing_information.best_latency,
            packet.timing_information.best_offset)
    else:
        mtz: float = np.nan
        best_latency: float = np.nan
        best_offset: float = np.nan

        for i, v in enumerate(packet.metadata):
            plus_1: int = i + 1
            try:
                if v == "machTimeZero" and plus_1 < len(packet.metadata):
                    mtz = float(packet.metadata[plus_1])
                if v == "bestLatency" and plus_1 < len(packet.metadata):
                    best_latency = float(packet.metadata[plus_1])
                if v == "bestOffset" and plus_1 < len(packet.metadata):
                    best_offset = float(packet.metadata[plus_1])
            except (KeyError, ValueError):
                continue

        # Get synch exchanges
        exchanges: Optional[np.ndarray] = None
        ch: api900_pb2.UnevenlySampledChannel
        for ch in packet.unevenly_sampled_channels:
            if api900_pb2.TIME_SYNCHRONIZATION in ch.channel_types:
                exchanges = util_900.extract_payload(ch)

        tsd = TimeSyncData(
            packet.redvox_id,
            packet.evenly_sampled_channels[0].sample_rate_hz,
            util_900.payload_len(packet.evenly_sampled_channels[0]),
            mtz,
            packet.evenly_sampled_channels[0].
            first_sample_timestamp_epoch_microseconds_utc,
            packet.server_timestamp_epoch_microseconds_utc,
            packet.app_file_start_timestamp_machine,
            list(exchanges),
            best_latency,
            best_offset,
        )

    return tsd
    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_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 __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 from_raw_packets(
        self, packets: List[Union[RedvoxPacketM,
                                  RedvoxPacket]]) -> 'TimeSyncAnalysis':
        """
        converts packets into TimeSyncData objects, then performs analysis

        :param packets: list of WrappedRedvoxPacketM to convert
        :return: modified version of self
        """
        timesync_data: List[TimeSyncData] = []

        packet: Union[RedvoxPacketM, RedvoxPacket]
        for packet in packets:
            tsd: TimeSyncData
            if isinstance(packet, RedvoxPacketM):
                exchanges: List[float] = reduce(
                    lambda acc, ex: acc +
                    [ex.a1, ex.a2, ex.a3, ex.b1, ex.b2, ex.b3],
                    packet.timing_information.synch_exchanges, [])
                tsd = TimeSyncData(
                    packet.station_information.id,
                    packet.sensors.audio.sample_rate,
                    len(packet.sensors.audio.samples.values),
                    packet.timing_information.app_start_mach_timestamp, packet.
                    timing_information.server_acquisition_arrival_timestamp,
                    packet.timing_information.packet_start_mach_timestamp,
                    packet.timing_information.packet_end_mach_timestamp,
                    exchanges, packet.timing_information.best_latency,
                    packet.timing_information.best_offset)
            else:
                mtz: float = np.nan
                best_latency: float = np.nan
                best_offset: float = np.nan

                for i, v in enumerate(packet.metadata):
                    plus_1: int = i + 1
                    try:
                        if v == "machTimeZero" and plus_1 < len(
                                packet.metadata):
                            mtz = float(packet.metadata[plus_1])
                        if v == "bestLatency" and plus_1 < len(
                                packet.metadata):
                            best_latency = float(packet.metadata[plus_1])
                        if v == "bestOffset" and plus_1 < len(packet.metadata):
                            best_offset = float(packet.metadata[plus_1])
                    except (KeyError, ValueError):
                        continue

                # Get synch exchanges
                exchanges: Optional[np.ndarray] = None
                ch: api900_pb2.UnevenlySampledChannel
                for ch in packet.unevenly_sampled_channels:
                    if api900_pb2.TIME_SYNCHRONIZATION in ch.channel_types:
                        exchanges = util_900.extract_payload(ch)

                tsd = TimeSyncData(
                    packet.redvox_id,
                    packet.evenly_sampled_channels[0].sample_rate_hz,
                    util_900.payload_len(packet.evenly_sampled_channels[0]),
                    mtz,
                    packet.evenly_sampled_channels[0].
                    first_sample_timestamp_epoch_microseconds_utc,
                    packet.server_timestamp_epoch_microseconds_utc,
                    packet.app_file_start_timestamp_machine,
                    list(exchanges),
                    best_latency,
                    best_offset,
                )

            timesync_data.append(tsd)

        self.timesync_data = timesync_data

        if len(self.timesync_data) > 0:
            self.evaluate_and_validate_data()

        return self