CVS: phpweather data_retrieval.php,1.32,1.33 phpweather.php,1.34,1.35...
Brought to you by:
iridium
From: Etienne T. <eti...@us...> - 2003-09-13 02:38:55
|
Update of /cvsroot/phpweather/phpweather In directory sc8-pr-cvs1:/tmp/cvs-serv17699 Modified Files: data_retrieval.php phpweather.php test2.php Log Message: Added hour-by-hour decoding of the taf. test2.php was modified to show that. Interpolation is done in BECMG periods and PROB periods are not added to the hour-by-hour report. Index: data_retrieval.php =================================================================== RCS file: /cvsroot/phpweather/phpweather/data_retrieval.php,v retrieving revision 1.32 retrieving revision 1.33 diff -u -3 -r1.32 -r1.33 Index: phpweather.php =================================================================== RCS file: /cvsroot/phpweather/phpweather/phpweather.php,v retrieving revision 1.34 retrieving revision 1.35 diff -u -3 -r1.34 -r1.35 --- phpweather.php 8 Sep 2003 04:20:44 -0000 1.34 +++ phpweather.php 13 Sep 2003 02:38:49 -0000 1.35 @@ -288,7 +288,7 @@ $group['ft'] = round($regs[1] * 3.28084); } if (!empty($regs[2])) { - $group['dir'] = $regs[2]; + $group['deg'] = $regs[2]; } $decoded_metar['visibility'][] = $group; @@ -701,6 +701,12 @@ * @see $decoded_taf * @access public */ + + //from http://www.nws.noaa.gov/mdl/icwf/avnfps/editor.html#TAFDecoder + //need to add NIL( AMD) (augmented data) + //and time consistency checks, Consistency Checks Within a Group + + function decode_taf() { /* initialization */ @@ -759,6 +765,7 @@ /* for each period, parse the data */ if(count($periods)>0) { + $last_fm_becmg = false; for($j=0;$j<count($periods);$j++) { $tmp_period = $periods[$j]; $data_period = $tmp_period; @@ -774,22 +781,38 @@ if ( (substr($parts[0],0,2)=='FM') ) { $type = 'FM'; $time_from = substr($parts[0],2,4); - $time_to = false; + $time_set = $time_from; + $time_to = false; $first_i = 1; + /* set the end time if the previous FM or BECMG to the start time of this one */ + if($last_fm_becmg!==false && $decoded_periods[$last_fm_becmg]['time_to']===false) { + $decoded_periods[$last_fm_becmg]['time_to'] = $time_from; + } + $last_fm_becmg = $j; } else if ($parts[0]=='BECMG') { $type = 'BECMG'; + $time_from = substr($parts[1],0,2).'00'; + $time_set = substr($parts[1],2,2).'00'; + $time_to = false; $first_i = 2; + /* set the end time if the previous FM or BECMG to the start time of this one */ + if($last_fm_becmg!==false && $decoded_periods[$last_fm_becmg]['time_to']===false) { + $decoded_periods[$last_fm_becmg]['time_to'] = $time_from; + } + $last_fm_becmg = $j; } else if ($parts[0]=='TEMPO') { $type = 'TEMPO'; $time_from = substr($parts[1],0,2).'00'; + $time_set = $time_from; //could interpolate for the first half ? $time_to = substr($parts[1],2,2).'00'; $first_i = 2; } else if (substr($parts[0],0,4)=='PROB') { $type = 'PROB'; $time_from = substr($parts[1],0,2).'00'; + $time_set = $time_from; $time_to = substr($parts[1],2,2).'00'; $prob = intval(substr($parts[0],4)); $first_i = 2; @@ -798,6 +821,7 @@ $type = 'COMPLETE'; $data_period = substr($data_period,9); $time_from = substr($parts[1],2,2).'00'; + $time_set = $time_from; $time_to = substr($parts[1],4,2).'00'; $first_i = 2; } @@ -809,6 +833,7 @@ $decoded_period['type'] = $type; $decoded_period['time_from'] = $time_from; $decoded_period['time_to'] = $time_to; + $decoded_period['time_set'] = $time_set; $decoded_period['prob'] = $prob; /* pass each element of the period */ @@ -818,12 +843,12 @@ if (ereg('^([0-9]{3}|VRB)([0-9]{2,3})G?([0-9]{2,3})?(KT)', $part, $regs)) { /* Wind Group */ - $decoded_period['wind']['deg'] = $regs[1]; + $decoded_period['desc']['wind']['deg'] = $regs[1]; $this->store_speed($regs[2], $regs[4], - $decoded_period['wind']['knots'], - $decoded_period['wind']['meters_per_second'], - $decoded_period['wind']['miles_per_hour']); + $decoded_period['desc']['wind']['knots'], + $decoded_period['desc']['wind']['meters_per_second'], + $decoded_period['desc']['wind']['miles_per_hour']); if (!empty($regs[3])) { @@ -832,17 +857,17 @@ */ $this->store_speed($regs[3], $regs[4], - $decoded_period['wind']['gust_knots'], - $decoded_period['wind']['gust_meters_per_second'], - $decoded_period['wind']['gust_miles_per_hour']); + $decoded_period['desc']['wind']['gust_knots'], + $decoded_period['desc']['wind']['gust_meters_per_second'], + $decoded_period['desc']['wind']['gust_miles_per_hour']); } } elseif (ereg('^([0-9]{3})V([0-9]{3})$', $part, $regs) && - !empty($decoded_period['wind']['deg'])) { + !empty($decoded_period['desc']['wind']['deg'])) { /* * Variable wind-direction */ - $decoded_period['wind']['var_beg'] = $regs[1]; - $decoded_period['wind']['var_end'] = $regs[2]; + $decoded_period['desc']['wind']['var_beg'] = $regs[1]; + $decoded_period['desc']['wind']['var_end'] = $regs[2]; } elseif (ereg('^([0-9]{4})([NS]?[EW]?)$', $part, $regs)) { /* * Visibility in meters (4 digits only) @@ -873,9 +898,9 @@ $group['ft'] = round($regs[1] * 3.28084); } if (!empty($regs[2])) { - $group['dir'] = $regs[2]; + $group['deg'] = $regs[2]; } - $decoded_period['visibility'][] = $group; + $decoded_period['desc']['visibility'][] = $group; } elseif (ereg('^[0-9]$', $part)) { /* @@ -887,11 +912,11 @@ unset($group); $group['prefix'] = 1; $vis_miles = 6; - $group['miles'] = number_format($vis_miles, 1); + $group['miles'] = $vis_miles; $group['ft'] = round($vis_miles * 5280, 1); $group['km'] = number_format($vis_miles * 1.6093, 1); $group['meter'] = round($vis_miles * 1609.3); - $decoded_period['visibility'][] = $group; + $decoded_period['desc']['visibility'][] = $group; } elseif (ereg('^[M]?(([0-9]?)[ ]?([0-9])(/?)([0-9]*))SM$', $temp_visibility_miles . ' ' . $part, $regs)) { @@ -924,11 +949,11 @@ /* The visibility measured in meters */ $group['meter'] = round($vis_miles * 1609.3); - $decoded_period['visibility'][] = $group; + $decoded_period['desc']['visibility'][] = $group; } elseif (ereg('^(VC)?' . /* Proximity */ '(-|\+)?' . /* Intensity */ - '(MI|PR|BC|DR|BL|SH|TS|FZ)?' . /* Descriptor */ + '(MI|PR|BC|DR|BL|SH|TS|FZ|NSW)?' . /* Descriptor */ '((DZ|RA|SN|SG|IC|PL|GR|GS|UP)+)?' . /* Precipitation */ '(BR|FG|FU|VA|DU|SA|HZ|PY)?' . /* Obscuration */ '(PO|SQ|FC|SS)?$', /* Other */ @@ -936,7 +961,7 @@ /* * Current weather-group. */ - $decoded_period['weather'][] = + $decoded_period['desc']['weather'][] = array('proximity' => $regs[1], 'intensity' => $regs[2], 'descriptor' => $regs[3], @@ -946,7 +971,7 @@ } elseif ($part == 'SKC' || $part == 'CLR') { /* Cloud-group */ - $decoded_period['clouds'][]['condition'] = $part; + $decoded_period['desc']['clouds'][]['condition'] = $part; } elseif (ereg('^(VV|FEW|SCT|BKN|OVC)([0-9]{3}|///)' . '(CB|TCU)?$', $part, $regs)) { @@ -970,7 +995,7 @@ $group['ft'] = $regs[2] *100; $group['meter'] = round($regs[2] * 30.48); } - $decoded_period['clouds'][] = $group; + $decoded_period['desc']['clouds'][] = $group; } elseif (ereg('^WS([0-9]{3})/([0-9]{3})([0-9]{2})KT$', $part, $regs)) { /* We have found a Wind Shear group. example WS011/27050KT */ @@ -987,18 +1012,90 @@ $ws['ft'] = $regs[1] *100; $ws['meter'] = round($regs[1] * 30.48); } - $ws['wind']['dir'] = $regs[2]; + $ws['wind']['deg'] = $regs[2]; $this->store_speed($regs[3],'KT', $ws['wind']['knots'], $ws['wind']['meters_per_second'], $ws['wind']['miles_per_hour']); - $decoded_period['wind_shear'][] = $ws; + $decoded_period['desc']['wind_shear'][] = $ws; } } } - $decoded_taf['periods'] = $decoded_periods; + + /* set the last FM or BECMG end time */ + if($last_fm_becmg!==false && $decoded_periods[$last_fm_becmg]['time_to']===false) { + $decoded_periods[$last_fm_becmg]['time_to'] = $decoded_periods[0]['time_to']; + } + + $decoded_taf['periods1'] = $decoded_periods; $decoded_taf['remarks'] = trim($decoded_taf['remarks']); } + + //ET tmp pass each period and fill in the missing pieces + /* + * taken from http://www.srh.noaa.gov/ftproot/MSD/html/note7.html + * includes icing, turbulence and temp forecast + * + * FM change rapidly within less than one hour ->from begin to end + * BECMG change slowly, normally within 2 hours, never exceed 4 hours -> interpolate each 30 min + * TEMPO temporary, less than half of the period ->from 1/4 to 3/4 interpolating + * PROB chance of occurence for the whole period ->from begin to end + */ + + $decoded_periods2 = array(); + $full_period = $full_period2 = false; + + /* for each period, parse the data */ + if(count($decoded_taf['periods1'])>0) { + $full_period = $decoded_taf['periods1'][0]; + for($j=0;$j<count($decoded_taf['periods1']);$j++) { + $tmp_period = $decoded_taf['periods1'][$j]; + $tmp_period2 = false; + + /* merge the permanent period with this one */ + if($tmp_period['type'] == "COMPLETE") $tmp_period2 = $full_period; + else $tmp_period2 = $this->merge_period($tmp_period,$full_period); + + /* fill $decoded_periods3 with data from each hour */ + $time_from = $tmp_period2['time_from']; + $tms_from = gmmktime(substr($time_from,0,2),(substr($time_from,2,2))); + $time_set = $tmp_period2['time_set']; + $tms_set = gmmktime(substr($time_set,0,2),(substr($time_set,2,2))); + $time_to = $tmp_period2['time_to']; + $tms_to = gmmktime(substr($time_to,0,2),(substr($time_to,2,2))); + if($time_to <= $time_from ) $tms_to += 24*60*60; + if($time_set < $time_from ) $tms_set += 24*60*60; + $duration = ($tms_to - $tms_from) / 60.0 / 60.0; + for($k=0;$k<ceil($duration);$k++) { + $tmp_period3 = $tmp_period2; + $tmp_tms_from = $tms_from + $k * 60*60; + $tmp_tms_to = $tmp_tms_from + 60*60;//see if fraction... + $tmp_time_from = gmdate("Hi",$tmp_tms_from); + $tmp_time_to = gmdate("Hi",$tmp_tms_to); + $tmp_period3['time_from'] = $tmp_time_from; + $tmp_period3['time_to'] = $tmp_time_to; + unset($tmp_period3['time_set']); + if($tmp_tms_from < $tms_set) { + $tmp_period3['interpolate']='yes'; + $this->interpolate_period($tmp_period3,$full_period2,$tms_from,$tms_set,$tmp_tms_from,$tmp_tms_to); + } + /* for now do not include PROB in the hour-by-hour */ + if ($tmp_period['type'] != "PROB") { + $decoded_periods3[gmdate("H",$tmp_tms_from)] = $tmp_period3; + } + } + + /* apply the permanent change for the next periods */ + if($tmp_period['type'] != "TEMPO" && $tmp_period['type'] != "PROB") { + $full_period2 = $full_period; + $full_period = $tmp_period2; + } + $decoded_periods2[$j] = $tmp_period2; + } + $decoded_taf['periods2'] = $decoded_periods2; + $decoded_taf['periods3'] = $decoded_periods3; + } + /* Finally we store our decoded TAF in $this->decoded_taf so * that other methods can use it. @@ -1007,6 +1104,60 @@ $this->decoded_taf = $decoded_taf; return $decoded_taf; + } + + function merge_period(&$period1,&$period2) { + $period = $period2; + reset($period1); + while(list($key,$val) = each($period1)) { + if(is_array($val)) { + while(list($key2,$val2) = each($val)) { + $period[$key][$key2] = $val2; + } + } + else + $period[$key] = $val; + } + return $period; + } + + function add_time($str_time,$add_hour,$add_min=0) { + $tms = gmmktime(substr($str_time,0,2),(substr($str_time,2,2))); + $tms += $add_hour*60*60 + $add_min*60; + return gmdate("Hi",$tms); + } + + + function interpolate_period(&$period,&$prev_period,$from,$set,$period_from,$period_to) { + //only interpolate wind, not: -visibility -weather -clouds -ws + $wind = $period['desc']['wind']; + $prev_wind = $prev_period['desc']['wind']; + $factor = ($period_to-$from)/($set-$from+60*60); + + $tmp_wind_speed1 = intval($prev_wind['knots']); + $tmp_wind_speed2 = intval($wind['knots']); + $tmp_wind_speed = $tmp_wind_speed1 + $factor*($tmp_wind_speed2-$tmp_wind_speed1); + + /* if VRB special treatment : set to VRB when on the VRB half */ + $tmp_wind_dir1 = $prev_wind['deg']; + $tmp_wind_dir2 = $wind['deg']; + if ($tmp_wind_speed1==0) $tmp_wind_dir = $tmp_wind_dir2; + else if ($tmp_wind_speed2==0) $tmp_wind_dir = $tmp_wind_dir1; + else { + if( ($tmp_wind_dir1=='VRB' && $tmp_wind_dir1=='VRB') || + ($factor<0.5 && $tmp_wind_dir1=='VRB') || + ($factor>0.5 && $tmp_wind_dir2=='VRB') ) { + $tmp_wind_dir = 'VRB'; + } + else + $tmp_wind_dir = $tmp_wind_dir1 + $factor*($tmp_wind_dir2-$tmp_wind_dir1); + } + + /* set the average values */ + $period['desc']['wind']['deg'] = $tmp_wind_dir; + $this->store_speed($tmp_wind_speed,'KT',$period['desc']['wind']['knots'], + $period['desc']['wind']['meters_per_second'], + $period['desc']['wind']['miles_per_hour']); } } Index: test2.php =================================================================== RCS file: /cvsroot/phpweather/phpweather/test2.php,v retrieving revision 1.1 retrieving revision 1.2 diff -u -3 -r1.1 -r1.2 --- test2.php 8 Sep 2003 04:25:54 -0000 1.1 +++ test2.php 13 Sep 2003 02:38:49 -0000 1.2 @@ -15,6 +15,7 @@ if (empty($language)) $language = 'en'; $weather = new phpweather(); +// $weather->properties['verbosity'] = 5; if (!empty($icao)) { @@ -46,12 +47,25 @@ $weather->set_icao($icao); + $language = 'en'; + require(PHPWEATHER_BASE_DIR . "/output/pw_text_$language.php"); + $type = 'pw_text_' . $language; + $text = new $type($weather); + + require(PHPWEATHER_BASE_DIR . "/output/pw_images.php"); + $icons = new pw_images($weather); + + /* echo "METAR for $icao : ".$weather->get_metar()."<br>\n"; echo "<br>Decoded METAR:<pre>"; print_r( $weather->decode_metar() ); echo "</pre><br>\n"; + */ echo "TAF for $icao : ".$weather->get_taf()."<br>\n"; + echo "<br>Print TAF:<br><br>"; + print_r( $text->print_taf() ); + echo "<br>\n"; echo "<br>Decoded TAF:<pre>"; print_r( $weather->decode_taf() ); echo "</pre><br>\n"; |