Cookbook: Difference between revisions

106 bytes added ,  22 August 2017
Some refactoring using <syntaxhighlight>.
(Some refactoring using <syntaxhighlight>.)
Line 15: Line 15:
This is a list of possible tests to check for features:
This is a list of possible tests to check for features:


    ## support for 64 bit indexing
<syntaxhighlight lang="Octave">
    sizemax () > intmax ("int32")
## support for 64 bit indexing
sizemax () > intmax ("int32")


    ## built with support for java
## built with support for java
    usejava ("jvm")
usejava ("jvm")


    ## Image IO with support for tif files
## Image IO with support for tif files
    any (cellfun (@(x) ismember ("tif", x), {imformats.ext}))
any (cellfun (@(x) ismember ("tif", x), {imformats.ext}))
    ## Image IO with support for png files
## Image IO with support for png files
    any (cellfun (@(x) ismember ("png", x), {imformats.ext}))
any (cellfun (@(x) ismember ("png", x), {imformats.ext}))
</syntaxhighlight>


=== Find if a package is installed ===
=== Find if a package is installed ===
Line 37: Line 39:
Use {{codeline|pkg ("list", pkg-name)}} like so:
Use {{codeline|pkg ("list", pkg-name)}} like so:


if (! isempty (pkg ("list", "foo")))
<syntaxhighlight lang="Octave">
  ## use functions from package foo, the prefered way
if (! isempty (pkg ("list", "foo")))
elseif (! isempty (pkg ("list", "bar")))
  ## use functions from package foo, the preferred way
  ## use functions from package bar, not so optimal
elseif (! isempty (pkg ("list", "bar")))
else
  ## use functions from package bar, not so optimal
  ## default case
else
endif
  ## default case
endif
</syntaxhighlight>


==== Discussion ====
==== Discussion ====
Line 56: Line 60:
then you might as well not catch it in the first place.
then you might as well not catch it in the first place.


## This contraption doesn't add anything.  If 'pkg load' fails, it
<syntaxhighlight lang="Octave">
## will already give an error message to the user.
## This contraption doesn't add anything.  If 'pkg load' fails, it
try
## will already give an error message to the user.
  pkg load foo;
try
catch
  pkg load foo;
  error ("failed to load foo: %s", lasterr ());
catch
end_try_catch
  error ("failed to load foo: %s", lasterr ());
end_try_catch


## Again, doesn't add anything.  The failure of 'pkg load' is enough
## Again, doesn't add anything.  The failure of 'pkg load' is enough
if (isempty (pkg ("list", "foo")))
if (isempty (pkg ("list", "foo")))
  error ("program: package foo is not installed");
  error ("program: package foo is not installed");
endif
endif
</syntaxhighlight>


Beware that an installed package is not always a guarantee that a function
Beware that an installed package is not always a guarantee that a function
Line 74: Line 80:


== Structures ==
== Structures ==
=== Retrieve a field value from all entries in a struct array ===
=== Retrieve a field value from all entries in a struct array ===
==== Problem ====
==== Problem ====
You have a struct array with multiple fields, and you want to access the value from a specific field from all elements. For example, you want to return the age from all patients in the following case:
You have a struct array with multiple fields, and you want to access the value from a specific field from all elements. For example, you want to return the age from all patients in the following case:


  samples = struct ("patient", {"Bob", "Kevin", "Bob" , "Andrew"},
<syntaxhighlight lang="Octave">
                    "age",    { 45  ,  52    ,  45  ,  23    },
samples = struct ("patient", {"Bob", "Kevin", "Bob" , "Andrew"},
                    "protein", {"H2B", "CDK2" , "CDK2", "Tip60" },
                  "age",    { 45  ,  52    ,  45  ,  23    },
                    "tube"  , { 3  ,  5    ,  2    ,  18    }
                  "protein", {"H2B", "CDK2" , "CDK2", "Tip60" },
                    );
                  "tube"  , { 3  ,  5    ,  2    ,  18    }
                  );
</syntaxhighlight>


==== Solution ====
==== Solution ====
Indexing the struct returns a comma separated list so use them to create a matrix.
Indexing the struct returns a comma separated list so use them to create a matrix.


  [samples(:).age]
<syntaxhighlight lang="Octave">
[samples(:).age]
</syntaxhighlight>


This however does not keep the original structure of the data, instead returning all values in a single column. To fix this, use {{Codeline|reshape()}}.
This however does not keep the original structure of the data, instead returning all values in a single column. To fix this, use {{Codeline|reshape()}}.


  reshape ([samples(:).age], size (samples))
<syntaxhighlight lang="Octave">
reshape ([samples(:).age], size (samples))
</syntaxhighlight>


