Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

advanced annotation features #11

Closed
wants to merge 14 commits into from
Closed

Conversation

danton267
Copy link
Collaborator

#8

@hannahker
Copy link
Collaborator

hannahker commented Jul 5, 2023

@danton267 could you resolve the conflicts with main?

EDIT: And also add some more detailed explanation about which parts of #8 are addressed here?

Base automatically changed from annotation-features to main July 5, 2023 22:04
@github-actions
Copy link

github-actions bot commented Jul 7, 2023

Staging application has been deployed and is available at: https://dash5-services.plotly.host/ml-exchange-staging
Production app name: ml-exchange
Current branch name: advanced-annotation-features
Commit: ed386a1

@danton267
Copy link
Collaborator Author

@danton267 could you resolve the conflicts with main?

EDIT: And also add some more detailed explanation about which parts of #8 are addressed here?

Description of what the PR contains:

  • Save annotations to an external database (will require resources and input from LBL)
    • annotations are stored every time relayout event happens on the figure in a local dcc.Store
    • user can go to the Save/Load/Export menu to save annotations permanently (it can be easily changed so that instead of saving locally, it saves permanently instead for a better user experience)
    • currently, it saves into a local file, but the destination can be modified to point to a database when we are given access
  • Allow user to select and load saved annotations
    • Save/Load/Export contains an option to load the aforementioned saved data
    • this option is project dependent - if the user has saved annotations for Project 1, and none for Project 2, they will be able to load annotations for Project 1 and continue using them, but there won't be an option to load anything for Project 2 since there are none stored
  • Allow users to download annotations in vector (JSON) or rasterized (TIFF) formats for interoperability with other software tools.
    • Added functionality to export active annotations as JSON and TIFF from the Save/Load/Export menu (TIFF version/style is still up for discussion so that it is compatible with the desired software)

Copy link
Collaborator

@hannahker hannahker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great @danton267 💃 I think we'll need to talk with LBL a bit more about how to handle cases of saving annotations across slices, but I think this is a great start for now.

I've also found a couple bugs, but I'm not too fussed with making it perfect as we'll probably still be adjusting some of this logic (just noting them down if we need for future reference):

  1. Loading a saved annotation on a slice different than the one it was created on gives a KeyError:
Traceback (most recent call last):
  File "/Users/hannahker/Desktop/mlex/mlex_highres_segmentation/callbacks/control_bar.py", line 259, in load_and_apply_selected_annotations
    patched_figure["layout"]["shapes"] = data[str(img_idx)]
KeyError: '2'
  1. Loading a saved annotation then switching slices gives:
Traceback (most recent call last):
  File "/Users/hannahker/Desktop/mlex/mlex_highres_segmentation/callbacks/image_viewer.py", line 63, in render_image
    fig["layout"]["shapes"] = annotation_data[str(image_idx)]
  File "/Users/hannahker/miniconda3/lib/python3.9/site-packages/plotly/basedatatypes.py", line 5853, in __setitem__
    super(BaseLayoutHierarchyType, self).__setitem__(prop, value)
  File "/Users/hannahker/miniconda3/lib/python3.9/site-packages/plotly/basedatatypes.py", line 4847, in __setitem__
    self._set_array_prop(prop, value)
  File "/Users/hannahker/miniconda3/lib/python3.9/site-packages/plotly/basedatatypes.py", line 5328, in _set_array_prop
    val = validator.validate_coerce(val, skip_invalid=self._skip_invalid)
  File "/Users/hannahker/miniconda3/lib/python3.9/site-packages/_plotly_utils/basevalidators.py", line 2568, in validate_coerce
    res.append(self.data_class(v_el, skip_invalid=skip_invalid))
  File "/Users/hannahker/miniconda3/lib/python3.9/site-packages/plotly/graph_objs/layout/_shape.py", line 1072, in __init__
    self._process_kwargs(**dict(arg, **kwargs))
  File "/Users/hannahker/miniconda3/lib/python3.9/site-packages/plotly/basedatatypes.py", line 4369, in _process_kwargs
    raise err
ValueError: Invalid property specified for object of type plotly.graph_objs.layout.Shape: 'label'

