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 projections schema to start doc #179

Merged
merged 13 commits into from
Aug 11, 2020
6 changes: 5 additions & 1 deletion event_model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1625,7 +1625,7 @@ def compose_descriptor(*, start, streams, event_counter,
partial(compose_event_page, descriptor=doc, event_counter=event_counter))


def compose_run(*, uid=None, time=None, metadata=None, validate=True):
def compose_run(*, uid=None, time=None, metadata=None, validate=True, projections=None):
Copy link
Member

Choose a reason for hiding this comment

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

All other non-required keys enter in through metadata. I think we should either add all of them to the signature or leave projections out of the signature.

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'll back out that change, let you add a projection to metadata.

"""
Compose a RunStart document and factory functions for related documents.

Expand All @@ -1641,6 +1641,8 @@ def compose_run(*, uid=None, time=None, metadata=None, validate=True):
Additional metadata include the document
validate : boolean, optional
Validate this document conforms to the schema.
projections: dict, optional
Additional projection data

Returns
-------
Expand All @@ -1652,6 +1654,8 @@ def compose_run(*, uid=None, time=None, metadata=None, validate=True):
time = ttime.time()
if metadata is None:
metadata = {}
if projections is not None:
metadata['projections'] = projections
doc = dict(uid=uid, time=time, **metadata)
# Define some mutable state to be shared internally by the closures composed
# below.
Expand Down
15 changes: 6 additions & 9 deletions event_model/schemas/run_start.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"type": "object",
"properties" : {
"stream": {"type": "string"},
"location": {"enum" : ["event", "configuration"]},
"location": {"enum" : ["event", "configuration"], "description": "event comes from event, configuration comes from fieles inthe run_start document"},
"field": {"type": "string"},
"slice_args": {
"type": "array",
Expand All @@ -19,18 +19,15 @@
}
}
},
"required" : ["stream", "location", "field"],
"required" : ["location", "field"],
"additionalProperties": false
},
"projections": {
"title" : "Describe how to interperet this run as the given technique",
"title" : "Describe how to interperet this run as the given projection",
"properties":{
"name": {"type": "string",
"description": "The name of the projection"},
"version": {"type": "string",
"description": "The version of the projection spec. Can specify the version of an external specification."},
"configuration" : {"type": "object",
"description": "Static information about technique"},
"name": {"type": "string", "description": "The name of the projection"},
"version": {"type": "string", "description": "The version of the projection spec. Can specify the version of an external specification."},
"configuration" : {"type": "object", "description": "Static information about projection"},
"projection" : {
"type": "object",
"patternProperties": {".": {"$ref": "#/definitions/projection"}},
Expand Down
44 changes: 0 additions & 44 deletions event_model/tests/test_em.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import event_model
import numpy
import pytest
from jsonschema.exceptions import ValidationError

def test_documents():
dn = event_model.DocumentNames
Expand Down Expand Up @@ -1197,46 +1196,3 @@ def test_pickle_filler():
deserialized = pickle.loads(serialized)
assert filler == deserialized

def test_projections():
event_model.schema_validators[event_model.DocumentNames.start].validate(
{
"uid": "abc",
"time": 0,
"projections": [
{
"name": "test",
"version": "42.0.0",
"configuration": {},
"projection": {
'Entry/instrument/detector/data': {
'location': 'event',
'stream': 'primary',
'field': 'ccd',
'slice_args': ['sdfsdfds']
},
},
}
],
})

with pytest.raises(ValidationError):
event_model.schema_validators[event_model.DocumentNames.start].validate(
{
"uid": "abc",
"time": 0,
"projections": [
{
"name": "test",
"version": "42.0.0",
"configuration": {},
"projection": {
'Entry/instrument/detector/data': {
'location': 'THIS IS NOT VALID',
'stream': 'primary',
'field': 'ccd',
'slice_args': ['sdfsdfds', 1]
},
},
}
],
})
73 changes: 73 additions & 0 deletions event_model/tests/test_projections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import event_model
import pytest
from jsonschema.exceptions import ValidationError

def test_projection_start_doc():
metadata = {'so_long': 'thanks_for_all_the_fish'}
# proejctions are added to metadata which is added to start document, so
# we have several paths to test here

# 1 add proection without metadata
run_bundle = event_model.compose_run(uid="42", projections=valid_projections)
start_doc = run_bundle.start_doc
assert start_doc['projections'] == valid_projections

# 2 add no projection
run_bundle = event_model.compose_run(uid="42", metadata=metadata)
start_doc = run_bundle.start_doc
assert 'projections' not in start_doc
assert start_doc['so_long'] == 'thanks_for_all_the_fish'


# 3 add projection with metadata
run_bundle = event_model.compose_run(uid="42", metadata=metadata, projections=valid_projections)
start_doc = run_bundle.start_doc
assert start_doc['projections'] == valid_projections
assert start_doc['so_long'] == 'thanks_for_all_the_fish'


def test_projection_schema():
start_doc['projections'] = valid_projections
event_model.schema_validators[event_model.DocumentNames.start].validate(start_doc)

with pytest.raises(ValidationError):
start_doc['projections'] = invalid_projections
event_model.schema_validators[event_model.DocumentNames.start].validate(start_doc)


valid_projections = [
{
"name": "test",
"version": "42.0.0",
"configuration": {},
"projection": {
'entry/instrument/detector/data': {
'location': 'event',
'stream': 'primary',
'field': 'ccd',
'slice_args': ['sdfsdfds']
},
},
}
]


invalid_projections = [
{
"name": "test",
"version": "42.0.0",
"configuration": {},
"projection": {
'entry/instrument/detector/data': {
'location': 'THIS IS NOT VALID',
'stream': 'primary',
'field': 'ccd',
'slice_args': ['sdfsdfds', 1]
},
},
}
]
start_doc = {
"uid": "abc",
"time": 0,
}