==== Discussion ====
==== Discussion ====
Returning all values in a comma separated lists allows you to make anything out of them. If numbers are expected, create a matrix by enclosing them in square brackets. But if strings are to be expected, a cell array can also be easily generated with curly brackets


  {samples(:).patient}
Returning all values in a comma separated lists allows you to make anything out of them.
If numbers are expected, create a matrix by enclosing them in square brackets.
But if strings are to be expected, a cell array can also be easily generated with curly brackets
 
<syntaxhighlight lang="Octave">
{samples(:).patient}
</syntaxhighlight>


You are also not limited to return all elements, you may use logical indexing from other fields to get values from the others:
You are also not limited to return all elements, you may use logical indexing from other fields to get values from the others:


  [samples([samples(:).age] > 34).tube]                ## return tube numbers from all samples from patients older than 34
<syntaxhighlight lang="Octave">
  [samples(strcmp({samples(:).protein}, "CDK2")).tube]  ## return all tube numbers for protein CDK2
[samples([samples(:).age] > 34).tube]                ## return tube numbers from all samples from patients older than 34
[samples(strcmp({samples(:).protein}, "CDK2")).tube]  ## return all tube numbers for protein CDK2
</syntaxhighlight>


== Array manipulation ==
== Array manipulation ==
Line 109: Line 131:
==== Problem ====
==== Problem ====


For an array {{Codeline|A}} with arbitrary number of dimensions, select, for example, the first column. This would be {{Codeline|A(:, 1)}} if {{Codeline|A}} was 2-D, {{Codeline|A(:, 1, :)}} if {{Codeline|A}} was 3-D, and so on.
For an array {{Codeline|A}} with arbitrary number of dimensions, select, for example, the first column.
This would be {{Codeline|A(:, 1)}} if {{Codeline|A}} was 2-D, {{Codeline|A(:, 1, :)}} if {{Codeline|A}} was 3-D, and so on.


==== Solution ====
==== Solution ====


One possibility is to use {{Codeline|subsref}} with the input {{Codeline|idx}} created dynamically with {{Codeline|repelems}} to have the right number of dimensions. This can be written as a function:
One possibility is to use {{manual|subsref}} with the input {{Codeline|idx}} created dynamically with {{manual|repelems}} to have the right number of dimensions.
 
This can be written as a function:


{{Code||<syntaxhighlight lang="octave" style="font-size:13px">
<syntaxhighlight lang="Octave">
function [B]= array_slice (A,k,d)
function [B]= array_slice (A,k,d)
#return the k-th slice (row, column...) of A, with d specifying the dimension to slice on
#return the k-th slice (row, column...) of A, with d specifying the dimension to slice on
Line 135: Line 158:
%! A=rand(2, 3, 4, 5, 6);
%! A=rand(2, 3, 4, 5, 6);
%!assert (array_slice (A,2,3), A(:, :, 2, :, :))
%!assert (array_slice (A,2,3), A(:, :, 2, :, :))
</syntaxhighlight>}}
</syntaxhighlight>


To remove the singleton dimension {{Codeline|d}} from the result {{Codeline|B}}, use  
To remove the singleton dimension {{Codeline|d}} from the result {{Codeline|B}}, use  
{{Code||<syntaxhighlight lang="octave" style="font-size:13px">
 
<syntaxhighlight lang="Octave">
B = reshape(B, [size(B)([1:d-1 d+1:end])]);
B = reshape(B, [size(B)([1:d-1 d+1:end])]);
</syntaxhighlight>}}
</syntaxhighlight>


== Input/output ==
== Input/output ==
=== Display matched elements from different arrays ===
=== Display matched elements from different arrays ===
==== Problem ====
==== Problem ====
You have two, or more, arrays with paired elements and want to print out a string about them. For example:
You have two, or more, arrays with paired elements and want to print out a string about them. For example:


    keys  = {"human",  "mouse", "chicken"};
<syntaxhighlight lang="Octave">
    values = [ 64        72      70      ];
keys  = {"human",  "mouse", "chicken"};
values = [ 64        72      70      ];
</syntaxhighlight>


and you want to display:
and you want to display:


    Calculated human genome GC content is 64%
Calculated human genome GC content is 64%
    Calculated mouse genome GC content is 72%
Calculated mouse genome GC content is 72%
    Calculated chicken genome GC content is 70%
Calculated chicken genome GC content is 70%


==== Solution ====
==== Solution ====
Make a two rows cell array, with each paired data in a column and supply a cs-list to printf


    values = num2cell (values);
Make a two rows cell array, with each paired data in a column and supply a cs-list to {{manual|printf}}
    new    = {keys{:}; values{:}};
 
    printf ("Calculated %s genome GC content is %i%%\n", new{:})
<syntaxhighlight lang="Octave">
values = num2cell (values);
new    = {keys{:}; values{:}};
printf ("Calculated %s genome GC content is %i%%\n", new{:})
</syntaxhighlight>


