-
Notifications
You must be signed in to change notification settings - Fork 84
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
[Docs]: Extra unsupplied attrs in VoltageClampStimulusSeries
, merge inheritance behavior needs more documentation
#1954
Comments
I can keep checking for these mismatches if you want, since my models are literal transcriptions of the schema, but also don't want to generate too much noise or be annoying, so just lmk Edit: I mean this in the sense of "I need to keep doing close reads of the schema because the models keep refusing to instantiate" not like "the models are perfect." Like "while im down here in the schema store yall want me to get anything" lol |
@sneakers-the-rat I believe it is the case that For the section of code you highlighted in Lines 171 to 172 in 2d00afe
TimeSeries , then that TimeSeries will be linked to so that the same data can be reused in multiple locations in the file.
|
ooh boy ok that's what i was afraid of. OK so just to be clear it's the case that if i do this: groups:
- neurodata_type_def: MyData
datasets:
- name: data
attributes:
- name: parent_attribute
dtype: float32
default_value: 1.0
- neurodata_type_def: MyChild
neurodata_type_inc: MyData
datasets:
- name: data
attributes:
- name: parent_attribute
dtype: text that we would expect all unset attributes to merge down into the child class and so here the That is not what i would have expected - i expect the inheritance from the parent class, but i did not expect that it would also recursively merge all properties, where even if i override a dataset, group, or attribute, the rest of the values come along with it. The docs could be clearer on this, and i am not sure that happens uniformly throughout the schema but i'll check Re: being able to use a |
The main reason is because otherwise this would break compliance with the base type. I.e., if |
Yes yes, inheritance is to be expected from the docs, i sort of assumed monotonicity (though that could be made more explicitly in the docs). The thing that is surprising to me here is that the inheritance is recursive through overrides. So i would imagine it working analogously to this: from dataclasses import dataclass
@dataclass
class TimeSeries:
data: 'Data'
timestamps: list[float]
# and the rest of the attrs/datasets/groups...
@dataclass
class Data:
conversion: float = 1.0
offset: float = 0.0
resolution: float = -1.0
unit: str
@dataclass
class VoltageClampStimulusSeries(TimeSeries):
data: 'Data'
# we have the rest of the top-level fields like timestamps here from inheritance
@dataclass
class Data:
unit: str = "float"
# because `Data` is defined locally within TimeSeries and VoltageClampStimulusSeries,
# we don't inherit the `conversion`, `offset`, and `resolution` Where This part is really no problem for me, because i have models for all the schema language elements and the adapter classes already have My question there is whether i should do that with everything in the parent model? like every field in every attr, dataset, and group should merge downwards recursively unless each individual field is overridden/refined by the child model? Can I draft some language for the docs that clarifies this? would like to help clear things up for the next person :) being the dogfood eater that helps find places that aren't obvious externally but might be obvious internally. The other behavior of @dataclass
class TimeSeriesData:
# the fields from the TimeSeries.data dataset...
@dataclass
class TimeSeries:
data: Union[TimeSeriesData, "TimeSeries"] I can see something like a subclass being able to refine the Or is it the case that just means something like this ts_a = TimeSeries(...)
ts_b = TimeSeries(data=ts_a.data) which would be fine and wouldn't require any changes for me, since I am reading by doing a reverse topological sort on the dependency graph of the datasets, resolving hardlinks, and so If it's the latter, then that's fine, just an optimization thing that's within schema, but lmk if it's the former bc i'll have to inspect all the signatures in pynwb and add all those extra ranges to my models. |
Implementing this now, and i'm struggling a bit - some properties seem to be recursively rolled down and merged and others don't. For example, Line 617 in b9f9e5a
doc value. it seems like it is only rolling down the data field (from get_docval ) but providing its own override of default manually.
when they are in conflict, should i prefer the API's implementation or the schema? |
VoltageClampStimulusSeries
VoltageClampStimulusSeries
, merge inheritance behavior needs more documentation
Another example where i am actually not sure what the expected behavior should be - when recursively rolling down inheritance, i am assuming that when a property is not set in the child, it should receive the last-set value from the parent(s). The
and pynwb indeed has The definition of When rolling down, though, it does receive a value for quantity from the parent class, so my baseline expectation would be that one would need to explicitly set the value to override it. I think it would be fine to have default values bind more tightly on the child classes, so default values override values from the parents, but then what about the other properties that have defaults? ctrl+f'ing through the documentation these are the properties that have some notion of default:
If the rule for tight binding on So trying to come up with a description of the inheritance behavior, am i correct here: default values that are not null take precedence over those inherited from the parent class? or is Additionally, why does the whole |
OK I believe this captures the inheritance behavior:
if that seems right, i'd be happy to contribute to the docs to clarify the inheritance behavior |
What happened?
Validating
nwb_linkml
&nwb_models
against live and synthetic data, and it looks likeVoltageClampStimulusSeries
adds additional attributes into thedata
dataset, and the validator doesn't catch it.In
core
version2.7.0
,VoltageClampStimulusSeries.data
is:and yet my generated dataset has
conversion = 1.0
,offset=0.0
, andresolution=-1.0
in it.This appears to come from how
PatchClampSeries.data
incorrectly specifies thatdata
is aTimeSeries.data
:pynwb/src/pynwb/icephys.py
Line 93 in 2d00afe
despite no such
neurodata_type_inc
existing in the schema.Unless it's the case that by doing
neurodata_type_inc
one is supposed to recursive merge all attributes in datasets and groups defined in inheriting classes, rather than overriding them, which would be... interesting.My MWE below is literally just following the docs example, so not too thrilling
Steps to Reproduce
Traceback
No response
Operating System
macOS
Python Executable
Python
Python Version
3.11
Package Versions
pynwb==2.8.1
hdmf==3.14.3
h5py==3.11.0
Code of Conduct
The text was updated successfully, but these errors were encountered: