Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [7.1.0] - 2026-09-08

Release da primeira execucao. A 7.0.1 fez o programa instalar e abrir sem
terminal; operando o resultado numa maquina limpa, tres lacunas apareceram --
todas no intervalo entre o duplo-clique e a primeira analise.

### Added

- **Janela de primeiros passos**, mostrada depois que a janela principal abre.
Ate aqui o operador recebia um aplicativo completo sem nenhuma indicacao do
que fazer primeiro -- e, em particular, nenhuma pista de que os seis modelos
precisam ser atribuidos a papeis antes de o rastreamento se comportar bem.

Ela explica os modelos, os quatro papeis que eles preenchem e quando vale
ligar o OpenVINO, e oferece abrir o painel onde essas escolhas sao feitas.
**O conselho sobre OpenVINO e lido da maquina, nao escrito no abstrato:**
"use OpenVINO quando nao houver placa NVIDIA" e verdade e inutil para quem nao
sabe o que tem instalado, entao o texto consulta `get_hardware_summary()` e
nomeia os dispositivos encontrados.

A caixa "nao mostrar novamente" grava **apenas** `ui.show_welcome` via
`write_local_override()`. Nunca `save_settings`, que despejaria a arvore
inteira de defaults em `config.local.yaml` e derrotaria de vez a fusao em
camadas `config.yaml` -> `config.local.yaml` naquela instalacao.

- **Entradas de menu para as definicoes de modelo e para os primeiros passos.**
O painel de configuracao de modelos **nao tinha entrada de menu nenhuma**:
era alcancavel so por um botao dentro da visao de projeto, ou seja, a unica
tela que o operador precisa antes da primeira analise era a que ele nao
conseguia achar. Agora esta em **Configuracoes -> Definicoes de modelo...**,
e a janela de boas-vindas volta por **Ajuda -> Primeiros passos...**, de modo
que dispensa-la em definitivo nao torna a explicacao inalcancavel.

- **Instalador guiado e atalho de area de trabalho.** Quem opera o programa nao
precisa mais abrir um terminal para usa-lo. `install.ps1` (duplo-clique via
`install.bat`) confere o Python, confere o Poetry, fixa o ambiente no
Expand All @@ -35,6 +66,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- **O duplo-clique passava ~4 s sem sinal de vida.** O splash era criado
*depois* do bloco de imports que monta o grafo de coordinators, entao a janela
so aparecia quando o carregamento pesado ja tinha terminado. Sob o atalho
(`pythonw.exe`, sem console) isso e indistinguivel de um icone morto.

Dois custos estavam na frente dele, ambos com cara de `import` comum:
`from zebtrack.utils import set_seed` -- `zebtrack.utils` importa torch em
corpo de modulo, ~1,1 s -- e o bloco `di_registrations`, que puxa ultralytics,
cv2 e matplotlib por cima do torch, ~3 s. Medido em `logs/analysis.log` entre
`application.starting` e `benchmark.running_first_time`.

O splash agora e construido logo apos `i18n.install()`, antes dos dois, e o
carregamento pesado roda sob a mensagem "Carregando o motor de rastreamento".
`tests/core/test_app_runner_splash_ordering.py` fixa a **ordem**, nao a
duracao: uma assercao de tempo seria instavel numa maquina carregada e nao
diria por que regrediu.

- **As etapas do benchmark nunca eram legiveis no splash.** Elas sempre foram
enviadas para la, mas varias terminam em milissegundos: a mensagem era
pintada e sobrescrita dentro do mesmo quadro, entao a sequencia so existia no
log. Cada etapa agora permanece um instante minimo na tela
(`SPLASH_MIN_STEP_SECONDS`), pulado quando a etapa ja demorou mais que isso.

- **O benchmark da primeira execucao nao media nada -- e cacheava o resultado.**
As etapas 3 a 5 sao guardadas por `if video_path and model_path and
profile.openvino_available`, e numa instalacao nova `openvino_model_cache/`
ainda nao existe, entao `_find_openvino_model()` devolvia `None` e **todas**
eram puladas. O benchmark inteiro terminava em 0,2 s e recomendava CPU a 0,0
FPS; esse resultado ia para o cache e nunca mais era recalculado, deixando a
maquina configurada por uma medicao que jamais aconteceu.

