def setup_distance_detectors(config, session_info, sensors):
    processing_config = presence_detection.get_processing_config()
    processing_config.inter_frame_fast_cutoff = 100
    processing_config.inter_frame_slow_cutoff = 1
    processing_config.inter_frame_deviation_time_const = 0.01
    processing_config.intra_frame_time_const = 0.01
    processing_config.intra_frame_weight = 0.7
    processing_config.detection_threshold = 0
    processors = {}
    tags = []
    sensor_id = 0
    config.sensor = sensors[sensor_id]
    for s in sensors:
        tag = "sensor_{}".format(s)
        tags.append(tag)
        processors[tag] = presence_detection.Processor(config,
                                                       processing_config,
                                                       session_info)
        processors[tag].depth_filter_length = 1
        sensor_id += 1
        if sensor_id < len(sensors):
            config.sensor = sensors[sensor_id]
    config.sensor = sensors

    return processors, tags
    def extract_feature(self, win_data, sensor_idx, options=None, dist_vec=None):
        try:
            num_sensors = win_data["sparse_data"].shape[0]
            if self.detector_processor is None:
                self.detector_processor = [None] * num_sensors
                self.history = None
            arr = win_data["sparse_data"][sensor_idx, :, :, :]
            sensor_config = options["sensor_config"]
            session_info = options["session_info"]
        except Exception as e:
            print("sparse_data not available!\n", e)
            return None

        point_repeats, data_len, win_len = arr.shape
        data_start = dist_vec[0]
        data_stop = dist_vec[-1]

        # dist_vec is in mm
        start = max(data_start, options["Start"] * 1000)
        stop = min(data_stop, options["Stop"] * 1000)

        if start >= data_stop:
            return None

        start_idx = np.argmin((dist_vec - start)**2)
        stop_idx = np.argmin((dist_vec - stop)**2) + 1

        stop_idx = max(start_idx + 1, stop_idx)

        if self.detector_processor[sensor_idx] is None:
            detector_config = presence_detection_sparse.get_processing_config()
            detector_config.detection_threshold = 0
            detector_config.inter_frame_fast_cutoff = 100
            detector_config.inter_frame_slow_cutoff = 0.9
            detector_config.inter_frame_deviation_time_const = 0.05
            detector_config.intra_frame_time_const = 0.03
            detector_config.intra_frame_weight = 0.8
            detector_config.output_time_const = 0.01
            detector_handle = presence_detection_sparse.PresenceDetectionSparseProcessor
            self.detector_processor[sensor_idx] = detector_handle(
                sensor_config,
                detector_config,
                session_info
                )
            self.detector_processor[sensor_idx].depth_filter_length = 1

        detector_output = self.detector_processor[sensor_idx].process(arr[:, :, 0])
        presence = detector_output["depthwise_presence"]

        if self.history is None:
            self.history = np.zeros((num_sensors, len(presence), win_len))

        self.history[sensor_idx, :, :] = np.roll(self.history[sensor_idx, :, :], 1, axis=1)
        self.history[sensor_idx, :, 0] = presence

        data = {
            "presence": self.history[sensor_idx, start_idx:stop_idx, :],
        }

        return data
    def trigger_presence_sparse(self, data, feature_map, trigger_options):
        detected = False
        threshold = trigger_options["auto_threshold"]
        score = 0
        message = ""
        num_sensors = data["sweep_data"].shape[0]
        sensor_config = data["sensor_config"]
        mode = sensor_config.mode

        if mode == Mode.SPARSE and not SPARSE_AUTO_DETECTION:
            if self.sweep_counter <= 10:
                print("Warning: Auto movement detection with spares not available.")

        if mode == Mode.SPARSE and SPARSE_AUTO_DETECTION:
            if not self.trigger_variables.get("motion_processors_initialized", False):
                self.motion_config = presence_detection_sparse.get_processing_config()
                self.motion_config.inter_frame_fast_cutoff = 100
                self.motion_config.inter_frame_slow_cutoff = 0.9
                self.motion_config.inter_frame_deviation_time_const = 0.05
                self.motion_config.intra_frame_weight = 0.8
                self.motion_config.intra_frame_time_const = 0.03
                self.motion_config.detection_threshold = 0
                self.motion_config.output_time_const = 0.01
                self.motion_class = presence_detection_sparse.Processor
                motion_processors_list = []
                for i in range(num_sensors):
                    motion_processors_list.append(
                        self.motion_class(
                            sensor_config,
                            self.motion_config,
                            data["session_info"]
                        )
                    )
                self.motion_processors = motion_processors_list
                self.trigger_variables["motion_processors_initialized"] = True
            else:
                score = 0
                for i in range(num_sensors):
                    motion_score = self.motion_processors[i].process(data["sweep_data"][i, :, :])
                    motion_score = motion_score["depthwise_presence"]
                    max_score = np.nanmax(motion_score)
                    if max_score > score:
                        score = max_score
                        message = "Triggered on sensor {}".format(i + 1)
                if score > threshold:
                    detected = True
                    motion_processors_list = []
                    for i in range(num_sensors):
                        motion_processors_list.append(
                            self.motion_class(
                                sensor_config,
                                self.motion_config,
                                data["session_info"]
                            )
                        )
                    self.motion_processors = motion_processors_list

        return detected, score, message
    def __init__(self, sensor_config, processing_config):
        self.history_len = processing_config["image_buffer"]["value"]

        pd_config = presence_detection_sparse.get_processing_config()
        processor_class = presence_detection_sparse.PresenceDetectionSparseProcessor
        self.pd_processors = [processor_class(sensor_config, pd_config)]

        self.smooth_max = example_utils.SmoothMax(sensor_config.sweep_rate)

        self.sweep_index = 0
