forked from joa-quim/mirone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mirone.m
5352 lines (4949 loc) · 258 KB
/
mirone.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
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
function varargout = mirone(varargin)
% MIRONE, by itself, creates a window bar from which you load a lot of grid/images formats
% MIRONE(FNAME) opens the file FNAME and displays it
% H = MIRONE(...) returns the handle to a new mirone window
%
% mirone('CALLBACK',handles,...) calls the local function named CALLBACK with the given input arguments.
% Copyright (c) 2004-2016 by J. Luis
%
% This program is part of Mirone and is free software; you can redistribute
% it and/or modify it under the terms of the GNU Lesser General Public
% License as published by the Free Software Foundation; either
% version 2.1 of the License, or 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
% Lesser General Public License for more details.
%
% Contact info: w3.ualg.pt/~jluis/mirone
% --------------------------------------------------------------------
% $Id: mirone.m 10034 2017-02-27 01:24:05Z j $
if (nargin > 1 && ischar(varargin{1}))
if ( ~isempty(strfind(varargin{1},':')) || ~isempty(strfind(varargin{1},filesep)) )
% Very likely called with a filename with those horrendous stupid blanks
for (k = 1:nargin-1), varargin{k}(end+1) = ' '; end
varargin = {[varargin{:}]}; h = mirone_OpeningFcn(varargin{:});
if (nargout), varargout{1} = h; end
else
gui_Callback = str2func(varargin{1});
[varargout{1:nargout}] = feval(gui_Callback,varargin{2:end});
end
else
h = mirone_OpeningFcn(varargin{:});
if (nargout), varargout{1} = h; end
end
% --------------------------------------------------------------------------------------------------
function hObject = mirone_OpeningFcn(varargin)
% PRAGMA SECTION (It's far far from clear when files must be declared here)
%#function uigetfolder_standalone mapproject_m grdproject_m coordinate_system gmtmbgrid_m gmtedit
%#function nearneighbor_m cpt2cmap grdfilter_m grdgradient_m grdsample_m grdtrack_m grdtrend_m
%#function grdutils scaleto8 bpass3d inv3d rtp3d syn3d igrf_m surface_m
%#function range_change swan tsun2 mansinha_m deform_mansinha deform_okada dim_funs
%----- These are for image
%#function grayto8 grayto16 grayxform imfilter_mex imhistc imlincombc parityscan intlutc ordf
%#function imreconstructmex applylutc bwboundariesmex bwlabel1 bwlabel2 ditherc bwlabelnmex morphmex
%----- These are in utils
%#function tabpanelfcn degree2dms dms2degree dec2deg dec_year ivan_the_terrible ddewhite string_token
%#function test_dms text_read double2ascii save_seismicity jd2date guess_file shading_mat
%#function getline_j new_frame3D histos_seis uirestore_j uisuspend_j
%----- These is for write_gmt_script
%#function draw_scale time_stamp pscoast_options_Mir paint_option w_option
%----- Those are ..., the hell with explanations for what I don't realy understand. They are needed, that's all.
%#function gmtlist_m country_select read_isf choosebox magbarcode listbox_message add_poles animate_seismicity
%#function get_polygon rot_euler datums telha_m find_clusters fft_stuff select_cols uistack_j smoothing_param
%#function patch_meca ui_edit_patch_special bands_list multibandread_j imscroll_j geog2projected_pts
%#function mltable_j iptcheckinput resampsep wgifc telhometro vitrinite edit_line move_obj make_arrow
%#function edit_track_mb save_track_mb houghmex qhullmx writegif mpgwrite cq helpdlg
%#function move2side aguentabar gdal_project gdalwarp_mex poly2mask_fig url2image calc_bonin_euler_pole spline_interp
%#function mat2clip buffer_j PolygonClip trend1d_m akimaspline shake_mex ground_motion wms_tool microlev
%#function write_esri_hdr distmin mag_synthetic image_histo write_gmt_symb mkpj decompress mosaicer
%#function lasreader_mex laszreader_mex escorrega show_manguito travel thresholdit intersections nswing runCB_tintol
%#function usgs_recent_seismicity sat_orbits uisetdate doy
%#function c_cpt2cmap c_grdfilter c_grdinfo c_grdlandmask c_grdproject c_grdread c_grdsample
%#function c_grdtrend c_mapproject c_nearneighbor c_shoredump c_surface popenr diffCenterVar hellinger bingham
global gmt_ver; gmt_ver = 5; global home_dir; fsep = filesep;
toCompile = false; % To compile set this one to TRUE
if (toCompile)
home_dir = cd;
else
if (isempty(home_dir)) % First time call. Find out where we are
home_dir = fileparts(mfilename('fullpath')); % Get the Mirone home dir and set path
addpath(home_dir, [home_dir fsep 'src_figs'],[home_dir fsep 'utils']);
if (exist('OCTAVE_VERSION','builtin') ~= 0) % This is a repetition of the test later in mirone_uis
addpath([home_dir fsep 'lib_mex' fsep 'octave' fsep octave_config_info.canonical_host_type]);
else
addpath([home_dir fsep 'lib_mex']);
end
end
end
[hObject,handles,home_dir] = mirone_uis(home_dir);
pos = get(handles.figure1,'pos');
if (pos(4) == 32) % On Win 8 and retina, the bloody OS insists in resetting it to 32
set(handles.figure1,'Pos',[pos(1), pos(2)+31, pos(3), 1]);
end
handles.home_dir = home_dir;
handles.DefLineThick = 0.5; % Default line thickness (overwriten by mirone_pref)
handles.DefLineColor = 'k'; % Default line color (overwriten by mirone_pref)
handles.DefineMeasureUnit = 'k';% Default measure units to kilometrs (overwriten by mirone_pref)
handles.grdname = []; % Contains the name of the current (if it's the case) gmt grid
handles.nTrack = 0; % Counter of the number of MB tracks imported
handles.origFig = []; % To store the original image copy
handles.fileName = []; % To store any input grid/image file name
handles.image_type = 0; % 1->grd; 2-> trivial (jpg,png,bmp,etc...); 3->GeoTIFF; 4->DEMs; 20-> white bg
handles.transparency = []; % Will hold the word 'alpha' when reading a RGBA image
handles.computed_grid = 0; % However, matrices with a gmt header will have this == 1, so that they can be saved
handles.no_file = 1; % 0 means a grid is loaded and 1 that it is not (to test when icons can be pushed)
handles.geog = 1; % By default grids are assumed to be in geographical coordinates
handles.swathRatio = 3; % Default swath width / water depth ratio for multibeam planing
handles.grdMaxSize = 524288000; % I use this for limiting the grid size that is stored in RAM (50 Mb)
handles.firstMBtrack = 1; % Used for knowing whether to display or not the MB planing info message in "start planing"
handles.EarthRad = 6371.005076; % Authalic radius
handles.maregraphs_count = 0; % Counter of maregraphs (tsunami modeling)
handles.Illumin_type = 0; % 0 -> no illumination; 1 -> grdgradient; 2 -> grdgradient Lambertian; 4 -> Lambertian;
handles.zoom_state = 0; % Flag to signal if zoom state is to be re-activated (0 means no re-activation)
handles.bg_color = [1 1 1]; % (default) Backgoround color used when grid values == NaN
handles.which_cont = []; % To store the contour levels (used to not draw repeated contours)
handles.have_nans = 0; % Used to know if the grids have NaNs
handles.is_draped = false; % Used to know if the image comes from draping
handles.was_int16 = false; % Keep track of short int imported grids
handles.Nodata_int16 = []; % To store Nodata of short int grids
handles.ForceInsitu = false; % Use "insitu" grid importing (transposition)
handles.DefineEllipsoide = [6378137, 0, 1/298.2572235630]; % Defaults to WGS-84
handles.path_tmp = [home_dir fsep 'tmp' fsep];
handles.path_data = [home_dir fsep 'data' fsep];
handles.last_directories = {handles.path_tmp; home_dir}; % Let it have something existent
handles.hImg = []; % To hold the image handle
handles.firstIllum = 1; % First illumination will use the displayed image which may have been IP
handles.flederBurn = 1; % When build a fleder obj burn eventual coastlines
handles.flederPlanar = 1; % Default to planar flder objs (but mirone_pref knows better)
handles.whichFleder = 1; % whichFleder = 1 for the free iview4d or 0 for the true thing (fledermaus)
handles.oldSize = [get(hObject,'Pos'); get(hObject,'Pos')]; % Duplicate so that we store ORIGINAL size
if (handles.oldSize(1,4) == 0), handles.oldSize(1,4) = 1; end
handles.is_projected = false; % To keep track if coords are projected or not
handles.defCoordsIn = 0; % To use when Load files and have to decide if we need to project
% 0 -> don't know; -1 -> Coords are already projected; 1 -> geog coords needing project
try handles.Projections; % Use a try/catch since isfield is brain-dead long
catch, handles.Projections = nan; % Set it to something to prevent "unknown field" error
end
handles.scale2meanLat = 1; % Scale geog ref images so that at middle image dx = dy in cartesian units (kind of proj)
handles.FOpenList = cell(numel(handles.RecentF),1);
handles.withSliders = true; % Set Zoom sliders
handles.validGrid = false; %
handles.nLayers = 1; % If > 1 after reading a netCDF file call aquamoto
handles.deflation_level = 0; % If > 0 will create compressed netCDF-4 files
handles.is_defRegion = false; % A def region is a particular case to create GMT custom symbols.
handles.screenSize = []; % Fill it for the case when one wants to fake a different get(0, 'ScreenSize')
try % A file named mirone_pref.mat contains the preferences, read them from it
prf = load([handles.path_data 'mirone_pref.mat']);
handles.geog = prf.geog;
handles.grdMaxSize = prf.grdMaxSize; % 2^20 = 1 Mb
handles.swathRatio = prf.swathRatio;
handles.last_directories = prf.directory_list;
handles.DefLineThick = sscanf(strtok(prf.DefLineThick{1}),'%f');
% Decode the line color string into the corresponding char (e.g. k,w, etc...)
if (strcmp(prf.DefLineColor{1},'Black')), handles.DefLineColor = 'k';
else handles.DefLineColor = lower(prf.DefLineColor{1}(1));
end
% Decode the Measure unities into a char code (e.g. n, k, m, u from {'nautical miles' 'kilometers' 'meters' 'user'})
handles.DefineMeasureUnit = prf.DefineMeasureUnit{1}(1);
handles.DefineEllipsoide = prf.DefineEllipsoide_params; % Set the default ellipsoide parameters (a,b,f)
handles.flederBurn = prf.flederBurn;
handles.flederPlanar = prf.flederPlanar;
handles.scale2meanLat = prf.scale2meanLat;
handles.FOpenList = prf.FOpenList;
handles.whichFleder = prf.whichFleder;
if (~prf.moveDoubleClick) % this info is used by UI_EDIT_POLYGON()
setappdata(handles.axes1,'MovPolyg','extend') % Move lines with a Shift-click drag-n-drop
end
handles.bg_color = prf.nanColor;
handles.deflation_level = prf.deflation_level;
try gmt_ver = prf.gmt_ver; % Hope that this will be a temporary thing till GMT5 is fully working
catch, gmt_ver = 5;
end
if (isfield(prf, 'TDRver')), handles.TDRver = prf.TDRver;
else handles.TDRver = '2.0';
end
catch
% Tell mirone_pref to write up the defaults.
mirone_pref(handles,'nikles')
handles = guidata(handles.figure1); % And need also the updated handles
gmt_ver = 5; % Default to GMT4
end
j = false(1,numel(handles.last_directories)); % vector for eventual cleaning non-existing dirs
for (i = 1:numel(handles.last_directories)) % Check that all dirs in last_directories exist
j(i) = (exist(handles.last_directories{i},'dir') ~= 7);
end
handles.last_directories(j) = []; % clean non-existing directories
if (isempty(handles.last_directories)) % Don't ever let it be empty
handles.last_directories = {handles.path_tmp; home_dir}; % Let it have something existent
end
if (any(j)) % If any of the old dirs evaporated, update that info in mirone_prefs
directory_list = handles.last_directories; isempty(directory_list); % To shut up MLint
if (handles.version7), save([handles.path_data 'mirone_pref.mat'],'directory_list', '-append', '-v6')
else save([handles.path_data 'mirone_pref.mat'],'directory_list', '-append')
end
end
handles.work_dir = handles.last_directories{1};
if (handles.work_dir ~= fsep), handles.work_dir = [handles.work_dir fsep]; end
handles.last_dir = handles.last_directories{1}; % Initialize last_dir to work_dir
setappdata(hObject,'swathRatio',handles.swathRatio); % I need this for getline_mb
% Change the MeasureDistance label to the selected (in prefs) units
set(handles.ToolsMeasureDist,'Label',['Distance in ' handles.DefineMeasureUnit])
% -------------------------- Find in which mode Mirone was called ----------------------------------
drv = []; grd_data_in = 0; grd_data_interfero = 0; pal = []; win_name = 'Mirone';
if ~isempty(varargin)
n_argin = nargin;
if (n_argin == 1 && ischar(varargin{1})) % Called with a file name as argument
[pato, fname, EXT] = fileparts(varargin{1}); % Test to check online command input
if (isempty(pato)), varargin{1} = [cd fsep fname EXT]; end
[drv, algures] = aux_funs('findFileType',varargin{1});
if (ischar(algures)), varargin{1} = algures; end % File exists but not in Mirone's root dir
if (ischar(algures) || algures), handles.fileName = varargin{1}; end % Can be added by recentFiles
elseif (isa(varargin{1},'uint8') || isa(varargin{1},'int8') || islogical(varargin{1}))
% Called with an image as argument and optionaly an struct header (& geog, name, cmap optional fields)
if (isa(varargin{1},'int8')) % We cannot represent a int8 image. Do something
varargin{1} = uint8(cvlib_mex('addS', int16(varargin{1}), 128)); % [-128 127] -> [0 255]
end
% Now deal with the case of a eventual multiband ( > than 3 planes) array
if (size(varargin{1},3) > 3), aux_funs('toBandsList', handles.figure1, varargin{1}, 'multiband array'), end
isReferenced = false;
if (n_argin == 2 && isa(varargin{2},'struct')) % An image with coordinates
tmp = varargin{2};
handles.head = tmp.head; X = tmp.X; Y = tmp.Y;
handles.image_type = 3; axis_t = 'xy';
if (isfield(tmp,'geog')), handles.geog = tmp.geog; end % Prevails over the guess in show_image (does it?)
if (isfield(tmp,'cmap')), set(handles.figure1,'Colormap',tmp.cmap); end
if (isfield(tmp,'name')), win_name = tmp.name; end
if (isfield(tmp,'srsWKT'))
aux_funs('appP', handles, tmp.srsWKT) % If we have a WKT proj, store it
isReferenced = true;
if (~handles.geog), handles.is_projected = true; end % WEAK LOGIC. SHOULD PARSE WKT TO MAKE SURE
end
else
X = []; Y = []; win_name = 'Cropped_image';
handles.image_type = 2; handles.geog = 0; axis_t = 'off';
handles.head = [1 size(varargin{1}, 2) 1 size(varargin{1}, 1) 0 255 0 1 1]; % Fake a grid reg GMT header
if (ndims(varargin{1}) == 2), set(handles.figure1,'Colormap',gray(256)); end
pal = getappdata(0,'CropedColormap'); % See if we have a colormap to use here
if (~isempty(pal)), set(handles.figure1,'Colormap',pal), rmappdata(0,'CropedColormap'), end
setappdata(hObject,'Croped','yes'); % ???
end
if (size(varargin{1},3) == 4), handles.transparency = 'alpha'; end % Signal show_image that 4th band is transparency
handles = show_image(handles,win_name,X,Y,varargin{1},0,axis_t,handles.head(7),1);
if (~isReferenced), grid_info(handles,[],'iminfo',varargin{1}); % Create a info string
else grid_info(handles,tmp.srsWKT,'referenced',varargin{1});
end
handles = aux_funs('isProj',handles); % Check/set about coordinates type
elseif (n_argin == 1 && isa(varargin{1},'struct') && isfield(varargin{1},'proj4'))
% A GMT5 grid/image structure. (for images we still do not use eventual alpha channel)
handles.head = [varargin{1}.range varargin{1}.registration varargin{1}.inc];
if (~isfield(varargin{1}, 'image'))
Z = varargin{1}.z; grd_data_in = true;
if (~isa(Z,'single')), Z = single(Z); end
handles.have_nans = grdutils(Z,'-N');
X = linspace(varargin{1}.range(1), varargin{1}.range(2), size(varargin{1}.z, 2));
Y = linspace(varargin{1}.range(3), varargin{1}.range(4), size(varargin{1}.z, 1));
else
handles.image_type = 2; isReferenced = false;
X = [varargin{1}.x(1) varargin{1}.x(end)]; Y = [varargin{1}.y(1) varargin{1}.y(end)];
handles.geog = aux_funs('guessGeog', [Y Y]);
ProjectionRefWKT = varargin{1}.wkt;
if (isempty(ProjectionRefWKT) && ~isempty(varargin{1}.proj4))
ProjectionRefWKT = ogrproj(varargin{1}.proj4);
end
if (~isempty(ProjectionRefWKT))
aux_funs('appP', handles, varargin{1}.wkt) % If we have a WKT proj, store it
isReferenced = true;
if (~handles.geog), handles.is_projected = true; end % WEAK LOGIC. SHOULD PARSE WKT TO MAKE SURE
end
if (ndims(varargin{1}.image) == 2), set(handles.figure1,'Colormap',gray(256)); end
win_name = 'Nikles';
if (~isempty(varargin{1}.title)), win_name = varargin{1}.title; end
alpha = 1;
if (~isempty(varargin{1}.alpha)), alpha = varargin{1}.alpha; end
handles = show_image(handles,win_name,X,Y,varargin{1}.image,0,'off',varargin{1}.registration,1, alpha);
if (~isReferenced), grid_info(handles,[],'iminfo',varargin{1}.image); % Create a info string
else grid_info(handles, ProjectionRefWKT, 'referenced', varargin{1}.image);
end
handles = aux_funs('isProj',handles); % Check/set about coordinates type
end
elseif (n_argin == 2 && isequal([size(varargin{2},1) size(varargin{2},2)],[1 9]))
% A matrix with the classic nine elements header vector
handles.head = varargin{2};
Z = varargin{1}; grd_data_in = true;
if (~isa(Z,'single')), Z = single(Z); end
handles.have_nans = grdutils(Z,'-N');
X = linspace(handles.head(1), handles.head(2), size(Z,2));
Y = linspace(handles.head(3), handles.head(4), size(Z,1));
elseif (n_argin == 3 && numel(varargin{1} == size(varargin{3},2)) && numel(varargin{2} == size(varargin{3},1)))
% A (X, Y, Z) where X,Y are the coord vectors and Z is the grid matrix
Z = varargin{3}; grd_data_in = true;
X = varargin{1}(:)'; Y = varargin{2}(:)';
if (X(2) < X(1)), X = X(end:-1:1); end
if (Y(2) < Y(1)), Y = Y(end:-1:1); end
if (~isa(Z,'single')), Z = single(Z); end
handles.have_nans = grdutils(Z,'-N');
win_name = 'Nikles';
zz = grdutils(Z,'-L');
handles.head = [X(1) X(end) Y(1) Y(end) zz(1) zz(2) 0 X(2)-X(1) Y(2)-Y(1)];
elseif (n_argin < 4 && ~(isa(varargin{1},'uint8') || isa(varargin{1},'int8')))
% A matrix. Treat it as if it is a gmt grid. No error testing on the grid head descriptor
Z = varargin{1}; grd_data_in = true;
if (~isa(Z,'single')), Z = single(Z); end
handles.have_nans = grdutils(Z,'-N');
if (numel(varargin) == 2 && isa(varargin{2},'struct')) % An grid with a header
tmp = varargin{2};
handles.head = tmp.head; X = tmp.X; Y = tmp.Y;
if (isfield(tmp,'name')), win_name = tmp.name; end % All calls should transmit a name, but ...
if (isfield(tmp,'cmap')), pal = tmp.cmap; end
if (isfield(tmp,'was_int16'))
handles.was_int16 = tmp.was_int16; handles.Nodata_int16 = tmp.Nodata_int16;
end
if (isfield(tmp,'srsWKT'))
grid_info(handles,tmp.srsWKT,'referenced',varargin{1}); % Create a info string
aux_funs('appP', handles, tmp.srsWKT) % We have a WKT proj, store it
handles.is_projected = true; % WEAK LOGIC. SHOULD PARSE WKT TO MAKE SURE
elseif (isfield(tmp,'ProjGMT')) % From geog_calculator. Has opt_J.
projection_menu(handles, tmp.ProjGMT)
handles = guidata(hObject); % Get the updated version changed in the above call
end
if (isfield(tmp,'screenSize'))
handles.screenSize = tmp.screenSize;
end
else
zz = grdutils(Z,'-L');
handles.head = [1 size(Z,2) 1 size(Z,1) zz(1) zz(2) 0 1 1];
X = 1:size(Z,2); Y = 1:size(Z,1);
end
elseif (n_argin == 4 && isnumeric(varargin{1}) && isa(varargin{2},'struct') && ...
(strcmp(varargin{3},'Deformation') || strcmp(varargin{3},'Interfero')) )
% A matrix. Treat it as if it'is a gmt grid. No error testing on the grid head descriptor
% Note: this is a special case of the situation above that will be used to identify this figure
% as an Okada deformtion data (via its Name). This info is searched by the tsunami modeling option
if (~isa(varargin{1},'single')), varargin{1} = single(varargin{1}); end
handles.head = varargin{2}.head; X = varargin{2}.X; Y = varargin{2}.Y;
Z = varargin{1};
handles.have_nans = grdutils(Z,'-N');
if (varargin{3}(1) == 'D')
grd_data_in = true; win_name = 'Okada deformation';
setappdata(hObject,'hFigParent',varargin{4});
else % A matrix input containing an interfeogram with cdo == varargin{4}
grd_data_interfero = true; win_name = 'Interferogram';
cdo = varargin{4};
end
end
end
% The following IF cases deal only with cases where a grid was given in argument
if (grd_data_in || grd_data_interfero)
handles.image_type = 1; handles.computed_grid = 1; % Signal that this is a computed grid
if (isempty(pal)), pal = jet(256); end
if (grd_data_interfero) % Interferogram grid
pal = load([handles.path_data 'gmt_other_palettes.mat'],'circular'); pal = pal.circular;
zz = uint8(abs(rem(double(Z),cdo)/cdo)*255);
else
zz = scaleto8(Z);
end
set(handles.figure1,'Colormap',pal)
aux_funs('StoreZ',handles,X,Y,Z) % If grid size is not to big we'll store it
aux_funs('colormap_bg',handles,Z,pal);
handles = show_image(handles,win_name,X,Y,zz,1,'xy',handles.head(7));
end
% ---------+================+---------- FIGURE VISIBLE HERE ----------+==============+-----------
set(handles.figure1,'Vis', 'on')
% ---------+================+---------- FIGURE VISIBLE HERE ----------+==============+-----------
handles.IAmAMac = strncmp(computer,'MAC',3);
setappdata(0,'IAmAMac',handles.IAmAMac)
if (handles.IAmAMac)
if (isempty(getappdata(0,'have_DYLD'))) % Deal with MacOSX blindness
%set_gmt(['DYLD_LIBRARY_PATH=' cd ':'],'DYLD_LIBRARY_PATH') % Prepend current dir to DYLD_LIBRARY_PATH
DYLD = getenv('DYLD_LIBRARY_PATH'); % Available only on > R14?? versions
setenv('DYLD_LIBRARY_PATH',[DYLD ':' cd])
setappdata(0,'have_DYLD',true) % Signal to do this only once
end
% F. TMW just cannot make things work decently on Macs. Labels are bigger than reserved space
% And now they screw it even more. The following simply f... on 2012 (and maybe earlier(
v = version('-release');
if (str2double(v(1:4)) < 2012)
set(handles.File, 'Label', ['<HTML><FONT size="3">' get(handles.File, 'Label') '</Font></html>'])
set(handles.Image, 'Label', ['<HTML><FONT size="3">' get(handles.Image, 'Label') '</Font></html>'])
set(handles.Tools, 'Label', ['<HTML><FONT size="3">' get(handles.Tools, 'Label') '</Font></html>'])
set(handles.Draw, 'Label', ['<HTML><FONT size="3">' get(handles.Draw, 'Label') '</Font></html>'])
set(handles.Geography, 'Label', ['<HTML><FONT size="3">' get(handles.Geography, 'Label') '</Font></html>'])
set(handles.Plates,'Label', ['<HTML><FONT size="3">' get(handles.Plates, 'Label') '</Font></html>'])
set(handles.MagGrav, 'Label', ['<HTML><FONT size="3">' get(handles.MagGrav, 'Label') '</Font></html>'])
set(handles.Seismology, 'Label', ['<HTML><FONT size="3">' get(handles.Seismology, 'Label') '</Font></html>'])
set(handles.Tsunamis, 'Label', ['<HTML><FONT size="3">' get(handles.Tsunamis, 'Label') '</Font></html>'])
set(handles.GMT, 'Label', ['<HTML><FONT size="3">' get(handles.GMT, 'Label') '</Font></html>'])
set(handles.GridTools, 'Label', ['<HTML><FONT size="3">' get(handles.GridTools, 'Label') '</Font></html>'])
set(handles.Projections, 'Label', ['<HTML><FONT size="3">' get(handles.Projections, 'Label') '</Font></html>'])
set(handles.Help, 'Label', ['<HTML><FONT size="3">' get(handles.Help, 'Label') '</Font></html>'])
end
set(hObject,'DockControls','off')
end
%Find out which gmt version is beeing used.
info = getappdata(0,'gmt_version'); % See if the info is already there.
if (isempty(info))
info = set_gmt(['GMT_USERDIR=' home_dir fsep 'gmt_userdir']);
setappdata(0,'gmt_version',info); % Save it so that the next time a new mirone window is opened
end
if (~strcmp(info.full, 'y'))
set([handles.CoastLineFull handles.PBFull handles.RiversFull], 'Enable','off')
end
if (~strcmp(info.high, 'y'))
set([handles.CoastLineHigh handles.PBHigh handles.RiversHigh], 'Enable','off')
end
if (~strcmp(info.intermediate, 'y'))
set([handles.CoastLineInterm handles.PBInterm handles.RiversInterm], 'Enable','off')
end
if (~strcmp(info.low, 'y'))
set([handles.CoastLineLow handles.PBLow handles.RiversLow], 'Enable','off')
end
if (~strcmp(info.crude, 'y'))
set([handles.CoastLineCrude handles.PBCrude handles.RiversCrude], 'Enable','off')
end
% Deal with the new (big) troubles introduced by using GMT5.2 that needs to know where to find its own share dir
if (gmt_ver == 5) % For GMT5 we have a shity highly police control on sharedir. Use this to cheat it.
t = set_gmt('GMT5_SHAREDIR', 'whatever'); % Inquire if GMT5_SHAREDIR exists
if (isempty(t) || (~(exist(t, 'dir') == 7))) % Test also that the dir exists
% If not, set a fake one with minimalist files so that GMT does not complain/errors
% We have to use GMT5_SHAREDIR and NOT GMT_SHAREDIR because it's the first one checked in gmt_init.c/GMT_set_env()
set_gmt(['GMT5_SHAREDIR=' home_dir fsep 'gmt_share']);
end
end
% See if we have a TMP dir set by a ENV var that will take precedence over the default one
t = set_gmt('MIRONE_TMP', 'whatever'); % Inquire if MIRONE_TMP exists
if (~isempty(t)) % Now check that the dir exists
if (exist(t, 'dir') == 7)
handles.path_tmp = [t fsep];
end
end
guidata(hObject, handles);
tmp.home_dir = home_dir; tmp.work_dir = handles.work_dir; tmp.last_dir = handles.last_dir;
setappdata(0,'MIRONE_DIRS',tmp); % To access from places where handles.home_dir is unknown (must precede gateLoadFile())
if (~isempty(drv))
gateLoadFile(handles,drv,varargin{1}); % load recognized file types
else
recentFiles(handles,[]); % Just make the "Recent files" entry available
end
if (~isempty(handles.hImg)) % If we had something in input, check the coordinates type
handles = aux_funs('isProj', guidata(hObject));
setAxesDefCoordIn(handles,1);
end
set_gmt(['PROJ_LIB=' home_dir fsep 'data' fsep 'proj_lib']); % For projections with GDAL
set_gmt(['GDAL_DATA=' home_dir fsep 'data' fsep 'gdal_data']);
set_gmt(['GEOTIFF_CSV=' home_dir fsep 'data' fsep 'gdal_data']);
try custom_menus(hObject, handles.path_data), end % Add any custom menus as commanded by OPTcontrol.txt
% --------------------------------------------------------------------------------------------------
function erro = gateLoadFile(handles,drv,fname)
% Gateway function to load a recognized file type using its name
erro = 0;
if (strncmp(drv, 'MB', 2)), drv_or = drv; drv = 'MB'; end % The MB (system) type case are actually several
switch drv
case 'gmt', loadGRID(handles, fname, 'GMT_relatives')
case 'dono', erro = FileOpenGeoTIFF_CB(handles,'dono',fname); % It means "I don't know" and dealt by GDAL
case 'generic', FileOpenNewImage_CB(handles, fname);
case 'geotif', FileOpenGeoTIFF_CB(handles, 'nikles', fname);
case 'ecw', FileOpenGeoTIFF_CB(handles, 'ecw', fname); % A particular case (includes jp2)
case 'multiband', FileOpenGDALmultiBand_CB(handles, 'AVHRR', fname);
case 'envherd', FileOpen_ENVI_Erdas_CB(handles, [], fname);
case 'mat', FileOpenSession_CB(handles, fname)
case 'mola', loadGRID(handles, fname, 'MOLA');
case 'cpt', color_palettes(fname);
case 'dat', load_xyz(handles, fname);
case 'pick', load_xyz(handles, fname, drv);
case 'ncshape', load_xyz(handles, fname, drv);
case 'shp', DrawImportShape_CB(handles, fname);
case 'ogr', DrawImportOGR_CB(handles, fname);
case 'las', read_las(handles, fname);
case 'mgg_gmt', GeophysicsImportGmtFile_CB(handles, fname);
case 'ghost', load_ps(handles, fname); % Put ghostscript on works
case 'sww', aquamoto(fname);
case 'MB', load_MB(handles, fname, drv_or);
otherwise, erro = 1;
end
if (erro), warndlg(['Sorry but couldn''t figure out what to do with the ' fname ' file'],'Warning'), end
% --------------------------------------------------------------------------------------------------
function handles = recentFiles(handles, opt)
if (~isempty(handles.fileName) && ~exist(handles.fileName,'file')), return, end % For example, subdatasets
jump = false; N = min(numel(handles.FOpenList), numel(handles.RecentF));
if (nargin == 1 && ~isempty(handles.fileName)) % Update list
for (i = 1:N) % See if new name is already in FOpenList
if (strcmpi(handles.fileName, handles.FOpenList{i}))
for (k = i:-1:2) % Yes, it is. So move it to the top
handles.FOpenList{k} = handles.FOpenList{k-1};
end
handles.FOpenList{1} = handles.fileName;
jump = true; break
end
end
if (~jump) % We got a new name
for (i = N:-1:2) % Make room for the new name at top of the list
handles.FOpenList{i} = handles.FOpenList{i-1};
end
handles.FOpenList{1} = handles.fileName;
end
end
if (isempty(handles.fileName)), jump = true; end
if ( ~jump && (nargin == 1 || (nargin == 2 && ~isempty(opt))) ) % Save only if it worth it
FOpenList = handles.FOpenList; fname = [handles.path_data 'mirone_pref.mat'];
if (~handles.version7), save(fname,'FOpenList','-append') % Update the list for "Recent files"
else save(fname,'FOpenList','-append', '-v6')
end
end
for (i = 1:N) % The ishandle test below is crutial when GCPs
if (isempty(handles.FOpenList{i}) || ~ishandle(handles.RecentF(i))), continue, end
set(handles.RecentF(i), 'Label',handles.FOpenList{i},'Call',{@openRF,i}, 'Vis','on')
end
if (~nargout), guidata(handles.figure1,handles), end
% --------------------------------------------------------------------------------------------------
function openRF(obj,event,n)
% Open from 'Recent Files'
handles = guidata(obj);
[drv, sim] = aux_funs('findFileType',handles.FOpenList{n});
if (sim)
gateLoadFile(handles,drv,handles.FOpenList{n});
else % File does not exist. Update the FOpenList
warndlg(['File: ' handles.FOpenList{n} ' no longer exists'],'Warning')
handles.FOpenList(n) = []; handles.FOpenList{end+1} = []; % Delete missing and add one at the end
delete(handles.RecentF(n)), guidata(handles.figure1,handles)
end
% --------------------------------------------------------------------------------------------------
function handles = SetAxesNumericType(handles,event)
% Save original X & Y labels in appdata for easear access when we want to change them
setappdata(handles.axes1,'XTickOrig',get(handles.axes1,'XTickLabel'))
setappdata(handles.axes1,'XTickOrigNum',get(handles.axes1,'XTick'))
setappdata(handles.axes1,'YTickOrig',get(handles.axes1,'YTickLabel'))
setappdata(handles.axes1,'YTickOrigNum',get(handles.axes1,'YTick'))
n1 = numel(get(handles.axes1,'YTick'));
fsize = get(handles.axes1, 'FontSize');
set(handles.axes1, 'FontSize', 9) % Make this the default
n2 = numel(get(handles.axes1,'YTick'));
if (n1 ~= n2) % BUT SOMETIMES IT FCK IT??????????. DAMN ML BUGS
set(handles.axes1, 'FontSize', fsize)
end
LFT = 'DegDec'; visibility = 'on'; % For the geog case
if (~handles.geog), LFT = 'NotGeog'; visibility = 'off'; end
setappdata(handles.axes1,'LabelFormatType',LFT)
set(handles.LabFormat, 'Vis', visibility)
if (handles.validGrid), set(handles.PixMode, 'Call', {@PixMode_CB,handles.figure1, true}, 'Vis', 'on')
else set(handles.PixMode, 'Vis', 'off')
end
set(handles.RCMode, 'Call', {@PixMode_CB,handles.figure1, false})
set(handles.FancyMode, 'Call', {@FancyMode_CB,handles.figure1})
% --------------------------------------------------------------------------------------------------
function PixMode_CB(hObject, event, hFig, opt)
% Inside each grid cell, which is a pixel on the screen, display only the grid node value
handles = guidata(hFig);
if (opt) % Pixel mode on/off
if (strcmp(get(hObject,'Checked'),'off'))
set(hObject,'Checked','on'), setappdata(hFig,'PixelMode',true)
else
set(hObject,'Checked','off'), setappdata(hFig,'PixelMode',false)
end
set(handles.RCMode, 'Checked','off'), setappdata(hFig,'RCMode',false) % Put the RowColMode to off
else % Row Col mode on/off
if (strcmp(get(hObject,'Checked'),'off'))
set(hObject,'Checked','on'), setappdata(hFig,'RCMode',true)
else
set(hObject,'Checked','off'), setappdata(hFig,'RCMode',false)
end
set(handles.PixMode, 'Checked','off'), setappdata(hFig,'PixelMode',false) % Put the PixMode to off
end
% --------------------------------------------------------------------------------------------------
function FancyMode_CB(hObject, evt, hFig)
% Call the function that sets or unsets the FANCY frame depending on the previous state
handles = guidata(hFig);
if (strcmp(get(hObject,'Checked'),'off'))
set(hObject,'Checked','on'), fancyFrame(handles,'set')
else
set(hObject,'Checked','off'), fancyFrame(handles,'unset')
end
% --------------------------------------------------------------------------------------------------
function PlatesAgeLift_CB(handles)
% Apply Parsons & Sclatter relation to compensate sea-bottom age sinking.
% It assumes that bathymetry is the loaded grid (in meters Z up) and age in Ma
if (handles.no_file), return, end
resp = inputdlg({'Full name (with path) of Age grid:'},'Where is the grid?',[1 80]);
if (isempty(resp)), return, end
fname = resp{1};
if (~exist(fname,'file'))
warndlg('The file name provided does not exist. Bye, Bye','Warning'), return
end
att = gdalread(fname,'-M','-C');
if (att.GMT_hdr(1) > handles.head(1) || att.GMT_hdr(2) < handles.head(2) || ...
att.GMT_hdr(3) > handles.head(3) || att.GMT_hdr(4) < handles.head(4))
errordlg('No way. The Age grid does not cover the limits of the bathymetry grid.','Error'), return
end
[Age, X, Y, srsWKT, miniHandles] = read_grid([], fname, 'GDAL', sprintf('-R%.12f/%.12f/%.12f/%.12f', handles.head(1:4)));
if (isempty(Age)), return, end % Something bad happened
lift = single(350 * sqrt(double(Age)));
[X,Y,Z] = load_grd(handles);
lift = cvlib_mex('resize', lift, [size(Z,1) size(Z,2)]);
lifted = cvlib_mex('add', lift, Z);
miniHandles.head(7:9) = handles.head(7:9); % min/max (5:6) will be updated in GRDdisplay
GRDdisplay(handles,X,Y,lifted,miniHandles.head,[],'AgeLiftedBathymetry',srsWKT)
% Now compute the depth anomaly
cvlib_mex('addS', lift, 2500);
cvlib_mex('add', lift, Z);
GRDdisplay(handles,X,Y,lift,miniHandles.head,[],'Bathymetry anomaly',srsWKT)
% --------------------------------------------------------------------------------------------------
function load_ps(handles, fname)
% Load a PostScript file ... via ghostscript and a MEX to access ghost stdout (SHITY QUALITY)
% P6
% # Image generated by Ghostscript (device=ppmraw)
% 612 792
% 255
P = popenr(['gswin64c -q -r300x300 -sDEVICE=ppmraw -sOutputFile=- ' fname]);
try
% The following while's are because we can't fseek a pipe and header size is variable.
while (popenr(P,1,'char') ~= 10), end % Consume First header line
while (popenr(P,1,'char') ~= 10), end % Consume Second header line
t = ' ';
for (k = 1:20)
t(k) = popenr(P,1,'char');
if (t(k) == 10), break, end % EOF reached
end
t(k:end) = []; % Remove excess characters
ii = find(t == 32); % Find the dimensions separator (a blank)
width = str2double(char( t(1 : ii(1)-1) )');
height = str2double(char( t(ii(1)+1 : end) )');
while (popenr(P,1,'char') ~= 10), end % Consume Fourth header line
img = popenr(P, [height width 3], 'char');
catch
popenr(P, -1) % Close the stdin stream
errordlg(lasterr, 'Error'), return
end
popenr(P, -1) % Close the stdin stream
mirone(img);
% --------------------------------------------------------------------------------------------------
function load_MB(handles, fname, frmt)
% Send MB datalist or single MB file to mbimport and get back an Image like that produced by mbswath
cmd = '';
fid = fopen(fname,'rt');
todos = fread(fid,'*char'); fclose(fid);
if (todos(1) == '#' || todos(1) == '>')
ind = find(todos == 10); % Find new lines
cmd = todos(2:ind(1)-1)';
%todos = todos(ind(1)+1:end);
end
%[nomes, frmt] = strread(todos,'%s %s');
I = gmtmex(['mbimport -I' fname ' ' cmd]);
mirone(I)
if (handles.no_file), delete(handles.figure1), end % Delete the old and empty fig.
% --------------------------------------------------------------------------------------------------
function varargout = ImageCrop_CB(handles, opt, opt2, opt3)
% OPT is either a handle to a line that may be a rectangle/polygon,
% a Mx2, a 2xM matrix with the (x y) vector coordinates, or a [xmin xmax ymin ymax] BB.
% If empty, it calls rubberbandbox to do a interactive croping (called by "Crop Grid")
% OPT2 is a string to direct this function to different operations that
% apply to the grid and update the image.
% OPT3 contains the interpolation method when OPT2 == 'FillGaps' ('cubic', 'linear' or 'sea')
% Or the fill value when OPT2 == 'SetConst'
% Note: I won't make the "Drape" option active in the cropped window
%
% VARARGOUT -> If used will hold the result of this function instead of creating a new Fig
% Currently implemented in cases:
% Crop image (opt == hLine), 'CropaWithCoords', 'CropaGrid_pure', 'ROI_Mean', 'ROI_Median', 'ROI_STD'
% For the 'CropaGrid_pure' case varargout actualy returns 4 values -- {X,Y,Z_rect,head}
if (handles.no_file), return, end
first_nans = 0; pal = []; mask = []; crop_pol = false; % Defaults to croping from a rectangle
wasROI = false; done = false; invert = false;
if (nargin < 3), opt2 = []; end
if (nargin < 4), opt3 = []; end
if ~isempty(opt) % OPT must be a rectangle/polygon handle (the rect may serve many purposes)
if ((numel(opt) == 1) && ishandle(opt))
x = get(opt,'XData'); y = get(opt,'YData');
elseif (numel(opt) == 4) % Assume that we have a [xmin xmax ymin ymax] BB
x = [opt(1) opt(1) opt(2) opt(2) opt(1)];
y = [opt(3) opt(4) opt(4) opt(3) opt(3)];
else
if (size(opt,2) > 2), x = opt(1,1:end); y = opt(2,1:end); % Row vectors
else x = opt(:,1)'; y = opt(:,2)'; % Were col vectors, make them row for consistency
end
end
xp = [min(x) max(x)];
yp = [min(y) max(y)];
if (numel(x) == 5 && (x(1) == x(end)) && (y(1) == y(end)) && ... % Test if we have a rectangle
(x(1) == x(2)) && (x(3) == x(4)) && (y(1) == y(4)) && (y(2) == y(3)) )
if (strcmp(opt2,'SetConst'))
[xp, yp] = aux_funs('adjust_rect', handles, xp, yp); % Adjust such that only inside nodes are selected
end
else
if (xp(1) < handles.head(1) || xp(2) > handles.head(2) || yp(1) < handles.head(3) || yp(2) > handles.head(4))
% Somewhat rare case where the polygon extends to outside grid/img limits. Must crop it to them.
P1.x = x(:); P1.y = y(:); P1.hole = 0; P2.hole = 0;
P2.x = [handles.head(1); handles.head(1); handles.head(2); handles.head(2); handles.head(1)];
P2.y = [handles.head(3); handles.head(4); handles.head(4); handles.head(3); handles.head(3)];
outPolyg = PolygonClip(P1, P2); % Intersection of polygon and map limits
x = outPolyg.x; y = outPolyg.y;
xp(1) = min(x); xp(2) = max(x);
yp(1) = min(y); yp(2) = max(y);
end
x_lim = [min(x) max(x)]; y_lim = [min(y) max(y)];
crop_pol = true; % Flag that we are croping from a polygon
end
rect_crop = [xp(1) yp(1) (xp(2) - xp(1)) (yp(2) - yp(1))]; % Even when from a rectangle (to insure a known order)
if isempty(opt2) % Just pure Image croping
Z_rect = get(handles.hImg,'CData');
if (isa(Z_rect, 'uint16')), Z_rect = scaleto8(Z_rect); end % In the rare event of "Noe Diluge" images
limits = getappdata(handles.axes1,'ThisImageLims');
I = cropimg(limits(1:2),limits(3:4),Z_rect,rect_crop);
if (crop_pol) % Shape cropping
mask = ~(img_fun('roipoly_j',x_lim,y_lim,I,x,y));
if (ndims(I) == 2), I(mask) = 0;
else
for (k = 1:3) % Sorry for the clutereness
tmp = I(:,:,k); tmp(mask) = 255; I(:,:,k) = tmp;
end
mask = uint8(~mask); cvlib_mex('CvtScale',mask,255,0); % NEW. 1st transparency attempt
I(:,:,4) = mask;
clear tmp mask
end
end
[m,n] = size(I);
elseif (strcmp(opt2,'CropaWithCoords')) % Crop Image with coordinates
Z_rect = get(handles.hImg,'CData');
if (isa(Z_rect, 'uint16')), Z_rect = scaleto8(Z_rect); end % In the rare event of "Noe Diluge" images
[I,r_c] = cropimg(handles.head(1:2),handles.head(3:4),Z_rect,rect_crop,'out_grid');
if (crop_pol) % Shape cropping
mask = ~(img_fun('roipoly_j',x_lim,y_lim,I,x,y));
if (ndims(I) == 2), I(mask) = 0;
else
for (k = 1:3)
tmp = I(:,:,k); tmp(mask) = 255; I(:,:,k) = tmp;
end
mask = uint8(~mask); cvlib_mex('CvtScale',mask,255,0); % NEW. 1st transparency attempt
I(:,:,4) = mask;
clear tmp mask
end
end
[m,n] = size(I);
elseif (strcmp(opt2,'ImplantGrid')) % Read and external grid and implant it in host grid
[Z_rect, r_c] = transplants(opt, 'grid', true, handles);
if (isempty(Z_rect)), return, end % User gave up
else % Extract the sub-grid inside the rectangle/polygon
[X,Y,Z,head] = load_grd(handles);
if isempty(Z), return, end % An error message was already issued
[Z_rect,r_c] = cropimg(head(1:2),head(3:4),Z,rect_crop,'out_grid');
if (crop_pol)
zzz = grdutils(Z_rect,'-L'); z_min = zzz(1); clear zzz;
resp = [];
if (strcmp(opt2,'CropaGrid_pure'))
resp = inputdlg({'Enter outside polygon value'},'Choose out value',[1 30],{sprintf('%.4f',z_min)}); pause(0.01)
if isempty(resp), return, end
resp = str2double(resp{1});
elseif (strcmp(opt2,'ROI_SetConst')) % Set the polygon in-or-out to cte
resp = question({'Enter new grid value'},'Replace with cte value',[1 30],'NaN','whatever');
if isempty(resp), return, end
invert = resp{2};
resp = str2double(resp{1});
end
if (isnan(resp)), handles.have_nans = 1; end
mask = img_fun('roipoly_j', x_lim, y_lim, Z_rect, x, y);
if (strcmp(opt2,'CropaGrid_pure'))
Z_rect(~mask) = single(resp);
elseif (strcmp(opt2,'ROI_SetConst'))
if (invert), mask = ~mask; end % Mask in the outside instead
Z_rect(mask) = single(resp); % Set the mask values to const
if (invert)
Z(:) = single(resp); % Actually, we need to mask the whole outside
else
handles.Z_back = Z(r_c(1):r_c(2),r_c(3):r_c(4)); handles.r_c = r_c; % For the Undo op
end
Z(r_c(1):r_c(2),r_c(3):r_c(4)) = Z_rect;
if (isnan(resp)), handles.have_nans = 1; first_nans = 1; end
elseif (strcmp(opt2,'ROI_Mean'))
res = Z_rect(mask); res(isnan(res)) = []; res = mean(double(res));
if (nargout), varargout{1} = res; return, end
msgbox(sprintf('Mean over ROI = %15g',res),'ROI-Mean'), return
elseif (strcmp(opt2,'ROI_Median'))
res = Z_rect(mask); res(isnan(res)) = []; res = median(res);
if (nargout), varargout{1} = res; return, end
msgbox(sprintf('Median over ROI = %15g',res),'ROI-Median'), return
elseif (strcmp(opt2,'ROI_STD'))
res = Z_rect(mask); res(isnan(res)) = []; res = std(double(res));
if (nargout), varargout{1} = res; return, end
msgbox(sprintf('STD over ROI = %15g',res),'ROI-STD'), return
elseif (strcmp(opt2,'ROI_MedianFilter'))
[Z,Z_rect,handles] = roi_filtering(handles, Z, head, Z_rect, r_c, mask);
elseif (strcmp(opt2,'ROI_SplineSmooth'))
opt2 = 'SplineSmooth'; % Strip the 'ROI_' part so that we can use the same code as for rectangles
wasROI = true; % Signal the SplineSmooth code below that we need to mask result
elseif (strncmp(opt2,'ROI_FillSinks', 13))
opt2 = opt2(5:end); % Strip the 'ROI_' part so that we can use the same code as for rectangles
wasROI = true; % Signal the FillSinks_xxxx code below that we need to mask result
elseif (strcmp(opt2,'CropaGrid_histo'))
Z_rect(~mask) = single(NaN);
elseif (strcmp(opt2,'ROI_Clip'))
opt2 = 'Clip'; % Now that we have the mask, make this case == to rectangle clip
else
errordlg('Unknown case in ImageCrop','Error'), return
end
end
[m,n] = size(Z_rect);
end
else % Interactive croping (either Grid or Image)
if (strcmp(opt2,'CropaGrid')) % Arrive here when called by "Grid Tools -> Crop Grid"
[X,Y,Z,head] = load_grd(handles);
if isempty(Z), return, end
[p1,p2] = rubberbandbox;
x0 = min(p1(1),p2(1)); y0 = min(p1(2),p2(2));
dx = abs(p2(1)-p1(1)); dy = abs(p2(2)-p1(2));
[Z_rect,r_c] = cropimg([head(1) head(2)],[head(3) head(4)],Z,[x0 y0 dx dy],'out_grid');
X = linspace( head(1) + (r_c(3)-1)*head(8), head(1) + (r_c(4)-1)*head(8), r_c(4) - r_c(3) + 1 );
Y = linspace( head(3) + (r_c(1)-1)*head(9), head(3) + (r_c(2)-1)*head(9), r_c(2) - r_c(1) + 1 );
head(1) = X(1); head(2) = X(end); head(3) = Y(1); head(4) = Y(end);
tit = 'Grid cut by Mirone'; % Have to change this to reflect the old title
GRDdisplay(handles,X,Y,Z_rect,head,tit,'Cropped_grid')
return
else % Just a image crop op
I = cropimg; [m,n] = size(I);
end
end
if (isempty(opt2) || strcmp(opt2,'CropaWithCoords')) % Just pure Image croping
if (m < 2 || n < 2), return, end % Image too small.
if (strcmp(get(handles.axes1,'Ydir'),'normal')), I = flipdim(I,1); end
if (ndims(I) == 2)
pal = get(handles.figure1, 'Colormap');
if (length(pal) == 64), pal = jet(256); end % Risky - This is a patch for "Find Clusters"
setappdata(0,'CropedColormap',pal); % indexed image, so I need to save it's colormap
end
set(handles.figure1,'pointer','arrow');
if (~isempty(opt2))
head(2) = handles.head(1) + (r_c(4)-1)*handles.head(8);
head(1) = handles.head(1) + (r_c(3)-1)*handles.head(8);
head(4) = handles.head(3) + (r_c(2)-1)*handles.head(9);
head(3) = handles.head(3) + (r_c(1)-1)*handles.head(9);
head(5:9) = [0 255 0 handles.head(8:9)]; tmp.name = 'Cropped_image';
tmp.head = head; tmp.geog = handles.geog; tmp.X = head(1:2); tmp.Y = head(3:4);
if (~isempty(pal)), tmp.cmap = pal; end
proj4 = getappdata(handles.figure1,'Proj4');
if (~isempty(proj4))
tmp.srsWKT = ogrproj(proj4);
else
projWKT = getappdata(handles.figure1,'ProjWKT');
if (~isempty(projWKT)), tmp.srsWKT = projWKT; end
end
end
if (nargout)
varargout{1} = I;
if (nargout == 2), varargout{2} = tmp; end
elseif (isempty(opt2)) % Crop without coords
mirone(I);
else
mirone(flipdim(I,1),tmp); % Crop with coords
end
done = true; % We are done. BYE BYE.
elseif (strncmp(opt2(1:min(length(opt2),9)),'CropaGrid',9)) % Do the operation indicated in opt2(11:end) & return
curr_opt = opt2(11:end);
if (~strcmp(curr_opt,'pure')) % We will need those for all other options
head(2) = head(1) + (r_c(4)-1)*head(8); head(1) = head(1) + (r_c(3)-1)*head(8);
head(4) = head(3) + (r_c(2)-1)*head(9); head(3) = head(3) + (r_c(1)-1)*head(9);
if (isa(Z,'single')), zz = grdutils(Z_rect,'-L'); head(5:6) = [zz(1) zz(2)];
else head(5) = double(min(Z_rect(:))); head(6) = double(max(Z_rect(:)));
end
to_func.Z = Z_rect; to_func.head = head;
end
if (strcmp(curr_opt,'pure')) % PURE means pure CropaGrid
X = linspace( head(1) + (r_c(3)-1)*head(8), head(1) + (r_c(4)-1)*head(8), r_c(4) - r_c(3) + 1 );
Y = linspace( head(3) + (r_c(1)-1)*head(9), head(3) + (r_c(2)-1)*head(9), r_c(2) - r_c(1) + 1 );
head(1) = X(1); head(2) = X(end); head(3) = Y(1); head(4) = Y(end);
if (isa(Z,'single')), zz = grdutils(Z_rect,'-L'); head(5:6) = [zz(1) zz(2)];
else head(5) = double(min(Z_rect(:))); head(6) = double(max(Z_rect(:)));
end
srsWKT = [];
if (~handles.geog)
prjInfoStruc = aux_funs('getFigProjInfo',handles);
if (~isempty(prjInfoStruc.projWKT)) % TODO. Otherwise check if prjInfoStruc.proj4 and convert it to WKT
srsWKT = prjInfoStruc.projWKT;
end
end
if (~nargout) % Create a new Fig
tit = 'Grid cuted by Mirone'; % Have to change this to reflect the old title
GRDdisplay(handles,X,Y,Z_rect,head,tit,'Cropped_grid',srsWKT)
else % Send back the cropped grid to whom asked for it.
varargout = {X,Y,Z_rect,head}; % Is not going to be easy to document this
end
elseif (strcmp(curr_opt,'histo')) % HISTO means compute histogram inside the selected rect area
GridToolsHistogram_CB(guidata(handles.figure1), to_func);
elseif (strcmp(curr_opt,'power')) % POWER means compute log10 power spectrum
GridToolsSectrum_CB(guidata(handles.figure1), 'Power', to_func)
elseif (strcmp(curr_opt,'autocorr')) % AUTOCORR means compute the autocorrelation
GridToolsSectrum_CB(guidata(handles.figure1), 'Autocorr', to_func)
elseif (strcmp(curr_opt,'fftTools')) % FFTTOOLS means call the fft_stuff
GridToolsSectrum_CB(guidata(handles.figure1), 'Allopts', to_func)
end
done = true; % We are done. BYE BYE.
elseif (strcmp(opt2,'FillGaps'))
if ~any(isnan(Z_rect(:))) % No gaps
warndlg('Selected area does not have any voids (NaNs)','Warning'), return
end
X = linspace( head(1) + (r_c(3)-1)*head(8), head(1) + (r_c(4)-1)*head(8), r_c(4) - r_c(3) + 1 );
Y = linspace( head(3) + (r_c(1)-1)*head(9), head(3) + (r_c(2)-1)*head(9), r_c(2) - r_c(1) + 1 );
if (~isempty(opt3) && strcmp(opt3,'surface'))
opt_R = sprintf('-R%.10f/%.10f/%.10f/%.10f', X(1), X(end), Y(1), Y(end));
opt_I = sprintf('-I%.10f/%.10f',head(8),head(9));
end
Z_rect = double(Z_rect); % It has to be
aa = isnan(Z_rect(:));
[X,Y] = meshgrid(X,Y);
ZZ = Z_rect(:); ZZ(aa) = [];
XX = X(:); XX(aa) = [];
YY = Y(:); YY(aa) = [];
if (~isempty(opt3))
switch opt3
case 'surface', Z_rect = gmtmbgrid_m(XX,YY,ZZ,opt_R,opt_I,'-T.25', '-Mz');
case 'cubic', Z_rect = griddata_j(XX,YY,ZZ,X,Y,'cubic');
case 'linear', Z_rect = griddata_j(XX,YY,ZZ,X,Y,'linear');
case 'sea', Z_rect(aa) = 0;
end
else
Z_rect = gmtmbgrid_m(XX,YY,ZZ,opt_R,opt_I,'-T.25','-v', '-Mz');
end
clear X XX Y YY ZZ;
elseif (strncmp(opt2,'FillSinks', 9))
handles.Z_back = Z(r_c(1):r_c(2),r_c(3):r_c(4)); handles.r_c = r_c; % For the Undo op
if (strcmp(opt2,'FillSinks_pitt')) % Fill up the holes
Z_rect = img_fun('imfill', Z_rect, 'holes');
else % Slice the peaks
grdutils(Z_rect, '-M-1'); % In-situ op
Z_rect = img_fun('imfill', Z_rect, 'holes');
grdutils(Z_rect, '-M-1'); % Set it back to vert-up
end
if (wasROI) % Reset the outside ROI to unchanged values
Z_rect(~mask) = handles.Z_back(~mask);
end
elseif (strcmp(opt2,'SplineSmooth'))
X = linspace( head(1) + (r_c(3)-1)*head(8), head(1) + (r_c(4)-1)*head(8), r_c(4) - r_c(3) + 1 );
Y = linspace( head(3) + (r_c(1)-1)*head(9), head(3) + (r_c(2)-1)*head(9), r_c(2) - r_c(1) + 1 );
Z_rect = double(Z_rect); % It has to be
[pp, p_guess] = spl_fun('csaps',{Y(1:min(m,10)),X(1:min(n,10))},Z_rect(1:min(m,10),1:min(n,10)));% Get a good estimate of p
prompt = {'Enter smoothing p paramer'}; dlg_title = 'Smoothing parameter input';
defAns = {sprintf('%.12f',p_guess{1})}; resp = inputdlg(prompt,dlg_title,[1 38],defAns);
if (isempty(resp)), return, end
resp = str2double(resp{1});
if (isnan(resp)), set(handles.figure1,'pointer','arrow'), return, end
pp = spl_fun('csaps',{Y,X},Z_rect,resp);
Z_rect = spl_fun('fnval',pp,{Y,X}); clear pp;
handles.Z_back = Z(r_c(1):r_c(2),r_c(3):r_c(4)); handles.r_c = r_c; % For the Undo op
if (wasROI) % Apply the mask and smooth over the mask edges
Z_rect = smooth_roipoly_edge(head, handles.have_nans, Z, handles.Z_back, Z_rect, r_c, mask, 3);
end
elseif (strcmp(opt2,'MedianFilter'))
[Z,Z_rect,handles] = roi_filtering(handles, Z, head, Z_rect, r_c, 'rect', 'no');
elseif (strcmp(opt2,'Clip'))
handles.Z_back = Z(r_c(1):r_c(2),r_c(3):r_c(4)); handles.r_c = r_c; % For the Undo op
[Z_rect,head] = ml_clip(handles, handles.Z_back);
if (isempty(Z_rect)), return, end
handles.head(5:6) = head(5:6);