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

add a class that allows storing locations of errors #46

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

moenigin
Copy link

  • add some typing and docstring

Copy link
Collaborator

@mjanusz mjanusz left a comment

Choose a reason for hiding this comment

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

Thanks for adding the new class! I left a bunch of comments, mostly regarding code style and formatting issues.

ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
@mjanusz
Copy link
Collaborator

mjanusz commented Aug 20, 2023

Could you please squash all the commits within the PR into a single one, and also run pyink on the code, using the settings from https://github.com/google/ffn/blob/master/ffn/pyproject.toml ?

implements requested changes

add a class that allows storing locations of errors

- add some typing and docstring

Update proofreading.py

pass actionstate to store_error_location with different mode input directly & remove intermedeiary functions
@moenigin
Copy link
Author

I hope what I did is what you were aiming for

@mjanusz
Copy link
Collaborator

mjanusz commented Aug 21, 2023

Thanks! Unfortunately, it looks like it formatted everything with 4 spaces. One problem might have been that our pyproject.toml got accidentally moved to an incorrect location, so maybe that's why the tool didn't pick up the config. This is now fixed. Could you try syncing the repo and running pyink again? (or manually specify the settings that we use in the config file).

@moenigin
Copy link
Author

sorry for not checking this properly and all the hassle this created (was to happy about seeing pyink printing "all done" and trusted it did work according to toml). I noticed that the docstrings are not corrected to 2 indents by pyink. I did this manually now, but maybe pyink can do this on its own...

ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
ffn/utils/proofreading.py Outdated Show resolved Hide resolved
objects: A list of objects.
bad: A list of bad objects or markers.
seg_error_coordinates: A dictionary of error coordinates.
load_annotations: A flag to indicate if annotations should be loaded.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's a use case where you would provide seg_error_coordinates, but set load_annotations to False?

Copy link
Author

Choose a reason for hiding this comment

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

A combination of laziness and generak flaws of the tool as is now. 1. If I pick up the review after a break I don't want to patch the final list of coordinates from different review session. 2. The annotation layer shows all annotations not only for the segment you are currently viewing. If in the last review session you already verfied that all locations you flagged in that session are correct, you may want to visualize only the novel locations.
Hope I am kind of making this clear here...

Copy link
Collaborator

Choose a reason for hiding this comment

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

OK, so is the idea that when load_annotations == False, the seg_error_coordinates are just stored (and appended to as you annotate more), but not actually displayed?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, that was my idea behind this because R. had already annotated >100 splits by the time we started this. Large numbers of annotations could be confusing. So if they are not needed because they are all verified from a previous revision round one can leave them out this way...
(Alternatively one could link the annotation to the errorneous segment of the todo list (requiring batch size to be one). By overriding update_segments one could only display the locations associated with a given batch of segments from the todo list. To view all marked location one could create a "show_all" function. However, as mentioned in the email thread I am not sure whether getting to split locations as implemented here is the most efficient way. Assembling segments belonging to one neurite by selection is usually faster. This would yield more coordinate pairs for a given split, but the would not necessarily be in close proximity to each other. If the latter is what you are after, that should be stated explicitly in the instructions.)

- include requested updates
- fix bug for annotation selection
@moenigin
Copy link
Author

thanks for the detailed inspection!

ffn/utils/proofreading.py Outdated Show resolved Hide resolved
@mjanusz
Copy link
Collaborator

mjanusz commented Aug 22, 2023

thanks for the detailed inspection!

Thanks for your patience with this. We're very close to having this completed now.

transform list of annotations id pair to frozenset
@moenigin
Copy link
Author

thanks for the detailed inspection!

Thanks for your patience with this. We're very close to having this completed now.

I am learning a lot :-) E.g. that conventions are much more "local" than expected :-).

@mjanusz
Copy link
Collaborator

mjanusz commented Aug 24, 2023

Could you please try running https://github.com/google/pytype on this code? We're getting a bunch of failures caused by the new annotations.

@moenigin
Copy link
Author

Could you please try running https://github.com/google/pytype on this code? We're getting a bunch of failures caused by the new annotations.

