Cookbook: Difference between revisions

Jump to navigation Jump to search
443 bytes removed ,  22 August 2017
Some more refactoring.
(Some refactoring using <syntaxhighlight>.)
(Some more refactoring.)
Line 266: Line 266:
===Load comma separated values (*.csv) files===
===Load comma separated values (*.csv) files===


{{Code|Load comma separated values files|<syntaxhighlight lang="octave" style="font-size:13px">
# Using {{manual|textread}} gets you a one column cell array.  The original size can be restored by using the {{manual|reshape}} function. <syntaxhighlight lang="Octave">
A=textread("file.csv", "%d", "delimiter", ",");
A = textread("file.csv", "%d", "delimiter", ",");
B=textread("file.csv", "%s", "delimiter", ",");
B = textread("file.csv", "%s", "delimiter", ",");
inds = isnan(A);
inds = isnan(A);
B(!inds) = num2cell(A(!inds))
B(! inds) = num2cell (A(! inds))
</syntaxhighlight>}}
</syntaxhighlight>
# Another option is to use the function {{manual|csvread}}.  However, this function can't handle non-numerical data.
# The probably best option is to use the function [https://octave.sourceforge.io/io/function/csv2cell.html <code>csv2cell</code>] from the [[IO package]].  This function can read mixed-type (numerical and text) .csv files, allows to specify other field separators than a comma and other text protection characters (default: <code>"</code> double quote) and can skip header lines.  If you have the [[IO package]] installed and loaded, type <code>help csv2cell</code> at the Octave prompt for more info.


This gets you a 1 column cell array. You can reshape it to the original size by using the <code>reshape</code> function
===Load XML files===


