SnapCheck is a tool to annotate data displayed by graphical boards. Its main goal is to provides an interface to assign ratings to data observed throughout sets of screenshots.
## Quick Start
Any piece of data displayed throughou web frontend. Exemple: images (JPEG, PNG, GIF...)
A rating is an annotation based on a scale wich may be accompagnied by a comment.
A set of elements which are displayed together. Each board can refer to several ratings.
The set of ratings and boards plus a general comment.
from snapcheck.snap.rating import RatingScale, RatingScaleItem
generic_scale = RatingScale(
description="Generic Scale",
ratings=[
RatingScaleItem(name="Bad", value=0, description="Too bad data", color="red"),
RatingScaleItem(name="Ok", value=1, description="Good enough data", color="lightgreen"),
RatingScaleItem(name="Excellent", value=2, description="Outstanding sample", color="green"),
],
)from snapcheck.snap.rating import Rating
fa_rating = Rating(
id="tracto_fa",
name="Carte de FA",
description="Qualité de la carte de FA",
scale=generic_scale,
)
md_rating = Rating(
id="tracto_md",
name="Carte de MD",
description="Qualité de la carte de MD",
scale=generic_scale,
)from snapcheck.snap import Board, ImageElement
metrics_board = Board(
title="Cartes de métriques",
description="Vérifiez la qualité des cartes de métriques.",
elements=[
ImageElement(
title="Carte de FA",
src=".local/demo_sources/CST_FA_and_bundles_masks.png",
intended_ratings=[fa_rating],
),
ImageElement(
title="Carte de MD",
src=".local/demo_sources/CST_MD_and_bundles_masks.png",
intended_ratings=[md_rating],
),
],
)from snapcheck.snap import load_snap
qc = Snap(
title="Tractométrie",
description=f"Tractométrie du CST (Corticospinal Tract) pour le sujet {visit.subject}/{visit.visit}",
metadata=visit.__dict__,
ratings=[
subject_observations,
b0_rating,
mni_registration_rating,
fa_rating,
md_rating,
]
+ bundles_ratings,
boards=[preproc_board, cst_board, metrics_board],
)
f = ".local/demo.snpk"
# qc.to_json(f)
qc.save(f)SnapCheck is made as a Web App. It is composed of a backend written in Python and a frontend, the GUI, written if TypeScript (Javascript).
The core python package, named "snapcheck", provide all it is need to create and read snap files (.snpk).
The backend end use FastAPI to serve the snaps, settings and track some usefull data for the GUI (like the last loaded files paths).
The frontend use the well known React typescript framework.
The backend and the frontend can communicate thanks to an javascript API automatically generated from the FastAPI backend.
Even if the SnapCheck GUI can be displayed by any web browser, a Qt based client is also provided to get a better experience (avoid to lost screen space and get a better focus).
The snapcheck command (or pixi run snapcheck from the sources) starts the backend, then the Qt client
which serves the frontend. The backend is stopped when the client is closed.
snapcheck [--host 127.0.0.1] [--backend-port 8050] [--frontend-port 3000]From the sources, the frontend is served by the Vite development server. In the installed package, the built frontend is served by the client.
The backend and the client can also be started separately:
# Backend. $SNAP_ALLOW_ORIGINS adds origins allowed to call the API (CORS), comma separated.
# By default, only the frontend ports 3000 and 5173 are allowed.
SNAP_ALLOW_ORIGINS=http://127.0.0.1:3050 python -m snapserve --port 8060 [--secret SECRET] [--session ID]
# Qt client, the frontend uses the backend at --api-url (given to the page with ?api=<url>)
python -m snapclient --port 3050 --api-url http://127.0.0.1:8060 [--jwt TOKEN]Set the SNAP_UNSAFE environment variable to 1 to disable API security checks.
The project use Pixi (Conda) to manage dependencies and build.
The frontend depends on the @lepton/core library, built in ../lepton/dist (see the lepton README).
pixi shell
npm install
npm run sass # compile the SASS files (or use a SASS live compiler in VSCode)
npm run build_api # generate the API client, see belowThe typed API client of the frontend (src/api/generated/, imported as @lepton/api) is generated from
the OpenAPI schema of the FastAPI backend. It is not versioned: generate it after cloning and after each
change of the backend API (routes, parameters or models):
npm run build_apiIt runs two steps:
python scripts/export_openapi.py: loads the backend app (snapserve.app) and exports its OpenAPI schema inopenapi.json. The python environment must provide the backend dependencies (lepton, lepton_common, fastapi...), like thelepton-dev-envenvironment.npx @hey-api/openapi-ts: generates the client insrc/api/generated/(types, SDK and TanStack Query options), as configured inopenapi-ts.config.ts.
Then check that the frontend still compiles with npm run typecheck. The generated files must not be edited.
The conda and wheel builds (see below) always regenerate the API client.
Two conda packages are built with rattler-build (recipe/recipe.yaml):
snapcheck: the core python package (no GUI)snapclient: the application (Qt client, backend and built frontend), started with thesnapcheckcommand
They depend on lepton-common and lepton-app, which must be available in the forge (local conda channel).
pixi run build-conda [FORGE] # packages in ./output/noarch
pixi run publish-conda FORGE # build, then publish in the forge
pixi run build-wheel FORGE # wheel (pip / uv) in ./output/wheels, frontend includedFORGE can also be set with the LEPTON_FORGE environment variable.
From the development environment (lepton-dev-env), pixi run build-all builds all the projects.
Install the application from a forge:
pixi global install -c file:///path/to/forge -c https://prefix.dev/conda-forge snapclient
snapcheckpixi run client
// or
python python/snapclient/main.py
Snap
* pouvoir ajouter des notes à un board voir un snap
* implémenter les notes booléenne et avac/sans commentaires
* ajouter un commentaire global
* note par défaut avec un flag qui dit si la valeur a été changée
* flag pour identifier si le snap est a été complété
Back
-
numéro de session dans le JWT, possible? => réouverture d'une session GUI en l'état?
-
save sidebar sections heights in user settings
-
make each section hiddable
-
prendre en compte les notes booléennes
-
ajouter l'élement viewer3d
GUI
* scroll sur les planches
* navigation avec les flêches aussi
* grossiessement du menu lors du dezoom sur les boards
* transformation des boards board/board
* lorsqu'un fichier est ouvert depuisles fichiers récents, afficher le dossier du fichier dans le broswer de fichiers
* clear le champs de recherche du broswer lorsqu'on change de fichier
* bien gérer le has_changed lorsqu'on modofie dans la sidebar
* afficher la nouvelle valeur lorsqu'on modifie la note via le menu contextuel
* férer la fermeture des snap correctement