Agora ele **converte um modelo para OpenVINO antes de medir** (nova etapa 2 de
7). Nao e sobrecarga acrescentada: e trabalho que a aplicacao pagaria de
qualquer forma no primeiro uso real do OpenVINO -- fazer aqui tira do caminho
da primeira analise e coloca num momento em que o splash pode explicar a
espera. E um resultado que nao mediu nada e marcado como inconclusivo e
**nao** vai para o cache: repetir a tentativa no proximo arranque custa
segundos; congelar a resposta errada custa a vida da instalacao.

- **Os caminhos do benchmark eram relativos ao diretorio de trabalho.**
`get_benchmark_cache_path()`, `_find_test_video()` e `_find_openvino_model()`
resolviam contra o CWD. Pelo atalho isso concordava por sorte -- o `.lnk` fixa
`WorkingDirectory` na pasta do repositorio -- mas iniciado de qualquer outro
lugar, `--reset` apagava um arquivo e a aplicacao escrevia outro. Todos
ancorados em `repo_root()` agora, como o resto do projeto.

- **Sem console, o logging morria a cada registro.** `configure_logging`
construia `StreamHandler(sys.stdout)` incondicionalmente. Sob `pythonw.exe`
-- exatamente como o atalho novo abre o app -- `sys.stdout` e None, e
Expand Down Expand Up @@ -87,6 +164,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **A instalacao passou a trazer os seis modelos, nao quatro.** `best_oi.pt` e
`best_seg.pt` estavam marcados `required: false` no manifesto e ficavam atras
de `fetch-weights --all`.

A razao registrada era circular: eles ficavam de fora do download **porque**
`WeightManager` nao sabia descobri-los. A descoberta varria so
`best_*_lateral.pt` e `best_*_topdown.pt`, entao os dois generalistas caiam em
`weights/` e nunca apareciam no catalogo -- baixa-los sem isso seria buscar um
arquivo que nada conseguia selecionar. O defeito real era a lacuna de
descoberta; ela foi corrigida (`discover_weights()` varre `best_*.pt`), e o
download deixou de precisar modelar o problema.

**Um generalista nunca toma um slot padrao.** Os especialistas sao treinados
para um angulo de camera especifico -- um modelo lateral numa cena de topo nao
devolve nada -- entao eles continuam sendo os padroes, e o generalista e algo
que o pesquisador escolhe no painel. O download passou de ~212 MB para
~240 MiB; `--all` continua aceito e agora nao muda nada.

- **A documentacao de instalacao passou a ter duas trilhas explicitas**, operador
e desenvolvedor, em vez de uma so escrita para quem desenvolve. A trilha do
operador nao pede Git (ZIP da pagina de releases) e diz **onde obter** Python e
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ authors:
email: "percilia.giaquinto@unesp.br"
affiliation: "São Paulo State University (UNESP), Botucatu, Brazil"
title: "DRerio LogAI"
version: 7.0.1
date-released: "2026-09-07"
version: 7.1.0
date-released: "2026-09-08"
abstract: "An open-source, GPU-free platform for automated tracking, closed-loop stimulation and behavioural analysis of adult zebrafish (Danio rerio), combining YOLOv11 detection, BYTETracker multi-object tracking and Intel OpenVINO inference in an event-driven architecture."
keywords:
- "zebrafish"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ on a machine without a toolchain — reporting, one command later, that the

**Disk space is the requirement that surprises people.** PyTorch, OpenVINO,
OpenCV and SciPy alone account for most of a ~1.7 GB virtual environment, and the
detector weights add another ~200 MB.
detector weights add another ~250 MB.

### Installing to use it

Expand Down Expand Up @@ -355,7 +355,7 @@ procedure.** It needs neither Git nor a terminal session you have to keep open.
does the same and makes updating easier.)

4. **Run the installer.** Open the extracted folder and **double-click
`install.bat`**. It installs the dependencies, downloads the ~200 MB of
`install.bat`**. It installs the dependencies, downloads the ~250 MB of
detector models, and puts a **DRerio LogAI** icon on your Desktop and in the
Start Menu. Expect several minutes.

Expand Down Expand Up @@ -394,7 +394,7 @@ poetry install --with dev
# Install pre-commit hooks
poetry run pre-commit install

# Download the detector models (~200 MB, required to run the app)
# Download the detector models (~250 MB, required to run the app)
poetry run fetch-weights

# Run the tests to verify the installation
Expand Down
6 changes: 3 additions & 3 deletions README.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ numa máquina sem toolchain — avisando, um comando depois, que o módulo

**Espaço em disco é o requisito que costuma surpreender.** PyTorch, OpenVINO,
OpenCV e SciPy sozinhos respondem pela maior parte de um ambiente virtual de
~1,7 GB, e os pesos do detector somam outros ~200 MB.
~1,7 GB, e os pesos do detector somam outros ~250 MB.

