photo-stack-finder 0.1.7__py3-none-any.whl → 0.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orchestrator/__init__.py +2 -2
- orchestrator/app.py +6 -11
- orchestrator/build_pipeline.py +19 -21
- orchestrator/orchestrator_runner.py +11 -8
- orchestrator/pipeline_builder.py +126 -126
- orchestrator/pipeline_orchestrator.py +604 -604
- orchestrator/review_persistence.py +162 -162
- orchestrator/static/orchestrator.css +76 -76
- orchestrator/static/orchestrator.html +11 -5
- orchestrator/static/orchestrator.js +3 -1
- overlap_metrics/__init__.py +1 -1
- overlap_metrics/config.py +135 -135
- overlap_metrics/core.py +284 -284
- overlap_metrics/estimators.py +292 -292
- overlap_metrics/metrics.py +307 -307
- overlap_metrics/registry.py +99 -99
- overlap_metrics/utils.py +104 -104
- photo_compare/__init__.py +1 -1
- photo_compare/base.py +285 -285
- photo_compare/config.py +225 -225
- photo_compare/distance.py +15 -15
- photo_compare/feature_methods.py +173 -173
- photo_compare/file_hash.py +29 -29
- photo_compare/hash_methods.py +99 -99
- photo_compare/histogram_methods.py +118 -118
- photo_compare/pixel_methods.py +58 -58
- photo_compare/structural_methods.py +104 -104
- photo_compare/types.py +28 -28
- {photo_stack_finder-0.1.7.dist-info → photo_stack_finder-0.1.8.dist-info}/METADATA +21 -22
- photo_stack_finder-0.1.8.dist-info/RECORD +75 -0
- scripts/orchestrate.py +12 -10
- utils/__init__.py +4 -3
- utils/base_pipeline_stage.py +171 -171
- utils/base_ports.py +176 -176
- utils/benchmark_utils.py +823 -823
- utils/channel.py +74 -74
- utils/comparison_gates.py +40 -21
- utils/compute_benchmarks.py +355 -355
- utils/compute_identical.py +94 -24
- utils/compute_indices.py +235 -235
- utils/compute_perceptual_hash.py +127 -127
- utils/compute_perceptual_match.py +240 -240
- utils/compute_sha_bins.py +64 -20
- utils/compute_template_similarity.py +1 -1
- utils/compute_versions.py +483 -483
- utils/config.py +8 -5
- utils/data_io.py +83 -83
- utils/graph_context.py +44 -44
- utils/logger.py +2 -2
- utils/models.py +2 -2
- utils/photo_file.py +90 -91
- utils/pipeline_graph.py +334 -334
- utils/pipeline_stage.py +408 -408
- utils/plot_helpers.py +123 -123
- utils/ports.py +136 -136
- utils/progress.py +415 -415
- utils/report_builder.py +139 -139
- utils/review_types.py +55 -55
- utils/review_utils.py +10 -19
- utils/sequence.py +10 -8
- utils/sequence_clustering.py +1 -1
- utils/template.py +57 -57
- utils/template_parsing.py +71 -0
- photo_stack_finder-0.1.7.dist-info/RECORD +0 -74
- {photo_stack_finder-0.1.7.dist-info → photo_stack_finder-0.1.8.dist-info}/WHEEL +0 -0
- {photo_stack_finder-0.1.7.dist-info → photo_stack_finder-0.1.8.dist-info}/entry_points.txt +0 -0
- {photo_stack_finder-0.1.7.dist-info → photo_stack_finder-0.1.8.dist-info}/licenses/LICENSE +0 -0
- {photo_stack_finder-0.1.7.dist-info → photo_stack_finder-0.1.8.dist-info}/top_level.txt +0 -0
utils/base_ports.py
CHANGED
|
@@ -1,176 +1,176 @@
|
|
|
1
|
-
"""Base classes for port-based pipeline connectivity.
|
|
2
|
-
|
|
3
|
-
This module contains the non-generic base classes that define the port interface.
|
|
4
|
-
These classes have minimal dependencies to avoid circular imports.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from abc import ABC, abstractmethod
|
|
10
|
-
from typing import Protocol
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class StageProtocol(Protocol):
|
|
14
|
-
"""Protocol defining the minimal interface needed from a pipeline stage.
|
|
15
|
-
|
|
16
|
-
This avoids circular dependency with pipeline_stage module.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
stage_name: str
|
|
20
|
-
|
|
21
|
-
def get_cache_timestamp(self) -> float:
|
|
22
|
-
"""Get timestamp when outputs were last computed.
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
Modification time in seconds since epoch
|
|
26
|
-
"""
|
|
27
|
-
...
|
|
28
|
-
|
|
29
|
-
def get_ref_photo_count(self) -> int | None:
|
|
30
|
-
"""Get count of reference photos after stage has run.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
Count of reference photos, or None if not available or stage hasn't run
|
|
34
|
-
"""
|
|
35
|
-
...
|
|
36
|
-
|
|
37
|
-
def get_ref_sequence_count(self) -> int | None:
|
|
38
|
-
"""Get count of reference sequences after stage has run.
|
|
39
|
-
|
|
40
|
-
Returns:
|
|
41
|
-
Count of reference sequences, or None if not available or stage hasn't run
|
|
42
|
-
"""
|
|
43
|
-
...
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class BaseOutputPort:
|
|
47
|
-
"""Non-generic base class for output ports.
|
|
48
|
-
|
|
49
|
-
Enables type checking and collections that work with any output port
|
|
50
|
-
regardless of data type. Useful for graph validation where we check
|
|
51
|
-
port connectivity without reading data.
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
owner: StageProtocol # Actual type is PipelineStage, but avoiding circular import
|
|
55
|
-
|
|
56
|
-
def __init__(
|
|
57
|
-
self,
|
|
58
|
-
owner: StageProtocol,
|
|
59
|
-
):
|
|
60
|
-
"""Initialize output port.
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
owner: The stage that produces this output (used for timestamps)
|
|
64
|
-
|
|
65
|
-
"""
|
|
66
|
-
self.owner = owner
|
|
67
|
-
|
|
68
|
-
def timestamp(self) -> float:
|
|
69
|
-
"""Get when this output was last updated.
|
|
70
|
-
|
|
71
|
-
All output ports from the same stage share the same timestamp
|
|
72
|
-
(they are computed together).
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
Modification time in seconds since epoch, or 0.0 if never computed
|
|
76
|
-
"""
|
|
77
|
-
return self.owner.get_cache_timestamp()
|
|
78
|
-
|
|
79
|
-
def get_ref_photo_count(self) -> int | None:
|
|
80
|
-
"""Get count of reference photos from owner stage.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
Count of reference photos in the owner, or None if not available
|
|
84
|
-
"""
|
|
85
|
-
return self.owner.get_ref_photo_count()
|
|
86
|
-
|
|
87
|
-
def get_ref_sequence_count(self) -> int | None:
|
|
88
|
-
"""Get count of reference sequences from owner stage.
|
|
89
|
-
|
|
90
|
-
Returns:
|
|
91
|
-
Count of reference sequences in the owner, or None if not available
|
|
92
|
-
"""
|
|
93
|
-
return self.owner.get_ref_sequence_count()
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class BaseInputPort(ABC):
|
|
97
|
-
"""Non-generic base class for input ports.
|
|
98
|
-
|
|
99
|
-
Enables type checking and collections that work with any input port
|
|
100
|
-
regardless of data type. Useful for graph validation where we check
|
|
101
|
-
port connectivity without reading data.
|
|
102
|
-
"""
|
|
103
|
-
|
|
104
|
-
_source: BaseOutputPort | None
|
|
105
|
-
name: str
|
|
106
|
-
|
|
107
|
-
def __init__(self, name: str):
|
|
108
|
-
"""Initialize input port.
|
|
109
|
-
|
|
110
|
-
Args:
|
|
111
|
-
name: Descriptive name for this input (e.g., "sha_bins", "forest")
|
|
112
|
-
"""
|
|
113
|
-
self.name = name
|
|
114
|
-
|
|
115
|
-
@abstractmethod
|
|
116
|
-
def is_bound(self) -> bool:
|
|
117
|
-
"""Check if this input is connected to a source.
|
|
118
|
-
|
|
119
|
-
Returns:
|
|
120
|
-
True if bind() has been called, False otherwise
|
|
121
|
-
"""
|
|
122
|
-
...
|
|
123
|
-
|
|
124
|
-
def timestamp(self) -> float:
|
|
125
|
-
"""Get timestamp from connected output.
|
|
126
|
-
|
|
127
|
-
Returns:
|
|
128
|
-
Timestamp from bound output port, or 0.0 if not bound
|
|
129
|
-
|
|
130
|
-
Raises:
|
|
131
|
-
RuntimeError: If port is not bound (should check is_bound() first)
|
|
132
|
-
"""
|
|
133
|
-
if self._source is None:
|
|
134
|
-
raise RuntimeError(f"Input port '{self.name}' is not bound to any source")
|
|
135
|
-
ts = self._source.timestamp()
|
|
136
|
-
if ts is None:
|
|
137
|
-
raise RuntimeError(f"{self._source.owner.stage_name} is reporting None timestamp")
|
|
138
|
-
return ts
|
|
139
|
-
|
|
140
|
-
def get_ref_photo_count(self) -> int | None:
|
|
141
|
-
"""Get count of reference photos from connected source.
|
|
142
|
-
|
|
143
|
-
Returns:
|
|
144
|
-
Count of reference photos from source, or None if not available
|
|
145
|
-
|
|
146
|
-
Raises:
|
|
147
|
-
RuntimeError: If port is not bound to a source
|
|
148
|
-
"""
|
|
149
|
-
if self._source is None:
|
|
150
|
-
raise RuntimeError(f"Input port '{self.name}' is not bound to any source")
|
|
151
|
-
return self._source.get_ref_photo_count()
|
|
152
|
-
|
|
153
|
-
def get_ref_sequence_count(self) -> int | None:
|
|
154
|
-
"""Get count of reference sequences from connected source.
|
|
155
|
-
|
|
156
|
-
Returns:
|
|
157
|
-
Count of reference sequences from source, or None if not available
|
|
158
|
-
|
|
159
|
-
Raises:
|
|
160
|
-
RuntimeError: If port is not bound to a source
|
|
161
|
-
"""
|
|
162
|
-
if self._source is None:
|
|
163
|
-
raise RuntimeError(f"Input port '{self.name}' is not bound to any source")
|
|
164
|
-
return self._source.get_ref_sequence_count()
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
class BaseChannel:
|
|
168
|
-
"""Non-generic base class for channels.
|
|
169
|
-
|
|
170
|
-
Enables type checking and collections that work with any channel
|
|
171
|
-
regardless of data type. Useful for graph storage where we track
|
|
172
|
-
channels with different type parameters.
|
|
173
|
-
"""
|
|
174
|
-
|
|
175
|
-
output: BaseOutputPort
|
|
176
|
-
input: BaseInputPort
|
|
1
|
+
"""Base classes for port-based pipeline connectivity.
|
|
2
|
+
|
|
3
|
+
This module contains the non-generic base classes that define the port interface.
|
|
4
|
+
These classes have minimal dependencies to avoid circular imports.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from typing import Protocol
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StageProtocol(Protocol):
|
|
14
|
+
"""Protocol defining the minimal interface needed from a pipeline stage.
|
|
15
|
+
|
|
16
|
+
This avoids circular dependency with pipeline_stage module.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
stage_name: str
|
|
20
|
+
|
|
21
|
+
def get_cache_timestamp(self) -> float:
|
|
22
|
+
"""Get timestamp when outputs were last computed.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Modification time in seconds since epoch
|
|
26
|
+
"""
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
def get_ref_photo_count(self) -> int | None:
|
|
30
|
+
"""Get count of reference photos after stage has run.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Count of reference photos, or None if not available or stage hasn't run
|
|
34
|
+
"""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
def get_ref_sequence_count(self) -> int | None:
|
|
38
|
+
"""Get count of reference sequences after stage has run.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Count of reference sequences, or None if not available or stage hasn't run
|
|
42
|
+
"""
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class BaseOutputPort:
|
|
47
|
+
"""Non-generic base class for output ports.
|
|
48
|
+
|
|
49
|
+
Enables type checking and collections that work with any output port
|
|
50
|
+
regardless of data type. Useful for graph validation where we check
|
|
51
|
+
port connectivity without reading data.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
owner: StageProtocol # Actual type is PipelineStage, but avoiding circular import
|
|
55
|
+
|
|
56
|
+
def __init__(
|
|
57
|
+
self,
|
|
58
|
+
owner: StageProtocol,
|
|
59
|
+
):
|
|
60
|
+
"""Initialize output port.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
owner: The stage that produces this output (used for timestamps)
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
self.owner = owner
|
|
67
|
+
|
|
68
|
+
def timestamp(self) -> float:
|
|
69
|
+
"""Get when this output was last updated.
|
|
70
|
+
|
|
71
|
+
All output ports from the same stage share the same timestamp
|
|
72
|
+
(they are computed together).
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Modification time in seconds since epoch, or 0.0 if never computed
|
|
76
|
+
"""
|
|
77
|
+
return self.owner.get_cache_timestamp()
|
|
78
|
+
|
|
79
|
+
def get_ref_photo_count(self) -> int | None:
|
|
80
|
+
"""Get count of reference photos from owner stage.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Count of reference photos in the owner, or None if not available
|
|
84
|
+
"""
|
|
85
|
+
return self.owner.get_ref_photo_count()
|
|
86
|
+
|
|
87
|
+
def get_ref_sequence_count(self) -> int | None:
|
|
88
|
+
"""Get count of reference sequences from owner stage.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Count of reference sequences in the owner, or None if not available
|
|
92
|
+
"""
|
|
93
|
+
return self.owner.get_ref_sequence_count()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class BaseInputPort(ABC):
|
|
97
|
+
"""Non-generic base class for input ports.
|
|
98
|
+
|
|
99
|
+
Enables type checking and collections that work with any input port
|
|
100
|
+
regardless of data type. Useful for graph validation where we check
|
|
101
|
+
port connectivity without reading data.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
_source: BaseOutputPort | None
|
|
105
|
+
name: str
|
|
106
|
+
|
|
107
|
+
def __init__(self, name: str):
|
|
108
|
+
"""Initialize input port.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
name: Descriptive name for this input (e.g., "sha_bins", "forest")
|
|
112
|
+
"""
|
|
113
|
+
self.name = name
|
|
114
|
+
|
|
115
|
+
@abstractmethod
|
|
116
|
+
def is_bound(self) -> bool:
|
|
117
|
+
"""Check if this input is connected to a source.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if bind() has been called, False otherwise
|
|
121
|
+
"""
|
|
122
|
+
...
|
|
123
|
+
|
|
124
|
+
def timestamp(self) -> float:
|
|
125
|
+
"""Get timestamp from connected output.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Timestamp from bound output port, or 0.0 if not bound
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
RuntimeError: If port is not bound (should check is_bound() first)
|
|
132
|
+
"""
|
|
133
|
+
if self._source is None:
|
|
134
|
+
raise RuntimeError(f"Input port '{self.name}' is not bound to any source")
|
|
135
|
+
ts = self._source.timestamp()
|
|
136
|
+
if ts is None:
|
|
137
|
+
raise RuntimeError(f"{self._source.owner.stage_name} is reporting None timestamp")
|
|
138
|
+
return ts
|
|
139
|
+
|
|
140
|
+
def get_ref_photo_count(self) -> int | None:
|
|
141
|
+
"""Get count of reference photos from connected source.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Count of reference photos from source, or None if not available
|
|
145
|
+
|
|
146
|
+
Raises:
|
|
147
|
+
RuntimeError: If port is not bound to a source
|
|
148
|
+
"""
|
|
149
|
+
if self._source is None:
|
|
150
|
+
raise RuntimeError(f"Input port '{self.name}' is not bound to any source")
|
|
151
|
+
return self._source.get_ref_photo_count()
|
|
152
|
+
|
|
153
|
+
def get_ref_sequence_count(self) -> int | None:
|
|
154
|
+
"""Get count of reference sequences from connected source.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Count of reference sequences from source, or None if not available
|
|
158
|
+
|
|
159
|
+
Raises:
|
|
160
|
+
RuntimeError: If port is not bound to a source
|
|
161
|
+
"""
|
|
162
|
+
if self._source is None:
|
|
163
|
+
raise RuntimeError(f"Input port '{self.name}' is not bound to any source")
|
|
164
|
+
return self._source.get_ref_sequence_count()
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class BaseChannel:
|
|
168
|
+
"""Non-generic base class for channels.
|
|
169
|
+
|
|
170
|
+
Enables type checking and collections that work with any channel
|
|
171
|
+
regardless of data type. Useful for graph storage where we track
|
|
172
|
+
channels with different type parameters.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
output: BaseOutputPort
|
|
176
|
+
input: BaseInputPort
|