This doesn't install on Windows. Unless there is an alternative to this I will not be able to check this for the next two weeks. Did the checks pass beforehand? Is there any hint to where the problem could be? I cannot view the details to this copybara thing either...

@mjanusz
Copy link
Collaborator

mjanusz commented Aug 24, 2023

Here are the specific failures that are triggered:

File "third_party/py/ffn/utils/proofreading.py", line 65, in __init__: Built-in function len was called with the wrong arguments [wrong-arg-types]
         Expected: (obj: Sized)
  Actually passed: (obj: Optional[Iterable[Tuple[int, int, int]]])
  Attributes of protocol Sized are not implemented on None: __len__
File "third_party/py/ffn/utils/proofreading.py", line 71, in Base: Invalid type annotation 'list[str, Any]'  [invalid-annotation]
  list[_T] expected 1 parameter, got 2
File "third_party/py/ffn/utils/proofreading.py", line 115, in update_segments: unsupported operand type(s) for item retrieval: 'aa: str' and 'layer: str' [unsupported-operands]
  No attribute '__getitem__' on 'aa: str'
File "third_party/py/ffn/utils/proofreading.py", line 166, in list_segments: bad return type [bad-return-type]
           Expected: List[int]
  Actually returned: List[str]
File "third_party/py/ffn/utils/proofreading.py", line 316, in mark_bad: No attribute 'add' on list [attribute-error]
File "third_party/py/ffn/utils/proofreading.py", line 316, in mark_bad: No attribute 'add' on list [attribute-error]
  In Union[Any, list]
Called from (traceback):
  line 281, in <lambda>
File "third_party/py/ffn/utils/proofreading.py", line 318, in mark_bad: No attribute 'add' on list [attribute-error]
File "third_party/py/ffn/utils/proofreading.py", line 318, in mark_bad: No attribute 'add' on list [attribute-error]
  In Union[Any, list]
Called from (traceback):
  line 281, in <lambda>
File "third_party/py/ffn/utils/proofreading.py", line 330, in mark_removed_bad: unsupported operand type(s) for |: 'list' and 'new_bad: Set[int]' [unsupported-operands]
  No attribute '__or__' on 'list' or '__ror__' on 'new_bad: Set[int]'
File "third_party/py/ffn/utils/proofreading.py", line 355, in ObjectReviewStoreLocation: Type annotation for seg_error_coordinates does not match type of assignment [annotation-type-mismatch]
  Annotation: Optional[List[str]]
  Assignment: Dict[nothing, nothing]
File "third_party/py/ffn/utils/proofreading.py", line 359, in ObjectReviewStoreLocation: Invalid type annotation 'list[str, List[List[int]]]'  [invalid-annotation]
  list[_T] expected 1 parameter, got 2
File "third_party/py/ffn/utils/proofreading.py", line 373, in __init__: No attribute 'items' on List[str] [attribute-error]
  In Optional[List[str]]
File "third_party/py/ffn/utils/proofreading.py", line 418, in get_id: No attribute 'keys' on None [attribute-error]
  In Optional[List[str]]
File "third_party/py/ffn/utils/proofreading.py", line 418, in get_id: No attribute 'keys' on List[str] [attribute-error]
  In Optional[List[str]]
File "third_party/py/ffn/utils/proofreading.py", line 457, in store_error_location: No attribute 'update' on None [attribute-error]
  In Optional[List[str]]
File "third_party/py/ffn/utils/proofreading.py", line 457, in store_error_location: No attribute 'update' on List[str] [attribute-error]
  In Optional[List[str]]
File "third_party/py/ffn/utils/proofreading.py", line 526, in delete_location_from_annotation: unsupported operand type(s) for item deletion: None [unsupported-operands]
  No attribute '__delitem__' on None
File "third_party/py/ffn/utils/proofreading.py", line 526, in delete_location_from_annotation: unsupported operand type(s) for item deletion: List[str] and str [unsupported-operands]
  Function __delitem__ on List[str] expects Union[SupportsIndex, slice]
File "third_party/py/ffn/utils/proofreading.py", line 545, in delete_last_location: unsupported operand type(s) for item deletion: None [unsupported-operands]
  No attribute '__delitem__' on None
File "third_party/py/ffn/utils/proofreading.py", line 545, in delete_last_location: unsupported operand type(s) for item deletion: List[str] and str [unsupported-operands]
  Function __delitem__ on List[str] expects Union[SupportsIndex, slice]
File "third_party/py/ffn/utils/proofreading.py", line 686, in add_ccs: Function GraphUpdater.update_segments was called with the wrong arguments [wrong-arg-types]
         Expected: (self, segments: List[int], ...)
  Actually passed: (self, segments: set)

These are not new, we just got to this stage where this could be run. Any chance you could try WSL which the page you linked suggests would make it possible to run pytype? If this doesn't work, you could also try running another type checker like https://mypy-lang.org/

correct typing
@mjanusz mjanusz self-assigned this Sep 12, 2023
@mjanusz
Copy link
Collaborator

mjanusz commented Sep 12, 2023

Were you able to get type checking to work on your end?

I'm still seeing some failures with the latest change:

File "third_party/py/ffn/utils/proofreading.py", line 115, in update_segments: unsupported operand type(s) for item retrieval: 'aa: str' and 'layer: str' [unsupported-operands]
  No attribute '__getitem__' on 'aa: str'
File "third_party/py/ffn/utils/proofreading.py", line 166, in list_segments: bad return type [bad-return-type]
           Expected: List[int]
  Actually returned: List[str]
File "third_party/py/ffn/utils/proofreading.py", line 418, in get_id: No attribute 'keys' on None [attribute-error]
  In Optional[Dict[str, list]]
File "third_party/py/ffn/utils/proofreading.py", line 457, in store_error_location: No attribute 'update' on None [attribute-error]
  In Optional[Dict[str, list]]
File "third_party/py/ffn/utils/proofreading.py", line 526, in delete_location_from_annotation: unsupported operand type(s) for item deletion: None [unsupported-operands]
  No attribute '__delitem__' on None
File "third_party/py/ffn/utils/proofreading.py", line 544, in delete_last_location: Function reversed.__init__ was called with the wrong arguments [wrong-arg-types]
         Expected: (self, sequence: Reversible)
  Actually passed: (self, sequence: Optional[Dict[str, list]])
  Attributes of protocol Reversible[_T2] are not implemented on Dict[str, list]: __reversed__
File "third_party/py/ffn/utils/proofreading.py", line 545, in delete_last_location: unsupported operand type(s) for item deletion: None [unsupported-operands]
  No attribute '__delitem__' on None
File "third_party/py/ffn/utils/proofreading.py", line 686, in add_ccs: Function GraphUpdater.update_segments was called with the wrong arguments [wrong-arg-types]
         Expected: (self, segments: List[int], ...)
  Actually passed: (self, segments: set)

@moenigin
Copy link
Author

Were you able to get type checking to work on your end?

I'm still seeing some failures with the latest change:

File "third_party/py/ffn/utils/proofreading.py", line 115, in update_segments: unsupported operand type(s) for item retrieval: 'aa: str' and 'layer: str' [unsupported-operands]
  No attribute '__getitem__' on 'aa: str'
File "third_party/py/ffn/utils/proofreading.py", line 166, in list_segments: bad return type [bad-return-type]
           Expected: List[int]
  Actually returned: List[str]
File "third_party/py/ffn/utils/proofreading.py", line 418, in get_id: No attribute 'keys' on None [attribute-error]
  In Optional[Dict[str, list]]
File "third_party/py/ffn/utils/proofreading.py", line 457, in store_error_location: No attribute 'update' on None [attribute-error]
  In Optional[Dict[str, list]]
File "third_party/py/ffn/utils/proofreading.py", line 526, in delete_location_from_annotation: unsupported operand type(s) for item deletion: None [unsupported-operands]
  No attribute '__delitem__' on None
File "third_party/py/ffn/utils/proofreading.py", line 544, in delete_last_location: Function reversed.__init__ was called with the wrong arguments [wrong-arg-types]
         Expected: (self, sequence: Reversible)
  Actually passed: (self, sequence: Optional[Dict[str, list]])
  Attributes of protocol Reversible[_T2] are not implemented on Dict[str, list]: __reversed__