The next version of octave (3.6) implements the <code>CollectOutput</code> switch as seen in example 8 here:                    http://www.mathworks.com/help/techdoc/ref/textscan.html
Reading XML in octave can be achieved using the java library [https://xerces.apache.org/ Apache Xerces].  


Another option is to use the function <code>csvread</code>, however this function can't handle non-numerical data.
It seems that the Matlab's <code>xmlread</code> is just a thin wrapper around the Apache Xerces library.
One should note however, that Java functions have the working directory set to the working directory when octave starts and the working directory is not modified by a {{manual|cd}} in octave.
Matlab has the same behavior, as Java does not provide a way to change the current working directory (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4045688).
To avoid any issues, it is thus better to use the absolute path to the XML file.


The probably best option is to use the function csv2cell() from the io package. This function can read mixed-type (numerical and text) .csv files, allows to specify other field separators than a comma and other text protection characters (default: " double quote) and can skip headerlines.  If you have the io package installed and loaded, type "help csv2cell" at the Octave prompt for more info.
You need the jar files {{Path|xercesImpl.jar}} and {{Path|xml-apis.jar}} from e.g. https://xerces.apache.org/mirrors.cgi#binary (check for the latest version).
Use {{manual|javaaddpath}} to include these files:


===Load XML files===
<syntaxhighlight lang="Octave">
javaaddpath ("/path/to/xerces-2_11_0/xercesImpl.jar");
javaaddpath ("/path/to/xerces-2_11_0/xml-apis.jar");
</syntaxhighlight>


Reading XML in octave can be achieved using the java library [http://xerces.apache.org/ Xerces] (from apache).
Example:


It seems that the matlab's xmlread is just a thin wrapper around the Xerces library. One should note however, that Java functions have the working directory set to the working directory when octave starts and the working directory is not modified by a cd in octave. Matlab has the same behavior, as Java does not provide a way to change the current working directory (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4045688). To avoid any issues, it is thus better to use the absolute path to the XML file.
<syntaxhighlight lang="Octave">
filename = "sample.xml";


You need the jar files xercesImpl.jar and xml-apis.jar from e.g. https://www.apache.org/dist/xerces/j/Xerces-J-bin.2.11.0.tar.gz (check for the latest version).
## These three lines are equivalent to xDoc = xmlread(filename) in Matlab
Use javaaddpath to include these files:
parser = javaObject("org.apache.xerces.parsers.DOMParser");
parser.parse(filename);
xDoc = parser.getDocument();


{{Code|Define java path|<syntaxhighlight lang="octave" style="font-size:1.1em">
elem = xDoc.getElementsByTagName("data").item(0); ## get first data element
  javaaddpath('/path/to/xerces-2_11_0/xercesImpl.jar');
data = elem.getFirstChild.getTextContent();       ## get text from child
  javaaddpath('/path/to/xerces-2_11_0/xml-apis.jar');
att  = elem.getAttribute("att");                 ## get attribute named att
</syntaxhighlight>}}
</syntaxhighlight>


A sample script:
{{File|sample.xml|
 
<syntaxhighlight lang="xml">
{{Code|Load XML file|<syntaxhighlight lang="octave" style="font-size:1.1em">
<root>
filename = 'sample.xml';
  <data att="1">hello</data>
</root>
% These 3 lines are equivalent to xDoc = xmlread(filename) in matlab
parser = javaObject('org.apache.xerces.parsers.DOMParser');
parser.parse(filename);
xDoc = parser.getDocument;
% get first data element
elem = xDoc.getElementsByTagName('data').item(0);
% get text from child
data = elem.getFirstChild.getTextContent
% get attribute named att
att = elem.getAttribute('att')
</syntaxhighlight>}}
 
The file <tt>sample.xml</tt>:
 
{{Code|Sample XML file|<syntaxhighlight lang="xml" style="font-size:1.1em">
<root>
<data att="1">hello</data>
</root>
</syntaxhighlight>}}
</syntaxhighlight>}}


Line 325: Line 318:
For example, to plot data using a string variable as a legend:
For example, to plot data using a string variable as a legend:


Option 1 (simplest):
# Static string as legend (simplest): <syntaxhighlight lang="Octave">
{{Code|Using variable strings in commands. op1|<syntaxhighlight lang="octave" style="font-size:13px">
x = linspace (-1, 3, 100);
y = sin (x);
legend = "-1;My data;";
legend = "-1;My data;";
plot(x, y, legend);
plot (x, y, legend);
</syntaxhighlight>}}
</syntaxhighlight>
 
# Variable string as legend (moderate): <syntaxhighlight lang="Octave">
Option 2 (to insert variables):
x = linspace (-1, 3, 100);
{{Code|Using variable strings in commands. op2|<syntaxhighlight lang="octave" style="font-size:13px">
y = sin (x);
plot(x, y, sprintf("-1;%s;", dataName));
dataName = "My data";
</syntaxhighlight>}}
plot (x, y, sprintf("-1;%s;", dataName));
 
</syntaxhighlight>
Option 3 (not as neat):
# Variable string as legend using {{manual|eval}} (not as neat): <syntaxhighlight lang="Octave">
{{Code|Using variable strings in commands. op3|<syntaxhighlight lang="octave" style="font-size:13px">
legend = "My data";
legend = 'my legend';
plot_command = ["plot (x, y, '-1;", legend, ";')"];
plot_command = ['plot(x,y,\';',legend,';\')'];
eval (plot_command);
eval(plot_command);
</syntaxhighlight>
</syntaxhighlight>}}


These same tricks are useful for reading and writing data files with unique names, etc.
These same tricks are useful for reading and writing data files with unique names, etc.


== Combinatorics ==
== Combinatorics ==
=== Combinations with string characters ===
=== Combinations with string characters ===
==== Problem ====
==== Problem ====
You want to get all combinations of different letters but {{codeline|nchoosek}} only accepts numeric input.
 
You want to get all combinations of different letters but {{manual|nchoosek}} only accepts numeric input.


==== Solution ====
==== Solution ====
Convert your string to numbers and then back to characters.
Convert your string to numbers and then back to characters.


{{Code||<syntaxhighlight lang="octave">
<syntaxhighlight lang="Octave">
string = "Hello";
n = 4;
char (nchoosek (uint8 (string), n))
char (nchoosek (uint8 (string), n))
</syntaxhighlight>}}
</syntaxhighlight>


==== Discussion ====
==== Discussion ====
A string in Octave is just a character matrix and can easily be converted to numeric form back and forth. Each character has an associated number (the {{codeline|asci}} function of the {{forge|miscellaneous}} package displays a nicely formatted conversion table).
 
A string in Octave is just a character matrix and can easily be converted to numeric form back and forth.
Each character has an associated number (the {{codeline|asci}} function of the {{forge|miscellaneous}} package displays a nicely formatted conversion table).


=== Permutations with repetition ===
=== Permutations with repetition ===
==== Problem ====
==== Problem ====
You want to generate all possible permutations of a vector with repetition.
You want to generate all possible permutations of a vector with repetition.


==== Solution ====
==== Solution ====
Use {{codeline|ndgrid}}


{{Code||<syntaxhighlight lang="octave">
Use {{manual|ndgrid}}:
[x y z] = ndgrid ([1 2 3 4 5]);
 
[x(:) y(:) z(:)]
<syntaxhighlight lang="Octave">
</syntaxhighlight>}}
[x, y, z] = ndgrid ([1, 2, 3, 4, 5]);
[x(:), y(:), z(:)]
</syntaxhighlight>


==== Discussion ====
==== Discussion ====
It is possible to expand the code above and make it work for any length of permutations.
It is possible to expand the code above and make it work for any length of permutations.


{{Code||<syntaxhighlight lang="octave">
<syntaxhighlight lang="Octave">
cart  = nthargout ([1:n], @ndgrid, vector);
cart  = nthargout ([1:n], @ndgrid, vector);
combs = cell2mat (cellfun (@(c) c(:), cart, "UniformOutput", false));
combs = cell2mat (cellfun (@(c) c(:), cart, "UniformOutput", false));
</syntaxhighlight>}}
</syntaxhighlight>


== Mathematics ==
== Mathematics ==
=== Test if a number is a integer ===
 
There are several methods to do this. The simplest method is probably {{Codeline|<nowiki>fix (x) == x</nowiki>}}
=== Test if a number is an integer ===
 
The simplest method is probably {{manual|fix}}:
 
<syntaxhighlight lang="Octave">
fix (x) == x
</syntaxhighlight>


=== Find if a number is even/odd ===
=== Find if a number is even/odd ===
==== Problem ====
==== Problem ====
You have a number, or an array or matrix of them, and want to know if any of them is an odd or even number, i.e., their parity.
You have a number, or an array or matrix of them, and want to know if any of them is an odd or even number, i.e., their parity.
==== Solution ====
==== Solution ====
Check the remainder of a division by two. If the remainder is zero, the number is even.
Check the remainder of a division by two. If the remainder is zero, the number is even.


  mod (value, 2) ## 1 if odd, zero if even
<syntaxhighlight lang="Octave">
mod (value, 2) ## 1 if odd, zero if even
</syntaxhighlight>


Since {{Codeline|mod()}} acceps a matrix, the following can be done:
Since {{manual|mod}} accepts a matrix, the following can be done:


  any  (mod (values, 2)) ## true if at least one number in values is even
<syntaxhighlight lang="Octave">
  all  (mod (values, 2)) ## true if all numbers in values are odd
any  (mod (values, 2)) ## true if at least one number in values is even
 
all  (mod (values, 2)) ## true if all numbers in values are odd
  any (!logical (mod (values, 2))) ## true if at least one number in values is even
 
  all (!logical (mod (values, 2))) ## true if all numbers in values are even
any (!logical (mod (values, 2))) ## true if at least one number in values is even
all (!logical (mod (values, 2))) ## true if all numbers in values are even
</syntaxhighlight>


==== Discussion ====
==== Discussion ====
Since we are checking for the remainder of a division, the first choice would be to use {{Codeline|rem()}}. However, in the case of negative numbers {{Codeline|mod()}} will still return a positive number making it easier for comparisons. Another alternative is to use {{Codeline|bitand (X, 1)}} or {{Codeline|bitget (X, 1)}} but those are a bit slower.


Note that this solution applies to integers only. Non-integers such as 1/2 or 4.201 are neither even nor odd. If the source of the numbers are unknown, such as user input, some sort of checking should be applied for NaN, Inf, or non-integer values.
Since we are checking for the remainder of a division, the first choice would be to use {{manual|rem}}.
However, in the case of negative numbers {{manual|mod}} will still return a positive number making it easier for comparisons.
Another alternative is to use {{Codeline|bitand (X, 1)}} or {{Codeline|bitget (X, 1)}} but those are a bit slower.


==== See also ====
Note that this solution applies to integers only.
Find if a number is an integer.
Non-integers such as <code>0.5</code> or <code>4.201</code> are neither even nor odd.
If the source of the numbers are unknown, such as user input, some sort of checking should be applied for <code>NaN</code>, <code>Inf</code>, or non-integer values.


=== Parametrized Functions ===
=== Parametrized Functions ===
==== Problem  ====
==== Problem  ====


Line 416: Line 438:


==== Solution ====
==== Solution ====
We could solve the problem with the following code:


{{Code|Solve spring equation for different values of the spring constant|<syntaxhighlight lang="octave" style="font-size:13px">
We could solve the problem with the following code to solve the spring equation for different values of the spring constant:
 
<syntaxhighlight lang="Octave">
t = linspace (0, 10, 100);
t = linspace (0, 10, 100);
function sprime = spring (s, t, k)
function sprime = spring (s, t, k)
Line 432: Line 455:
plot (t, x1, t, x2)
plot (t, x1, t, x2)
legend ('x1', 'x2')
legend ('x1', 'x2')
</syntaxhighlight>}}
</syntaxhighlight>


[[File:solparfun.png|400px]]
[[File:solparfun.png|400px]]
Line 441: Line 464:


The [http://www.gnu.org/software/octave/doc/interpreter/Anonymous-Functions.html#Anonymous-Functions anonymous function]
The [http://www.gnu.org/software/octave/doc/interpreter/Anonymous-Functions.html#Anonymous-Functions anonymous function]
{{Code||<syntaxhighlight lang="octave" style="font-size:13px">
  @(x, t) sprime (x, t, k)
</syntaxhighlight>}}


is a function of only <math>x, t</math> where the parameter <math>k</math> is 'frozen' to the value it has at the moment in the current scope.
<syntaxhighlight lang="Octave">
@(x, t) sprime (x, t, k)
</syntaxhighlight>
 
is a function of only <math>x, t</math> where the parameter <math>k</math> is "frozen" to the value it has at the moment in the current scope.


=== Distance between points ===
=== Distance between points ===
==== Problem  ====
==== Problem  ====
Given a set of points in space we want to calculate the distance between all of them. Each point is described by its components <math> (x_i,y_i,\ldots)</math>. Asusme that the points are saved in a matrix '''<tt>P</tt>''' with '''<tt>N</tt>''' rows (one for each point) and '''<tt>D</tt>''' columns, one for each component.
 
Given a set of points in space we want to calculate the distance between all of them.
Each point is described by its components <math> (x_i,y_i,\ldots)</math>.
Assume that the points are saved in a matrix <code>P</code> with <code>m</code> rows (one for each point) and <code>n</code> columns, one for each component.
 
==== Solution ====
==== Solution ====
One way of proceeding is to use the broadcast properties of operators in GNU Octave. The square distance between the points can be calculated with the code
 
<!-- {{SyntaxHighlight| -->
One way of proceeding is to use the broadcast properties of operators in GNU Octave.
{{Code|Calculate square distance between points|<syntaxhighlight lang="octave" style="font-size:13px">
The square distance between the points can be calculated with the code:
[N, dim] = size (P);
 
Dsq    = zeros (N);  
<syntaxhighlight lang="Octave">
for i = 1:dim
[m, n] = size (P);
Dsq    = zeros (m);  
for i = 1:n
   Dsq += (P(:,i) - P(:,i)').^2;
   Dsq += (P(:,i) - P(:,i)').^2;
endfor
endfor
</syntaxhighlight>}}
</syntaxhighlight>
 
This matrix is symmetric with zero diagonal.
This matrix is symmetric with zero diagonal.


Similarly the vectors pointing from one point to the another is
Similarly the vectors pointing from one point to the another is
<!-- {{SyntaxHighlight| -->
 
{{Code|Calculate radius vector between points|<syntaxhighlight lang="octave" style="font-size:13px">
<syntaxhighlight lang="Octave">
R     = zeros (N,N,dim);  
R = zeros (m, m, n);  
for i = 1:dim
for i = 1:n
   R(:,:,i) = P(:,i) - P(:,i)';
   R(:,:,i) = P(:,i) - P(:,i)';
endfor
endfor
</syntaxhighlight>}}
</syntaxhighlight>
 
The relation between <code>Dsq</code> and <code>R</code> is


The relation between <tt>Dsq</tt> and <tt>R</tt> is
<syntaxhighlight lang="Octave">
<!-- {{SyntaxHighlight| -->
Dsq = sumsq (R, 3);  
{{Code||<syntaxhighlight lang="octave" style="font-size:13px">
</syntaxhighlight>
Dsq = sumsq (R,3);  
</syntaxhighlight>}}


==== Discussion ====
==== Discussion ====
The calculation can be implemented using functions like <tt>cellfun</tt> and avoid the loop over components of the points. However in most cases we will have more points than components and the improvement, if any, will be minimal.


Another observation is that the matrix Dsq is symmetric and we could store only the lower or upper triangular part. To use this optimization in a practical way check the help of the functions <tt>vech</tt> and <tt>unvech</tt> (this one is in the Forge package ''general''). Two functions that haven't seen the light yet are <tt>sub2ind_tril</tt> and <tt>ind2sub_tril</tt> (currently private functions in the [[Mechanics_package | Forge package mechanics]]) that are useful to index the elements of a vector constructed with the function <tt>vech</tt>. Each page (the third index) of the multidimensional array <tt>R</tt> is an anti-symmetric matrix and we could also save some memory by keeping only one of the triangular submatrices.
The calculation can be implemented using functions like {{manual|cellfun}} and avoid the loop over components of the points.
However in most cases we will have more points than components and the improvement, if any, will be minimal.
 
Another observation is that the matrix <code>Dsq</code> is symmetric and we could store only the lower or upper triangular part.
To use this optimization in a practical way check the help of the functions <code>vech</code> and <code>unvech</code> (this one is in the Forge package {{Forge|general}}).
Two functions that haven't seen the light yet are <code>sub2ind_tril</code> and <code>ind2sub_tril</code> (currently private functions in the [[Mechanics_package | Forge package mechanics]]) that are useful to index the elements of a vector constructed with the function <code>vech</code>.
Each page (the third index) of the multidimensional array <code>R</code> is an anti-symmetric matrix and we could also save some memory by keeping only one of the triangular submatrices.


Check the [[Geometry package]] for many more distance functions (points, lines, polygons, etc.).
Check the [[Geometry package]] for many more distance functions (points, lines, polygons, etc.).

Navigation menu