PageRenderTime 54ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/other/Matlab/detection/detect_fit.m

http://github.com/jbeezley/wrf-fire
Objective C | 289 lines | 249 code | 40 blank | 0 comment | 24 complexity | a7ad0631ad0391c8d163e8552bb5c64a MD5 | raw file
Possible License(s): AGPL-1.0
  1. function analysis=detect_fit
  2. % from a copy of barker2
  3. disp('input data')
  4. % to create conus.kml:
  5. % download http://firemapper.sc.egov.usda.gov/data_viirs/kml/conus_hist/conus_20120914.kmz
  6. % and gunzip
  7. %
  8. % to create w.mat:
  9. % run Adam's simulation, currently results in
  10. % /home/akochans/NASA_WSU/wrf-fire/WRFV3/test/em_barker_moist/wrfoutputfiles_live_0.25
  11. % then in Matlab
  12. % f='wrfout_d05_2012-09-15_00:00:00';
  13. % t=nc2struct(f,{'Times'},{'DX','DY'}); n=size(t.times,2); w=nc2struct(f,{'TIGN_G','FXLONG','FXLAT','UNIT_FXLAT','UNIT_FXLONG'},{},n);
  14. % save ~/w.mat w
  15. %
  16. % to create c.mat
  17. % c=nc2struct(f,{'NFUEL_CAT'},{},1);
  18. % save ~/c.mat c
  19. %
  20. % to create s.mat:
  21. % s=read_wrfout_sel({'wrfout_d05_2012-09-09_00:00:00','wrfout_d05_2012-09-12_00:00:00','wrfout_d05_2012-09-15_00:00:00'},{'FGRNHFX'});
  22. % save ~/s.mat s
  23. %
  24. % fuels.m is created by WRF-SFIRE at the beginning of the run
  25. % ****** REQUIRES Matlab 2013a - will not run in earlier versions *******
  26. conus = input_num('0 for viirs, 1 for modis',0);
  27. if conus==0,
  28. v=read_fire_kml('conus_viirs.kml');
  29. detection='VIIRS';
  30. elseif conus==1,
  31. v=read_fire_kml('conus_modis.kml');
  32. detection='MODIS';
  33. else
  34. error('need kml file')
  35. end
  36. a=load('w');w=a.w;
  37. if ~isfield('dx',w),
  38. w.dx=444.44;
  39. w.dy=444.44;
  40. warning('fixing up w for old w.mat file from Barker fire')
  41. end
  42. a=load('s');s=a.s;
  43. a=load('c');c=a.c;
  44. fuel.weight=0; % just to let Matlab know what fuel is going to be at compile time
  45. fuels
  46. disp('subset and process inputs')
  47. % establish boundaries from simulations
  48. min_lat = min(w.fxlat(:))
  49. max_lat = max(w.fxlat(:))
  50. min_lon = min(w.fxlong(:))
  51. max_lon = max(w.fxlong(:))
  52. min_tign= min(w.tign_g(:))
  53. default_bounds{1}=[min_lon,max_lon,min_lat,max_lat];
  54. default_bounds{2}=[-119.5, -119.0, 47.95, 48.15];
  55. display_bounds=default_bounds{2};
  56. for i=1:length(default_bounds),fprintf('default bounds %i: %8.5f %8.5f %8.5f %8.5f\n',i,default_bounds{i});end
  57. bounds=input_num('bounds [min_lon,max_lon,min_lat,max_lat] or number of bounds above',1);
  58. if length(bounds)==1, bounds=default_bounds{bounds}; end
  59. [ii,jj]=find(w.fxlong>=bounds(1) & w.fxlong<=bounds(2) & w.fxlat >=bounds(3) & w.fxlat <=bounds(4));
  60. ispan=min(ii):max(ii);
  61. jspan=min(jj):max(jj);
  62. % restrict data
  63. w.fxlat=w.fxlat(ispan,jspan);
  64. w.fxlong=w.fxlong(ispan,jspan);
  65. w.tign_g=w.tign_g(ispan,jspan);
  66. c.nfuel_cat=c.nfuel_cat(ispan,jspan);
  67. min_lat = min(w.fxlat(:))
  68. max_lat = max(w.fxlat(:))
  69. min_lon = min(w.fxlong(:))
  70. max_lon = max(w.fxlong(:))
  71. min_lon = display_bounds(1);
  72. max_lon = display_bounds(2);
  73. min_lat = display_bounds(3);
  74. max_lat = display_bounds(4);
  75. min_tign= min(w.tign_g(:))
  76. % rebase time on the largest tign_g = the time of the last frame, in days
  77. last_time=datenum(char(w.times)');
  78. max_tign_g=max(w.tign_g(:));
  79. tim_all = v.tim - last_time;
  80. tign= (w.tign_g - max_tign_g)/(24*60*60); % now tign is in days
  81. min_tign= min(tign(:)); % initial ignition time
  82. tign_disp=tign;
  83. tign_disp(tign==0)=NaN; % for display
  84. % select fire detection within the domain and time
  85. bii=(v.lon > min_lon & v.lon < max_lon & v.lat > min_lat & v.lat < max_lat);
  86. tim_in = tim_all(bii);
  87. u_in = unique(tim_in);
  88. fprintf('detection times from first ignition\n')
  89. for i=1:length(u_in)
  90. detection_freq(i)=sum(tim_in==u_in(i));
  91. fprintf('%8.5f days %s UTC %3i %s detections\n',u_in(i)-min_tign,...
  92. datestr(u_in(i)+last_time),detection_freq(i),detection);
  93. end
  94. [max_freq,i]=max(detection_freq);
  95. tol=0.01;
  96. detection_bounds=input_num('detection bounds as [upper,lower]',...
  97. [u_in(i)-min_tign-tol,u_in(i)-min_tign+tol]);
  98. bi = bii & detection_bounds(1) + min_tign <= tim_all ...
  99. & tim_all <= detection_bounds(2) + min_tign;
  100. % now detection selected in time and space
  101. lon=v.lon(bi);
  102. lat=v.lat(bi);
  103. res=v.res(bi);
  104. tim=tim_all(bi);
  105. tim_ref = mean(tim);
  106. fprintf('%i detections selected\n',sum(bi))
  107. detection_days_from_ignition=tim_ref-min_tign;
  108. detection_datestr=datestr(tim_ref+last_time);
  109. fprintf('mean detection time %g days from ignition %s UTC\n',...
  110. detection_days_from_ignition,detection_datestr);
  111. fprintf('days from ignition min %8.5f max %8.5f\n',min(tim)-min_tign,max(tim)-min_tign);
  112. fprintf('longitude min %8.5f max %8.5f\n',min(lon),max(lon));
  113. fprintf('latitude min %8.5f max %8.5f\n',min(lat),max(lat));
  114. % detection selected in time and space
  115. lon=v.lon(bi);
  116. lat=v.lat(bi);
  117. res=v.res(bi);
  118. tim=tim_all(bi);
  119. % set up reduced resolution plots
  120. [m,n]=size(w.fxlong);
  121. m_plot=m; n_plot=n;
  122. m1=map_index(display_bounds(1),bounds(1),bounds(2),m);
  123. m2=map_index(display_bounds(2),bounds(1),bounds(2),m);
  124. n1=map_index(display_bounds(3),bounds(3),bounds(4),n);
  125. n2=map_index(display_bounds(4),bounds(3),bounds(4),n);
  126. mi=m1:ceil((m2-m1+1)/m_plot):m2; % reduced index vectors
  127. ni=n1:ceil((n2-n1+1)/n_plot):n2;
  128. mesh_fxlong=w.fxlong(mi,ni);
  129. mesh_fxlat=w.fxlat(mi,ni);
  130. [mesh_m,mesh_n]=size(mesh_fxlat);
  131. % find ignition point
  132. [i_ign,j_ign]=find(w.tign_g == min(w.tign_g(:)));
  133. if length(i_ign)~=1,error('assuming single ignition point here'),end
  134. % set up constraint on ignition point being the same
  135. Constr_ign = zeros(m,n); Constr_ign(i_ign,j_ign)=1;
  136. detection_mask=zeros(m,n);
  137. detection_time=tim_ref*ones(m,n);
  138. % resolution diameter in longitude/latitude units
  139. rlon=0.5*res/w.unit_fxlong;
  140. rlat=0.5*res/w.unit_fxlat;
  141. lon1=lon-rlon;
  142. lon2=lon+rlon;
  143. lat1=lat-rlat;
  144. lat2=lat+rlat;
  145. for i=1:length(lon),
  146. square = w.fxlong>=lon1(i) & w.fxlong<=lon2(i) & ...
  147. w.fxlat >=lat1(i) & w.fxlat <=lat2(i);
  148. detection_mask(square)=1;
  149. end
  150. C=0.5*ones(1,length(res));
  151. X=[lon-rlon,lon+rlon,lon+rlon,lon-rlon]';
  152. Y=[lat-rlat,lat-rlat,lat+rlat,lat+rlat]';
  153. plotstate(1,detection_mask,['Fire detection at ',detection_datestr],[])
  154. % add ignition point
  155. hold on, plot(w.fxlong(i_ign,j_ign),w.fxlat(i_ign,j_ign),'xw'); hold off
  156. % legend('first ignition at %g %g',w.fxlong(i_ign,j_ign),w.fxlat(i_ign,j_ign))
  157. fuelweight(length(fuel)+1:max(c.nfuel_cat(:)))=NaN;
  158. for j=1:length(fuel),
  159. fuelweight(j)=fuel(j).weight;
  160. end
  161. W = zeros(m,n);
  162. for j=1:n, for i=1:m
  163. W(i,j)=fuelweight(c.nfuel_cat(i,j));
  164. end,end
  165. plotstate(2,W,'Fuel weight',[])
  166. disp('optimization loop')
  167. h =zeros(m,n); % initial increment
  168. plotstate(3,tign,'Forecast fire arrival time',detection_time(1));
  169. for istep=1:5
  170. % can change the objective function here
  171. alpha=input_num('penalty coefficient alpha, <0 to end',1e-2);
  172. if alpha<0, break, end
  173. % TC = W/(900*24); % time constant = fuel gone in one hour
  174. TC = 1/24; % detection time constants in hours
  175. stretch=input_num('Tmin,Tmax,Tneg,Tpos',[0.5,10,5,10]);
  176. nodetw=input_num('no fire detection weight',0.1);
  177. power=input_num('negative laplacian power',0.51);
  178. psi = detection_mask - nodetw*(1-detection_mask);
  179. [Js,search]=objective(tign,h);
  180. search = -search/big(search); % initial search direction
  181. plotstate(4,search,'Search direction',0);
  182. h=zeros(m,n); % initial increment
  183. stepsize=0;
  184. % initial estimate of stepsize
  185. last_stepsize = 3;
  186. for i=2:100 % crude manual line search
  187. s=input_num('step size',last_stepsize);
  188. stepsize(i)=s;
  189. last_stepsize=s;
  190. plotstate(5,tign+h+last_stepsize*search,'Line search',detection_time(1));
  191. [Js(i),delta]=objective(tign,h+last_stepsize*search,'noplot');
  192. c=input_num('try another step size: 0/1',1)
  193. if c==0, break, end
  194. end
  195. h = h + last_stepsize*search;
  196. plotstate(6,tign+h,sprintf('Analysis descent iteration %i',istep),detection_time(1));
  197. end
  198. disp('converting analysis fire arrival time from days with zero at the end of the fire to original scale')
  199. analysis=max_tign_g+(24*60*60)*(tign+h);
  200. disp('input the analysis as tign in WRF-SFIRE with fire_perimeter_time=detection time')
  201. function [J,delta]=objective(tign,h,noplot)
  202. % compute objective function and optionally ascent direction
  203. T=tign+h;
  204. [f0,f1]=like1(psi,detection_time-T,TC*stretch);
  205. F = f1; % forcing
  206. % objective function and preconditioned gradient
  207. Ah = poisson_fft2(h,[w.dx,w.dy],1);
  208. J = alpha*0.5*(h(:)'*Ah(:)) - ssum(psi.*f0)/(m*n);
  209. fprintf('Objective function J=%g\n',J);
  210. gradJ = alpha*Ah + F;
  211. if ~exist('noplot','var'),
  212. plotstate(7,f0,'Detection likelihood',0.5,'-w');
  213. plotstate(8,f1,'Detection likelihood derivative',0);
  214. plotstate(9,F,'Forcing',0);
  215. plotstate(10,gradJ,'gradient of J',0);
  216. end
  217. delta = solve_saddle(Constr_ign,h,F,0,@(u) poisson_fft2(u,[w.dx,w.dy],-power)/alpha);
  218. % plotstate(11,delta,'Preconditioned gradient',0);
  219. fprintf('norm(grad(J))=%g norm(delta)=%g\n',norm(gradJ,'fro'),norm(delta,'fro'))
  220. end
  221. function plotstate(fig,T,s,c,linespec)
  222. fprintf('Figure %i %s\n',fig,s)
  223. plotmap(fig,mesh_fxlong,mesh_fxlat,T(mi,ni),' ');
  224. hold on
  225. hh=fill(X,Y,C,'EdgeAlpha',1,'FaceAlpha',0);
  226. if ~exist('c','var') || isempty(c) || isnan(c),
  227. title(s);
  228. else
  229. title(sprintf('%s, contour=%g',s,c(1)))
  230. if ~exist('linespec','var'),
  231. linespec='-k';
  232. end
  233. contour(mesh_fxlong,mesh_fxlat,T(mi,ni),[c c],linespec)
  234. end
  235. hold off
  236. ratio=[w.unit_fxlat,w.unit_fxlong];
  237. xlabel longtitude
  238. ylabel latitude
  239. ratio=[ratio/norm(ratio),1];
  240. daspect(ratio)
  241. axis tight
  242. drawnow
  243. end
  244. end % detect_fit
  245. function i=map_index(x,a,b,n)
  246. % find image of x under linear map [a,b] -> [1,m]
  247. % and round to integer
  248. i=round(1+(n-1)*(x-a)/(b-a));
  249. end