apjanke / octave-tablicious

Table (relational, tabular data) implementation for GNU Octave
https://apjanke.github.io/octave-tablicious/
GNU General Public License v3.0
29 stars 11 forks source link

calling table2cell method and table file I/O #105

Closed snk4tr closed 8 months ago

snk4tr commented 1 year ago

Dear @apjanke, thank you for your great contribution with the tablicious library.

As a newbie with Matlab/Octave, I have a question running the table2cell method. My end goal is to just run some .m file with Octave with minimal edits of the initial functionality. Some of the methods there are not implemented in Octave so your library is really handy (e.g. the table2cell method). I am doing the following:

pkg install https://github.com/apjanke/octave-tablicious/releases/download/v0.3.7/tablicious-0.3.7.tar.gz
pkg load tablicious
run("myFile.m")

>>> error: 'table2cell' undefined near line 9, column 6
The ’table2cell’ function is not yet implemented in Octave.

While this trick worked with the io package, here it looks like Octave does not see the tablicious package. In the documentation I found that the table2cell method is a part of the table subpackage so I also tried to import is as tablicious.table or modify the initial Matlab code to call the table2cell method as table.table2cell. Neither tricks worked. Could you please assist me with the issue? How do I replace the standard table2cell method with your implementation in the tablicious package? Thank you!

apjanke commented 1 year ago

Hi, @snk4tr ! Thanks for using Tablicious.

In Tablicious, tablicious.table is not a subpackage you can import; table is a class provided by the Tablicious package, and it lives in the global namespace. The tablicious namespace (the stuff in the +tablicious/ subdirectory) is for Tablicious's internal use, and you as a user of Tablicious should not have to interact with it direcly.

In Tablicious, table2cell is not implemented as a function (because I did not want to stomp on that name in the global namespace), but as a method on the table class. Which means you can only call it on Tablicious table objects. If you're getting that "table2cell undefined" error, that probably means that the value or object you are passing to it is not a Tablicious table object. So instead of calling the table2cell method on the table class in the Tablicious package, you are hitting the table2cell "stub" function in core Octave, which is just a little placeholder that tells you "this function doesn't exist yet".

If you want to use Tablicious's table2cell, make sure that what you are passing to it is a Tablicious table object. Tablicious doesn't support table-like objects from other packages or whatever. Like this:

>> tb = table(420)
tb =
table: 1 rows x 1 variables
  VariableNames: Var1
>> c = table2cell(tb)
c =
{
  [1,1] = 420
}

>>

Can you maybe share your myFile.m file so I can see exactly what is being constructed that you're trying to call table2cell on?

I don't think that Tablicious can really provide a table2cell function that works on data structures from other packages or whatever: that behavior depends somewhat on the internal representation of those objects, and as far as I know, the Octave developer community hasn't standardized around a common tabular or similar interface to write generic functions against.

snk4tr commented 1 year ago

Thank you for your quick response @apjanke! Here is the initial code that uses the table2cell function:

tb = readtable('kadis700k_ref_imgs.csv');
tb = table2cell(tb);

for i = 1:size(tb,1)
    ref_im = imread(['ref_imgs/' tb{i,1}]);
    dist_type = tb{i,2};

    for dist_level = 1:5
        [dist_im] = imdist_generator(ref_im, dist_type, dist_level);
        strs = split(tb{i,1},'.');
        dist_im_name = [strs{1}  '_' num2str(tb{i,2},'%02d')  '_' num2str(dist_level,'%02d') '.bmp'];
        disp(dist_im_name);
        imwrite(dist_im, ['dist_imgs/' dist_im_name]);
    end
end

As I already figured out, the readtable is also not implemented in Octave so I replaced it with the xlsread package:

tb = xlsread('kadis700k_ref_imgs.csv');
tb = table2cell(tb);

The rest of the code stays the same. With your explanation is becomes clear that I need to either read the .csv file with some function from the tablicious library that returns the table object or somehow cast the object returned by xlsread. How could any of these be done?

apjanke commented 1 year ago

Yep! The tabular file I/O functions like readtable are still on my to-do list for Tablicious (https://github.com/apjanke/octave-tablicious/issues/49), but if you can read in the data with Octave or io's csvread, xlsread, or textscan functions, then you can convert it to a table by passing the data to Tablicious's array2table or cell2table functions, or to table's constructor, probably using its form where you pass in the optional VariableNames argument in addition to the data.

Exactly which of those functions you should use depends on the specific format of the data in your CSV file. If you want to show me the first few lines of it, I could probably whip up a little script for you that does the whole thing. If it's xlsread you're using like in your example, you probably want array2table. But if your CSV file has a header line with column names in it, you might need to do textscan instead, and then either cell2table or array2table.

apjanke commented 8 months ago

Hi, @snk4tr,

Are your questions here aside from the I/O functions themselves answered? I think I'm going to close this as a duplicate of https://github.com/apjanke/octave-tablicious/issues/49 and handle table I/O development over there; head on over there if you want to follow its progress.