//Program to convert FRAM data to standard IMMA1 format //Author: Eric Freeman //Affiliation: STG, Inc./NOAA/NCDC import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; public class fram_imma1 { private static String IpPath = ""; private static String OpPath = ""; /*** File ***/ public static File InputFile, OutputFile; public static BufferedReader ipbr; public static BufferedWriter opbw; private static boolean bdebug=true; static boolean Eflag; /*******************************************************************************************************************/ public static void main(String[] args) { try { //Process process(args); } catch (Exception e) { e.printStackTrace(); } } public static void process(String[] args) throws IOException, ParseException { if(args.length == 2) { IpPath = args[0]; OpPath = args[1]; } else if(bdebug) { System.out.println("*** Warning *** \nProgram Is Running In Debug Mode"); IpPath = "sea_Sep_1_to_Sep_19_1898.csv"; OpPath = "sea_Sep_1_to_Sep_19_1898_imma1_v8"; } else { System.out.println("*** ARGUMENT ERROR *** Num of Arguments = " + args.length + "\nRequired Arguments: InPut Path, OutPut Path, and Log Path"); System.exit(1); } // Open IP File openFiles(); String str = ""; while ((str = ipbr.readLine()) != null) { try { String [] cols = str.split(","); String yr = (cols.length <= 0) ? "" : cols[0]; String mo = (cols.length <= 1) ? "" : cols[1]; String day = (cols.length <= 2) ? "" : cols[2]; String hr = (cols.length <= 3) ? "" : cols[3]; String lat = (cols.length <= 4) ? "" : cols[4]; String lon = (cols.length <= 5) ? "" : cols[5]; String wd = (cols.length <= 6) ? "" : cols[6]; String ws = (cols.length <= 7) ? "" : cols[7]; String slp = (cols.length <= 8) ? "" : cols[8]; String at = (cols.length <= 9) ? "" : cols[9]; String vapor = (cols.length <= 10) ? "" : cols[10]; String rh = (cols.length <= 11) ? "" : cols[11]; String c_amt = (cols.length <= 12) ? "" : cols[12]; String c_type = (cols.length <= 13) ? "" : cols[13]; String c_dir = (cols.length <= 14) ? "" : cols[14]; String wx = (cols.length <= 15) ? "" : cols[15]; String sea_dir = (cols.length <= 16) ? "" : cols[16]; String sea_state = (cols.length <= 17) ? "" : cols[17]; String sst = (cols.length <= 18) ? "" : cols[18]; //Table C0 - Core String b4 = yr.trim(); // year 1-4 try { Integer I = new Integer(b4); int i = I.intValue(); if (i<1898 | i>1902) Eflag=true; // } catch (NumberFormatException e) { Eflag = true; } String b5 = mo.trim(); // month 5-6 if (b5.trim().length() == 1){ b5 = " " + b5; } try { Integer I = new Integer(b5.trim()); int i = I.intValue(); if (i<1 | i>12) Eflag=true; } catch (NumberFormatException e) { Eflag = true; } String b6 = day.trim(); // day 7-8 if (b6.trim().length() == 1){ b6 = " " + b6; } try { Integer I = new Integer(b6.trim()); int i = I.intValue(); if (i<1 | i>31) Eflag=true; } catch (NumberFormatException e) { Eflag = true; } String b7 = hr.trim(); // hr 9-10; plus checks on hour 24 and changing dates try { Integer I = new Integer(b7.trim()); int i = I.intValue(); if (i<0 | i>24) Eflag=true; } catch (NumberFormatException e) { Eflag = true; } if (b7.trim().length() == 0) {b7 = " ";} //Hour not reported else if (b7.trim().length() == 3) { // 1-digit hour + minutes String hour = " " + b7.trim().substring(0,1); String minutes = b7.trim().substring(1,3); if (minutes.equals("15")) {minutes = "25";} if (minutes.equals("30")) {minutes = "50";} if (minutes.equals("45")) {minutes = "75";} b7 = hour+minutes; } else if (b7.trim().length() == 4) { // 2-digit hour + minutes String hour = b7.trim().substring(0,2); String minutes = b7.trim().substring(2,4); if (minutes.equals("15")) {minutes = "25";} if (minutes.equals("30")) {minutes = "50";} if (minutes.equals("45")) {minutes = "75";} b7 = hour+minutes; } else if (b7.trim().length() == 1) {b7 = " " + b7 + "00";} //One digit hour reported, e.g. '4' else { // Two digit hour reported, e.g. '12' if (b7.equals("24")) { b7 = " 0"; // if '24' then convert to ' 0' Integer Y = new Integer(b4.trim()); int y = Y.intValue(); Integer M = new Integer(b5.trim()); int m = M.intValue(); Integer D = new Integer(b6.trim()); int d = D.intValue(); //month has 31 days (Jan, Mar, May, July, Aug, Oct, Dec) if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) { if (d == 31) { //last day of the month if (m == 12) { //and December (new year coming up); increment year; start month 1 day 1 y = y+1; m = 1; d = 1; b4 = Integer.toString(y).trim(); b5 = Integer.toString(m).trim(); if (b5.length() == 1) {b5 = " " + b5;} b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } else { //all other months w/ 31 days increment month by 1; start on day 1 m = m+1; d = 1; b5 = Integer.toString(m).trim(); if (b5.length() == 1) {b5 = " " + b5;} b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } } else { //less than 31 days, month & year stay the same; increment day by 1 d = d+1; b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } } // month has 30 days (Apr, June, Sept, Nov) else if (m == 4 || m == 6 || m == 9 || m == 11) { if (d == 30) { //last day of the month m = m+1; d = 1; b5 = Integer.toString(m).trim(); if (b5.length() == 1) {b5 = " " + b5;} b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } else { d = d+1; b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } } // month has 28 days (Feb) else if (m == 2) { if (d == 28) { //last day of the month if (y == 1900) { //leap year d = d+1; //day 29 b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } else { //next month (March); day 1 m = 3; d = 1; b5 = Integer.toString(m).trim(); if (b5.length() == 1) {b5 = " " + b5;} b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } } else { // increment day by 1 d = d+1; b6 = Integer.toString(d).trim(); if (b6.length() == 1) {b6 = " " + b6;} } } } else {b7 = b7 + "00";} // hour not 24 so add "00" minutes } //Platform type - This is set in the lat/lon sections below. String pt = null; //Latitude String b2; //lat if (lat.trim().length() == 0) { b2 = " "; } else { if (lat.trim().equals("Gaasefjord")) { b2 = " 7682"; pt= " 9"; } else if (lat.trim().equals("Godhavn")) { b2 = " 6925"; pt= " 9"; } else if (lat.trim().equals("at_Godhavn")) { b2 = " 6925"; pt= " 5"; } else if (lat.trim().equals("Havenfjord") || lat.trim().equals("Havnefjord")) { b2 = " 7649"; pt= " 9"; } else if (lat.trim().length() == 0) { b2 = " "; pt=" 5"; } else { String [] lat_split = lat.split("°"); String lat_deg = lat_split[0].trim(); //whole degrees String lat_min = lat_split[1].trim(); //minutes if (lat_min.contains("'")) { lat_min = lat_min.replace("'","").trim(); lat_min = conv_MinToDecimal(lat_min);//convert lat_min to hundredths of degree } else { lat_min = conv_MinToDecimal(lat_min);//convert lat_min to hundredths of degree } b2 = lat_deg + lat_min; b2 = StringUtils.leftPad(b2, 5); //pad length to 5 chars pt=" 5"; } } //Longitude String b3; if (lat.trim().equals("at_Godhavn")){ b3 = " 30647"; } else if (lon.trim().length() == 0) { b3 = " "; } else { if (lon.trim().equals("Gaasefjord")) { b3 = " 27134"; } else if (lon.trim().equals("Godhavn") || lat.trim().equals("at_Godhavn")) { b3 = " 30647"; } else if (lon.trim().equals("Havenfjord") || lon.trim().equals("Havnefjord")) { b3 = " 27594"; } else { String [] lon_split = lon.split("°"); String lon_deg = lon_split[0].trim(); //whole degrees String lon_min = lon_split[1].trim(); //minutes if (lon_min.contains("'")) { lon_min = lon_min.replace("'","").trim(); lon_min = conv_MinToDecimal(lon_min);//convert lon_min to hundredths of degree } else { lon_min = conv_MinToDecimal(lon_min);//convert lon_min to hundredths of degree } String lon_full = lon_deg + lon_min; // lon decimal degrees W for UTC conversion 18-23 b3 = conv_Lon(lon_full); // lon degrees E for IMMA1 } } //Special case for PT in file 'sea_Sep_1_to_Sep_19_1898.csv; lat/lons are provided but it is noted in the publication that this is overwintering station. //All PT=9 for ice station/overwintering ship if (IpPath.equals("sea_Sep_1_to_Sep_19_1898.csv")) { pt= " 9"; } //Special case for lat/lon in file 'sea_Aug_30_to_Oct_23_1899.csv; must populate blank entries with lat/lon of Havenfjord if (IpPath.equals("sea_Aug_30_to_Oct_23_1899.csv") && b2.trim().length() == 0 && b3.trim().length() == 0) { b2 = " 7649"; b3 = " 27594"; pt= " 9"; } //Special case for lat/lon in file 'sea_1900.csv; must populate blank entries with lat/lon of Gaasefjord if (IpPath.equals("sea_1900.csv") && b2.trim().length() == 0 && b3.trim().length() == 0) { b2 = " 7682"; b3 = " 27134"; pt= " 9"; } String gmtDate = null; //Convert local date/time to UTC if (b7.equals(" 0")) { b7=" 000"; } if (b7.trim().length() == 0) { gmtDate = b4+b5+b6+" "; } //Calculate hour offset and convert time to UTC (Based on subroutine rxltut from lmrlib: http://icoads.noaa.gov/software/lmrlib else { int elon = Integer.parseInt(b3.trim()); //convert imma longitude [b3] string to integer int wlon = 36000 - elon; int dhr = (wlon + 749)/1500; //calculate hour offset String localDate = b4+b5+b6+b7; //local date yyyymmddhhmm if (b7.substring(2,4).trim().equals("75")) { localDate = b4+b5+b6+b7.substring(0,2)+"45"; //local date yyyymmddhhmm } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); Date date = sdf.parse(localDate); // System.out.println(date); Date newDate = DateUtils.addHours(date, dhr); gmtDate = sdf.format(newDate); if (gmtDate.substring(10,12).trim().equals("45")) { gmtDate = gmtDate.substring(0,10)+"75"; //gmt date yyyymmddhhmm } if (gmtDate.substring(4,5).equals("0")) { gmtDate = gmtDate.substring(0,4) + " " + gmtDate.substring(5); } if (gmtDate.substring(6,7).equals("0")) { gmtDate = gmtDate.substring(0,6) + " " + gmtDate.substring(7); } if (gmtDate.substring(8,9).equals("0") && gmtDate.substring(9,10).equals("0") && gmtDate.substring(10,11).equals("0")) { gmtDate = gmtDate.substring(0,8) + " " + gmtDate.substring(11); } if (gmtDate.substring(8,9).equals("0") && gmtDate.substring(9,10).equals("0")) { gmtDate = gmtDate.substring(0,8) + " " + gmtDate.substring(10); } if (gmtDate.substring(8,9).equals("0")) { gmtDate = gmtDate.substring(0,8) + " " + gmtDate.substring(9); } } //22222233333 //45678901234 Hard code Data String f1 = " 1204 10"; // 24-34: IM(24-25);ATTC(26);TI(27);LI(28);DS(29);VS(30);NID(31-32);II(33-34) II=10=composite info from early ship data String b1 = "FRAM "; // call sign 35-43 //44444455 //45678901 Create Filler Space String f2 = " "; // 44-45 Country Code String fwdi = "1"; // DI - wind dir ind 50 DI = 1 = 32 Point Compass String b13 = wd.trim(); if (wd.trim().length() == 0) { // wind dir 47-49 b13 = " "; fwdi = " "; } else if (b13.trim().equals("0")) { b13 = " 0"; } else { b13 = conv_WD(wd); //convert from alpha to numeric direction } String b14 = ws.trim(); // wind speed in m/s 51-53 if (b14.length() > 0) { BigDecimal ms = new BigDecimal(b14); //convert string to BigDecimal BigDecimal d_ms = ms.divide(BigDecimal.valueOf(0.1)); //remove decimal BigDecimal i_ms = d_ms.setScale(0,RoundingMode.UNNECESSARY); //scale = 0 (no values right of decimal); no rounding needed String new_ms = i_ms.toString(); //convert back to string b14 = StringUtils.leftPad(new_ms, 3); //pad length to 3 chars } else { b14 = " ";} // if wind speed = 0 and wind direction is blank assume calm, IMMA output wind direction = 361 for calm if (b13.trim().length() == 0 && b14.trim().equals("0")) { b13 = "361"; fwdi = "1"; } String b12; // wind Sp Ind. 50 WI=1=m/s if (b14.trim().length() == 0) { b12 = " "; } else {b12 = "1";} //55555555566 //12345678901 Create Filler Space String f3 = " "; // 54-56: VI(54);VV(55-56) String b23 = " "; //pres wx 57-58; Not mapped to IMMA1 String b24 = " "; // past wx 59; not populated String b11 = slp.trim(); // slp 60-64 if (b11.length() > 0) { BigDecimal mm = new BigDecimal(b11); //convert string to BigDecimal BigDecimal D_hpa = mm.multiply(BigDecimal.valueOf(1.333224)); //hPa = mm * 1.333224 per fxmmmb from lmrlib.f (http://icoads.noaa.gov/software/lmrlib) BigDecimal I_hpa = D_hpa.setScale(1,RoundingMode.HALF_UP); //scale = 1 (keep 1 decimal value); round accordingly BigDecimal d_hpa = I_hpa.divide(BigDecimal.valueOf(0.1)); //remove decimal BigDecimal i_hpa = d_hpa.setScale(0,RoundingMode.UNNECESSARY); //scale = 0 (no values right of decimal); no rounding needed String new_hpa = i_hpa.toString(); //convert back to string b11 = StringUtils.leftPad(new_hpa, 5); //pad length to 5 chars } else {b11 = " ";} //6666 //5678 Create Filler Space String f4 = " "; // 65-68: A(65);PPP(66-68) String b17 = at.trim(); // air temp 70-73 if (b17.length() > 0) { BigDecimal celsius = new BigDecimal(b17); //convert string to BigDecimal BigDecimal d_celsius = celsius.divide(BigDecimal.valueOf(0.1)); //remove decimal BigDecimal i_celsius = d_celsius.setScale(0,RoundingMode.UNNECESSARY); //scale = 0 (no values right of decimal); no rounding needed String new_celsius = i_celsius.toString(); //convert back to string b17 = StringUtils.leftPad(new_celsius, 4); //pad length to 4 chars } else {b17 = " ";} String b18 = " "; //wetBI 74 String b19 = " "; // wetBulb 75-78 //DPTI (79) and DPT (80-83) // String f5 = " "; // DPTI 79 // String b20 = " "; // dwpt 80-83 //DPTI (79) and DPT (80-83) String f5,b20; if (vapor.trim().length()==0 || slp.trim().length()==0){ f5 = " "; // DPTI 79 b20 = " "; // dwpt 80-83 } else { //Calculate dwpt using caclDwpt method; 2 args: slp and vapor String dwpt = calcDwpt(slp,vapor); f5 = "1"; // DPTI 79: DPTI = 1 = Calculated b20 = dwpt; // dwpt 80-83 } String b33; // SI 84-85 if (sst.trim().length() == 0) { b33 = " "; } else {b33 = "10"; } // SI = 10 = implied bucket (indirectly disclosed in description of thermometers used. See transpec for more info. String b34 = sst.trim(); //SST if (b34.length() > 0) { BigDecimal sstC = new BigDecimal(b34); //convert string to BigDecimal BigDecimal d_sstC = sstC.divide(BigDecimal.valueOf(0.1)); //remove decimal BigDecimal i_sstC = d_sstC.setScale(0,RoundingMode.UNNECESSARY); //scale = 0 (no values right of decimal); no rounding needed String new_sstC = i_sstC.toString(); //convert back to string b34 = StringUtils.leftPad(new_sstC, 4); //pad length to 4 chars } else { b34 = " "; } String fIT = null; // IT (temp indicator) 69 if (b17.trim().length() == 0 && b34.trim().length() == 0) { fIT = " "; } else { fIT = "0"; // IT = 0 = temps in tenths °C } String b25 = c_amt.trim(); // tot cld amt 90 - Mohn 1907 values are 'tenths of sky covered'; use ixt1ok from lmrlib to convert to oktas (see amt_Cloud) if (b25.trim().length() == 0) { // ck for missing b25 = " "; } else { b25 = amt_Cloud(b25); } String b26 = " "; //NH Low Cld Amt 91 (Not reported) String b27 = " "; // HI,H 93-94 (Not reported) String b28 = " "; // CL - low cloud type 92 //Cloud types taken from WMO Codes 0513 (low), 0515 (med), 0509 (high) String b29 = " "; // CM - mid cloud type 95 String b30 = " "; // CH - high cloud type 96 if (c_type.trim().length() == 0 || c_type.trim().equals("Fr-Nb")|| c_type.trim().equals("Nb") || c_type.trim().equals("Nb&Fr-Nb")) { b28 = " "; b29 = " "; b30 = " "; } else if (c_type.trim().equals("Ci-St") || c_type.trim().equals("\"Ci-St") || c_type.trim().equals("Ci-St3")) { b28 = " "; b29 = " "; b30 = "7"; } else if (c_type.trim().equals("A-Cu")) { b28 = " "; b29 = "3"; b30 = " "; } else if (c_type.trim().equals("A-Cu&St") || c_type.trim().equals("A-Cu-St")) { b28 = "6"; b29 = "3"; b30 = " "; } else if (c_type.trim().equals("Ci")) { b28 = " "; b29 = " "; b30 = "1"; } else if (c_type.trim().equals("Ci&St")) { b28 = "6"; b29 = " "; b30 = "1"; } else if (c_type.trim().equals("Ci-Cu")) { b28 = " "; b29 = " "; b30 = "9"; } else if (c_type.trim().equals("Ci-Cu&St")) { b28 = "6"; b29 = " "; b30 = "9"; } else if (c_type.trim().equals("Ci-St&St") || c_type.trim().equals("Ci-St1&St1") || c_type.trim().equals("Ci-St2&St2") || c_type.trim().equals("Ci-St2&St3") || c_type.trim().equals("Ci-St2&St7") || c_type.trim().equals("Ci-St3&St1") || c_type.trim().equals("Ci-St4&St1") || c_type.trim().equals("Ci-St4&St3") || c_type.trim().equals("Ci-St5&St3") || c_type.trim().equals("Ci-St7&St1") || c_type.trim().equals("Ci-St7&St3")) { b28 = "6"; b29 = " "; b30 = "7"; } else if (c_type.trim().equals("Ci-StSt-Cu")) { b28 = "5"; b29 = " "; b30 = "7"; } else if (c_type.trim().equals("Ci2&St-Cu1")) { b28 = "5"; b29 = " "; b30 = "1"; } else if (c_type.trim().equals("Cu")) { b28 = "1"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("Cu-Nb")) { b28 = "3"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("Fr-St")) { b28 = "7"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St")) { b28 = "6"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St&Fr-St") || c_type.trim().equals("St3&Fr-St0-1") || c_type.trim().equals("St4&Fr-St")) { //stratus trumps stratus fractus b28 = "6"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St&St-Cu") || c_type.trim().equals("St-Cu&St") || c_type.trim().equals("St6&St-Cu3")) { //stratus trumps strato-cu b28 = "6"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St-Cu")) { b28 = "5"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St-Cu&Nb")) { b28 = "5"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St-Cu2&Cu-Nb7")) { b28 = "9"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St-Cu2&Cu-Nb7")) { b28 = "9"; b29 = " "; b30 = " "; } else if (c_type.trim().equals("St7&Cu2")) { //stratus trumps cumulus b28 = "6"; b29 = " "; b30 = " "; } String waves = " "; // 97-108 Sea/Swell State reported but indeterminable which of the 2 was being reported: //WD(97-98);WP(99-100);WH(101-102);SD(103-104);SP(105-106);SH(107-108) // Table C1 - Icoads attm (Most fields populated by ICOADS QC software) String icoadsPt1= //111111111111111111111111111111111111 //0111111111122222222223333333333444444 //9012345678901234567890123456789012345 Beg " 165 734128"; // 109-124 //DCK=734 //SID=128 //PT=5 (ship) or PT=9 (ice station/overwintering) - This is set in lat/lon sections. String icoadsPt2=" "; // 127-173 // Table C5 - Immt attm (remove attm if RH blank) String immt; if (rh.trim().length() > 0) { //Part 1 String immt1 = " 594 "+ // 174-208 " "; // 209-254 //Part 2 String hum = rh.trim(); //255-258 RH if (hum.trim().length() == 1) { hum = " " + hum + "0"; } else if (hum.trim().length() == 2) { hum = " " + hum + "0"; } else if (hum.trim().length() == 3) { hum = hum + "0"; } //Part 3 String humI = "4"; // 259 RHI = 4 = Whole percentage;Computed //Part 4 String immt2 = " "; // 260-267 (AWSI [260];IMONO [261-267]) immt = immt1+hum+humI+immt2; } else { immt = ""; } //Supplemental Attm - Original observation attached here String s50 = "99 0 "; // //Full IMMA record assembled here String outrec = gmtDate+b2+b3+f1+b1+f2+fwdi +b13+b12+b14+f3+b23+b24+b11+f4+fIT+b17+b18+b19 +f5+b20+b33+b34+b25+b26+b28+b27+b29+b30+waves +icoadsPt1+pt+icoadsPt2+immt+s50+str+","+IpPath; //Full IMMA record assembled here // String outrec = b4+b5+b6+b7+b2+b3+f1+b1+f2+fwdi // +b13+b12+b14+f3+b23+b24+b11+f4+fIT+b17+b18+b19 // +f5+b20+b33+b34+b25+b26+b28+b27+b29+b30+waves // +icoads+immt+s50+str+","+IpPath; //write IMMA record to output file writeString(opbw,outrec); System.out.println(outrec); } catch (NumberFormatException e) { System.out.println(e); System.out.println(str); e.printStackTrace(); break; } }//end while closeUp(); } private static boolean ValidCheck(int i, String localDate) { return false; } /******************************************************************************************************************************/ public static void openFiles() { try /*** IP File ***/ { System.out.println("Opening For Read: " + IpPath + "\n"); InputFile = new File(IpPath); ipbr = new BufferedReader(new FileReader(InputFile)); } catch(IOException e) { System.out.println("*** Error *** " + e.toString()); System.out.println("Could Not Open " + IpPath); System.exit(1); } try /*** OP File ***/ { System.out.println("Opening For Write: " + OpPath + "\n"); OutputFile = new File(OpPath); opbw = new BufferedWriter(new FileWriter(OutputFile)); } catch(IOException e) { System.out.println("*** Error *** " + e.toString()); System.out.println("Could Not Open " + OpPath); System.exit(1); } } /******************************************************************************************************************************/ public static boolean writeString(BufferedWriter locbw, String locString) { try { locbw.write(locString + "\n"); return(true); } catch(IOException e) { System.out.println("*** Error *** " + e.toString()); } return(false); } /******************************************************************************************************************************/ public static void closeUp() { try { ipbr.close(); opbw.close(); } catch(IOException e) { System.out.println("*** ERROR Closing Files ***\n"); } } /*********************************************** * String Function to convert longitude from E-W to degrees East (IMMA convention). */ public static String conv_MinToDecimal(String latlon_minutes) { BigDecimal whole = new BigDecimal(latlon_minutes); //convert string to BigDecimal BigDecimal d_decimal = whole.divide(BigDecimal.valueOf(60),2,RoundingMode.HALF_UP); //convert minutes to hundredths of degree BigDecimal remove_decimal = d_decimal.divide(BigDecimal.valueOf(0.01)); //remove decimal String new_decimal = remove_decimal.toString(); //convert back to string String decimalLength = new_decimal.trim(); //Check string length and pad where needed int l = decimalLength.length(); if (l==1) {new_decimal = "0" + decimalLength;} return new_decimal; } /*********************************************** * String Function to convert longitude from E-W to degrees East (IMMA convention). */ public static String conv_Lon(String longitude) { Double D_lon = new Double(longitude); //Create double obj double d_lon = D_lon.doubleValue(); //Create double num d_lon = 36000 - d_lon; // Convert to degrees east (only in case of positive longitude) d_lon = Math.round(d_lon); //Round to whole# D_lon = new Double(d_lon); //Convert to int int i_lon = D_lon.intValue(); Integer I_lon = new Integer(i_lon); // Convert back to string String lon = I_lon.toString(); lon = StringUtils.leftPad(lon, 6); //pad length to 6 chars return lon; } /**************************************************************** * Integer Function to calculate time zone offset in hours for conversion of local date/time to GMT */ public static int getTimezoneOffsetInHours(String longitude) { Integer lon_int = new Integer(longitude); int y = lon_int.intValue(); int lon_offset = (y/100)/24; return lon_offset; } /*********************************************** * String Function to convert units of mmHg to hPa (millibars) for SLP or moisture calculations */ public static String conv_hPa(String mmHg) { BigDecimal mm = new BigDecimal(mmHg); //convert string to BigDecimal BigDecimal D_hpa = mm.multiply(BigDecimal.valueOf(1.333224)); //hPa = mm * 1.333224 per fxmmmb from lmrlib.f (http://icoads.noaa.gov/software/lmrlib) BigDecimal I_hpa = D_hpa.setScale(1,RoundingMode.HALF_UP); //scale = 1 (keep 1 decimal value); round accordingly BigDecimal d_hpa = I_hpa.divide(BigDecimal.valueOf(0.1)); //remove decimal BigDecimal i_hpa = d_hpa.setScale(0,RoundingMode.UNNECESSARY); //scale = 0 (no values right of decimal); no rounding needed String new_hpa = i_hpa.toString(); //convert back to string new_hpa = StringUtils.leftPad(new_hpa, 5); //pad length to 5 chars return new_hpa; } /**************************************************************** * String Function to convert 32 point Alpha Wind directions to degrees */ public static String conv_WD(String AlphaWD) { String NumWD=" "; if (AlphaWD.trim().equalsIgnoreCase("NbE") || AlphaWD.trim().equalsIgnoreCase("NxE") || AlphaWD.trim().equalsIgnoreCase("NXE")) NumWD=" 11"; if (AlphaWD.trim().equalsIgnoreCase("NNE")) NumWD=" 23"; if (AlphaWD.trim().equalsIgnoreCase("NEbN") || AlphaWD.trim().equalsIgnoreCase("NExN") || AlphaWD.trim().equalsIgnoreCase("NEXN")) NumWD=" 34"; if (AlphaWD.trim().equalsIgnoreCase("NE")) NumWD=" 45"; if (AlphaWD.trim().equalsIgnoreCase("NEbE") || AlphaWD.trim().equalsIgnoreCase("NExE") || AlphaWD.trim().equalsIgnoreCase("NEXE")) NumWD=" 56"; if (AlphaWD.trim().equalsIgnoreCase("ENE")) NumWD=" 68"; if (AlphaWD.trim().equalsIgnoreCase("EbN") || AlphaWD.trim().equalsIgnoreCase("ExN") || AlphaWD.trim().equalsIgnoreCase("EXN")) NumWD=" 79"; if (AlphaWD.trim().equalsIgnoreCase("E")) NumWD=" 90"; if (AlphaWD.trim().equalsIgnoreCase("EbS") || AlphaWD.trim().equalsIgnoreCase("ExS") || AlphaWD.trim().equalsIgnoreCase("EXS")) NumWD="101"; if (AlphaWD.trim().equalsIgnoreCase("ESE")) NumWD="113"; if (AlphaWD.trim().equalsIgnoreCase("SEbE") || AlphaWD.trim().equalsIgnoreCase("SExE") || AlphaWD.trim().equalsIgnoreCase("SEXE")) NumWD="124"; if (AlphaWD.trim().equalsIgnoreCase("SE")) NumWD="135"; if (AlphaWD.trim().equalsIgnoreCase("SEbS") || AlphaWD.trim().equalsIgnoreCase("SExS") || AlphaWD.trim().equalsIgnoreCase("SEXS")) NumWD="146"; if (AlphaWD.trim().equalsIgnoreCase("SSE")) NumWD="158"; if (AlphaWD.trim().equalsIgnoreCase("SbE") || AlphaWD.trim().equalsIgnoreCase("SxE") || AlphaWD.trim().equalsIgnoreCase("SXE")) NumWD="169"; if (AlphaWD.trim().equalsIgnoreCase("S")) NumWD="180"; if (AlphaWD.trim().equalsIgnoreCase("SbW") || AlphaWD.trim().equalsIgnoreCase("SxW") || AlphaWD.trim().equalsIgnoreCase("SXW")) NumWD="191"; if (AlphaWD.trim().equalsIgnoreCase("SSW")) NumWD="203"; if (AlphaWD.trim().equalsIgnoreCase("SWbS") || AlphaWD.trim().equalsIgnoreCase("SWxS") || AlphaWD.trim().equalsIgnoreCase("SWXS")) NumWD="214"; if (AlphaWD.trim().equalsIgnoreCase("SW")) NumWD="225"; if (AlphaWD.trim().equalsIgnoreCase("SWbW") || AlphaWD.trim().equalsIgnoreCase("SWxW") || AlphaWD.trim().equalsIgnoreCase("SWXW")) NumWD="236"; if (AlphaWD.trim().equalsIgnoreCase("WSW")) NumWD="248"; if (AlphaWD.trim().equalsIgnoreCase("WbS") || AlphaWD.trim().equalsIgnoreCase("WxS") || AlphaWD.trim().equalsIgnoreCase("WXS")) NumWD="259"; if (AlphaWD.trim().equalsIgnoreCase("W")) NumWD="270"; if (AlphaWD.trim().equalsIgnoreCase("WbN") || AlphaWD.trim().equalsIgnoreCase("WxN") || AlphaWD.trim().equalsIgnoreCase("WXN")) NumWD="281"; if (AlphaWD.trim().equalsIgnoreCase("WNW")) NumWD="293"; if (AlphaWD.trim().equalsIgnoreCase("NWbW") || AlphaWD.trim().equalsIgnoreCase("NWxW") || AlphaWD.trim().equalsIgnoreCase("NWXW")) NumWD="304"; if (AlphaWD.trim().equalsIgnoreCase("NW")) NumWD="315"; if (AlphaWD.trim().equalsIgnoreCase("NWbN") ||AlphaWD.trim().equalsIgnoreCase("NWxN") || AlphaWD.trim().equalsIgnoreCase("NWXN")) NumWD="326"; if (AlphaWD.trim().equalsIgnoreCase("NNW")) NumWD="338"; if (AlphaWD.trim().equalsIgnoreCase("NbW") || AlphaWD.trim().equalsIgnoreCase("NxW") || AlphaWD.trim().equalsIgnoreCase("NXW")) NumWD="349"; if (AlphaWD.trim().equalsIgnoreCase("N")) NumWD="360"; if (AlphaWD.trim().equalsIgnoreCase("C")) NumWD="361"; if (AlphaWD.trim().equalsIgnoreCase("V") || AlphaWD.trim().equalsIgnoreCase("Var.") || AlphaWD.trim().equalsIgnoreCase("VAR")) NumWD="362"; return NumWD; } /**************************************************************** * String Function to convert amt sky (covered) from tenths to oktas */ public static String amt_Cloud (String amt) { String NC = null; if (amt.trim().equals("0")) { NC="0"; return NC; } if (amt.trim().equals("1") || amt.trim().equals("0-1") || amt.trim().equals("1+") || amt.trim().equals("1-")) { NC="1"; return NC; } if (amt.trim().equals("2") || amt.trim().equals("3") || amt.trim().equals("1-2") || amt.trim().equals("1-2-") || amt.trim().equals("2-") || amt.trim().equals("2-3") || amt.trim().equals("2-Jan") || amt.trim().equals("3-") || amt.trim().equals("3-Feb")) { NC="2"; return NC; } if (amt.trim().equals("4") || amt.trim().equals("4+") || amt.trim().equals("4-")) { NC="3"; return NC; } if (amt.trim().equals("5") || amt.trim().equals("5-")) { NC="4"; return NC; } if (amt.trim().equals("6") || amt.trim().equals("6-") || amt.trim().equals("6+")) { NC="5"; return NC; } if (amt.trim().equals("7") || amt.trim().equals("8") || amt.trim().equals("7-") || amt.trim().equals("8-") || amt.trim().equals("8+")) { NC="6"; return NC; } if (amt.trim().equals("9") || amt.trim().equals("9-") || amt.trim().equals("9+") || amt.trim().equals("90")) { NC="7"; return NC; } if (amt.trim().equals("10") || amt.trim().equals("10+") || amt.trim().equals("10-") || amt.trim().equals("9-10") || amt.trim().equals("10-Sep")) { NC="8"; return NC; } else { System.err.println("Cloud Amt = "+amt); NC=" "; return NC; } } /*********************************************** * String Function to calculate dwpt from available dry bulb, pressure and vapor tension */ public static String calcDwpt(String pressure, String vapTension) { //convert slp in mmHg to mb double slp_mmHg = Double.parseDouble(pressure); //Create double num double slp_mb = slp_mmHg * 1.333224; // convert vapor tension from mmHg to mb //convert vapor tension in mmHg to mb double vap_mmHg = Double.parseDouble(vapTension); //Create double num double vap_mb = vap_mmHg * 1.333224; // convert vapor tension from mmHg to mb //Sat. Vap. Pressure calculation double calc_fp = 1.0016 + (3.15 * Math.pow(10,-6) * slp_mb) - 0.074 * Math.pow(slp_mb, -1); //dwpt calculation double calc_dwpt = (243.12 * Math.log(vap_mb / (6.112 * calc_fp))) / (17.62 - Math.log(vap_mb / (6.112 * calc_fp))); BigDecimal i_dwpt = new BigDecimal(calc_dwpt); BigDecimal I_dwpt = i_dwpt.setScale(1,RoundingMode.HALF_UP); //scale = 1 (keep 1 decimal value); round accordingly BigDecimal d_dwpt = I_dwpt.divide(BigDecimal.valueOf(0.1)); //remove decimal String new_dwpt = d_dwpt.toString(); //convert back to string new_dwpt = StringUtils.leftPad(new_dwpt, 4); //pad length to 4 chars return new_dwpt; } /****************************************************************************** Returns false if any character in CheckString is not also in ValidChars *******************************************************************************/ public static boolean ValidCheck(String ValidChars, String CheckString) { for(int n=0;n