Skip to content

Commit 7c0e863

Browse files
committed
Merge pull request #743 from satra/fix/prov
Fix/prov
2 parents 7902c09 + c7e3fdb commit 7c0e863

File tree

5 files changed

+45
-45
lines changed

5 files changed

+45
-45
lines changed

examples/fmri_spm.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
1616
Import necessary modules from nipype."""
1717

18+
from nipype import config
19+
config.enable_provenance()
20+
1821
from nipype import spm, fsl
1922

2023
# In order to use this example with SPM's matlab common runtime
@@ -389,6 +392,4 @@ def getstripdir(subject_id):
389392

390393
if __name__ == '__main__':
391394
l1pipeline.run('MultiProc')
392-
# l2pipeline.run()
393-
# l1pipeline.write_graph()
394-
395+
l2pipeline.run('MultiProc')

nipype/external/provcopy.py

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import datetime
1515
import json
1616
import re
17+
import dateutil.parser
1718
import collections
1819
from collections import defaultdict
1920

@@ -179,31 +180,10 @@
179180

180181

181182
# Datatypes
182-
_r_xsd_dateTime = re.compile(""" ^
183-
(?P<year>-?[0-9]{4}) - (?P<month>[0-9]{2}) - (?P<day>[0-9]{2})
184-
T (?P<hour>[0-9]{2}) : (?P<minute>[0-9]{2}) : (?P<second>[0-9]{2})
185-
(?P<microsecond>\.[0-9]{1,6})?
186-
(?P<tz>
187-
Z | (?P<tz_hr>[-+][0-9]{2}) : (?P<tz_min>[0-9]{2})
188-
)?
189-
$ """, re.X)
190-
191183
attr2rdf = lambda attr: PROV[PROV_ID_ATTRIBUTES_MAP[attr].split('prov:')[1]].rdf_representation()
192184

193185
def _parse_xsd_dateTime(s):
194-
"""Returns datetime or None."""
195-
m = _r_xsd_dateTime.match(s)
196-
if m is not None:
197-
values = m.groupdict()
198-
if values["microsecond"] is None:
199-
values["microsecond"] = 0
200-
else:
201-
values["microsecond"] = values["microsecond"][1:]
202-
values["microsecond"] += "0" * (6 - len(values["microsecond"]))
203-
values = dict((k, int(v)) for k, v in values.iteritems() if not k.startswith("tz"))
204-
return datetime.datetime(**values)
205-
else:
206-
return None
186+
return dateutil.parser.parse(s)
207187

208188

209189
def _ensure_datetime(time):
@@ -359,7 +339,7 @@ def provn_representation(self):
359339

360340
def json_representation(self):
361341
return {'$': self._uri, 'type': u'xsd:anyURI'}
362-
342+
363343
def rdf_representation(self):
364344
return URIRef(self.get_uri())
365345

@@ -773,7 +753,7 @@ def rdf(self, graph=None, subj=None):
773753
obj = RDFLiteral(value)
774754
graph.add((subj, pred, obj))
775755
return graph
776-
756+
777757
def is_asserted(self):
778758
return self._asserted
779759

@@ -788,7 +768,7 @@ def is_relation(self):
788768
class ProvElement(ProvRecord):
789769
def is_element(self):
790770
return True
791-
771+
792772
def rdf(self, graph=None):
793773
if graph is None:
794774
graph = Graph()
@@ -1666,15 +1646,15 @@ def rdf(self, graph=None):
16661646
# graph should not None here
16671647
uri = self.get_identifier().rdf_representation()
16681648
graph = Graph(graph.store, uri)
1669-
1649+
16701650
for prefix, namespace in self._namespaces.items():
16711651
graph.bind(prefix, namespace.get_uri())
1672-
1652+
16731653
for record in self._records:
16741654
if record.is_asserted():
16751655
record.rdf(graph)
16761656
return graph
1677-
1657+
16781658
def get_provjson(self, **kw):
16791659
"""Return the `PROV-JSON <http://www.w3.org/Submission/prov-json/>`_ representation for the bundle/document.
16801660

