Richard Suchenwirth 2002-05-15: The following code gets maps of predicted precipitation (for North Atlantic, Europe, and parts of adjacent continents) for the next 15 days, in 12 hour steps, from a German weather station via HTTP and displays them in a canvas.
DKF 2003-06-27: This code no longer works because the site no longer provides the data (or at least not in the same way...?)
RS: fixed, runs again :)
proc cycle listName { upvar 1 $listName list set res [lindex $list 0] set list [concat [lrange $list 1 end] [list $res]] } proc every {ms body} {eval $body; after $ms [namespace code [info level 0]]} package require http # http::config -proxyhost proxy -proxyport 80 set prefix http://129.13.102.67/pics/Rtavn ;# fixed set suffix 4.gif pack [canvas .c -width 800 -height 680] -expand 1 -fill both wm title . Loading... for {set i 12} {$i<=504} {incr i 12} { set gif [http::data [http::geturl $prefix$i$suffix]] if ![catch {lappend ims [image create photo im$i -data $gif]}] { .c create image 0 0 -anchor nw -image im$i -tag im$i } } wm title . Film bind . q exit bind . <Control-c> exit every 1000 {.c raise [lindex [cycle ::ims] 0]}
KBK: I found that the above caused my Windows desktop to, uhhhm, "become unresponsive." Apparently, the Windows implementation, at least on my machine, can't cope with 32 images of that size inside a canvas at once.
Changing so that the canvas has only two image objects and loading them in alternation helps a lot. (It also allows the animation to start while the images are still downloading, if done right.) Here's an alternative implementation:
proc every {ms body} {eval $body; after $ms [namespace code [info level 0]]} proc cycleImages { } { variable ims variable imsIndex variable buffer if { [llength $ims] > 0 } { .c raise buffer$buffer wm title . "image $imsIndex" set buffer [expr { 2 - $buffer }] incr imsIndex if { $imsIndex >= [llength $ims] } { set imsIndex 0 } .c itemconfig buffer$buffer -image [lindex $ims $imsIndex] } } proc loadImage { i } { variable prefix variable suffix if { $i > 504 } return http::geturl $prefix$i$suffix -command [list loadFinished $i] } proc loadFinished { i token } { variable ims lappend ims [image create photo -data [http::data $token]] http::cleanup $token after 0 [list loadImage [expr { $i + 12 }]] } package require http # http::config -proxyhost webcache -proxyport 8080 set prefix http://129.13.102.67/pics/Rvtmrf set suffix 4.gif pack [canvas .c -width 800 -height 680 -bg white] -expand 1 -fill both .c create image 10 10 -anchor nw -tag buffer1 .c create image 10 10 -anchor nw -tag buffer2 set ims {} set imsIndex 0 set buffer 1 bind . q exit bind . <Control-c> exit every 1000 cycleImages loadImage 12
DKF: Now, I'm lucky enough to have a machine big enough to take all the images, but I don't like the way that they load; I'd like to issue a bunch of HTTP requests at once and get things back ASAP (I'm on quite a big network pipe here) so I do something like this (min. Tcl version 8.4):
package require http # http::config -proxyhost proxy -proxyport 80 proc every {ms body} {eval $body; after $ms [namespace code [info level 0]]} set prefix http://129.13.102.67/pics/Rvtmrf set suffix 4.gif set ims {} pack [canvas .c -width 800 -height 680] -expand 1 -fill both wm title . Loading... update set throttle 6 set cmds {} proc loadImage {i step limit} { global prefix suffix if { $i > $limit } return loadImageCore $prefix$i$suffix after 150 loadImage [expr {$i + $step}] $step $limit } proc loadImageCore {url} { global ims cmds throttle set l [llength $ims] lappend ims {} if {$throttle < 1} { lappend cmds [list \ http::geturl $url -command [list loadFinished $l]] } else { incr throttle -1 http::geturl $url -command [list loadFinished $l] } } proc loadFinished { l token } { global ims throttle incr throttle set image [image create photo -data [http::data $token]] lset ims $l [.c create image 0 0 -anchor nw -image $image] http::cleanup $token after 1000 anotherCommand } proc anotherCommand {} { global cmds if {[llength $cmds]} { set cmd [lindex $cmds 0] set cmds [lrange $cmds 1 end] uplevel #0 $cmd } } set idx 0 proc cycleImage {} { global ims idx set item [lindex $ims $idx] if {$item ne {}} { .c raise $item } if {[incr idx] >= [llength $ims]} { set idx 0 } } every [expr {1000/15}] {cycleImage} loadImage 12 12 504 wm title . Film bind . q exit bind . <Control-c> exit
Alas, asynchronous HTTP has quite a hefty synchronous start-up phase on this system. :^(
Multiply your possibilities by changing the trailing digit in the URL (4.gif above):
'Nother massive source of weather data is METAR [L1 ]. Not predictive but reporting current conditions (hourly, I think). Using a well-defined textual dataset with lines such as:
KCPC 190751Z AUTO 00000KT 10SM SCT015 OVC110 21/19 A3016 RMK AO2 705
That's an airport code, timecode, and then al sorts of weather info. There are several sources of collected data, e.g. [L2 ].
jcs: Hmm.... are there any contour plot solutions for Tcl?
RS: Iain Findleton reported that he is using the turtle graphics code from Turtleshell, which was intended more as demo for kids, to plot weather maps which he receives in relative coordinates...
AM: Believe it or not: Vince Darley maintains Plplot ("Plplotter" widget) at [L3 ], a package that does that sort of plots.
jcw: (Now at [L4 ], Vince adds that the 'plplot' sourceforge project has the Plplotter code partially integrated into the main branch of plplot, but the TEA configure/build stuff is in a 'tea' branch off the main project branch. Unfortunately TEA was such a disaster that everyone's patience was exhausted before the code could get incorporated into the main tree. It is a very nice plotting widget, however! (I've used it both for my thesis work and in a commercial product). A binary release of plplot for Windows is available .
jcw: As for parsing METAR data files - turns out that it has already been done, see Jason Tang's TclWeather. Good.
MPJ: I have been using TclWeather for a couple of months now (even works behind a proxy). You may also want to see his stock ticker, TclStock, application.
The 4-letter "ICAO identifiers" define each airport, there's a list with some 6000 entries along with names and longitude/latitude at [L5 ] (about 500 Kb ascii, field description at [L6 ]).
jcw: One could take TclWorld, fetch current temperatures on there, and then draw a contour plot... hmm, that could be fun
Jason Tang: Indeed, I have written an applet that downloads and parses the METAR data for nearly any place on the planet. I haven't finished cleaning up and documenting TclWeather yet; it'll be ready Real Soon Now(tm). It uses my lexical scanner, (insert plug here) fickle to break down a METAR report into its individual parts. Update: Go to TclWeather.