This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Install dependencies
pip install -r requirements.txt
# Initialize the database (run once before first use)
flask init-db
# Run the development server (FLASK_DEBUG=1 permits the insecure dev SECRET_KEY;
# in any non-debug run a real SECRET_KEY env var is required or startup aborts)
FLASK_DEBUG=1 flask runThere are no tests or linting tools configured in this project.
This is a Flask web application for laboratory sample tracking, focused on protein cross-linking and mass spectrometry experiments.
- app.py — Flask app, all routes, CRUD logic, and form/model wiring
- models.py — SQLAlchemy ORM models with relationships
- forms.py — WTForms form definitions, including a custom
MultiCheckboxField - config.py — Flask/SQLAlchemy config (SQLite by default)
- schema.sql — Raw DDL; used by
flask init-dbto create tables - fileInfoScript.py — standalone command-line
SpectraAddressBookutility (run directly, e.g.python fileInfoScript.py <path>) that recursively scans directories for mass spectrometry data files (.raw,.mgf,.mzml, and.dacquisition directories) and writes a CSV. It is not imported by the web app — it's an offline helper for populating file inventories.
Five main entities: Project → Experiment → Sample, plus Species, CellLine, and Virus as reference data.
- Samples are polymorphic:
CrosslinkSamplevsIdentificationSample, each with a distinct set of type-specific fields. The discriminator is thecrosslinked_sampleflag (1 = crosslink, 0 = identification); app.py nullifies the irrelevant type's fields on save to maintain integrity. - Species and CellLine relate to Sample via many-to-many junction tables (
sample_species,sample_cell_line). - CellLine relates to Virus via the
cell_line_virusmany-to-many junction table. - Virus has an optional FK to Species and an optional
variantfield. - Projects have an
activeflag for archival without data deletion. Project.code,Experiment.code, andMassSpecSample.code(the PK fields) may not contain underscores — enforced by theno_underscoresvalidator in forms.py. This is required because the run queue's generatedfile_name_root(see Files & Run Queue) joins codes with_as a separator; an underscore inside a code would make that filename unparseable.
- Route handlers in
app.pyinstantiate forms (fromforms.py) and query models (frommodels.py). - Form choices (dropdowns, multi-selects) are populated dynamically from the database at request time.
- On POST, form data is validated, then mapped to SQLAlchemy model instances and committed.
- Templates in
templates/<entity>/render the response;base.htmland_form_helpers.htmlare shared.
- Acquired files are tracked as
AcquiredFileDB rows (not by live disk scanning). They are listed at/files, created per-sample via.../db-files/new, and can be re-associated to a different sample at/files/<id>/edit. Sizes are stored in bytes (entered as decimal GB and multiplied by1e9). - Run queue (
QueuedFile):/api/queue/*endpoints append/update/delete/clear runs for an instrument's per-day run order, driven by thestatic/js/queue-panel.jspanel.daily_counteris the run order; clearing marks rowsexportedrather than deleting so counters never get reused./api/queue/csvexports a Thermo Xcalibur sequence CSV (cp1252-encoded). - Aggregate views:
/api/tree(size-sorted project→experiment→sample→file tree),/instrument-usage, and/disk-usage.