-
Notifications
You must be signed in to change notification settings - Fork 68
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
Adding DecodedIntensityTable class #1489
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1489 +/- ##
==========================================
- Coverage 87.23% 87.17% -0.07%
==========================================
Files 138 140 +2
Lines 5023 5020 -3
==========================================
- Hits 4382 4376 -6
- Misses 641 644 +3
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly fine. The move of the plausibly-only-used-in-test-code code to its own module can happen in a separate PR if easier. The deduplication of synthetic_intensities
should happen.
starfish/core/codebook/codebook.py
Outdated
return DecodedIntensityTable.from_intensity_table( | ||
intensities, | ||
targets=(Features.AXIS, np.empty(0, dtype='U')), | ||
distances=(Features.AXIS, np.empty(0, dtype=float)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: would prefer the explicit type, like np.float32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine with this suggestion but suggest not dropping precision: suggest using np.float64
if changing.
|
||
""" | ||
|
||
# TODO nsofroniew: right now there is no jitter on x-y positions of the spots |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, this should probably call IntensityTable.synthetic_intensities
and assign targets to the spots.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
return intensities | ||
|
||
@classmethod | ||
def assign_synthetic_targets(cls, intensities: IntensityTable) -> "DecodedIntensityTable": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is used only for tests, I would consider moving this outside of the class to keep things easier for users.
""" | ||
|
||
@classmethod | ||
def synthetic_intensities( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is only for tests. If true, I would consider moving this outside of the class to keep things easier for users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't heard of our users leveraging this module, so @ttung 's suggestion to move it out seems reasonable.
targets=(Features.AXIS, np.random.choice(list('ABCD'), size=20)), | ||
distances=(Features.AXIS, np.random.rand(20))) | ||
|
||
def assign_cell_ids(self, cell_ids: Tuple[str, np.ndarray]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of the scope of this PR, but I question whether this method makes sense in this class. Intuitively, it seems misplaced, but I am curious what you and @ambrosejcarr think.
I strongly feel, however, if we keep this here, that we should make it an internal API (prefixed with _).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on internal if retained. @ttung is your intuition is that users should be leveraging AssignTargets
? Makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll remove this method and just assign targets directly in tests
""" | ||
|
||
@classmethod | ||
def synthetic_intensities( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't heard of our users leveraging this module, so @ttung 's suggestion to move it out seems reasonable.
|
||
""" | ||
|
||
# TODO nsofroniew: right now there is no jitter on x-y positions of the spots |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
targets=(Features.AXIS, np.random.choice(list('ABCD'), size=20)), | ||
distances=(Features.AXIS, np.random.rand(20))) | ||
|
||
def assign_cell_ids(self, cell_ids: Tuple[str, np.ndarray]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on internal if retained. @ttung is your intuition is that users should be leveraging AssignTargets
? Makes sense.
""" | ||
self[Features.CELL_ID] = cell_ids | ||
|
||
def to_decoded_spots(self) -> DecodedSpots: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name confuses me now that the class is explicitly "decoded". I suggest to_dataframe
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xarray already has a to_dataframe()
method so we can't override that, how about to_decoded_dataframe
?
from starfish.core.util.dtype import preserve_float_range | ||
|
||
|
||
class DecodedIntensityTable(IntensityTable): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if both IntensityTable
and DecodedIntensityTable
should subclass a common AbstractClass, instead of having linear inheritance. I don't think the decoding machinery is needed by DecodedIntensityTable
Alternatively, @ttung is consistent in wanting functional code like decoding to live in its own component (see his comments about gene assignment). If going this way, it would be out of scope for this PR, but should be captured in a follow-up issue.
5db69cb
to
dd52d49
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, please see comments before landing.
starfish/core/codebook/codebook.py
Outdated
return DecodedIntensityTable.from_intensity_table( | ||
intensities, | ||
targets=(Features.AXIS, np.empty(0, dtype='U')), | ||
distances=(Features.AXIS, np.empty(0, dtype=float)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
np.float64 like above.
|
||
class DecodedIntensityTable(IntensityTable): | ||
""" | ||
DecodedIntensityTable is a container for spot or pixel features extracted from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unwrap as per 100-col convention, pls.
Generates a dataframe containing decoded spot information. Guaranteed to contain physical | ||
spot coordinates (z, y, x) and gene target. Does not contain pixel coordinates. | ||
""" | ||
if Features.TARGET not in self.coords.keys(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not necessary any more.
""" | ||
|
||
# verify the IntensityTable has been decoded | ||
if Features.TARGET not in self.coords.keys(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also not necessary any more.
@@ -7,6 +7,7 @@ | |||
|
|||
from starfish.core.codebook.test.factories import codebook_array_factory | |||
from starfish.core.imagestack.test.factories import imagestack_with_coords_factory | |||
from starfish.core.intensity_table.test import factories |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a relative import, i.e., from .factories import synthetic_decoded_intenisty_table
Oh, can you verify the docs generate correctly for this? I think we need to link it in from the |
7fce7e4
to
a112655
Compare
a112655
to
b73ab2f
Compare
Introducing DecodedIntensityTable which is just a subclass of IntensityTable. I moved anything related to decoded spots into the DecodedIntensityTable class. This is mostly to reduce confusion in the codebase between the outputs of various spot finding and decoding methods. In most cases the very end of a pipeline will now be a DecodedIntensityTable.