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