{"name":"napari-worm-neuron-annotator","display_name":"Worm Neuron Annotator","visibility":"public","icon":null,"categories":["Utilities"],"schema_version":"0.2.1","on_activate":null,"on_deactivate":null,"contributions":{"commands":[{"id":"napari-worm-neuron-annotator.LabelManager","title":"Worm Neuron Annotator","python_name":"napari_worm_neuron_annotator._widget:LabelManager","short_title":null,"category":null,"icon":null,"enablement":null}],"readers":null,"writers":null,"widgets":[{"command":"napari-worm-neuron-annotator.LabelManager","display_name":"Worm Neuron Annotator","autogenerate":false}],"sample_data":null,"themes":null,"menus":{},"submenus":null,"keybindings":null,"configuration":[]},"package_metadata":{"metadata_version":"2.4","name":"napari-worm-neuron-annotator","version":"0.2.0","dynamic":["license-file"],"platform":null,"supported_platform":null,"summary":"Navigate neuron box ROIs and control Labels visibility in napari","description":"# napari-worm-neuron-annotator\n\n`napari-worm-neuron-annotator` is a napari plugin for navigating neuron bounding-box\nROIs and controlling the visibility of checked IDs in a `Labels` layer.\n\nThe plugin treats the two representations differently:\n\n- the ROI array is the authoritative neuron identity and box geometry;\n- the `Labels` layer is a display context in which label value\n  `neuron_id + 1` represents a zero-based neuron ID;\n- napari `Vectors` layers are generated at runtime to show overlapping boxes\n  without writing them into a dense integer mask.\n\nOriginal ROI arrays and Labels data are never modified.\n\n## Features\n\n- Checkable neuron list with a distinct active neuron.\n- All/None controls and cumulative Q/W navigation.\n- Independent opacity for checked and unchecked Labels.\n- Exact RGB preservation when changing alpha.\n- Read-only loading of `neuron_pt_tuple.npy`.\n- Dynamic 2D bounding rectangles on the current z slice.\n- Dynamic 3D 12-edge wireframes for the current volume.\n- Active-neuron highlighting and view centering.\n- Zero-copy Z-layer display synchronized across Image, Labels, and boxes.\n- Zero-based ROI annotation with optional Excel import/export.\n- Automatic restoration of the original Labels colormap and opacity when the\n  widget closes or switches to another Labels layer.\n\n## Installation\n\nInstall into an existing napari environment:\n\n```text\npip install napari-worm-neuron-annotator\n```\n\nFor a fresh environment, install napari with its default Qt 6 backend:\n\n```text\npip install \"napari-worm-neuron-annotator[all]\"\n```\n\nExcel support alone is available through:\n\n```text\npip install \"napari-worm-neuron-annotator[excel]\"\n```\n\nThe base plugin does not install or select a Qt binding. The napari\nenvironment owns the Qt backend; the convenience `all` extra delegates that\nchoice to napari.\n\nThis release targets Python 3.11–3.14 and napari 0.8.x. See the\n[napari 0.8 migration notes](docs/napari-0.8-migration.md) for the dependency\nand compatibility decisions.\n\n## Basic Labels workflow\n\n1. Open a `Labels` layer.\n2. Open `Plugins > Worm Neuron Annotator`.\n3. Select the Labels layer in the widget.\n4. Click a row to check and activate that ID.\n5. Use the checkbox column to add or remove IDs from the persistent set.\n6. Use Q and W to check and activate the previous or next valid ID without\n   clearing IDs already checked.\n7. Use **All** or **None** to check every ID or clear all checked/active IDs.\n\nThe active row is bold and remains the current row. Unchecking the active ID\nclears the active state; unchecking another ID does not change the active\nneuron.\n\nThe **Labels Layer** panel also controls checked and unchecked label alpha.\nThe defaults are `0.50` for checked labels and `0.00` for unchecked labels.\nHide the entire mask with the normal eye icon in napari's layer list. The\noriginal Labels colormap and opacity are restored automatically when the\nwidget closes or switches to another Labels layer.\n\nFor small in-memory arrays, IDs are discovered exactly from the Labels data.\nThe plugin intentionally does not scan out-of-core arrays or arrays larger\nthan 10 million voxels. Load an ROI NPY file in those cases.\n\nLabels-only discovery cannot recover an identity that has already been\ncompletely overwritten in a dense mask.\n\n## Z-layer display\n\nThe compact **Z Layers** panel separates a 3D volume along Z so individual\ndepth ranges can be rendered without the other ranges obscuring them:\n\n1. Select a compatible Image layer.\n2. Inspect the current-time curve showing how many pixels in each Z slice are\n   strictly above the editable threshold (default `170`). Click the curve to\n   add or remove a cut, or enter explicit cuts such as `4,10`.\n3. Click **Split**.\n4. Use **Show** to select `All` or one generated layer.\n\nCuts use half-open Python ranges. For a volume with 18 Z slices, `4,10`\ncreates `[0,4)`, `[4,10)`, and `[10,18)`. A boundary slice belongs to the\nfollowing layer.\n\n**All** displays every generated Image layer using additive blending, the\ncomplete Labels layer, and all currently valid checked boxes. **Layer k**\ndisplays only that Image\nrange, the corresponding read-only Labels slice, and boxes whose center Z\nbelongs to the range. A box that crosses a cut is shown whole in the one\nlayer containing its center.\n\nChecked and active neuron identities remain global. In an individual layer,\nQ/W navigates only neurons assigned to that layer; other neurons remain in\nthe list, are shown in gray, and keep operable checkboxes. Activating a gray\nrow does not move the view outside the selected Z layer.\n\nGenerated Image layers use slices of NumPy arrays, memory maps, or Dask\narrays rather than full-size zero-filled copies. Direct Zarr arrays should\nbe wrapped as Dask arrays before splitting. The Image and Labels sources\nmust have matching `(z,y,x)` or `(t,z,y,x)` shape, axis labels, scale,\ntranslation, and units, with axis-aligned volume depiction and no clipping\nplanes. **Clear** removes all generated Z layers and restores the original\nsource visibility. Normal napari eye icons may still override visibility\nuntil the next **Show** selection.\n\n### Launch the validated 20260417_w2 dataset\n\nThe repository includes a ready-to-use launcher for the local validation\ndataset:\n\n```text\npixi run launch-actual\n```\n\nIt memory-maps `volumes.npy`, `neuron_mask.npy`, and\n`neuron_point_tuple.npy`, opens napari, docks the navigator, and loads all\n138 ROI identities automatically.\n\n## ROI input format\n\nThe ROI loader accepts a numeric NumPy array with shape:\n\n```text\n(T, N, K), K >= 6\n```\n\nThe first six fields are:\n\n```text\nx_center, y_center, z_scaled, width, height, depth_scaled\n```\n\nAdditional fields are ignored. The neuron ID is the index on the `N` axis:\n\n```text\nneuron_id = 0 ... N - 1\nlabel_value = neuron_id + 1\nbackground label_value = 0\n```\n\nNaN, infinite values, non-positive sizes, and time points outside the source\narray are treated as missing observations. Missing neurons remain in the\ncheckable list so that their global identity is stable, but Q/W skips them at\nthe current time point.\n\n### Coordinate and time mapping\n\nThe plugin assumes the controlled Labels layer has one of these axis orders:\n\n```text\n(z, y, x)\n(t, z, y, x)\n```\n\n`z_divisor`, defaulting to 5, converts source z and depth coordinates:\n\n```text\nz_index = z_scaled / z_divisor\ndepth_in_slices = depth_scaled / z_divisor\n```\n\nFor a viewer that displays a cropped or strided time range:\n\n```text\nsource_t = volume_start + viewer_t * volume_stride\n```\n\nConfigure `volume_start` and `volume_stride` before loading the NPY.\n\nThe derived ROI overlay layers copy scale, translation, axis labels, and\nunits from the controlled Labels layer. Do not apply the z scale a second\ntime in the ROI coordinates.\n\n## 2D and 3D box display\n\nTwo managed Vectors layers are created after loading an ROI file:\n\n- `Neuron boxes – selected`: checked, currently valid boxes at low opacity;\n- `Neuron box – active`: the active box with a thick yellow outline.\n\nInitially only the first valid neuron is checked and active. **All** includes\nall IDs in the selected layer, while **None** empties both box layers and the\noptional text overlay. Checked identities that are missing at the current time\nremain checked but are temporarily omitted from the geometry.\n\nEnable **Show selected box labels** to place one text label at the center of\neach currently rendered checked box. The text uses the annotation table's\n`biological` value when present and otherwise falls back to the zero-based\n`neuron_id`. The third `annotation` column is not used for box labels. The\noption is off by default. Use **Text color** to choose a session-only label\ncolor that contrasts with the current Image colormap.\n\nIn 2D mode, the plugin draws four rectangle edges only when the current z\nslice intersects the box's half-open z range.\n\nIn 3D mode, each box is represented by 12 vector edges. Overlapping boxes\nremain independent vector records with a `neuron_id` feature. They may overlap\nvisually, but one box does not erase the identity of another.\n\nVectors and the transparent Points text layer are derived display data. They\nare removed when the ROI is unloaded or the widget closes and are not saved\nas a separate annotation format.\n\n## Annotation\n\nIn ROI mode, the `digital` column always stores the zero-based `neuron_id`.\nIn Labels-only mode, it stores the raw Labels value.\n\nThe table automatically follows the current identities. Existing biological\nnames and annotation text are preserved by identity when the source changes.\nActivating a neuron selects its annotation row. Selecting a table row checks\nand activates the corresponding neuron without clearing other checked IDs.\nThe `biological` value is also displayed in the neuron list.\n\nThe complete navigator is vertically scrollable when the napari dock is\nshorter than its controls.\n\nExcel operations support `.xlsx` workbooks. Saving and loading do not apply an\nimplicit `+1` or `-1` conversion.\n\n## Development\n\nRun tests and lint from the repository root:\n\n```text\npixi run pytest -q\npixi run -e excel pytest -q\npixi run ruff check .\n```\n\nThe repository uses a `src` layout. Pure ROI parsing and geometry live in\n`src/napari_worm_neuron_annotator/_roi.py`; Qt and napari lifecycle behavior\nlive in `src/napari_worm_neuron_annotator/_widget.py`.\n\n## License\n\nDistributed under the BSD-3-Clause license.\n","description_content_type":"text/markdown","keywords":null,"home_page":null,"download_url":null,"author":"JH Wang","author_email":"wjh19937458882@mail.ustc.edu.cn","maintainer":null,"maintainer_email":null,"license":null,"classifier":["Development Status :: 2 - Pre-Alpha","Framework :: napari","Intended Audience :: Developers","Operating System :: OS Independent","Programming Language :: Python","Programming Language :: Python :: 3","Programming Language :: Python :: 3 :: Only","Programming Language :: Python :: 3.11","Programming Language :: Python :: 3.12","Programming Language :: Python :: 3.13","Programming Language :: Python :: 3.14","Topic :: Scientific/Engineering :: Image Processing"],"requires_dist":["napari<0.9,>=0.8","numpy","qtpy","napari[all]<0.9,>=0.8; extra == \"all\"","openpyxl>=3.1; extra == \"excel\"","tox; extra == \"testing\"","pytest; extra == \"testing\"","pytest-cov; extra == \"testing\"","pytest-qt; extra == \"testing\"","napari[pyqt6]<0.9,>=0.8; extra == \"testing\""],"requires_python":"<3.15,>=3.11","requires_external":null,"project_url":["Bug Tracker, https://github.com/Wenlab/napari-worm-neuron-annotator/issues","Documentation, https://github.com/Wenlab/napari-worm-neuron-annotator#README.md","Source Code, https://github.com/Wenlab/napari-worm-neuron-annotator","User Support, https://github.com/Wenlab/napari-worm-neuron-annotator/issues"],"provides_extra":["all","excel","testing"],"provides_dist":null,"obsoletes_dist":null},"npe1_shim":false}