Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package octave-forge-splines for 
openSUSE:Factory checked in at 2021-03-17 20:16:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/octave-forge-splines (Old)
 and      /work/SRC/openSUSE:Factory/.octave-forge-splines.new.2401 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "octave-forge-splines"

Wed Mar 17 20:16:47 2021 rev:6 rq:879590 version:1.3.4

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/octave-forge-splines/octave-forge-splines.changes    
    2019-11-28 10:15:22.131637926 +0100
+++ 
/work/SRC/openSUSE:Factory/.octave-forge-splines.new.2401/octave-forge-splines.changes
      2021-03-17 20:20:06.463330051 +0100
@@ -1,0 +2,6 @@
+Sat Mar 13 13:48:18 UTC 2021 - Atri Bhattacharya <[email protected]>
+
+- Update to version 1.3.4:
+  * New functions regularization, regularization2D
+
+-------------------------------------------------------------------

Old:
----
  splines-1.3.3.tar.gz

New:
----
  splines-1.3.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ octave-forge-splines.spec ++++++
--- /var/tmp/diff_new_pack.eOPCTN/_old  2021-03-17 20:20:06.951330718 +0100
+++ /var/tmp/diff_new_pack.eOPCTN/_new  2021-03-17 20:20:06.955330723 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package octave-forge-splines
 #
-# Copyright (c) 2019 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %define octpkg  splines
 Name:           octave-forge-%{octpkg}
-Version:        1.3.3
+Version:        1.3.4
 Release:        0
 Summary:        Additional spline functions for Octave
 License:        GPL-2.0-or-later AND GPL-3.0-or-later AND SUSE-Public-Domain

++++++ splines-1.3.3.tar.gz -> splines-1.3.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/CITATION new/splines-1.3.4/CITATION
--- old/splines-1.3.3/CITATION  2019-10-23 20:45:53.000000000 +0200
+++ new/splines-1.3.4/CITATION  2021-02-24 02:14:16.000000000 +0100
@@ -2,6 +2,6 @@
    author = {Krakauer, Nir Y. and others},
    title = {Splines Package for GNU Octave},
    url = {http://octave.sourceforge.net/splines},
-   version = {1.3.2},
-   date = {2016-11-23},
+   version = {1.3.4},
+   date = {2021-02-23},
  }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/DESCRIPTION 
new/splines-1.3.4/DESCRIPTION
--- old/splines-1.3.3/DESCRIPTION       2019-10-23 20:45:53.000000000 +0200
+++ new/splines-1.3.4/DESCRIPTION       2021-02-24 02:14:16.000000000 +0100
@@ -1,6 +1,6 @@
 Name: splines
-Version: 1.3.3
-Date: 2019-10-17
+Version: 1.3.4
+Date: 2021-02-23
 Author: various authors
 Maintainer: Nir Krakauer <[email protected]>
 Title: Splines.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/INDEX new/splines-1.3.4/INDEX
--- old/splines-1.3.3/INDEX     2019-10-23 20:45:53.000000000 +0200
+++ new/splines-1.3.4/INDEX     2021-02-24 02:14:16.000000000 +0100
@@ -10,6 +10,8 @@
  fnder 
  fnplt 
  fnval