Did you mean "layer"?

    Valid properties:
        editable
            Determines whether the shape could be activated for
            edit or not. Has no effect when the older editable
            shapes mode is enabled via `config.editable` or
            `config.edits.shapePosition`.
        fillcolor
            Sets the color filling the shape's interior. Only
            applies to closed shapes.
        fillrule
            Determines which regions of complex paths constitute
            the interior. For more info please visit
            https://developer.mozilla.org/en-
            US/docs/Web/SVG/Attribute/fill-rule
        layer
            Specifies whether shapes are drawn below or above
            traces.
        line
            :class:`plotly.graph_objects.layout.shape.Line`
            instance or dict with compatible properties
        name
            When used in a template, named items are created in the
            output figure in addition to any items the figure
            already has in this array. You can modify these items
            in the output figure by making your own item with
            `templateitemname` matching this `name` alongside your
            modifications (including `visible: false` or `enabled:
            false` to hide it). Has no effect outside of a
            template.
        opacity
            Sets the opacity of the shape.
        path
            For `type` "path" - a valid SVG path with the pixel
            values replaced by data values in
            `xsizemode`/`ysizemode` being "scaled" and taken
            unmodified as pixels relative to `xanchor` and
            `yanchor` in case of "pixel" size mode. There are a few
            restrictions / quirks only absolute instructions, not
            relative. So the allowed segments are: M, L, H, V, Q,
            C, T, S, and Z arcs (A) are not allowed because radius
            rx and ry are relative. In the future we could consider
            supporting relative commands, but we would have to
            decide on how to handle date and log axes. Note that
            even as is, Q and C Bezier paths that are smooth on
            linear axes may not be smooth on log, and vice versa.
            no chained "polybezier" commands - specify the segment
            type for each one. On category axes, values are numbers
            scaled to the serial numbers of categories because
            using the categories themselves there would be no way
            to describe fractional positions On data axes: because
            space and T are both normal components of path strings,
            we can't use either to separate date from time parts.
            Therefore we'll use underscore for this purpose:
            2015-02-21_13:45:56.789
        templateitemname
            Used to refer to a named item in this array in the
            template. Named items from the template will be created
            even without a matching item in the input figure, but
            you can modify one by making an item with
            `templateitemname` matching its `name`, alongside your
            modifications (including `visible: false` or `enabled:
            false` to hide it). If there is no template or no
            matching item, this item will be hidden unless you
            explicitly show it with `visible: true`.
        type
            Specifies the shape type to be drawn. If "line", a line
            is drawn from (`x0`,`y0`) to (`x1`,`y1`) with respect
            to the axes' sizing mode. If "circle", a circle is
            drawn from ((`x0`+`x1`)/2, (`y0`+`y1`)/2)) with radius
            (|(`x0`+`x1`)/2 - `x0`|, |(`y0`+`y1`)/2 -`y0`)|) with
            respect to the axes' sizing mode. If "rect", a
            rectangle is drawn linking (`x0`,`y0`), (`x1`,`y0`),
            (`x1`,`y1`), (`x0`,`y1`), (`x0`,`y0`) with respect to
            the axes' sizing mode. If "path", draw a custom SVG
            path using `path`. with respect to the axes' sizing
            mode.
        visible
            Determines whether or not this shape is visible.
        x0
            Sets the shape's starting x position. See `type` and
            `xsizemode` for more info.
        x1
            Sets the shape's end x position. See `type` and
            `xsizemode` for more info.
        xanchor
            Only relevant in conjunction with `xsizemode` set to
            "pixel". Specifies the anchor point on the x axis to
            which `x0`, `x1` and x coordinates within `path` are
            relative to. E.g. useful to attach a pixel sized shape
            to a certain data value. No effect when `xsizemode` not
            set to "pixel".
        xref
            Sets the shape's x coordinate axis. If set to a x axis
            id (e.g. "x" or "x2"), the `x` position refers to a x
            coordinate. If set to "paper", the `x` position refers
            to the distance from the left of the plotting area in
            normalized coordinates where 0 (1) corresponds to the
            left (right). If set to a x axis ID followed by
            "domain" (separated by a space), the position behaves
            like for "paper", but refers to the distance in
            fractions of the domain length from the left of the
            domain of that axis: e.g., *x2 domain* refers to the
            domain of the second x  axis and a x position of 0.5
            refers to the point between the left and the right of
            the domain of the second x axis.
        xsizemode
            Sets the shapes's sizing mode along the x axis. If set
            to "scaled", `x0`, `x1` and x coordinates within `path`
            refer to data values on the x axis or a fraction of the
            plot area's width (`xref` set to "paper"). If set to
            "pixel", `xanchor` specifies the x position in terms of
            data or plot fraction but `x0`, `x1` and x coordinates
            within `path` are pixels relative to `xanchor`. This
            way, the shape can have a fixed width while maintaining
            a position relative to data or plot fraction.
        y0
            Sets the shape's starting y position. See `type` and
            `ysizemode` for more info.
        y1
            Sets the shape's end y position. See `type` and
            `ysizemode` for more info.
        yanchor
            Only relevant in conjunction with `ysizemode` set to
            "pixel". Specifies the anchor point on the y axis to
            which `y0`, `y1` and y coordinates within `path` are
            relative to. E.g. useful to attach a pixel sized shape
            to a certain data value. No effect when `ysizemode` not
            set to "pixel".
        yref
            Sets the shape's y coordinate axis. If set to a y axis
            id (e.g. "y" or "y2"), the `y` position refers to a y
            coordinate. If set to "paper", the `y` position refers
            to the distance from the bottom of the plotting area in
            normalized coordinates where 0 (1) corresponds to the
            bottom (top). If set to a y axis ID followed by
            "domain" (separated by a space), the position behaves
            like for "paper", but refers to the distance in
            fractions of the domain length from the bottom of the
            domain of that axis: e.g., *y2 domain* refers to the
            domain of the second y  axis and a y position of 0.5
            refers to the point between the bottom and the top of
            the domain of the second y axis.
        ysizemode
            Sets the shapes's sizing mode along the y axis. If set
            to "scaled", `y0`, `y1` and y coordinates within `path`
            refer to data values on the y axis or a fraction of the
            plot area's height (`yref` set to "paper"). If set to
            "pixel", `yanchor` specifies the y position in terms of
            data or plot fraction but `y0`, `y1` and y coordinates
            within `path` are pixels relative to `yanchor`. This
            way, the shape can have a fixed height while
            maintaining a position relative to data or plot
            fraction.
        
Did you mean "layer"?

Bad property path:
label
^^^^^

@danton267
Copy link
Collaborator Author

  1. Loading a saved annotation and then switching slices gives:

I could not recreate that issue; from the code, it looks like it should never happen. Maybe it used an old save file on your system?

@danton267 danton267 linked an issue Jul 13, 2023 that may be closed by this pull request
@hannahker hannahker closed this Jul 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add advanced annotations functionality
2 participants