001 /*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2013
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 *
010 * All Rights Reserved
011 *
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.
014 *
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 *
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023 * GNU Lesser Public License for more details.
024 *
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program. If not, see http://www.gnu.org/licenses.
027 */
028
029 package edu.wisc.ssec.mcidasv.control.cyclone;
030
031 import java.util.ArrayList;
032 import java.util.List;
033
034 /**
035 * Created by IntelliJ IDEA. User: yuanho Date: Mar 9, 2009 Time: 2:16:30 PM To
036 * change this template use File | Settings | File Templates.
037 */
038 public class StormAODTUtil {
039
040 /**
041 * _more_
042 *
043 * @param odtcurrent
044 * _more_
045 * @param domain
046 * _more_
047 *
048 * @return _more_
049 */
050 public static List aodtv72_textscreenoutput(
051 StormAODTInfo.IRData odtcurrent, int domain)
052 /*
053 * Output information to text screen. Inputs : global structure
054 * odtcurrent_v72 containting current image information Outputs : none
055 */
056 {
057
058 int day, mon, year, ibasin, iok;
059 int degree, minute, second, xr8 = 0, xr9 = 0, xrpd = 0;
060 int cloudcat, eyecat, cfft;
061 int ptr, ptr2, nptr;
062 String cdate, ctime, clat, clon;
063 String cmin, csec, clatmax, clonmax;
064 char iout2;
065 String latc = "N", lonc = "W";
066 String[] cr9 = { "OFF ", "ON ", "WEAKEN" };
067 String[] crpd = { "OFF ", "FLAG ", "ON ", "ON " };
068 String[] cbd = { "LOW CLD", "OFF WHT", "DK GRAY", "MD GRAY", "LT GRAY",
069 "BLACK ", "WHITE " };
070 String[] cr8 = { "NO LIMIT ", "0.5T/6hr ", "1.2T/6hr ", "1.7T/12hr",
071 "2.2T/18hr", "2.7T/24hr", " ", " ",
072 "0.1T/hour", "0.5T/hour", "NO LIMIT ", "0.5T/6hr ",
073 "1.7T/6hr ", "2.2T/12hr", "2.7T/18hr", "3.2T/24hr",
074 " ", " ", "0.1T/hour", "0.5T/hour",
075 "NO LIMIT ", "0.5T/6hr ", "0.7T/6hr ", "1.2T/12hr",
076 "1.7T/18hr", "2.2T/24hr", " ", " ",
077 "0.1T/hour", "0.5T/hour" };
078 String[] basin = { "ATLANTIC ", "WEST PACIFIC", "EAST PACIFIC",
079 "INDIAN " };
080 String[] cuse = { "MANUAL", "FORECAST INTERPOLATION",
081 "LAPLACIAN ANALYSIS", "WARMEST PIXEL SEARCH",
082 "SPIRAL ANALYSIS", "RING/SPIRAL COMBINATION",
083 "LINEAR EXTRAPOLATION" };
084 String scenetype;
085 String scenetypemax;
086 String scenetypemaxll;
087 String eyermw;
088 String version;
089 float pwip, pwiw, cloudtemp, arcd, arcdmax, sdist, xlat, xlon, m;
090 boolean bettercb = false, rmwflag = false;
091
092 /* convert Julian date/time to day/month/year format */
093 int[] out = aodtv72_yddmy(odtcurrent.date);
094 day = out[0];
095 mon = out[1];
096 year = out[2];
097 /* format character string for date output */
098 cdate = Integer.toString(day) + "-" + Integer.toString(mon) + "-"
099 + Integer.toString(year);
100
101 /* format character string for time output */
102
103 ctime = Integer.toString(odtcurrent.time);
104
105 /* convert xx.xxxx latitude format to degree/minute/second format */
106 xlat = odtcurrent.latitude;
107 xlon = odtcurrent.longitude;
108 out = aodtv72_lldms(xlat);
109 degree = out[0];
110 minute = out[1];
111 second = out[2];
112
113 if (xlat < 0.0) {
114 latc = "S";
115 }
116 /* format character string for latitude output */
117
118 clat = Integer.toString(degree) + "-" + Integer.toString(minute) + "-"
119 + Integer.toString(second) + latc;
120
121 /* convert xx.xxxx longitude format to degree/minute/second format */
122 out = aodtv72_lldms(xlon);
123 degree = out[0];
124 minute = out[1];
125 second = out[2];
126 if (xlon < 0.0) {
127 lonc = "E";
128 }
129 /* format character string for longitude output */
130
131 clon = Integer.toString(degree) + "-" + Integer.toString(minute) + "-"
132 + Integer.toString(second) + lonc;
133
134 /* determine current ocean basin in which storm is located */
135 // ibasin=aodtv72_oceanbasin(xlat,xlon);
136
137 /* determine Dvorak pressure/wind speed in relation to final CI # */
138 pwip = aodtv72_getpwval(0, odtcurrent.CI, domain);
139 pwiw = aodtv72_getpwval(1, odtcurrent.CI, domain);
140
141 /* determine Rule 8 and Rule 9 screen output values */
142 xr8 = odtcurrent.rule8;
143 if (odtcurrent.rule9 == 1) {
144 xr9 = 1;
145 }
146 xrpd = odtcurrent.rapiddiss;
147 cloudtemp = odtcurrent.cloudt;
148 /* determine scenetype to be output to screen */
149 eyecat = odtcurrent.eyescene;
150 cloudcat = odtcurrent.cloudscene;
151 cfft = odtcurrent.cloudfft;
152 if (cloudcat == 2) {
153 scenetype = StormAODTInfo.cloudtype_v72[cloudcat];
154 } else if (cloudcat == 3) {
155 arcd = (float) (odtcurrent.ringcbval - 1) / 24.0f;
156 arcdmax = (float) (odtcurrent.ringcbvalmax - 1) / 25.0f;
157 if (arcdmax > arcd) {
158 bettercb = true;
159 }
160 scenetype = "CURVED BAND with " + arcd + " ARC in "
161 + cbd[odtcurrent.ringcb];
162
163 if (bettercb) {
164 scenetypemax = "Maximum CURVED BAND with " + arcdmax
165 + " ARC in " + cbd[odtcurrent.ringcb];
166
167 /*
168 * convert xx.xxxx latitude format to degree/minute/second
169 * format
170 */
171 out = aodtv72_lldms(odtcurrent.ringcblatmax);
172 degree = out[0];
173 minute = out[1];
174 second = out[2];
175
176 if (odtcurrent.ringcblatmax < 0.0) {
177 latc = "S";
178 }
179 /* format character string for latitude output */
180 clatmax = Integer.toString(degree) + "-"
181 + Integer.toString(minute) + "-"
182 + Integer.toString(second) + latc;
183
184 /*
185 * convert xx.xxxx longitude format to degree/minute/second
186 * format
187 */
188 out = aodtv72_lldms(odtcurrent.ringcblonmax);
189 degree = out[0];
190 minute = out[1];
191 second = out[2];
192
193 if (odtcurrent.ringcblonmax < 0.0) {
194 lonc = "E";
195 }
196 /* format character string for longitude output */
197 clonmax = Integer.toString(degree) + "-"
198 + Integer.toString(minute) + "-"
199 + Integer.toString(second) + lonc;
200
201 scenetypemaxll = " at Lat:" + clatmax + " Lon:" + clonmax;
202
203 }
204 } else if (cloudcat == 4) {
205 sdist = odtcurrent.eyecdosize / 110.0f;
206 if (sdist < 1.30) {
207 scenetype = "SHEAR (%4.2f^ TO DG)* " + sdist;
208 } else {
209 scenetype = "SHEAR (>1.25^ TO DG)*";
210 }
211
212 } else {
213 if (eyecat <= 2) {
214 scenetype = StormAODTInfo.eyetype_v72[eyecat];
215 if (eyecat <= 2) {
216 rmwflag = true;
217 }
218
219 if (odtcurrent.rmw < 0.0) {
220 if (eyecat == 1) {
221 eyermw = "<10";
222 } else {
223 eyermw = "N/A";
224 }
225 } else {
226 eyermw = Integer.toString((int) odtcurrent.rmw);
227 /* if(eyecat==1) sprintf(eyermw,"<10"); */
228 }
229 } else {
230 scenetype = "CLOUD REGION* "
231 + StormAODTInfo.cloudtype_v72[cloudcat];
232 }
233
234 }
235
236 List result = new ArrayList();
237
238 /* send results to the screen */
239 result.add("<tr><td>"
240 + "\n****************************************************\n"
241 + "</td></tr>");
242 result.add("<tr><td>" + " ADVANCED DVORAK TECHNIQUE \n"
243 + "</td></tr>");
244 result.add("<tr><td>"
245 + " Tropical Cyclone Intensity Algorithm \n\n"
246 + "</td></tr>");
247 result.add("<tr><td>" + " ----- Current Analysis ----- \n"
248 + "</td></tr>");
249 result.add("<tr><td>" + " Date : " + cdate + "Time : " + ctime + "\n"
250 + "</td></tr>");
251 result.add("<tr><td>" + " Lat : " + clat + "Lon : " + clon + "\n"
252 + "</td></tr>");
253 if ((odtcurrent.land == 1)) {
254 result.add("<tr><td>"
255 + " TROPICAL CYCLONE OVER LAND\n"
256 + "</td></tr>");
257 result.add("<tr><td>"
258 + " NO ADT ANALYSIS AVAILABLE\n"
259 + "</td></tr>");
260 } else {
261 result.add("<tr><td>" + " CI# /Pressure/ Vmax\n" + "</td></tr>");
262 result.add("<tr><td>" + odtcurrent.CI + " "
263 + (pwip + odtcurrent.CIadjp) + " " + pwiw + "\n"
264 + "</td></tr>");
265
266 result.add("<tr><td>" + "Latitude bias adjustment to MSLP : "
267 + odtcurrent.CIadjp + "\n" + "</td></tr>");
268 result.add("<tr><td>" + " Center Temp : " + odtcurrent.eyet
269 + "Cloud Region Temp : " + cloudtemp + "\n" + "</td></tr>");
270 result.add("<tr><td>" + " Scene Type : " + scenetype + "\n"
271 + "</td></tr>");
272
273 }
274
275 result.add("<tr><td>"
276 + "\n****************************************************\n"
277 + "</td></tr>");
278
279 return result;
280
281 }
282
283 /**
284 * _more_
285 *
286 * @param llval
287 * _more_
288 *
289 * @return _more_
290 */
291 public static int[] aodtv72_lldms(float llval)
292 /*
293 * Convert degree.degree to degree/minute/second format. Inputs : llval -
294 * latitude/longitude to convert Outputs : degree - degrees minute - minutes
295 * second - seconds
296 */
297 {
298 int deg;
299 float min, sec;
300
301 deg = (int) llval;
302 min = (llval - (float) deg) * 60.0f;
303 sec = (min - (float) ((int) min)) * 60.0f;
304
305 int[] out = { deg, (int) min, (int) sec };
306
307 return out;
308 }
309
310 /**
311 * _more_
312 *
313 * @param syd
314 * _more_
315 *
316 * @return _more_
317 */
318 public static int[] aodtv72_yddmy(int syd)
319 /*
320 * Convert yyyyddd to dd/mm/yy format. Inputs : syd - Julian day (yyyyddd)
321 * Outputs : day - date month - month year - year (yyyy)
322 */
323 {
324 int[][] dn = {
325 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
326 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } };
327 int iyy, idd, imm, ily = 0;
328
329 iyy = syd / 1000;
330 if (iyy < 1900) {
331 if (iyy > 70) {
332 iyy = iyy + 1900;
333 } else {
334 iyy = iyy + 2000;
335 }
336 }
337 idd = (syd % 1000);
338 if ((iyy % 4) == 0) {
339 ily = 1;
340 }
341 for (imm = 0; imm < 13; imm++) {
342 if (idd <= dn[ily][imm]) {
343 break;
344 }
345 }
346
347 int[] out = { idd - dn[ily][imm - 1], imm, iyy };
348 return out;
349
350 }
351
352 /**
353 * _more_
354 *
355 * @param ival
356 * _more_
357 * @param cival
358 * _more_
359 * @param idomain_v72
360 * _more_
361 *
362 * @return _more_
363 */
364 public static float aodtv72_getpwval(int ival, float cival, int idomain_v72)
365 /*
366 * Obtain pressure or wind_v72 value (for Atlantic or West Pacific storms)
367 * given the intensity estimate value. Inputs : ival - flag for wind_v72 (1)
368 * or pressure (0) output cival - Current Intensity (CI) value Outputs :
369 * return value is pressure/wind_v72 value
370 */
371 {
372 float value;
373 int ixx = 2;
374
375 /* determine correct pressure/wind_v72 array bin */
376 while ((cival > StormAODTInfo.tno_v72[ixx]) && (ixx < 82)) {
377 ixx++;
378 }
379
380 /* convert CI value to wind_v72/pressure value */
381 if (ival == 1) {
382 value = (float) StormAODTInfo.wind_v72[ixx]; /* WIND */
383 } else {
384 value = (float) StormAODTInfo.pres_v72[idomain_v72][ixx]; /* PRESSURE */
385 }
386
387 return value;
388 }
389
390 }