+ regularization
+ regularization2D
  tpaps
  tps_val
  tps_val_der
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/Makefile new/splines-1.3.4/Makefile
--- old/splines-1.3.3/Makefile  1970-01-01 01:00:00.000000000 +0100
+++ new/splines-1.3.4/Makefile  2021-02-24 02:14:16.000000000 +0100
@@ -0,0 +1,235 @@
+## Copyright 2015-2016 Carn?? Draug
+## Copyright 2015-2016 Oliver Heimlich
+## Copyright 2017 Julien Bect <[email protected]>
+## Copyright 2017 Olaf Till <[email protected]>
+##
+## Copying and distribution of this file, with or without modification,
+## are permitted in any medium without royalty provided the copyright
+## notice and this notice are preserved.  This file is offered as-is,
+## without any warranty.
+
+## Some basic tools (can be overriden using environment variables)
+SED ?= sed
+TAR ?= tar
+GREP ?= grep
+CUT ?= cut
+TR ?= tr
+
+## Note the use of ':=' (immediate set) and not just '=' (lazy set).
+## http://stackoverflow.com/a/448939/1609556
+package := $(shell $(GREP) "^Name: " DESCRIPTION | $(CUT) -f2 -d" " | \
+$(TR) '[:upper:]' '[:lower:]')
+version := $(shell $(GREP) "^Version: " DESCRIPTION | $(CUT) -f2 -d" ")
+
+## These are the paths that will be created for the releases.
+target_dir       := target
+release_dir      := $(target_dir)/$(package)-$(version)
+release_tarball  := $(target_dir)/$(package)-$(version).tar.gz
+html_dir         := $(target_dir)/$(package)-html
+html_tarball     := $(target_dir)/$(package)-html.tar.gz
+## Using $(realpath ...) avoids problems with symlinks due to bug
+## #50994 in Octaves scripts/pkg/private/install.m.  But at least the
+## release directory above is needed in the relative form, for 'git
+## archive --format=tar --prefix=$(release_dir).
+real_target_dir  := $(realpath .)/$(target_dir)
+installation_dir := $(real_target_dir)/.installation
+package_list     := $(installation_dir)/.octave_packages
+install_stamp    := $(installation_dir)/.install_stamp
+
+## These can be set by environment variables which allow to easily
+## test with different Octave versions.
+ifndef OCTAVE
+OCTAVE := octave
+endif
+OCTAVE := $(OCTAVE) --no-gui --silent --norc
+MKOCTFILE ?= mkoctfile
+
+## Command used to set permissions before creating tarballs
+FIX_PERMISSIONS ?= chmod -R a+rX,u+w,go-w,ug-s
+
+## Detect which VCS is used
+vcs := $(if $(wildcard .hg),hg,$(if $(wildcard .git),git,unknown))
+ifeq ($(vcs),hg)
+release_dir_dep := .hg/dirstate
+endif
+ifeq ($(vcs),git)
+release_dir_dep := .git/index
+endif
+
+
+## .PHONY indicates targets that are not filenames
+## (https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html)
+.PHONY: help
+
+## make will display the command before runnning them.  Use @command
+## to not display it (makes specially sense for echo).
+help:
+       @echo "Targets:"
+       @echo "   dist    - Create $(release_tarball) for release."
+       @echo "   html    - Create $(html_tarball) for release."
+       @echo "   release - Create both of the above and show md5sums."
+       @echo "   install - Install the package in $(installation_dir), where 
it is not visible in a normal Octave session."
+       @echo "   check   - Execute package tests."
+       @echo "   doctest - Test the help texts with the doctest package."
+       @echo "   run     - Run Octave with the package installed in 
$(installation_dir) in the path."
+       @echo "   clean   - Remove everything made with this Makefile."
+
+
+##
+## Recipes for release tarballs (package + html)
+##
+
+.PHONY: release dist html clean-tarballs clean-unpacked-release
+
+## To make a release, build the distribution and html tarballs.
+release: dist html
+       md5sum $(release_tarball) $(html_tarball)
+       @echo "Upload @ https://sourceforge.net/p/octave/package-releases/new/";
+       @echo "    and note the changeset the release corresponds to"
+
+## dist and html targets are only PHONY/alias targets to the release
+## and html tarballs.
+dist: $(release_tarball)
+html: $(html_tarball)
+
+## An implicit rule with a recipe to build the tarballs correctly.
+%.tar.gz: %
+       $(TAR) -c -f - --posix -C "$(target_dir)/" "$(notdir $<)" | gzip -9n > 
"$@"
+
+clean-tarballs:
+       @echo "## Cleaning release tarballs (package + html)..."
+       -$(RM) $(release_tarball) $(html_tarball)
+       @echo
+
+## Create the unpacked package.
+##
+## Notes:
+##    * having ".hg/dirstate" (or ".git/index") as a prerequesite means it is
+##      only rebuilt if we are at a different commit.
+##    * the variable RM usually defaults to "rm -f"
+##    * having this recipe separate from the one that makes the tarball
+##      makes it easy to have packages in alternative formats (such as zip)
+##    * note that if a commands needs to be run in a specific directory,
+##      the command to "cd" needs to be on the same line.  Each line restores
+##      the original working directory.
+$(release_dir): $(release_dir_dep)
+       -$(RM) -r "$@"
+ifeq (${vcs},hg)
+       hg archive --exclude ".hg*" --type files "$@"
+endif
+ifeq (${vcs},git)
+       git archive --format=tar --prefix="$@/" HEAD | $(TAR) -x
+       $(RM) "$@/.gitignore"
+endif
+## Don't fall back to run the supposed necessary contents of
+## 'bootstrap' here. Users are better off if they provide
+## 'bootstrap'. Administrators, checking build reproducibility, can
+## put in the missing 'bootstrap' file if they feel they know its
+## necessary contents.
+ifneq (,$(wildcard src/bootstrap))
+       cd "$@/src" && ./bootstrap && $(RM) -r "autom4te.cache"
+endif
+## Uncomment this if your src/Makefile.in has these targets for
+## pre-building something for the release (e.g. documentation).
+#      cd "$@/src" && ./configure && $(MAKE) prebuild && \
+#        $(MAKE) distclean && $(RM) Makefile
+##
+       ${FIX_PERMISSIONS} "$@"
+
+run_in_place = $(OCTAVE) --eval ' pkg ("local_list", "$(package_list)"); ' \
+                         --eval ' pkg ("load", "$(package)"); '
+
+html_options = --eval 'options = get_html_options ("octave-forge");'
+## Uncomment this for package documentation.
+# html_options = --eval 'options = get_html_options ("octave-forge");' \
+#                --eval 'options.package_doc = "$(package).texi";'
+$(html_dir): $(install_stamp)
+       $(RM) -r "$@";
+       $(run_in_place)                    \
+        --eval ' pkg load generate_html; ' \
+       $(html_options)                    \
+        --eval ' generate_package_html ("$(package)", "$@", options); ';
+       $(FIX_PERMISSIONS) "$@";
+
+clean-unpacked-release:
+       @echo "## Cleaning unpacked release tarballs (package + html)..."
+       -$(RM) -r $(release_dir) $(html_dir)
+       @echo
+
+##
+## Recipes for installing the package.
+##
+
+.PHONY: install clean-install
+
+octave_install_commands = \
+' llist_path = pkg ("local_list"); \
+  mkdir ("$(installation_dir)"); \
+  load (llist_path); \
+  local_packages(cellfun (@ (x) strcmp ("$(package)", x.name), 
local_packages)) = []; \
+  save ("$(package_list)", "local_packages"); \
+  pkg ("local_list", "$(package_list)"); \
+  pkg ("prefix", "$(installation_dir)", "$(installation_dir)"); \
+  pkg ("install", "-local", "-verbose", "$(release_tarball)"); '
+
+## Install unconditionally. Maybe useful for testing installation with
+## different versions of Octave.
+install: $(release_tarball)
+       @echo "Installing package under $(installation_dir) ..."
+       $(OCTAVE) --eval $(octave_install_commands)
+       touch $(install_stamp)
+
+## Install only if installation (under target/...) is not current.
+$(install_stamp): $(release_tarball)
+       @echo "Installing package under $(installation_dir) ..."
+       $(OCTAVE) --eval $(octave_install_commands)
+       touch $(install_stamp)
+
+clean-install:
+       @echo "## Cleaning installation under $(installation_dir) ..."
+       -$(RM) -r $(installation_dir)
+       @echo
+
+
+##
+## Recipes for testing purposes
+##
+
+.PHONY: run doctest check
+
+## Start an Octave session with the package directories on the path for
+## interactice test of development sources.
+run: $(install_stamp)
+       $(run_in_place) --persist
+
+## Test example blocks in the documentation.  Needs doctest package
+##  https://octave.sourceforge.io/doctest/index.html
+doctest: $(install_stamp)
+       $(run_in_place) --eval 'pkg load doctest;'                              
                            \
