Repository: physiopy/phys2bids

Issue:
Output files are not BIDS compliant
<!--- Provide a general summary of the issue in the Title above -->

## Expected Behavior
<!--- NECESSARY -->
<!--- Describe what one would expect from the buggy code -->
Following [BIDS 1.2.2](https://bids-specification.readthedocs.io/en/v1.2.2/), the `.tsv.gz` files should have a column for each channel.

## Actual Behavior
<!--- NECESSARY -->
<!--- Describe what the buggy code is actually doing/returning -->
<!--- Do not hesitate and share screenshots and code snippets that could help understand the issue -->
Our output has a row for each channel

## Possible solution
<!--- Describe a possible approach to solve the issue -->
We can solve this in two ways:
1. a very easy very quick `BlueprintOutput.timeseries` transpose before (during) the final export to `tsv`, or
2. a less easy, less quick inversion of `BlueprintOutput.timeseries` indexes, followed by adaptation of the scripts, so that `BlueprintOutput.timeseries` will be always created and managed as if we were importing a BIDS compliant `tsv` file.

I prefer option number 2, that could be a bit less easy, but will work very well in case we need to import files or we need this object to be used in other libraries that only import BIDS compliant files. But I'd like to know what y'all think (starting with code contributors @vinferrer @rmarkello @eurunuela)

(thanks to @sangfrois for pointing it out)

Discussion:

Patch:
diff --git a/phys2bids/phys2bids.py b/phys2bids/phys2bids.py
index bed7050..573bc64 100644
--- a/phys2bids/phys2bids.py
+++ b/phys2bids/phys2bids.py
@@ -348,7 +348,7 @@ def phys2bids(filename, info=False, indir='.', outdir='.', heur_file=None,
                 outfile = f'{outfile}_{uniq_freq}'
 
         LGR.info(f'Exporting files for freq {uniq_freq}')
-        savetxt(outfile + '.tsv.gz', phys_out[uniq_freq].timeseries.T,
+        savetxt(outfile + '.tsv.gz', phys_out[uniq_freq].timeseries,
                 fmt='%.8e', delimiter='\t')
         print_json(outfile, phys_out[uniq_freq].freq,
                    phys_out[uniq_freq].start_time,
diff --git a/phys2bids/physio_obj.py b/phys2bids/physio_obj.py
index 15fa8df..99d1587 100644
--- a/phys2bids/physio_obj.py
+++ b/phys2bids/physio_obj.py
@@ -379,7 +379,7 @@ class BlueprintOutput():
         int
             Number of channels
         """
-        return len(self.timeseries)
+        return self.timeseries.shape[1]
 
     def return_index(self, idx):
         """
@@ -397,7 +397,7 @@ class BlueprintOutput():
             Tuple containing the proper list entry of all the
             properties of the object with index `idx`
         """
-        return (self.timeseries[idx], self.ch_amount, self.freq,
+        return (self.timeseries[:, idx], self.ch_amount, self.freq,
                 self.ch_name[idx], self.units[idx], self.start_time)
 
     def delete_at_index(self, idx):
@@ -423,7 +423,7 @@ class BlueprintOutput():
             In all the property that are lists, the element correspondent to
             `idx` gets deleted
         """
-        self.timeseries = np.delete(self.timeseries, idx, axis=0)
+        self.timeseries = np.delete(self.timeseries, idx, axis=1)
         del self.ch_name[idx]
         del self.units[idx]
 
@@ -445,7 +445,7 @@ class BlueprintOutput():
         cls: :obj: `BlueprintOutput`
             Populated `BlueprintOutput` object.
         """
-        timeseries = np.asarray(blueprint.timeseries)
+        timeseries = np.asarray(blueprint.timeseries).T
         freq = blueprint.freq[0]
         ch_name = blueprint.ch_name
         units = blueprint.units


Test patch:
diff --git a/phys2bids/tests/test_physio_obj.py b/phys2bids/tests/test_physio_obj.py
index 488b374..f5cabaf 100644
--- a/phys2bids/tests/test_physio_obj.py
+++ b/phys2bids/tests/test_physio_obj.py
@@ -93,7 +93,7 @@ def test_BlueprintOutput():
     # Tests init_from_blueprint
     blueprint_out = po.BlueprintOutput.init_from_blueprint(blueprint_in)
     start_time = blueprint_out.start_time
-    assert (blueprint_out.timeseries == test_timeseries).all()
+    assert (blueprint_out.timeseries == np.asarray(test_timeseries).T).all()
     assert blueprint_out.freq == test_freq[0]
     assert blueprint_out.ch_name == test_chn_name
     assert blueprint_out.units == test_units
@@ -102,16 +102,16 @@ def test_BlueprintOutput():
     # Tests return_index
     test_timeseries = np.array([[0, 1, 1, 2, 3, 5, 8, 13],
                                 [0, 1, 0, 0, 0, 0, 0, 0],
-                                [1, 0, 0, 1, 0, 0, 1, 0]])
+                                [1, 0, 0, 1, 0, 0, 1, 0]]).T
     test_freq = 42.0
     test_chn_name = ['trigger', 'time', 'chocolate']
     test_units = ['s', 's', 'sweetness']
-    num_channnels = len(test_timeseries)
+    num_channnels = test_timeseries.shape[1]
     blueprint_out = po.BlueprintOutput(test_timeseries, test_freq, test_chn_name, test_units,
                                        start_time)
     test_index = blueprint_out.return_index(1)
     assert (test_index[0] == test_trigger).all()
-    assert test_index[1] == len(test_timeseries)
+    assert test_index[1] == test_timeseries.shape[1]
     assert test_index[3] == test_chn_name[1]
     assert test_index[4] == test_units[1]
 
@@ -119,5 +119,5 @@ def test_BlueprintOutput():
     blueprint_out.delete_at_index(1)
     assert len(blueprint_out.ch_name) == num_channnels - 1
     assert len(blueprint_out.units) == num_channnels - 1
-    assert blueprint_out.timeseries.shape[0] == num_channnels - 1
+    assert blueprint_out.timeseries.shape[1] == num_channnels - 1
     assert blueprint_out.ch_amount == num_channnels - 1