Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cytoskeletal Organization Classifier

Pixi Badge Python Commit activity GitHub

This tool looks at microscopy images of cells and tries to automatically tell apart two experimental conditions based on the organization of the cytoskeleton (e.g. tubulin staining) around each cell's nucleus. It doesn't care what the two conditions actually are biologically — treatment vs. control, a knockdown vs. wild-type, two drug doses, and so on all work the same way structurally. The tool currently ships set up for a doxycycline-inducible system (labels doxpos/doxneg), which is just this project's naming convention, not a limitation of what you can compare with it — see the filename requirement below.

You don't need any Python or image analysis experience to use it. This guide walks through installing it, preparing your images, running it, and reading the results. If you get stuck, skip to Troubleshooting.

What it actually does, in plain terms

For every image you give it, the tool:

  1. Finds each nucleus (using the DAPI/nuclear stain channel).
  2. Draws a boundary around each cell, growing outward from its nucleus until it hits either another cell or the edge of the stained region (using the cytoskeleton stain channel).
  3. Measures a set of numbers for each individual cell — its shape (size, roundness, elongation), how bright and how variable the staining is, and how "textured" or granular the cytoskeleton staining looks.
  4. Puts all of those measurements into a spreadsheet (one row per cell).
  5. Trains a machine-learning classifier (a Random Forest) to see whether those measurements can reliably distinguish the two conditions' cells apart, and reports how confident that distinction is.
  6. Tells you which measurements mattered most for that distinction, as a table and a bar chart.

The goal isn't just a yes/no answer — it's a quantitative, reproducible way to ask "does this cytoskeletal organization actually differ between conditions, and if so, in what way?" rather than relying on eyeballing images.

Before you start

  • A computer (Windows, Linux, or Intel Mac) with your .czi microscopy image files accessible on disk. Apple Silicon (M-series) Macs aren't supported yet — the version of TensorFlow this project depends on doesn't ship a build for that chip; ask a developer if you need this added.
  • Each image should contain (at least) two channels: one nuclear stain (e.g. DAPI) and one cytoskeletal stain (e.g. tubulin).
  • Each image's filename must contain a condition label the tool recognizes — currently the literal text doxpos or doxneg (case doesn't matter). This is how the tool knows which of the two conditions each image belongs to; images whose filenames contain neither are skipped with a warning, not silently guessed at. If your experiment doesn't naturally use those labels, the simplest fix is to include them somewhere in the filename anyway (e.g. by renaming a copy of the file); ask a developer if you'd like the tool changed to recognize your own label text instead.
  • You'll need pixi installed — this is a tool that automatically installs the correct Python and all the scientific libraries this project needs, in an isolated environment that won't interfere with anything else on your computer. If it's not installed, see the pixi install instructions.

Installing

Open a terminal (PowerShell on Windows; Terminal on macOS/Linux) in this project's folder and run:

pixi install