nipype/pipeline/engine.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -689,10 +689,10 @@ def run(self, plugin=None, plugin_args=None, updatehash=False):
689689
runner.run(execgraph, updatehash=updatehash, config=self.config)
690690
datestr = datetime.utcnow().strftime('%Y%m%dT%H%M%S')
691691
if str2bool(self.config['execution']['write_provenance']):
692-
write_workflow_prov(execgraph,
693-
os.path.join(self.base_dir,
694-
'workflow_provenance_%s' % datestr),
695-
format='all')
692+
prov_base = os.path.join(self.base_dir,
693+
'workflow_provenance_%s' % datestr)
694+
logger.info('Provenance file prefix: %s' % prov_base)
695+
write_workflow_prov(execgraph, prov_base, format='all')
696696
return execgraph
697697

698698
# PRIVATE API AND FUNCTIONS

nipype/pipeline/utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,11 @@ def merge_dict(d1, d2, merge=lambda x, y: y):
10701070
return result
10711071

10721072

1073+
def merge_bundles(g1, g2):
1074+
for rec in g2.get_records():
1075+
g1._add_record(rec)
1076+
return g1
1077+
10731078
def write_workflow_prov(graph, filename=None, format='turtle'):
10741079
"""Write W3C PROV Model JSON file
10751080
"""
@@ -1102,12 +1107,12 @@ def write_workflow_prov(graph, filename=None, format='turtle'):
11021107
if isdefined(values):
11031108
subresult.outputs[key] = values[idx]
11041109
sub_bundle = ProvStore().add_results(subresult)
1105-
ps.g.add_bundle(sub_bundle)
1110+
ps.g = merge_bundles(ps.g, sub_bundle)
11061111
ps.g.wasGeneratedBy(sub_bundle, process)
11071112
else:
11081113
process.add_extra_attributes({pm.PROV["type"]: nipype_ns["Node"]})
11091114
result_bundle = ProvStore().add_results(result)
1110-
ps.g.add_bundle(result_bundle)
1115+
ps.g = merge_bundles(ps.g, result_bundle)
11111116
ps.g.wasGeneratedBy(result_bundle, process)
11121117
processes.append(process)
11131118

nipype/utils/provenance.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
get_id = lambda: niiri[uuid1().hex]
3232

3333
def get_attr_id(attr, skip=None):
34-
dictwithhash, hashval = get_hashval(attr, skip=None)
34+
dictwithhash, hashval = get_hashval(attr, skip=skip)
3535
return niiri[hashval]
3636

3737
max_text_len = 1024000
@@ -59,10 +59,19 @@ def get_hashval(inputdict, skip=None):
5959

6060
dict_withhash = {}
6161
dict_nofilename = OrderedDict()
62-
for name, val in sorted(inputdict.items()):
63-
if skip is not None and name in skip:
62+
keys = {}
63+
for key in inputdict:
64+
if skip is not None and key in skip:
6465
continue
65-
outname = name.get_uri()
66+
keys[key.get_uri()] = key
67+
for key in sorted(keys):
68+
val = inputdict[keys[key]]
69+
outname = key
70+
try:
71+
if isinstance(val, pm.URIRef):
72+
val = val.decode()
73+
except AttributeError:
74+
pass
6675
if isinstance(val, pm.QName):
6776
val = val.get_uri()
6877
if isinstance(val, pm.Literal):
@@ -180,14 +189,19 @@ def prov_encode(graph, value, create_container=True):
180189
entities = []
181190
for item in value:
182191
item_entity = prov_encode(graph, item)
183-
if 'file://' not in item_entity.get_value():
184-
raise ValueError('No file found')
185192
entities.append(item_entity)
193+
if isinstance(item, list):
194+
continue
195+
if not isinstance(item_entity.get_value()[0], basestring):
196+
raise ValueError('Not a string literal')
197+
if 'file://' not in item_entity.get_value()[0]:
198+
raise ValueError('No file found')
186199
id = get_id()
187200
entity = graph.collection(identifier=id)
188201
for item_entity in entities:
189-
graph.hadMember(id, item_entity.get_identifier())
190-
except ValueError:
202+
graph.hadMember(id, item_entity)
203+
except ValueError, e:
204+
iflogger.debug(e)
191205
entity = prov_encode(graph, value, create_container=False)
192206
else:
193207
entity = prov_encode(graph, value[0])

0 commit comments

Comments
 (0)