-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgetTOARmapGrid.m
More file actions
231 lines (189 loc) · 8.74 KB
/
getTOARmapGrid.m
File metadata and controls
231 lines (189 loc) · 8.74 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
function ck = getTOARmapGrid(resolution, keepOnlyLand , includeAntarctica, gridOffset)
% getTOARmapGrid - Generates estimation grid on land for TOAR mapping
%
% Creates and caches a regular grid of estimation points covering land areas
%
% SYNTAX:
% ck = getTOARmapGrid(resolution, includeAntarctica)
%
% INPUTS:
% resolution - Grid resolution in degrees (e.g., 0.5, 1.0)
% default: 1.0
% keepOnlyLand - Include only land points in grid (true/false)
% default: true
% includeAntarctica - Include Antarctica in grid (true/false)
% default: false
% gridOffset - Optional [lonOffset, latOffset] to shift grid points (default: [0, 0])
%
% OUTPUT:
% ck - [nPoints x 2] matrix of estimation points [lon, lat]
%
% EXAMPLE:
% ck = getTOARmapGrid(0.5, true, false); % 0.5° grid, no Antarctica
% ck = getTOARmapGrid(1.0, true, true); % 1.0° grid, with Antarctica
if nargin < 1, resolution = 1.0; end
if nargin < 2, keepOnlyLand = true; end
if nargin < 3, includeAntarctica = false; end
if nargin < 4, gridOffset = [0, 0]; end
% Setup directories
dataDir = '1data';
gridSubdir = fullfile(dataDir, 'grids');
if ~exist(gridSubdir, 'dir'), mkdir(gridSubdir); end
% Filename based on parameters (include offset in cache key when non-zero)
if any(gridOffset ~= 0)
gridFile = sprintf('map_grid_res%.2f_onlyLand%d_antarctica%d_off%.3f_%.3f.mat', ...
resolution, keepOnlyLand, includeAntarctica, gridOffset(1), gridOffset(min(2,end)));
else
gridFile = sprintf('map_grid_res%.2f_onlyLand%d_antarctica%d.mat', resolution, keepOnlyLand, includeAntarctica);
end
gridPath = fullfile(gridSubdir, gridFile);
% Load from cache if exists
if exist(gridPath, 'file')
fprintf('Loading existing map grid: %s\n', gridFile);
load(gridPath, 'ck');
fprintf(' %d grid points loaded\n', size(ck, 1));
return;
end
fprintf('Generating map grid (%.2f° resolution)...\n', resolution);
% Generate global grid
[lon_grid, lat_grid] = meshgrid(-180:resolution:180, -90:resolution:90);
grid_all = [lon_grid(:), lat_grid(:)];
% Apply grid offset if specified
if any(gridOffset ~= 0)
fprintf('Applying grid offset: [%.2f, %.2f] degrees\n', gridOffset(1), gridOffset(2));
grid_all(:, 1) = grid_all(:, 1) + gridOffset(1);
grid_all(:, 2) = grid_all(:, 2) + gridOffset(2);
end
% Filter Antarctica if requested
if ~includeAntarctica
grid_all = grid_all(grid_all(:, 2) > -60, :);
end
% Keep only land points
if keepOnlyLand
fprintf(' Filtering to land points only using coastlines.mat...\n');
% Try coastlines.mat first (produces better quality results)
coastFile = fullfile(dataDir, 'coastlines.mat');
if exist(coastFile, 'file')
try
coast = load(coastFile, 'coastlon', 'coastlat');
on_land = inpolygon(grid_all(:, 1), grid_all(:, 2), ...
coast.coastlon, coast.coastlat);
ck = grid_all(on_land, :);
nPoints = size(grid_all, 1);
fprintf(' Land filtering complete: %d/%d points on land (%.1f%% reduction)\n', ...
sum(on_land), nPoints, 100*(1 - sum(on_land)/nPoints));
catch ME
warning('Could not load coastlines.mat: %s', ME.message);
fprintf(' Attempting fallback to landareas.shp...\n');
% Fallback to landareas.shp
try
% Use MATLAB's built-in landareas.shp (from Mapping Toolbox)
landShapefile = 'landareas.shp';
landAreas = shaperead(landShapefile);
fprintf(' Loaded %d land polygons from landareas.shp\n', length(landAreas));
% Pre-allocate logical array
on_land = false(size(grid_all, 1), 1);
% Check each point against all land polygons
% Use a more efficient approach: check batches of points
nPoints = size(grid_all, 1);
nPolygons = length(landAreas);
fprintf(' Checking %d grid points against %d land polygons...\n', nPoints, nPolygons);
% For each land polygon, check which points are inside
for iPoly = 1:nPolygons
if mod(iPoly, 100) == 0
fprintf(' Processing polygon %d/%d (%.1f%%)...\n', ...
iPoly, nPolygons, 100*iPoly/nPolygons);
end
% Get polygon coordinates
polyLon = landAreas(iPoly).X(:);
polyLat = landAreas(iPoly).Y(:);
% Remove NaN separators
validIdx = ~isnan(polyLon) & ~isnan(polyLat);
polyLon = polyLon(validIdx);
polyLat = polyLat(validIdx);
% Skip if polygon is empty
if isempty(polyLon)
continue;
end
% Check which points (not yet marked as land) are in this polygon
% This optimization skips points already identified as land
pointsToCheck = ~on_land;
if any(pointsToCheck)
in_this_poly = inpolygon(grid_all(pointsToCheck, 1), ...
grid_all(pointsToCheck, 2), ...
polyLon, polyLat);
% Update the land mask
temp = find(pointsToCheck);
on_land(temp(in_this_poly)) = true;
end
end
ck = grid_all(on_land, :);
fprintf(' Land filtering complete: %d/%d points on land (%.1f%% reduction)\n', ...
sum(on_land), nPoints, 100*(1 - sum(on_land)/nPoints));
catch ME2
warning('Could not load landareas.shp: %s', ME2.message);
warning('No land filtering available. Using all grid points.');
ck = grid_all;
end
end
else
% coastlines.mat doesn't exist, try landareas.shp
fprintf(' coastlines.mat not found. Attempting landareas.shp...\n');
try
% Use MATLAB's built-in landareas.shp (from Mapping Toolbox)
landShapefile = 'landareas.shp';
landAreas = shaperead(landShapefile);
fprintf(' Loaded %d land polygons from landareas.shp\n', length(landAreas));
% Pre-allocate logical array
on_land = false(size(grid_all, 1), 1);
% Check each point against all land polygons
% Use a more efficient approach: check batches of points
nPoints = size(grid_all, 1);
nPolygons = length(landAreas);
fprintf(' Checking %d grid points against %d land polygons...\n', nPoints, nPolygons);
% For each land polygon, check which points are inside
for iPoly = 1:nPolygons
if mod(iPoly, 100) == 0
fprintf(' Processing polygon %d/%d (%.1f%%)...\n', ...
iPoly, nPolygons, 100*iPoly/nPolygons);
end
% Get polygon coordinates
polyLon = landAreas(iPoly).X(:);
polyLat = landAreas(iPoly).Y(:);
% Remove NaN separators
validIdx = ~isnan(polyLon) & ~isnan(polyLat);
polyLon = polyLon(validIdx);
polyLat = polyLat(validIdx);
% Skip if polygon is empty
if isempty(polyLon)
continue;
end
% Check which points (not yet marked as land) are in this polygon
% This optimization skips points already identified as land
pointsToCheck = ~on_land;
if any(pointsToCheck)
in_this_poly = inpolygon(grid_all(pointsToCheck, 1), ...
grid_all(pointsToCheck, 2), ...
polyLon, polyLat);
% Update the land mask
temp = find(pointsToCheck);
on_land(temp(in_this_poly)) = true;
end
end
ck = grid_all(on_land, :);
fprintf(' Land filtering complete: %d/%d points on land (%.1f%% reduction)\n', ...
sum(on_land), nPoints, 100*(1 - sum(on_land)/nPoints));
catch ME
warning('Could not load landareas.shp: %s', ME.message);
warning('No land filtering available. Using all grid points.');
ck = grid_all;
end
end
else
ck = grid_all;
end
% Save to cache
fprintf(' Generated %d land points\n', size(ck, 1));
fprintf(' Saving to: %s\n', gridPath);
save(gridPath, 'ck', '-v7.3');
end