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    }