def setup_presence_detector(config, session_info):
    processing_config = presence_detection.get_processing_config()
    processing_config.inter_frame_fast_cutoff = 100
    processing_config.inter_frame_slow_cutoff = 1
    processing_config.detection_threshold = 1.5
    processing_config.inter_frame_deviation_time_const = 0.4
    processing_config.intra_frame_time_const = 0.1
    processing_config.output_time_const = 0.4
    processor = presence_detection.Processor(config, processing_config,
                                             session_info)

    return processor
    def auto_motion_detect(self, data):
        detected = False
        num_sensors = data["num_sensors"]
        sensor_config = data["sensor_config"]
        mode = sensor_config.mode

        if mode == "sparse" and not SPARSE_AUTO_DETECTION:
            if self.sweep_counter == 0:
                print(
                    "Warning: Auto movement detection with spares not available."
                )

        if mode == "sparse" and SPARSE_AUTO_DETECTION:
            if self.motion_processors is None:
                self.motion_config = presence_detection_sparse.get_processing_config(
                )
                self.motion_config.inter_frame_fast_cutoff = 100
                self.motion_config.inter_frame_slow_cutoff = 1
                self.motion_config.inter_frame_deviation_time_const = 0.1
                self.motion_class = presence_detection_sparse.PresenceDetectionSparseProcessor
                self.motion_processors = self.motion_class(
                    sensor_config, self.motion_config, data["session_info"])
            else:
                motion_score = self.motion_processors.process(
                    data["iq_data"][0, :, :])
                motion_score = motion_score["depthwise_presence"]
                self.motion_score_normalized = np.nanmax(motion_score)
                if self.motion_score_normalized > self.auto_threshold:
                    detected = True
                    self.motion_processors = self.motion_class(
                        sensor_config, self.motion_config,
                        data["session_info"])
                    return detected
        else:
            for i in range(num_sensors):
                motion_score = np.max(np.abs(data["env_ampl"][i, :]))
                if self.motion_score is None:
                    self.motion_score = motion_score
                self.motion_score_normalized = motion_score / self.motion_score
                if motion_score < self.motion_score:
                    self.motion_score = motion_score
                if motion_score > self.auto_threshold * self.motion_score:
                    detected = True
                    return detected
        return detected
    def __init__(self, sensor_config, processing_config, session_info):
        num_sensors = len(sensor_config.sensor)
        num_depths = utils.get_range_depths(sensor_config, session_info).size
        history_len = processing_config.history_length

        pd_config = presence_detection_sparse.get_processing_config()
        processor_class = presence_detection_sparse.Processor

        try:
            self.pd_processors = [
                processor_class(sensor_config, pd_config, session_info)
            ]
        except AssertionError:
            self.pd_processors = None

        self.data_history = np.ones([history_len, num_sensors, num_depths
                                     ]) * 2**15
        self.presence_history = np.zeros(
            [history_len, num_sensors, num_depths])
    def __init__(self, sensor_config, processing_config, session_info):
        num_sensors = len(sensor_config.sensor)
        num_depths = len(get_range_depths(sensor_config, session_info))
        history_len = processing_config["image_buffer"]["value"]

        pd_config = presence_detection_sparse.get_processing_config()
        processor_class = presence_detection_sparse.PresenceDetectionSparseProcessor

        try:
            self.pd_processors = [
                processor_class(sensor_config, pd_config, session_info)
            ]
        except AssertionError:
            self.pd_processors = None

        self.smooth_max = example_utils.SmoothMax(sensor_config.sweep_rate)

        self.data_history = np.zeros([history_len, num_sensors, num_depths])
        self.presence_history = np.zeros(
            [history_len, num_sensors, num_depths])

        self.sweep_index = 0
    def extract_feature(self, win_data, win_params):
        try:
            num_sensors = win_data["sparse_data"].shape[0]
            if self.detector_processor is None:
                self.detector_processor = [None] * num_sensors
                self.history = None
            sensor_config = win_params["sensor_config"]
            session_info = win_params["session_info"]
            sensor_idx = win_params["sensor_idx"]
            dist_vec = win_params["dist_vec"]
            options = win_params["options"]
            arr = win_data["sparse_data"][sensor_idx, :, :, :]
        except Exception as e:
            print("sparse_data not available!\n", e)
            return None

        point_repeats, data_len, win_len = arr.shape
        data_start = dist_vec[0]
        data_stop = dist_vec[-1]

        # dist_vec is in mm
        start = max(data_start, options["Start"] * 1000)
        stop = min(data_stop, options["Stop"] * 1000) + 1

        if start >= data_stop:
            return None

        start_idx = np.argmin((dist_vec - start)**2)
        stop_idx = np.argmin((dist_vec - stop)**2) + 1

        stop_idx = max(start_idx + 1, stop_idx)

        if self.detector_processor[sensor_idx] is None:
            detector_config = presence_detection_sparse.get_processing_config()
            detector_config.detection_threshold = 0
            detector_config.inter_frame_fast_cutoff = 100
            detector_config.inter_frame_slow_cutoff = 0.9
            detector_config.inter_frame_deviation_time_const = 0.05
            detector_config.intra_frame_time_const = 0.03
            detector_config.intra_frame_weight = 0.8
            detector_config.output_time_const = 0.01
            detector_handle = presence_detection_sparse.Processor
            self.detector_processor[sensor_idx] = detector_handle(
                sensor_config, detector_config, session_info)
            self.detector_processor[sensor_idx].depth_filter_length = 1

        detector_output = self.detector_processor[sensor_idx].process(arr[:, :,
                                                                          0])
        presence = detector_output["depthwise_presence"]

        if self.history is None:
            self.history = np.zeros((num_sensors, len(presence), win_len))

        self.history[sensor_idx, :, :] = np.roll(
            self.history[sensor_idx, :, :], 1, axis=1)
        self.history[sensor_idx, :, 0] = presence

        presence = self.history[sensor_idx, start_idx:stop_idx, :]
        avg_presence = np.mean(presence, axis=1)

        if self.avg_presence is None:
            self.avg_presence = np.zeros((num_sensors, len(avg_presence)))

        if options.get("Calibrate Avg.", False):
            if self.idx == 0:
                self.bg = np.zeros((num_sensors, len(avg_presence)))
            if self.idx < self.calib:
                self.bg[sensor_idx, :] = np.maximum(self.bg[sensor_idx, :],
                                                    1.2 * avg_presence)
                if sensor_idx == num_sensors - 1:
                    self.idx += 1

            avg_presence = avg_presence / self.bg[sensor_idx, :]
            avg_presence[avg_presence < 1] = 1

        self.avg_presence[sensor_idx, :] = avg_presence
        avg_presence = avg_presence / np.max(self.avg_presence) * 256

        data = {
            "presence": presence,
            "presence_avg": avg_presence,
        }

        if self.last_cal != options.get("Calibrate Avg.", False):
            self.idx = 0
            self.last_cal = options.get("Calibrate Avg.", False)

        if options.get("Calibrate Avg.", False):
            if self.idx < self.calib + self.dead_time:
                data = None
                if sensor_idx == num_sensors - 1:
                    self.idx += 1

        return data
    def auto_motion_detect(self, data, feature_based=False):
        detected = False

        if feature_based:
            wing = self.auto_offset
            if len(data.shape) == 2:
                if wing >= (self.frame_size / 2):
                    self.motion_score_normalized = "Reduce offset!"
                    detected = True
                else:
                    center = np.sum(
                        data[:, wing:-wing]) / (self.frame_size - 2 * wing)
                    left = np.sum(data[:, 0:wing]) / wing
                    right = np.sum(data[:, -(wing + 1):-1]) / wing
                    if right == 0 or left == 0:
                        self.motion_score_normalized = 0
                        return detected
                    if left / right > 0.9 and left / right < 1.1:
                        self.motion_score_normalized = 2 * center / (left +
                                                                     right)
                        if self.motion_score_normalized > self.auto_threshold:
                            detected = True
            else:
                self.motion_score_normalized = "Not implemented"
                detected = True
            return detected

        num_sensors = data["sweep_data"].shape[0]
        sensor_config = data["sensor_config"]
        mode = sensor_config.mode

        if mode == Mode.SPARSE and not SPARSE_AUTO_DETECTION:
            if self.sweep_counter <= 10:
                print(
                    "Warning: Auto movement detection with spares not available."
                )

        if mode == Mode.SPARSE and SPARSE_AUTO_DETECTION:
            if self.motion_processors is None:
                self.motion_config = presence_detection_sparse.get_processing_config(
                )
                self.motion_config.inter_frame_fast_cutoff = 100
                self.motion_config.inter_frame_slow_cutoff = 0.9
                self.motion_config.inter_frame_deviation_time_const = 0.05
                self.motion_config.intra_frame_weight = 0.8
                self.motion_config.intra_frame_time_const = 0.03
                self.motion_config.detection_threshold = 0
                self.motion_config.output_time_const = 0.01
                self.motion_class = presence_detection_sparse.Processor
                motion_processors_list = []
                for i in range(num_sensors):
                    motion_processors_list.append(
                        self.motion_class(sensor_config, self.motion_config,
                                          data["session_info"]))
                self.motion_processors = motion_processors_list
            else:
                motion_score = 0
                for i in range(num_sensors):
                    score = self.motion_processors[i].process(
                        data["sweep_data"][i, :, :])
                    score = score["depthwise_presence"]
                    max_score = np.nanmax(score)
                    if max_score > motion_score:
                        motion_score = max_score
                self.motion_score_normalized = motion_score
                if self.motion_score_normalized > self.auto_threshold:
                    detected = True
                    motion_processors_list = []
                    for i in range(num_sensors):
                        motion_processors_list.append(
                            self.motion_class(sensor_config,
                                              self.motion_config,
                                              data["session_info"]))
                    self.motion_processors = motion_processors_list
                    return detected
        else:
            if self.motion_score is None:
                self.motion_score_normalized = 0
                self.motion_score = np.full(num_sensors, np.inf)

            for i in range(num_sensors):
                motion_score = np.max(np.abs(data["env_ampl"][i, :]))

                if motion_score < self.motion_score[i]:
                    if self.motion_score[i] == np.inf:
                        self.motion_score[i] = motion_score

                self.motion_score_normalized = max(
                    self.motion_score_normalized,
                    motion_score / self.motion_score[i])

                if self.motion_score_normalized > self.auto_threshold:
                    self.motion_pass_counter += 1
                    if self.motion_pass_counter >= self.motion_pass:
                        self.motion_pass_counter = 0
                        self.motion_score = None
                        detected = True
                        return detected
                else:
                    # Try to remove small scale variations
                    self.motion_score[
                        i] = 0.9 * self.motion_score[i] + 0.1 * motion_score

        return detected
    def auto_motion_detect(self, data):
        detected = False
        num_sensors = data["iq_data"].shape[0]
        sensor_config = data["sensor_config"]
        mode = sensor_config.mode

        if mode == "sparse" and not SPARSE_AUTO_DETECTION:
            if self.sweep_counter <= 10:
                print(
                    "Warning: Auto movement detection with spares not available."
                )

        if mode == "sparse" and SPARSE_AUTO_DETECTION:
            if self.motion_processors is None:
                self.motion_config = presence_detection_sparse.get_processing_config(
                )
                self.motion_config.inter_frame_fast_cutoff = 100
                self.motion_config.inter_frame_slow_cutoff = 1
                self.motion_config.inter_frame_deviation_time_const = 0.1
                self.motion_config.intra_frame_weight = 0.7
                self.motion_config.intra_frame_time_const = 0.1
                self.motion_config.detection_threshold = 0
                self.motion_class = presence_detection_sparse.PresenceDetectionSparseProcessor
                motion_processors_list = []
                for i in range(num_sensors):
                    motion_processors_list.append(
                        self.motion_class(sensor_config, self.motion_config,
                                          data["session_info"]))
                self.motion_processors = motion_processors_list
            else:
                motion_score = 0
                for i in range(num_sensors):
                    score = self.motion_processors[i].process(
                        data["iq_data"][i, :, :])
                    score = score["depthwise_presence"]
                    max_score = np.nanmax(score)
                    if max_score > motion_score:
                        motion_score = max_score
                self.motion_score_normalized = motion_score
                if self.motion_score_normalized > self.auto_threshold:
                    detected = True
                    motion_processors_list = []
                    for i in range(num_sensors):
                        motion_processors_list.append(
                            self.motion_class(sensor_config,
                                              self.motion_config,
                                              data["session_info"]))
                    self.motion_processors = motion_processors_list
                    return detected
        else:
            if self.motion_score is None:
                self.motion_score_normalized = np.zeros(num_sensors)
                self.motion_score = np.full(num_sensors, np.inf)

            for i in range(num_sensors):
                motion_score = np.max(np.abs(data["env_ampl"][i, :]))

                if motion_score < self.motion_score[i]:
                    if self.motion_score[i] == np.inf:
                        self.motion_score[i] = motion_score

                self.motion_score_normalized[
                    i] = motion_score / self.motion_score[i]

                if self.motion_score_normalized[i] > self.auto_threshold:
                    self.motion_pass_counter += 1
                    if self.motion_pass_counter >= self.motion_pass:
                        self.motion_pass_counter = 0
                        detected = True
                        return detected
                else:
                    # Try to remove small scale variations
                    self.motion_score[
                        i] = 0.9 * self.motion_score[i] + 0.1 * motion_score

        return detected