-
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
1.) Provenance logging refactor and support for SpotFindingResults #1517
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -3,10 +3,7 @@ | |||||
from abc import ABCMeta | ||||||
|
||||||
from starfish.core.imagestack.imagestack import ImageStack | ||||||
from starfish.core.intensity_table.intensity_table import IntensityTable | ||||||
from starfish.core.types import LOG | ||||||
from starfish.core.types._constants import STARFISH_EXTRAS_KEY | ||||||
from starfish.core.util.logging import LogEncoder | ||||||
|
||||||
|
||||||
class AlgorithmBase(ABCMeta): | ||||||
|
@@ -21,29 +18,33 @@ def run_with_logging(func): | |||||
This method extends each pipeline component.run() method to also log itself and | ||||||
runtime parameters to the IntensityTable and ImageStack objects. There are two | ||||||
scenarios for this method: | ||||||
1.) Filtering/ApplyTransform: | ||||||
Imagestack -> Imagestack | ||||||
2.) Spot Detection: | ||||||
ImageStack -> IntensityTable | ||||||
ImageStack -> [IntensityTable, ConnectedComponentDecodingResult] | ||||||
TODO segmentation and decoding | ||||||
""" | ||||||
@functools.wraps(func) | ||||||
def helper(*args, **kwargs): | ||||||
result = func(*args, **kwargs) | ||||||
# Scenario 1, Filtering, ApplyTransform | ||||||
if isinstance(result, ImageStack): | ||||||
result.update_log(args[0]) | ||||||
# Scenario 2, Spot detection | ||||||
elif isinstance(result, tuple) or isinstance(result, IntensityTable): | ||||||
if isinstance(args[1], ImageStack): | ||||||
stack = args[1] | ||||||
# update log with spot detection instance args[0] | ||||||
stack.update_log(args[0]) | ||||||
# get resulting intensity table and set log | ||||||
it = result | ||||||
if isinstance(result, tuple): | ||||||
it = result[0] | ||||||
it.attrs[STARFISH_EXTRAS_KEY] = LogEncoder().encode({LOG: stack.log}) | ||||||
if result is not None: | ||||||
method_class_str = str(args[0].__class__) | ||||||
if 'ApplyTransform' in method_class_str or 'Filter' in method_class_str: | ||||||
# Update the log on the resulting ImageStack | ||||||
result.log.update_log(args[0]) | ||||||
if 'FindSpots' in method_class_str: | ||||||
# Update the log on the resulting SpotFindingResults | ||||||
result.log.update_log(args[0]) | ||||||
if 'DecodeSpots' in method_class_str: | ||||||
# update log then transfer to DecodedIntensityTable | ||||||
spot_results = kwargs['spots'] | ||||||
spot_results.log.update_log(args[0]) | ||||||
result.attrs[STARFISH_EXTRAS_KEY] = spot_results.log.encode() | ||||||
# OLD CODE FOR DETECT WILL GET REMOVED | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
if 'DetectSpots' in method_class_str or 'DetectPixels' in method_class_str: | ||||||
if isinstance(args[1], ImageStack): | ||||||
stack = args[1] | ||||||
# update log with spot detection instance args[0] | ||||||
stack.log.update_log(args[0]) | ||||||
# get resulting intensity table and set log | ||||||
it = result | ||||||
if isinstance(result, tuple): | ||||||
it = result[0] | ||||||
it.attrs[STARFISH_EXTRAS_KEY] = stack.log.encode() | ||||||
return result | ||||||
return helper |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,45 @@ | ||
import platform | ||
from functools import lru_cache | ||
from json import JSONEncoder | ||
from typing import Mapping | ||
from typing import List, Mapping | ||
|
||
import pkg_resources | ||
|
||
import starfish.core | ||
from starfish.core.types import CORE_DEPENDENCIES | ||
from starfish.core.types import CORE_DEPENDENCIES, LOG | ||
|
||
|
||
class Log: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love the idea. Is this only used by spot finding? My intuition is that this should trigger a bigger refactor. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nah this is used by everything. This PR was basically the "bigger" logging refactor needed to keep everything working throughout the refactor |
||
def __init__(self): | ||
""" | ||
Class for capturing methods and their parameters applied by an analysis | ||
pipeline. | ||
""" | ||
self._log: List[dict] = list() | ||
|
||
def update_log(self, class_instance) -> None: | ||
""" | ||
Adds a new entry to the log list. | ||
|
||
Parameters | ||
---------- | ||
class_instance: The instance of a class being applied to the imagestack | ||
shanaxel42 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
entry = {"method": class_instance.__class__.__name__, | ||
"arguments": class_instance.__dict__, | ||
"os": get_os_info(), | ||
"dependencies": get_core_dependency_info(), | ||
"release tag": get_release_tag(), | ||
"starfish version": get_dependency_version('starfish') | ||
} | ||
self._log.append(entry) | ||
|
||
def encode(self): | ||
return LogEncoder().encode({LOG: self.data}) | ||
|
||
@property | ||
def data(self): | ||
return self._log | ||
|
||
|
||
@lru_cache(maxsize=1) | ||
|
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.
It's plausible that we have mechanisms that take multiple loggable objects.
It might be a good idea to have a base
ProvenanceTracked
class that all objects (ImageStack
,IntensityTable
, etc.) inherit, and then to walk through all the arguments to find objects that extendProvenanceTracked
. Then scrape the logs from those objects and build up a provenance graph.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 seems like a larger refactor, like maybe something post spot finding stuff
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.
Sure, can you tack that onto the logging epic?
There are a lot of gaps in the logging -- for instance, ApplyTransform plausibly should log the origin of the warping data. Also can be covered afterwards.