diff --git a/docs/index.rst b/docs/index.rst index 37a8ec619d..ed12341c45 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,7 +6,7 @@ Neuroglancer :hidden: :caption: User Guide - user-guide/navigation + user-guide/index .. toctree:: :hidden: diff --git a/docs/user-guide/annotation_shaders.rst b/docs/user-guide/annotation_shaders.rst new file mode 100644 index 0000000000..a92421aa59 --- /dev/null +++ b/docs/user-guide/annotation_shaders.rst @@ -0,0 +1,287 @@ +Annotation Shaders +------------------ +As with other elements of neuroglancer, one can write custom +GLSL code to control the way annotations are rendered on the +screen. Technical documentation about how to set control +different aspects of the annotations +`Can be found here `_. + +This guide is a more gentle introduction to GLSL that will +guide you through developing your first annotation shader code, +so that properties of annotations can adjust their visual appearance. + +Many of the lessons applied here also are relevant to shaders on image layers +or segmentation layers, but this will stay focused on annotation shaders. + +Color +~~~~~ +The first and most obvious thing to change about an annotation is its +color. Colors can either be defined by red, green, blue (RGB) values, +or red, green, blue, alpha (RGBA) values, if you want annotations to be +transparent. In GLSL, RGB colors are defined by a ``vec3`` variable type +and RGBA colors are ``vec4``. Calling ``setColor`` with either a ``vec3`` +or ``vec4`` will set the color. + +You can see this in the default shader that comes with any new annotation +layer + +.. code-block:: glsl + + void main() { + setColor(defaultColor()); + } + +Here, ``defaultColor()`` is a function which returns the ``vec3`` RGB color +that is the ``Annotation color`` UI control just below the shader code. +Clicking on the UI control will bring up an RGB picker that will allow you +to change the color returned by ``defaultColor()``. + +You can add more color pickers to the set of UI controls with a ``#uicontrol`` +directive, optionally give it a default value, and pass it to set color. + +.. code-block:: glsl + + #uicontrol vec3 mycolor color(default="red") + void main() { + setColor(mycolor); + } + +There are more ``#uicontrol`` types, such as ``slider``. Let's add a ``slider`` to +control the red channel of a color. To create a new ``vec3`` value, +we declare it with the type, name, and an initializer. + +.. code-block:: glsl + + #uicontrol float red slider(min=0.0, max=1.0, step=0.05, default=1.0) + void main() { + vec3 mycolor = vec3(red, 0.0, 0.0); + setColor(mycolor); + } + +Data mapping +~~~~~~~~~~~~ + +More powerfully, we might want to take some data from an annotation +property and use it to drive the red channel. However to do so, +we often want to remap the values of that property to a ``0-1`` range. +Say our annotation has a property called ``temperature`` and it ranges +from 0 to 1000 across the annotations, but most annotations are +around 10-30. The ``invlerp`` control (short for **inverse linear +interpolation**) will help us do that. + +.. code-block:: glsl + + #uicontrol float red invlerp(range=[10,30], window=[0,1000]) + void main() { + vec3 mycolor = vec3(red(), 0.0, 0.0); + setColor(mycolor); + } + +Now in the UI you will see a widget appear that has a dropdown menu +to select which property you want to remap. The ``range`` parameter +sets the min and max data values of the linear remap: values above the +max are clamped to 1, and values below the min are clamped to 0. +``window`` sets what range of values the widget shows you when adjusting +``range``. You can omit ``window``, which defaults to the same interval +as ``range``, and you can omit ``range``, in which case neuroglancer +will pick a reasonable default from the current distribution of the +selected property. Both can be adjusted from the widget at any time. + +These basic elements can be combined to create many kinds of coloring +behaviors. For example, let's say we want a single-color colormap +that ramps from black to a user-selectable color as an annotation +property goes from low to high. + +.. code-block:: glsl + + #uicontrol float intensity invlerp(range=[10,30], window=[0,1000]) + #uicontrol vec3 mycolor color(default="red") + void main() { + setColor(intensity()*mycolor); + } + +I can simply scale the ``mycolor`` ``vec3`` by my remapped intensity +invlerp control that will be between 0 and 1. Users can now +change the colormap and set what 'bright' looks like. + +What about discrete variables, like categories, where continuous +changes don't make sense? We can set up a lookup table that maps +each discrete code to a specific color. The natural way to express +this in GLSL is a constant array indexed by the code. + +Let's say we had a categorical property called ``category`` whose +values are codes ``0``, ``1``, or ``2``. (Categorical / dictionary-encoded +annotation properties surface in the shader as a ``uint`` code — the index +into the property's ``categories`` array — so we use ``uint`` for the +lookup index.) Declare a ``const vec3`` array with one row per code, +index it by the code, and fall back to ``defaultColor()`` for +out-of-range values: + +.. code-block:: glsl + + const vec3 categoryColors[3] = vec3[3]( + vec3(1.0, 0.0, 0.0), // 0: red + vec3(0.0, 1.0, 0.0), // 1: green + vec3(0.0, 0.0, 1.0) // 2: blue + ); + + void main() { + uint code = prop_category(); + vec3 rgb = (code < 3u) ? categoryColors[code] : defaultColor(); + setColor(rgb); + } + +A few things to notice: + +- ``const vec3 array[N] = vec3[N](...)`` is the GLSL syntax for a + compile-time-constant array. The size ``N`` appears in both the + declaration and the constructor and must match. +- Array indices must be non-negative integers, so ``code`` is a ``uint`` + and the bounds check uses ``3u`` (a ``uint`` literal). Comparing + ``uint`` to ``int`` is not allowed. +- The fallback to ``defaultColor()`` handles unexpected codes safely — + without it, reading past the array end is undefined. +- This pattern scales naturally to dozens or hundreds of categories + (e.g. cell-type taxonomies). Lining up the row comment with the + corresponding entry in the property's on-disk ``categories`` array + makes the mapping easy to audit. + +Lines and Polylines have colors for their lines, points and endpoints. +``setLineColor`` can be called with 1 color, or with 2, if you want the +color to vary across the line. ``setEndPointMarkerColor`` similarly can +be called with 1 color to mark both ends the same, or 2 colors to +make the start and endpoint colors different. You can read more +about the details of these in the +`rendering guide `_ + + +Size +~~~~ +The next obvious thing to modulate beside color is the size of annotations. +Annotations have different things to size. Points have ``setPointMarkerSize`` +which will dynamically scale annotations. All the same things that we +learned about ``#uicontrol`` apply here. So if we wanted our point +annotations to scale between 1 and 20 pixels based on a property, +we might use the ``invlerp`` control again. + +.. code-block:: glsl + + #uicontrol float intensity invlerp(range=[10,30], window=[0,1000]) + void main() { + setColor(defaultColor()); + setPointMarkerSize(1.0 + 19.0*intensity()); + } + +We could control the maximum size with a slider to give the user even more +control. + +.. code-block:: glsl + + #uicontrol float intensity invlerp(range=[10,30], window=[0,1000]) + #uicontrol float maxsize slider(min=1.0, max=50.0, step=1.0) + void main() { + setColor(defaultColor()); + setPointMarkerSize(1.0 + (maxsize-1.0)*intensity()); + } + +The ``1.0 +`` and ``(maxsize - 1.0)`` here mean that our points never +disappear, no matter how small the slider goes. + + +Toggles +~~~~~~~ + +To switch a visual feature on and off, use a ``checkbox`` uicontrol. + +The name of the UI control will be available to the shader as a +boolean binary variable. We can use this to +toggle some aspect of our visualization on and off, such as making +the bordrs of point annotations visible or invisible in the +example below. + +.. code-block:: glsl + + #uicontrol bool showBorders checkbox(default=true) + + void main() { + setColor(defaultColor()); + setPointMarkerSize(8.0); + if (showBorders) { + setPointMarkerBorderColor(vec4(0.0, 0.0, 0.0, 1.0)); + setPointMarkerBorderWidth(1.0); + } + else { + setPointMarkerBorderWidth(0.0); + } + } + + + +Discard +~~~~~~~ +As the number of annotation points you want to render gets higher and +higher, the performance of rendering will go down. The controls will +start to feel sluggish, and your page might crash if the GPU gets +overwhelmed. + +One way to address this is to use the data itself to render only the +subset of points you are interested in. Inside ``main()``, the +``discard`` keyword drops the current annotation entirely — no +geometry is drawn for it. + +.. code-block:: glsl + + void main() { + if (prop_quality() < 0.5) { + discard; + } else { + setColor(defaultColor()); + } + } + +To let the user adjust the cutoff interactively, drive it from a +slider: + +.. code-block:: glsl + + #uicontrol float minQuality slider(min=0.0, max=1.0, step=0.01, default=0.5) + void main() { + if (prop_quality() < minQuality) discard; + setColor(defaultColor()); + } + +For a categorical property, compare against the code directly. To show +only annotations belonging to a single category, pair a ``uint`` +slider with an equality check: + +.. code-block:: glsl + + #uicontrol uint onlyCategory slider(min=0, max=2, default=0) + void main() { + if (prop_category() != onlyCategory) discard; + setColor(defaultColor()); + } + +Combine a ``checkbox`` with a discard to make a filter optional — +when the checkbox is off, all the annotations of a particular +category are dropped. + +.. code-block:: glsl + + #uicontrol bool hideCategoryTwo checkbox(default=false) + void main() { + if (hideCategoryTwo && prop_category() == 2u) discard; + setColor(defaultColor()); + } + +Multiple discards can be stacked — the annotation is dropped if +*any* condition matches: + +.. code-block:: glsl + + #uicontrol float minQuality slider(min=0.0, max=1.0, default=0.5) + void main() { + if (prop_quality() < minQuality) discard; + if (prop_category() == 2u) discard; + setColor(defaultColor()); + } diff --git a/docs/user-guide/annotations.rst b/docs/user-guide/annotations.rst new file mode 100644 index 0000000000..8aa78a6e12 --- /dev/null +++ b/docs/user-guide/annotations.rst @@ -0,0 +1,456 @@ +.. _annotation-layers: + +Annotation Layers +================= + +Annotation layers let you place geometric markers — points, lines, +bounding boxes, ellipsoids, and polylines — on top of any other data +displayed in the viewer. Local annotations are stored as part of the +viewer state and can be linked to segmentation layers so that each +annotation records the IDs of the segments it touches. Remote +annotations can stream from data locations outside of neuroglancer, +but this guide will focus on local annotations. + +.. _creating-an-annotation-layer: + +Creating a local annotation layer +--------------------------------- + +To create a new annotation layer: + +1. :si-icon:`material/mouse-left-click-outline` Click the + :guilabel:`+` button at the right end of the layer bar at the top + of the viewer. + +2. In the layer type picker, choose :guilabel:`annotation` (abbreviated + ``ann``). Then type local://annotations as the source to make a + local annotation layer. + +shortcut: ctrl+click :si-icon:`material/mouse-left-click-outline` the +'+' button to make a new annotation layer immediately. + +3. A new, empty local annotation layer is added to the layer bar and + its side panel opens. + +.. _annotations-tab: + +The Annotations tab +------------------- + +Selecting an annotation layer opens its side panel. Within the side +panel, select the :guilabel:`Annotations` tab. This tab contains: + +- A row of tool buttons for placing new annotations (see + :ref:`annotation-tools` below). +- A list of all annotations in the layer. + :si-icon:`material/mouse-right-click-outline` an entry in this list + selects that annotation and moves the view to its position. + + +the :guilabel:`Rendering tab` for controls related to how annotations +are drawn, including: +- Controls for the annotation layer's color. +- The annotation shader code, which can control how annotations are +rendered. + +.. _annotation-tools: + +Annotation tools +---------------- + +The :guilabel:`Annotations` tab provides one button per annotation +type. :si-icon:`material/mouse-left-click-outline` Click a tool button to activate that tool for the layer. With +the tool active, you place points by holding :kbd:`Ctrl` + +:si-icon:`material/mouse-left-click-outline` left-clicking in +**either a 2-D cross-section view or the 3-D projection view** — both +work for every annotation tool. The point is placed at the location +under the mouse cursor in whichever view you click. + +Each tool interprets your :kbd:`Ctrl` +:si-icon:`material/mouse-left-click-outline` left-clicks as follows: + +:guilabel:`Annotate point` + A single :kbd:`Ctrl` + :si-icon:`material/mouse-left-click-outline` left-click places a + point at the cursor and finishes the annotation. Each subsequent + click starts a new point annotation. + +:guilabel:`Annotate line` + - **First** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: places the start + endpoint of the line. + - **Second** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: places the end + endpoint of the line and finishes the annotation. + +:guilabel:`Annotate bounding box` + - **First** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: places one corner + of the axis-aligned bounding box. + - **Second** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: places the + opposite corner and finishes the annotation. The box is drawn + axis-aligned in the annotation coordinate space between the two + corner points. + +:guilabel:`Annotate ellipsoid` + - **First** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: places the + **center** of the axis-aligned ellipsoid. + - **Second** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: sets the + ellipsoid's radii. The radius along each axis is taken from the + absolute distance between the center and the second click along + that axis, so clicking farther from the center produces a larger + ellipsoid. The second click also finishes the annotation. + +:guilabel:`Annotate polyline` + - **First** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: places the first + vertex of the polyline. + - **Each subsequent** :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline`: appends another + vertex, extending the polyline by one segment. + - **Finishing:** hit enter to end the polyline. See + :ref:`working-with-polylines` for details and how to undo the + last vertex. + +All clicks use the same :kbd:`Ctrl` + +:si-icon:`material/mouse-left-click-outline` left-click binding +regardless of whether you are clicking in a 2-D or 3-D view. +Neuroglancer will use the same picking scheme that the right click +tool uses when moving. + +Note, you can still :si-icon:`material/mouse-right-click-outline` +right click to move around, or +:si-icon:`material/mouse-left-click-outline` drag/scroll through +the dataset to find the place where you want to annotate. + +.. _working-with-polylines: + +Working with polylines +---------------------- + +The polyline tool builds up an annotation one point at a time. To +finish a polyline, hit :kbd:`Enter` or **click the last point a second +time** — that is, place a new point at the exact location of the +previous one. Neuroglancer treats two consecutive points at the same +position as the end of the polyline. + +To remove the most recently added point of an in-progress annotation +(useful if you misclicked a vertex of a polyline, line, box, or +ellipsoid), press :kbd:`Backspace`. + +.. _selecting-annotations: + +Selecting an annotation +----------------------- + +To select an existing annotation: + +- **In a data view (2-D or 3-D):** hover over the annotation and press + :kbd:`Ctrl` + :si-icon:`material/mouse-right-click-outline` + right-click. The annotation is selected and its details appear in + the selection panel. +- **In the annotation list:** + :si-icon:`material/mouse-left-click-outline` left-click an entry in + the list inside the :guilabel:`Annotations` tab. The annotation is + pinned in the selection panel and the view recenters on it. +- **Jump to an annotation without selecting it:** + :si-icon:`material/mouse-right-click-outline` right-click an entry + in the annotation list. The view moves directly to that + annotation's location without changing the current pinned + selection. + +.. _deleting-annotations: + +Deleting an annotation +---------------------- + +There are three ways to delete an annotation: + +- **From a data view:** hover over the annotation and press + :kbd:`Ctrl` + :kbd:`Alt` + + :si-icon:`material/mouse-right-click-outline` right-click. +- **From the annotation list:** hover over the annotation's entry in + the list and click the trash-can icon that appears. +- **From the selection panel:** select the annotation (:kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline` left-click) so its + details open in the selection panel, then click the trash-can icon + in the selection widget. + + +.. _moving-annotation-points: + +Moving annotation points +------------------------ + +Individual points and vertices of existing annotations can be moved +by holding :kbd:`Alt` + :si-icon:`material/mouse-left-click-outline` +left-click-dragging on the point. This works for the endpoints of a +line, the corners of a bounding box, the center and radius handles of +an ellipsoid, and any vertex of a polyline. + +If you do the same :kbd:`Alt` + +:si-icon:`material/mouse-left-click-outline` left-click-dragging on +the lines of an annotation you will move the entire annotation +instead of just a single point. This is useful for repositioning an +annotation without changing its shape. Also, this works in 3d, but +moves points in the plane parallel to the screen, witout changing the +points depth relative to the camera. You may need to move a point +rotate 90 degrees, and then move the point again to get it close to +what where you watn to be. + +Note, shift + :si-icon:`material/mouse-left-click-outline` +left-click-dragging on an annotation point in the 2D view will rotate +the plane of that 2D view to make for an "off-axis" cut of the data. +This can be disorienting, if you don't know what is happening. In +anisotropic data, this can lead to 'striping' patterns in the +rendering, where different slices of lower resolution, data occupy +different regions of the screen. To 'snap' the plane back to the +nearest axis-aligned orientation, hit the :kbd:`Z` shortcut. + +If you use the same :kbd:`Alt` + +:si-icon:`material/mouse-left-click-outline` left-click-dragging in +the annotation list, you can reorder the annotations in the list. + + +.. _reordering-annotations: + +Reordering annotations in the list +---------------------------------- + +For local annotation layers, you can change the order of annotations +in the :guilabel:`Annotations` tab by :kbd:`Alt` + +:si-icon:`material/mouse-left-click-outline` left-click-dragging an +entry in the list to a new position. While dragging, a colored bar +indicates whether the dragged annotation will be placed **before** +(top edge) or **after** (bottom edge) the row under the cursor. +Release the mouse to commit the move, or press :kbd:`Escape` to +cancel. + +Reordering is restricted to annotations within the same local +annotation source and is persisted in the viewer JSON state. + +.. _annotation-descriptions: + +Adding a description to an annotation +------------------------------------- + +Each annotation can carry a free-form text description. + +1. Select the annotation (see :ref:`selecting-annotations`). Its + details open in the selection panel on the right. +2. In the selection panel, locate the :guilabel:`Description` text + area underneath the annotation's properties. +3. Type your description. The text is saved to the annotation when + the text area loses focus (for example, when you click elsewhere + or :kbd:`Tab` away). + +The description is stored on the annotation itself and is persisted +as part of the viewer state. + +.. _depth-range-and-annotations: + +Depth Range and Annotations +--------------------------- + +Neuroglancer has a concept of a "depth range" that controls which +objects are visible in the 2D and 3D views based on their depth +relative to the cursor. Annotations are visible if they are within +that depth range. This applies to all objects in the 3d view, and or +other vector based objects (i.e. skeletons) which are not voxel based +in the 2d view. Voxel based objects (images/segmentation) are always +"sliced" through at a single pixel depth in the 2D views. + +The depth range can be found by hovering over the xyz position +readout in the upper left of each rendering panel. The depth range is +expressed in physical units if the dimensions rendered has them. (for +example, nm = nanometers, um=microns, mm=millimeters, etc). + +You may need to adjust the depth range to get rendering behavior that +you desire. For example, consider annotating cell body locations in an +Electron Microscopy dataset that has 40nm thick sections in Z. + +With a depth range of 10nm, annotations are visible only in the precise +section where they were placed. If you relax the depth range to 120nm and +move through sections, annotations fade out after a few sections. Setting +it back to 40nm makes annotations visible only in the annotated section. + +If the "zoom-relative" button is checked, neuroglancer adjusts the +depth range to scale up as you zoom out and scale down as you zoom in. +When zoomed out and flipping through sections, annotations appear +'farther' away in Z than when zoomed in. For some applications this +is natural, as images downsample as you zoom out — annotations then +render at a similar relative depth to the voxels used for the current view. + +However for some applications this is unintuitive. For example, if you +want to easily see whether a cell has already been annotated regardless +of zoom level, disable the "zoom-relative" option and set the depth range +to the approximate radius of the object you are annotating (say 5 microns +for a cell). Annotations will then fade in and out on that length scale, +no matter the zoom. + +.. _annotation-keyboard-shortcuts: + +Annotation Properties and Schema +-------------------------------- +Annotations are geometries in space that can represent many things, +but often you also want to write something else down about those +annotations. The description field is nice, but any scientist who +has tried to turn free form text fields into data knows that +unstructured fields are not the best way to capture information. +Plus, if we write down our data in structured way we can easily +use that data to drive the visual appearence of our annotations, +which you can read about in :doc:`annotation_shaders`. + +The schema tab of the local annotation layer lets you define custom +properties for your annotations, with default properties. +To add a new property click the + button. You first select a data type +from the list of available types. This will add a new row to the schema. +Once added, you can name the property and give it a default value. +New annotations will hae the default value. Note however, if you change +the default value, existing annotations will not be updated to have the new default value. Press the pencil icon to the right to edit the description +of the property. + +Once you have added properties, the selection widget will show the +properties of that annotation in the selection widget, +and you can set the properties for that annotation there. and the rendering +tab will show the properties as options to drive the shader code +(see :doc:`annotation_shaders`). The descriptions will be available +as tooltips hover text in both locations. + +Enums +~~~~~ +If you scroll down in this list of available types, below "Numeric" +you will find a list of "Enum" types. These are useful for when you +want to mark annotations with a controlled vocabulary of strings. +If you want free form text, the annotation description field is +already available for that. + +When you pick an enum type, below the "Default value" for that enum +will be a interface to add and rename enum values. You can add new +values with the + button found there. Once you have added some enum +values, you can select one as the default value for that property. +When you edit the property of an annotation, you will get a dropdown +to select which enum value you want to set that property to. + + +Keyboard and mouse shortcuts +---------------------------- + +The following default bindings apply when an annotation tool is +active on the selected layer: + +.. list-table:: + :header-rows: 1 + :widths: 55 45 + + * - Action + - Binding + * - Create annotation / place next point + - :kbd:`Ctrl` + + :si-icon:`material/mouse-left-click-outline` left-click + * - Select annotation under cursor + - :kbd:`Ctrl` + + :si-icon:`material/mouse-right-click-outline` right-click + * - Move an annotation point + - :kbd:`Alt` + + :si-icon:`material/mouse-left-click-outline` left-click-drag + * - Reorder an annotation in the list (local annotations) + - :kbd:`Alt` + + :si-icon:`material/mouse-left-click-outline` left-click-drag + on a list entry + * - Delete an annotation + - :kbd:`Ctrl` + :kbd:`Alt` + + :si-icon:`material/mouse-right-click-outline` right-click + * - Undo last annotation point (during multi-point placement) + - :kbd:`Backspace` + * - Finish polyline annotation + - :kbd:`Enter` or place a new point at the same position as the + previous one + +.. _annotation-custom-hotkeys: + +Custom hotkeys +------------------------- + +Mainline neuroglancer does **not** include built-in hotkeys for +cycling through annotations (for example, "next annotation" / +"previous annotation"). + +Forks or downstream deployments of neuroglancer may bundle additional +default bindings for annotation navigation. + +.. _linked-segmentations: + +Linked segmentation layers +-------------------------- + +An annotation layer can be linked to one or more segmentation layers +through named **relationships**. The default relationship is named +``segments``. When an annotation is created on or near a segment in a +linked segmentation layer, the segment's ID is captured on the +annotation as a **related ID** for that relationship. + +To link an annotation to a segmentation, select the segmentation layer +from the dropdown next to the segments relationship control. Once +selected, any annotations you make will capture the segment ID underneath +the annotation, in either 2d or 3d. + +Once annotations have related IDs, then checking the box next to +the relationship control will trigger selective loading of the +annotations that are related to visible segmentIDs selected +from the segmentation layer. + +Note, this same control works for non-local annotation layers that +have registered relationships as well. + +Linking a segmentation layer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the annotation layer's side panel, the linked-segmentations widget +shows one row per relationship. Each row provides: + +- A checkbox that controls whether annotations are filtered by this + relationship's related IDs (see :ref:`filtering-by-segmentation`). +- The relationship name (for example, ``segments``). +- A layer selector for picking the segmentation layer this + relationship is linked to. + +Selecting a segmentation layer in this widget establishes the link. +After that, newly created annotations automatically pick up the IDs +of the segments under their points. + +Related segments in the selection panel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a single annotation is selected, the selection panel includes a +**Related Segments** section for each relationship. The section lists +the related IDs for that annotation and lets you: + +- Toggle the visibility of each related segment in the linked + segmentation layer. +- Copy segment IDs. +- Add or remove related IDs. + +.. _filtering-by-segmentation: + +Filtering annotations by segmentation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the filter checkbox for a relationship is enabled, the +annotation layer displays only annotations whose related IDs for that +relationship are currently visible in the linked segmentation layer. +This is useful for showing only the annotations that belong to the +segments you have selected. + +An additional :guilabel:`Ignore null related segment filter` checkbox +controls how annotations with no related IDs are treated while +filtering is active: + +- When enabled, annotations with no related IDs are shown regardless + of which segments are visible. +- When disabled, annotations with no related IDs are hidden whenever + filtering by segmentation is on. + diff --git a/docs/user-guide/index.rst b/docs/user-guide/index.rst new file mode 100644 index 0000000000..4230a8380c --- /dev/null +++ b/docs/user-guide/index.rst @@ -0,0 +1,21 @@ +User Guide +========== + +This section describes how to use the neuroglancer viewer interactively — +how to navigate volumetric data, work with layers, and create annotations. + +Topics +------ + +- :doc:`navigation` — moving, rotating, and zooming the data views. +- :doc:`annotations` — creating and editing annotations, and linking them + to segmentation layers. +- :doc:`annotation_shaders` — writing custom GLSL shader code to drive + the visual appearance of annotations from their properties. + +.. toctree:: + :hidden: + + navigation + annotations + annotation_shaders diff --git a/src/ui/annotations.ts b/src/ui/annotations.ts index 43fc43387a..cc44d8e70c 100644 --- a/src/ui/annotations.ts +++ b/src/ui/annotations.ts @@ -508,9 +508,9 @@ export class AnnotationLayerView extends Tab { const helpIcon = makeIcon({ title: - "The left icons allow you to select the type of the anotation. Color and other display settings are available in the 'Rendering' tab.", + "The left icons allow you to select the type of the annotation. Color and other display settings are available in the 'Rendering' tab. Click for documentation.", svg: svg_help, - clickable: false, + href: "https://neuroglancer-docs.web.app/user-guide/annotation.html", }); helpIcon.style.marginLeft = "auto"; mutableControls.appendChild(helpIcon);