Skip to content

Commit d2215c3

Browse files
committed
RF: Subclass GiftiMetaData from CaretMetaData and add API compatibility hacks
1 parent 6144535 commit d2215c3

File tree

2 files changed

+50
-36
lines changed

2 files changed

+50
-36
lines changed

nibabel/gifti/gifti.py

+43-30
Original file line numberDiff line numberDiff line change
@@ -15,62 +15,75 @@
1515
import sys
1616
import numpy as np
1717
import base64
18+
import warnings
1819

1920
from .. import xmlutils as xml
2021
from ..filebasedimages import SerializableImage
2122
from ..nifti1 import data_type_codes, xform_codes, intent_codes
23+
from ..caret import CaretMetaData
2224
from .util import (array_index_order_codes, gifti_encoding_codes,
2325
gifti_endian_codes, KIND2FMT)
2426
from ..deprecated import deprecate_with_version
2527

2628

27-
class GiftiMetaData(xml.XmlSerializable):
29+
class GiftiMetaData(CaretMetaData):
2830
""" A sequence of GiftiNVPairs containing metadata for a gifti data array
2931
"""
3032

31-
def __init__(self, nvpair=None):
32-
self.data = []
33-
if nvpair is not None:
34-
self.data.append(nvpair)
33+
def __init__(self, *args, **kwargs):
34+
dep_init = False
35+
# Positional arg
36+
dep_init |= not kwargs and len(args) == 1 and isinstance(args[0], GiftiNVPairs)
37+
# Keyword arg
38+
dep_init |= not args and list(kwargs) == ["nvpair"]
39+
if dep_init:
40+
warnings.warn(
41+
"GiftiMetaData now has a dict-like interface. "
42+
"See ``pydoc dict`` for initialization options. "
43+
"Passing ``GiftiNVPairs()`` or using the ``nvpair`` "
44+
"keyword will fail or behave unexpectedly in NiBabel 6.0.",
45+
FutureWarning, stacklevel=2)
46+
super().__init__()
47+
pair = args[0] if args else kwargs.get("nvpair")
48+
self[pair.name] = pair.value
49+
else:
50+
super().__init__(*args, **kwargs)
51+
52+
@property
53+
def data(self):
54+
warnings.warn(
55+
"GiftiMetaData.data will be a dict in NiBabel 6.0.",
56+
FutureWarning, stacklevel=2)
57+
return [GiftiNVPairs(k, v) for k, v in self._data.items()]
3558

3659
@classmethod
60+
@deprecate_with_version(
61+
'from_dict class method deprecated. Use GiftiMetaData directly.',
62+
'4.0', '6.0')
3763
def from_dict(klass, data_dict):
38-
meda = klass()
39-
for k, v in data_dict.items():
40-
nv = GiftiNVPairs(k, v)
41-
meda.data.append(nv)
42-
return meda
64+
return klass(data_dict)
4365

4466
@deprecate_with_version(
4567
'get_metadata method deprecated. '
4668
"Use the metadata property instead.",
4769
'2.1', '4.0')
4870
def get_metadata(self):
49-
return self.metadata
71+
return dict(self)
5072

5173
@property
74+
@deprecate_with_version(
75+
'metadata property deprecated. Use GiftiMetadata object '
76+
'as dict or pass to dict() for a standard dictionary.',
77+
'4.0', '6.0')
5278
def metadata(self):
5379
""" Returns metadata as dictionary """
54-
self.data_as_dict = {}
55-
for ele in self.data:
56-
self.data_as_dict[ele.name] = ele.value
57-
return self.data_as_dict
58-
59-
def _to_xml_element(self):
60-
metadata = xml.Element('MetaData')
61-
for ele in self.data:
62-
md = xml.SubElement(metadata, 'MD')
63-
name = xml.SubElement(md, 'Name')
64-
value = xml.SubElement(md, 'Value')
65-
name.text = ele.name
66-
value.text = ele.value
67-
return metadata
80+
return dict(self)
6881

6982
def print_summary(self):
70-
print(self.metadata)
83+
print(dict(self))
7184

7285

73-
class GiftiNVPairs(object):
86+
class GiftiNVPairs:
7487
""" Gifti name / value pairs
7588
7689
Attributes
@@ -370,7 +383,7 @@ def __init__(self,
370383
self.ind_ord = array_index_order_codes.code[ordering]
371384
self.meta = (GiftiMetaData() if meta is None else
372385
meta if isinstance(meta, GiftiMetaData) else
373-
GiftiMetaData.from_dict(meta))
386+
GiftiMetaData(meta))
374387
self.ext_fname = ext_fname
375388
self.ext_offset = ext_offset
376389
self.dims = [] if self.data is None else list(self.data.shape)
@@ -526,12 +539,12 @@ def print_summary(self):
526539
"Use the metadata property instead.",
527540
'2.1', '4.0')
528541
def get_metadata(self):
529-
return self.meta.metadata
542+
return dict(self.meta)
530543

531544
@property
532545
def metadata(self):
533546
""" Returns metadata as dictionary """
534-
return self.meta.metadata
547+
return dict(self.meta)
535548

536549

537550
class GiftiImage(xml.XmlSerializable, SerializableImage):

nibabel/gifti/parse_gifti_fast.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import numpy as np
1919

2020
from .gifti import (GiftiMetaData, GiftiImage, GiftiLabel,
21-
GiftiLabelTable, GiftiNVPairs, GiftiDataArray,
21+
GiftiLabelTable, GiftiDataArray,
2222
GiftiCoordSystem)
2323
from .util import (array_index_order_codes, gifti_encoding_codes,
2424
gifti_endian_codes)
@@ -202,7 +202,7 @@ def StartElementHandler(self, name, attrs):
202202
self.meta_da = GiftiMetaData()
203203

204204
elif name == 'MD':
205-
self.nvpair = GiftiNVPairs()
205+
self.nvpair = ['', '']
206206
self.fsm_state.append('MD')
207207

208208
elif name == 'Name':
@@ -313,10 +313,11 @@ def EndElementHandler(self, name):
313313

314314
elif name == 'MD':
315315
self.fsm_state.pop()
316+
key, val = self.nvpair
316317
if self.meta_global is not None and self.meta_da is None:
317-
self.meta_global.data.append(self.nvpair)
318+
self.meta_global[key] = val
318319
elif self.meta_da is not None and self.meta_global is None:
319-
self.meta_da.data.append(self.nvpair)
320+
self.meta_da[key] = val
320321
# remove reference
321322
self.nvpair = None
322323

@@ -374,11 +375,11 @@ def flush_chardata(self):
374375
# Process data
375376
if self.write_to == 'Name':
376377
data = data.strip()
377-
self.nvpair.name = data
378+
self.nvpair[0] = data
378379

379380
elif self.write_to == 'Value':
380381
data = data.strip()
381-
self.nvpair.value = data
382+
self.nvpair[1] = data
382383

383384
elif self.write_to == 'DataSpace':
384385
data = data.strip()

0 commit comments

Comments
 (0)