Skip to content

Commit a4a299c

Browse files
committed
updated api
1 parent 9431c95 commit a4a299c

3 files changed

Lines changed: 74 additions & 34 deletions

File tree

src/openptv_python/tracking_frame_buf.py

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def quicksort_n_tupel(arr: np.recarray) -> np.recarray:
4040
-------
4141
A list of n_tupel instances, sorted by the corr attribute.
4242
"""
43-
# inline sorting
4443
arr.sort(order="corr")
4544
return arr
4645

@@ -53,6 +52,16 @@ def quicksort_n_tupel(arr: np.recarray) -> np.recarray:
5352
)
5453

5554

55+
def _resolve_frame_base(file_base: str, frame_num: int, suffix: str = "") -> Path:
56+
if frame_num > 0:
57+
if "%" in file_base:
58+
return Path(file_base % frame_num + suffix)
59+
if file_base.endswith((".", "_", "-", "/")):
60+
return Path(f"{file_base}{frame_num:04d}{suffix}")
61+
return Path(f"{file_base}.{frame_num:04d}{suffix}")
62+
return Path(f"{file_base}{suffix}")
63+
64+
5665
# def __eq__(self, other):
5766
# return self.nr == other.nr and np.all(self.p == other.p)
5867

@@ -165,17 +174,7 @@ def num_targs(self):
165174
def read_targets(file_base: str, frame_num: int) -> List[Target]:
166175
"""Read targets from a file."""
167176
buffer = []
168-
169-
# # if file_base has an extension, remove it
170-
# file_base = file_base.split(".")[0]
171-
172-
if frame_num > 0:
173-
# filename = f"{file_base}{frame_num:04d}_targets"
174-
fname = file_base % frame_num + "_targets"
175-
else:
176-
fname = f"{file_base}_targets"
177-
178-
filename = Path(fname)
177+
filename = _resolve_frame_base(file_base, frame_num, "_targets")
179178
print(f" filename: {filename}")
180179

181180
try:
@@ -214,17 +213,7 @@ def write_targets(
214213
) -> bool:
215214
"""Write targets to a file."""
216215
success = False
217-
218-
# fix old-type names, that are like cam1.# or just cam1.
219-
if "#" in file_base:
220-
file_base = file_base.replace("#", "%05d")
221-
if "%" not in file_base:
222-
file_base = file_base + "%05d"
223-
224-
if frame_num == 0:
225-
frame_num = 123456789
226-
227-
file_name = file_base % frame_num + "_targets"
216+
file_name = _resolve_frame_base(file_base, frame_num, "_targets")
228217

229218
try:
230219
# Convert targets to a 2D numpy array
@@ -341,19 +330,16 @@ def read(
341330
frame_num: int,
342331
) -> bool:
343332
"""Read a frame from the disk."""
344-
required_files = [Path(f"{corres_file_base}.{frame_num}")]
333+
required_files = [_resolve_frame_base(corres_file_base, frame_num)]
345334

346335
if linkage_file_base != "":
347-
required_files.append(Path(f"{linkage_file_base}.{frame_num}"))
336+
required_files.append(_resolve_frame_base(linkage_file_base, frame_num))
348337

349338
if prio_file_base != "":
350-
required_files.append(Path(f"{prio_file_base}.{frame_num}"))
339+
required_files.append(_resolve_frame_base(prio_file_base, frame_num))
351340

352341
for file_base in target_file_base:
353-
if frame_num > 0:
354-
required_files.append(Path(file_base % frame_num + "_targets"))
355-
else:
356-
required_files.append(Path(f"{file_base}_targets"))
342+
required_files.append(_resolve_frame_base(file_base, frame_num, "_targets"))
357343

358344
for path in required_files:
359345
if not path.exists():

src/pyptv/ptv.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
SHORT_BASE = "cam" # Use this as the short base for camera file naming
6767

6868

69+
def _as_text(value: str | bytes) -> str:
70+
return value.decode() if isinstance(value, bytes) else value
71+
72+
6973
def _prepare_output_path(filename: str) -> Path:
7074
"""Return a writable output path, creating parent directories when needed."""
7175
output_path = Path(filename)
@@ -503,7 +507,7 @@ def py_determination_proc_c(
503507
print_corresp = concatenated_corresp
504508

505509
output_path = _prepare_output_path(
506-
f"{default_naming['corres'].decode()}.{DEFAULT_FRAME_NUM}"
510+
f"{_as_text(default_naming['corres'])}.{DEFAULT_FRAME_NUM}"
507511
)
508512

509513
print(f"Prepared {output_path} to write positions")
@@ -683,14 +687,19 @@ def py_sequence_loop(exp) -> None:
683687
flat = np.array(
684688
[corr.get_by_pnrs(corresp) for corr, corresp in zip(corrected, sorted_corresp)]
685689
)
686-
pos, _ = point_positions(flat.transpose(1, 0, 2), exp.cpar, exp.cals, exp.vpar)
690+
pos, _ = point_positions(
691+
flat.transpose(1, 0, 2),
692+
exp.cpar.mm,
693+
exp.cals,
694+
exp.vpar,
695+
)
687696
if len(exp.cals) < 4:
688697
print_corresp = -1 * np.ones((4, sorted_corresp.shape[1]))
689698
print_corresp[: len(exp.cals), :] = sorted_corresp
690699
else:
691700
print_corresp = sorted_corresp
692701

693-
output_path = _prepare_output_path(f"{default_naming['corres'].decode()}.{frame}")
702+
output_path = _prepare_output_path(f"{_as_text(default_naming['corres'])}.{frame}")
694703
try:
695704
with open(output_path, "w", encoding="utf8") as rt_is:
696705
rt_is.write(f"{pos.shape[0]}\n")
@@ -795,9 +804,20 @@ def write_targets(targets: TargetArray, short_file_base: str, frame: int) -> boo
795804
return True # No targets to write, but file created successfully
796805

797806
try:
807+
def _value(field):
808+
return field() if callable(field) else field
809+
798810
target_arr = np.array(
799811
[
800-
([t.pnr(), *t.pos(), *t.count_pixels(), t.sum_grey_value(), t.tnr()])
812+
(
813+
[
814+
_value(t.pnr),
815+
*t.pos(),
816+
*t.count_pixels(),
817+
t.sum_grey_value(),
818+
_value(t.tnr),
819+
]
820+
)
801821
for t in targets
802822
]
803823
)

tests/test_fb.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import os
2+
import tempfile
23
import unittest
4+
from pathlib import Path
35

46
import numpy as np
57

68
from openptv_python.constants import POSI
79
from openptv_python.tracking_frame_buf import (
810
Corres_dtype,
11+
Frame,
912
Pathinfo,
1013
Target,
1114
compare_corres,
@@ -103,6 +106,37 @@ def test_write_targets(self):
103106
os.remove(file_base % frame_num + "_targets")
104107

105108

109+
class TestPlainBaseFrameIO(unittest.TestCase):
110+
def test_frame_read_accepts_plain_short_bases(self):
111+
with tempfile.TemporaryDirectory() as tmpdir:
112+
tmp_path = Path(tmpdir)
113+
corres_base = tmp_path / "res" / "rt_is"
114+
target_base = tmp_path / "img" / "cam1"
115+
116+
corres_base.parent.mkdir(parents=True, exist_ok=True)
117+
target_base.parent.mkdir(parents=True, exist_ok=True)
118+
119+
frame_num = 42
120+
(corres_base.parent / f"{corres_base.name}.0042").write_text("0\n", encoding="utf-8")
121+
(target_base.parent / f"{target_base.name}.0042_targets").write_text(
122+
"0\n",
123+
encoding="utf-8",
124+
)
125+
126+
frame = Frame(num_cams=1, max_targets=1)
127+
128+
result = frame.read(
129+
str(corres_base),
130+
"",
131+
"",
132+
[str(target_base)],
133+
frame_num,
134+
)
135+
136+
self.assertTrue(result)
137+
self.assertEqual(frame.num_targets[0], 0)
138+
139+
106140
class TestReadPathFrame(unittest.TestCase):
107141
def test_read_path_frame(self):
108142
"""Test reading path frame with and without links.

0 commit comments

Comments
 (0)