### Instalando para usar

Expand Down Expand Up @@ -358,7 +358,7 @@ inteiro.** Não exige Git nem manter um terminal aberto.
faz o mesmo e facilita atualizar depois.)

4. **Rode o instalador.** Abra a pasta extraída e dê **duplo-clique em
`install.bat`**. Ele instala as dependências, baixa os ~200 MB de modelos do
`install.bat`**. Ele instala as dependências, baixa os ~250 MB de modelos do
detector e coloca um ícone **DRerio LogAI** na Área de Trabalho e no Menu
Iniciar. Leva alguns minutos.

Expand Down Expand Up @@ -397,7 +397,7 @@ poetry install --with dev
# Instale os hooks de pré-commit
poetry run pre-commit install

# Baixe os modelos do detector (~200 MB, obrigatórios para rodar o app)
# Baixe os modelos do detector (~250 MB, obrigatórios para rodar o app)
poetry run fetch-weights

# Execute os testes para verificar a instalação
Expand Down
15 changes: 10 additions & 5 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,10 @@ yolo_model:
# This path is used as fallback; actual model selection happens via model_selection section
# Path is relative to the project root; weights live under weights.source_dir.
#
# Points at a weight `fetch-weights` installs by DEFAULT. It used to name
# `best_seg.pt`, which is published but sits behind `--all`, so a correctly
# provisioned machine still logged `yolo_model.path.not_found` on every start
# -- a permanent false alarm that trained everyone to ignore the one warning
# that means the weights are really missing.
# Points at a perspective-specific weight rather than the generalist
# `best_seg.pt`. Both are installed now -- `fetch-weights` fetches all six --
# but a lateral-trained model is the better default: the generalist is
# something the researcher opts into from the model configuration panel.
path: 'weights/best_seg_lateral.pt'

# Confidence threshold for the ARENA (aquarium) detection.
Expand Down Expand Up @@ -452,6 +451,12 @@ ui:
# The operating system locale is deliberately NOT consulted.
language: en

# Show the getting-started window once the main window is up. It explains the
# six detector models, the four roles they fill, and when OpenVINO helps.
# The window's "do not show again" checkbox writes this key (and only this
# key) to config.local.yaml; it stays reachable from Help -> Getting Started.
show_welcome: true

# -----------------------------------------------------------------------------
# Performance & Parallelization (Phase 8)
# -----------------------------------------------------------------------------
Expand Down
130 changes: 130 additions & 0 deletions docs/releases/RELEASE_NOTES_v7.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# DRerio LogAI v7.1.0

The first-run release. v7.0.0 made the software citable; the work since then has
been about the interval between double-clicking the icon and starting the first
analysis — the part a researcher meets before any of the science.

This release supersedes the unreleased 7.0.1 entry in the changelog: v7.0.0 is
the only tag published so far, so everything below has accumulated since it.

## Relation to the published results

Unchanged from v7.0.0. The validation and benchmark results reported in the
associated manuscripts were produced with release **4.0.0**, available as tag
`v4.0.0`, which remains the version to check out for exact reproduction. Releases
5 through 7 are subsequent work on the codebase and were not used to generate any
reported result.

## Installing this release

On Windows, download the source ZIP from this page and double-click
`install.bat`. It checks Python, checks Poetry, pins the environment to a
supported interpreter, installs the dependencies, downloads the models and
creates a **DRerio LogAI** icon on the Desktop and in the Start Menu.

From a terminal, on any platform:

```bash
git clone https://github.com/MarkSant/DRerio-LogAI.git && cd DRerio-LogAI
poetry install
poetry run fetch-weights # ~240 MiB of trained models, required
poetry run zebtrack
```

No C compiler is needed any more — every dependency installs from a prebuilt
wheel. Budget about 3 GB of free disk for the virtual environment and the models
together. Python 3.12 or 3.13; **not** 3.14, where the pinned numpy has no wheel.

### All six models are now installed

`fetch-weights` downloads **all six** trained models and verifies every file
against a SHA-256 recorded in `weights_manifest.json`. Previously it installed
four and left the two generalists — `best_oi.pt` and `best_seg.pt` — behind an
`--all` flag.

The reason they were excluded turned out to be circular. They were skipped
*because* the weight catalogue could not discover them: discovery globbed only
`best_*_lateral.pt` and `best_*_topdown.pt`, so a downloaded generalist landed in
`weights/` and never appeared in the model panel. Fetching a file nothing could
select was pointless. The discovery gap was the real defect; with it fixed, the
download no longer has to model it. `--all` is still accepted and now changes
nothing.

