|
| 1 | +function itrfmap(refto, reffrom, refepoch, latrange, lonrange, sel, pmm, tecplate,id) |
| 2 | +%ITRFMAP Plot map of ITRF/ETRF velocity and coordinate changes. |
| 3 | +% ITRFMAP(REFTO,REFFROM,EPOCH,LATRANGE,LONGRANGE) plots the difference |
| 4 | +% in velocity for the reference frame REFTO with the velocity in REFFROM |
| 5 | +% on a map with latitude range LATRANGE and longitude range LONRANGE. |
| 6 | +% EPOCH is the epoch, but this is only used internally for the computation |
| 7 | +% and has no significance for the velocity output. |
| 8 | +% |
| 9 | +% ITRFMAP(...,SEL), with SEL='pos', plots the coordinate differences |
| 10 | +% instead of the velocity differences (SEL='vel' is the default). EPOCH |
| 11 | +% is the epoch for the coordinate difference. |
| 12 | +% |
| 13 | +% ITRFMAP(...,SEL,PMM,TECPLATE) applies a correction to REFTO using |
| 14 | +% the plate motion model given by PMM for tectonic plates TECPLATE. |
| 15 | +% |
| 16 | +% ITRFMAP(...,SEL,PMM,TECPLATE,ID) reads high-resolution shape files |
| 17 | +% for land areas, rivers and borders (if available) with ID. The only |
| 18 | +% high-resolution data currently supported is ID='nweurope` and the |
| 19 | +% shapefiles must on the search path. Default (ID='none') is to use |
| 20 | +% low resolution maps that come with the Matlab mapping toolbox. |
| 21 | +% |
| 22 | +% A short legend to the available arguments is: |
| 23 | +% |
| 24 | +% Reference frames Plate motion model (none/pmm) -----+ |
| 25 | +% from ------------+ | |
| 26 | +% to ------+ | Plot type (vel/pos) --+ | |
| 27 | +% | | | | |
| 28 | +% v v v v |
| 29 | +% itrfmap(refto, reffrom, epoch, latrange, lonrange, sel, pmm, tecplate, id) |
| 30 | +% |
| 31 | +% Supported reference frames are [ "ETRF2020"; "ETRF2014"; "ETRF2000"; |
| 32 | +% "ITRF2020"; "ITRF2014"; "ITRF2008"; "ITRF2005"; "ITRF2000"; "ITRF97"; "ITRF96"; |
| 33 | +% "ITRF94"; "ITRF93"; "ITRF92"; "ITRF91"; "ITRF90"; "ITRF89"; "ITRF88" ]. |
| 34 | +% |
| 35 | +% Supported plate motion models PMM are [ "none"; "NUVEL 1A NNR"; "ITRF2000"; |
| 36 | +% "ITRF2008"; "ITRF2014"; "ITRF2020"; "GSRM 2.1 IGS08"; "GSRM 2.1 NNR" ]. |
| 37 | +% The tectonic plate TECPLATE can be specified by it's full name, four- |
| 38 | +% and two character abbreviation. The supported plates depend on the |
| 39 | +% plate motion model being used. Some of the possible values for TECPLATE |
| 40 | +% are [ "Africa"; "Antarctica"; "Arabia"; "Australia"; "Caribbean"; "Cocos"; |
| 41 | +% "Eurasia"; "India"; "Nazca"; "NorthAmerica"; "Pacific"; "SouthAmerica" ]; |
| 42 | +% |
| 43 | +% Examples: |
| 44 | +% |
| 45 | +% latrange=[35 68]; lonrange=[-12 35 ]; % Europe |
| 46 | +% |
| 47 | +% itrfmap('ITRF2008', 'ETRF2000', 2010.0, latrange, lonrange) |
| 48 | +% itrfmap('ITRF2014', 'ETRF2000', 2018.0, latrange, lonrange, 'vel') |
| 49 | +% itrfmap('ITRF2020', 'ETRF2000', 2020.0, latrange, lonrange, 'vel', 'none') |
| 50 | +% itrfmap('ITRF2008', 'ETRF2000', 2020.0, latrange, lonrange, 'vel', 'GSRM 2.1 IGS08', 'Eurasia') |
| 51 | +% |
| 52 | +% itrfmap('ITRF2020', 'ITRF2014', 2020.0, latrange, lonrange, 'vel', 'none') |
| 53 | +% |
| 54 | +% itrfmap('ITRF2008', 'ETRF2020', 1989.0, latrange, lonrange, 'pos', 'none') |
| 55 | +% itrfmap('ITRF2008', 'ETRF2020', 2020.0, latrange, lonrange, 'pos', 'GSRM 2.1 IGS08', 'Eurasia') |
| 56 | +% itrfmap('ITRF2020', 'ETRF2020', 1989.0, latrange, lonrange, 'pos', 'none') |
| 57 | +% itrfmap('ITRF2020', 'ETRF2020', 2020.0, latrange, lonrange, 'pos', 'ITRF2020', 'Eurasia') |
| 58 | +% |
| 59 | +% latrange=[50 54.5]; lonrange=[1.5 8.5 ]; % Netherlands |
| 60 | +% addpath('d:\Surfdrive\Matlab\models\') % Path to high resolution maps |
| 61 | +% |
| 62 | +% itrfmap('ITRF2008', 'ETRF2000', 2020.0, latrange, lonrange, 'vel', 'GSRM 2.1 IGS08', 'Eurasia','nweurope') |
| 63 | +% itrfmap('ETRF2020', 'ETRF2014', 2020.0, latrange, lonrange, 'vel', 'none', 'none', 'nweurope') |
| 64 | +% |
| 65 | +% See also ITRF2ITRF and PMMVEL. |
| 66 | +% |
| 67 | +% Requires the Matlab mapping toolbox (if not available, should not be |
| 68 | +% too difficult to adjust the plotting part using coastlines only). |
| 69 | +% |
| 70 | +% (c) Hans van der Marel, Delft University of Technology, 2018-2025. |
| 71 | + |
| 72 | +% Created: 9 February 2018 by Hans van der Marel |
| 73 | +% Modified: 2 June 2025 by Hans van der Marel |
| 74 | +% - Major overhaul using itrf toolbox version 2 (with newly |
| 75 | +% added pmm functions and support for more TRF's) |
| 76 | +% - optional correction for plate motion (pmm) |
| 77 | +% - choice between plotting velocity differences and position |
| 78 | +% differences |
| 79 | +% - added option for low-resolution maps (useful when high |
| 80 | +% resolution shape files are unavailable) |
| 81 | +% 14 July 2025 by Hans van der Marel |
| 82 | +% - single figure with subplots |
| 83 | +% - added extra argument for high resolution maps |
| 84 | +% - added function help |
| 85 | + |
| 86 | +tic |
| 87 | + |
| 88 | +% Check arguments |
| 89 | + |
| 90 | +if nargin < 9 |
| 91 | + id='none'; |
| 92 | + if nargin < 7 |
| 93 | + pmm='none'; |
| 94 | + if nargin < 6 |
| 95 | + sel='vel'; |
| 96 | + end |
| 97 | + end |
| 98 | +end |
| 99 | +if nargin < 5 || ( nargin == 7 && ~strcmpi(pmm,'none') ) |
| 100 | + error('insufficient number of input arguments') |
| 101 | +end |
| 102 | + |
| 103 | +% Compute meshgrid |
| 104 | + |
| 105 | +bbox = [ lonrange' latrange']; |
| 106 | + |
| 107 | +%opt.interval=.1; % interpolation interval in deg |
| 108 | +opt.interval= (ceil(lonrange(2))-floor(lonrange(1))+ceil(latrange(2))-floor(latrange(1)))/100; |
| 109 | +tx=floor(bbox(1)):opt.interval:ceil(bbox(2)); |
| 110 | +ty=floor(bbox(3)):opt.interval:ceil(bbox(4)); |
| 111 | + |
| 112 | +[qx,qy]=meshgrid(tx,ty); |
| 113 | + |
| 114 | +% Compute (nominal) velocity/position REFTO wrt to REFFROM |
| 115 | + |
| 116 | +plh=[ qy(:)*pi/180 qx(:)*pi/180 zeros(size(qx(:)))]; |
| 117 | +xyz=plh2xyz(plh); |
| 118 | + |
| 119 | +xyzitrf=itrf2itrf([xyz zeros(size(xyz)) ] ,char(reffrom),char(refto),refepoch); |
| 120 | + |
| 121 | +posneuitrf=xyz2neu(xyzitrf(:,1:3)-xyz,xyz,'r'); |
| 122 | +velneuitrf=xyz2neu(xyzitrf(:,4:6),xyz,'r'); |
| 123 | + |
| 124 | +% Optionally correct for plate motion model (PMM) velocity |
| 125 | + |
| 126 | +if ~strcmpi(pmm,'none') |
| 127 | + posneuitrf = posneuitrf - pmmvel(pmm,tecplate,plh) * ( refepoch - 1989.0); %ETRS89 ref epoch |
| 128 | + velneuitrf = velneuitrf - pmmvel(pmm,tecplate,plh); |
| 129 | +end |
| 130 | + |
| 131 | +% Select plot type |
| 132 | + |
| 133 | +if strncmpi(sel,'velocity',3) |
| 134 | + plttitle = [ 'Velocity{\Delta} ' char(refto) ' wrt ' char(reffrom) ]; |
| 135 | + units='[mm/y]'; |
| 136 | +elseif strncmpi(sel,'position',3) |
| 137 | + velneuitrf=posneuitrf; |
| 138 | + plttitle = [ 'Coordinate{\Delta} ' char(refto) '@' num2str(refepoch,'%.1f') ' wrt ' char(reffrom) ]; |
| 139 | + units='[mm]'; |
| 140 | +else |
| 141 | + error('Invalid selection, use vel or pos') |
| 142 | +end |
| 143 | +if ~strcmpi(pmm,'none') |
| 144 | + plttitle = [ plttitle ', pmm=' char(pmm)]; |
| 145 | +end |
| 146 | + |
| 147 | +% Land areas, rivers and borders |
| 148 | + |
| 149 | +if ~strcmpi(id,'none') |
| 150 | + try |
| 151 | + %id='nweurope'; |
| 152 | + resolution='f'; |
| 153 | + landareas = shaperead(['landareas_' id '_' resolution],'UseGeoCoords', true, 'BoundingBox', bbox); |
| 154 | + borders = shaperead(['borders_' id '_' resolution],'UseGeoCoords', true, 'BoundingBox', bbox); |
| 155 | + rivers = shaperead(['rivers_' id '_' resolution],'UseGeoCoords', true, 'BoundingBox', bbox); |
| 156 | + disp('Using high resolution land areas, rivers and borders.') |
| 157 | + catch |
| 158 | + disp('No high resolution land areas, rivers and borders available, maybe you did not set the path, using low resolution instead.') |
| 159 | + id='none'; |
| 160 | + end |
| 161 | +end |
| 162 | +if strcmpi(id,'none') |
| 163 | + landareas = readgeotable("landareas.shp"); |
| 164 | + rivers = readgeotable("worldrivers.shp"); |
| 165 | + borders = geopoint(); % empty |
| 166 | +end |
| 167 | + |
| 168 | +% Plot four figures, with basemap and contour overlay of velocities or |
| 169 | +% differences, in resp. North, East, Horizontal and Vertical direction |
| 170 | + |
| 171 | +% Fig 1 - Plot the North velocity/difference |
| 172 | + |
| 173 | +qz=reshape(velneuitrf(:,1)*1000,size(qx)); |
| 174 | +levels=getlevels(qz); |
| 175 | + |
| 176 | +figure('position',[10,10,1000,800]); |
| 177 | +t=tiledlayout(2,2,'TileSpacing','Compact','Padding','Compact'); |
| 178 | +title(t,plttitle) |
| 179 | + |
| 180 | +nexttile; |
| 181 | +%figure; |
| 182 | +ax=worldmap(latrange,lonrange); |
| 183 | +setm(ax,'GLineStyle',':','GColor','k','FFaceColor','none'); % 'FFaceColor','cyan' |
| 184 | +%[cs,h]=contourfm(qy,qx,qz,'LevelStep',levelstep,'LineColor',[0.6 0.6 0.6]); |
| 185 | +try |
| 186 | + [cs,h]=contourfm(qy,qx,qz,levels,'LineColor',[0.6 0.6 0.6]); |
| 187 | + ht = clabelm(cs,h); |
| 188 | + set(ht,'Color','white','BackgroundColor','none','FontWeight','normal') |
| 189 | +catch |
| 190 | + disp('Contourfm failure, skip...') |
| 191 | +end |
| 192 | +c=colorbar; |
| 193 | +c.Label.String=units; |
| 194 | +geoshow(landareas, 'FaceColor','none','EdgeColor','black'); |
| 195 | +geoshow(rivers, 'Color', 'cyan') |
| 196 | +geoshow(borders, 'Color','black') |
| 197 | +%title(['North ' plttitle]) |
| 198 | +title('North') |
| 199 | + |
| 200 | +% Fig 2 - Plot the East velocity/difference |
| 201 | + |
| 202 | +qz=reshape(velneuitrf(:,2)*1000,size(qx)); |
| 203 | +levels=getlevels(qz); |
| 204 | + |
| 205 | +nexttile; |
| 206 | +%figure; |
| 207 | +ax=worldmap(latrange,lonrange); |
| 208 | +setm(ax,'GLineStyle',':','GColor','k','FFaceColor','none'); % 'FFaceColor','cyan' |
| 209 | +%[cs,h]=contourfm(qy,qx,qz,'LevelStep',levelstep,'LineColor',[0.6 0.6 0.6]); |
| 210 | +try |
| 211 | + [cs,h]=contourfm(qy,qx,qz,levels,'LineColor',[0.6 0.6 0.6]); |
| 212 | + ht = clabelm(cs,h); |
| 213 | + set(ht,'Color','white','BackgroundColor','none','FontWeight','normal') |
| 214 | +catch |
| 215 | + disp('Contourfm failure, skip...') |
| 216 | +end |
| 217 | +c=colorbar; |
| 218 | +c.Label.String=units; |
| 219 | +geoshow(landareas, 'FaceColor','none','EdgeColor','black'); |
| 220 | +geoshow(rivers, 'Color', 'cyan') |
| 221 | +geoshow(borders, 'Color','black') |
| 222 | +%title(['East ' plttitle]) |
| 223 | +title('East') |
| 224 | + |
| 225 | +% Fig 3 - Plot the Horizontal velocity/difference |
| 226 | + |
| 227 | +qz=reshape(sqrt(velneuitrf(:,1).^2+velneuitrf(:,2).^2)*1000,size(qx)); |
| 228 | +levels=getlevels(qz); |
| 229 | + |
| 230 | +nexttile; |
| 231 | +%figure; |
| 232 | +ax=worldmap(latrange,lonrange); |
| 233 | +setm(ax,'GLineStyle',':','GColor','k','FFaceColor','none'); % 'FFaceColor','cyan' |
| 234 | +%[cs,h]=contourfm(qy,qx,qz,'LevelStep',levelstep,'LineColor',[0.6 0.6 0.6]); |
| 235 | +try |
| 236 | + [cs,h]=contourfm(qy,qx,qz,levels,'LineColor',[0.6 0.6 0.6]); |
| 237 | + ht = clabelm(cs,h); |
| 238 | + set(ht,'Color','white','BackgroundColor','none','FontWeight','normal') |
| 239 | +catch |
| 240 | + disp('Contourfm failure, skip...') |
| 241 | +end |
| 242 | +c=colorbar; |
| 243 | +c.Label.String=units; |
| 244 | +geoshow(landareas, 'FaceColor','none','EdgeColor','black'); |
| 245 | +geoshow(rivers, 'Color', 'cyan') |
| 246 | +geoshow(borders, 'Color','black') |
| 247 | + |
| 248 | +istep=6; |
| 249 | +ix=floor(istep/2)+1:istep:size(qx,1); |
| 250 | +iy=floor(istep/2)+1:istep:size(qx,2); |
| 251 | +qxx=qx(ix,iy); |
| 252 | +qyy=qy(ix,iy); |
| 253 | +qzv=reshape(velneuitrf(:,1)*1000,size(qx)); |
| 254 | +qzu=reshape(velneuitrf(:,2)*1000,size(qx)); |
| 255 | +qzv=qzv(ix,iy); |
| 256 | +qzu=qzu(ix,iy)./cosd(qyy); |
| 257 | +hold on |
| 258 | +quiverm(qyy(:),qxx(:),qzv(:),qzu(:),'r','filled') |
| 259 | + |
| 260 | +%title(['Horizontal ' plttitle]) |
| 261 | +title('Horizontal') |
| 262 | + |
| 263 | +% Fig 4 - Plot the Vertical velocity/difference |
| 264 | + |
| 265 | +qz=reshape(velneuitrf(:,3)*1000,size(qx)); |
| 266 | +levels=getlevels(qz); |
| 267 | + |
| 268 | +nexttile; |
| 269 | +%figure; |
| 270 | +ax=worldmap(latrange,lonrange); |
| 271 | +setm(ax,'GLineStyle',':','GColor','k','FFaceColor','none'); % 'FFaceColor','cyan' |
| 272 | +%[cs,h]=contourfm(qy,qx,qz,'LevelStep',levelstep,'LineColor',[0.6 0.6 0.6]); |
| 273 | +try |
| 274 | + [cs,h]=contourfm(qy,qx,qz,levels,'LineColor',[0.6 0.6 0.6]); |
| 275 | + ht = clabelm(cs,h); |
| 276 | + set(ht,'Color','white','BackgroundColor','none','FontWeight','normal') |
| 277 | +catch |
| 278 | + disp('Contourfm failure, skip...') |
| 279 | +end |
| 280 | +c=colorbar; |
| 281 | +c.Label.String=units; |
| 282 | +geoshow(landareas, 'FaceColor','none','EdgeColor','black'); |
| 283 | +geoshow(rivers, 'Color', 'cyan') |
| 284 | +geoshow(borders, 'Color','black') |
| 285 | +%title(['Vertical ' plttitle]) |
| 286 | +title('Vertical') |
| 287 | + |
| 288 | +toc |
| 289 | + |
| 290 | +end |
| 291 | + |
| 292 | +function levels=getlevels(qz) |
| 293 | + |
| 294 | +minz=min(qz(:)); |
| 295 | +maxz=max(qz(:)); |
| 296 | +zrange=maxz-minz; |
| 297 | +if zrange < 0.01 |
| 298 | + minz=minz-0.01/2; |
| 299 | + maxz=maxz+0.01/2; |
| 300 | + zrange=maxz-minz; |
| 301 | +end |
| 302 | +levelstep=10^(floor(log10(zrange))); |
| 303 | +numlevels=ceil(zrange/levelstep); |
| 304 | +%levelstep=levelstep/floor(10/numlevels); |
| 305 | +while numlevels < 6 |
| 306 | + levelstep=levelstep/2; |
| 307 | + numlevels=ceil(zrange/levelstep); |
| 308 | +end |
| 309 | +levelstep=max(levelstep,0.01); |
| 310 | +levels=floor(minz/levelstep)*levelstep:levelstep:ceil(maxz/levelstep)*levelstep; |
| 311 | +if length(levels) <1 |
| 312 | + levels(1) = levels(1) - levelstep/2; |
| 313 | + levels(2) = levels(1) + levelstep; |
| 314 | +end |
| 315 | + |
| 316 | +end |
0 commit comments