001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2016
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
029package edu.wisc.ssec.mcidasv.control.cyclone;
030
031import java.util.ArrayList;
032import 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 */
038public 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}