.nminterp.spline
author Andreas Thurnherr <ant@ldeo.columbia.edu>
Mon, 13 Apr 2020 11:06:22 -0400
changeset 40 c1803ae2540f
parent 39 56bdfe65a697
permissions -rw-r--r--
.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     1
#======================================================================
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     2
#                    . N M I N T E R P . S P L I N E 
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     3
#                    doc: Wed Nov 22 21:01:09 2000
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     4
#                    dlm: Fri Sep 23 16:52:31 2011
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     5
#                    (c) 2000 A.M. Thurnherr
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     6
#                    uE-Info: 19 50 NIL 0 0 72 2 2 4 NIL ofnI
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     7
#======================================================================
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     8
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
     9
# spline interpolation for [fillgaps]
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    10
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    11
# HISTORY:
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    12
#	Apr  3, 2006: - created from [.interp.spline]
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    13
#	Jul 28, 2006: - made to work
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    14
#	Jul 30, 2006: - added max-gap support
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    15
#				  - BUG: extended interpolation into last interval
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    16
#				  - BUG: assertions made it incompatible with decreasing data
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    17
#	Aug  8, 2008: - renamed
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    18
#	Sep 23, 2011: - removed $xv from interpolate() args
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    19
#				  - added error when xf<0 (%RECNO)
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    20
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    21
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    22
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    23
# THE FOLLOWING VARIABLES MUST BE SET GLOBALLY (i.e. during loading)
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    24
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    25
#	$ISOpts				string of allowed options
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    26
#	$ISOptsUsage		usage information string for options
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    27
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    28
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    29
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    30
$ISOpts = '';
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    31
$ISOptsUsage = '';
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    32
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    33
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    34
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    35
# &ISUsage() 	mangle parameters (options, really)
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    36
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    37
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    38
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    39
sub ISUsage() {}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    40
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    41
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    42
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    43
# &ISInit(f,xf)				init interpolation of field f
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    44
#       f					field number
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    45
#		xf					x field number
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    46
#       <ret val>           none
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    47
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    48
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    49
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    50
my(@y2);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    51
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    52
sub ISInit($$) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    53
	my($f,$xf) = @_;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    54
	my($k,$i,$p,$qn,$sig,$un,@u);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    55
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    56
	croak(".nminterp.spline: cannot use %RECNO as x-field (implementation restriction)\n")
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    57
		unless ($xf >= 0);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    58
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    59
	my($pi,$ppi,$li);				# find idx of first 3 & last valid recs
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    60
	for (my($r)=0; $r<=$#ants_; $r++) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    61
		if (numberp($ants_[$r][$f])) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    62
			unless (defined($ppi)) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    63
				$ppi = $pi; $pi = $i; $i = $r;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    64
			}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    65
			$li = $r;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    66
		}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    67
	}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    68
	unless (defined($ppi)) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    69
		&antsInfo("WARNING: not enough <$antsLayout[$f]> data for spline interpolation");
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    70
		return;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    71
	}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    72
		
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    73
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    74
	my($fpi) = $pi;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    75
	$y2[$pi][$f] = $u[$pi] = 0;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    76
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    77
	for (; $i<=$li; $i++) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    78
		next unless numberp($ants_[$i][$f]);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    79
		
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    80
		$sig = ($ants_[$pi][$xf]-$ants_[$ppi][$xf]) /
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    81
				($ants_[$i][$xf]-$ants_[$ppi][$xf]);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    82
		$p = $sig*$y2[$pi][$f] + 2;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    83
		$y2[$i][$f] = ($sig-1)/$p;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    84
		$u[$i] = ($ants_[$i][$f]-$ants_[$pi][$f]) /
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    85
					($ants_[$i][$xf]-$ants_[$pi][$xf])
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    86
						- ($ants_[$pi][$f]-$ants_[$ppi][$f]) /
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    87
							($ants_[$pi][$xf]-$ants_[$ppi][$xf]);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    88
		$u[$i] = (6*$u[$i]/($ants_[$i][$xf]-$ants_[$ppi][$xf]) -
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    89
					$sig * $u[$pi]) / $p;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    90
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    91
		$ppi = $pi; $pi = $i;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    92
	}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    93
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    94
	$qn = $un = 0;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    95
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    96
	$y2[$li][$f] = ($un-$qn*$u[$pi]) / ($qn*$y2[$pi][$f]+1);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    97
	my($pk) = $li;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    98
	for ($k=$pi; $k>=$fpi; $k--) {
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
    99
		next unless numberp($ants_[$k][$f]);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   100
		$y2[$k][$f] = $y2[$k][$f] * $y2[$pk][$f] + $u[$k];
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   101
		$pk = $k;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   102
	}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   103
}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   104
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   105
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   106
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   107
# &interpolate(xf,mg,f,lvr,cr)	interpolate field f
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   108
#		xf							x field
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   109
#		mg							max allowed x gap
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   110
#		f							field number to interpolate
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   111
#		lvr							last record with valid y val
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   112
#		cr							current record
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   113
#		<ret val>					interpolated value
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   114
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   115
# NB:
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   116
#	- handle f == xf
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   117
#	- return undef if interpolation cannot be carried out
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   118
#	- x VALUES MAY NOT BE MONOTONIC
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   119
#
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   120
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   121
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   122
sub interpolate($$$$$$)
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   123
{
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   124
	my($xf,$mg,$f,$lvr,$cr) = @_;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   125
	
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   126
	return $ants_[$cr][$xf] if ($xf == $f);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   127
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   128
	return $ants_[$lvr][$f]							# edge values are ok
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   129
		if equal($ants_[$cr][$xf],$ants_[$lvr][$xf]);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   130
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   131
	my($nvr1) = $cr + 1;							# find next
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   132
	while ($nvr1 <= $#y2 && !numberp($y2[$nvr1][$f])) { $nvr1++; }
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   133
	return undef									# none or gap too large
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   134
		if ($nvr1>$#ants_ || abs($ants_[$nvr1][$xf]-$ants_[$lvr][$xf])>$mg);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   135
	return $ants_[$nvr1][$f]						# edge values are ok
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   136
		if equal($ants_[$cr][$xf],$ants_[$nvr1][$xf]);
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   137
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   138
	my($nvr2) = $nvr1 + 1;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   139
	while ($nvr2 <= $#y2 && !numberp($y2[$nvr2][$f])) { $nvr2++; }
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   140
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   141
	my($h) = $ants_[$nvr1][$xf] - $ants_[$lvr][$xf];
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   142
	my($a) = ($ants_[$nvr1][$xf] - $ants_[$cr][$xf]) / $h;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   143
	my($b) = ($ants_[$cr][$xf] - $ants_[$lvr][$xf]) / $h;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   144
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   145
	return $a*$ants_[$lvr][$f] + $b*$ants_[$nvr1][$f] +
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   146
			(($a*$a*$a-$a) * $y2[$nvr1][$f] +
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   147
			 ($b*$b*$b-$b) * $y2[$nvr2][$f]) *
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   148
			 	($h*$h)/6;
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   149
}
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   150
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   151
#----------------------------------------------------------------------
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   152
A.M. Thurnherr <athurnherr@yahoo.com>
parents:
diff changeset
   153
1;