---
# System prepended metadata

title: Hackathon Working Group Notes

---

# Hackathon Working Group Notes

## Sunday

Missing toolboxes (Juan/Guillaume/Draga/Tim)
Intro to GitHub/napari/etc. (Melissa/Zuzanna/Rensu)
Layer refactoring (Lorenzo/Yohsuke/Carlos)

Tim/Aroj?
Rensu/Grzegorz
    
### Missing toolboxes

- Currently scale is displayed in the status bar by integer, would like to be able to display a scaled float as you pan around the image
    - GW: did that in a plugin already
    - JNI: xarray dataset where timescale is in nanoseconds but the scale is days, so you have like 10b, 11b etc. Want the status to be a smart thing that depends on the separation between adjacent timepoints. Not thinking slider values atm, but just the non-displayed dimension in the status bar.
    - Idea: right click on slider value and change between pixel-scale and data-scale. Easy to do as a separate item. ACTION: open issue
- Histogram:
    - not a small lift.
    - Difficulty: if you change layer, you need a histogram to change with it
    - Draga: Tim kinda did it, by attaching it to contrast limits
    - where is Tim's histogram code??
        - currently on contrast limits, and also a separate collapsible thing under the contrast limits
        - Tim has three separate branches on his home machine which he will push tonight
        - log-scaled histogram very important for sparse data
        - Tim will open PR tomorrow in napari
- Metadata viewer:
    - there's already a plugin built by Andy. We could play with it and see how it's working and build it up. It's on the plugin side, not so much core
    - install plugin, see if it works
    - It works!
    - Needs to be more types for axes
        - pint set of dimensions
        - not used, but displayed, and editable
        - pint can fill in the type of the dimension based on the unit
    - Space units/time units: should use pint units
    - Plugin -> Should be called 'Source' as in viewer
    - Needs affine and rotate
    - Needs to be migrated to pyproject.toml

### Units

- Does a layer inherit missing metadata properties from existing layers in the viewer, upon being added?
    - GW: Fiji doesn't really have that problem because you have a window for each image, so they don't overlay. Assuming the same units is fine in 99% of the cases. Now with correlative microscopy?
    - JNI: what we hope is that then you'd have the right metadata
    - Always want to give users a way to do it without the magic (Juan thinks it should be based on active layer)

### Ideas

- (After coffe break Sunday) Architecture overview
    - RECORDING
- Juan: has a message somewhere about what happens when you slice a layer. Should turn that into a docs page
    - He found it, he's going to turn it into a docs page
- Issue about new labels layer showing 0 but colour being 1

## Architecture Overview

- Vispy accepts a numpy array, passes it to OpenGL, and renders it
- Renderer (Vispy), GUI (Qt), BaseModels (Layer, Camera).


## Layer refactoring

- Sunday: fighting with environments, finally got it working
- Monday: pairing with Grzegorz because he's going to push forward the existing draft PR #8254


## Sunday Summary

- Rensu PR to docs!
- Architecture/slicing overview
- Reviewing a PR live
- Intro to GitHub

## Monday Summary

- Zuzana first PR!
    - AND second PR, almost merged!
- 1:15pm - plugin intro. Recorded.
- Idea: "highlight selected" label option rather than just "show selected"
    - feature-based label coloring is a core visualization need
    - won't support coloring labels that are not in the features table
        - general complication of the labels, because we don't know the number of segments
- Draga & Lorenzo on readers:
    - Readers receive a list of paths when the user chooses the "Open Files as Stack..." option. There is an implicit contract that receiving a list means you should stack. This is not documented, advertised, or really enforced. Plugins should be able to declare four different bools in the reader contribution in the manifest: `accepts_single_path`, `accepts_directories`, `accepts_multiple_paths`, and `accepts_stackable_paths`(?). These are already selections the user can make, so this would just be updating the plugin's available options to match, and to make the contract explicit.
    - Need to update plugin template to use memmap on numpy in reader to check dtype as our get_reader
        - Done, just need to push a few commits
- Plugin template improvements!
    - exposing the prompts doc
    - moving tests outside of src, ensuring they're in sdist
    - modernizing build workflow
