1

I m using ILNumerics to read and write from/to matfiles. I get some data from a database as object[,] because it contains numbers and headings (strings).

The data structure of object[,] loaddata is a mixture of System.String and System.Double, first two columns and first row contains strings rest doubles. I want to write the doubles into the matfile. Dimensions are roughly loaddata[9000,500].

This is my very cumbersome detour via system arrays that doesnt even work:

ILArray<object> loaddata = DBQuery(....);
//this next line has error
var tempoobj = ToSystemMatrix<object>(loaddata["2:end", "1:end"]);
double[,] tempdouble = new double[500, 8784];
Array.Copy(tempoobj, tempdouble, tempoobj.Length);
ILArray<double> B = tempdouble;
using (ILMatFile matW = new ILMatFile())
{
      B.Name = "power";
      matW.AddArray(B);
      matW.Write(@"C:\Temp\Test.mat");
}

with the ToSystemMatrix function from here How to convert ILArray into double[,] array? - which I couldnt make work.

any ideas how to simplify this? and also how to make that function work (as it is usefull anyways).

UPDATE

I made this work but it feels like going at it with a sledgehammer.... But here it comes:

       object[,] loaddata = DBQuery(...);

        for (int i = 0; i < loaddata.GetLength(0); i++)
        {
            loaddata[i, 0] = Convert.ToDouble(0);
            loaddata[i, 1] = Convert.ToDouble(0);
        }
        for (int i = 0; i < loaddata.GetLength(1); i++)
        {
            loaddata[0, i] = Convert.ToDouble(0);
        }

        double[,] tempdouble = new double[loaddata.GetLength(0), loaddata.GetLength(1)];
        Array.Copy(loaddata, tempdouble, loaddata.Length);
        ILArray<double> B = tempdouble;


        using (ILMatFile matW = new ILMatFile())
        {
            B.Name = "power";
            matW.AddArray(B["1:end","2:end"].T);
            matW.Write(@"C:\Temp\Test.mat");
        }

I also tried to use ILCell instead but ILCell loaddata = DBQuery(...) and cell(loaddata) threw errors.

Any ideas how to make this more neat?

Community
  • 1
  • 1
nik
  • 1,672
  • 2
  • 17
  • 36
  • Could you give an example of how your `ILArray` data is structured? – decPL Sep 25 '14 at 12:30
  • please see second paragraph in question – nik Sep 25 '14 at 13:26
  • I have limited understanding of how ILNumerics work, what type of object is in your array? I.e. could you show the output of `loaddata.First().GetType()`? – decPL Sep 25 '14 at 13:30
  • @decPL: sorry maybe I dont get it but I did run what you said and also loaddata.Last().GetType() and as said in second paragraph the underlying types are System.String and System.Double. Or what do you mean? Sorry I m still a learner and any help is appreciated! – nik Sep 25 '14 at 14:30
  • no worries, we're all learning every day (I'm learning about ILNumerics now it seems ;) ). Basically I need to know - how would you translate a single entry in your `ILArray` to a double. If you know how to do this, doing it for the whole set seems quite trivial (and yes, I'm willing to share :P ). – decPL Sep 25 '14 at 14:34
  • I would appreciate if you comment and tell me why you voted the question down so that I can learn and improve. Thank you. – nik Sep 25 '14 at 14:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61916/discussion-between-nik-and-decpl). – nik Sep 25 '14 at 14:35
  • Does ILArray implement IEnumerable? I am asking because using LINQ might make your life easy there. – Aditya Patil Sep 25 '14 at 16:07
  • as far as I know it does – nik Sep 25 '14 at 16:24
  • Yes it does. But it obviously does not know the concept of multidimensionality. The enumerator rather goes straight along all elements in sequential (column major) order. – Haymo Kutschbach Sep 25 '14 at 21:04
  • Consider using `ILCell` rather than `ILArray` in order to store column headers and data in the same structure. See: [Cells](http://ilnumerics.net/Cells.html) – Haymo Kutschbach Sep 25 '14 at 21:05

2 Answers2

1

Change this line:

 var tempoobj = ToSystemMatrix<object>(loaddata["2:end", "1:end"]);

to

 var tempoobj = ToSystemMatrix<double>(loaddata["2:end", "1:end"]);

This assumes that you've selected only the part of loaddata where all the data are doubles.

KC-NH
  • 748
  • 3
  • 6
  • Your correction of using double for the generic type (rather than object) is correct. But ToSystemMatrix from the link given uses `Buffer.BlockCopy`. I would expect the elements in the `ILArray` to be *boxed double* elements. A simple byte copy will not unbox them? – Haymo Kutschbach Sep 25 '14 at 21:09
  • Thanks for your answer but this doesnt work, because the function expects double and i dont unbox anywhere. error: The best overloaded method match for 'ReadMatFileIL.Program.ToSystemMatrix(ILNumerics.ILInArray)' has some invalid arguments – nik Sep 26 '14 at 06:03
1

Consider rethinking your design. In order to return multiple information from DBQuery(....) you could either utilize ILCell or some other data structure which is able to store typed information about your headers and elements (let's say DataTable). Just object[,] seems too general.

Since I don't have specific information about your setup, I'll give one example for ILCell:

using ILNumerics;
using System;

namespace Cell_DBQuery_Example {
    class Program {
        static void Main(string[] args) {

            using (ILScope.Enter()) {
                ILCell data = Helper.DBQuery(); 
                // data is: 
                //Cell [2,2]
                //[0]: <String>           header 1  <Double> [100,200]           
                //[1]: <String>           header 2  <Single> [2,3000]  

                // store into mat file
                ILMatFile mat = new ILMatFile();
                var key1 = (string)data.GetArray<string>(0, 0); 
                mat.AddArray(data.GetArray<double>(0, 1), key1);  // stores rand(100,200) as key: "header1"
                // proceed with other columns...

                // write mat file
                mat.Write("filename"); 
            }
        }

        class Helper : ILMath {

            public static ILRetCell DBQuery() {
                using (ILScope.Enter()) {
                    // prepare return cell
                    ILCell ret = cell(size(2, 2)); 
                    // todo: fetch data from db and replace below example data
                    ret[0, 0] = "header_1";
                    ret[1, 0] = "header_2";
                    ret[0, 1] = rand(100, 200);
                    ret[1, 1] = ones<float>(2, 3000);
                    return ret; 
                }
            }
        }
    }
}

This creates and returns a cell in the Helper class. The cell contains the header and numeric data in seperate cell elements. It is than be used to retrieve the information from the cell and stores them into a mat file.

Some references: http://ilnumerics.net/Cells.html

http://ilnumerics.net/GeneralRules.html - general rules for ILNumerics functions

http://ilnumerics.net/hdf5-interface.html - more options of writing compatible formats: HDF5

Haymo Kutschbach
  • 3,322
  • 1
  • 17
  • 25