The four specialists remain the defaults. They are trained for a specific camera
angle — a lateral model on a top-down scene returns nothing — so a generalist is
registered but never claims a default slot; it is something you opt into from the
model panel.

**The model assets for this release are the same files published on `v7.0.0`,
byte for byte**, and `weights_manifest.json` still points there. That is
deliberate: the manifest names a published release, so `fetch-weights` works
immediately rather than depending on this page.

## What changed

### The icon no longer looks dead for four seconds

The splash screen was created *after* the import block that builds the
coordinator graph, so the window only appeared once the heavy loading had already
finished. Under the desktop shortcut the app runs through `pythonw.exe` with no
console, so there was nothing at all to see: no window, no cursor change, no
taskbar entry.

Two costs sat in front of it, both looking like ordinary import lines —
`zebtrack.utils` imports torch in its module body (~1.1 s), and the DI
registration block pulls ultralytics, cv2 and matplotlib on top of it (~3 s).
The splash is now built before both, and the heavy loading runs under a progress
message.

### The first-run benchmark now measures something

Its inference steps are guarded on an OpenVINO model existing, and on a fresh
install nothing has been converted yet — so every measurement step was skipped.
The whole benchmark finished in 0.2 seconds and recommended CPU at 0.0 FPS. That
result was then cached and never recomputed, leaving the machine configured from
a measurement that never happened.

It now converts one model to OpenVINO before measuring. This is not added
overhead: it is work the application pays anyway the first time OpenVINO is used
for real, moved out of your first analysis and into a moment where the splash can
explain the wait. A run that still measures nothing is marked inconclusive and is
**not** cached, so it retries on the next launch instead of freezing a guess.

The seven benchmark steps are also legible now. They were always sent to the
splash, but several finish in milliseconds and were overwritten within a single
frame, so the sequence existed only in the log.

### A getting-started window, and a menu entry that should have existed

Opening the application for the first time gave you a complete interface and no
indication of what to do first — in particular, no hint that the six models need
assigning to roles. Worse, the model configuration panel had **no menu entry at
all**: it was reachable only from a button inside a project view.

There is now a getting-started window after the main window opens, explaining the
models, the four roles they fill, and whether OpenVINO is worth enabling on
*your* machine — it reads the detected hardware and names the devices rather than
offering generic advice. It is reachable afterwards from **Help → Getting
Started**, and the panel itself from **Settings → Model settings**.

### Installing and launching without a terminal (from the unreleased 7.0.1 work)

- `install.ps1` / `install.bat` and `setup.sh`: guided installation that stops at
the first failing step and says what to do about it.
- A desktop and Start Menu shortcut targeting `pythonw.exe -m zebtrack`.
- **Logging died on every record without a console.** `StreamHandler(sys.stdout)`
under `pythonw` got `None`, and the fallback to `sys.stderr` is `None` too —
every record raised inside `emit`, silently.
- **Camera detection needed a stderr to silence.** A failed redirect closed the
process's real stderr; the wizard then listed no cameras at all.
- **The very first launch hung on a window that was never drawn.** The language
chooser called `transient()` on a withdrawn root, and a transient inherits its
master's withdrawn state — so `wait_window` blocked forever on a window nobody
could see, focus or close.
- **A failure before Tk existed vanished without trace.** Startup errors now
reach a message box instead of a `sys.stderr` that does not exist.

## Full changelog

See [`CHANGELOG.md`](../../CHANGELOG.md) for the complete list with the reasoning
behind each change.
2 changes: 1 addition & 1 deletion docs/tasks/active/REFACTOR_GIANTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ top-level helpers and 1 exception class. Concerns:

| Concern | Approx. line range | Marker methods |
| ----------------------------- | ------------------ | ----------------------------------------------------------------------------- |
| Loading & discovery | 145–520 | `_resolve_weights_dir`, `_load_weights`, `discover_perspective_weights`, `_maybe_relocate_path` |
| Loading & discovery | 145–520 | `_resolve_weights_dir`, `_load_weights`, `discover_weights`, `_maybe_relocate_path` |
| Classification | 391–435 | `_classify_weight_type`, `_classify_perspective` |
| Persistence | 522–650 | `_initialize_default_weight`, `save_weights` |
| CRUD (single weight) | 654–1056 | `get_weight_*`, `set_default_weight*`, `add_weight`, `delete_weight` |
Expand Down
Loading
Loading