diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_epoch.py index 33abf7e..ada000f 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_file.py index 3bd6ec5..548cc3b 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_file.py @@ -394,7 +394,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -403,7 +403,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -412,7 +412,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -421,7 +421,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel.""", json_schema_extra={ @@ -430,7 +430,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -439,7 +439,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, float] = Field( + filtering: VectorData[NDArray[Any, float]] = Field( ..., description="""Description of hardware filtering.""", json_schema_extra={ @@ -451,7 +451,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -460,7 +460,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -469,7 +469,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -478,7 +478,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -487,7 +487,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -501,7 +501,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_icephys.py index f09b466..86cbcb4 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_icephys.py @@ -864,7 +864,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -893,7 +893,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_misc.py index b1e0fe6..0e16f74 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_0/core_nwb_misc.py @@ -401,7 +401,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -410,7 +410,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -424,12 +424,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -439,7 +439,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -489,19 +489,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -530,16 +532,20 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") colnames: List[str] = Field( @@ -547,7 +553,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_epoch.py index 3e84ef3..92fd747 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_file.py index 199bbda..06fdd52 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_file.py @@ -394,7 +394,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -403,7 +403,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -412,7 +412,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -421,7 +421,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel.""", json_schema_extra={ @@ -430,7 +430,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -439,7 +439,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, float] = Field( + filtering: VectorData[NDArray[Any, float]] = Field( ..., description="""Description of hardware filtering.""", json_schema_extra={ @@ -451,7 +451,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -460,7 +460,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -469,7 +469,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -478,7 +478,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -487,7 +487,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -501,7 +501,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_icephys.py index 9c49daa..d004723 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_icephys.py @@ -864,7 +864,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -893,7 +893,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_misc.py index c547aef..cf92403 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_1/core_nwb_misc.py @@ -401,7 +401,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -410,7 +410,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -424,12 +424,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -439,7 +439,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -489,19 +489,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -530,16 +532,20 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") colnames: List[str] = Field( @@ -547,7 +553,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_epoch.py index 35bfa64..215cca6 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_file.py index c05c351..5d28191 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_file.py @@ -394,7 +394,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -403,7 +403,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -412,7 +412,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -421,7 +421,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel.""", json_schema_extra={ @@ -430,7 +430,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -439,7 +439,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, float] = Field( + filtering: VectorData[NDArray[Any, float]] = Field( ..., description="""Description of hardware filtering.""", json_schema_extra={ @@ -451,7 +451,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -460,7 +460,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -469,7 +469,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -478,7 +478,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -487,7 +487,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -501,7 +501,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_icephys.py index 5cc88ed..cb14508 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_icephys.py @@ -864,7 +864,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -893,7 +893,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_misc.py index 1f41641..6e8daf9 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_2/core_nwb_misc.py @@ -401,7 +401,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -410,7 +410,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -424,12 +424,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -439,7 +439,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -489,19 +489,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -530,16 +532,20 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") colnames: List[str] = Field( @@ -547,7 +553,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_epoch.py index 8012a74..e216685 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_file.py index 24f0613..e70c2dc 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_file.py @@ -370,7 +370,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -379,7 +379,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -388,7 +388,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -397,7 +397,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel.""", json_schema_extra={ @@ -406,7 +406,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -415,7 +415,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, float] = Field( + filtering: VectorData[NDArray[Any, float]] = Field( ..., description="""Description of hardware filtering.""", json_schema_extra={ @@ -427,7 +427,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -436,7 +436,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -445,7 +445,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -454,7 +454,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -463,7 +463,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -477,7 +477,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_icephys.py index 4272b2e..98b68dc 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_icephys.py @@ -864,7 +864,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -893,7 +893,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_misc.py index dc6d0a6..1a7a26a 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_misc.py @@ -401,7 +401,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -410,7 +410,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -424,12 +424,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -439,7 +439,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -489,19 +489,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -530,16 +532,20 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") colnames: List[str] = Field( @@ -547,7 +553,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_ophys.py index d7adad4..54b8b6a 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_4/core_nwb_ophys.py @@ -369,7 +369,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_epoch.py index 4a4f076..3bee6b5 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_file.py index 21932b7..5f22cff 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_file.py @@ -370,7 +370,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -379,7 +379,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -388,7 +388,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -397,7 +397,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel.""", json_schema_extra={ @@ -406,7 +406,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -415,7 +415,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, float] = Field( + filtering: VectorData[NDArray[Any, float]] = Field( ..., description="""Description of hardware filtering.""", json_schema_extra={ @@ -427,7 +427,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -436,7 +436,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -445,7 +445,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -454,7 +454,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -463,7 +463,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -477,7 +477,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_icephys.py index 2dd0607..220fc73 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_icephys.py @@ -864,7 +864,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -893,7 +893,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_misc.py index b9ef472..4a2cdd6 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_misc.py @@ -401,7 +401,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -410,7 +410,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -424,12 +424,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -439,7 +439,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -489,19 +489,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -530,16 +532,20 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") colnames: List[str] = Field( @@ -547,7 +553,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_ophys.py index 1b006ba..4e95539 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_2_5/core_nwb_ophys.py @@ -371,7 +371,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_epoch.py index ff49854..fd6ff0a 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_file.py index dcd3d20..4fbd77b 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_file.py @@ -370,7 +370,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -379,7 +379,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -388,7 +388,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -397,7 +397,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel, in ohms.""", json_schema_extra={ @@ -406,7 +406,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -415,7 +415,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, float] = Field( + filtering: VectorData[NDArray[Any, float]] = Field( ..., description="""Description of hardware filtering, including the filter name and frequency cutoffs.""", json_schema_extra={ @@ -427,7 +427,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -436,7 +436,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -445,7 +445,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -454,7 +454,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -463,7 +463,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -477,7 +477,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_icephys.py index bac67ab..95dc2af 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_icephys.py @@ -866,7 +866,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -895,7 +895,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_misc.py index 6e382f4..f0e9795 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_misc.py @@ -413,7 +413,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -422,7 +422,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -436,12 +436,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -451,7 +451,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -498,19 +498,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -539,26 +541,32 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") - waveforms: Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]] = Field( - None, - description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", - json_schema_extra={ - "linkml_meta": { - "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} - } - }, + waveforms: VectorData[Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]]] = ( + Field( + None, + description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", + json_schema_extra={ + "linkml_meta": { + "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} + } + }, + ) ) waveforms_index: Named[Optional[VectorIndex]] = Field( None, @@ -589,7 +597,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_ophys.py index 637d869..ee291fb 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_3_0/core_nwb_ophys.py @@ -380,7 +380,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_base.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_base.py index 2b85c2f..2328c2c 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_base.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_base.py @@ -5,7 +5,20 @@ from enum import Enum import re import sys import numpy as np -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, overload, Iterable, Tuple +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from pydantic import BaseModel, ConfigDict, Field, RootModel, field_validator, model_validator from ...hdmf_common.v1_5_0.hdmf_common_base import Data, Container from numpydantic import NDArray, Shape @@ -58,8 +71,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -67,7 +82,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -125,6 +140,9 @@ class TimeSeriesReferenceVectorDataMixin(VectorDataMixin): @model_validator(mode="after") def ensure_equal_length(self) -> "TimeSeriesReferenceVectorDataMixin": + """ + Each of the three indexing columns must be the same length to work! + """ assert len(self.idx_start) == len(self.timeseries) == len(self.count), ( f"Columns have differing lengths: idx: {len(self.idx_start)}, count: {len(self.count)}," f" timeseries: {len(self.timeseries)}" diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_epoch.py index c4415c8..31033ca 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -164,7 +164,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_file.py index 8ddb92c..bc2132e 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_file.py @@ -378,7 +378,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: NDArray[Any, float] = Field( + x: VectorData[NDArray[Any, float]] = Field( ..., description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -387,7 +387,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: NDArray[Any, float] = Field( + y: VectorData[NDArray[Any, float]] = Field( ..., description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -396,7 +396,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: NDArray[Any, float] = Field( + z: VectorData[NDArray[Any, float]] = Field( ..., description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -405,7 +405,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: NDArray[Any, float] = Field( + imp: VectorData[NDArray[Any, float]] = Field( ..., description="""Impedance of the channel, in ohms.""", json_schema_extra={ @@ -414,7 +414,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -423,7 +423,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: NDArray[Any, str] = Field( + filtering: VectorData[NDArray[Any, str]] = Field( ..., description="""Description of hardware filtering, including the filter name and frequency cutoffs.""", json_schema_extra={ @@ -435,7 +435,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -444,7 +444,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -453,7 +453,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -462,7 +462,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -471,7 +471,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference used for this electrode.""", json_schema_extra={ @@ -485,7 +485,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_icephys.py index cd08504..10cce5d 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_icephys.py @@ -873,7 +873,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -902,7 +902,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -939,7 +939,7 @@ class IntracellularElectrodesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -985,7 +985,7 @@ class IntracellularStimuliTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1031,7 +1031,7 @@ class IntracellularResponsesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1097,7 +1097,7 @@ class IntracellularRecordingsTable(AlignedDynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1146,7 +1146,7 @@ class SimultaneousRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1220,7 +1220,7 @@ class SequentialRecordingsTable(DynamicTable): } }, ) - stimulus_type: NDArray[Any, str] = Field( + stimulus_type: VectorData[NDArray[Any, str]] = Field( ..., description="""The type of stimulus used for the sequential recording.""", json_schema_extra={ @@ -1234,7 +1234,7 @@ class SequentialRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1313,7 +1313,7 @@ class RepetitionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1394,7 +1394,7 @@ class ExperimentalConditionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_misc.py index 7c6183f..5a64e12 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_misc.py @@ -413,7 +413,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -422,7 +422,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -436,12 +436,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -451,7 +451,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -498,19 +498,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -539,26 +541,32 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") - waveforms: Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]] = Field( - None, - description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", - json_schema_extra={ - "linkml_meta": { - "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} - } - }, + waveforms: VectorData[Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]]] = ( + Field( + None, + description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", + json_schema_extra={ + "linkml_meta": { + "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} + } + }, + ) ) waveforms_index: Named[Optional[VectorIndex]] = Field( None, @@ -589,7 +597,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_ophys.py index 96a8013..da2c58f 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_4_0/core_nwb_ophys.py @@ -380,7 +380,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_base.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_base.py index 7973568..d080acf 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_base.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_base.py @@ -16,12 +16,13 @@ from typing import ( Dict, Optional, Union, - overload, + Generic, Iterable, Tuple, + TypeVar, + overload, Annotated, Type, - TypeVar, ) from pydantic import ( BaseModel, @@ -81,8 +82,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -90,7 +93,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -148,6 +151,9 @@ class TimeSeriesReferenceVectorDataMixin(VectorDataMixin): @model_validator(mode="after") def ensure_equal_length(self) -> "TimeSeriesReferenceVectorDataMixin": + """ + Each of the three indexing columns must be the same length to work! + """ assert len(self.idx_start) == len(self.timeseries) == len(self.count), ( f"Columns have differing lengths: idx: {len(self.idx_start)}, count: {len(self.count)}," f" timeseries: {len(self.timeseries)}" diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_epoch.py index 6091bbf..fd5f403 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -173,7 +173,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_file.py index e09f4fb..ae0ce47 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_file.py @@ -381,7 +381,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: Optional[NDArray[Any, float]] = Field( + x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -390,7 +390,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: Optional[NDArray[Any, float]] = Field( + y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -399,7 +399,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: Optional[NDArray[Any, float]] = Field( + z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -408,7 +408,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: Optional[NDArray[Any, float]] = Field( + imp: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""Impedance of the channel, in ohms.""", json_schema_extra={ @@ -417,7 +417,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -426,7 +426,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: Optional[NDArray[Any, str]] = Field( + filtering: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of hardware filtering, including the filter name and frequency cutoffs.""", json_schema_extra={ @@ -438,7 +438,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -447,7 +447,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -456,7 +456,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -465,7 +465,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -474,7 +474,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference electrode and/or reference scheme used for this electrode, e.g., \"stainless steel skull screw\" or \"online common average referencing\".""", json_schema_extra={ @@ -488,7 +488,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_icephys.py index a7175f4..4a7ccc2 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_icephys.py @@ -874,7 +874,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -903,7 +903,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -940,7 +940,7 @@ class IntracellularElectrodesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -986,7 +986,7 @@ class IntracellularStimuliTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1032,7 +1032,7 @@ class IntracellularResponsesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1098,7 +1098,7 @@ class IntracellularRecordingsTable(AlignedDynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1147,7 +1147,7 @@ class SimultaneousRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1221,7 +1221,7 @@ class SequentialRecordingsTable(DynamicTable): } }, ) - stimulus_type: NDArray[Any, str] = Field( + stimulus_type: VectorData[NDArray[Any, str]] = Field( ..., description="""The type of stimulus used for the sequential recording.""", json_schema_extra={ @@ -1235,7 +1235,7 @@ class SequentialRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1314,7 +1314,7 @@ class RepetitionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1395,7 +1395,7 @@ class ExperimentalConditionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_misc.py index e463240..5a7755b 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_misc.py @@ -413,7 +413,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -422,7 +422,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -436,12 +436,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -451,7 +451,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -498,19 +498,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -539,26 +541,32 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") - waveforms: Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]] = Field( - None, - description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", - json_schema_extra={ - "linkml_meta": { - "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} - } - }, + waveforms: VectorData[Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]]] = ( + Field( + None, + description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", + json_schema_extra={ + "linkml_meta": { + "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} + } + }, + ) ) waveforms_index: Named[Optional[VectorIndex]] = Field( None, @@ -589,7 +597,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_ophys.py index c80c328..268b313 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_5_0/core_nwb_ophys.py @@ -380,7 +380,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_base.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_base.py index 6cf4107..26677a0 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_base.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_base.py @@ -16,12 +16,13 @@ from typing import ( Dict, Optional, Union, - overload, + Generic, Iterable, Tuple, + TypeVar, + overload, Annotated, Type, - TypeVar, ) from pydantic import ( BaseModel, @@ -81,8 +82,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -90,7 +93,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -148,6 +151,9 @@ class TimeSeriesReferenceVectorDataMixin(VectorDataMixin): @model_validator(mode="after") def ensure_equal_length(self) -> "TimeSeriesReferenceVectorDataMixin": + """ + Each of the three indexing columns must be the same length to work! + """ assert len(self.idx_start) == len(self.timeseries) == len(self.count), ( f"Columns have differing lengths: idx: {len(self.idx_start)}, count: {len(self.count)}," f" timeseries: {len(self.timeseries)}" diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_epoch.py index 6095a6f..29ed69e 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -173,7 +173,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_file.py index 19bdf9c..db4b5ca 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_file.py @@ -381,7 +381,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: Optional[NDArray[Any, float]] = Field( + x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -390,7 +390,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: Optional[NDArray[Any, float]] = Field( + y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -399,7 +399,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: Optional[NDArray[Any, float]] = Field( + z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -408,7 +408,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: Optional[NDArray[Any, float]] = Field( + imp: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""Impedance of the channel, in ohms.""", json_schema_extra={ @@ -417,7 +417,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -426,7 +426,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: Optional[NDArray[Any, str]] = Field( + filtering: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of hardware filtering, including the filter name and frequency cutoffs.""", json_schema_extra={ @@ -438,7 +438,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -447,7 +447,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -456,7 +456,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -465,7 +465,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -474,7 +474,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference electrode and/or reference scheme used for this electrode, e.g., \"stainless steel skull screw\" or \"online common average referencing\".""", json_schema_extra={ @@ -488,7 +488,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_icephys.py index 731a452..b18f673 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_icephys.py @@ -874,7 +874,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -903,7 +903,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -940,7 +940,7 @@ class IntracellularElectrodesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -986,7 +986,7 @@ class IntracellularStimuliTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1032,7 +1032,7 @@ class IntracellularResponsesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1098,7 +1098,7 @@ class IntracellularRecordingsTable(AlignedDynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1147,7 +1147,7 @@ class SimultaneousRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1221,7 +1221,7 @@ class SequentialRecordingsTable(DynamicTable): } }, ) - stimulus_type: NDArray[Any, str] = Field( + stimulus_type: VectorData[NDArray[Any, str]] = Field( ..., description="""The type of stimulus used for the sequential recording.""", json_schema_extra={ @@ -1235,7 +1235,7 @@ class SequentialRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1314,7 +1314,7 @@ class RepetitionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1395,7 +1395,7 @@ class ExperimentalConditionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_misc.py index 18065b1..66dad75 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_misc.py @@ -413,7 +413,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -422,7 +422,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -436,12 +436,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -451,7 +451,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -498,19 +498,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -539,26 +541,32 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") - waveforms: Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]] = Field( - None, - description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", - json_schema_extra={ - "linkml_meta": { - "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} - } - }, + waveforms: VectorData[Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]]] = ( + Field( + None, + description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", + json_schema_extra={ + "linkml_meta": { + "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} + } + }, + ) ) waveforms_index: Named[Optional[VectorIndex]] = Field( None, @@ -589,7 +597,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_ophys.py index dc54f7c..7c3e17b 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_6_0_alpha/core_nwb_ophys.py @@ -479,7 +479,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_base.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_base.py index 430e080..096733f 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_base.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_base.py @@ -1,4 +1,9 @@ from __future__ import annotations +from datetime import datetime, date +from decimal import Decimal +from enum import Enum +import re +import sys import numpy as np from ...hdmf_common.v1_8_0.hdmf_common_base import Data, Container from numpydantic import NDArray, Shape @@ -11,18 +16,20 @@ from typing import ( Dict, Optional, Union, - overload, + Generic, Iterable, Tuple, + TypeVar, + overload, Annotated, Type, - TypeVar, ) from pydantic import ( BaseModel, ConfigDict, Field, RootModel, + field_validator, model_validator, ValidationInfo, BeforeValidator, @@ -75,8 +82,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -84,7 +93,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -142,6 +151,9 @@ class TimeSeriesReferenceVectorDataMixin(VectorDataMixin): @model_validator(mode="after") def ensure_equal_length(self) -> "TimeSeriesReferenceVectorDataMixin": + """ + Each of the three indexing columns must be the same length to work! + """ assert len(self.idx_start) == len(self.timeseries) == len(self.count), ( f"Columns have differing lengths: idx: {len(self.idx_start)}, count: {len(self.count)}," f" timeseries: {len(self.timeseries)}" diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_epoch.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_epoch.py index d10191e..1b07dac 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_epoch.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_epoch.py @@ -105,7 +105,7 @@ class TimeIntervals(DynamicTable): ) name: str = Field(...) - start_time: NDArray[Any, float] = Field( + start_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Start time of epoch, in seconds.""", json_schema_extra={ @@ -114,7 +114,7 @@ class TimeIntervals(DynamicTable): } }, ) - stop_time: NDArray[Any, float] = Field( + stop_time: VectorData[NDArray[Any, float]] = Field( ..., description="""Stop time of epoch, in seconds.""", json_schema_extra={ @@ -123,7 +123,7 @@ class TimeIntervals(DynamicTable): } }, ) - tags: Optional[NDArray[Any, str]] = Field( + tags: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""User-defined tags that identify or categorize events.""", json_schema_extra={ @@ -173,7 +173,7 @@ class TimeIntervals(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_file.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_file.py index 950faa5..20ea663 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_file.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_file.py @@ -389,7 +389,7 @@ class ExtracellularEphysElectrodes(DynamicTable): "linkml_meta": {"equals_string": "electrodes", "ifabsent": "string(electrodes)"} }, ) - x: Optional[NDArray[Any, float]] = Field( + x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate of the channel location in the brain (+x is posterior).""", json_schema_extra={ @@ -398,7 +398,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - y: Optional[NDArray[Any, float]] = Field( + y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate of the channel location in the brain (+y is inferior).""", json_schema_extra={ @@ -407,7 +407,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - z: Optional[NDArray[Any, float]] = Field( + z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate of the channel location in the brain (+z is right).""", json_schema_extra={ @@ -416,7 +416,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - imp: Optional[NDArray[Any, float]] = Field( + imp: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""Impedance of the channel, in ohms.""", json_schema_extra={ @@ -425,7 +425,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - location: NDArray[Any, str] = Field( + location: VectorData[NDArray[Any, str]] = Field( ..., description="""Location of the electrode (channel). Specify the area, layer, comments on estimation of area/layer, stereotaxic coordinates if in vivo, etc. Use standard atlas names for anatomical regions when possible.""", json_schema_extra={ @@ -434,7 +434,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - filtering: Optional[NDArray[Any, str]] = Field( + filtering: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of hardware filtering, including the filter name and frequency cutoffs.""", json_schema_extra={ @@ -446,7 +446,7 @@ class ExtracellularEphysElectrodes(DynamicTable): group: List[ElectrodeGroup] = Field( ..., description="""Reference to the ElectrodeGroup this electrode is a part of.""" ) - group_name: NDArray[Any, str] = Field( + group_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the ElectrodeGroup this electrode is a part of.""", json_schema_extra={ @@ -455,7 +455,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_x: Optional[NDArray[Any, float]] = Field( + rel_x: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""x coordinate in electrode group""", json_schema_extra={ @@ -464,7 +464,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_y: Optional[NDArray[Any, float]] = Field( + rel_y: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""y coordinate in electrode group""", json_schema_extra={ @@ -473,7 +473,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - rel_z: Optional[NDArray[Any, float]] = Field( + rel_z: VectorData[Optional[NDArray[Any, float]]] = Field( None, description="""z coordinate in electrode group""", json_schema_extra={ @@ -482,7 +482,7 @@ class ExtracellularEphysElectrodes(DynamicTable): } }, ) - reference: Optional[NDArray[Any, str]] = Field( + reference: VectorData[Optional[NDArray[Any, str]]] = Field( None, description="""Description of the reference electrode and/or reference scheme used for this electrode, e.g., \"stainless steel skull screw\" or \"online common average referencing\".""", json_schema_extra={ @@ -496,7 +496,7 @@ class ExtracellularEphysElectrodes(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_icephys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_icephys.py index 86754a8..6993568 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_icephys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_icephys.py @@ -874,7 +874,7 @@ class SweepTable(DynamicTable): ) name: str = Field(...) - sweep_number: NDArray[Any, int] = Field( + sweep_number: VectorData[NDArray[Any, int]] = Field( ..., description="""Sweep number of the PatchClampSeries in that row.""", json_schema_extra={ @@ -903,7 +903,7 @@ class SweepTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -940,7 +940,7 @@ class IntracellularElectrodesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -998,7 +998,7 @@ class IntracellularStimuliTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1044,7 +1044,7 @@ class IntracellularResponsesTable(DynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1110,7 +1110,7 @@ class IntracellularRecordingsTable(AlignedDynamicTable): ..., description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1159,7 +1159,7 @@ class SimultaneousRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1233,7 +1233,7 @@ class SequentialRecordingsTable(DynamicTable): } }, ) - stimulus_type: NDArray[Any, str] = Field( + stimulus_type: VectorData[NDArray[Any, str]] = Field( ..., description="""The type of stimulus used for the sequential recording.""", json_schema_extra={ @@ -1247,7 +1247,7 @@ class SequentialRecordingsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1326,7 +1326,7 @@ class RepetitionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -1407,7 +1407,7 @@ class ExperimentalConditionsTable(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_misc.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_misc.py index 2739d41..a30d3e0 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_misc.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_misc.py @@ -413,7 +413,7 @@ class DecompositionSeriesBands(DynamicTable): "bands", json_schema_extra={"linkml_meta": {"equals_string": "bands", "ifabsent": "string(bands)"}}, ) - band_name: NDArray[Any, str] = Field( + band_name: VectorData[NDArray[Any, str]] = Field( ..., description="""Name of the band, e.g. theta.""", json_schema_extra={ @@ -422,7 +422,7 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_limits: NDArray[Shape["* num_bands, 2 low_high"], float] = Field( + band_limits: VectorData[NDArray[Shape["* num_bands, 2 low_high"], float]] = Field( ..., description="""Low and high limit of each band in Hz. If it is a Gaussian filter, use 2 SD on either side of the center.""", json_schema_extra={ @@ -436,12 +436,12 @@ class DecompositionSeriesBands(DynamicTable): } }, ) - band_mean: NDArray[Shape["* num_bands"], float] = Field( + band_mean: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The mean Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, ) - band_stdev: NDArray[Shape["* num_bands"], float] = Field( + band_stdev: VectorData[NDArray[Shape["* num_bands"], float]] = Field( ..., description="""The standard deviation of Gaussian filters, in Hz.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_bands"}]}}}, @@ -451,7 +451,7 @@ class DecompositionSeriesBands(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -498,19 +498,21 @@ class Units(DynamicTable): } }, ) - obs_intervals: Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]] = Field( - None, - description="""Observation intervals for each unit.""", - json_schema_extra={ - "linkml_meta": { - "array": { - "dimensions": [ - {"alias": "num_intervals"}, - {"alias": "start_end", "exact_cardinality": 2}, - ] + obs_intervals: VectorData[Optional[NDArray[Shape["* num_intervals, 2 start_end"], float]]] = ( + Field( + None, + description="""Observation intervals for each unit.""", + json_schema_extra={ + "linkml_meta": { + "array": { + "dimensions": [ + {"alias": "num_intervals"}, + {"alias": "start_end", "exact_cardinality": 2}, + ] + } } - } - }, + }, + ) ) electrodes_index: Named[Optional[VectorIndex]] = Field( None, @@ -539,26 +541,32 @@ class Units(DynamicTable): electrode_group: Optional[List[ElectrodeGroup]] = Field( None, description="""Electrode group that each spike unit came from.""" ) - waveform_mean: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_mean: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform mean for each spike unit.""") - waveform_sd: Optional[ - Union[ - NDArray[Shape["* num_units, * num_samples"], float], - NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + waveform_sd: VectorData[ + Optional[ + Union[ + NDArray[Shape["* num_units, * num_samples"], float], + NDArray[Shape["* num_units, * num_samples, * num_electrodes"], float], + ] ] ] = Field(None, description="""Spike waveform standard deviation for each spike unit.""") - waveforms: Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]] = Field( - None, - description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", - json_schema_extra={ - "linkml_meta": { - "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} - } - }, + waveforms: VectorData[Optional[NDArray[Shape["* num_waveforms, * num_samples"], float]]] = ( + Field( + None, + description="""Individual waveforms for each spike on each electrode. This is a doubly indexed column. The 'waveforms_index' column indexes which waveforms in this column belong to the same spike event for a given unit, where each waveform was recorded from a different electrode. The 'waveforms_index_index' column indexes the 'waveforms_index' column to indicate which spike events belong to a given unit. For example, if the 'waveforms_index_index' column has values [2, 5, 6], then the first 2 elements of the 'waveforms_index' column correspond to the 2 spike events of the first unit, the next 3 elements of the 'waveforms_index' column correspond to the 3 spike events of the second unit, and the next 1 element of the 'waveforms_index' column corresponds to the 1 spike event of the third unit. If the 'waveforms_index' column has values [3, 6, 8, 10, 12, 13], then the first 3 elements of the 'waveforms' column contain the 3 spike waveforms that were recorded from 3 different electrodes for the first spike time of the first unit. See https://nwb-schema.readthedocs.io/en/stable/format_description.html#doubly-ragged-arrays for a graphical representation of this example. When there is only one electrode for each unit (i.e., each spike time is associated with a single waveform), then the 'waveforms_index' column will have values 1, 2, ..., N, where N is the number of spike events. The number of electrodes for each spike event should be the same within a given unit. The 'electrodes' column should be used to indicate which electrodes are associated with each unit, and the order of the waveforms within a given unit x spike event should be in the same order as the electrodes referenced in the 'electrodes' column of this table. The number of samples for each waveform must be the same.""", + json_schema_extra={ + "linkml_meta": { + "array": {"dimensions": [{"alias": "num_waveforms"}, {"alias": "num_samples"}]} + } + }, + ) ) waveforms_index: Named[Optional[VectorIndex]] = Field( None, @@ -589,7 +597,7 @@ class Units(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_ophys.py b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_ophys.py index 04dcee9..e17fe42 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_ophys.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/core/v2_7_0/core_nwb_ophys.py @@ -479,7 +479,7 @@ class PlaneSegmentation(DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py index 9d5b38f..4676d58 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py @@ -5,7 +5,20 @@ from enum import Enum import re import sys import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -67,8 +80,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -76,7 +91,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -119,13 +134,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -406,20 +421,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -569,6 +592,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -698,7 +747,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py index 825e522..5066800 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py @@ -5,7 +5,20 @@ from enum import Enum import re import sys import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -67,8 +80,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -76,7 +91,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -119,13 +134,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -406,20 +421,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -569,6 +592,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -698,7 +747,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py index e837810..02d0686 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py @@ -5,7 +5,20 @@ from enum import Enum import re import sys import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -67,8 +80,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -76,7 +91,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -119,13 +134,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -406,20 +421,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -569,6 +592,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -717,7 +766,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py index 7c232b0..2d3ccc4 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_2_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -711,7 +760,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py index 9c4e909..df0d847 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_2_1.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -711,7 +760,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py index f77e052..7d465e2 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_3_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -711,7 +760,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py index 6514e14..47400e6 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_4_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from numpydantic import NDArray, Shape from pydantic import ( BaseModel, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -685,7 +734,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py index b64b835..92c5eeb 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_5_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from pydantic import ( BaseModel, ConfigDict, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -685,7 +734,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -713,7 +762,7 @@ class AlignedDynamicTable(AlignedDynamicTableMixin, DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py index 3593099..755b884 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_5_1.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from pydantic import ( BaseModel, ConfigDict, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -685,7 +734,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -713,7 +762,7 @@ class AlignedDynamicTable(AlignedDynamicTableMixin, DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py index b5d6b93..63d007d 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_6_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from pydantic import ( BaseModel, ConfigDict, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -685,7 +734,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -713,7 +762,7 @@ class AlignedDynamicTable(AlignedDynamicTableMixin, DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py index 51820ad..4be797e 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py @@ -6,7 +6,20 @@ import re import sys from ...hdmf_common.v1_7_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Literal, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from pydantic import ( BaseModel, ConfigDict, @@ -68,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -77,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -120,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -407,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -570,6 +593,32 @@ class AlignedDynamicTableMixin(DynamicTableMixin): df.set_index((self.name, "id"), drop=True, inplace=True) return df + @model_validator(mode="before") + @classmethod + def create_categories(cls, model: Dict[str, Any]) -> Dict: + """ + Construct categories from arguments. + + the model dict is ordered after python3.6, so we can use that minus + anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order + """ + if "categories" not in model: + categories = [ + k for k in model if k not in cls.NON_CATEGORY_FIELDS and not k.endswith("_index") + ] + model["categories"] = categories + else: + # add any columns not explicitly given an order at the end + categories = [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["categories"] + ] + model["categories"].extend(categories) + return model + linkml_meta = LinkMLMeta( { @@ -685,7 +734,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -713,7 +762,7 @@ class AlignedDynamicTable(AlignedDynamicTableMixin, DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py index 6104fd5..c1b0a8d 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py @@ -1,7 +1,25 @@ from __future__ import annotations -from ...hdmf_common.v1_8_0.hdmf_common_base import Data +from datetime import datetime, date +from decimal import Decimal +from enum import Enum +import re +import sys +from ...hdmf_common.v1_8_0.hdmf_common_base import Data, Container import pandas as pd -from typing import Any, ClassVar, List, Dict, Optional, Union, Iterable, Tuple, overload +from typing import ( + Any, + ClassVar, + List, + Literal, + Dict, + Optional, + Union, + Generic, + Iterable, + Tuple, + TypeVar, + overload, +) from pydantic import ( BaseModel, ConfigDict, @@ -63,8 +81,10 @@ class LinkMLMeta(RootModel): NUMPYDANTIC_VERSION = "1.2.1" +T = TypeVar("T", bound=NDArray) -class VectorDataMixin(BaseModel): + +class VectorDataMixin(BaseModel, Generic[T]): """ Mixin class to give VectorData indexing abilities """ @@ -72,7 +92,7 @@ class VectorDataMixin(BaseModel): _index: Optional["VectorIndex"] = None # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): if value is not None and "value" not in kwargs: @@ -115,13 +135,13 @@ class VectorDataMixin(BaseModel): return len(self.value) -class VectorIndexMixin(BaseModel): +class VectorIndexMixin(BaseModel, Generic[T]): """ Mixin class to give VectorIndex indexing abilities """ # redefined in `VectorData`, but included here for testing and type checking - value: Optional[NDArray] = None + value: Optional[T] = None target: Optional["VectorData"] = None def __init__(self, value: Optional[NDArray] = None, **kwargs): @@ -402,20 +422,28 @@ class DynamicTableMixin(BaseModel): anything in :attr:`.NON_COLUMN_FIELDS` to determine order implied from passage order """ if "colnames" not in model: - colnames = [ - k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - ] - model["colnames"] = colnames - else: - # add any columns not explicitly given an order at the end colnames = [ k for k in model if k not in cls.NON_COLUMN_FIELDS and not k.endswith("_index") - and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) ] - model["colnames"].extend(colnames) + model["colnames"] = colnames + else: + # add any columns not explicitly given an order at the end + colnames = model["colnames"].copy() + colnames.extend( + [ + k + for k in model + if k not in cls.NON_COLUMN_FIELDS + and not k.endswith("_index") + and k not in model["colnames"] + and not isinstance(model[k], VectorIndexMixin) + ] + ) + model["colnames"] = colnames return model @model_validator(mode="after") @@ -706,7 +734,7 @@ class DynamicTable(DynamicTableMixin): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}}, @@ -734,7 +762,7 @@ class AlignedDynamicTable(AlignedDynamicTableMixin, DynamicTable): description="""The names of the columns in this table. This should be used to specify an order to the columns.""", ) description: str = Field(..., description="""Description of what is in this dynamic table.""") - id: NDArray[Shape["* num_rows"], int] = Field( + id: VectorData[NDArray[Shape["* num_rows"], int]] = Field( ..., description="""Array of unique identifiers for the rows of this dynamic table.""", json_schema_extra={"linkml_meta": {"array": {"dimensions": [{"alias": "num_rows"}]}}},