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 to provenance log #968

Merged
merged 17 commits into from
Feb 28, 2019
3 changes: 3 additions & 0 deletions starfish/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
# NOTE: if we move to python 3.7, we can produce this value at call time via __getattr__
__version__ = pkg_resources.require("starfish")[0].version

# Variable to be set by release process
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would make it super explicit, e.g., is_released_version or something like that.

also, cc: #761

__release_tag__ = None


if __name__ == "__main__":
starfish()
12 changes: 9 additions & 3 deletions starfish/imagestack/imagestack.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
PhysicalCoordinateTypes,
STARFISH_EXTRAS_KEY
)
from starfish.util.JSONenocder import LogEncoder
from starfish.util import logging
from ._mp_dataarray import MPDataArray
from .dataorder import AXES_DATA, N_AXES

Expand Down Expand Up @@ -952,7 +952,13 @@ def update_log(self, class_instance) -> None:
----------
class_instance: The instance of a class being applied to the imagestack
"""
entry = {"method": class_instance.__class__.__name__, "arguments": class_instance.__dict__}
entry = {"method": class_instance.__class__.__name__,
ttung marked this conversation as resolved.
Show resolved Hide resolved
"arguments": class_instance.__dict__,
"os": logging.get_os_info(),
"dependencies": logging.get_core_dependency_info(),
"release tag": logging.get_release_tag(),
"starfish version": logging.get_dependency_version('starfish')
}
self._log.append(entry)

@property
Expand Down Expand Up @@ -1087,7 +1093,7 @@ def export(self,

"""
# Add log data to extras
self._tile_data.extras[STARFISH_EXTRAS_KEY] = LogEncoder().encode({LOG: self.log})
self._tile_data.extras[STARFISH_EXTRAS_KEY] = logging.LogEncoder().encode({LOG: self.log})
tileset = TileSet(
dimensions={
Axes.ROUND,
Expand Down
2 changes: 1 addition & 1 deletion starfish/pipeline/algorithmbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from starfish.intensity_table.intensity_table import IntensityTable
from starfish.types import LOG
from starfish.types._constants import STARFISH_EXTRAS_KEY
from starfish.util.JSONenocder import LogEncoder
from starfish.util.logging import LogEncoder


class AlgorithmBaseType(type):
Expand Down
1 change: 1 addition & 0 deletions starfish/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from ._constants import (
Axes,
Coordinates,
CORE_DEPENDENCIES,
Features,
LOG,
PHYSICAL_COORDINATE_DIMENSION,
Expand Down
4 changes: 4 additions & 0 deletions starfish/types/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class Coordinates(AugmentedEnum):
"""
This is name of the provenance log attribute stored on the IntensityTable
"""
CORE_DEPENDENCIES = {'numpy', 'scikit-image', 'pandas', 'scikit-learn', 'scipy', 'xarray', 'sympy'}
"""
The set of dependencies whose versions are are logged for each starfish session
"""


class PhysicalCoordinateTypes(AugmentedEnum):
Expand Down
14 changes: 0 additions & 14 deletions starfish/util/JSONenocder.py

This file was deleted.

49 changes: 49 additions & 0 deletions starfish/util/logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import platform
from functools import lru_cache
from json import JSONEncoder
from typing import Mapping

import pkg_resources

import starfish
from starfish.types import CORE_DEPENDENCIES


@lru_cache(maxsize=1)
def get_core_dependency_info() -> Mapping[str, str]:
dependency_info = dict()
for dependency in CORE_DEPENDENCIES:
version = get_dependency_version(dependency)
dependency_info[dependency] = version
return dependency_info


def get_dependency_version(dependency: str) -> str:
return pkg_resources.get_distribution(dependency).version


@lru_cache(maxsize=1)
def get_release_tag() -> str:
if not starfish.__release_tag__:
return "Running starfish from source"
return starfish.__release_tag__


@lru_cache(maxsize=1)
def get_os_info() -> Mapping[str, str]:
return {"Platform": platform.system(),
"Version:": platform.version(),
"Python Version": platform.python_version()}


class LogEncoder(JSONEncoder):
"""
JSON encodes the List[Dict] pipeline provence log. For simple
objects use default JSON encoding. For more complex objects
(ex. Imagestack, Codebook) encode the repr of the object.
"""
def default(self, o):
try:
return super(LogEncoder, self).default(o)
except TypeError:
return JSONEncoder().encode(repr(o))