|
1 | 1 | from dateutil.parser import parse as dateutil_parse |
| 2 | +import typing |
2 | 3 |
|
3 | | -from hdmf.build import ObjectMapper |
| 4 | +from hdmf.build import ObjectMapper, Builder, GroupBuilder |
| 5 | +from hdmf.utils import docval, get_docval |
4 | 6 |
|
5 | 7 | from .. import register_map |
6 | 8 | from ..file import NWBFile, Subject |
@@ -130,6 +132,34 @@ def __init__(self, spec): |
130 | 132 | self.map_spec('scratch_containers', scratch_spec.get_neurodata_type('NWBContainer')) |
131 | 133 | self.map_spec('scratch_containers', scratch_spec.get_neurodata_type('DynamicTable')) |
132 | 134 |
|
| 135 | + @docval(*get_docval(ObjectMapper.construct)) |
| 136 | + def construct(self, **kwargs): |
| 137 | + nwbfile_builder = kwargs["builder"] |
| 138 | + electrodes_builder = nwbfile_builder.get("general", dict()).get("extracellular_ephys", dict()).get("electrodes") |
| 139 | + if (electrodes_builder is not None and electrodes_builder.attributes['neurodata_type'] != 'ElectrodesTable'): |
| 140 | + electrodes_builder.attributes['neurodata_type'] = 'ElectrodesTable' |
| 141 | + electrodes_builder.attributes['namespace'] = 'core' |
| 142 | + |
| 143 | + def apply_to_child_builders(builder: Builder, funcs: list[typing.Callable]): |
| 144 | + # iterate recursively through each builder (which is just a dict of dicts) and make migration changes |
| 145 | + for bchild_value in builder.values(): |
| 146 | + if isinstance(bchild_value, Builder): |
| 147 | + for func in funcs: |
| 148 | + func(bchild_value) |
| 149 | + apply_to_child_builders(bchild_value, funcs) |
| 150 | + |
| 151 | + def update_builder_frequency_bands_table(builder: Builder): |
| 152 | + if (isinstance(builder, GroupBuilder) and |
| 153 | + builder.attributes.get('namespace') == 'core' and |
| 154 | + builder.attributes.get('neurodata_type') == 'DecompositionSeries' and |
| 155 | + builder.groups['bands'].attributes['neurodata_type'] == 'DynamicTable'): |
| 156 | + builder.groups['bands'].attributes['neurodata_type'] = 'FrequencyBandsTable' |
| 157 | + builder.groups['bands'].attributes['namespace'] = 'core' |
| 158 | + |
| 159 | + apply_to_child_builders(nwbfile_builder, [update_builder_frequency_bands_table]) |
| 160 | + |
| 161 | + return super().construct(**kwargs) |
| 162 | + |
133 | 163 | @ObjectMapper.object_attr('scratch_datas') |
134 | 164 | def scratch_datas(self, container, manager): |
135 | 165 | """Set the value for the 'scratch_datas' spec on NWBFile to a list of ScratchData objects. |
@@ -185,24 +215,6 @@ def scratch(self, builder, manager): |
185 | 215 | ret.append(manager.construct(d)) |
186 | 216 | return tuple(ret) if len(ret) > 0 else None |
187 | 217 |
|
188 | | - @ObjectMapper.constructor_arg('electrodes') |
189 | | - def electrodes(self, builder, manager): |
190 | | - try: |
191 | | - electrodes_builder = builder['general']['extracellular_ephys']['electrodes'] |
192 | | - except KeyError: |
193 | | - # Note: This is here because the ObjectMapper pulls argname from docval and checks to see |
194 | | - # if there is an override even if the file doesn't have what is looking for. In this case, |
195 | | - # electrodes for NWBFile. |
196 | | - electrodes_builder = None |
197 | | - if (electrodes_builder is not None and electrodes_builder.attributes['neurodata_type'] != 'ElectrodesTable'): |
198 | | - electrodes_builder.attributes['neurodata_type'] = 'ElectrodesTable' |
199 | | - electrodes_builder.attributes['namespace'] = 'core' |
200 | | - manager.clear_cache() |
201 | | - new_container = manager.construct(electrodes_builder) |
202 | | - return new_container |
203 | | - else: |
204 | | - return None |
205 | | - |
206 | 218 | @ObjectMapper.constructor_arg('session_start_time') |
207 | 219 | def dateconversion(self, builder, manager): |
208 | 220 | """Set the constructor arg for 'session_start_time' to a datetime object. |
|
0 commit comments