Skip to content

distance

Calculates distance between Singles. Note: this is probably post-attention in humans, only calculated for a subset of features, and based on the saccades of the eyes.

Distance

Bases: FeatureExtractor[DistanceFeature]

Source code in roc/feature_extractors/distance.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
@register_component("distance", "perception")
class Distance(FeatureExtractor[DistanceFeature]):
    def __init__(self) -> None:
        super().__init__()
        self.prev_features: list[SingleFeature] = []

    def event_filter(self, e: PerceptionEvent) -> bool:
        # only listen to single:perception events
        if e.src_id.name == "single" and e.src_id.type == "perception":
            return True
        return False

    def get_feature(self, e: PerceptionEvent) -> None:
        data = e.data

        if isinstance(data, Settled):
            self.prev_features.clear()
            self.settled()
            return

        # calculate distance between all previous elements and emit event for each
        assert isinstance(data, SingleFeature)
        curr_pt = data.point
        # print("### single point:", curr_pt)
        for f in self.prev_features:
            prev_pt = f.point
            dist = chebyshev_distance(curr_pt, prev_pt)
            # print(f"# distance: ({prev_pt[0]}, {prev_pt[1]}) ({curr_pt[0]}, {curr_pt[1]}) {dist}")
            self.pb_conn.send(
                DistanceFeature(
                    origin_id=self.id,
                    start_point=prev_pt,
                    end_point=curr_pt,
                    size=dist,
                )
            )

        # add to previous elements
        self.prev_features.append(data)

prev_features = [] instance-attribute

__init__()

Source code in roc/feature_extractors/distance.py
47
48
49
def __init__(self) -> None:
    super().__init__()
    self.prev_features: list[SingleFeature] = []

event_filter(e)

Source code in roc/feature_extractors/distance.py
51
52
53
54
55
def event_filter(self, e: PerceptionEvent) -> bool:
    # only listen to single:perception events
    if e.src_id.name == "single" and e.src_id.type == "perception":
        return True
    return False

get_feature(e)

Source code in roc/feature_extractors/distance.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def get_feature(self, e: PerceptionEvent) -> None:
    data = e.data

    if isinstance(data, Settled):
        self.prev_features.clear()
        self.settled()
        return

    # calculate distance between all previous elements and emit event for each
    assert isinstance(data, SingleFeature)
    curr_pt = data.point
    # print("### single point:", curr_pt)
    for f in self.prev_features:
        prev_pt = f.point
        dist = chebyshev_distance(curr_pt, prev_pt)
        # print(f"# distance: ({prev_pt[0]}, {prev_pt[1]}) ({curr_pt[0]}, {curr_pt[1]}) {dist}")
        self.pb_conn.send(
            DistanceFeature(
                origin_id=self.id,
                start_point=prev_pt,
                end_point=curr_pt,
                size=dist,
            )
        )

    # add to previous elements
    self.prev_features.append(data)

DistanceFeature dataclass

Bases: Feature[DistanceNode]

The distance between two features

Source code in roc/feature_extractors/distance.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@dataclass(kw_only=True)
class DistanceFeature(Feature[DistanceNode]):
    """The distance between two features"""

    feature_name: str = "Distance"
    start_point: tuple[XLoc, YLoc]
    end_point: tuple[XLoc, YLoc]
    size: int

    def get_points(self) -> set[tuple[XLoc, YLoc]]:
        return {self.start_point, self.end_point}

    def node_hash(self) -> int:
        return hash(self.size)

    def _create_nodes(self) -> DistanceNode:
        return DistanceNode(size=self.size)

    def _dbfetch_nodes(self) -> DistanceNode | None:
        return DistanceNode.find_one("src.size = $size", params={"size": self.size})

end_point instance-attribute

feature_name = 'Distance' class-attribute instance-attribute

size instance-attribute

start_point instance-attribute

__init__(*, feature_name='Distance', start_point, end_point, size)

get_points()

Source code in roc/feature_extractors/distance.py
32
33
def get_points(self) -> set[tuple[XLoc, YLoc]]:
    return {self.start_point, self.end_point}

node_hash()

Source code in roc/feature_extractors/distance.py
35
36
def node_hash(self) -> int:
    return hash(self.size)

DistanceNode

Bases: FeatureNode

Source code in roc/feature_extractors/distance.py
15
16
17
18
19
20
class DistanceNode(FeatureNode):
    size: int

    @property
    def attr_strs(self) -> list[str]:
        return [str(self.size)]

attr_strs property

size instance-attribute

chebyshev_distance(p1, p2)

Source code in roc/feature_extractors/distance.py
86
87
88
89
90
91
92
93
def chebyshev_distance(p1: tuple[XLoc, YLoc], p2: tuple[XLoc, YLoc]) -> int:
    x1 = p1[0]
    x2 = p2[0]
    y1 = p1[1]
    y2 = p2[1]
    dx = abs(x1 - x2)
    dy = abs(y1 - y2)
    return max(dx, dy)