or in a single line:
or in a single line:
    printf ("Calculated %s genome GC content is %i%%\n", {keys{:}; num2cell(values){:}}{:})
 
   
<syntaxhighlight lang="Octave">
printf ("Calculated %s genome GC content is %i%%\n", {keys{:}; num2cell(values){:}}{:})
</syntaxhighlight>   


==== Discussion ====
==== Discussion ====
{{Codeline|printf}} and family do not accept cell arrays as values. However, they keep repeating the template given as long as it has enough arguments to keep going. As such, the trick is on supplying a cs-list of elements which can be done by using a cell array and index it with {{Codeline|<nowiki>{}</nowiki>}}.


Since values are stored in column-major order, paired values need to be on the same column. A new row of data can then be added later with {{Codeline|new(end+1,:) <nowiki>= {"Andrew", "Bob", "Kevin"}</nowiki>}}. Note that normal brackets are now being used for indexing.
{{manual|printf}} and family do not accept cell arrays as values.
However, they keep repeating the template given as long as it has enough arguments to keep going.
As such, the trick is on supplying a cs-list of elements which can be done by using a cell array and index it with <code>{}</code>.
 
Since values are stored in column-major order, paired values need to be on the same column.
A new row of data can then be added later with
 
<syntaxhighlight lang="Octave">
new(end+1,:) = {"Andrew", "Bob", "Kevin"};
</syntaxhighlight>
 
Note that normal brackets are now being used for indexing.


=== Swap values ===
=== Swap values ===
If you want to exchange the value between two variables without creating a dummy one, you can simply do:
If you want to exchange the value between two variables without creating a dummy one, you can simply do:


{{Code|Swap values without dummy variable|<syntaxhighlight lang="octave" style="font-size:13px">
<syntaxhighlight lang="Octave">
[b,a] = deal (a,b);
[b,a] = deal (a,b);
</syntaxhighlight>}}
</syntaxhighlight>


=== Collect all output arguments of a function ===
=== Collect all output arguments of a function ===
If you have a function that returns several values, e.g.  
If you have a function that returns several values, e.g.  


{{Code||<syntaxhighlight lang="octave" style="font-size:13px">
<syntaxhighlight lang="Octave">
function [a b c]= myfunc ()
function [a b c]= myfunc ()
   [a,b,c] = deal (1,2,3);  
   [a,b,c] = deal (1,2,3);  
endfunction
endfunction
</syntaxhighlight>}}
</syntaxhighlight>


and you want to collect them all into a single cell (similarly to Python's zip() function) you can do:
and you want to collect them all into a single cell (similarly to Python's zip() function) you can do:


{{Code|Collect multiple output arguments|<syntaxhighlight lang="octave" style="font-size:13px">
<syntaxhighlight lang="Octave">
outargs = nthargout (1:3, @myfunc)
outargs = nthargout (1:3, @myfunc)
</syntaxhighlight>}}
</syntaxhighlight>


=== Create a text table with fprintf===
=== Create a text table with fprintf===
(a.k.a. A funny formatting trick with fprintf found by chance)


Imagine that you want to create a text table with fprintf with 2 columns of 15 characters width and both right justified. How to do this thing?
Imagine that you want to create a text table with {{manual|fprintf}} with 2 columns of 15 characters width and both right justified.
How to do this thing?


That's easy:
That's easy:


If the variable Text is a cell array of strings (of length <15) with two columns and a certain number of rows, simply type for the kth row of Text
If the variable Text is a cell array of strings (of length < 15) with two columns and a certain number of rows, simply type for the k-th row of Text
{{Code||<syntaxhighlight lang="octave" style="font-size:13px">
 
fprintf('%15.15s | %15.15s\n', Text{k,1}, Text{k,2});
<syntaxhighlight lang="Octave">
</syntaxhighlight>}}
fprintf('%15.15s | %15.15s\n', Text{k,1}, Text{k,2});
The syntax '%<n>.<m>s' allocates '<n>' places to write chars and display the '<m>' first characters of the string to display.
</syntaxhighlight>
 
The syntax <code>%<n>.<m>s</code> allocates <code>n</code> places to write chars and display the <code>m</code> first characters of the string to display.


Example:
Example:
{{Code|Example create a text table with fprintf|<syntaxhighlight lang="octave" style="font-size:13px">
 
octave:1> Text={'Hello','World'};
<syntaxhighlight lang="Octave">
octave:2> fprintf('%15.15s | %15.15s\n', Text{1,1}, Text{1,2})
Text = {"Hello", "World"};
fprintf('%15.15s | %15.15s\n', Text{1,1}, Text{1,2})
</syntaxhighlight>
 
           Hello |          World
           Hello |          World
</syntaxhighlight>}}


===Load comma separated values (*.csv) files===
===Load comma separated values (*.csv) files===