fabius Posté(e) 4 août 2008 Partager Posté(e) 4 août 2008 Salut à tous les passionnés, Je me présente rapidement, je suis Fabien de Dijon, et je suis responsable de la génération de météo dans l'association IVAO (www.ivao.aero) rassemblant les passionnés de l'aviation en proposant un réseau de simulation de ce qui existe en réel. Mon but est de recréer la MTO réelle sur le réseau (je développe des serveurs pour cela). Voilà /emoticons/happy@2x.png 2x" width="20" height="20"> Bref, j'aurais voulu savoir comment générer (quels outils utiliser) des images à partir de mes données Grib2/GFS pour superviser la météo (en fait). Oui, ça peut vous paraitre étrange, mais mon but n'est pas de proposer au public des prévisions MTO à x jours... mais seulement d'afficher les cartes aux utilisateurs (supervision/information destinée au réseau). PRMSL; WINDS, TEMP, TCDC, TMP à différents niveaux entre autre. Par ailleurs, si vous connaissez d'autres sources de météo (à part les METAR/TAF et NOAA/NCEP grib) je suis preneur car je galère pas mal depuis 6 mois (je suis tout seul). Ah oui, je cherche un acces à des radiosondages bouées et "land stations". /emoticons/tongue@2x.png 2x" width="20" height="20"> Merci d'avance, Fabien Lien à poster Partager sur d’autres sites More sharing options...
snowman43 Posté(e) 4 août 2008 Le Puy en Velay Partager Posté(e) 4 août 2008 http://www.iges.org/grads/ http://www.ncl.ucar.edu/ Lien à poster Partager sur d’autres sites More sharing options...
Comode Posté(e) 7 août 2008 Partager Posté(e) 7 août 2008 Bonjour, J'ai fait un petit site qui fabrique ses propres cartes à partir de modèles GFS... Il est codé en PHP et à pour particularité de n'utiliser q'un seul et unique logiciel compilé en C et que je n'ai pas codé moi même : wgrib (je viens juste de compiler le wgrib2, je vais essayer de migrer le tout vers grib2). Tout le reste est en PHP ! Les fonctions permettant la conversion du fichier texte généré par wgrib en une image sont donc aisément portable d'une machine à l'autre. C'est en réalité une petite implémentation de l'algo marching square en PHP. L'inconvénient, c'est que c'est un méga gouffre en puissance de clacul... Il faut environ 100 secondes à un Q6600 avec 2Go RAM pour faire une carte de pression sur tout le globe par pas de 2 ou 3mb...D'autre part, il faut pouvoir dévérouiller la limite mémoire des scripts pour pas etre emmerdé sur une telle surface. Mais je pense qu'on doit avoir des performances acceptable sur une zone géographique restreinte comme l'europe. Je pense re-implémenter tout ça en C quand j'aurais un peu de temps, mon but étant de pouvoir me passer d'outils tel que grad pour générer toutes les cartes possible depuis GFS. En attendant, tu peux jeter un coup d'oeil par exemple sur http://www.cyclone-hunter.com/?page=home&a...mp;page=analyse pour avoir un aperçu. Si les algo (c'est encore des brouillons, mais ils marchent bien) t'interessent, mp. Lien à poster Partager sur d’autres sites More sharing options...
fabius Posté(e) 9 août 2008 Auteur Partager Posté(e) 9 août 2008 Merci à tous les deux pour vos réponses. /emoticons/biggrin@2x.png 2x" width="20" height="20"> C'est vrai que PHP permet beaucoup de choses. Pour ma part, j'ai finalement réussi à créer des images avec grads. Sinon, pour gérer la météo sur mon réseau, je lis directement dans un fichier binaire exporté de wgrib2 avec un petit script PHP. Comode: ton site est pas mal du tout. Si je peux me permettre, les courbes paressent très anguleuses. Peut-etre regarder avec des fonction non linéraires pour rendre plus arrondi ?? Sinon, je trouve qu'en général le site est très bien ! Pour plus de rapidité, je te conseille vivement de lire le fichier binaire plutot que fichier texte ASCII (àla sortie de wgrib2). Pour ma part, le script de lecture du fichier binaire met 15 sec avec un celeon pour toute la Terre et une resolution de 1° (juste pour donner une idée). Je veux bien jeter un coup d'oeil à tes algorithmes. Pour NCL, ça a l'air plus puissant que grads (je sais pas trop en fait) mais j'ai pas encore compris le fonctionnement. Si vous avez quelques pistes, je suis très intéressé /emoticons/happy@2x.png 2x" width="20" height="20"> ! Lien à poster Partager sur d’autres sites More sharing options...
Comode Posté(e) 20 août 2008 Partager Posté(e) 20 août 2008 Citation (fabius @ 9/08/2008 - 11:14) Merci à tous les deux pour vos réponses. C'est vrai que PHP permet beaucoup de choses. Pour ma part, j'ai finalement réussi à créer des images avec grads. Sinon, pour gérer la météo sur mon réseau, je lis directement dans un fichier binaire exporté de wgrib2 avec un petit script PHP. Comode: ton site est pas mal du tout. Si je peux me permettre, les courbes paressent très anguleuses. Peut-etre regarder avec des fonction non linéraires pour rendre plus arrondi ?? Sinon, je trouve qu'en général le site est très bien ! Pour plus de rapidité, je te conseille vivement de lire le fichier binaire plutot que fichier texte ASCII (àla sortie de wgrib2). Pour ma part, le script de lecture du fichier binaire met 15 sec avec un celeon pour toute la Terre et une resolution de 1° (juste pour donner une idée). Je veux bien jeter un coup d'oeil à tes algorithmes. Pour NCL, ça a l'air plus puissant que grads (je sais pas trop en fait) mais j'ai pas encore compris le fonctionnement. Si vous avez quelques pistes, je suis très intéressé ! En fait, ce n'est pas l'extraction des données le problème... C'est la création des cartes isobares globales (enfin isobares, mais aussi humidité, windshear, pluie, vortex...). Ma démarche consiste a d'abord créer un fichier PHP contenant une matrice globale (un tableau de 4Mo), ce qui permet de réutiliser simplement ces données sur d'autre site web juste en incluant le fichier. Ensuite vient un algo de marching square pour "dessiner" les courbes isobares, et c'est lui qui prend un max de temps... Je me permet de te donner l'intégralité d'une réadaptation d'un de mes scripts que j'utilise pour faire des découpes transversale dans les sorties grib2 de GFS... Ca reprend à peu près tout ce que j'ai écrit d'interessant sur le sujet... Donc c'est pas optimisé pour un sous (faut vraiment remplacer ces switch et mettre des callbacks), c'est pas non plus super propre, mais tout ça est expérimental (puisque je compte tout re-écrire en C pour la prochaine saison). En vrac, ça donne : Code ><?php $i = 0; if($_GET['help'] == 1) { echo " filename [url locale] : fichier source au format GRIB2 \n parametre [HGT|TMP|VVEL|ABSV|RH|CLWMR|...] : donnée a extraire\n filled [0|1] : 1 = graph plein, 0 = lignes\n longitude [0 -> +360] : Longitude en deg, entre 0 et 360\n latitude [-90 -> +90] : latitude en deg entre -90 et +90\n largeur [0 -> 360] : Nombre de mailles horieontales a partir de lon et lat (1pts = 0.5deg)\n hauteur [0 -> 90] : NE PAS UTILISER\n coef [numerique] : coefficient par lequel sera multiplié la valeur extraite\n echelle_min : Indique la valeur extraite minimum apres application du coef (les valeurs inférieur seront de la même couleurs)\n echelle_max : Indique la valeur maximum extraire apres application du coef (les valeurs supéreirus seront de la meme couleur)\n echelle_pas : pas de l'echelle\n verbose[0|1] : affiche le tableau genere output [url local] : fichier de sortie (jpg) "; exit; } if(strlen($_GET['filename'])) $filename = $_GET['filename']; else $filename = 'GFS2'; if(strlen($_GET['parametre'])) $parametre = $_GET['parametre']; else $parametre = 'TMP'; $tabpressure[] = array(); echo '/home/cyclone/www/wgrib2 /home/cyclone/www/GFS/'.$filename.' | grep ":'.$parametre.':" '."\n\n"; $res = shell_exec('/home/cyclone/www/wgrib2 /home/cyclone/www/GFS/'.$filename.' | grep ":'.$parametre.':" '); preg_match_all("[0-9]{1,4}) mb:", $res, $tp, PREG_SET_ORDER); foreach($tp as $val) $tabpressure[] = $val[1]; sort($tabpressure); if(strlen($_GET['filled'])) $filled = $_GET['filled']; else $filled = 0; if(strlen($_GET['longitude'])) $longitude = $_GET['longitude']; else $longitude = '290'; if(strlen($_GET['latitude'])) $latitude = $_GET['latitude']; else $latitude = '16'; if(strlen($_GET['output'])) $output = $_GET['output']; else $output = './out.jpg'; if(strlen($_GET['largeur'])) $largeur = $_GET['largeur']; else $largeur = '20'; if(strlen($_GET['hauteur'])) $hauteur = $_GET['hauteur']; else $hauteur = count($tabpressure); if(strlen($_GET['coef'])) $coef = $_GET['coef']; else $coef = '1'; if(strlen($_GET['echelle_min'])) $echelle_min = $_GET['echelle_min']; else $echelle_min = 0; if(!is_numeric($echelle_min)) $echelle_min = 0; if(strlen($_GET['echelle_max'])) $echelle_max = $_GET['echelle_max']; else $echelle_max = 100; if(!is_numeric($echelle_max)) $echelle_max = 100; if(strlen($_GET['echelle_pas'])) $echelle_pas = $_GET['echelle_pas']; else $echelle_pas = 1; if(!is_numeric($echelle_pas)) $echelle_pas = 1; echo "* * * * * * * * * * * PARAMETRES * * * * * * * * * * *\n\n"; echo "Fichier : $filename\n\nCoord depart : Lon$longitude Lat$latitude\nHauteur : $hauteur\nLargeur : $largeur\nParametre : $parametre\nEchelle $echelle_min a $echelle_max par pas de $echelle_pas\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"; $T = array(); $minimum_data = 9999999999; $maximum_data = -9999999999; foreach($tabpressure as $pressure) { if(is_numeric($pressure) && ($pressure*1) > 0) { echo "$pressure mb \n"; $i++; $res = shell_exec('/home/cyclone/www/wgrib2 /home/cyclone/www/GFS/'.$filename.' | grep ":'.$parametre.':" | grep ":'.$pressure.' mb:"'); $arr_res = array(); preg_match("#^([0-9]*):#is", $res, $arr_res); $id_pos = $arr_res[1]; $arr_res = array(); shell_exec('/home/cyclone/www/wgrib2 /home/cyclone/www/GFS/'.$filename.' -d '.$id_pos.' -lola '.$longitude.':'.$largeur.':0.5 '.$latitude.':1:0.5 /home/cyclone/www/GFS/hgt_file text'); $f = fopen('/home/cyclone/www/GFS/hgt_file', "r"); fgets($f); $j = 1; while(!feof($f)) { $t = fgets($f); $T[$i][$j] = (is_numeric(trim($t)*1) ? (trim($t)*$coef) : '0'); if($T[$i][$j] > $maximum_data) $maximum_data = $T[$i][$j]; if($T[$i][$j] < $minimum_data) $minimum_data = $T[$i][$j]; $j++; } fclose($f); } } $i++; $res = shell_exec('/home/cyclone/www/wgrib2 /home/cyclone/www/GFS/land.grib2 | grep ":LAND:"'); $arr_res = array(); preg_match("#^([0-9]*):#is", $res, $arr_res); $id_pos = $arr_res[1]; $arr_res = array(); shell_exec('/home/cyclone/www/wgrib2 /home/cyclone/www/GFS/land.grib2 -d '.$id_pos.' -lola '.$longitude.':'.$largeur.':0.5 '.$latitude.':1:0.5 /home/cyclone/www/GFS/hgt_file text'); $f = fopen('/home/cyclone/www/GFS/hgt_file', "r"); fgets($f); $j = 1; while(!feof($f)) { $t = fgets($f); $T[$i][$j] = $t * 1 ? 1 : 0; $j++; } fclose($f); echo "Done\n".$minimum_data.' => '.$maximum_data."\n"; if($_GET['verbose'] == 1) { print_r($T); echo "-----------------------------------------------------\n"; } class hgt { var $matrice = false; var $img = false; var $resolution = 10; var $largeur = 0;//91; var $hauteur = 0;//26; var $echelle_pas = 5; var $echelle_min = 0; var $echelle_max = 100; var $minval = 999999999; var $maxval = -999999999; var $tab_color = array( 0 => array(230, 255, 255), 1 => array(210, 240, 255), 2 => array(190, 230, 255), 3 => array(160, 220, 255), 4 => array(130, 200, 255), 5 => array(100, 150, 255), 6 => array(100, 100, 60), 7 => array(200, 100, 60), 8 => array(200, 150, 60), 9 => array(200, 200, 0), 10 => array(255, 0, 0), ); function color_pression($vor) { if($vor > $this->maxval) $this->maxval = $vor; if($vor < $this->minval) $this->minval = $vor; $val = round((($vor - $this->echelle_min) / ($this->echelle_max - $this->echelle_min)) * 255); if($val < 0 || $val > 255) return array(255, 0, 0); return array(round($val), 0, 255 - round($val)); } function hgt(&$matrice, $min, $max, $pas, $filled = false) { $this->echelle_min = $min; $this->echelle_max = $max; $this->echelle_pas = $pas; $this->filled = $filled ? true : false; $this->largeur = count($matrice[1]); $this->hauteur = count($matrice); $this->img = imagecreatetruecolor($this->largeur * $this->resolution, ($this->hauteur * $this->resolution) + $this->resolution); $bgcolor = imagecolorallocate($this->img, 255, 255, 255); imagefill($this->img, 0, 0, $bgcolor); $this->matrice = $matrice;//array(); } function DrawPetitCarre($x , $y, $taille, $hg, $hd, $bg, $bd, $r, $g, $ { $color = imagecolorallocate($this->img, $r, $g, $; $test = ($hg ? 1 : 0).($hd ? 1 : 0).($bg ? 1 : 0).($bd ? 1 : 0); $demi = $taille / 2; switch($test) { case '0000':break; case '0001': imageline($this->img, $x + $demi, $y + $taille, $x + $taille, $y + $demi, $color);break; case '0010': imageline($this->img, $x, $y + $demi, $x + $demi, $y + $taille, $color);break; case '0011': imageline($this->img, $x, $y + $demi, $x + $taille, $y + $demi, $color);break; case '0100': imageline($this->img, $x + $demi, $y, $x + $taille, $y + $demi, $color);break; case '0101': imageline($this->img, $x + $demi, $y, $x + $demi, $y + $taille, $color);break; case '0110': imageline($this->img, $x, $y + $demi, $x + $demi, $y, $color);imageline($this->img, $x + $demi, $y + $taille, $x + $taille, $y + $demi, $color);break; case '0111': imageline($this->img, $x, $y + $demi, $x + $demi, $y , $color);break; case '1000': imageline($this->img, $x, $y + $demi, $x + $demi, $y, $color);break; case '1001': imageline($this->img, $x + $demi, $y, $x + $taille, $y + $demi, $color);imageline($this->img, $x, $y + $demi, $x + $demi, $y + $taille, $color);break; case '1010': imageline($this->img, $x + $demi, $y, $x + $demi, $y + $taille, $color);break; case '1011': imageline($this->img, $x + $demi, $y, $x + $taille, $y + $demi, $color);break; case '1100': imageline($this->img, $x, $y + $demi, $x + $taille, $y + $demi, $color);break; case '1101': imageline($this->img, $x + $demi, $y + $taille, $x , $y + $demi, $color);break; case '1110': imageline($this->img, $x + $demi, $y + $taille, $x + $taille , $y + $demi, $color);break; case '1111':break; } } function DrawFilledPetitCarre($x , $y, $taille, $hg, $hd, $bg, $bd, $r, $g, $ { $color = imagecolorallocate($this->img, $r, $g, $; $test = ($hg ? 1 : 0).($hd ? 1 : 0).($bg ? 1 : 0).($bd ? 1 : 0); $demi = $taille / 2; switch($test) { case '0000': imagefilledrectangle($this->img, $x, $y, $x + $taille, $y + $taille, $color); break; case '0001': imagefilledpolygon($this->img, array($x, $y, $x, $y + $taille, $x + $demi, $y + $taille, $x + $taille, $y + $demi, $x + $taille, $y), 5, $color); /*imageline($this->img, $x + $demi, $y + $taille, $x + $taille, $y + $demi, $color2);*/break; case '0010': imagefilledpolygon($this->img, array($x, $y, $x, $y + $demi, $x + $demi, $y + $taille, $x + $taille, $y + $taille, $x + $taille, $y), 5, $color); /*imageline($this->img, $x, $y + $demi, $x + $demi, $y + $taille, $color);*/break; case '0011': imagefilledrectangle($this->img, $x, $y, $x + $taille, $y + $demi, $color);/*imageline($this->img, $x, $y + $demi, $x + $taille, $y + $demi, $color);*/break; case '0100': imagefilledpolygon($this->img, array($x, $y, $x + $demi, $y, $x + $taille, $y + $demi, $x + $taille, $y + $taille, $x, $y + $taille), 5, $color);/*imageline($this->img, $x + $demi, $y, $x + $taille, $y + $demi, $color);*/break; case '0101': imagefilledrectangle($this->img, $x , $y, $x + $demi, $y + $taille, $color);/*imageline($this->img, $x + $demi, $y, $x + $demi, $y + $taille, $color);*/break; case '0110': imagefilledpolygon($this->img, array($x, $y, $x + $demi, $y, $x + $taille, $y + $demi, $x + $taille, $y + $taille, $x + $demi, $y + $taille, $x, $y + $demi), 6, $color);/*imageline($this->img, $x, $y + $demi, $x + $demi, $y, $color);imageline($this->img, $x + $demi, $y + $taille, $x + $taille, $y + $demi, $color);*/break; case '0111': imagefilledpolygon($this->img, array($x, $y + $demi, $x + $demi, $y, $x, $y ), 3, $color);/*imageline($this->img, $x, $y + $demi, $x + $demi, $y , $color);*/break; case '1000': imagefilledpolygon($this->img, array($x, $y + $demi, $x + $demi, $y, $x + $taille, $y, $x + $taille, $y + $taille, $x, $y + $taille), 5, $color);/*imageline($this->img, $x, $y + $demi, $x + $demi, $y, $color);*/break; case '1001': imagefilledpolygon($this->img, array($x + $demi, $y, $x + $taille, $y, $x + $taille, $y + $demi, $x + $demi, $y + $taille, $x, $y + $taille, $x, $y + $demi), 6, $color);/*imageline($this->img, $x + $demi, $y, $x + $taille, $y + $demi, $color);imageline($this->img, $x, $y + $demi, $x + $demi, $y + $taille, $color);*/break; case '1010': imagefilledrectangle($this->img, $x + $demi, $y, $x + $taille, $y + $taille, $color);/*imageline($this->img, $x + $demi, $y, $x + $demi, $y + $taille, $color);*/break; case '1011': imagefilledpolygon($this->img, array($x + $demi, $y, $x + $taille, $y + $demi, $x + $taille, $y), 3, $color);/*imageline($this->img, $x + $demi, $y, $x + $taille, $y + $demi, $color);*/break; case '1100': imagefilledrectangle($this->img, $x, $y + $demi, $x + $taille, $y + $taille , $color);/*imageline($this->img, $x, $y + $demi, $x + $taille, $y + $demi, $color);*/break; case '1101': imagefilledpolygon($this->img, array($x + $demi, $y + $taille, $x , $y + $demi, $x, $y + $taille ), 3, $color);/*imageline($this->img, $x + $demi, $y + $taille, $x , $y + $demi, $color);*/break; case '1110': imagefilledpolygon($this->img, array($x + $demi, $y + $taille, $x + $taille, $y + $demi, $x + $taille, $y + $taille ), 3, $color);/*imageline($this->img, $x + $demi, $y + $taille, $x + $taille , $y + $demi, $color);*/break; case '1111':break; } } function Render() { if($this->filled) { for($val=$this->echelle_min;$val<=$this->echelle_max;$val+=$this->echelle_pas) { list($cR, $cG, $cB) = $this->color_pression($val); for($i=0.5;$i<$this->largeur-1;$i++)//for($i=round($x_from)+0.5;$ihauteur-2;$j++)//for($j=round($y_from)+0.5;$jDrawFilledPetitCarre(($i*$this->resolution) + ($this->resolution/2) , ($j * $this->resolution) + ($this->resolution / 2), $this->resolution, (abs($this->matrice[floor($j)][floor($i)]) < $val ? 1 : 0), (abs($this->matrice[floor($j)][ceil($i)]) < $val ? 1 : 0), (abs($this->matrice[ceil($j)][floor($i)]) < $val ? 1 : 0), (abs($this->matrice[ceil($j)][ceil($i)]) < $val ? 1 : 0), $cR, $cG, $cB//$val == 5 ? 255 : 0, $val == 9 ? 255 : 0, $val == 1 ? 255 : 0 ); } } } } else { for($val=$this->echelle_min;$val<=$this->echelle_max;$val+=$this->echelle_pas) { list($cR, $cG, $cB) = $this->color_pression($val); for($i=0.5;$i<$this->largeur-1;$i++)//for($i=round($x_from)+0.5;$ihauteur-2;$j++)//for($j=round($y_from)+0.5;$jDrawPetitCarre(($i*$this->resolution) + ($this->resolution/2) , ($j * $this->resolution) + ($this->resolution / 2), $this->resolution, (abs($this->matrice[floor($j)][floor($i)]) < $val ? 1 : 0), (abs($this->matrice[floor($j)][ceil($i)]) < $val ? 1 : 0), (abs($this->matrice[ceil($j)][floor($i)]) < $val ? 1 : 0), (abs($this->matrice[ceil($j)][ceil($i)]) < $val ? 1 : 0), $cR, $cG, $cB//$val == 5 ? 255 : 0, $val == 9 ? 255 : 0, $val == 1 ? 255 : 0 ); } } } } for($i=0.5;$i<$this->largeur;$i++) { if($this->matrice[$this->hauteur][$i] == 1) $solmer = imagecolorallocate($this->img,0, 127, 0); else $solmer = imagecolorallocate($this->img,0, 0, 127); imagefilledrectangle($this->img, $this->resolution * ($i+0.5), ($this->hauteur - 1) * $this->resolution, $this->resolution * ($i+1.5), $this->hauteur * $this->resolution, $solmer ); } } function HtmlRenderMatrice() { $texte = '</pre> <table style="border-collapse:collapse;">'.$valy.'</table>'; return $texte; } } echo "Creation de l'image...\n"; $iso = new hgt($T, $echelle_min, $echelle_max, $echelle_pas, $filled); $iso->Render(); $resolution = $iso->resolution; $haut = $iso->hauteur; $large = $iso->largeur; $tmpcolor = imagecolorallocate($iso->img, 0, 127, 0); imagettftext($iso->img, 8, 0, 1, 9, $tmpcolor, './arial.ttf', $parametre.' - '.$longitude.'°EW '.$latitude.'°NS sur '.($largeur * 0.5).'°W Ordon. en mb'); $i = 1; $tmpcolor = imagecolorallocate($iso->img, 0, 0, 0); imagefilledrectangle($iso->img, 0, 10, 25, ($resolution * $haut), $tmpcolor); $tmpcolor = imagecolorallocate($iso->img, 255, 255, 255); foreach($tabpressure as $val) { if($i >1 && is_numeric($val)) imagettftext($iso->img, 8, 0, 1, ($i * $resolution), $tmpcolor, './arial.ttf', $val.' '); $i++; } function SayLongitude($val) { $val %= 360; if($val > 180) { return round(360 - $val,1).'W'; } else { return round($val, 1).'E'; } } $tmpcolor = imagecolorallocate($iso->img, 255, 255, 255); for($i=0;$i < ($large * $resolution); $i+=60) { if($i > 0) imagettftext($iso->img, 9, 0, $i, ($haut * $resolution)-1, $tmpcolor, './arial.ttf', SayLongitude(($longitude + (( $large / (($large * $resolution) / $i)) * 0.5) )).'°'); else imagettftext($iso->img, 9, 0, $i, ($haut * $resolution)-1, $tmpcolor, './arial.ttf', SayLongitude($longitude).'°'); } imagejpeg($iso->img, $output); echo "TERMINE !\n"; C'est fait pour être utilisé en mode console, et je n'ai pas mis de variable pour les chemin de fichier qu'il te faudra changer pour pouvoir en profiter. J'avais également re-écrit une version pour windows (qui ne connait pas les | grep), dispo à la demande. J'ai un peu honte aussi pour ma fonction Render ou j'ai honteusement dupliqué ma fonction pour ne pas coller un if() gourmand dans une double boucle. Enfin tout ça pour dire que c'est pas exempt de petites disgraces... Faudra que je prenne le temps d'écrire une vrai lib un de ces 4 Le résultat de ce script ressemble à ça (vertical velocity sur une coupe transversale de cyclone avec coloration des courbes de niveaux): PS : Après tests, sur de petites surface (genre l'atlantique nord), les temps de traitement du marching square sont de l'ordre de 5 à 10 secondes en PHP... Lien à poster Partager sur d’autres sites More sharing options...
fabius Posté(e) 11 septembre 2008 Auteur Partager Posté(e) 11 septembre 2008 Sympa comme résultat ! Le script est très bien pensé. Perso, j'ai réécris mon script PHP qui lit dans les fichiers binaires de sortie de -lola en Java qui me fais gagner 50% du temps d'exécution sur le script PHP que voilà : Code #!/usr/bin/php <?php error_reporting(E_ALL); define('COORDBOXESIZE', 1); define('DATADIR', "dataset"); # files to read $fn_index = DATADIR.'/last.bin.index'; $fn_bin = DATADIR.'/last.bin'; # --- NO NEED TO MODIFY BELOW --- # # contient les infos $index = array(); $index_out = array(); $fp = fopen($fn_index, 'r'); while(!feof($fp)) { $l = trim(fgets($fp)); $a = explode(':', $l); if(count($a) === 7) { $index[] = array($a[3], $a[4], $a[5]); $index_out[$a[4]][] = $a[3]; } unset($l, $a); } fclose($fp); # # # DATA : $lat =-90+COORDBOXESIZE/2; $lon = -180+COORDBOXESIZE/2; $nbr_lon = 360/COORDBOXESIZE; $nbr_lat = 180/COORDBOXESIZE; $correct_file = false; $point_num=0; $count_index = count($index); # $nbr_points = $nbr_lon * $nbr_lat; $fp = fopen($fn_bin, 'rb'); for($lat; $lat <= 90; $lat += COORDBOXESIZE) { for($lon; $lon <= 180; $lon += COORDBOXESIZE) { //---------------------------------------------------------------BeginningOfMessage $data = array(); for($n=0; $n < $count_index; $n++) { $val = unpack('f', fread($fp, 4)); $type = $index[$n][0]; $level = $index[$n][1]; $time = $index[$n][2]; $data[$level][$type] = (float)$val[1]; # returning at top position if(fseek($fp, 4*$nbr_points-4, SEEK_CUR) === -1 || feof($fp)) die('## fseek/foef failed on line '. __LINE__ ."\n"); } /* print_r($data); exit;/* debug */ $empty = array(); $empty[] = 0; $empty[] = 0; $empty[] = 0; $clouds = array('H'=>$empty,'M'=>$empty,'L'=>$empty,'C'=>$empty); echo sprintf('%+.2f',$lat).':'.sprintf('%+.2f',$lon); reset($index_out); while(list($k,$v)=each($index_out)) { if($k === "surface") { # Precipitation Rate [kg/m^2/s]*3600 = mm/hour (1L=1dm^3) (1mm<=>1L) $prate = $data[$k]['PRATE']*3600; //unit: mm/hour if($prate > 0) { echo ' P'; echo sprintf("%.2f", $prate); # Precipitation type if((float)$data[$k]['CRAIN'] != 0) echo 'R'; if((float)$data[$k]['CSNOW'] != 0) echo 'S'; if((float)$data[$k]['CFRZR'] != 0) echo 'F'; if((float)$data[$k]['CICEP'] != 0) echo 'I'; } } elseif(ereg('cloud', $k)) { if(isset($data[$k]['PRES'])) { $pres = (int) (((float)$data[$k]['PRES'])/100); // --top level-- if($k === "high cloud top level") { $clouds['H'][0] = $pres; } elseif($k === "middle cloud top level") { $clouds['M'][0] = $pres; } elseif($k === "low cloud top level") { $clouds['L'][0] = $pres; } //- -bottom level-- elseif($k === "high cloud bottom level") { $clouds['H'][1] = $pres; } elseif($k === "middle cloud bottom level") { $clouds['M'][1] = $pres; } elseif($k === "low cloud bottom level") { $clouds['L'][1] = $pres; } } elseif(isset($data[$k]['TCDC'])) { $p = (int) $data[$k]['TCDC']; if($p > 100) $p = 0; // prevent from using an undefined value (unknown = no clouds) if($p > 99) $p = 99; if($k === "high cloud layer") { $clouds['H'][2] = $p; } elseif($k === "middle cloud layer") { $clouds['M'][2] = $p; } elseif($k === "low cloud layer") { $clouds['L'][2] = $p; } elseif($k === "convective cloud layer") { $clouds['C'][2] = $p; } } } else { list($lev, $unit) = explode(' ', $k); if($unit === "mb") { //--compulsory fields # Level information (in mb/10) echo sprintf(" %d", $lev/10); # Temperature (2 digits with sign) $tmp = (int)($data[$k]['TMP']-273+0.5); if($tmp > 99) $tmp = 99; if($tmp < 0) echo '-'; else echo '+'; echo sprintf("%02d", abs($tmp)); # Wind $u = (float)$data[$k]['UGRD']; $v = (float)$data[$k]['VGRD']; $spd = sqrt(pow($u, 2) + pow($v, 2)); $spd *= 1.943861286; if($u == 0) $dir = $v < 0 ? -pi()/2 : pi()/2; else $dir = atan($v/$u); if($u < 0) $dir += pi(); $dir = (int) (630 - rad2deg($dir))%360; // 630=90+360+180 (+180 because vetor shows what the wind does, not were it is coming from) if($spd > 299) { echo sprintf('%03dPP%02d', $dir, 99); } elseif($spd > 199) { echo sprintf('%03dPP%02d', $dir, $spd-200); } elseif($spd > 99) { echo sprintf('%03dP%02d', $dir, $spd-100); } else { echo sprintf('%03d%02d', $dir, $spd); } //--optional fields # Relative humidity if(isset($data[$k]['RH'])) { $rh = (int)$data[$k]['RH']; if($rh > 99) $rh = 99; if($rh != 0) echo sprintf('%02d', $rh); } # Cloud Mixing Ratio [mg/kg] if(isset($data[$k]['CLWMR'])) { $cmr = (int) ($data[$k]['CLWMR'] * 1e6); if($cmr != 0) echo sprintf('C%d', $cmr); } } elseif($lev === "mean") { $qnh = $data[$k]['PRMSL']/100; echo sprintf(' Q%.1f', $qnh); } } } $list = array('L','M','H','C'); $first = true; foreach($list as $k) { $v = $clouds[$k]; if($v[0] > 0 && $v[1] > 0 && $v[2] > 0 && ((float)$v[0]) * ((float)$v[1]) * ((float)$v[2]) !== 0) { if($first) echo ' '; if($k === 'C') echo $k.sprintf('%02d', $v[2]); else echo $k.sprintf('%04d%04d%02d', $v[0], $v[1], $v[2]); $first = false; } } echo "\n";/* end of line -> new line */ # Moving to next point $point_num++; if(fseek($fp, 4*$point_num) === -1) die('## fseek failed on line '. __LINE__ ." (moving to next point)\n"); //-----------------------------------------------------------------EndOfMessage } $lon = -180+COORDBOXESIZE/2; } fclose($fp); ?> Bon, le script ci-dessus lit sur la Terre entière avec une résolution de 1° (changeable en fonction de la commande lola) et donne en sortie un META format que mon serveur météo sait lire Si ça peut te donner des idées En ce moment, IKE fait des ravages Lien à poster Partager sur d’autres sites More sharing options...
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant