001    /*
002     * $Id: StormAODT.java,v 1.1 2012/01/04 20:40:50 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.data.cyclone;
032    
033    import java.util.List;
034    
035    import ucar.unidata.data.grid.GridUtil;
036    import ucar.unidata.util.IOUtil;
037    import ucar.unidata.util.StringUtil;
038    import visad.FlatField;
039    
040    /**
041     * Created by IntelliJ IDEA. User: yuanho Date: Feb 20, 2009 Time: 3:09:14 PM To
042     * change this template use File | Settings | File Templates.
043     */
044    
045    public class StormAODT {
046    
047            /** _more_ */
048            StormAODTInfo.IRData odtcurrent_v72IR;
049    
050            /** _more_ */
051            StormAODTInfo.DataGrid areadata_v72;
052    
053            /** _more_ */
054            boolean lauto = false;
055    
056            /** _more_ */
057            int idomain_v72, ixdomain_v72, ifixtype_v72, rmwsizeman_v72;
058    
059            /** _more_ */
060            int oland_v72;
061    
062            /** _more_ */
063            boolean osearch_v72;
064    
065            /** _more_ */
066            int ostartstr_v72;
067    
068            /** _more_ */
069            float osstr_v72;
070    
071            /** _more_ */
072            static double c1 = 1.191066E-5;
073    
074            /** _more_ */
075            static double c2 = 1.438833;
076    
077            public StormAODT() {
078    
079            }
080    
081            /**
082             * _more_
083             * 
084             * 
085             * @param satgrid
086             *            _more_
087             * @param cenlat
088             *            _more_
089             * @param cenlon
090             *            _more_
091             * @param posm
092             *            _more_
093             * @param curdate
094             *            _more_
095             * @param cursat
096             *            _more_
097             * @param g_domain
098             *            _more_
099             * 
100             * @return _more_
101             */
102            public StormAODTInfo.IRData aodtv72_drive(FlatField satgrid, float cenlat,
103                            float cenlon, int posm, double curdate, int cursat,
104                            String g_domain, int satId, int satChannel, boolean isTemperature) {
105    
106                    float ftmps, flats, flons, cenlon2;
107    
108                    int radius, irad, np, ii, jj, length;
109                    int idomain = 0;
110    
111                    /*
112                     * Set miscoptions flags in AODT
113                     */
114    
115                    int eyeSize = -99;
116                    oland_v72 = 0; /* allow AODT operation over land */
117                    osearch_v72 = false; /* search for maximum curved band position */
118                    rmwsizeman_v72 = eyeSize; /* eye size parameter */
119                    odtcurrent_v72IR = new StormAODTInfo.IRData();
120                    odtcurrent_v72IR.domain = idomain_v72;
121    
122                    /*
123                     * Set initial classification flag and value in AODT
124                     */
125    
126                    ostartstr_v72 = 0; /* user defined initial classification flag */
127                    osstr_v72 = 0.0f; /* starting initial classification value */
128    
129                    /*
130                     * Set image date/time info in AODT
131                     */
132    
133                    int iaodt = aodtv72_setIRimageinfo(curdate, cursat);
134    
135                    /*
136                     * Get storm center lat/lon
137                     */
138                    if (lauto == true) {
139                            // aodtv72_runautomode( nauto, fauto, imagefile, &cenlat, &cenlon,
140                            // &posm );
141                    }
142    
143                    /*
144                     * Set center location in AODT positioning method (1=interpolation,
145                     * 4=extrapolation, 0=error)
146                     */
147                    // posm = 1;
148                    aodtv72_setlocation(cenlat, cenlon, posm);
149    
150                    /*
151                     * Set domain FLAG in AODT
152                     */
153    
154                    if (g_domain.equalsIgnoreCase("AUTO")) {
155                            idomain = 0;
156                    }
157                    if (g_domain.equalsIgnoreCase("Atlantic")) {
158                            idomain = 1;
159                    }
160                    if (g_domain.equalsIgnoreCase("Pacific")) {
161                            idomain = 2;
162                    }
163                    if (g_domain.equalsIgnoreCase("Indian")) {
164                            idomain = 2;
165                    }
166    
167                    iaodt = aodtv72_setdomain(idomain);
168    
169                    /*
170                     * Retrieve temperatures from image. This to be done in IDV
171                     */
172    
173                    GridUtil.Grid2D g2d = null;
174                    float[][] temps = null;
175                    float[][][] satimage = null;
176                    float[][] lons = null;
177                    float[][] lats = null;
178                    int numx = 123;
179                    int numy = 123;
180    
181                    try {
182                            g2d = GridUtil.makeGrid2D(satgrid);
183                            lons = g2d.getlons();
184                            lats = g2d.getlats();
185    
186                    } catch (Exception re) {
187                    }
188    
189                    /* now spatial subset numx by numy */
190                    GridUtil.Grid2D g2d1 = spatialSubset(g2d, cenlat, cenlon, numx, numy);
191    
192                    satimage = g2d1.getvalues();
193                    float[][] temp0 = satimage[0];
194                    int imsorc = satId, imtype = satChannel;
195    
196                    if (isTemperature)
197                            temps = temp0;
198                    else
199                            temps = im_gvtota(numx, numy, temp0, imsorc, imtype);
200    
201                    /*
202                     * Load the IR image information in AODT init areadata_v72
203                     */
204    
205                    aodtv72_loadIRimage(temps, g2d1.getlats(), g2d1.getlons(), numx, numy);
206    
207                    /*
208                     * Set eye and cloud temperature values in AODT, return position for IR
209                     * image data read
210                     */
211    
212                    StormAODTInfo.IRData tvIR = aodtv72_seteyecloudtemp(
213                                    StormAODTInfo.keyerM_v72, areadata_v72);
214    
215                    odtcurrent_v72IR.warmt = tvIR.warmt;
216                    odtcurrent_v72IR.warmlatitude = tvIR.warmlatitude;
217                    odtcurrent_v72IR.warmlongitude = tvIR.warmlongitude;
218                    odtcurrent_v72IR.eyet = tvIR.eyet;
219                    odtcurrent_v72IR.cwcloudt = tvIR.cwcloudt;
220                    odtcurrent_v72IR.cwring = tvIR.cwring;
221    
222                    /*
223                     * Determine scene type Set scene type
224                     */
225    
226                    float[] oscen = StormAODTSceneType.aodtv72_calcscene(odtcurrent_v72IR,
227                                    areadata_v72);
228    
229                    odtcurrent_v72IR.cloudt = oscen[0];
230                    odtcurrent_v72IR.cloudt2 = oscen[1];
231                    odtcurrent_v72IR.eyestdv = oscen[2];
232                    odtcurrent_v72IR.cloudsymave = oscen[3];
233                    odtcurrent_v72IR.eyefft = (int) oscen[4];
234                    odtcurrent_v72IR.cloudfft = (int) oscen[5];
235                    // { alst, Aaveext, Estdveye, Aavesym, eyecnt, rngcnt};
236                    float[] oscen1 = StormAODTSceneType.aodtv72_classify(odtcurrent_v72IR,
237                                    rmwsizeman_v72, areadata_v72, osstr_v72, osearch_v72);
238    
239                    odtcurrent_v72IR.eyescene = (int) oscen1[0];
240                    odtcurrent_v72IR.cloudscene = (int) oscen1[1];
241                    odtcurrent_v72IR.eyesceneold = -1;
242                    odtcurrent_v72IR.cloudsceneold = -1;
243                    odtcurrent_v72IR.eyecdosize = oscen1[2];
244                    odtcurrent_v72IR.ringcb = (int) oscen1[3];
245                    odtcurrent_v72IR.ringcbval = (int) oscen1[4];
246                    odtcurrent_v72IR.ringcbvalmax = (int) oscen1[5];
247                    odtcurrent_v72IR.ringcblatmax = oscen1[6];
248                    odtcurrent_v72IR.ringcblonmax = oscen1[7];
249                    odtcurrent_v72IR.rmw = oscen1[8];
250    
251                    /*
252                     * Determine intensity
253                     */
254    
255                    iaodt = aodtv72_calcintensity(idomain);
256                    if (iaodt == 71) {
257                            throw new IllegalStateException("center location is over land");
258                    }
259    
260                    /*
261                     * Print out all diagnostic messages to screen
262                     */
263                    return odtcurrent_v72IR;
264            }
265    
266            public static class AODTResult {
267            }
268    
269            /**
270             * _more_
271             * 
272             * @param g2d
273             *            _more_
274             * @param cenlat
275             *            _more_
276             * @param cenlon
277             *            _more_
278             * @param numx
279             *            _more_
280             * @param numy
281             *            _more_
282             * 
283             * @return _more_
284             */
285    
286            GridUtil.Grid2D spatialSubset(GridUtil.Grid2D g2d, float cenlat,
287                            float cenlon, int numx, int numy) {
288                    float[][] lats = g2d.getlats();
289                    float[][] lons = g2d.getlons();
290                    float[][][] values = g2d.getvalues();
291                    float[][] slats = new float[numx][numy];
292                    float[][] slons = new float[numx][numy];
293                    float[][][] svalues = new float[1][numx][numy];
294    
295                    int ly = lats[0].length;
296                    int ly0 = ly / 2;
297                    int lx = lats.length;
298                    int lx0 = lx / 2;
299                    int ii = numx / 2, jj = numy / 2;
300    
301                    for (int j = 0; j < ly - 1; j++) {
302                            if (Float.isNaN(lats[lx0][j]))
303                                    continue;
304                            if ((lats[lx0][j] > cenlat) && (lats[lx0][j + 1] < cenlat)) {
305                                    jj = j;
306                            }
307                    }
308                    for (int i = 0; i < lx - 1; i++) {
309                            if (Float.isNaN(lons[i][ly0]))
310                                    continue;
311                            if ((lons[i][ly0] < cenlon) && (lons[i + 1][ly0] > cenlon)) {
312                                    ii = i;
313                            }
314                    }
315                    int startx = ii - (numx / 2 - 1);
316                    int starty = jj - (numy / 2 - 1);
317                    if (startx < 0)
318                            startx = 0;
319                    if (starty < 0)
320                            starty = 0;
321    
322                    for (int i = 0; i < numx; i++) {
323                            for (int j = 0; j < numy; j++) {
324                                    slats[i][j] = lats[i + startx][j + starty];
325                                    slons[i][j] = lons[i + startx][j + starty];
326                                    svalues[0][i][j] = values[0][i + startx][j + starty];
327                            }
328                    }
329    
330                    return new GridUtil.Grid2D(slats, slons, svalues);
331            }
332    
333            /**
334             * _more_
335             * 
336             * @param nx
337             *            _more_
338             * @param ny
339             *            _more_
340             * @param gv
341             *            _more_
342             * @param imsorc
343             *            _more_
344             * @param imtype
345             *            _more_
346             * 
347             * @return _more_
348             */
349            float[][] im_gvtota(int nx, int ny, float[][] gv, int imsorc, int imtype)
350    
351            /**
352             * im_gvtota
353             * 
354             * This subroutine converts GVAR counts to actual temperatures based on the
355             * current image set in IM_SIMG.
356             * 
357             * im_gvtota ( int *nvals, unsigned int *gv, float *ta, int *iret )
358             * 
359             * Input parameters: *nvals int Number of values to convert *gv int Array of
360             * GVAR count values
361             * 
362             * Output parameters: *ta float Array of actual temperatures *iret int
363             * Return value = -1 - could not open table = -2 - could not find match
364             * 
365             * 
366             * Log: D.W.Plummer/NCEP 02/03 D.W.Plummer/NCEP 06/03 Add coeff G for 2nd
367             * order poly conv T. Piper/SAIC 07/06 Added tmpdbl to eliminate warning
368             */
369            {
370                    int ii, ip, chan, found, ier;
371                    double Rad, Teff, tmpdbl;
372                    float[][] ta = new float[nx][ny];
373                    int iret;
374                    String fp = "/ucar/unidata/data/storm/ImgCoeffs.tbl";
375    
376                    iret = 0;
377    
378                    for (ii = 0; ii < nx; ii++) {
379                            for (int jj = 0; jj < ny; jj++) {
380                                    ta[ii][jj] = Float.NaN;
381                            }
382                    }
383    
384                    /*
385                     * Read in coefficient table if necessary.
386                     */
387                    String s = null;
388                    try {
389                            s = IOUtil.readContents(fp);
390                    } catch (Exception re) {
391                    }
392    
393                    int i = 0;
394                    StormAODTInfo.ImgCoeffs[] ImageConvInfo = new StormAODTInfo.ImgCoeffs[50];
395                    for (String line : StringUtil.split(s, "\n", true, true)) {
396                            if (line.startsWith("!")) {
397                                    continue;
398                            }
399                            List<String> stoks = StringUtil.split(line, " ", true, true);
400    
401                            ImageConvInfo[i] = new StormAODTInfo.ImgCoeffs(stoks);
402                            ;
403                            i++;
404                    }
405                    int nImgRecs = i;
406                    found = 0;
407                    ii = 0;
408                    while ((ii < nImgRecs) && (found == 0)) {
409    
410                            tmpdbl = (double) (ImageConvInfo[ii].chan - 1)
411                                            * (ImageConvInfo[ii].chan - 1);
412                            chan = G_NINT(tmpdbl);
413    
414                            if ((imsorc == ImageConvInfo[ii].sat_num) && (imtype == chan)) {
415                                    found = 1;
416                            } else {
417                                    ii++;
418                            }
419    
420                    }
421    
422                    if (found == 0) {
423                            iret = -2;
424                            return null;
425                    } else {
426    
427                            ip = ii;
428                            for (ii = 0; ii < nx; ii++) {
429                                    for (int jj = 0; jj < ny; jj++) {
430    
431                                            /*
432                                             * Convert GVAR count (gv) to Scene Radiance
433                                             */
434                                            Rad = ((double) gv[ii][jj] - ImageConvInfo[ip].scal_b) /
435                                            /* ------------------------------------- */
436                                            ImageConvInfo[ip].scal_m;
437    
438                                            Rad = Math.max(Rad, 0.0);
439    
440                                            /*
441                                             * Convert Scene Radiance to Effective Temperature
442                                             */
443                                            Teff = (c2 * ImageConvInfo[ip].conv_n)
444                                                            /
445                                                            /*
446                                                             * --------------------------------------------------
447                                                             * -----
448                                                             */
449                                                            (Math.log(1.0
450                                                                            + (c1 * Math.pow(ImageConvInfo[ip].conv_n,
451                                                                                            3.0)) / Rad));
452    
453                                            /*
454                                             * Convert Effective Temperature to Temperature
455                                             */
456                                            ta[ii][jj] = (float) (ImageConvInfo[ip].conv_a
457                                                            + ImageConvInfo[ip].conv_b * Teff + ImageConvInfo[ip].conv_g
458                                                            * Teff * Teff);
459                                    }
460    
461                            }
462    
463                    }
464    
465                    return ta;
466    
467            }
468    
469            /**
470             * _more_
471             * 
472             * @param x
473             *            _more_
474             * 
475             * @return _more_
476             */
477            public int G_NINT(double x) {
478                    return (((x) < 0.0F) ? ((((x) - (float) ((int) (x))) <= -.5f) ? (int) ((x) - .5f)
479                                    : (int) (x))
480                                    : ((((x) - (float) ((int) (x))) >= .5f) ? (int) ((x) + .5f)
481                                                    : (int) (x)));
482            }
483    
484            /**
485             * _more_
486             * 
487             * @param keyerM_v72
488             *            _more_
489             * @param areadata
490             *            _more_
491             * 
492             * @return _more_
493             */
494            StormAODTInfo.IRData aodtv72_seteyecloudtemp(int keyerM_v72,
495                            StormAODTInfo.DataGrid areadata)
496            /*
497             * Routine to search for, identify, and set the eye and cloud temperature
498             * values for the AODT library. Temperatures are set within AODT library.
499             * Inputs : none Outputs: none Return : -51 : eye, CWcloud, or warmest
500             * temperature <-100C or >+40C 0 : o.k.
501             */
502            {
503                    StormAODTInfo.IRData ird = StormAODTSceneType.aodtv72_gettemps(
504                                    keyerM_v72, areadata);
505                    if (ird == null) {
506                            throw new IllegalStateException(
507                                            "eye, CWcloud, or warmest temperature <-100C or >+40C");
508                    }
509    
510                    return ird;
511    
512                    // return iok;
513            }
514    
515            /**
516             * _more_
517             * 
518             * @param temps
519             *            _more_
520             * @param lats
521             *            _more_
522             * @param lons
523             *            _more_
524             * @param numx
525             *            _more_
526             * @param numy
527             *            _more_
528             * 
529             * @return _more_
530             */
531            public int aodtv72_loadIRimage(float[][] temps, float[][] lats,
532                            float[][] lons, int numx, int numy)
533            /*
534             * Subroutine to load IR image data grid values (temperatures and positions)
535             * into data structure for AODT library Inputs : temperature, latitude, and
536             * longitude arrays centered on storm position location along with number of
537             * columns (x) and rows (y) in grid Outputs: none (areadata_v72 structure
538             * passed via global variable) Return : 0 : o.k.
539             */
540            {
541                    StormAODTInfo sinfo = new StormAODTInfo();
542                    /* allocate space for data */
543                    areadata_v72 = new StormAODTInfo.DataGrid(temps, lats, lons, numx, numy);
544                    return 0;
545            }
546    
547            /**
548             * _more_
549             * 
550             * @param indomain
551             *            _more_
552             * 
553             * @return _more_
554             */
555            int aodtv72_setdomain(int indomain)
556            /*
557             * set current ocean domain variable within AODT library memory Inputs :
558             * domain flag value from input Outputs: none Return : -81 : error
559             * determining storm basin
560             */
561            {
562                    int domain;
563                    float xlon;
564    
565                    /* obtain current storm center longitude */
566                    xlon = odtcurrent_v72IR.longitude;
567                    if ((xlon < -180.0) || (xlon > 180.0)) {
568                            return -81;
569                    }
570    
571                    ixdomain_v72 = indomain;
572                    /* determine oceanic domain */
573                    if (indomain == 0) {
574                            /* automatically determined storm basin */
575                            if (xlon >= 0.0) {
576                                    domain = 0; /* atlantic and east pacific to 180W/dateline */
577                            } else {
578                                    domain = 1; /* west pacific and other regions */
579                            }
580                    } else {
581                            /* manually determined storm basin */
582                            domain = indomain - 1;
583                    }
584    
585                    /* assign ocean domain flag value to AODT library variable */
586                    idomain_v72 = domain;
587    
588                    return 0;
589            }
590    
591            /**
592             * _more_
593             * 
594             * @param ilat
595             *            _more_
596             * @param ilon
597             *            _more_
598             * @param ipos
599             *            _more_
600             * 
601             * @return _more_
602             */
603            int aodtv72_setlocation(float ilat, float ilon, int ipos)
604            /*
605             * set current storm center location within from AODT library memory Inputs
606             * : AODT library current storm center latitude and longitude values and
607             * location positioning method : 1-forecast interpolation 2-laplacian
608             * technique 3-warm spot 4-extrapolation Outputs: none Return : -21 :
609             * invalid storm center position 21 : user selected storm center position 22
610             * : auto selected storm center position
611             */
612            {
613                    int iret;
614    
615                    /* assign current storm center latitude value to AODT library variable */
616                    odtcurrent_v72IR.latitude = ilat;
617                    /* assign current storm center longitude value to AODT library variable */
618                    odtcurrent_v72IR.longitude = ilon;
619                    /* assign current storm center positioning flag to AODT library variable */
620                    odtcurrent_v72IR.autopos = ipos;
621                    if ((odtcurrent_v72IR.longitude < -180.)
622                                    || (odtcurrent_v72IR.longitude > 180.)) {
623                            iret = -21;
624                    }
625                    if ((odtcurrent_v72IR.latitude < -90.)
626                                    || (odtcurrent_v72IR.latitude > 90.)) {
627                            iret = -21;
628                    }
629    
630                    iret = 21; /* user selected image location */
631                    if (ipos >= 1) {
632                            iret = 22;
633                    }
634    
635                    return iret;
636            }
637    
638            /**
639             * _more_
640             * 
641             * @param datetime
642             *            _more_
643             * @param sat
644             *            _more_
645             * 
646             * @return _more_
647             */
648            int aodtv72_setIRimageinfo(double datetime, int sat)
649            /*
650             * set IR image date/time within AODT library memory Inputs : AODT library
651             * IR image date/time/satellite information Outputs: none Return : 0 : o.k.
652             */
653            {
654                    /* assign IR image date to AODT library variable */
655                    odtcurrent_v72IR.date = datetime;
656    
657                    /* assign IR image satellite type to AODT library variable */
658                    odtcurrent_v72IR.sattype = sat;
659    
660                    return 0;
661            }
662    
663            /**
664             * _more_
665             * 
666             * @param idomain
667             *            _more_
668             * 
669             * @return _more_
670             */
671            public int aodtv72_calcintensity(int idomain)
672            /*
673             * Compute intensity values CI, Final T#, and Raw T#. Inputs : global
674             * structure odtcurrent_v72 containing current analysis Outputs : none
675             * Return : 71 : storm is over land 0 : o.k.
676             */
677            {
678                    int iok;
679                    int iret;
680                    int strength;
681    
682                    if ((odtcurrent_v72IR.land == 1)) {
683                            iok = aodtv72_initcurrent(true, odtcurrent_v72IR);
684                            iret = 71;
685                    } else {
686                            /* calculate current Raw T# value */
687                            odtcurrent_v72IR.Traw = aodtv72_Tnoraw(odtcurrent_v72IR, idomain);
688                            odtcurrent_v72IR.TrawO = odtcurrent_v72IR.Traw;
689                            /* check for spot analysis or full analysis using history file */
690                            /* if(hfile_v72==(char *)NULL) { */
691                            if (true) {
692                                    /* perform spot analysis (only Traw) */
693                                    odtcurrent_v72IR.Tfinal = odtcurrent_v72IR.Traw;
694                                    odtcurrent_v72IR.Tfinal3 = odtcurrent_v72IR.Traw;
695                                    odtcurrent_v72IR.CI = odtcurrent_v72IR.Traw;
696                                    odtcurrent_v72IR.CIadjp = aodtv72_latbias(odtcurrent_v72IR.CI,
697                                                    odtcurrent_v72IR.latitude, odtcurrent_v72IR.longitude,
698                                                    odtcurrent_v72IR);
699                                    /*
700                                     * printf("%f %f %f   %f\n",odtcurrent_v72IR.CI,odtcurrent_v72IR.
701                                     * latitude
702                                     * ,odtcurrent_v72->IR.longitude,odtcurrent_v72->IR.CIadjp);
703                                     */
704                                    odtcurrent_v72IR.rule9 = 0;
705                                    /* odtcurrent_v72->IR.TIEraw=aodtv72_TIEmodel(); */
706                                    /* odtcurrent_v72->IR.TIEavg=odtcurrent_v72->IR.TIEraw; */
707                                    /* odtcurrent_v72->IR.TIEflag=aodtv72_tieflag(); */
708                            } else {
709                            }
710    
711                            iret = 0;
712                    }
713    
714                    return iret;
715            }
716    
717            /**
718             * _more_
719             * 
720             * @param initval
721             *            _more_
722             * @param latitude
723             *            _more_
724             * @param longitude
725             *            _more_
726             * @param odtcurrent_v72IR
727             *            _more_
728             * 
729             * @return _more_
730             */
731            float aodtv72_latbias(float initval, float latitude, float longitude,
732                            StormAODTInfo.IRData odtcurrent_v72IR)
733            /*
734             * Apply Latitude Bias Adjustment to CI value Inputs : initval - initial CI
735             * value latitude - current latitude of storm Outputs : adjusted MSLP value
736             * as return value
737             */
738            {
739                    float initvalp;
740    
741                    float initvalpx;
742                    float value; /* lat bias adjustement amount (0.00-1.00) */
743                    int sceneflag; /*
744                                                     * contains lat bias adjustment flag 0=no adjustment
745                                                     * 1=intermediate adjustment (6 hours) 2=full adjustment
746                                                     */
747    
748                    sceneflag = aodtv72_scenesearch(0); /*
749                                                                                             * 0 means search for EIR based
750                                                                                             * parameters... cdo, etc
751                                                                                             */
752                    value = 1.0f; /* this value should be return from scenesearch() */
753                    /* printf("sceneflag=%d  value=%f\n",sceneflag,value); */
754                    odtcurrent_v72IR.LBflag = sceneflag;
755                    /* initvalp=aodtv72_getpwval(0,initval); TLO */
756                    initvalp = 0.0f;
757                    if (sceneflag >= 2) {
758                            /* EIR scene */
759                            if ((latitude >= 0.0)
760                                            && ((longitude >= -100.0) && (longitude <= -40.0))) {
761                                    /* do not make adjustment in N Indian Ocean */
762                                    return initvalp;
763                            }
764                            /* apply bias adjustment to pressure */
765                            /* initvalp=-1.0*value*(-20.60822+(0.88463*A_ABS(latitude))); */
766                            initvalp = value * (7.325f - (0.302f * Math.abs(latitude)));
767                    }
768    
769                    return initvalp;
770            }
771    
772            /**
773             * _more_
774             * 
775             * @param type
776             *            _more_
777             * 
778             * @return _more_
779             */
780            int aodtv72_scenesearch(int type) {
781                    int curflag = 1, flag, eirflag;
782                    float eirvalue, civalue, ciadjvalue, latitude;
783                    double curtime, xtime, curtimem6, mergetimefirst, mergetimelast, firsttime = -9999.0;
784    
785                    float pvalue;
786    
787                    /*
788                     * if(((odthistoryfirst_v72==0)&&(ostartstr_v72==TRUE))&&(hfile_v72!=(char
789                     * *)NULL)) {
790                     */
791    
792                    if (true) {
793                            flag = 2;
794                            pvalue = 1.0f;
795                            return flag;
796                    }
797    
798                    return flag;
799            }
800    
801            /**
802             * _more_
803             * 
804             * @param redo
805             *            _more_
806             * @param odtcurrent_v72IR
807             *            _more_
808             * 
809             * @return _more_
810             */
811            int aodtv72_initcurrent(boolean redo, StormAODTInfo.IRData odtcurrent_v72IR)
812            /*
813             * initialize odtcurrent_v72 array or reset values for land interaction
814             * situations
815             */
816            {
817                    int b, bb;
818                    // char comm[50]="\0";
819    
820                    if (!redo) {
821                            // odtcurrent_v72=(struct odtdata *)malloc(sizeof(struct odtdata));
822                            odtcurrent_v72IR.latitude = 999.99f;
823                            odtcurrent_v72IR.longitude = 999.99f;
824                            odtcurrent_v72IR.land = 0;
825                            odtcurrent_v72IR.autopos = 0;
826                            // strcpy(odtcurrent_v72IR.comment,comm);
827                            // diagnostics_v72=(char *)calloc((size_t)50000,sizeof(char));
828                            // hfile_v72=(char *)calloc((size_t)200,sizeof(char));
829                            // fixfile_v72=(char *)calloc((size_t)200,sizeof(char));
830    
831                            // b=sizeof(float);
832                            // bb=sizeof(double);
833                            // fcstlat_v72=(float *)calloc((size_t)5,b);
834                            // fcstlon_v72=(float *)calloc((size_t)5,b);
835                            // fcsttime_v72=(double *)calloc((size_t)5,bb);
836                    }
837    
838                    odtcurrent_v72IR.Traw = 0.0f;
839                    odtcurrent_v72IR.TrawO = 0.0f;
840                    odtcurrent_v72IR.Tfinal = 0.0f;
841                    odtcurrent_v72IR.Tfinal3 = 0.0f;
842                    odtcurrent_v72IR.CI = 0.0f;
843                    odtcurrent_v72IR.eyet = 99.99f;
844                    odtcurrent_v72IR.warmt = 99.99f;
845                    odtcurrent_v72IR.cloudt = 99.99f;
846                    odtcurrent_v72IR.cloudt2 = 99.99f;
847                    odtcurrent_v72IR.cwcloudt = 99.99f;
848                    odtcurrent_v72IR.warmlatitude = 999.99f;
849                    odtcurrent_v72IR.warmlongitude = 999.99f;
850                    odtcurrent_v72IR.eyecdosize = 0.0f;
851                    odtcurrent_v72IR.eyestdv = 0.0f;
852                    odtcurrent_v72IR.cloudsymave = 0.0f;
853                    odtcurrent_v72IR.eyescene = 0;
854                    odtcurrent_v72IR.cloudscene = 0;
855                    odtcurrent_v72IR.eyesceneold = -1;
856                    odtcurrent_v72IR.cloudsceneold = -1;
857                    odtcurrent_v72IR.rule9 = 0;
858                    odtcurrent_v72IR.rule8 = 0;
859                    odtcurrent_v72IR.LBflag = 0;
860                    odtcurrent_v72IR.rapiddiss = 0;
861                    odtcurrent_v72IR.eyefft = 0;
862                    odtcurrent_v72IR.cloudfft = 0;
863                    odtcurrent_v72IR.cwring = 0;
864                    odtcurrent_v72IR.ringcb = 0;
865                    odtcurrent_v72IR.ringcbval = 0;
866                    odtcurrent_v72IR.ringcbvalmax = 0;
867                    odtcurrent_v72IR.CIadjp = 0.0f;
868                    odtcurrent_v72IR.rmw = -99.9f;
869                    /* odtcurrent_v72->IR.TIEflag=0; */
870                    /* odtcurrent_v72->IR.TIEraw=0.0; */
871                    /* odtcurrent_v72->IR.TIEavg=0.0; */
872                    /* odtcurrent_v72->IR.sst=-99.9; */
873                    // if(!redo) odtcurrent_v72->nextrec=NULL; /* added by CDB */
874    
875                    return 0;
876            }
877    
878            /**
879             * Compute initial Raw T-Number value using original Dvorak rules
880             * 
881             * @param odtcurrent
882             * @param idomain_v72
883             * @return return value is Raw T#
884             */
885    
886            float aodtv72_Tnoraw(StormAODTInfo.IRData odtcurrent, int idomain_v72)
887            /*
888             * Compute initial Raw T-Number value using original Dvorak rules Inputs :
889             * global structure odtcurrent_v72 containing current analysis Outputs :
890             * return value is Raw T#
891             * 
892             * ODT SCENE/TEMPERATURE TABLE BD | WMG OW DG MG LG B W CMG CDG | TEMP |30.0
893             * 0.0 -30.0 -42.0 -54.0 -64.0 -70.0 -76.0 -80.0+|
894             * ---------------------------------------------------------------| Atl EYE
895             * | 3.5 4.0 4.5 4.5 5.0 5.5 6.0 6.5 7.0 | EMBC | 3.5 3.5 4.0 4.0 4.5 4.5
896             * 5.0 5.0 5.0 | CDO | 3.0 3.0 3.5 4.0 4.5 4.5 4.5 5.0 5.0 |
897             * ---------------------------------------------------------------| Pac EYE
898             * | 4.0 4.0 4.0 4.5 4.5 5.0 5.5 6.0 6.5 | EMBC | 3.5 3.5 4.0 4.0 4.5 4.5
899             * 5.0 5.0 5.0 | CDO | 3.0 3.5 3.5 4.0 4.5 4.5 4.5 4.5 5.0 |
900             * ---------------------------------------------------------------| Cat diff
901             * | 0 1 2 3 4 5 6 7 8 | add | 0.0 0.0 0.0 0.0 0.0-->0.5 0.5-->1.0 1.5 |
902             * (old) add |-0.5 -0.5 0.0 0.0-->0.5 0.5 0.5-->1.0 1.0 | (new)
903             * ---------------------------------------------------------------|
904             */
905            {
906    
907                    double[][] eno = {
908                                    { 1.00, 2.00, 3.25, 4.00, 4.75, 5.50, 5.90, 6.50, 7.00, 7.50,
909                                                    8.00 }, /* original plus adjusted > CDG+ */
910                                    { 1.50, 2.25, 3.30, 3.85, 4.50, 5.00, 5.40, 5.75, 6.25, 6.50,
911                                                    7.00 } }; /* adjusted based */
912                    double[][] cdo = {
913                                    { 2.00, 2.40, 3.25, 3.50, 3.75, 4.00, 4.10, 4.20, 4.30, 4.40,
914                                                    4.70 },
915                                    { 2.05, 2.40, 3.00, 3.20, 3.40, 3.55, 3.65, 3.75, 3.80, 3.90,
916                                                    4.10 } };
917                    double[] curbnd = { 1.0, 1.5, 2.5, 3.0, 3.5, 4.0, 4.5 };
918                    double[] shrdst = { 0.0, 35.0, 50.0, 80.0, 110.0, 140.0 };
919                    double[] shrcat = { 3.5, 3.0, 2.5, 2.25, 2.0, 1.5 };
920    
921                    double[][] diffchk = {
922                                    { 0.0, 0.5, 1.2, 1.7, 2.2, 2.7, 0.0, 0.0, 0.1, 0.5 }, /*
923                                                                                                                                             * shear
924                                                                                                                                             * scene
925                                                                                                                                             * types...
926                                                                                                                                             * original
927                                                                                                                                             * Rule 8
928                                                                                                                                             * rules
929                                                                                                                                             */
930                                    { 0.0, 0.5, 1.7, 2.2, 2.7, 3.2, 0.0, 0.0, 0.1, 0.5 }, /*
931                                                                                                                                             * eye scene
932                                                                                                                                             * types...
933                                                                                                                                             * add 0.5
934                                                                                                                                             * to Rule 8
935                                                                                                                                             * rules
936                                                                                                                                             */
937                                    { 0.0, 0.5, 0.7, 1.2, 1.7, 2.2, 0.0, 0.0, 0.1, 0.5 } }; /*
938                                                                                                                                                     * other
939                                                                                                                                                     * scene
940                                                                                                                                                     * types
941                                                                                                                                                     * ...
942                                                                                                                                                     * subtract
943                                                                                                                                                     * 0.5
944                                                                                                                                                     * from
945                                                                                                                                                     * Rule
946                                                                                                                                                     * 8
947                                                                                                                                                     * rules
948                                                                                                                                                     */
949                    double eyeadjfacEYE[] = { 0.011, 0.015 }; /*
950                                                                                                     * modified wpac value to be
951                                                                                                     * closer to atlantic
952                                                                                                     */
953                    double symadjfacEYE[] = { -0.015, -0.015 };
954                    double dgraysizefacCLD[] = { 0.002, 0.001 };
955                    double symadjfacCLD[] = { -0.030, -0.015 };
956    
957                    int diffchkcat;
958                    int ixx, cloudcat, eyecat, diffcat, rp, xrp, rb;
959                    float incval, lastci, lasttno, lastr9, lastraw;
960                    float xpart, xparteye, xaddtno, eyeadj, spart, ddvor, dvorchart, ciadj;
961                    float sdist, cloudtemp, eyetemp, fftcloud;
962                    float t1val, t6val, t12val, t18val, t24val, delt1, delt6, delt12, delt18, delt24;
963                    float t1valraw, t1valrawx, txvalmin, txvalmax;
964                    double curtime, xtime, firsttime, firstlandtime;
965                    double ttime1, ttime6, ttime12, ttime18, ttime24, t1valrawxtime;
966                    StormAODTInfo.IRData odthistory, prevrec;
967                    boolean oceancheck, adjustshear, firstland;
968                    boolean t1found = false, t6found = false, t12found = false, t18found = false, t24found = false;
969                    boolean first6hrs = false;
970                    float symadj, dgraysizeadj, deltaT;
971    
972                    cloudtemp = odtcurrent.cloudt;
973                    eyetemp = odtcurrent.eyet;
974                    cloudcat = 0;
975                    eyecat = 0;
976                    lastci = 4.0f;
977                    xpart = 0.0f;
978    
979                    for (ixx = 0; ixx < 10; ixx++) {
980                            /* compute cloud category */
981                            if ((cloudtemp <= StormAODTInfo.ebd_v72[ixx])
982                                            && (cloudtemp > StormAODTInfo.ebd_v72[ixx + 1])) {
983                                    cloudcat = ixx;
984                                    xpart = (float) (cloudtemp - StormAODTInfo.ebd_v72[cloudcat])
985                                                    / (float) (StormAODTInfo.ebd_v72[cloudcat + 1] - StormAODTInfo.ebd_v72[cloudcat]);
986                            }
987                            /* compute eye category for eye adjustment */
988                            if ((eyetemp <= StormAODTInfo.ebd_v72[ixx])
989                                            && (eyetemp > StormAODTInfo.ebd_v72[ixx + 1])) {
990                                    eyecat = ixx;
991                            }
992                            /* eyetemp=Math.min(0.0,eyetemp); */
993                    }
994                    if (odtcurrent.eyescene == 1) {
995                            /* for pinhole eye, determine what storm should be seeing */
996                            /*
997                             * eyetemp=pinhole(odtcurrent_v72->IR.latitude,odtcurrent_v72->IR.longitude
998                             * ,eyetemp);
999                             */
1000                            /*
1001                             * eyetemp=(9.0-eyetemp)/2.0; / this matches DT used at NHC (jack
1002                             * beven)
1003                             */
1004                            eyetemp = (float) (eyetemp - 9.0) / 2.0f; /*
1005                                                                                                             * between +9C (beven) and
1006                                                                                                             * measured eye temp (turk)
1007                                                                                                             */
1008                            odtcurrent.eyet = eyetemp;
1009                    }
1010    
1011                    /* category difference between eye and cloud region */
1012                    diffcat = Math.max(0, cloudcat - eyecat);
1013    
1014                    /* if scenetype is EYE */
1015                    rp = odtcurrent.ringcbval;
1016                    rb = odtcurrent.ringcb;
1017                    fftcloud = odtcurrent.cloudfft;
1018    
1019                    if (odtcurrent.cloudscene == 3) {
1020                            /* CURVED BAND */
1021                            rp = Math.min(30, rp + 1); /* added 1 for testing */
1022                            xrp = rp / 5;
1023                            incval = 0.1f;
1024                            if (xrp == 1) {
1025                                    incval = 0.2f;
1026                            }
1027                            ddvor = (float) curbnd[xrp];
1028                            xaddtno = incval * (float) (rp - (xrp * 5));
1029                            /*
1030                             * printf("rp=%d  xrp=%d  rb=%d  ddvor=%f  xaddtno=%f\n",rp,xrp,rb,ddvor
1031                             * ,xaddtno);
1032                             */
1033                            ddvor = ddvor + xaddtno;
1034                            if (rb == 5) {
1035                                    ddvor = Math.min(4.0f, ddvor + 0.5f);
1036                            }
1037                            if (rb == 6) {
1038                                    ddvor = Math.min(4.5f, ddvor + 1.0f);
1039                            }
1040                            diffchkcat = 2; /* added for test - non-eye/shear cases */
1041                    } else if (odtcurrent.cloudscene == 4) {
1042                            /* POSSIBLE SHEAR -- new definition from NHC */
1043                            ixx = 0;
1044                            ddvor = 1.0f;
1045                            sdist = odtcurrent.eyecdosize; /* shear distance */
1046                            while (ixx < 5) {
1047                                    if ((sdist >= shrdst[ixx]) && (sdist < shrdst[ixx + 1])) {
1048                                            spart = (float) ((sdist - shrdst[ixx]) / (shrdst[ixx + 1] - shrdst[ixx]));
1049                                            xaddtno = (float) ((spart * (shrcat[ixx + 1] - shrcat[ixx])));
1050                                            ddvor = (float) (shrcat[ixx] + xaddtno);
1051                                            ixx = 5;
1052                                    } else {
1053                                            ixx++;
1054                                    }
1055                            }
1056                            diffchkcat = 0; /* added for test - shear cases */
1057                    } else {
1058                            /* EYE or NO EYE */
1059                            if (odtcurrent.eyescene <= 2) {
1060                                    /* EYE */
1061                                    xaddtno = (float) (xpart * (eno[idomain_v72][cloudcat + 1] - eno[idomain_v72][cloudcat]));
1062                                    /*
1063                                     * cloud category must be white (-70C) or below for full
1064                                     * adjustment; value will be merged in starting at black (-64C)
1065                                     * / if(cloudcat<5) { / gray shades / xparteye=0.00; } else
1066                                     * if(cloudcat==5) { / black / xparteye=xpart; } else { / white
1067                                     * and colder / xparteye=1.00; }
1068                                     */
1069                                    eyeadj = (float) eyeadjfacEYE[idomain_v72]
1070                                                    * (eyetemp - cloudtemp);
1071                                    /* symadj=-0.02*(odtcurrent_v72->IR.cloudsymave); */
1072                                    symadj = (float) symadjfacEYE[idomain_v72]
1073                                                    * (odtcurrent.cloudsymave);
1074                                    /*
1075                                     * printf("EYE : cloudsymave=%f  symadj=%f\n",odtcurrent_v72->IR.
1076                                     * cloudsymave,symadj);
1077                                     */
1078                                    ddvor = (float) eno[idomain_v72][cloudcat] + xaddtno + eyeadj
1079                                                    + symadj;
1080                                    /*
1081                                     * printf("EYE : xaddtno=%f  eyeadj=%f  symadj=%f   ddvor=%f\n",xaddtno
1082                                     * ,eyeadj,symadj,ddvor);
1083                                     */
1084                                    ddvor = Math.min(ddvor, 9.0f);
1085                                    /* printf("ddvor=%f\n",ddvor); */
1086                                    if (odtcurrent.eyescene == 2) {
1087                                            ddvor = Math.min(ddvor - 0.5f, 6.5f); /* LARGE EYE adjustment */
1088                                    }
1089                                    /*
1090                                     * if(odtcurrent_v72->IR.eyescene==3)
1091                                     * ddvor=Math.min(ddvor-0.5,6.0); / LARGE RAGGED EYE adjustment
1092                                     */
1093                                    diffchkcat = 1; /* added for test - eye cases */
1094                                    /* printf("ddvor=%f\n",ddvor); */
1095                            } else {
1096                                    /* NO EYE */
1097                                    /* CDO */
1098                                    xaddtno = (float) (xpart * (cdo[idomain_v72][cloudcat + 1] - cdo[idomain_v72][cloudcat]));
1099                                    /* dgraysizeadj=0.002*odtcurrent_v72->IR.eyecdosize; */
1100                                    dgraysizeadj = (float) dgraysizefacCLD[idomain_v72]
1101                                                    * odtcurrent.eyecdosize;
1102                                    /*
1103                                     * printf("CDO : dgraysize=%f  symadj=%f\n",odtcurrent_v72->IR.eyecdosize
1104                                     * ,dgraysizeadj);
1105                                     */
1106                                    /* symadj=-0.03*(odtcurrent_v72->IR.cloudsymave); */
1107                                    symadj = (float) symadjfacCLD[idomain_v72]
1108                                                    * (odtcurrent.cloudsymave);
1109                                    /*
1110                                     * printf("CDO : cloudsymave=%f  symadj=%f\n",odtcurrent_v72->IR.
1111                                     * cloudsymave,symadj);
1112                                     */
1113                                    ddvor = (float) cdo[idomain_v72][cloudcat] + xaddtno
1114                                                    + dgraysizeadj + symadj;
1115                                    ddvor = ddvor - 0.1f; /* bias adjustment */
1116                                    /*
1117                                     * printf("CDO : xaddtno=%f dgraysizeadj=%f  symadj=%f   ddvor=%f\n"
1118                                     * ,xaddtno,dgraysizeadj,symadj,ddvor);
1119                                     */
1120                                    ciadj = 0.0f;
1121                                    if (odtcurrent.cloudscene == 0) { /* CDO */
1122                                            if (lastci >= 4.5) {
1123                                                    ciadj = Math.max(0.0f, Math.min(1.0f, lastci - 4.5f));
1124                                            }
1125                                            if (lastci <= 3.0) {
1126                                                    ciadj = Math.min(0.0f, Math.max(-1.0f, lastci - 3.0f));
1127                                            }
1128                                            /* printf("CDO : lastci=%f   xaddtno=%f\n",lastci,ciadj); */
1129                                            ddvor = ddvor + ciadj;
1130                                    }
1131                                    if (odtcurrent.cloudscene == 1) { /* EMBEDDED CENTER */
1132                                            ciadj = Math.max(0.0f, Math.min(1.5f, lastci - 4.0f));
1133                                            /* printf("EMBC : lastci=%f   xaddtno=%f\n",lastci,ciadj); */
1134                                            ddvor = ddvor + ciadj; /* changed from 0.5 */
1135                                    }
1136                                    if (odtcurrent.cloudscene == 2) { /* IRREGULAR CDO (PT=3.5) */
1137                                            ddvor = ddvor + 0.3f; /* additional IrrCDO bias adjustment */
1138                                            ddvor = Math.min(3.5f, Math.max(2.5f, ddvor));
1139                                    }
1140                                    diffchkcat = 2; /* added for test - non-eye/shear cases */
1141                            }
1142                    }
1143    
1144                    dvorchart = ((float) (int) (ddvor * 10.0f)) / 10.0f;
1145                    // odtcurrent_v72IR.TrawO=dvorchart;
1146    
1147                    return dvorchart;
1148    
1149            }
1150    
1151    }