Python optimize [Multi-coop multi-floor discovery, Auto .engine compilation, API, mortality webapp trigger, parallel processing/tensor batching/hybrid, etc.] #3

Merged
zakaria merged 39 commits from andrew/chicken-counting-sukawarna-det:python-optimize into python-optimize 2026-08-20 11:00:31 +07:00
24 changed files with 2068 additions and 74 deletions
Showing only changes of commit b00923dc2b - Show all commits

No files matched your search

+4
View File
@@ -24,6 +24,7 @@ visual.
```text
configs/
K1-L1.yaml .. K5-L2.yaml ← Standard floor configurations (K1-L1 to K5-L2)
cameras/example_camera.yaml
cycle7_batch.yaml
cycle7_batch_optimized.yaml
@@ -49,6 +50,9 @@ src/chicken_counter/
dashboard.py
export_engine.py
export_excel_report.py
run_all_coops.sh ← Master multi-coop batch runner
start_dashboard.sh ← Live dashboard launcher
test_run_folder/ ← Archive of test run scripts and logs
```
## Install
+19 -32
View File
@@ -34,6 +34,7 @@ venv/bin/pip install -r requirements.txt
```text
chicken-counting-sukawarna-det/
├── configs/
│ ├── K1-L1.yaml .. K5-L2.yaml ← Standard floor configurations (K1-L1 to K5-L2)
│ ├── cycle7_batch_optimized.yaml ← Main batch processing config
│ ├── cycle7_batch.yaml ← Alternate batch config
│ ├── mortality_config.yaml ← Mortality (carcass) detection config
@@ -50,9 +51,9 @@ chicken-counting-sukawarna-det/
├── dashboard.py ← Live API + Dashboard server
├── export_engine.py ← Manual TensorRT export utility
├── export_excel_report.py ← Excel reporting & analytics generator
├── run_all_coops.sh ← Master multi-coop batch runner (K1-L1 to K5-L2)
├── start_dashboard.sh ← Portable dashboard launcher ← USE THIS
├── test_run_mortality.sh ← Run mortality detection
├── test_run.sh ← Run batch processing all dates
├── test_run_folder/ ← Archive of test run scripts and logs
└── requirements.txt
```
@@ -76,47 +77,33 @@ Put your model files in the `models/` directory.
### A — Batch Video Processing (Daily Chicken Count)
Place input videos under the `VIDEOS` folder adjacent to the project:
Place input videos under the `VIDEOS` folder adjacent to the project following the `K{coop}-L{floor}` format:
```text
../VIDEOS/cycle7/kandang-atas/
2026-06-18/
kandang_1_camera_1_2026-06-18_120056.mp4
kandang_1_camera_2_2026-06-18_120456.mp4
...
../VIDEOS/cycle7/
K1-L1/
2026-06-18/
K1-L1_cam1_2026-06-18_120056.mp4
K1-L1_cam2_2026-06-18_120456.mp4
K1-L1_cam3_2026-06-18_121012.mp4
K1-L1_cam4_2026-06-18_121530.mp4
```
Then run:
```bash
# Run all dates (multi-process mode)
./test_run.sh
# Run all coops (10 floors: K1-L1 to K5-L2) for a specific date
./run_all_coops.sh 2026-06-18
# Run all dates (Tensor Batching mode)
./test_run_tensor_batch.sh
# Run all dates (Hybrid mode: Threaded CPU + Batched GPU)
./test_run_hybrid.sh
# Run a specific date (4 cameras in parallel)
# Run a specific floor (e.g. Kandang 1 Lantai 1)
PYTHONPATH=src venv/bin/python -m chicken_counter.cli batch \
--config configs/cycle7_batch_optimized.yaml \
--config configs/K1-L1.yaml \
--date 2026-06-18
# Run a specific date using Model-Level Tensor Batching
PYTHONPATH=src venv/bin/python -m chicken_counter.cli batch \
--config configs/cycle7_batch_optimized.yaml \
--date 2026-06-18 \
--mode tensor_batching
# Run a specific date using Hybrid Execution Mode
PYTHONPATH=src venv/bin/python -m chicken_counter.cli batch \
--config configs/cycle7_batch_optimized.yaml \
--date 2026-06-18 \
--mode hybrid
# Run with video output enabled
./test_run_video_2026-06-18.sh
# Run archive scripts in test_run_folder
./test_run_folder/test_run.sh
./test_run_folder/test_run_tensor_batch.sh
./test_run_folder/test_run_hybrid.sh
```
Output is saved in `../VIDEOS/cycle7/kandang-atas/2026-06-18/output/`.
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K1-L1
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K1-L1
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K1-L2
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K1-L2
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K2-L1
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K2-L1
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K2-L2
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K2-L2
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K3-L1
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K3-L1
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K3-L2
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K3-L2
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K4-L1
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K4-L1
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K4-L2
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K4-L2
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K5-L1
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K5-L1
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+186
View File
@@ -0,0 +1,186 @@
batch:
root_dir: ../VIDEOS/cycle7/K5-L2
camera_glob: '*cam{num}_*.mp4'
output_subdir: output
compress_max_mb: 200
delete_intermediate: false
checkpoint_every_n_frames: 3000
location: K5-L2
db_path: db/chicken_counts.db
cycle_start_date: '2026-05-22'
execution_mode: parallel_processes
stages:
early_cycle:
day_min: 0
day_max: 15
detection:
conf: 0.1
min_box_area_px: 100
roi:
min_overlap_ratio: 0.1
mid_cycle:
day_min: 16
day_max: 999
defaults:
detection:
model_path: models/NUC5070_chicken-detection-model-v26n-300e-best-2026-05-02-NEW.engine
classes:
- 0
ignored_classes:
- 1
- 2
conf: 0.4
iou: 0.55
imgsz: 640
device: '0'
min_box_area_px: 3000
validate_while_inside: true
dedupe_radius_px: 0
dedupe_frames: 12
detection_zone:
enabled: true
buffer_above_px: 250
buffer_below_px: 250
show_in_overlay: true
tracker:
tracker_config_path: configs/trackers/botsort_chicken.yaml
persist: true
track_buffer: 90
gate:
mode: two_line
lines_y:
- 420
- 730
direction: bottom_to_up
motion:
enabled: true
axis: vertical
forward_sign: 1.0
ema_alpha: 0.2
reverse_enter_threshold: -1.5
reverse_exit_threshold: -0.5
debounce_frames: 12
min_features: 40
max_corners: 50
stride_frames: 3
flow_scale: 0.5
quality_level: 0.01
min_distance: 8
block_radius: 6
overlay:
show_boxes: true
show_track_trails: false
trail_length: 20
show_center_marker: false
show_track_ring: false
count_anchor:
- 780
- 120
inside_box_only: true
validated_only: true
pending_blink: true
pending_colors:
- - 255
- 255
- 0
- - 0
- 255
- 255
display:
show_window: false
encoder: auto
output_bitrate_kbps: 2000
codec_preference:
- avc1
- mp4v
- H264
performance:
half: false
overlay_buffer_reuse: true
inference_stride: 2
stream:
enabled: true
shm_dir: /dev/shm
interval_frames: 5
feedback:
enabled: true
every_n_frames: 3000
save_images: false
log_to_terminal: true
roi:
inset_left_px: 60
inset_right_px: 60
inset_top_px: 0
inset_bottom_px: 0
min_overlap_ratio: 0.3
cameras:
CC1:
camera_num: 1
count_anchor:
- 780
- 120
detection:
min_box_area_px: 2500
conf: 0.35
roi:
points:
- - 250
- 330
- - 1650
- 330
- - 1650
- 720
- - 250
- 720
CC2:
camera_num: 2
count_anchor:
- 900
- 120
detection:
conf: 0.5
dedupe_radius_px: 32
dedupe_frames: 24
roi:
points:
- - 20
- 380
- - 1880
- 380
- - 1880
- 720
- - 20
- 720
CC3:
camera_num: 3
count_anchor:
- 900
- 120
detection:
dedupe_radius_px: 24
dedupe_frames: 16
roi:
points:
- - 20
- 330
- - 1880
- 330
- - 1880
- 720
- - 20
- 720
CC4:
camera_num: 4
count_anchor:
- 700
- 120
roi:
points:
- - 50
- 330
- - 1450
- 330
- - 1450
- 720
- - 50
- 720
+56
View File
@@ -0,0 +1,56 @@
#!/bin/bash
# Master runner for 5-coop / 10-floor daily processing
set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
if [ -f "$SCRIPT_DIR/venv/bin/python" ]; then
PYTHON="$SCRIPT_DIR/venv/bin/python"
else
PYTHON="python3"
fi
DATE="${1:-$(date +%Y-%m-%d)}"
MODE="${2:-parallel_processes}"
# List of all configured floors
CONFIGS=(
"configs/K1-L1.yaml"
"configs/K1-L2.yaml"
"configs/K2-L1.yaml"
"configs/K2-L2.yaml"
"configs/K3-L1.yaml"
"configs/K3-L2.yaml"
"configs/K4-L1.yaml"
"configs/K4-L2.yaml"
"configs/K5-L1.yaml"
"configs/K5-L2.yaml"
)
echo "================================================================="
echo " Starting 5-Coop Multi-Floor Batch Processing for Date: $DATE"
echo " Execution Mode: $MODE"
echo "================================================================="
SUCCESS_COUNT=0
SKIPPED_COUNT=0
for config in "${CONFIGS[@]}"; do
if [ -f "$SCRIPT_DIR/$config" ]; then
echo ""
echo ">>> [PROCESSING] Location Config: $config <<<"
if $PYTHON -m chicken_counter.cli batch --config "$config" --date "$DATE" --mode "$MODE"; then
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
else
echo "⚠️ [SKIPPED / ERROR] $config for date $DATE (video not found or error occurred)."
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
fi
fi
done
echo ""
echo "================================================================="
echo " Multi-Floor Batch Summary: $SUCCESS_COUNT completed, $SKIPPED_COUNT skipped."
echo " Database: db/chicken_counts.db"
echo "================================================================="
+45 -3
View File
@@ -21,17 +21,59 @@ def discover_camera_videos(day_dir: Path, settings: BatchSettings) -> CameraDisc
result = CameraDiscoveryResult()
total_configured = len(settings.cameras)
# Exclude output videos and non-video files
def _is_valid_source_video(path: Path) -> bool:
name = path.name.lower()
if name.endswith(("_vis.mp4", "_compressed.mp4", "_overlay.mp4", "_preview.mp4")):
return False
if "output" in path.parts:
return False
return path.suffix.lower() in (".mp4", ".avi", ".mkv", ".mov")
for camera_id, preset in sorted(
settings.cameras.items(),
key=lambda item: item[1].camera_num,
):
pattern = settings.batch.camera_glob.format(num=preset.camera_num)
matches = sorted(day_dir.glob(pattern))
num = preset.camera_num
primary_pattern = settings.batch.camera_glob.format(num=num)
matches = [p for p in sorted(day_dir.glob(primary_pattern)) if _is_valid_source_video(p)]
# Fallback candidate patterns if primary pattern doesn't match
if not matches:
fallback_patterns = [
f"*cam{num}_*.mp4",
f"*cam_{num}_*.mp4",
f"*camera_{num}_*.mp4",
f"*camera{num}_*.mp4",
f"*_c{num}_*.mp4",
f"*cam{num}.mp4",
f"*camera{num}.mp4",
f"*camera_{num}.mp4",
]
for fb_pat in fallback_patterns:
matches = [p for p in sorted(day_dir.glob(fb_pat)) if _is_valid_source_video(p)]
if matches:
break
# Case-insensitive fallback search
if not matches:
for f in sorted(day_dir.iterdir()):
if f.is_file() and _is_valid_source_video(f):
fname = f.name.lower()
if (
f"cam{num}" in fname
or f"cam_{num}" in fname
or f"camera_{num}" in fname
or f"camera{num}" in fname
or f"_c{num}" in fname
):
matches.append(f)
if not matches:
result.skipped[camera_id] = "video_not_found"
continue
if len(matches) > 1:
result.skipped[camera_id] = "multiple_matches"
result.skipped[camera_id] = f"multiple_matches ({[m.name for m in matches]})"
continue
result.found[camera_id] = matches[0]
File renamed without changes.
+10 -5
View File
@@ -2,14 +2,19 @@
set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
# Use project-local venv if available
if [ -f "$SCRIPT_DIR/venv/bin/python" ]; then
PYTHON="$SCRIPT_DIR/venv/bin/python"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
dates=(
"2026-06-10" "2026-06-11" "2026-06-12" "2026-06-13" "2026-06-14"
"2026-06-15" "2026-06-16" "2026-06-17" "2026-06-18" "2026-06-19"
@@ -2,19 +2,20 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
# Use project-local venv if available
if [ -f "$SCRIPT_DIR/venv/bin/python" ]; then
PYTHON="$SCRIPT_DIR/venv/bin/python"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
# Allow passing a specific date as $1 (e.g. ./test_run_hybrid.sh 2026-06-18)
# Or default to all dates 2026-06-10 through 2026-06-19
if [ -n "${1:-}" ]; then
dates=("$1")
dates=("$1")
else
dates=(
"2026-06-10" "2026-06-11" "2026-06-12" "2026-06-13" "2026-06-14"
File renamed without changes.
@@ -2,19 +2,20 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
# Use project-local venv if available
if [ -f "$SCRIPT_DIR/venv/bin/python" ]; then
PYTHON="$SCRIPT_DIR/venv/bin/python"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
# Allow passing a specific date as $1 (e.g. ./test_run_tensor_batch.sh 2026-06-18)
# Or default to all dates 2026-06-10 through 2026-06-19
if [ -n "${1:-}" ]; then
dates=("$1")
dates=("$1")
else
dates=(
"2026-06-10" "2026-06-11" "2026-06-12" "2026-06-13" "2026-06-14"
@@ -2,15 +2,19 @@
set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
# Use project-local venv if available
if [ -f "$SCRIPT_DIR/venv/bin/python" ]; then
PYTHON="$SCRIPT_DIR/venv/bin/python"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
dates=(
"2026-05-23"
)
@@ -2,9 +2,19 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
PYTHON="python3"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
dates=(
"2026-05-24"
)
@@ -2,15 +2,19 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
# Use project-local venv if available
if [ -f "$SCRIPT_DIR/venv/bin/python" ]; then
PYTHON="$SCRIPT_DIR/venv/bin/python"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
dates=(
"2026-06-06"
)
@@ -2,9 +2,19 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
PYTHON="python3"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
dates=(
"2026-06-16"
)
@@ -2,9 +2,19 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PYTHONPATH="$SCRIPT_DIR/src"
PYTHON="python3"
if [ -d "$SCRIPT_DIR/../src" ]; then
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
else
PROJECT_ROOT="$SCRIPT_DIR"
fi
cd "$PROJECT_ROOT"
export PYTHONPATH="$PROJECT_ROOT/src"
if [ -f "$PROJECT_ROOT/venv/bin/python" ]; then
PYTHON="$PROJECT_ROOT/venv/bin/python"
else
PYTHON="python3"
fi
dates=(
"2026-06-18"
)