ClassiPyR 0.3.0
- ClassiPyR now requires R >= 4.4.0 (for base R’s
%||%operator, which the app already relied on). -
Python is no longer required. iRfcb 0.10.0 reads and writes MATLAB
.matfiles with a native R implementation, so ClassiPyR now requiresiRfcb >= 0.10.0and all Python-related code has been removed:reticulateis no longer an Import, the app no longer initializes a Python environment at startup, and the “Python not available” warnings and export blocks are gone —.matsaving, SQLite →.matexport and MATLAB ZIP export work out of the box for everyone.-
init_python_env()is deprecated and now a no-op; thevenv_pathargument ofrun_app()is deprecated and ignored (a warning is issued when supplied). Thepython_venv_pathentry in saved settings is ignored. - If you need a Python environment for other iRfcb features (e.g. feature extraction), use
iRfcb::ifcb_py_install()directly.
-
New features
- New exported function
fill_unclassified_db()backfills a partially imported sample. After importing only selected taxa withimport_png_folder_to_db(), it reads each sample’s complete ROI list from its.adcfile and inserts the remaining ROIs asunclassified(marked as not yet reviewed), leaving existing annotations untouched. - New exported function
import_png_folder_with_unclassified()wrapsimport_png_folder_to_db()andfill_unclassified_db()into a single call. It imports the selected-taxa PNGs and then backfills the remaining ROIs asunclassifiedfor only the samples that were just imported, so each imported sample is fully represented without touching samples from earlier import sessions. - New exported function
update_settings_file()performs read-merge-write updates to the settings JSON file, so callers that only know a subset of settings keys can update them without erasing the rest (#36).
Performance
- Selecting images is now instant: Clicking or drag-selecting images in the gallery previously re-rendered the entire page of image cards on the server for every selection change (the gallery greyed out while Shiny recomputed and the browser rebuilt the DOM), purely to apply a border color the browser had already drawn. The gallery render now isolates the selection state and leaves selection styling to the client; the Select Page / Select All / Deselect All buttons sync card styling through a lightweight custom message instead of a full re-render. The renders that do still happen (page or filter changes, relabels) are also faster: two per-card linear scans over the classification tables were replaced with vectorized lookups.
- Selecting images no longer shifts the gallery layout: The thicker blue (selected) and yellow (relabeled) borders made cards a few pixels wider than unselected ones, which could push the last image of a row onto the next line — moving images around mid-selection. Card styling now lives in CSS rules where border and padding always sum to the same width, so state changes never resize a card.
Bug fixes
Interface bug review (#36) — data integrity:
-
Settings are no longer partially erased: Uploading a class list file or running a “SQLite → MATLAB ZIP” export previously rewrote
settings.jsonwith only the keys those dialogs knew about, silently resetting storage format, data source, dashboard configuration, Python venv path, prediction model and other saved settings on the next start. All settings writes now merge into the existing file. -
“Both SQLite and MAT” storage now persists the class list: With save format “Both” selected, class list changes were never auto-saved to the database and never restored at startup (the check only matched the literal value
"sqlite"), so class list edits silently disappeared between sessions. - Predict no longer overwrites manual corrections on repeated runs: The second Predict click re-classified images that had been manually relabeled before the first prediction, silently discarding the user’s corrections. All manual relabels recorded in the session’s changes log are now excluded from re-prediction.
-
External class review no longer leaks into the database: Relabeling in an external PNG folder review and then switching back to Sample Mode (or closing the app) wrote a bogus
__external_review__sample into the annotations database, polluted the Class Review filter dropdowns, and copied the external PNGs into the PNG output folder. Leaving class review now clears the review data, and the auto-save paths refuse class review state entirely. - Cached samples no longer mix up classifications: Reopening a previously loaded sample from the session cache and switching it to validation mode could restore the previous sample’s classifications into it (every tile showed “Not found”, and a save would have written them under the wrong sample name). A failed cache load (e.g. moved or unmounted data folder) also no longer leaves the gallery pointing at the previous sample’s images.
- Save failures are reported as errors: A failed save (e.g. MAT format with Python unavailable) was previously indistinguishable from “nothing to save” and surfaced as a benign “Save returned no changes” warning. Errors from any storage backend are now shown as errors with the underlying message.
- Session-end auto-save uses each sample’s own image folder: Unsaved cached samples were saved with the folder of the last-viewed sample, so their PNG/MAT export silently produced nothing. An empty Annotator field is now saved as “Unknown” instead of an empty string, and closing the app no longer deletes the persistent dashboard PNG cache.
Interface bug review (#36) — user interface:
-
Save button works for PNG-only samples: Samples that exist only as extracted PNG folders (no
.roifile) failed to save with “Cannot find ROI data folder”, even for SQLite saves that never need it. The button now uses the same PNG-folder fallback as the navigation auto-save, and an ADC folder is only required when a MAT export actually needs it. - WoRMS “Rematch Unmatched” works: The button always failed with an internal error due to a column mismatch in the results assignment, and never updated the match table.
-
WoRMS “Rename classes” keeps taxonomy fields: Applying matches with renaming enabled stored only the AphiaID for renamed classes; their
scientific_name,accepted_nameandaccepted_aphia_idfields were left empty, which in turn blanked the EcoTaxa hierarchy export for those classes. - Drag-select works on scrolled pages: The selection rectangle was offset from the cursor by the scroll distance once the gallery was scrolled, selecting the wrong images.
- Relabeled images keep their yellow border after being selected and deselected.
-
Gallery empty states render correctly: Filtering to a class with no images now shows “No images to display” instead of a blank area with a nonsensical “Page 1/1 (1-0 of 0)” pager, and pagination no longer desyncs (dead prev/next buttons) after relabeling shrinks a filtered class. Loading a classification CSV without a
scorecolumn no longer breaks the gallery render, and the annotation-mode title bar no longer fails to render with zero images. - Sample dropdown with large sample lists: The random/previous/next buttons updated the server-side sample dropdown in a way that only worked for the first ~1000 options; with larger filtered lists the dropdown went blank and (for the random button) the following Load click did nothing.
- Filters survive rescans: Saving an unrelated setting or re-syncing folders no longer resets the Year/IFCB filters back to their defaults; current selections are kept when still valid.
- Annotation markers survive startup failures: When the startup folder scan bailed out early (missing folder, empty dashboard URL), the cached file index was stripped of its annotated-samples list, hiding all ✎ markers until a full re-sync.
- Prediction model survives an unreachable Gradio endpoint: Opening Settings while the Gradio API was down cleared the configured prediction model, and saving any setting then persisted the empty value, permanently disabling the Predict button.
- Export dialog fixes: Removing every instrument from the “Filter by IFCB” export filter now aborts with a warning instead of exporting the entire database; classes added during a PNG import appear in the “Relabel to:” dropdown immediately; dashboard export completion counts now add up (skip-filtered samples are counted as skipped).
-
Summary Table shows NA instead of
NaN%/Inf%for classes whose images have no prediction scores, and local sample loads show a single “N images” notification instead of two with differing counts. -
Dashboard bin listing:
list_dashboard_bins()now usesiRfcb::ifcb_download_dashboard_metadata()(theapi/export_metadataendpoint) instead of theapi/list_binsendpoint, which was removed from the upstream IFCB Dashboard (2026-03-08) and no longer worked.
ClassiPyR 0.2.1
New features
-
Export SQLite → MATLAB ZIP: New “SQLite → MATLAB ZIP” button in Settings that bundles
.matannotation files, feature CSVs, aclass2use.matconfig file, optional raw data, and READMEs into a distributable MATLAB-format ZIP archive viaiRfcb::ifcb_zip_matlab(). When using SQLite-only storage, annotations are automatically converted to.matfiles (requires Python with scipy). Supports the same README metadata fields as the existing PNG ZIP export. - IFCB instrument filter for ZIP exports: Both ZIP and MATLAB ZIP export dialogs now include a “Filter by IFCB” dropdown when the database contains samples from multiple instruments. Select one or more instruments to include; deselect instruments to exclude them from the archive.
- Local classifier files in dashboard mode: When “Use dashboard auto-classifications” is disabled and a Classification Folder is configured, local classifier output files (CSV/H5/MAT) are now scanned during dashboard sync. Classified samples show the correct status (checkmark) in the sample dropdown, consistent with the loading behavior.
-
Clear Annotations: Added a “Clear Annotations” button in sample mode that permanently deletes a sample’s annotations from the SQLite database (and removes the
.matfile if present). The button is disabled outside annotation mode and shows a confirmation dialog before proceeding. After clearing, the sample resets to a blank unclassified state. - New exported function
delete_annotations_db()for programmatic deletion of a sample’s annotations from the database.
UI Improvements
- Reorganised Settings panel: Folder paths are now grouped into clear “Input Folders” and “Output” sections. The ROI/PNG data folder is listed first as the primary input. Database folder and annotation storage format are grouped together under Output. The former standalone “Annotation Storage” section has been merged into Output.
- Added descriptive help text to all folder path fields in Settings.
- Help text is now visually closer to the field it describes, with more spacing before the next field.
- The Predict button is now always visible (greyed out when disabled).
Bug fixes
-
Dashboard auto-classification URL: Fixed class_scores CSV download failing for dashboard URLs without a
?dataset=parameter. The IFCB Dashboard serves class_scores files from a dataset-specific path (e.g.,/mvco/) rather than the generic/data/endpoint used for other file types. The newresolve_sample_dataset()function automatically queries the Dashboard bin API to determine the correct dataset when not explicitly provided in the URL. - Mode switching in dashboard mode: Fixed “No ROI dimensions available to create annotations” error when switching from validation to annotation mode for dashboard-loaded samples. The mode-switching code now checks the dashboard PNG cache for ROI dimension inference, not just local PNG paths.
-
Python environment detection: Fixed
py_discover_config()returning system Python instead of the active virtualenv in the Shiny runtime, causing iRfcb’s scipy check to fail for all.matfile operations (class list download, SQLite → .mat export, MATLAB ZIP export). The fix setsRETICULATE_PYTHONbefore Python initialization so thatpy_discover_config()resolves to the correct virtualenv binary. - Dashboard auto-classification fallback: When “Use dashboard auto-classifications” is enabled but the dashboard has no classifier output for a sample, a user-friendly notification is now shown instead of only logging a console warning. Local classifier files are no longer loaded as an unintended fallback in this mode.
- The validation/annotation mode toggle now appears whenever auto-classification data exists for a sample, not only when both manual annotations AND auto-classifications pre-exist. This allows switching to annotation mode for samples that only have auto-classifications (✓), creating blank annotations on the fly. Previously these samples had no toggle and were locked in validation mode.
- The session cache now stores and restores the mode toggle state, so the toggle no longer disappears after switching between cached samples.
- Fixed “argument is of length zero” warning when closing the app, caused by the autosave-on-close handler failing to read the annotator name and class list after the session had already ended.
ClassiPyR 0.2.0
New features
Class List Persistence
-
Auto-persist class list in SQLite: When using SQLite storage (the default), the class list is now automatically saved to a
global_class_listtable whenever it changes — adding classes, renaming, applying WoRMS matches, uploading a file, or importing from PNGs. On next startup the class list is restored from the database, so no manual file upload is needed. File-based class lists (.mat/.txt) remain supported as a fallback and for sharing. - New exported functions:
save_global_class_list_db()andload_global_class_list_db()for programmatic access to the persisted class list.
Import / Export
- Added Import PNG → SQLite button in Settings > Import / Export (#15). Imports annotations from a folder of PNG images organized in class-name subfolders (e.g. exported by ClassiPyR or other tools). Folder names follow the iRfcb convention where trailing
_NNNsuffixes are stripped. - When importing PNG folders with class names not in the current class list, a class mapping dialog lets users remap unmatched classes to existing ones or add them as new classes.
- Overwrite warning dialog shown when imported samples already exist in the database.
- New exported functions:
scan_png_class_folder()for scanning PNG class folder structures, andimport_png_folder_to_db()for programmatic bulk import. - Skip class from PNG export: New option in Settings to exclude a specific class (e.g. “unclassified”) from PNG output.
-
Export SQLite → ZIP (EcoTaxa-ready): Added a new export action in Settings > Import / Export to create a ZIP archive directly from SQLite annotations. The flow exports class-organized PNGs, writes per-class inventories as
ecotaxa_<CLASSNAME>.tsv(with EcoTaxa type row), and zips withinclude_txt = TRUE(#21). - Customizable ZIP README metadata: The ZIP export dialog now supports optional README fields (Author, Contact e-mail, DOI, Licence, Version, Citation, Institute), persisted in settings. Empty optional fields are omitted from the generated README. The README also appends archive provenance including the current ClassiPyR version and citation.
-
Optional ZIP splitting: ZIP export dialog now exposes
split_zipandmax_sizecontrols mapped toiRfcb::ifcb_zip_pngs().max_sizeis shown only when split mode is enabled. - Local sample discovery now supports extracted PNG sample-folder layouts in addition to ROI files. Both simple and hierarchical folder structures are detected, as long as sample directories follow IFCB sample naming.
- Local sample loading now falls back to PNG sample folders when ROI files are unavailable, enabling image viewing and annotation workflows for PNG-only datasets.
- PNG-only samples now derive ROI-like dimensions from PNG headers and sort images by area (
width * height) to match ROI-based ordering behavior. - Folder sync progress now reports staged updates (including long directory scans) so the “Syncing folders…” progress bar shows meaningful movement instead of remaining static.
- Added safeguards to ensure user-managed PNG source folders are never deleted by temporary-folder cleanup logic.
Classification / Review
-
HDF5 classification support: Load classifications from
.h5files produced by iRfcb (>= 0.8.0) (#14). Requires the optionalhdf5rpackage. - Classification threshold toggle: New “Apply classification threshold” checkbox in Settings controls whether thresholded or raw predictions are used, for all classification formats (CSV, H5, MAT).
-
Live Prediction: Added a “Predict” button in Sample Mode that classifies all images in the loaded sample using a remote CNN model via
iRfcb::ifcb_classify_images()(#17). Configure the Gradio API URL and model in Settings > Live Prediction. The model dropdown is populated dynamically from the Gradio server. Predictions respect the classification threshold setting, skip manually reclassified images, and new class names from the model are added to the class list automatically. A per-image progress bar shows classification progress. - Class Review Mode: View and reclassify all annotated images of a specific class across the entire database (#16). Switch to class review via the mode toggle in the sidebar, select a class, and load all matching images from all samples at once. Changes are saved as row-level updates to the database.
- External PNG folder review: Class Review mode now supports an External PNG Folder source in addition to the database. Load a folder of PNG images, relabel them in the gallery, and export into class-name subfolders. Useful for sorting or correcting a flat folder of images from an external classifier without importing into the database.
- New exported functions:
list_classes_db(),load_class_annotations_db(), andsave_class_review_changes_db()for programmatic class review operations.
Taxonomy / WoRMS
-
WoRMS class matching: Added a Match WoRMS AphiaID action in the Class List Editor. Class names can now be matched against WoRMS (
worrms::wm_records_names()), with accepted AphiaIDs stored per class and shown inline in the class list. Matching results distinguish accepted names, synonyms, unmatched classes, and skipped long queries (>80 chars). The results dialog supports manual rematch by editing query text per unmatched class before applying. - New exported functions:
sanitize_worms_query(),build_worms_match_rows(),save_class_taxonomy_db(), andload_class_taxonomy_db()for programmatic WoRMS/taxonomy workflows.
IFCB Dashboard
-
IFCB Dashboard support: Connect directly to remote IFCB Dashboard instances (e.g.
https://habon-ifcb.whoi.edu/) without downloading data locally (#13). Toggle between “Local Folders” and “IFCB Dashboard” in Settings, enter a Dashboard URL (with optional?dataset=parameter), and browse samples from the API. Images are downloaded on demand and cached locally. Optionally load dashboard auto-classifications for validation mode. Supports MAT export by downloading ADC files on demand, with graceful fallback to SQLite-only when ADC is unavailable. - Configurable dashboard download settings: Dashboard mode now exposes parallel downloads, sleep time, timeout, and max retries in an “Advanced Download Settings” section in Settings.
- Local classification files in dashboard mode: The Classification Folder setting is now available in dashboard mode. When configured, local CSV/H5/MAT classification files take priority over dashboard auto-classifications, with dashboard autoclass as a fallback.
- New exported functions:
parse_dashboard_url(),list_dashboard_bins(),download_dashboard_images(),download_dashboard_images_bulk(),download_dashboard_image_single(),download_dashboard_images_individual(),download_dashboard_adc(),download_dashboard_autoclass(), andget_dashboard_cache_dir()for programmatic dashboard access.
UI improvements
- The class list editor now shows the number of annotated images per class in parentheses, queried from the SQLite database.
- The class list editor now optionally shows
[AphiaID: ...]per class when WoRMS mappings exist. - Added an Apply button in Settings to activate changes immediately without closing the dialog (#18).
- Prevented shinyFiles from freezing when an invalid path is entered by disabling Browse and showing a notification for non-existent input folders (#19).
- Select Page / Select All: The “Select All” button now uses a two-click workflow — first click selects the current page, second click selects all images across all pages. Resets automatically when navigating pages, changing filters, or loading a new sample.
- In annotation mode, images are now sorted by width (x-dimension, descending) instead of area, for all classes. This groups images with similar widths for a more uniform gallery layout.
-
Gallery images at native resolution: Removed the
max-height: 120pxCSS constraint so images display at their actual pixel dimensions. This preserves small morphological details and ensures the measuring tool reports accurate distances.
ClassiPyR 0.1.1
New features
- Added “Export validation statistics” checkbox in Settings (below the output folder path). When unchecked, per-sample CSV files are not written to the
validation_statistics/subfolder. Useful when annotating from scratch where validation statistics are not relevant (#9). - Added a confirmation dialog before bulk export of SQLite annotations to
.matfiles. The dialog explains that existing.matfiles in the output folder will be overwritten, preventing accidental data loss (#10).
ClassiPyR 0.1.0
Initial release of ClassiPyR, a Shiny application for manual classification and validation of Imaging FlowCytobot (IFCB) plankton images.
Features
Sample Management
- Load samples from ROI files with automatic year/month filtering
- Support for validation mode (existing classifications) and annotation mode (new samples)
- Resume previous annotations from saved files
- Navigate between samples with previous/next/random buttons
- Filter samples by classification status (all/classified/annotated/unannotated)
- Samples with auto-classifications can switch between validation and annotation modes
Classification Loading
- Load classifications from CSV files (recursive folder search)
- Load classifications from MATLAB classifier output (.mat files)
- Option to apply classification threshold for MATLAB results
- Automatic sample status indicators in dropdown:
- ✎ = Has manual annotation
- ✓ = Has auto-classification
- ✎✓ = Has both
- = Unannotated
Image Gallery
- Paginated image display (50/100/200/500 images per page)
- Images grouped by class on consecutive pages for efficient review
- Filter images by class
- Click to select/deselect individual images
- Drag-select to select multiple images at once
- Visual indicators for selected and relabeled images
- Unmatched class detection with yellow warning highlighting
Annotation Tools
- Relabel selected images to any class
- Select all / deselect all buttons
- Quick class search in relabel dropdown
- Changes tracked and displayed in statistics tab
Class List Management
- Load class lists from .mat or .txt files
- Create class lists from scratch directly in the app
- Edit class names (with warnings about index preservation for ifcb-analysis)
- Add new classes to end of list
- Sort class list by ID or alphabetically (view only)
- Export class list as .mat or .txt
- Visual warnings for classes in classifications not in class2use list
Annotation Storage
- SQLite database backend (default) — no Python dependency required
- Optional MATLAB
.matfile export for ifcb-analysis compatibility (requires Python/scipy) - Configurable storage format in Settings: “SQLite”, “MAT file”, or “Both”
-
import_mat_to_db()andexport_db_to_mat()for migration between formats - Sample discovery scans both
.matfiles and the SQLite database - When loading a sample, SQLite is checked first (faster), with
.matfallback - Separate database folder setting (defaults to output folder)
Output
- Save validation statistics as CSV
- Organize output PNGs by class folder (for CNN training)
- Auto-save when navigating between samples
- Support for non-standard folder structures via direct ADC path resolution
File Index Cache
- Disk-based file index cache for faster app startup on subsequent launches
- Avoids expensive recursive directory scans when folder contents haven’t changed
- Sync button in sidebar to manually refresh the file index
- Cache age indicator shows when folders were last scanned
-
rescan_file_index()function for headless use (e.g. cron jobs) - Auto-sync option (enabled by default) to control whether app scans on startup
Pre-releases
- v0.1.0-beta.2 (2026-02-04): File index cache, cross-platform folder browser, annotation mode sorting, and notification improvements.
- v0.1.0-beta.1 (2026-01-29): First beta version.
Technical Notes
- SQLite is the default annotation storage — works out of the box with RSQLite
- Python with scipy is optional — only needed for MAT file export
- Uses iRfcb package for IFCB data handling
- Session cache preserves work when switching samples
- Input validation, XSS prevention, and path traversal protection