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

DM-17248: ap_verify should create .json files in the workspace by default #66

Merged
merged 3 commits into from
Mar 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 25 additions & 5 deletions python/lsst/ap/verify/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
__all__ = ["MetricsParser", "computeMetrics"]

import argparse
import collections
import copy
import os
import warnings
Expand All @@ -50,10 +51,11 @@ def __init__(self):
# Help and documentation will be handled by main program's parser
argparse.ArgumentParser.__init__(self, add_help=False)
self.add_argument(
'--metrics-file', default='ap_verify.{dataId}.verify.json',
'--metrics-file', default='{output}/ap_verify.{dataId}.verify.json',
help="The file template to which to output metrics in lsst.verify "
"format; {dataId} will be replaced with the job\'s data ID. "
"Defaults to ap_verify.{dataId}.verify.json.")
"format. {output} will be replaced with the value of the "
"--output argument, while {dataId} will be replaced with the "
"job\'s data ID. Defaults to {output}/ap_verify.{dataId}.verify.json.")
# TODO: remove --silent in DM-18120
self.add_argument('--silent', dest='submitMetrics', nargs=0,
action=DeprecatedAction,
Expand Down Expand Up @@ -91,6 +93,19 @@ def __call__(self, _parser, _namespace, _values, option_string=None):
warnings.warn(message, category=FutureWarning)


class _OptionalFormatDict(collections.UserDict):
"""A dictionary that, when used with a formatter, preserves unknown
replacement fields.

This lets clients perform partial string substitution without `str.format`
or `str.format_map` failing over missing keywords.
"""
def __missing__(self, key):
"""Re-create the replacement field if there is no replacement.
"""
return "{%s}" % key


def computeMetrics(workspace, dataIds, args):
"""Measure any metrics that apply to the final result of the AP pipeline,
rather than to a particular processing stage.
Expand All @@ -104,14 +119,19 @@ def computeMetrics(workspace, dataIds, args):
args : `argparse.Namespace`
Command-line arguments, including arguments controlling output.
"""
# Substitute all fields that won't be filled in by MetricsControllerTask
# _OptionalFormatDict makes format_map preserve unspecified fields for later replacement
metricsFile = args.metrics_file.format_map(
_OptionalFormatDict(output=workspace.workDir))

imageConfig = _getMetricsConfig(args.image_metrics_config,
"default_image_metrics.py",
args.metrics_file)
metricsFile)
_runMetricTasks(imageConfig, dataIds.refList)

datasetConfig = _getMetricsConfig(args.dataset_metrics_config,
"default_dataset_metrics.py",
args.metrics_file)
metricsFile)
_runMetricTasks(datasetConfig, [workspace.workButler.dataRef("apPipe_config")])


Expand Down
9 changes: 8 additions & 1 deletion python/lsst/ap/verify/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,16 @@ def __init__(self, location):
self._workButler = None
self._analysisButler = None

@property
def workDir(self):
"""The location of the workspace as a whole (`str`, read-only).
"""
return self._location

@property
def configDir(self):
"""The location of a directory containing custom Task config files for use with the data.
"""The location of a directory containing custom Task config files for
use with the data (`str`, read-only).
"""
return os.path.join(self._location, 'config')

Expand Down
3 changes: 2 additions & 1 deletion tests/test_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def _assertInDir(self, path, baseDir):
self.assertEqual(ancestor, _canonDir)

def _assertNotInDir(self, path, baseDir):
"""Test that ``path`` is a subpath of ``baseDir``.
"""Test that ``path`` is not a subpath of ``baseDir``.
kfindeisen marked this conversation as resolved.
Show resolved Hide resolved
"""
_canonPath = os.path.abspath(os.path.realpath(path))
_canonDir = os.path.abspath(os.path.realpath(baseDir))
Expand Down Expand Up @@ -84,6 +84,7 @@ def testDirectories(self):
The exact repository locations are not tested, as they are likely to change.
"""
root = self._testWorkspace
self.assertEqual(self._testbed.workDir, root)
self._assertInDir(self._testbed.configDir, root)
for repo in WorkspaceTestSuite._allRepos(self._testbed):
# Workspace spec allows these to be URIs or paths, whatever the Butler accepts
Expand Down