This downloads and sets up everything the tool needs. It only needs to be done once (or again if pixi.toml/pixi.lock change). On macOS, StarDist segmentation runs on the CPU rather than a GPU (there's no NVIDIA CUDA support on Mac) — it'll still work, just more slowly; see --segmentation-method below for a lighter-weight alternative.

Running the analysis

The simplest way to run it, using the defaults, is:

pixi run python cytoskeleton_classifier.py --input-folder "/path/to/your/images"

(on Windows, a path like "C:\path\to\your\images" works just as well)

This will:

  • Look at every .czi file in that folder.
  • Process each one (this can take a while — segmentation and feature extraction happen per image, and there's a progress bar so you can see it working).
  • Write everything to a results folder (created automatically) in this project's directory.

You can watch the console output as it runs — it prints, for each image, how many nuclei and cells were found, and later prints accuracy numbers as the classifier is trained (see Understanding the results below).

Useful options

Run pixi run python cytoskeleton_classifier.py --help to see the full list. The ones you're most likely to need:

Option What it's for Default
--input-folder Folder containing your .czi files (a placeholder path — you'll want to set this)
--output-folder Where results get written ./results
--nuclei-channel Which channel index is your nuclear stain 0
--cells-channel Which channel index is your cytoskeletal stain 1
--z-slice Which focal plane (z-slice) to analyze, if your images are 3D stacks 0 (the first)
--segmentation-method Algorithm used to find nuclei: stardist or conventional stardist
--workers How many images to analyze in parallel (speeds things up on multi-core machines) all CPU cores

Channel indices are zero-based — the first channel in your file is 0, the second is 1, and so on. If the tool's console output shows the nuclei/cells intensity ranges looking wrong (e.g. very flat, mostly-zero images), the channel indices are the first thing to check — you may have the nuclear and cytoskeletal channels swapped, or your file may have more channels than expected.

Segmentation methodstardist is a pretrained deep-learning model for finding nuclei and is the default; conventional is a more traditional thresholding-based approach. In testing, the two give very similar results, so conventional is a reasonable fallback if StarDist is slow on your machine (no GPU) or behaves oddly on unusual staining.

Understanding the results

Everything lands in the output folder (results by default):

  • cell_features.csv — one row per cell, across all your images. Columns include the condition (doxpos/doxneg, or whichever two labels your filenames use), which image the cell came from, and all the measured features (shape, intensity, texture — see What gets measured below). Open this in Excel if you want to explore or re-plot the raw numbers yourself.
  • feature_importance.csv and feature_importance.png — after training, a ranked table and bar chart of which measurements were most useful for telling the two conditions' cells apart. A feature near the top of this list is one worth following up on biologically; features near the bottom contributed little to the classifier's decisions.
  • segmentation_qc/ — for every image, two label images (..._nuclei_labels.png and ..._cell_labels.png) showing exactly which pixels were assigned to which nucleus/cell. Look at a few of these before trusting the numbers — if the segmentation looks wrong (cells merged together, obvious background picked up as a "cell", etc.), the downstream features and classifier accuracy will be unreliable too, since they're all computed from these boundaries.

The two accuracy numbers printed to the console

The tool prints two different diagnostic scores while it runs — they answer different questions and it's easy to conflate them:

  1. "Image-identity accuracy" — can the classifier tell which image a cell came from, just from its measurements, ignoring condition entirely? This is a sanity check, not the result you care about. If this number is high (much higher than 1 divided by your number of images), it means your images differ from each other in ways that have nothing to do with the condition being compared — e.g. staining brightness, focus, or exactly where the segmentation threshold landed on that particular image. That's an early warning that the real classifier below might be picking up on "which image" rather than "which biological condition," which would make its result meaningless.
  2. "Cross-validation accuracy" — the number that actually answers "can the two conditions be told apart?" It's reported both per-image (each line shows one image's filename and the accuracy when that image was held out and predicted using only the other images) and as an overall average at the end. Held-out testing per image, rather than per cell, matters here: cells from the same image resemble each other for boring technical reasons (shared staining batch, shared focus, shared segmentation run), so testing on cells the model has already seen images from would flatter the score. If one image's accuracy is much lower than the rest, that image is worth a closer look (check its QC images) before trusting the overall average.

A cross-validation accuracy well above 50% (chance, for a two-condition problem), especially if consistent across held-out images, is evidence of a real, reproducible difference between conditions. An accuracy near 50%, or one that swings wildly image-to-image, means the tool isn't finding a reliable difference — worth investigating rather than reported as a negative result outright, since it could also mean the features it measures aren't capturing the biology you're interested in.

What gets measured per cell

All intensity-based measurements are first corrected for that cell's own nuclear stain brightness, so that differences in overall staining intensity or illumination between images don't get mistaken for real biological differences.

  • Shape: area, perimeter, eccentricity (how elongated), solidity (how much of the convex hull is filled — lower means more irregular/concave), aspect_ratio.
  • Nuclear intensity: nuclei_std, nuclei_max, nuclei_min (spread and extremes of DAPI signal within the cell).
  • Cytoskeletal intensity: cells_mean, cells_std, cells_max, cells_min, cells_cv (coefficient of variation — how "patchy" the staining is relative to its own average).
  • Texture: cells_granularity — a measure of fine-grained structure/texture in the cytoskeletal stain (higher means more filamentous/textured detail, lower means smoother/more diffuse staining).
  • Colocalization: nuclei_cells_correlation — how closely the nuclear and cytoskeletal signals track each other spatially within the cell.

Troubleshooting

"No CZI files found in ..." — double check --input-folder points at the right folder, and that the files really do have a .czi extension.

A specific image gets skipped with "Could not determine condition" — its filename doesn't contain doxpos or doxneg (the two condition labels the tool currently recognizes). Rename the file (or a copy of it) to include one of those strings.

Nuclei/cells intensity ranges printed to the console look wrong (e.g. all near zero, or one channel looks identical to the other) — check --nuclei-channel and --cells-channel against how your microscope software actually ordered the channels in the file; they may need to be swapped, or your file may have channels this tool doesn't expect.

Segmentation looks bad in the QC images (nuclei merged together, cells running into each other, obvious noise picked up as a cell) — try switching --segmentation-method to the other option and compare; also check --z-slice is actually the plane you meant to analyze if your images are z-stacks.

It's slow — increase --workers if you have spare CPU cores (feature extraction runs in parallel; nuclei/cell segmentation always runs one image at a time, since the default StarDist method is GPU-accelerated where a GPU is available and doesn't benefit from parallel CPU workers).

Cross-validation accuracy is low or inconsistent, and image-identity accuracy is high — your features are likely dominated by per-image technical variation (staining batch, illumination, focus) rather than biology. This isn't a bug in the tool; it's the tool correctly telling you the images aren't comparable enough yet. Consider more consistent staining/imaging conditions across your two conditions' samples, or imaging more replicates per condition.

For anyone extending the code

See CLAUDE.md for a developer-oriented description of the pipeline's internals, architecture, and implementation conventions.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages