Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Christopher22
Copy link
Contributor

Description

This small patch allows a custom "pipeline" of image filters within the TissueMask to optimize for specific demands regarding tissue. The default behavior is not changed.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Documentation

Issues Fixed or Closed by This PR

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

@codecov
Copy link

codecov bot commented Jan 26, 2022

Codecov Report

Merging #377 (ecf8a33) into master (df69137) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #377   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           17        17           
  Lines         1411      1430   +19     
  Branches       218       222    +4     
=========================================
+ Hits          1411      1430   +19     
Impacted Files Coverage Δ
histolab/filters/compositions.py 100.00% <100.00%> (ø)
histolab/masks.py 100.00% <100.00%> (ø)
histolab/tile.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update df69137...ecf8a33. Read the comment docs.

Copy link
Member

@ernestoarbitrio ernestoarbitrio 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 your contribution @Christopher22 ❤️ !
I have some concerns on this PR 🤷🏽‍♂️ . The first thing is the tests you provided. Please read my comment.
Furthermore @alessiamarcolini can give you other consideration on you work.

Copy link
Member

@ernestoarbitrio ernestoarbitrio left a comment

Choose a reason for hiding this comment

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

@Christopher22 I did this CR round with @alessiamarcolini.
Sorry for the bunch of request changes ... but overall looks neat.
Could you please address the comments in order to make us able to do a final round?
Thanks again for you effort 💪🏽 ... we really appreciated it 😄

tissue_mask = TissueMask(*custom_filters)
_ = tissue_mask(slide)

set_custom_filters_.assert_called_once()
Copy link
Member

Choose a reason for hiding this comment

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

I'm not a huge fan of assert_called_once. The reason is that, yes, you're asserting that a proper method has been called, but the interesting info would be also know with which parameters? I'd suggest to switch to assert_called_once_with and check the calling args 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I try to remove all of the things. However, I sometimes have no access to the "self" parameter. In this case, I try to check only the remaining arguments.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry I do not understand this point. Could you elaborate? Thx

# and the custom filter itself is called
set_custom_filters_.assert_called_once()
assert set_custom_filters_.call_args[0][1] == custom_filters[0]
custom_filter_call_.assert_called_once()
Copy link
Member

Choose a reason for hiding this comment

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

same

Copy link
Collaborator

Choose a reason for hiding this comment

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

Regarding the whole test: I feel that testing that RgbToGrayscale is called is not a good strategy, because:

  1. usually we want to mock all the methods/instances that get called/used directly by the method we are testing, so in this case it would be Tile.calculate_tissue_mask
  2. as a proof for my first point: this test is not really checking that the mask is built with the custom filters, because RgbToGrayscale is actually the first filter in the "default" filter sequence (for both Slide and Tile). So this test would actually pass with both the default and the "custom" filters represented by [RgbToGrayscale()] 🤓

Please let me know if this makes sense for you!

Copy link
Collaborator

Choose a reason for hiding this comment

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

@Christopher22 I think you misunderstood my points here. This updated test covers point number 2 but not number 1, the mocked object is not directly called/used by the method you're testing.

@Christopher22
Copy link
Contributor Author

Thank you so much for your comments! I hope, I was able to fix the things up you mentioned.

As a small refactor, I removed my 'set_custom_filters' and replaced it with a meaningful constructor which fits better in your existing codebase.

Copy link
Member

@ernestoarbitrio ernestoarbitrio left a comment

Choose a reason for hiding this comment

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

Hey @Christopher22 thanks for all your commitment. I left a couple of furhter minor comments. Could you please take a look? After that we are probably ready to go.

Heads up to @alessiamarcolini ☝🏽

@Christopher22
Copy link
Contributor Author

Amazing! Your highlighed areas should be fixed by now :)

Copy link
Collaborator

@alessiamarcolini alessiamarcolini left a comment

Choose a reason for hiding this comment

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

Apart from a couple of docstrings improvements, I had to reason carefully about two unit tests (see comments) and please try to cover all of your new code with tests (follow codecov comments), as we cannot merge this PR if it does not provide 100% coverage ✌🏼

[False, True],
]
tissue_mask_tile_.return_value = expected_mask

Copy link
Collaborator

Choose a reason for hiding this comment

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

not your responsibility, but since you touched this method... this line should also be removed

# and the custom filter itself is called
set_custom_filters_.assert_called_once()
assert set_custom_filters_.call_args[0][1] == custom_filters[0]
custom_filter_call_.assert_called_once()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Regarding the whole test: I feel that testing that RgbToGrayscale is called is not a good strategy, because:

  1. usually we want to mock all the methods/instances that get called/used directly by the method we are testing, so in this case it would be Tile.calculate_tissue_mask
  2. as a proof for my first point: this test is not really checking that the mask is built with the custom filters, because RgbToGrayscale is actually the first filter in the "default" filter sequence (for both Slide and Tile). So this test would actually pass with both the default and the "custom" filters represented by [RgbToGrayscale()] 🤓

Please let me know if this makes sense for you!

@Christopher22
Copy link
Contributor Author

Such cute apes! ;) Your comments should be integrated by now!

Copy link
Collaborator

@alessiamarcolini alessiamarcolini left a comment

Choose a reason for hiding this comment

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

Please check the comment I left about the it_knows_its_mask_tile_and_supports_custom_filters test.

PS please squash the commits at the end of the review, otherwise it's more difficult for us to be on track with the changes between review rounds ✌🏼

@Christopher22
Copy link
Contributor Author

@alessiamarcolini Do you prefer a test such as this instead? :)

Copy link
Collaborator

@alessiamarcolini alessiamarcolini left a comment

Choose a reason for hiding this comment

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

Just a minor comment for consistency, the rest is perfect!! 👏🏼

@Christopher22
Copy link
Contributor Author

Ready for squash ;)

Copy link
Collaborator

@alessiamarcolini alessiamarcolini left a comment

Choose a reason for hiding this comment

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

Let's merge it!

@ernestoarbitrio ernestoarbitrio merged commit 34389aa into histolab:master Feb 25, 2022
@alessiamarcolini
Copy link
Collaborator

@Christopher22 thank you so much for your valuable contribution! 👏🏼👏🏼

Now, to have a consistent code base, we would like to provide the same flexibility for the BiggestTissueBoxMask as well. Please let us know if you are interested in contributing again in this regard! Otherwise, we can take care of it, no pressure at all 😉

@alessiamarcolini alessiamarcolini added this to the 0.5.0 milestone Mar 8, 2022
@alessiamarcolini alessiamarcolini added the enhancement New feature or request label Mar 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow custom filters for TissueMask

3 participants