Closed campagnola closed 4 years ago
From what I can tell, this can be expressed with the current schema language, i.e., you have a group for storing metadata that allows you to add zero or more metadata containers. I don't think we need to modify NWBContainer
for this (not all types need this feature) but you could just create a new base type that extends NWBContainer
The suggestion above was the result of a discussion I had with @ajtritt at the end of the hackathon. I actually do think all types need this support so that people writing their own metadata extensions are not tempted to use subclassing. If we continue down this path of subclassing, we will have many extensions created by the community that cannot be used together. At best, this will result in a lot of code duplication. At worst, this will discourage extension sharing and prevent further standardization.
The suggestion above also has some real benefits over simply making a metadata group:
image.has_interface('camera')
rather than iterating over a list of metadata objects and hoping to find the right thing.image.camera.exposure_time
rather than iterating over a list of metadata objects.
General Problem
There are several places in the schema where we run into problems caused by the use of class inheritance as the sole mechanism of extension. It is often desirable to have a class that combines properties from multiple superclasses, but it is not straightforward to achieve this combination without either modifying the core classes or duplicating code. Examples: #131 #129
The typical case that we have seen repeated is that a base class (such as ImageSeries, or PatchClampSeries) comes in many different varieties, and each one implies different types/combinations of metadata. Attempting to use an inheritance hierarchy to describe this variety leads to combinatorial explosion, so instead we need a compositional approach (for background read any of the many web articles on "inheritance vs composition").
A specific example
The core spec currently contains two classes
ImageSeries
andTwoPhotonSeries
, where the latter class inherits from the former and adds on metadata specific to a 2-photon imaging session, such asscan_line_rate
andpmt_gain
. Now we want to create a new classImage
that is just likeImageSeries
, but representing a single snapshot in time. Things get tricky from here:TwoPhotonSeries
to make a parallelTwoPhotonImage
class?The number of classes that would be needed to describe this combinatorial space grows multiplicatively with each new piece of metadata. A more natural approach is to simply say: we have a base
Image
class, and it contains any number of extra metadata pieces. However switching to a compositional approach requires careful consideration; we still want to have a strongly defined schema, and there are many different possible approaches to implementing composition.What kind of composition to use?
We want a solution with the following properties:
imageSeries
instance, and then attach to it metadata about a 2-photon imaging session.Proposed solution
Python API example:
A core spec modification is needed in order to store information about the interfaces attached to any object:
And the Interface objects created above would need to be described in the spec (core or extension) as well:
Open questions
TwoPhotonSeries
seems like a good candidate,CurrentClampSeries
,VoltageClampSeries
,CurrentClampStimulusSeries
, andVoltageClampStimulusSeries
are also possibilities.