forked from dmkaplan2000/openMA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopenMA_modes_fit_with_errors_NaNs.m
159 lines (138 loc) · 5.23 KB
/
openMA_modes_fit_with_errors_NaNs.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
function [ alpha, cov_alpha, ux, uy ] = openMA_modes_fit_with_errors_NaNs( varargin )
% OPENMA_MODES_FIT_WITH_ERRORS_NANS - fits modes to data with error
% propagation and taking NaN's into account.
%
% Usage: [alpha,cov_alpha,ux,uy] = openMA_modes_fit_with_errors_NaNs( ...
% ux, uy, K, theta, magn, weights,
% covaraince_matrix )
% [alpha,cov_alpha,ux,uy] = openMA_modes_fit_with_errors_NaNs( ...
% vfm, dfm, bm, K, cc, theta, ...
% magn, weights, covaraince_matrix )
%
% This function is identical to openMA_modes_fit_with_errors, except that there can
% be some bad data (represented by NaN's or inf's). See that function
% for additional documentation.
%
% Note also that weights can now have multiple columns for each column of
% data (though empty or a single column vector for weights is still
% acceptable).
%
% openMA_modes_fit_with_errors could be slightly faster if there is no bad
% or missing data, but generally it is easier to use this function.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% $Id: openMA_modes_fit_with_errors_NaNs.m 70 2007-02-22 02:24:34Z dmk $
%
% Copyright (C) 2006 David M. Kaplan
% Licence: GPL (Gnu Public License)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Find out type of input arguments - mode structures or matrices
if isa(varargin{1},'struct') | isempty( varargin{1} )
[K,cc] = deal( varargin{4:5} );
% This next line is usually very time consuming compared to the time it
% takes to fit the data to the interpolated modes.
[ux,uy] = openMA_modes_interp( cc, varargin{1:3} );
varargin = varargin(6:end);
else
[ux,uy,K] = deal( varargin{1:3} );
varargin = varargin(4:end);
end
if length(varargin) ~= 4
error( 'Bad input arguments' )
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Get basic matrices that go into linear model.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[theta,magn,weights,covmat] = deal( varargin{:} );
% Deal with empty weights
if isempty( weights )
weights = 1;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Figure out what type of covariance matrix we were given
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if length(size(covmat)) == 3
% Must be full covariance matrix for each timestep
cmt = 3;
% Check to make sure size is correct
if ~all( size(covmat) == [ size(magn,1), size(magn,1), size(magn,2) ] )
error( 'covaraince matrix does not appear to be correct size.' );
end
elseif prod(size(covmat)) == 1
% Scalar
cmt = 1;
else % Must be a 2D matrix - now need to figure out what that means.
if all( size(covmat) == size(magn) )
% Case where we have multiple timesteps, and each column are the
% variances for that timestep (covariances are zero).
cmt = 2;
elseif size(magn,2)==1 & ...
all( size(covmat) == [size(magn,1),size(magn,1)] )
% Case where we have one timestep, but use a full covariance matrix.
cmt = 3;
else
error( 'covaraince matrix does not appear to be correct size. cmt=2' );
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Deal with bad data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Do this just in case we have a lot of rows missing the same data points
% and having the same weights - potentially faster than just looping over
% columns. In particular, for all good data and a scalar weight, this
% function should take basically the same amount of time as
% openMA_modes_fit.
if prod(size(weights)) == length(weights)
[BD,II,JJ] = unique( isfinite(magn)', 'rows' );
BD = BD';
else
% If different weights for each column, must run each column separately
% through openMA_modes_fit_with_errors.
% Better have as many weight columns as magnitude columns.
[BD,II,JJ] = unique( [ isfinite(magn); weights ]', 'rows' );
BD = logical(BD(:,1:end/2))';
end
disp( [ 'openMA_modes_fit_NaNs: Loop over ' int2str(length(II)) ...
' "data groups" which correspond to ' int2str(size(magn,2)) ...
' data columns.' ] );
cn = 10^(max(1,floor(log10(length(II))-1)));
disp( [ 'openMA_modes_fit_with_errors_NaNs: Will count by ' int2str(cn) ...
'.' ] );
% Initialize matrices
alpha = zeros( size(ux,2), size(magn,2) );
cov_alpha = zeros( size(ux,2), size(ux,2), size(magn,2) );
% Loop and do fits
for k = 1:length(II)
if mod(k,cn) == 1
disp( [ 'Loop number ' int2str(k) '.' ] );
end
mn = magn( BD(:,k), JJ == k );
th = theta( BD(:,k) );
uu = ux( BD(:,k), : );
vv = uy( BD(:,k), : );
% Deal with scalar, vector and matrix weights as openMA_modes_fit can
% only accept a single vector or a scalar.
if prod(size(weights)) == 1
we = weights;
elseif prod(size(weights)) == length(weights)
we = weights( BD(:,k) );
else
we = weights( BD(:,k), JJ == k );
we = we(:,1);
end
% Deal with different types of covariance matrices
switch cmt
case 1
cm = covmat;
case 2
cm = covmat( BD(:,k), JJ == k );
case 3
cm = covmat( BD(:,k), BD(:,k), JJ == k );
end
%keyboard
[aa,ca] = openMA_modes_fit_with_errors( uu, vv, K, th, mn, we, cm );
alpha( :, JJ == k ) = aa;
cov_alpha( :, :, JJ == k ) = ca;
end