- Tim citation PR
- Juan/Guillaume & tiling
    - Juan: improving status bar coordinates with scaled coordinates. We currently show integers which means you're not getting detailed info when mousing around. Didn't get very far.
    - Currently take numpy array -> texture -> display in openGL: very nice and smooth.
    - But there's a texture limit that depends on your graphics card, so if your data is slightly too big, we downscale, which is sad
    - Instead, we should make multiple textures, tiled automatically, so that we only ever send a single texture
    - Lots of complicated stuff that doesn't seem to work correctly. There's some vispy weirdness in that the scene graph (grouping visuals together) allows stuff to move together, but the compound visual, which should give a lot of convenience, transforms each individual visual to the same value, which is not what you want.
    - feels finishable, but tricky with the transforms, which Lorenzo implemented so he should be able to help
    - Will keep pushing on it
- Yohsuke
    - replacing selecting a single label with the ability to select multiple labels, using a `Selection` object, where the selected label is the active object of the `Selection`. First PR is nothing actually changes, purely a refactor. Eventually, if you select multiple labels, you could "show selected" and it shows them all. Haven't talked about what that would look like for the spinbox.
        - Spinbox should always be active label? Active is None if multiple are selected though... Should be the latest thing you clicked on
        - this is a precursor to the highlighting mutliple labels option
- Layer refactors: Grzegorz needed to finish up and solve some problems in the PR setting up the initial stage.
    - private API is using untyped part of the codebase so it's hard to figure out where it's being used
    - not sure whether to finish blog post about performance improvements?
    - should keep hacking on layers, check if there's something to be done for napari-tiff release?
        - just ship it, says Juan and Tim, with improved metadata reading
    - opened PR to check if a PR author is present in citation.cff, opinion about how it should work?
- Melissa:
    - linting the entire docs repo with a myst-markdown linter
    - will help with docs contributions when you don't want to build the docs, but will still catch tiny things and syntax errors before submitting PRs
    - survey data analysis notebook almost ready in a draft. There will need to be some manual adjustments because the surveys aren't the same every year, but at least there's a template
    - conversation to be had: bunch of people in the room who use the docs regularly, and would like to get a feeling for what people feel about the **organization** of the docs. What's getting in the way of people doing their work
- Rensu:
    - building docs with pixi is now platform agnostic! Will be documenting how to use it, and potentially starting on a new plugin!
- Tim:
    - inertia? folks are mostly in favour. Think it should be off by default but enableable and the amount of inertia configurable, because it could be an accessibility issue (in each direction).
    - involves creating a queue of events, so we'll need some careful management of this
