# ---------------------------------------------------------------------- # HUBZERO: server for VMD # # This program runs VMD and acts as a server for client applications. # ---------------------------------------------------------------------- # Michael McLennan (mmclennan@purdue.edu) # ====================================================================== # Copyright (c) 2013 - HUBzero Foundation, LLC # ====================================================================== # The VMD TCL interpreter is by default interactive. Turn this off # so that unknown commands like "scene" don't get exec-ed. set ::tcl_interactive 0 proc bgerror {mesg} { puts stderr "SERVER ERROR: $mesg" } # parse command line args set Paradigm "socket" while {[llength $argv] > 0} { set opt [lindex $argv 0] set argv [lrange $argv 1 end] switch -- $opt { -socket { set Paradigm "socket" } -stdio { set Paradigm "stdio" } default { puts stderr "bad option \"$opt\": should be -socket or -stdio" } } } # use this to take snapshots to send to clients image create photo SnapShot # set the screen to a good size set DisplaySize(w) 300 set DisplaySize(h) 300 display resize $DisplaySize(w) $DisplaySize(h) set DisplaySize(changed) 0 # capture initial display settings for later reset display antialias on set DisplayProps(options) "" foreach key { ambientocclusion antialias aoambient aodirect backgroundgradient culling cuestart cueend cuedensity cuemode depthcue distance eyesep farclip focallength height nearclip projection shadows stereo } { if {$key eq "nearclip" || $key eq "farclip"} { append DisplayProps(options) [list display $key set [display get $key]] "\n" } else { append DisplayProps(options) [list display $key [display get $key]] "\n" } } # initialize work queue and epoch counter (see server_send_image) set Epoch 0 set Work(queue) "" set Sendqueue "" set Scenes(@CURRENT) "" set tmpDir "" set parser [interp create -safe] foreach cmd { axes color gettimestep graphics imd label vmd_label light material measure mobile mol molinfo molecule mouse parallel plugin rawtimestep render rotate rotmat scale vmd_scale spaceball stage tkrender tool translate user vecadd veccross vecdist vecdot vecinvert veclength veclength2 vecmean vecmul vecnorm vecscale vecscale vecstddev vecsub vecsum veczero vmdcollab vmdcon vmdinfo vmdbench volmap } { $parser alias $cmd $cmd } # ---------------------------------------------------------------------- # USAGE: display option ?arg arg...? # # Executes the "command arg arg..." string in the server and substitutes # the result into the template string in place of each "%v" field. # Sends the result back to the client. # ---------------------------------------------------------------------- proc cmd_display {args} { set option [lindex $args 0] if {[lsearch {resize reposition rendermode update fps} $option] >= 0} { # ignore these commands -- they cause trouble return "" } eval display $args } $parser alias display cmd_display # ---------------------------------------------------------------------- # USAGE: tellme "command template with %v" command arg arg... # # Executes the "command arg arg..." string in the server and substitutes # the result into the template string in place of each "%v" field. # Sends the result back to the client. # ---------------------------------------------------------------------- proc cmd_tellme {fmt args} { global parser client # evaluate args as a command and subst the result in the fmt string if {[catch {$parser eval $args} result] == 0} { server_send_result $client "nv>[string map [list %v $result] $fmt]" } else { server_oops $client $result } } $parser alias tellme cmd_tellme $parser alias set_temporary_directory server_set_temporary_directory # ---------------------------------------------------------------------- # USAGE: queryinfo ?-prev atomid atomid? # USAGE: queryinfo ?-prev atomid? # USAGE: queryinfo # # Picks the atom at screen coordinate , and returns information # about it. If one previous atom is specified, then this command # returns the bond length between the previous atom and the current # one. If two previous atoms are specified, then it returns the # angle between the three atoms. # ---------------------------------------------------------------------- proc cmd_queryinfo {x y args} { global DisplayProps MolNames MolInfo # handle command arguments set prevatoms "" while {[llength $args] > 0} { set option [lindex $args 0] set args [lrange $args 1 end] if {$option eq "-prev"} { while {[llength $args] > 0} { set val [lindex $args 0] if {[regexp {^[0-9]} $val]} { lappend prevatoms $val set args [lrange $args 1 end] } else { break } } } else { error "bad option \"$option\": should be -prev" } } # be careful -- VMD uses coordinates from LOWER-left corner of window set vmdy [expr {$DisplayProps(frameh)-$y}] set vals [pick $x $vmdy] if {$vals ne ""} { array set data $vals # map the molecule ID back to the name used within MD Showcase foreach molname $MolNames { if {$MolInfo($molname) == $data(mol)} { set data(molname) $molname break } } # pass back the click coord on screen so we know where this came from set data(screenx) $x set data(screeny) $y # if there are -prev atoms, query extra info set curr [list $data(index) $data(mol)] set meas $prevatoms set i [lsearch -exact $meas $curr] if {$i >= 0} { set meas [lreplace $meas $i $i] } set meas [linsert $meas 0 $curr] set meas [lrange $meas 0 2] switch -- [llength $meas] { 2 { set data(bondlength) [measure bond $meas] } 3 { set data(bondlength) [measure bond [lrange $meas 0 1]] set data(bondlength2) [measure bond [lrange $meas 1 2]] set data(angle) [measure angle $meas] } } # convert data back to return value set vals [array get data] } return $vals } $parser alias queryinfo cmd_queryinfo # ---------------------------------------------------------------------- # USAGE: resize # # Resizes the visualization window to the given width and height # . The next image sent should be this size. # ---------------------------------------------------------------------- proc cmd_resize {w h} { global DisplayProps # store the desired size in case we downscale set DisplayProps(framew) $w set DisplayProps(frameh) $h server_safe_resize $w $h } $parser alias resize cmd_resize # ---------------------------------------------------------------------- # USAGE: setview ?-rotate ? ?-scale ? ?-center ? ?-global ? # # Sets the view matrix for one or more components of the view. This # is a convenient way of getting a view for a particular frame just # right in one shot. # ---------------------------------------------------------------------- proc cmd_setview {args} { if {[llength $args] == 8} { # setting all matrices? then start clean display resetview } foreach {key val} $args { switch -- $key { -rotate { molinfo top set rotate_matrix [list $val] } -scale { molinfo top set scale_matrix [list $val] } -center { molinfo top set center_matrix [list $val] } -global { molinfo top set global_matrix [list $val] } default { error "bad option \"$key\": should be -rotate, -scale, -center, or -global" } } } } $parser alias setview cmd_setview # ---------------------------------------------------------------------- # USAGE: drag start|end # # Resizes the visualization window to the given width and height # . The next image sent should be this size. # ---------------------------------------------------------------------- proc cmd_drag {action} { global DisplayProps switch -- $action { start { # simplify rendering so it goes faster during drag operations set neww [expr {round($DisplayProps(framew)/2.0)}] set newh [expr {round($DisplayProps(frameh)/2.0)}] server_safe_resize $neww $newh display rendermode Normal display shadows off if 0 { foreach nmol [molinfo list] { set max [molinfo $nmol get numreps] for {set nrep 0} {$nrep < $max} {incr nrep} { mol modstyle $nrep $nmol "Lines" } } } } end { # put original rendering options back server_safe_resize $DisplayProps(framew) $DisplayProps(frameh) display rendermode $DisplayProps(rendermode) display shadows $DisplayProps(shadows) if 0 { # restore rendering methods for all representations foreach nmol [molinfo list] { set max [molinfo $nmol get numreps] for {set nrep 0} {$nrep < $max} {incr nrep} { mol modstyle $nrep $nmol $DisplayProps(rep-$nmol-$nrep) } } } } default { error "bad option \"$action\": should be start or end" } } } $parser alias drag cmd_drag # ---------------------------------------------------------------------- # USAGE: setquality normal|high # # Sets the rendering quality for the scene--either "high" (GLSL) or # normal. # ---------------------------------------------------------------------- proc cmd_setquality {newval} { global DisplayProps switch -- $newval { high { display rendermode GLSL set DisplayProps(rendermode) "GLSL" } normal { display rendermode Normal set DisplayProps(rendermode) "Normal" } default { error "bad quality value \"$newval\": should be normal or high" } } } $parser alias setquality cmd_setquality # ---------------------------------------------------------------------- # USAGE: smoothreps # # Changes the smoothing factor for all representations of the current # molecule. # ---------------------------------------------------------------------- proc cmd_smoothreps {val} { if {$val < 0} { error "bad smoothing value \"$val\": should be >= 0" } foreach nmol [molinfo list] { set max [molinfo $nmol get numreps] for {set nrep 0} {$nrep < $max} {incr nrep} { mol smoothrep $nmol $nrep $val } } } $parser alias smoothreps cmd_smoothreps # ---------------------------------------------------------------------- # USAGE: animate