NeurodataWithoutBorders / matnwb

A Matlab interface for reading and writing NWB files
BSD 2-Clause "Simplified" License
50 stars 32 forks source link

[Bug]: Generation of table where there are colum names that don't correspond to any columns does not fail. #574

Open achilleasNP opened 3 months ago

achilleasNP commented 3 months ago

What happened?

I was allowed to create a types.hdmf_common.DynamicTable where one of the columns that were stated in colnames was not declared. An error was thrown only when trying to view the rows. I was expecting that creating the table would fail with an error.

Steps to Reproduce

col1 = types.hdmf_common.VectorData( ...
    'description', 'column #1', ...
    'data', [1;2;3] ...
    );

my_table = types.hdmf_common.DynamicTable( ...
    'description', 'an_example table', ...
    'colnames', {'col1', 'col2'}, ...
    'col1', col1, ...
    'id', types.hdmf_common.ElementIdentifiers('data', [0;1;2]) ...
    );
% The above works but then the statement below fails.
% my_table.getRow(1)

Error Message

No response

Operating System

Windows

Matlab Version

'24.1.0.2603908 (R2024a) Update 3'

Code of Conduct

ehennestad commented 3 months ago

I think that this does not fail because there are scenarios where you might want to declare a set of columns for a table and then gradually fill in column data as data becomes available.

The following statement would work: my_table.getRow(1, 'columns', {'col1'})

One thing that could be done is to generate a more specific error message when running my_table.getRow(1), for example:

There is no row data for the column named 'col2' instead of The specified key is not present in this container.

bendichter commented 2 weeks ago

Yes, we have this workflow in the intro tutorial:

trials = types.core.TimeIntervals( ...
    'colnames', {'start_time', 'stop_time', 'correct'}, ...
    'description', 'trial data and properties');

trials.addRow('start_time', 0.1, 'stop_time', 1.0, 'correct', false)
trials.addRow('start_time', 1.5, 'stop_time', 2.0, 'correct', true)
trials.addRow('start_time', 2.5, 'stop_time', 3.0, 'correct', false)

where the data is not added in the constructor. However, I do think it would be strange to add some columns in the constructor but not others. How would you add the other columns later? Is that possible right now?