File "third_party/py/ffn/utils/proofreading.py", line 545, in delete_last_location: unsupported operand type(s) for item deletion: None [unsupported-operands]
  No attribute '__delitem__' on None
File "third_party/py/ffn/utils/proofreading.py", line 686, in add_ccs: Function GraphUpdater.update_segments was called with the wrong arguments [wrong-arg-types]
         Expected: (self, segments: List[int], ...)
  Actually passed: (self, segments: set)

I have tried as far as possible without human support to get pytype running - it would not be recognized in WSL. I therefore used mypy. This did not run through error free but the errors that remained are non-overlapping with the ones you indicate:

proofreading.py:24: error: Skipping analyzing "networkx": module is installed, but missing library stubs or py.typed marker [import]
proofreading.py:24: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
proofreading.py:25: error: Skipping analyzing "neuroglancer": module is installed, but missing library stubs or py.typed marker [import]
proofreading.py:55: error: Need type annotation for "todo" (hint: "todo: List[] = ...") [var-annotated]
proofreading.py:67: error: Incompatible types in assignment (expression has type "None", variable has type "list[Sequence[int]]") [assignment]
proofreading.py:375: error: Need type annotation for "temp_coord_list" (hint: "temp_coord_list: List[] = ...") [var-annotated]
proofreading.py:509: error: Return value expected [return-value]
Found 6 errors in 1 file (checked 1 source file)

IIUC this is mypy not understanding some packages, complains about class attributes not being typed and does not understand None is returned in line509. I was hoping your typing tool would not crash there (apparantly the case!).

About the errors you get:
I can fix line 418, line 457, line 526, line 544, line 545 - had this fixed before but must have undone this somehow before committing. Sorry! I think the error in line 686 is likely fixed by cenverting line 95 to '''segments: Sequence[int],'''
However, the errors in line 115 and line 166 I don't understand. If self.todo is a list of dictionaries mapping lists of integer on layer (str) the typing should be correct. Do you see the error?

The type check you are doing is based on pytype? I can try to get help to get this running again but it may take me some time (human experts are scarce)

- fix/silence type hint errors (I hope)
- fix error annotation count
- fix error type assignment by only the second location
@mjanusz
Copy link
Collaborator

mjanusz commented Sep 25, 2023

Thanks for the last round of changes! The latest version passes all our internal type checks, but I noticed that the annotation for the object list was actually not completely correct. I just pushed a commit that provides the correct annotations for that list -- could you please rebase on top of that and adjust the annotations where needed?

def update_segments(
self,
segments: Union[set[int], list[int]],
loc: Optional[Sequence[int]] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

pls use Optional[Point]

@@ -94,39 +117,55 @@ def update_segments(self, segments, loc=None, layer='seg'):
else:
l.equivalences.clear()
for a in self.todo[self.index : self.index + self.batch]:
a = [aa[layer] for aa in a]
a = [cast(dict, aa)[layer] for aa in a]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is the cast still needed now that self.todo is typed?

objects: Union[dict[str, int], Sequence[int]],
bad: set,
num_to_prefetch: int = 10,
locations: Optional[list[Sequence[int]]] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

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

pls use Point here

def __init__(self, objects, bad, num_to_prefetch=10, locations=None):
def __init__(
self,
objects: Union[dict[str, int], Sequence[int]],
Copy link
Collaborator

Choose a reason for hiding this comment

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

pls use Iterable[ObjectItem]


def __init__(
self,
objects: list,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Iterable[ObjectItem]

self.make_point_annotation(coord, annotation_id)

def make_point_annotation(
self, coordinate: list[int], annotation_id: str
Copy link
Collaborator

Choose a reason for hiding this comment

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

Point?

self.cur_error_type = None

def annotate_error_locations(
self, coordinates: list[list[int]], error_id: str
Copy link
Collaborator

Choose a reason for hiding this comment

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

Iterable[Point]?

@mjanusz
Copy link
Collaborator

mjanusz commented Sep 26, 2023

Looks great, just a few minor typing changes suggested above. Thanks!

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.

None yet

2 participants