]> Creatis software - CreaPhase.git/blobdiff - octave_packages/nnet-0.1.13/mapstd.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / nnet-0.1.13 / mapstd.m
diff --git a/octave_packages/nnet-0.1.13/mapstd.m b/octave_packages/nnet-0.1.13/mapstd.m
new file mode 100644 (file)
index 0000000..bccf290
--- /dev/null
@@ -0,0 +1,329 @@
+## Copyright (C) 2009 Luiz Angelo Daros de Luca <luizluca@gmail.com>
+##
+##
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} [@var{YY},@var{PS}] = mapstd (@var{XX},@var{ymean},@var{ystd})
+## Map values to mean 0 and standard derivation to 1.
+##
+## @example
+## [YY,PS] = mapstd(XX,ymean,ystd)
+##
+##    Apply the conversion and returns YY as (YY-ymean)/ystd.
+##
+## [YY,PS] = mapstd(XX,FP)
+##
+##    Apply the conversion but using an struct to inform target mean/stddev.
+##    This is the same of [YY,PS]=mapstd(XX,FP.ymean, FP.ystd).
+##
+## YY = mapstd('apply',XX,PS)
+##
+##    Reapply the conversion based on a previous operation data.
+##    PS stores the mean and stddev of the first XX used.
+##
+## XX = mapstd('reverse',YY,PS)
+##
+##    Reverse a conversion of a previous applied operation.
+##
+## dx_dy = mapstd('dx',XX,YY,PS)
+##
+##    Returns the derivative of Y with respect to X.
+##
+## dx_dy = mapstd('dx',XX,[],PS)
+##
+##    Returns the derivative (less efficient).
+##
+## name = mapstd('name');
+##
+##    Returns the name of this convesion process.
+##
+## FP = mapstd('pdefaults');
+##
+##    Returns the default process parameters.
+##
+## names = mapstd('pnames');
+##
+##    Returns the description of the process parameters.
+##
+## mapstd('pcheck',FP);
+##
+##    Raises an error if FP has some inconsistent.
+## @end example
+##
+## @end deftypefn
+
+function [out1,out2]=mapstd(in1,in2,in3,in4)
+  #
+  # Map values to mean 0 and standard derivation to 1.
+  #
+  # [YY,PS] = mapstd(XX,ymean,ystd)
+  #
+  #    Apply the conversion and returns YY as (YY-ymean)/ystd.
+  #
+  # [YY,PS] = mapstd(XX,FP)
+  #
+  #    Apply the conversion but using an struct to inform target mean/stddev.
+  #    This is the same of [YY,PS]=mapstd(XX,FP.ymean, FP.ystd).
+  #
+  # YY = mapstd('apply',XX,PS)
+  #
+  #    Reapply the conversion based on a previous operation data.
+  #    PS stores the mean and stddev of the first XX used.
+  #
+  # XX = mapstd('reverse',YY,PS)
+  #
+  #    Reverse a conversion of a previous applied operation.
+  #
+  # dx_dy = mapstd('dx',XX,YY,PS)
+  #
+  #    Returns the derivative of Y with respect to X.
+  #
+  # dx_dy = mapstd('dx',XX,[],PS)
+  #
+  #    Returns the derivative (less efficient).
+  #
+  # name = mapstd('name');
+  #
+  #    Returns the name of this convesion process.
+  #
+  # FP = mapstd('pdefaults');
+  #
+  #    Returns the default process parameters.
+  #
+  # names = mapstd('pnames');
+  #
+  #    Returns the description of the process parameters.
+  #
+  # mapstd('pcheck',FP);
+  #
+  #    Raises an error if FP has some inconsistent.
+  #
+
+  if nargin==0
+    error("Not enough arguments.")
+  endif
+
+  # Defaults
+  ps.name="mapstd";
+  ps.ymean=0;
+  ps.ystd=1;
+
+  if ischar(in1)
+    switch in1
+        case "name"
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            if nargin>1
+                error("Too many input arguments");
+            endif
+            out1="Map Mean and Standard Deviation";
+            return;
+        case "pdefaults"
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            if nargin>1
+                error("Too many input arguments");
+            endif
+            out1=ps;
+        case "pcheck"
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            if nargin<2
+                error("Not enough input arguments");
+            endif
+            if nargin>2
+                error("Too many input arguments");
+            endif
+            
+            fp=in2;           
+            if ~isstruct(fp)
+                error("FP must be a struct")                
+            elseif ~isfield(fp,"ymean")
+                error("FP must include ymean field")
+            elseif ~isfield(fp,"ystd")
+                error("FP must include ystd field")
+            elseif isdouble(fp.ymean)
+                error("FP.ymean must be a real scalar value")
+            elseif isdouble(fp.ystd)
+                error("FP.ystd must be a real scalar value")
+            else
+                out1='';
+            endif
+            return;
+        # MATLAB uses pnames but documents as pdesc (that does not work)
+        case "pnames"
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            if nargin>1
+                error("Too many input arguments");
+            endif
+            # MATLAB seems to be buggy in the second element
+            #out1={'Mean value for each row of Y.','Maximum value for each
+            #row of Y.'};            
+            out1={"Mean value for each row of Y.","Standart deviation value for each row of Y."};                        
+        case "apply"
+            if nargin<3
+                error("Not enough input arguments");
+            endif
+            if nargin>3
+                error("Too many input arguments");
+            endif
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            xx=in2;
+            ps=in3;
+            yy=apply(xx,ps);
+            out1=yy;
+            out2=ps;
+            return;
+        case "reverse"
+            if nargin<3
+                error("Not enough input arguments");
+            endif
+            if nargin>3
+                error("Too many input arguments");
+            endif
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            yy=in2;
+            ps=in3;
+            xx=reverse(yy,ps);
+            out1=xx;
+            out2=ps;
+            return;
+        case "dx"
+            if nargin<3
+                error("Not enough input arguments");
+            endif
+            if nargin>3
+                error("Too many input arguments");
+            endif
+            if nargout>1
+                error("Too many output arguments");
+            endif
+            xx=in2;
+            yy=in3;
+            ps=in4;
+            xx_yy=derivate(xx,yy,ps);
+            out1=xx_yy;
+            return;
+    endswitch
+  else
+    xx=in1;
+    ps.xrows=size(xx,1);
+    ps.yrows=size(xx,1);
+    ps.xmean=mean(xx,2);
+    ps.xstd=std(xx,0,2);      
+    
+    if nargin==1
+        # All correct
+    elseif nargin==2
+        if isstruct(in2)
+            ps.ymean=in2.ymean;
+            ps.ystd=in2.ystd;
+        else
+            ps.ymean=in2;
+        endif
+    elseif nargin == 3
+        ps.ymean=in2;
+        ps.ystd=in3;
+    else
+        error("Too many input arguments");
+    endif
+    
+    out1=apply(xx,ps);   
+    out2=ps;
+  endif
+
+  # Verify args
+  function checkargs(values,ps)
+    # check xx is matrix
+    if ~isnumeric(values)
+        error("Just numeric values are accepted")
+    endif
+    # check ps is struct
+    if ~isstruct(ps)
+        error("PS should be a struct")
+    endif
+    # check ymean,ystd
+    if ~isa(ps.ymean,"double")
+        error("PS.ymean should be a double")
+    endif
+    if ~isa(ps.ystd,"double")
+        error("PS.ystd should be a double")
+    endif
+    if ~all(size(ps.ymean)==[1 1])
+        error("PS.ymean should be a scalar")
+    endif
+    if ~all(size(ps.ystd)==[1 1])
+        error("PS.ystd should be a scalar")
+    endif
+    # check xmean,ystd
+    if ~isnumeric(ps.xmean)
+        error("PS.xmean should be a numeric")
+    endif
+    if ~isnumeric(ps.xstd)
+        error("PS.xstd should be a numeric")
+    endif
+    if ~all(size(ps.xmean)==size(ps.xstd))
+        error("Size of PS.xmean and PS.xstd must match")
+    endif
+  endfunction
+
+  # Apply the mapping operation
+  function [yy]=apply(xx,ps)
+    checkargs(xx,ps)
+
+    if ~all(size(xx,1)==size(ps.xmean,1))
+        error("Size of XX rows should match PS.xmean and PS.xstd")
+    endif
+    # Avoid multiply/division by zero
+    ps.xstd(ps.xstd == 0) = 1;
+    yy=(xx - (ps.xmean*ones(1,size(xx,2)))) ./ (ps.xstd*ones(1,size(xx,2)));
+    yy=(yy + ps.ymean) .* ps.ystd;
+  endfunction
+
+  # Reverse the mapping operation
+  function [xx]=reverse(yy,ps)
+    checkargs(yy,ps)
+    if ~all(size(yy,1)==size(ps.xmean,1))
+        error("Size of YY rows should match PS.xmean and PS.xstd")
+    endif
+    # Avoid multiply/division by zero
+    ps.xstd(ps.xstd == 0) = 1;
+    yy=(yy ./ ps.ystd) - ps.ymean;
+    xx=(yy .* (ps.xstd*ones(1,size(yy,2)))) + (ps.xmean*ones(1,size(yy,2)));
+  endfunction
+
+  # I don't know why this exists but matlab implements it
+  function [dy_dx]=derivate(xx,yy,ps)
+    checkargs(yy,ps)
+    checkargs(xx,ps)
+
+    cols = size(xx,2);
+    diagonal = diag(ps.ystd ./ ps.xstd);
+    dy_dx = diagonal(:,:,ones(1,cols));
+  endfunction
+
+#end
+
+endfunction
\ No newline at end of file