Example #1
0
def main():
    descr = "Merge data from Peripheral and Central. Synchronization events" \
            " should be registered at the beginning and at the end of" \
            " measurements (used to compensate clock drift)."
    parser = argparse.ArgumentParser(description=descr)
    parser.add_argument("peripheral_dataset", help="Name of Peripheral dataset")
    parser.add_argument("peripheral_sync_event",
                        help="Event used for synchronization - Peripheral")
    parser.add_argument("central_dataset", help="Name of Central dataset")
    parser.add_argument("central_sync_event",
                        help="Event used for synchronization - Central")
    parser.add_argument("result_dataset", help="Name for result dataset")
    args = parser.parse_args()

    evt_peripheral = ProcessedEvents()
    evt_peripheral.read_data_from_files(args.peripheral_dataset + ".csv",
                                        args.peripheral_dataset + ".json")

    evt_central = ProcessedEvents()
    evt_central.read_data_from_files(args.central_dataset + ".csv",
                                     args.central_dataset + ".json")

    # Compensating clock drift - based on synchronization events
    sync_evt_peripheral = evt_peripheral.get_event_type_id(args.peripheral_sync_event)
    sync_evt_central = evt_central.get_event_type_id(args.central_sync_event)

    sync_peripheral = list(filter(lambda x: x.submit.type_id == sync_evt_peripheral,
                                  evt_peripheral.tracked_events))

    sync_central = list(filter(lambda x: x.submit.type_id == sync_evt_central,
                               evt_central.tracked_events))

    ts_peripheral = np.array(list(map(lambda x: list([x.submit.timestamp, x.proc_start_time, x.proc_end_time]),
                                      evt_peripheral.tracked_events)))
    sync_ts_peripheral = list(map(lambda x: x.submit.timestamp, sync_peripheral))
    sync_ts_central = list(map(lambda x: x.submit.timestamp, sync_central))

    sync_diffs_central = np.subtract(sync_ts_central[1:], sync_ts_central[:-1])
    sync_diffs_peripheral = np.subtract(sync_ts_peripheral[1:], sync_ts_peripheral[:-1])

    rounded_diffs_central = list(map(lambda x: round(x, 1), sync_diffs_central))
    rounded_diffs_peripheral = list(map(lambda x: round(x, 1), sync_diffs_peripheral))

    shift_c = rounded_diffs_central.index(rounded_diffs_peripheral[0])
    shift_p = rounded_diffs_peripheral.index(rounded_diffs_central[0])

    if shift_c < shift_p:
        sync_ts_central = sync_ts_central[shift_c:]
    elif shift_p < shift_c:
        sync_ts_peripheral = sync_ts_peripheral[shift_p:]

    if len(sync_ts_central) < len(sync_ts_peripheral):
        sync_ts_peripheral = sync_ts_peripheral[:len(sync_ts_central)]
    elif len(sync_ts_peripheral) < len(sync_ts_central):
        sync_ts_central = sync_ts_central[:len(sync_ts_peripheral)]

    new_ts_peripheral = ts_peripheral.copy()
    new_ts_peripheral[list(list(elem is not None for elem in row) for row in new_ts_peripheral)] = \
        sync_peripheral_ts(ts_peripheral, sync_ts_peripheral, sync_ts_central)
    assert len(new_ts_peripheral) == len(ts_peripheral)
    # Reindexing, renaming and compensating time differences for peripheral events
    max_central_id = max([int(i) for i in evt_central.registered_events_types])

    assert len(new_ts_peripheral) == len(evt_peripheral.tracked_events)
    evt_peripheral.tracked_events = list(map(lambda x, y:
                                         TrackedEvent(Event(x.submit.type_id + max_central_id + 1, y[0], x.submit.data),
                                                      y[1],
                                                      y[2]),
                                             evt_peripheral.tracked_events, new_ts_peripheral))

    evt_peripheral.registered_events_types = {k + max_central_id + 1 :
                EventType(v.name + "_peripheral", v.data_types, v.data_descriptions)
                for k, v in evt_peripheral.registered_events_types.items()}

    evt_central.registered_events_types = {
                k : EventType(v.name + "_central",
                              v.data_types, v.data_descriptions)
                for k, v in evt_central.registered_events_types.items()}

    # Filter out events that are out of synchronization period
    TIME_DIFF = 0.5
    start_time = sync_ts_central[0] - TIME_DIFF
    end_time = sync_ts_central[-1] + TIME_DIFF
    evt_peripheral.tracked_events = list(filter(lambda x:
        x.submit.timestamp >= start_time and (x.proc_end_time <= end_time if x.proc_end_time is not None \
            else x.submit.timestamp <= end_time),
        evt_peripheral.tracked_events))

    evt_central.tracked_events = list(filter(lambda x:
        x.submit.timestamp >= start_time and (x.proc_end_time <= end_time if x.proc_end_time is not None \
            else x.submit.timestamp <= end_time),
        evt_central.tracked_events))

    # Filter out events that were out of interpolation range
    evt_peripheral.tracked_events = list(filter(lambda x:
        INTERP_OUT_OF_RANGE_VAL not in (x.submit.timestamp, x.proc_start_time, x.proc_end_time),
        evt_peripheral.tracked_events))

    all_registered_events_types = evt_peripheral.registered_events_types.copy()
    all_registered_events_types.update(evt_central.registered_events_types)

    result_events = ProcessedEvents()
    result_events.tracked_events = evt_peripheral.tracked_events + evt_central.tracked_events
    result_events.registered_events_types = all_registered_events_types

    result_events.write_data_to_files(args.result_dataset + ".csv",
                                      args.result_dataset + ".json")

    print('Profiler data merged successfully')