+         --eval "targets = '$(shell (ls inst; ls src | $(GREP) .oct) | $(CUT) 
-f2 -d@ | $(CUT) -f1 -d.)';" \
+         --eval "targets = strsplit (targets, ' ');  doctest (targets);"
+
+
+## Test package.
+octave_test_commands = \
+' args = {"inst", "src"}; \
+  args(cellfun (@ (x) isempty (a = stat (x)) || ! S_ISDIR (a.mode), args)) = 
[]; \
+  if (isempty (args)) error ("no \"inst\" or \"src\" directory"); exit (1); \
+    else cellfun(@runtests, args); endif '
+check: $(install_stamp)
+       $(run_in_place) --eval $(octave_test_commands)
+
+
+##
+## CLEAN
+##
+
+.PHONY: clean
+
+clean: clean-tarballs clean-unpacked-release clean-install
+       @echo "## Removing target directory (if empty)..."
+       -rmdir $(target_dir)
+       @echo
+       @echo "## Cleaning done"
+       @echo
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/NEWS new/splines-1.3.4/NEWS
--- old/splines-1.3.3/NEWS      2019-10-23 20:45:53.000000000 +0200
+++ new/splines-1.3.4/NEWS      2021-02-24 02:14:16.000000000 +0100
@@ -1,3 +1,9 @@
+Summary of important user-visible changes for splines 1.3.4:
+-------------------------------------------------------------------
+
+ ** New functions regularization, regularization2D
+
+
 Summary of important user-visible changes for splines 1.3.3:
 -------------------------------------------------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/inst/regularization.m 
new/splines-1.3.4/inst/regularization.m
--- old/splines-1.3.3/inst/regularization.m     1970-01-01 01:00:00.000000000 
+0100
+++ new/splines-1.3.4/inst/regularization.m     2021-02-24 02:14:16.000000000 
+0100
@@ -0,0 +1,175 @@
+## Copyright (C) 2019 Andreas Stahel
+## 
+## 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 3 of the License, 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.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*- 
+## @deftypefn {Function File} {[@var{grid},@var{u}] =} regularization 
(@var{data}, @var{interval}, @var{N}, @var{F1})
+## @deftypefnx {Function File} {[@var{grid},@var{u}] =} regularization 
(@var{data}, @var{interval}, @var{N}, @var{F1}, @var{F2})
+##
+## Apply a Tikhonov regularization, the functional to be minimized is@*
+## @var{F} = @var{FD} + @var{lambda1}*@var{F1} + @var{lambda2}*@var{F2} @*
+##  = sum_(i=1)^M (y_i-u(x_i))^2
+## + @var{lambda1}*int_a^b (u'(x)  - @var{g1}(x))^2 dx
+## + @var{lambda2}*int_a^b (u''(x) - @var{g2}(x))^2 dx
+##
+## With @var{lambda1} = 0 and @var{G2}(x) = 0 this leads to a smoothing spline.
+##
+## Parameters:
+## @itemize
+## @item @var{data} is a M*2 matrix with the x values in the first column and 
the y values in the second column.
+## @item @var{interval} = [a,b] is the interval on which the regularization is 
applied.
+## @item @var{N} is the number of subintervals of equal length. @var{grid} 
will consist of @var{N+1} grid points.
+## @item @var{F1} is a structure containing the information on the first 
regularization term, integrating the square of the first derivative.
+## @itemize
+## @item @var{F1.lambda} is the value of the regularization parameter 
@var{lambda1}>=0.
+## @item @var{F1.g} is the function handle for the function @var{g1(x)}. If 
not provided @var{G1=0} is used.
+## @end itemize
+## @item @var{F2} is a structure containing the information on the second 
regularization term, integrating the square of the second derivative. If 
@var{F2} is not provided @var{lambda2}=0 is assumed.
+## @itemize
+## @item @var{F2.lambda} is the value of the regularization parameter 
@var{lambda2}>=0.
+## @item @var{F2.g} is the function handle for the function @var{g2(x)}. If 
not provided @var{G2=0} is used.
+## @end itemize
+## @end itemize
+##
+## Return values:
+## @itemize
+## @item @var{grid} is the grid on which @var{u} is evaluated. It consists of 
@var{N+1} equidistant points on the @var{interval}.
+## @item @var{u} are the values of the regularized approximation to the 
@var{data} evaluated at @var{grid}.
+## @end itemize
+## @seealso{csaps, regularization2D, demo regularization}
+## @end deftypefn
+
+## Author: Andreas Stahel <[email protected]>
+## Created: 2019-03-26
+
+function [grid,u] = regularization (data, interval, N, F1, F2)
+  a = interval (1);  b = interval (2);
+  grid = linspace (a, b, N + 1)';
+  dx = grid (2) - grid (1);
+  x = data (:, 1);
+  ## select points in interval only
+  ind = find ((x >= a) .* (x <= b));
+  x = x (ind);
+  y = data (:, 2);  y = y (ind);
+  M = length (x);
+  Interp = sparse (M, N + 1);  ## interpolation matrix
+  pos = floor ((x - a) / dx) + 1;
+  theta = mod ((x - a) / dx, 1);
+  for ii = 1:M
+    if theta (ii) > 10*eps
+      Interp (ii, pos (ii)) = 1 - theta (ii);
+      Interp (ii, pos (ii) + 1) = theta (ii);
+    else
+      Interp (ii, pos (ii)) = 1;
+    endif
+  endfor
+  mat = Interp' * Interp;
+  rhs = (Interp' * y);
+  if isfield (F1, 'lambda')
+    A1 = spdiags ([-ones(N, 1), +ones(N, 1)], [0, 1], N, N + 1) / dx;
+    mat = mat + F1.lambda * dx * A1' * A1;
+    if isfield (F1, 'g')
+      g1 = F1.g (grid (1:end - 1) + dx / 2);
+      rhs = rhs + F1.lambda * dx * A1' * g1;
+    endif
+  endif
+  if exist ('F2')
+    A2 = spdiags (ones (N, 1) * [1, -2, 1], [0, 1, 2], N - 1, N + 1) / dx^2;
+    mat = mat + F2.lambda * dx * A2' * A2;
+    if isfield (F2, 'g')
+      g2 = F2.g (grid (2:end - 1));
+      rhs = rhs + F2.lambda * dx * A2' * g2;
+      endif
+  endif
+  u = mat \ rhs;
+endfunction
+
+%!demo
+%! N = 100;   interval = [0,10];
+%! x = [3.2,4,5,5.2,5.6]'; y = x;
+%!
+%! clear F1 F2
+%! %% regularize towards slope 0.1, no smoothing
+%! F1.lambda = 1e-2;   F1.g = @(x)0.1*ones(size(x));
+%! [grid,u1] = regularization([x,y],interval,N,F1);
+%! %% regularize towards slope 0.1, with some smoothing
+%! F2.lambda = 1*1e-3;
+%! [grid,u2] = regularization([x,y],interval,N,F1,F2);
+%!
+%! figure(1)
+%! plot(grid,u1,'b',grid,u2,'g',x,y,'*r')
+%! xlabel('x'); ylabel('solution');
+%! legend('regular1','regular2','data','location','northwest')
+
+%!demo
+%! N = 1000;   interval = [0,pi];
+%! x = linspace( pi/4,3*pi/4,15)';   y = sin(x)+ 0.03*randn(size(x));
+%!
+%! clear F1 F2
+%! %% regularize by smoothing only
+%! F1.lambda = 0;  F2.lambda = 1e-3;
+%! [grid,u1] = regularization([x,y],interval,N,F1,F2);
+%! %% regularize by smoothing and aim for slope 0
+%! F1.lambda = 1*1e-2;
+%! [grid,u2] = regularization([x,y],interval,N,F1,F2);
+%! 
+%! figure(1)
+%! plot(grid,u1,'b',grid,u2,'g',x,y,'*r')
+%! xlabel('x'); ylabel('solution');
+%! legend('regular1','regular2','data','location','northwest')
+
+%!demo
+%! interval = [0,1];
+%! N = 400;
+%! x = rand(200,1);
+%! %% generate the data on four line segments, add some noise
+%! y = 2 - 2*x + (x>0.25) - 2*(x>0.5).*(x<0.65)+ 0.1*randn(length(x),1);
+%! clear F1
+%! %% apply regularization with three different parameters
+%! F1.lambda = 1e-3; [grid,u1] = regularization([x,y],interval,N,F1);
+%! F1.lambda = 1e-1; [grid,u2] = regularization([x,y],interval,N,F1);
+%! F1.lambda = 3e+0; [grid,u3] = regularization([x,y],interval,N,F1);
+%! 
+%! figure(1); plot(grid,u1,'b',grid,u2,'g',grid,u3,'m',x,y,'+r')
+%!            xlabel('x'); ylabel('solution')
+%!            legend('\lambda_1=0.001','\lambda_1=0.1','\lambda_1=3','data')
+
+%!demo
+%! %% generate a smoothing spline, see also csaps() in the package splines
+%! N = 1000;  interval = [0,10.3];
+%! x = [0 3 4 6 10]';  y = [0 1 0 1 0]';
+%! clear F2
+%! F2.lambda = 1e-2;
+%! %% apply regularization, the result is a smoothing spline
+%! [grid,u] = regularization([x,y],interval,N,0,F2);
+%! 
+%! figure(1);
+%! plot(grid,u,'b',x,y,'*r')
+%! legend('spline','data')
+%! xlabel('x'); ylabel('solution')
+
+
+%!test
+%! data = [0,0;1,1;2,2];
+%! F1.lambda = 0.0; F2.lambda = 0.1;
+%! [grid,u] = regularization(data,[0,1],10,F1,F2);
+%! assert(norm(grid-u),0,1e-12)
+
+%!test
+%! x = linspace(-1,1,11); 
+%! F1.lambda = 0.01;F2.g = @(x) 2*ones(size(x)); F2.lambda = 0.01;
+%! [grid,u] = regularization([x;x.^2]',[-2,2],20,F1,F2);
+%! assert(u(11),7.330959483903200e-03,1e-8)
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/splines-1.3.3/inst/regularization2D.m 
new/splines-1.3.4/inst/regularization2D.m
--- old/splines-1.3.3/inst/regularization2D.m   1970-01-01 01:00:00.000000000 
+0100
+++ new/splines-1.3.4/inst/regularization2D.m   2021-02-24 02:14:16.000000000 
+0100
@@ -0,0 +1,161 @@
+## Copyright (C) 2021 Andreas Stahel
+## 
+## 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 3 of the License, 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.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*- 
+## @deftypefn {Function File} {[@var{grid},@var{u},@var{data_valid}] =} 
regularization2D (@var{data}, @var{box}, @var{N}, @var{lambda1},@var{lambda2})
+##
+## Apply a Tikhonov regularization, the functional to be minimized is@*
+## @var{F} = @var{FD} + @var{lambda1} * @var{F1} + @var{lambda2} * @var{F2} @*
+##   = sum_(i=1)^M (y_i-u(x_i))^2 +@*
+##  + @var{lambda1} * dintegral (du/dx)^2+(du/dy)^2 dA +@*
+##  + @var{lambda2} * dintegral (d^2u/dx^2)^2+(d^2u/dy^2)^2+2*(d^2u/dxdy) dA
+##
+## With @var{lambda1} = 0 and @var{lambda2}>0 this leads to a thin plate 
smoothing spline.
+##
+## Parameters:
+## @itemize
+## @item @var{data} is a M*3 matrix with the (x,y) values in the first two 
columns and the y values in the third column.@*
+## Only data points strictly inside the @var{box} are used
+## @item @var{box} = [x0,x1;y0,y1] is the rectangle x0<x<x1 and y0<y<y1 on 
which the regularization is applied.
+## @item @var{N} = [N1,N2] determines the number of subintervals of equal 
length. @var{grid} will consist of (@var{N1+1})x(@var{N2+1}) grid points.
+## @item @var{lambda1} >= 0 is the value of the first regularization parameter
+## @item @var{lambda2} > 0 is the value of the secondregularization parameter
+## @end itemize
+##
+## Return values:
+## @itemize
+## @item @var{grid} is the grid on which @var{u} is evaluated. It consists of
+## (@var{N1+1})x(@var{N2}+1) equidistant points on the the rectangle @var{box}.
+## @item @var{u} are the values of the regularized approximation to the 
@var{data} evaluated on the @var{grid}.
+## @item @var{data_valid} returns the values data points used and the values 
of the regularized function at these points
+## @end itemize
+## @seealso {tpaps, regularization, demo regularization2D}
+## @end deftypefn
+
+## Author: Andreas Stahel <[email protected]>
+## Created: 2021-01-13
+
+function [grid,u,data_valid] = regularization2D (data, box, N, lambda1, 
lambda2)
+%% generate the grid
+  N = N+1;  %%%  now N is the number of grid points in either direction
+  x = linspace(box(1,1),box(1,2),N(1));
+  y = linspace(box(2,1),box(2,2),N(2));
+  [xx,yy] = meshgrid(x,y);
+  dx = diff(box(1,:))/(N(1)-1);  dy = diff(box(2,:))/(N(2)-1);
+  grid.x  = xx;
+  grid.y  = yy;
+  x = data (:,1); y = data(:,2); z = data(:,3); 
+  ## select points in box only
+  ind = find ((x > box(1,1)) .* (x < box(1,2)) .* (y > box(2,1)) .* (y < 
box(2,2)));
+  x = x (ind); y = y (ind); z = z (ind);
+  %% generate the sparse interpolation matrix
+  M = length (x);
+  x_ind = floor((x-box(1,1))/dx);
+  %% xi = mod(x,dx)/dx;
+  xi = (x-box(1,1)-x_ind*dx)/dx;
+  y_ind = floor((y-box(2,1))/dy);
+  %%nu = mod(y,dy)/dy;
+  nu = (y-box(2,1)-y_ind*dy)/dy;
+  row = ones(4,1)*[1:M]; 
+  index_base = N(2)*x_ind+y_ind+1;
+  index = index_base + [0,N(2),1,N(2)+1]; index = index';
+  coeff = [(1-xi).*(1-nu),xi.*(1-nu),(1-xi).*nu,xi.*nu]; coeff = coeff';
+  Interp = sparse(row(:),index(:),coeff(:),M,N(1)*N(2));
+  mat = Interp' * Interp;
+  rhs = (Interp' * z);
+  
+%%% derivative with respect to x
+  Dx = kron(spdiags(ones(N(1),1)*[-1 1],[0 1],N(1)-1,N(1))/dx,speye(N(2)));
+  Wx = ones(N(2),1); Wx(1) = 1/2; Wx(N(2)) = 1/2;
+  Wx = kron(speye(N(1)-1),diag(Wx))*dx*dy;
+%%% derivative with respect to y
+ 
+  Wy = ones(N(1),1); Wy(1) = 1/2; Wy(N(1)) = 1/2;
+  Wy = kron(diag(Wy),speye(N(2)-1))*dx*dy;
+  if lambda1 > 0
+    Dy = kron(speye(N(1)),spdiags(ones(N(2),1)*[-1 1],[0 1],N(2)-1,N(2))/dy);
+    mat += lambda1*(Dx'*Wx*Dx + Dy'*Wy*Dy);
+  endif
+
+%%% second derivative with respect to x
+  Dxx = spdiags(ones(N(1),1)*[1 -1 -1 1],[-1 0 1 2],N(1)-1,N(1));
+  Dxx(1,1:4) = [3 -7 5  -1]; Dxx(N(1)-1,N(1)-3:N(1)) = [-1 5 -7 3];
+  Dxx = Dxx/(2*dx^2);
+  Dxx = kron(Dxx,speye(N(2)));
+%%% second derivative with respect to y
+  Dyy = spdiags(ones(N(2),1)*[1 -1 -1 1],[-1 0 1 2],N(2)-1,N(2));
+  Dyy(1,1:4) = [3 -7 5  -1]; Dyy(N(2)-1,N(2)-3:N(2)) = [-1 5 -7 3];
+  Dyy = Dyy/(2*dy^2);
+  Dyy = kron(speye(N(1)),Dyy);
+%%% mixed second derivative
+  Dy2 = kron(speye(N(1)-1),spdiags(ones(N(2),1)*[-1 1],[0 1],N(2)-1,N(2))/dy);
+  Dxy = Dy2*Dx*sqrt(dx*dy);
+  mat += lambda2*(Dxx'*Wx*Dxx + Dyy'*Wy*Dyy + 2*Dxy'*Dxy);
+
+%%% solve
+  u = reshape(mat\rhs,N(2),N(1));
+  if nargout>2
+    data_valid =[x,y,Interp*u(:)];
+  endif
+
+endfunction
+
+%!demo
+%! M = 100;
+%! lambda1 = 0; lambda2 = 0.05;
+%! x = 2*rand(M,1)-1;     y = 2*rand(M,1)-1;
+%! z = x.*y + 0.1*randn(M,1);
+%! data = [x,y,z];
+%! [grid,u] = regularization2D(data,[-1 1;-1 1],[50 50],lambda1,lambda2);
+%! figure()
+%! mesh(grid.x, grid.y,u)
+%! xlabel('x'); ylabel('y');
+%! hold on
+%! plot3(data(:,1),data(:,2),data(:,3),'*b','Markersize',2)
+%! hold off
+%! view([30,30]);
+
+%!demo
+%! lambda1 = 0; lambda2 = 0.01;
+%! M = 4;  angles = [1:M]/M*2*pi;  
+%! data = zeros(M+1,3);  data(M+1,3) = 1;
+%! data(1:M,1) = cos(angles); data(1:M,2) = sin(angles);
+%! [grid,u] = regularization2D(data,[-1.5 1.5;-1.5 1.5],[50 
50],lambda1,lambda2);
+%! figure()
+%! mesh(grid.x, grid.y,u)
+%! xlabel('x'); ylabel('y');
+%! hold on
+%! plot3(data(:,1),data(:,2),data(:,3),'*b','Markersize',2)
+%! hold off
+
+%!test
+%! data = [0,0,0;1,2,3;2,0,2;0,2,2];  % data on z = x+y
+%! lambda1 = 0.0 ; lambda2 = 0.1;
+%! [grid,u,u_valid] = regularization2D(data,[-0.2 2.2; 
-0.2,2.2],[11,12],lambda1,lambda2);
+%! assert(norm(data-u_valid),0,1e-12)
+%! assert(norm(grid.x(:) + grid.y(:) - u(:)),0,1e-10)
+
+%!test
+%! data = [0,0,0;1,1,3;2,1,2;0,2,-2;-1.5,-1,0;-2,2,0];
+%! lambda1 = 0.001 ; lambda2 = 0.01;
+%! [grid,u,u_valid] = regularization2D(data,[-2.1 
2.1;-2.1,2.1],[40,50],lambda1,lambda2);
+%!  value_at_data = [   1.233351091378741e-01
+%!   2.694454049778803e+00
+%!   2.102786670571836e+00
+%!  -1.870655633783656e+00
+%!  -1.635243922246946e-02
+%!  -3.356775648311422e-02];
+%! assert(norm(value_at_data-u_valid(:,3)),0,1e-12)

Reply via email to