- Mehdi:
    - joining us today. At HT in Milan
    - Two plugins: [FeatureForest](https://github.com/juglab/featureforest) and [CAREamics-ui](https://github.com/CAREamics/careamics-ui)!
    - Question: how can the layer toolbar be customized
        - connect to the mode change event and modify it back
        - disablable? 
        - how hard can it be to make a button disablable?
    - New contribution ideas:
        - new layer types, new layer controls, declarative
    - basic tools like cropping tools, histogram, extracting images out of stack

Tuesday

- Draga: npe2 reader + fix CI + improve reader example
- Zuzana: new PR merged!
- Cropping?
- Tiling
    - current state: new type of vispy node to handle tiled data. napari can now handle bigger than opengl stuff
    - still need to ensure updates get passed to the correct place
    - fix is probably not straightforward
    - once this is fixed, should not be too far
    - next step is a PR which Guillaume will open
        - WIP PR should be open so that it's out there, regardless of the current fix
    - does this change anything about 3D?
        - no. same behaviour as usual
        - applying to 3D is the next step
- Rensu
    - refactoring docs contributing docs, PR is open
    - extensive, so check it thoroughly!
- Zuzana
    - updated tests for second PR, which is now merged!
    - Worked on converting points to labels, getting inspo from shapes where it's implemented already
    - reported issue with shapes ordering
    - played with the inertia thing
    - looking to join community meetings
- Aroj
    - worked on his own plugin, now have a draft of it!
    - demoed!!
    - gallery example!
- Tim
    - bunch of reviewing
    - fixed the inertia issue, think we're not handling the difference in angles correctly
    - please pull down the inertia thing and see if it behaves like you'd expect
    - seems harder to active for rotation in 3d than would be expected
    - panning is on the buttery side, but should mean you feel it
    - rest of the week will push on histogram
- Melissa
    - finished linting docs repo
    - working on survey notebook
    - pandas trouble :<
    - data is different format to previous years
    - light reviewing and guiding folks
- Lorenzo: reviewing layer refactoring and floating around critically
- Grzegorz:
    - struggling with saving units in napari-tiff
    - working to read and write units and axis names to/from file
    - layer refactoring: ready to merge soon, benchmarks passing finally
        - should make subsequent PRs a lot easier
        - #8254
        - will require playing with napari to make sure it's not exploding anywhere
        - removing slicing functions from all layers except shapes
        - no expected performance changes
        - should be indistinguishable to main
- Yohsuke
    - running around a lot
    - working on multiple selection 
    - need to make WIP PR and discuss, help fix tests etc.
- Carlos
    - working on the napari-metadata plugin
    - bit of a mess
    - was writing metadata into a weird place in the metadata key
    - destroyed everything using the weird classes, gutted it down
    - basically same functionality but now it's making fewer assumptions and the code is cleaner
    - cleaning up code because of comments, etc.
    - setting axis labels, units, scales
    - pretty useful now
    - building up the GUI again after destroying stuff
    - PR soon!
- Mehdi
    - good first issues, exploring the code
    - will need to put more time
    - remembered that for feature forest plugin, there's a few things that can be proposed as features to label layer e.g. adding class name for annotation instead of just the number
        - background class could be a checkbox to be hidden so it's not visualized. This is for when background is also being annotated. 
- Plugin template

Wednesday
- Group photo!
- Survey
- After standup: docs org discussion
    - mirroring the top bar on the side bar, similarly to how you have the section guide within individual sections, on home page?
    - many folks don't use the docs at all (only core team and Guillaume do it)
    - "I just click on buttons until it works"
    - "Go to source code because I come to the website and it's a little lacking"
        - getters and setters for dimensions etc. What types it's expecting and how to access them
        - most of the stuff is in the API reference, but when I've followed what was hinted in the typing of the API reference, there are some types that are missing
        - not that common
        - LG: never reach for this. I'll always look in the source code over the API reference
        - TM: API reference never made sense to me. Ultimately the way I interact is by trying to understand e.g. viewer.add_image, but this just documents the class
        - JNI: hardly anyone uses the layer objects but they're at the top
        - How do we organize our API docs so the most used stuff is at the top?
            - manually organize rather than relying on the autogenerated structure
            - stuff will have to move "as a whole", while our e.g. utils might fit under separate manual org, so maybe we actually need to organize **the code** better, so that the docs make sense
            - e.g. pull out Affine stuff into their own module
    - "Developer API": viewer.components.camera is developer-facing, while viewer.camera is user-facing
        - for some data structures, some attributes are more developer than user focused
        - "API reference feels like I'm opening internal stuff not user stuff"
        - "API reference feels almost accidental"
    - Link to the relevant API docs from the usage docs
        - adding more links from the narrative usage docs to the API reference
        - from the examples and gallery it works if you click within a code snippet - this would also be nice
    - within an individual class in the API reference, the right-hand sidebar is empty, but it **should** be listing methods of the class so you can navigate easily
        - hmm it appears when you scroll down...?
    - duplicate descriptions of objects are creating warnings and errors when making autosummary because "same object is described twice"
        - no way to ignore that error wholesale, have to filter it based on warning message, and it's language specific
    - API reference visuals
        - the parameter listing within the brackets is hard to parse
        - the HTML generated by sphinx is what needs changing
        - numpy ones look ok, but maybe it's just a matter of too many?
        - the parameter listing - the description should be on separate line and indented after the typing
        - dark mode contrast on the parameter listing needs fixing
    - GW: mostly using docs when doing training to check installation etc.
        - getting started is fine, now I want to annotate stuff
        - entry-level annotation is "Annotating videos with napari" but that's horrible
        - from a user perspective, there should be a simpler example
        - "beginner user isn't going to know that using the labels layer is for annotation because they don't know what the labels is"
        - Using etc.
            - should be "Displaying images", "working with masks/annotations", etc.
        - who can design a better sidebar progression?
            - hard to develop a "path" via the sidebar e.g. like the numpy one, because there's so many different usages
            - although there's lots of different paths, our workshops are always following the same "beginning" path, so maybe this should be our starting path, before we branch off into everything
    - TIM: look over Guillaume's workshops
    - Getting started
        - What is quick start if it doesn't include all the other things listed in that section?
            - maybe should be overview?
        - viewer tutorial is kinda buried here, under four different other items
            - "I'm surprised that viewer tutorial which is a dense piece of information is buried in the middle of launch, install, etc."
            - viewer tutorial should be top-level on the sidebar
        - feature highlights is a strange thing, I would never click on it - need better name?
    - user space vs. developer space
        - spoken previously about via GUI vs. via code side-by-side
            - not going to be one-to-one
        - separating is tricky because of the duplication
        - should be more obvious in each page whether you're following "by code" or "by GUI" path
    - googling napari docs gives you some random organization doc
        - this is SEO issue
        - we can request to pull in latest docs
        - if it's top link, people keep linking it
    - how-to guides
        - really like the guides for layers, but what the user expects here is more task-specific/application-specific stuff, rather than "using points layer"
        - advanced stuff is in the same level as the headers
    - bit difficult to reach the other external tutorials
    - nothing about opening images and specific formats, bad ways to do things, good ways to do things, what is reading even?
    - getting to community stuff
        - can't get at a glance info from the community page
        - often scroll through to footer 

### Notes on implementing crop

- Use a SelectionBox overlay ([components/overlays/interaction_box.py]( https://github.com/napari/napari/blob/2f5c1641563c1aa0acebd573fcbce80203050d61/src/napari/components/overlays/interaction_box.py#L8))
- Add it as a new overlay in the base layer called 'crop_box' [in layers/base/base.py](https://github.com/napari/napari/blob/8702decd7ba64c2df48f6f4ac56bb47e5e6973c3/src/napari/layers/base/base.py#L491)
- Example for custom usage in [examples/dev/controllable_overlay.py](https://github.com/napari/napari/blob/f824d597942dcb62c5ebc099cd9ca202adcc48a1/examples/dev/controllable_overlay.py#L2) including interaction
- add interactivity in [base layer mouse bindings]( https://github.com/napari/napari/blob/2f5c1641563c1aa0acebd573fcbce80203050d61/src/napari/layers/base/_base_mouse_bindings.py#L21)
- [get_nearby_handle](https://github.com/napari/napari/blob/f824d597942dcb62c5ebc099cd9ca202adcc48a1/src/napari/layers/utils/interaction_box.py#L124) works in data coordinates!  (look for usages e.g. [base mouse bindings](https://github.com/napari/napari/blob/2f5c1641563c1aa0acebd573fcbce80203050d61/src/napari/layers/base/_base_mouse_bindings.py#L33))
- we need to make two functions:
  - make the crop box visible
  - given a layer that has a crop box, crop that layer, producing a new layer (and probably, hide the crop box)
- we need to make corresponding actions. See e.g. [this function in qactions/_layerlist_context]( https://github.com/napari/napari/blob/d43bf0546388f40d4223c10cd922b43b6e185e5d/src/napari/_qt/_qapp_model/qactions/_layerlist_context.py#L78) which is made into an action [later in that file]( https://github.com/napari/napari/blob/d43bf0546388f40d4223c10cd922b43b6e185e5d/src/napari/_qt/_qapp_model/qactions/_layerlist_context.py#L210)
- but we should put them [in the layer_actions file](https://github.com/napari/napari/blob/2f5c1641563c1aa0acebd573fcbce80203050d61/src/napari/_qt/_qapp_model/qactions/_layers_actions.py#L1), adjacent to that one and currently containing no actions.

## New contributor PRs:

- Rensu docs
- Zuzana napari/napari
- Yohsuke plugin-template
- Carlos napari-metadata

## Other

- logos!

## Issue on plugin path bools

Currently, plugin readers get given either a single file path, a directory path or a list of paths, based on the following user choices:

- `File -> Open File(s)`: when user selects single path, plugin gets given a single file path
- `File -> Open File(s)`: when user selects multiple paths, plugin gets given each path individually
- `File -> Open Folder`: plugin gets given directory path, **if and only if** `accepts_directories: True`
- `File -> Open Files as Stack`: plugin gets given a list of paths

Historically, the implication was that a plugin receiving a **list** of paths should open all the paths and **stack** them. This implication is poorly documented, and plugins have no option to declare whether or not they are even happy or capable of stacking a list of files. Furthermore, there are instances where a plugin may want to receive a list of files and **not** stack them, but rather combine information from them in some other way to produce the desired napari layers. Currently, there is no way for the plugin developer to ensure they are given the full list of selected paths, unless the  user selects `Open Files as Stack`, which could lead to unexpected behaviour for both the plugin developer and the user.

At the GloBIAS hackathon, we discussed expanding the reader contribution to allow plugin developers to be more explicit about what path input types they support, and to allow for a one-to-one mapping between the user's choices and the path(s) received by the plugin.

Our proposal is to extend the manifest