class StatsNordic():
    def __init__(self, events_filename, events_types_filename, log_lvl):
        self.data_name = events_filename.split('.')[0]
        self.processed_data = ProcessedEvents()
        self.processed_data.read_data_from_files(events_filename, events_types_filename)

        self.logger = logging.getLogger('Stats Nordic')
        self.logger_console = logging.StreamHandler()
        self.logger.setLevel(log_lvl)
        self.log_format = logging.Formatter(
            '[%(levelname)s] %(name)s: %(message)s')
        self.logger_console.setFormatter(self.log_format)
        self.logger.addHandler(self.logger_console)

    def calculate_stats_preset1(self, start_meas, end_meas):
        self.time_between_events("hid_mouse_event_dongle", EventState.SUBMIT,
                                 "hid_report_sent_event_device", EventState.SUBMIT,
                                 0.05, start_meas, end_meas)
        self.time_between_events("hid_mouse_event_dongle", EventState.SUBMIT,
                                 "hid_report_sent_event_device", EventState.SUBMIT,
                                 0.05, start_meas, end_meas)
        self.time_between_events("hid_report_sent_event_dongle", EventState.SUBMIT,
                                 "hid_report_sent_event_dongle", EventState.SUBMIT,
                                 0.05, start_meas, end_meas)
        self.time_between_events("hid_mouse_event_dongle", EventState.SUBMIT,
                                 "hid_report_sent_event_dongle", EventState.SUBMIT,
                                 0.05, start_meas, end_meas)
        self.time_between_events("hid_mouse_event_device", EventState.SUBMIT,
                                 "hid_mouse_event_dongle", EventState.SUBMIT,
                                 0.05, start_meas, end_meas)
        plt.show()

    def _get_timestamps(self, event_name, event_state, start_meas, end_meas):
        event_type_id = self.processed_data.get_event_type_id(event_name)
        if event_type_id is None:
            self.logger.error("Event name not found: " + event_name)
            return None
        if not self.processed_data.is_event_tracked(event_type_id) and event_state != EventState.SUBMIT:
            self.logger.error("This event is not tracked: " + event_name)
            return None

        trackings = list(filter(lambda x:
                      x.submit.type_id == event_type_id,
                      self.processed_data.tracked_events))

        if not isinstance(event_state, EventState):
            self.logger.error("Event state should be EventState enum")
            return None

        if event_state == EventState.SUBMIT:
            timestamps = np.fromiter(map(lambda x: x.submit.timestamp, trackings),
                                     dtype=np.float)
        elif event_state == EventState.PROC_START:
            timestamps = np.fromiter(map(lambda x: x.proc_start_time, trackings),
                                     dtype=np.float)
        elif event_state == EventState.PROC_END:
            timestamps = np.fromiter(map(lambda x: x.proc_end_time, trackings),
                                     dtype=np.float)

        timestamps = timestamps[np.where((timestamps > start_meas)
                                         & (timestamps < end_meas))]

        return timestamps

    @staticmethod
    def calculate_times_between(start_times, end_times):
        if end_times[0] <= start_times[0]:
            end_times = end_times[1:]
        if len(start_times) > len(end_times):
            start_times = start_times[:-1]

        return (end_times - start_times) * 1000

    @staticmethod
    def prepare_stats_txt(times_between):
        stats_text = "Max time: "
        stats_text += "{0:.3f}".format(max(times_between)) + "ms\n"
        stats_text += "Min time: "
        stats_text += "{0:.3f}".format(min(times_between)) + "ms\n"
        stats_text += "Mean time: "
        stats_text += "{0:.3f}".format(np.mean(times_between)) + "ms\n"
        stats_text += "Std dev of time: "
        stats_text += "{0:.3f}".format(np.std(times_between)) + "ms\n"
        stats_text += "Median time: "
        stats_text += "{0:.3f}".format(np.median(times_between)) + "ms\n"
        stats_text += "Number of records: {}".format(len(times_between)) + "\n"

        return stats_text

    def time_between_events(self, start_event_name, start_event_state,
                            end_event_name, end_event_state, hist_bin_width=0.01,
                            start_meas=0, end_meas=float('inf')):
        self.logger.info("Stats calculating: {}->{}".format(start_event_name,
                                                            end_event_name))

        start_times = self._get_timestamps(start_event_name, start_event_state,
                                           start_meas, end_meas)
        end_times = self._get_timestamps(end_event_name, end_event_state,
                                           start_meas, end_meas)

        if start_times is None or end_times is None:
            return

        if len(start_times) == 0:
            self.logger.error("No events logged: " + start_event_name)
            return

        if len(end_times) == 0:
            self.logger.error("No events logged: " + end_event_name)
            return

        if len(start_times) != len(end_times):
            self.logger.error("Number of start_times and end_times is not equal")
            self.logger.error("Got {} start_times and {} end_times".format(
                len(start_times), len(end_times)))

            return

        times_between = self.calculate_times_between(start_times, end_times)
        stats_text = self.prepare_stats_txt(times_between)

        plt.figure()

        ax = plt.gca()
        ax.text(0.05,
                0.95,
                stats_text,
                transform=ax.transAxes,
                fontsize=12,
                verticalalignment='top',
                bbox=dict(boxstyle='round',
                            alpha=0.5,
                            facecolor='linen'))

        plt.xlabel('Duration[ms]')
        plt.ylabel('Number of occurrences')

        event_status_str = {
                        EventState.SUBMIT : "submission",
                        EventState.PROC_START : "processing start",
                        EventState.PROC_END : "processing end"
        }

        title = "From " + start_event_name + ' ' + \
                event_status_str[start_event_state] + "\nto " + \
                end_event_name + ' ' + event_status_str[end_event_state] + \
                ' (' + self.data_name + ')'
        plt.title(title)
        plt.hist(times_between, bins = (int)((max(times_between) - min(times_between))
                                        / hist_bin_width))

        plt.yscale('log')
        plt.grid(True)

        if end_meas == float('inf'):
            end_meas_string = 'inf'
        else:
            end_meas_string = int(end_meas)
        dir_name = "{}{}_{}_{}/".format(OUTPUT_FOLDER, self.data_name,
                                        int(start_meas), end_meas_string)
        if not os.path.exists(dir_name):
            os.makedirs(dir_name)

        plt.savefig(dir_name +
                    title.lower().replace(' ', '_').replace('\n', '_') +'.png')