## APBS Run 1.1
##
## GUI plugin for APBS. More info on APBS can be found at
##
##
## Authors: Eamon Caddigan and John Stone
## vmd@ks.uiuc.edu
##
## $Id: apbsrun.tcl,v 1.101 2005/12/07 23:02:10 johns Exp $
##
## TODO:
## * Load charges and radii from ff-parameter files better.
## * User-defined ff-parameter file location.
## * Specify which molecule maps should be loaded into upon completion.
## * Real modal dialogs -- stop stealing focus from other VMD plugins.
## * In main window, display descriptive names for ELEC statements (e.g.,
## molecule and calculation type) instead of simply displaying their
## indecies.
## * Kill APBS on windows.
## * User-defined map names for write statements (also prevent clobbering).
## * GUI elements for counterion declarations, calcenergy, calcforce,
## writemat, usemap.
## * Display new molecules in drop-down menus immediately after loading them.
## * Progress bar during run (by parsing io.mc?).
## * New defaults.
##
## Example code to add this plugin to the VMD extensions menu:
##
# if { [catch {package require apbsrun} msg] } {
# puts "VMD APBSRun package could not be loaded:\n$msg"
# } elseif { [catch {menu tk register "apbsrun" apbsrun} msg] } {
# puts "VMD APBSRun could not be started:\n$msg"
# }
## Tell Tcl that we're a package and any dependencies we may have
package provide apbsrun 1.1
package require Tcl 8.4
package require exectool
namespace eval ::APBSRun:: {
namespace export apbsrun
# window handles
variable main_win ;# handle to main window
variable elec_win ;# handle to elec-statement editing window
variable settings_win ;# handle to settings window
variable map_win ;# handle to map-loading window
# global settings
variable elec_listbox ;# the listbox displaying the elec statements
variable elec_list ;# a list containing the elements of elec_listbox
variable elec_index ;# next unused index for new elec_listbox elements
variable elec_current_index ;# elec item being edited
variable apbs_status ;# status of the current apbs run
variable apbs_button ;# text of the APBS Button
variable apbs_type ;# type of apbs run
# Default and user-edited apbs input information, stored as a hash with
# each key representing a "type" and each element consisting of a list
# of elec settings, where each elec setting is a list containing pairs of
# elements (for setting with 'array set')
variable default_apbs_config
variable current_apbs_config
variable elec_temp
# APBSRun Configuration variables
variable workdir
variable apbsbin
variable setup_only
variable use_dat_radii
variable use_dat_charges
variable datfile
variable apbs_input
variable ff_radii
variable ff_charges
variable pqrfiles
variable elec_keyword
variable molids
variable output_files
variable load_files
}
##
## Initialize the values, then launch the main window
##
proc ::APBSRun::apbsrun {} {
variable apbs_status
variable apbs_button
variable apbs_type
variable workdir
variable apbsbin
variable setup_only
variable use_dat_radii
variable use_dat_charges
variable datfile
variable ff_radii
variable ff_charges
variable file_list
set workdir [file join /tmp]
set apbsbin [::FinderTool::find apbs]
set setup_only 0
set use_dat_radii 0
set use_dat_charges 0
set apbs_status "Status: Ready"
set apbs_button "Run APBS"
set datfile [file join $::env(VMDDIR) plugins noarch tcl apbsrun1.1 radii.dat]
if { ![file exists $datfile] || [catch {set file [open $datfile]}] } {
puts "apbsrun: warning, can't find parameter file"
set datfile {}
} else {
# Load the radii and charges
while {-1 != [gets $file line]} {
if {![regexp {\s*#} $line]} {
set line [split $line \t]
set ff_radii([lindex $line 0],[lindex $line 1]) [lindex $line 3]
set ff_charges([lindex $line 0],[lindex $line 1]) [lindex $line 2]
}
}
close $file
}
# Maintain a list of VMD's molecules
::APBSRun::update_file_list
trace add variable ::vmd_initialize_structure write \
::APBSRun::update_file_list
# Set the default for all types
trace remove variable ::APBSRun::apbs_type write \
::APBSRun::update_elec_list
set apbs_type {}
::APBSRun::set_default
# Update the elec list every time the type is changed
trace add variable ::APBSRun::apbs_type write \
::APBSRun::update_elec_list
# Launch the main window
::APBSRun::apbs_mainwin
}
# Update the list of elec statements, to reflect the current type of APBS
# run
proc ::APBSRun::update_elec_list {args} {
variable elec_list
variable elec_index
variable current_apbs_config
variable apbs_type
set elec_list {}
for {set i 0} {$i < [llength $current_apbs_config($apbs_type)]} {incr i} {
if {[lindex $::APBSRun::current_apbs_config($apbs_type) $i] != {}} {
lappend elec_list $i
}
}
set elec_index $i
}
proc ::APBSRun::update_file_list {args} {
variable file_list
set file_list {}
# Append each loaded molecule to the list of files
# XXX - Omitting molecules without atoms or coordinates would be
# preferable, but the vmd_initialize_structure variable is only written
# when a new molecule is created, so there's no way to know what other
# information will be loaded into a molecule later
foreach molid [molinfo list] {
lappend file_list [concat $molid [molinfo $molid get name]]
}
# If there are no valid molecules loaded, add an empty item to the list
if { [llength $file_list] == 0 } {
lappend file_list {}
}
}
##
## Create the main window
##
proc ::APBSRun::apbs_mainwin {} {
variable main_win
variable elec_listbox
variable elec_list
variable elec_index
# If already initialized, just turn on
if { [winfo exists .apbsrun] } {
wm deiconify $main_win
return
}
set main_win [toplevel ".apbsrun"]
wm title $main_win "APBS Tool"
wm resizable $main_win yes yes
## make the menu bar
frame $main_win.menubar -relief raised -bd 2 ;# frame for menubar
pack $main_win.menubar -padx 1 -fill x -side top
menubutton $main_win.menubar.edit -text "Edit" -underline 0 \
-menu $main_win.menubar.edit.menu
# XXX - set menubutton width to avoid truncation in OS X
$main_win.menubar.edit config -width 5
pack $main_win.menubar.edit -side left
menubutton $main_win.menubar.help -text "Help" -underline 0 \
-menu $main_win.menubar.help.menu
# XXX - set menubutton width to avoid truncation in OS X
$main_win.menubar.help config -width 5
pack $main_win.menubar.help -side right
## edit menu
menu $main_win.menubar.edit.menu -tearoff no
$main_win.menubar.edit.menu add command -label "Settings..." \
-command ::APBSRun::apbs_settings
## help menu
menu $main_win.menubar.help.menu -tearoff no
$main_win.menubar.help.menu add command -label "About" \
-command {tk_messageBox -type ok -title "About apbsrun" \
-message "GUI for initiating APBS runs."}
$main_win.menubar.help.menu add command -label "Help..." \
-command "vmd_open_url [string trimright [vmdinfo www] /]/plugins/apbsrun"
## Main window
frame $main_win.edit
tk_optionMenu $main_win.edit.type ::APBSRun::apbs_type \
"Electrostatic Potential" "Solvent Accessibility" "Custom"
$main_win.edit.type config -width 25
pack $main_win.edit.type -fill x -expand yes
button $main_win.edit.button -text "Default" -width 8 \
-command ::APBSRun::set_default
pack $main_win.edit.type $main_win.edit.button \
-side left -anchor w -fill x
pack $main_win.edit \
-side top -anchor w -padx 10 -pady 10
frame $main_win.list
pack [label $main_win.list.label -anchor w \
-text "Individual PB calculations (ELEC):"] -side top -anchor w
set elec_listbox [listbox $main_win.list.names \
-yscrollcommand {$::APBSRun::main_win.list.scroll set} \
-listvariable ::APBSRun::elec_list -relief sunken -bd 2 -height 5]
pack [scrollbar $main_win.list.scroll \
-command {$::APBSRun::main_win.list.names yview}] -side right -fill y
pack $main_win.list.names \
-side top -anchor w -fill both -expand yes
pack $main_win.list \
-side top -anchor w -fill both -expand yes -padx 10 -pady 10
frame $main_win.elec_buttons
button $main_win.elec_buttons.add -text "Add" -width 8 \
-command ::APBSRun::elec_add
button $main_win.elec_buttons.edit -text "Edit" -width 8 \
-command ::APBSRun::elec_edit
button $main_win.elec_buttons.del -text "Delete" -width 8 \
-command ::APBSRun::elec_del
pack $main_win.elec_buttons.add $main_win.elec_buttons.edit \
$main_win.elec_buttons.del \
-side left
pack $main_win.elec_buttons \
-side top -anchor w -padx 10 -pady 10
frame $main_win.apbs
label $main_win.apbs.status -textvar ::APBSRun::apbs_status
button $main_win.apbs.button -textvar ::APBSRun::apbs_button \
-width 10 -command ::APBSRun::apbs_setup
pack $main_win.apbs.status $main_win.apbs.button \
-side top -anchor w
pack $main_win.apbs \
-side top -anchor w -padx 10 -pady 10
}
# Validate values, set up the files for APBS, and run it
proc ::APBSRun::apbs_setup {} {
variable apbs_status
variable apbs_button
variable apbs_fd
variable current_apbs_config
variable selected_apbs_config
variable apbs_type
variable elec_temp
variable workdir
variable apbs_input
variable apbsbin
variable setup_only
variable pqrfiles
variable molids
# If APBS is running, do nothing
if {[string equal $apbs_button "Stop APBS"]} {
# Try to kill the process.
# XXX - this simply won't work on Windows without a seperate "kill"
# program being installed, so fail gracefully.
if { [catch {exec kill [pid $apbs_fd]} err] } {
puts "apbsrun: can't close APBS:\n $err"
}
return
}
# Check that we have a valid location for apbs before proceeding
if {$apbsbin == {} && !$setup_only} {
# Prompt the user for its location
set apbsbin [::FinderTool::find -interactive apbs]
if {$apbsbin == {}} {
puts "apbsrun: please set the APBS location in the Settings Menu"
return
}
}
set pqrfiles {}
# Copy the data (a list of elec statements) into selected_apbs_config
set selected_apbs_config $current_apbs_config($apbs_type)
# XXX - this implementation won't work when the user wants to use the same
# molecule with more than one unique selection in different elec
# statements
# Create a list of all molecules used by the plugin
array unset molids
array unset selections
set molid_list {}
set mol_index 1
for {set i 0} {$i < [llength $selected_apbs_config]} {incr i} {
array set elec_temp [lindex $selected_apbs_config $i]
# Check the elec statement for errors
if { ![::APBSRun::elec_check elec_temp] } {
puts "apbsrun: Exiting."
return
}
set vmd_molid [string index $elec_temp(mol) 0]
set vmd_cgcent_molid [string index $elec_temp(cgcent_mol) 0]
set vmd_fgcent_molid [string index $elec_temp(fgcent_mol) 0]
if {![info exists molids($vmd_molid)]} {
set molids($vmd_molid) $mol_index
lappend molid_list $vmd_molid
set selections($vmd_molid) $elec_temp(atomsel)
incr mol_index
}
if {[string equal $elec_temp(cgcent_method) "molid"] &&
![info exists molids($vmd_cgcent_molid)]} {
set molids($vmd_cgcent_molid) $mol_index
lappend molid_list $vmd_cgcent_molid
incr mol_index
}
if {[string equal $elec_temp(fgcent_method) "molid"] &&
![info exists molids($vmd_fgcent_molid)]} {
set molids($vmd_fgcent_molid) $mol_index
lappend molid_list $vmd_fgcent_molid
incr mol_index
}
}
# Write a pqr file for each molecule referenced in the plugin
foreach vmd_molid $molid_list {
if {[info exists selections($vmd_molid)]} {
set sel [atomselect $vmd_molid $selections($vmd_molid)]
} else {
set sel [atomselect $vmd_molid all]
}
set filename [file rootname [molinfo $vmd_molid get name]]
set filename [file join $workdir "$filename.pqr"]
lappend pqrfiles $filename
set apbs_status "Status: Writing PQR file: $filename"
if { [catch {::APBSRun::write_mol $sel $filename} err] } {
puts "$err"
set apbs_status "Status: Ready"
return
}
$sel delete
}
# Write the APBS input file to workdir
set apbs_input [file join $workdir apbs.in]
set apbs_status "Status: Writing APBS input file: $apbs_input"
if { [catch {::APBSRun::write_input $apbs_input} err] } {
puts "$err"
set apbs_status "Status: Ready"
return
}
# Run apbs in the working directory
if {! $setup_only} {
set currentdir [pwd]
cd $workdir
set apbs_status "Status: Running APBS"
set apbs_button "Stop APBS"
::APBSRun::apbs_run
cd $currentdir
} else {
set apbs_status "Status: Ready"
set apbs_button "Run APBS"
}
}
#
# Procs for running and stopping APBS. These can be overridden locally.
#
proc ::APBSRun::apbs_run {} {
variable apbsbin
variable apbs_input
variable apbs_fd
# Attach APBS to a filehandle and print output as it becomes available
if { [catch {set apbs_fd [open "|$apbsbin $apbs_input"]}] } {
puts "apbsrun: error running $apbsbin"
::APBSRun::apbs_stop
} else {
fconfigure $apbs_fd -blocking false
fileevent $apbs_fd readable [list ::APBSRun::read_handler $apbs_fd]
}
}
# Call this function when apbs is done
proc ::APBSRun::apbs_stop {} {
variable apbs_status
variable apbs_button
variable apbs_fd
if { [catch {close $apbs_fd} err] } {
puts "apbsrun: error occurred while running APBS:\n $err"
} else {
# No errors occurred, prompt the user to load maps
::APBSRun::prompt_load_maps
}
set apbs_status "Status: Ready"
set apbs_button "Run APBS"
}
# Read and print a line of APBS output.
proc ::APBSRun::read_handler { chan } {
if {[eof $chan]} {
fileevent $chan readable ""
::APBSRun::apbs_stop
return
}
if {[gets $chan line] > 0} {
puts "$line"
}
}
# Write an apbs input file. Return error if the file can't be written.
proc ::APBSRun::write_input {outfile} {
variable selected_apbs_config
variable pqrfiles
variable molids
variable output_files
if { [catch {set file [open $outfile w]}] } {
error "apbsrun: can't open $outfile for writing"
}
# Write the READ section, a list of molecules to use
puts $file "read"
foreach pqrfile $pqrfiles {
set pqrfile [file normalize $pqrfile]
puts $file " mol pqr $pqrfile"
}
puts $file "end"
# Write the ELEC statements
for {set i 0} {$i < [llength $selected_apbs_config]} {incr i} {
array set elec_statement [lindex $selected_apbs_config $i]
set apbs_cgcent $molids([string index $elec_statement(cgcent_mol) 0])
set apbs_fgcent $molids([string index $elec_statement(fgcent_mol) 0])
puts $file "elec"
# mg-manual|mg-auto|mg-para|mg-dummy
puts $file " $elec_statement(calc_type)"
# dime
puts $file " dime $elec_statement(dime_x) $elec_statement(dime_y) $elec_statement(dime_z)"
if {[string equal $elec_statement(calc_type) "mg-manual"] ||
[string equal $elec_statement(calc_type) "mg-dummy"]} {
# nlev
puts $file " nlev $elec_statement(nlev)"
# glen
puts $file " glen $elec_statement(cglen_x) $elec_statement(cglen_y) $elec_statement(cglen_z)"
# gcent
if {[string equal $elec_statement(cgcent_method) "molid"]} {
puts $file " gcent mol $apbs_cgcent"
} else {
puts $file " gcent $elec_statement(cgcent_x) $elec_statement(cgcent_y) $elec_statement(cgcent_z)"
}
} elseif {[string equal $elec_statement(calc_type) "mg-auto"] ||
[string equal $elec_statement(calc_type) "mg-para"]} {
# cglen
puts $file " cglen $elec_statement(cglen_x) $elec_statement(cglen_y) $elec_statement(cglen_z)"
# cgcent
if {[string equal $elec_statement(cgcent_method) "molid"]} {
puts $file " cgcent mol $apbs_cgcent"
} else {
puts $file " cgcent $elec_statement(cgcent_x) $elec_statement(cgcent_y) $elec_statement(cgcent_z)"
}
# fglen
puts $file " fglen $elec_statement(fglen_x) $elec_statement(fglen_y) $elec_statement(fglen_z)"
# fgcent
if {[string equal $elec_statement(fgcent_method) "molid"]} {
puts $file " fgcent mol $apbs_fgcent"
} else {
puts $file " fgcent $elec_statement(fgcent_x) $elec_statement(fgcent_y) $elec_statement(fgcent_z)"
}
if {[string equal $elec_statement(calc_type) "mg-para"]} {
# pdime
puts $file " pdime $elec_statement(pdime_x) $elec_statement(pdime_y) $elec_statement(pdime_z)"
# ofrac
puts $file " ofrac $elec_statement(ofrac)"
}
} else {
puts stderr "apbsrun: unknown calc_type $elec_statement(calc_type)"
}
# mol
set apbs_molid $molids([string index $elec_statement(mol) 0])
puts $file " mol $apbs_molid"
# lpbe|npbe
puts $file " $elec_statement(pbe)"
# bcfl
if {[string equal $elec_statement(bcfl) "Zero boundary conditions"]} {
puts $file " bcfl zero"
} elseif {[string equal $elec_statement(bcfl) "Single ion for molecule"]} {
puts $file " bcfl sdh"
} elseif {[string equal $elec_statement(bcfl) "Single ion for each ion"]} {
puts $file " bcfl mdh"
} elseif {[string equal $elec_statement(bcfl) "Solution from previous calculation"]} {
puts $file " bcfl focus"
} else {
puts stderr "apbsrun: unknown bcfl $elec_statement(bcfl)"
}
# srfm
if {[string equal $elec_statement(srfm) "No smoothing"]} {
puts $file " srfm mol"
} elseif {[string equal $elec_statement(srfm) "Harmonic average smoothing"]} {
puts $file " srfm smol"
} elseif {[string equal $elec_statement(srfm) "Spline-based surface definitions"]} {
puts $file " srfm spl2"
} else {
puts stderr "apbsrun: unknown srfm $elec_statement(srfm)"
}
# chgm
if {[string equal $elec_statement(chgm) "Trilinear hat-function"]} {
puts $file " chgm spl0"
} elseif {[string equal $elec_statement(chgm) "Cubic B-Spline"]} {
puts $file " chgm spl2"
} else {
puts stderr "apbsrun: unknown chgm $elec_statement(chgm)"
}
# ion (optional)
if {[info exists elec_statement(ion)] && [llength $elec_statement(ion)] != 0} {
foreach ion $elec_statement(ion) {
puts $file " ion $ion"
}
}
# pdie sdie srad swin temp gamma
foreach keyword {pdie sdie srad swin temp gamma} {
puts $file " $keyword $elec_statement($keyword)"
}
#XXX - fix these
puts $file " calcenergy no"
puts $file " calcforce no"
# write (optional)
# XXX - this *will* break when multiple ELEC statements attempt to
# output the same type of file.
set output_files {}
foreach type {charge pot smol sspl vdw ivdw lap edens ndens qdens dielx diely dielz kappa} {
if { [info exists elec_statement(write,$type)] &&
($elec_statement(write,$type) == 1) } {
puts $file " write $type dx $type"
lappend output_files $type
}
}
# XXX - writemat (optional)
puts $file "end"
}
puts $file "quit"
close $file
}
# Overwrite the selection's radii with those found in the CHARMM parameter
# file
proc ::APBSRun::set_parameter_radii {sel} {
variable ff_radii
set radiusOK yes
set newradius {}
foreach {resname} [$sel get resname] {name} [$sel get name] {radius} [$sel get radius] {
if {[info exists ff_radii($resname,$name)]} {
lappend newradius $ff_radii($resname,$name)
} else {
lappend newradius $radius
set radiusOK no
}
}
$sel set radius $newradius
if {!$radiusOK} {
puts "apbsrun: warning, parameter file does not contain entries for all selected"
puts "apbsrun: atoms, using VMD radii for these."
}
}
# Overwrite the selection's charges with those found in the CHARMM parameter
# file
proc ::APBSRun::set_parameter_charges {sel} {
variable ff_charges
set chargeOK yes
set newcharge {}
foreach {resname} [$sel get resname] {name} [$sel get name] {charge} [$sel get charge] {
if {[info exists ff_charges($resname,$name)]} {
lappend newcharge $ff_charges($resname,$name)
} else {
lappend newcharge $charge
set chargeOK no
}
}
$sel set charge $newcharge
if {!$chargeOK} {
puts "apbsrun: warning, parameter file does not contain entries for all selected"
puts "apbsrun: atoms, using VMD charges for these."
}
}
# Create a pqr file for the given atom selection with the given name
proc ::APBSRun::write_mol {sel file} {
variable datfile
variable use_dat_radii
variable use_dat_charges
# Save the radius and charge before overriding with parameter values
set oldradius [$sel get radius]
set oldcharge [$sel get charge]
# Override current VMD values with CHARMM parameter values
if { $datfile != {} } {
if { $use_dat_radii } {
puts "apbsrun: using CHARMM radii"
::APBSRun::set_parameter_radii $sel
} else {
puts "apbsrun: using VMD radii"
}
#XXX - Disabled until the parameter assigning code is improved
# if { $use_dat_charges } {
# puts "apbsrun: using CHARMM charges"
# ::APBSRun::set_parameter_charges $sel
# } else {
# puts "apbsrun: using VMD charges"
# }
}
# Make sure the molecule is charged.
# XXX - APBS should (maybe?) allow uncharged molecules for mg-dummy
# calculation, but it currently doens't. If future versions allow it, we
# should add a simple if statement to do so as well.
set chargeOK 0
foreach charge [$sel get charge] {
if {$charge != 0} {
set chargeOK 1
break
}
}
if {!$chargeOK &&
[string equal "no" [tk_messageBox -type yesno \
-title "Uncharged Molecule" -icon warning \
-message "Molecule is uncharged. Proceed?"]] } {
error "apbsrun: refusing to write uncharged molecule"
}
# Check for the availability of the pqrplugin
set plugin_available [plugin info {mol file reader} pqr plugin_info]
if {$plugin_available} {
puts "apbsrun: using pqrplugin for $file"
if { [catch {$sel writepqr $file}] } {
error "apbsrun: couldn't write $file"
}
} else {
puts "apbsrun: creating $file"
if { [catch {set fd [open $file w]}] } {
error "apbsrun: can't open $file for writing"
}
set i 0
foreach name [$sel get name] resname [$sel get resname] \
resid [$sel get resid] x [$sel get x] y [$sel get y] z [$sel get z] \
charge [$sel get charge] radius [$sel get radius] {
puts $fd [format "ATOM %5d %-4s %s %5d %8.3f%8.3f%8.3f %.3f %.3f" \
$i [string range $name 0 3] [string range $resname 0 3] \
[string range $resid 0 6] $x $y $z $charge $radius]
incr i
}
close $fd
}
# Restore original values
$sel set radius $oldradius
$sel set charge $oldcharge
}
#
# Open a window for changing APBSRun settings
#
proc ::APBSRun::apbs_settings {} {
variable main_win
variable settings_win
set ::APBSRun::use_dat_charges_temp $::APBSRun::use_dat_charges
set ::APBSRun::use_dat_radii_temp $::APBSRun::use_dat_radii
set ::APBSRun::setup_only_temp $::APBSRun::setup_only
set ::APBSRun::apbsbin_temp $::APBSRun::apbsbin
set ::APBSRun::workdir_temp $::APBSRun::workdir
# If already initialized, just turn on
if { [winfo exists $main_win.settings] } {
wm deiconify $settings_win
return
}
set settings_win [toplevel "$main_win.settings"]
wm title $settings_win "Settings"
wm resizable $settings_win yes yes
# Make this window modal.
grab $settings_win
wm transient $settings_win $main_win
wm protocol $settings_win WM_DELETE_WINDOW {
grab release $::APBSRun::settings_win
after idle destroy $::APBSRun::settings_win
}
raise $settings_win
frame $settings_win.workdir
grid [label $settings_win.workdir.label -anchor w \
-text "Working Directory"] -row 0 -column 0 -sticky ew
grid [entry $settings_win.workdir.value -width 30 \
-textvariable ::APBSRun::workdir_temp] -row 1 -column 0 -sticky nsew
grid [button $settings_win.workdir.button -text "Browse" \
-command {
set tempdir [tk_chooseDirectory]
if {![string equal $tempdir ""]} {
set ::APBSRun::workdir_temp $tempdir
}}] -row 1 -column 1 -sticky ew
grid columnconfigure $settings_win.workdir 0 -weight 1
grid rowconfigure $settings_win.workdir 1 -weight 1
frame $settings_win.apbsbin
grid [label $settings_win.apbsbin.label -anchor w \
-text "APBS Location"] -row 0 -column 0 -sticky ew
grid [entry $settings_win.apbsbin.value -width 30 \
-textvariable ::APBSRun::apbsbin_temp] -row 1 -column 0 -sticky nsew
grid [button $settings_win.apbsbin.button -text "Browse" \
-command {
set tempfile [tk_getOpenFile]
if {![string equal $tempfile ""]} {
set ::APBSRun::apbsbin_temp $tempfile
}}] -row 1 -column 1 -sticky ew
grid columnconfigure $settings_win.apbsbin 0 -weight 1
grid rowconfigure $settings_win.apbsbin 1 -weight 1
frame $settings_win.apbssetup
checkbutton $settings_win.apbssetup.setup_button \
-text "Setup files only, do not run APBS" \
-variable ::APBSRun::setup_only_temp
checkbutton $settings_win.apbssetup.radii_button \
-text "Use CHARMM radii" \
-variable ::APBSRun::use_dat_radii_temp
#XXX - Disabled until the parameter assigning code is improved
# checkbutton $settings_win.apbssetup.charges_button \
# -text "Use CHARMM charges" \
# -variable ::APBSRun::use_dat_charges_temp
pack $settings_win.apbssetup.setup_button \
$settings_win.apbssetup.radii_button \
-side top -anchor w
frame $settings_win.okaycancel
button $settings_win.okaycancel.okay -text OK -width 6 \
-command {
set ::APBSRun::use_dat_charges $::APBSRun::use_dat_charges_temp
set ::APBSRun::use_dat_radii $::APBSRun::use_dat_radii_temp
set ::APBSRun::setup_only $::APBSRun::setup_only_temp
set ::APBSRun::apbsbin $::APBSRun::apbsbin_temp
set ::APBSRun::workdir $::APBSRun::workdir_temp
grab release $::APBSRun::settings_win
after idle destroy $::APBSRun::settings_win
}
button $settings_win.okaycancel.cancel -text "Cancel" -width 6 \
-command {
grab release $::APBSRun::settings_win
after idle destroy $::APBSRun::settings_win
}
pack $settings_win.okaycancel.okay $settings_win.okaycancel.cancel \
-side left -anchor w
pack $settings_win.workdir $settings_win.apbsbin $settings_win.apbssetup \
$settings_win.okaycancel \
-side top -anchor w -fill both -expand yes -padx 10 -pady 10
}
# Reset the current apbs configuration to the default values and
# reset the current *default* apbs configuration to reflect the top molecule
proc ::APBSRun::set_default {} {
variable default_apbs_config
variable current_apbs_config
variable apbs_type
variable elec_list
variable elec_index
variable file_list
# Get information about the top mol to set the defaults
if { $file_list == {{}} } {
set topmol {}
} else {
set topmol [lsearch -inline $file_list [molinfo top]*]
if {$topmol == {}} {
set topmol [lindex $file_list 0]
}
# Make sure this molecule contains atoms and coordinates. If not, use
# the first molecule that does.
foreach loaded_mol [concat [list $topmol] $file_list] {
set topmol_id [string index $loaded_mol 0]
if { [molinfo $topmol_id get numatoms] != 0 &&
[molinfo $topmol_id get numframes] != 0 } {
set topmol $loaded_mol
break
} else {
set topmol {}
}
}
}
if {$topmol == {}} {
set selection_text "all"
set molsize_x 0
set molsize_y 0
set molsize_z 0
} else {
set topmol_id [string index $topmol 0]
set selection_text [lindex [molinfo $topmol_id get {"selection 0"}] 0]
# Find the size of the molecule
set sel [atomselect $topmol_id all]
set minmax [measure minmax $sel]
$sel delete
set molsize_x [expr [lindex $minmax 1 0] - [lindex $minmax 0 0]]
set molsize_y [expr [lindex $minmax 1 1] - [lindex $minmax 0 1]]
set molsize_z [expr [lindex $minmax 1 2] - [lindex $minmax 0 2]]
}
# Set Default APBS info
set default_apbs_config([concat "Electrostatic" "Potential"]) [list [list \
mol $topmol atomsel $selection_text pbe lpbe \
bcfl "Single ion for molecule" pdie 1.0 sdie 78.54 \
srfm "Harmonic average smoothing" chgm "Cubic B-Spline" \
srad 1.4 swin 0.3 temp 298.15 gamma 0.105 \
write,pot 1 \
ion { {1 0.150 2.0} {-1 0.150 2.0} } \
calc_type {mg-auto} dime_x 129 dime_y 129 dime_z 129 \
cglen_x [expr 1.5 * $molsize_x] cglen_y [expr 1.5 * $molsize_y] \
cglen_z [expr 1.5 * $molsize_z] cgcent_method {molid} \
cgcent_x {} cgcent_y {} cgcent_z {} cgcent_mol $topmol \
fglen_x $molsize_x fglen_y $molsize_y \
fglen_z $molsize_z fgcent_method {molid} \
fgcent_x {} fgcent_y {} fgcent_z {} fgcent_mol $topmol \
nlev 4 ofrac 0.1 pdime_x 4 pdime_y 4 pdime_z 4 ] ]
set default_apbs_config([concat "Solvent" "Accessibility"]) [list [list \
mol $topmol atomsel $selection_text pbe lpbe \
bcfl "Single ion for molecule" pdie 1.0 sdie 78.54 \
srfm "Harmonic average smoothing" chgm "Cubic B-Spline" \
srad 1.4 swin 0.3 temp 298.15 gamma 0.105 \
write,sspl 1 \
ion { {1 0.150 2.0} {-1 0.150 2.0} } \
calc_type {mg-dummy} dime_x 129 dime_y 129 dime_z 129 \
cglen_x [expr 1.5 * $molsize_x] cglen_y [expr 1.5 * $molsize_y] \
cglen_z [expr 1.5 * $molsize_z] cgcent_method {molid} \
cgcent_x {} cgcent_y {} cgcent_z {} cgcent_mol $topmol \
fglen_x $molsize_x fglen_y $molsize_y \
fglen_z $molsize_z fgcent_method {molid} \
fgcent_x {} fgcent_y {} fgcent_z {} fgcent_mol $topmol \
nlev 4 ofrac 0.1 pdime_x 4 pdime_y 4 pdime_z 4 ] ]
set default_apbs_config(Custom) {}
# Copy the defaults to the user-edited APBS info
if {$apbs_type == {}} {
array set current_apbs_config [array get default_apbs_config]
set apbs_type "Electrostatic Potential"
} else {
set current_apbs_config($apbs_type) $default_apbs_config($apbs_type)
}
::APBSRun::update_elec_list
}
# Add an ELEC statement to elec_vals
proc ::APBSRun::elec_add {} {
variable elec_temp
variable elec_index
variable elec_current_index
# Clear the temp array
array unset elec_temp
# Launch the elec-editing window
set elec_current_index $elec_index
::APBSRun::elecmenu
}
# Edit an ELEC statement in elec_vals
proc ::APBSRun::elec_edit {} {
variable elec_temp
variable elec_listbox
variable elec_list
variable elec_current_index
variable current_apbs_config
variable apbs_type
# Can't edit anything if no ELEC statements exist
if {[llength $elec_list] == 0} {
return
}
set elec_current_index [string index [$elec_listbox get active] 0]
# Clear the temporary array, and load it with previous values
array unset elec_temp
array set elec_temp \
[lindex $current_apbs_config($apbs_type) $elec_current_index]
# Launch the elec-editing window
::APBSRun::elecmenu
}
# Remove an ELEC statement from elec_vals
proc ::APBSRun::elec_del {} {
variable elec_listbox
variable current_apbs_config
variable apbs_type
set index [string index [$elec_listbox get active] 0]
# Remove the entry from the listbox
$elec_listbox delete active
# Set the appropriate item in current_apbs_config to nothing
#XXX - this is ugly
lset current_apbs_config($apbs_type) $index {}
}
# Open a window for editing the values of an elec statement
proc ::APBSRun::elecmenu {} {
variable main_win
variable elec_win
variable elec_temp
variable file_list
variable elec_keyword
# If already initialized, just turn on
if { [winfo exists $main_win.elec] } {
wm deiconify $elec_win
return
}
set elec_win [toplevel "$main_win.elec"]
wm title $elec_win "ELEC values"
wm resizable $elec_win yes yes
# Make this window modal.
grab $elec_win
wm transient $elec_win $main_win
wm protocol $elec_win WM_DELETE_WINDOW {
grab release $::APBSRun::elec_win
after idle destroy $::APBSRun::elec_win
}
raise $elec_win
# make the menu bar
frame $elec_win.menubar -relief raised -bd 2 ;# frame for menubar
grid $elec_win.menubar -padx 1 -column 0 -columnspan 2 -row 0 -sticky ew
menubutton $elec_win.menubar.calc -text "Calculation" -underline 0 \
-menu $elec_win.menubar.calc.menu
# XXX - set menubutton width to avoid truncation in OS X
$elec_win.menubar.calc config -width 11
menubutton $elec_win.menubar.output -text "Output" -underline 0 \
-menu $elec_win.menubar.output.menu
# XXX - set menubutton width to avoid truncation in OS X
$elec_win.menubar.output config -width 7
pack $elec_win.menubar.calc $elec_win.menubar.output -side left
# calculation menu
menu $elec_win.menubar.calc.menu -tearoff no
$elec_win.menubar.calc.menu add radiobutton -label "Automatic" \
-variable ::APBSRun::elec_temp(calc_type) -value {mg-auto}
$elec_win.menubar.calc.menu add radiobutton -label "Manual" \
-variable ::APBSRun::elec_temp(calc_type) -value {mg-manual}
$elec_win.menubar.calc.menu add radiobutton -label "Parallel" \
-variable ::APBSRun::elec_temp(calc_type) -value {mg-para}
$elec_win.menubar.calc.menu add radiobutton -label "Dummy" \
-variable ::APBSRun::elec_temp(calc_type) -value {mg-dummy}
$elec_win.menubar.calc.menu add separator
$elec_win.menubar.calc.menu add radiobutton -label "Linearized PBE" \
-variable ::APBSRun::elec_temp(pbe) -value {lpbe}
$elec_win.menubar.calc.menu add radiobutton -label "Nonlinear PBE"\
-variable ::APBSRun::elec_temp(pbe) -value {npbe}
# output menu
menu $elec_win.menubar.output.menu -tearoff no
$elec_win.menubar.output.menu add checkbutton -label "Charge distribution" \
-variable ::APBSRun::elec_temp(write,charge)
$elec_win.menubar.output.menu add checkbutton -label "Potential" \
-variable ::APBSRun::elec_temp(write,pot)
$elec_win.menubar.output.menu add checkbutton -label "Solvent accessibility" \
-variable ::APBSRun::elec_temp(write,sspl)
$elec_win.menubar.output.menu add checkbutton -label "Van der Waals accessibility" \
-variable ::APBSRun::elec_temp(write,vdw)
$elec_win.menubar.output.menu add checkbutton -label "Ion accessibility" \
-variable ::APBSRun::elec_temp(write,ivdw)
$elec_win.menubar.output.menu add checkbutton -label "Laplacian of potential" \
-variable ::APBSRun::elec_temp(write,lap)
$elec_win.menubar.output.menu add checkbutton -label "Energy density" \
-variable ::APBSRun::elec_temp(write,edens)
$elec_win.menubar.output.menu add checkbutton -label "Ion number density" \
-variable ::APBSRun::elec_temp(write,ndens)
$elec_win.menubar.output.menu add checkbutton -label "Ion charge density" \
-variable ::APBSRun::elec_temp(write,qdens)
$elec_win.menubar.output.menu add checkbutton -label "x-shifted dielectric map" \
-variable ::APBSRun::elec_temp(write,dielx)
$elec_win.menubar.output.menu add checkbutton -label "y-shifted dielectric map" \
-variable ::APBSRun::elec_temp(write,diely)
$elec_win.menubar.output.menu add checkbutton -label "z-shifted dielectric map" \
-variable ::APBSRun::elec_temp(write,dielz)
$elec_win.menubar.output.menu add checkbutton -label "Map function" \
-variable ::APBSRun::elec_temp(write,kappa)
if {![info exists ::APBSRun::elec_temp(calc_type)]} {
set ::APBSRun::elec_temp(calc_type) {mg-auto}
}
# Trace the keyword variable so different options can be displayed when it
# changes
trace add variable ::APBSRun::elec_temp(calc_type) write \
::APBSRun::change_keyword
# Remove the trace when this window is destroyed
bind $elec_win {+trace remove variable \
::APBSRun::elec_temp(calc_type) write ::APBSRun::change_keyword}
### frame for options used by all ELEC keyworks
frame $elec_win.options
# mol
frame $elec_win.options.mol
label $elec_win.options.mol.label -text "Molecule: " \
-anchor w
eval tk_optionMenu $elec_win.options.mol.id ::APBSRun::elec_temp(mol) \
$file_list
$elec_win.options.mol.id configure -width 12
pack $elec_win.options.mol.label $elec_win.options.mol.id \
-side left -anchor w -fill x -expand yes
# selection
frame $elec_win.options.atomsel
label $elec_win.options.atomsel.label -text "Selection: " \
-anchor w
entry $elec_win.options.atomsel.entry -width 20 \
-textvar ::APBSRun::elec_temp(atomsel)
pack $elec_win.options.atomsel.label $elec_win.options.atomsel.entry \
-side left -anchor w -fill x -expand yes
# bcfl
frame $elec_win.options.bcfl
label $elec_win.options.bcfl.label -text "Boundary condition: "
tk_optionMenu $elec_win.options.bcfl.menu ::APBSRun::elec_temp(bcfl) \
"Zero boundary conditions" \
"Single ion for molecule" \
"Single ion for each ion" \
"Solution from previous calculation"
$elec_win.options.bcfl.menu config -width 25
pack $elec_win.options.bcfl.label $elec_win.options.bcfl.menu \
-side top -anchor w
# ion (optional)
# XXX - TODO
# pdie
# sdie
frame $elec_win.options.diel
label $elec_win.options.diel.label -text "Dielectric constants: "
frame $elec_win.options.diel.vals
label $elec_win.options.diel.vals.plabel -text "solute: "
entry $elec_win.options.diel.vals.pval -width 6 -textvar ::APBSRun::elec_temp(pdie)
label $elec_win.options.diel.vals.slabel -text " solvent: "
entry $elec_win.options.diel.vals.sval -width 6 -textvar ::APBSRun::elec_temp(sdie)
pack $elec_win.options.diel.vals.plabel $elec_win.options.diel.vals.pval \
$elec_win.options.diel.vals.slabel $elec_win.options.diel.vals.sval \
-side left -anchor w
pack $elec_win.options.diel.label $elec_win.options.diel.vals \
-side top -anchor w
# chgm
frame $elec_win.options.chgm
label $elec_win.options.chgm.label -text "Charge discretization: "
tk_optionMenu $elec_win.options.chgm.menu ::APBSRun::elec_temp(chgm) \
"Trilinear hat-function" \
"Cubic B-Spline"
$elec_win.options.chgm.menu config -width 25
pack $elec_win.options.chgm.label $elec_win.options.chgm.menu \
-side top -anchor w
# srfm
frame $elec_win.options.srfm
label $elec_win.options.srfm.label -text "Surface definition: "
tk_optionMenu $elec_win.options.srfm.menu ::APBSRun::elec_temp(srfm) \
"No smoothing" \
"Harmonic average smoothing" \
"Spline-based surface definitions"
$elec_win.options.srfm.menu config -width 25
pack $elec_win.options.srfm.label $elec_win.options.srfm.menu \
-side top -anchor w
# usemap (optional)
# XXX - TODO
# Grid containing a few system options
frame $elec_win.options.system
# srad
label $elec_win.options.system.sradl -text "Solvent radius: " \
-anchor w
entry $elec_win.options.system.sradval -width 6 \
-textvar ::APBSRun::elec_temp(srad)
grid $elec_win.options.system.sradl $elec_win.options.system.sradval \
-row 0 -sticky ew
# swin
label $elec_win.options.system.swinl -text "Spline window: " \
-anchor w
entry $elec_win.options.system.swinval -width 6 \
-textvar ::APBSRun::elec_temp(swin)
grid $elec_win.options.system.swinl $elec_win.options.system.swinval \
-row 1 -sticky ew
# temp
label $elec_win.options.system.templ -text "System temperature (K): " \
-anchor w
entry $elec_win.options.system.tempval -width 6 \
-textvar ::APBSRun::elec_temp(temp)
grid $elec_win.options.system.templ $elec_win.options.system.tempval \
-row 2 -sticky ew
# gamma
label $elec_win.options.system.gammal -text "Surface tension: " \
-anchor w
entry $elec_win.options.system.gammaval -width 6 \
-textvar ::APBSRun::elec_temp(gamma)
grid $elec_win.options.system.gammal $elec_win.options.system.gammaval \
-row 3 -sticky ew
grid columnconfigure $elec_win.options.system 1 -weight 1
# XXX calcforce and calcenergy -- write results to stdout
# write (optional)
# XXX - TODO
# writemat (optional)
# XXX - TODO
pack $elec_win.options.mol $elec_win.options.atomsel \
$elec_win.options.bcfl $elec_win.options.diel \
$elec_win.options.chgm $elec_win.options.srfm \
$elec_win.options.system \
-side top -pady 8 -padx 8 -fill x -anchor w
# End the frame for selecting general APBS options
grid $elec_win.options -column 0 -row 1 \
-sticky nsew -padx 8 -pady 0
### Grid (and keyword) specific options
frame $elec_win.grid
# dime
frame $elec_win.grid.dime
label $elec_win.grid.dime.label -text "Number of gridpoints: "
frame $elec_win.grid.dime.coord
label $elec_win.grid.dime.coord.xlabel -text "x: "
entry $elec_win.grid.dime.coord.xentry -width 6 -textvar ::APBSRun::elec_temp(dime_x)
label $elec_win.grid.dime.coord.ylabel -text " y: "
entry $elec_win.grid.dime.coord.yentry -width 6 -textvar ::APBSRun::elec_temp(dime_y)
label $elec_win.grid.dime.coord.zlabel -text " z: "
entry $elec_win.grid.dime.coord.zentry -width 6 -textvar ::APBSRun::elec_temp(dime_z)
pack $elec_win.grid.dime.coord.xlabel $elec_win.grid.dime.coord.xentry $elec_win.grid.dime.coord.ylabel \
$elec_win.grid.dime.coord.yentry $elec_win.grid.dime.coord.zlabel $elec_win.grid.dime.coord.zentry \
-side left
pack $elec_win.grid.dime.label $elec_win.grid.dime.coord \
-side top -anchor w
pack $elec_win.grid.dime -side top -anchor w -fill x \
-pady 8 -padx 8
# Draw the appropriate keyword options
draw_mg_para $elec_win.grid.mg_para
draw_mg_auto $elec_win.grid.mg_auto
draw_mg_manual $elec_win.grid.mg_manual
set elec_keyword $elec_win.grid.mg_auto
::APBSRun::change_keyword
# End the frame for selecting ELEC keyword and keyword-specific options
grid $elec_win.grid -column 1 -row 1 -rowspan 2 \
-sticky nsew -padx 8 -pady 0
frame $elec_win.okaycancel
button $elec_win.okaycancel.okay -text OK -width 6 \
-command {
if { [::APBSRun::elec_check ::APBSRun::elec_temp] } {
::APBSRun::elec_save ::APBSRun::elec_temp
grab release $::APBSRun::elec_win
after idle destroy $::APBSRun::elec_win
}
}
button $elec_win.okaycancel.cancel -text Cancel -width 6 \
-command {
grab release $::APBSRun::elec_win
after idle destroy $::APBSRun::elec_win
}
pack $elec_win.okaycancel.okay $elec_win.okaycancel.cancel \
-side left
grid $elec_win.okaycancel -column 0 -row 2 \
-sticky w -padx 8 -pady 8
grid columnconfigure $elec_win {0 1} -weight 1
grid rowconfigure $elec_win 1 -weight 1
}
# When elec_temp(calc_type) changes, change the contents of the elec_win
proc ::APBSRun::change_keyword {args} {
variable elec_win
variable elec_temp
variable elec_keyword
pack forget $elec_keyword
if {[string equal $elec_temp(calc_type) "mg-para"]} {
set elec_keyword $elec_win.grid.mg_para
} elseif {[string equal $elec_temp(calc_type) "mg-auto"]} {
set elec_keyword $elec_win.grid.mg_auto
} elseif {[string equal $elec_temp(calc_type) "mg-manual"] ||
[string equal $elec_temp(calc_type) "mg-dummy"]} {
set elec_keyword $elec_win.grid.mg_manual
}
pack $elec_keyword -side top -anchor w
}
# Draw the mg_manual frame
proc ::APBSRun::draw_mg_manual {pathName} {
variable elec_temp
variable file_list
frame $pathName
#
# Grid
#
frame $pathName.g -relief groove -bd 2
pack [label $pathName.g.label -text "Grid Options"] \
-side top -anchor w -padx 8 -pady 4
# glen
frame $pathName.g.len
label $pathName.g.len.label -text "Mesh Lengths:"
frame $pathName.g.len.coord
label $pathName.g.len.coord.xlabel -text "x: "
entry $pathName.g.len.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cglen_x)
label $pathName.g.len.coord.ylabel -text " y: "
entry $pathName.g.len.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cglen_y)
label $pathName.g.len.coord.zlabel -text " z: "
entry $pathName.g.len.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cglen_z)
pack $pathName.g.len.coord.xlabel $pathName.g.len.coord.xvalue \
$pathName.g.len.coord.ylabel $pathName.g.len.coord.yvalue \
$pathName.g.len.coord.zlabel $pathName.g.len.coord.zvalue \
-side left -anchor w
pack $pathName.g.len.label $pathName.g.len.coord \
-side top -anchor w
pack $pathName.g.len -side top -anchor w -padx 8 -pady 4
# gcent
frame $pathName.g.cent
label $pathName.g.cent.label -text "Center:" -anchor w
frame $pathName.g.cent.mol
radiobutton $pathName.g.cent.mol.button -anchor w \
-variable ::APBSRun::elec_temp(cgcent_method) -value "molid"
eval tk_optionMenu $pathName.g.cent.mol.id \
::APBSRun::elec_temp(cgcent_mol) $file_list
$pathName.g.cent.mol.id configure -width 12
pack $pathName.g.cent.mol.button $pathName.g.cent.mol.id \
-side left
frame $pathName.g.cent.coord
radiobutton $pathName.g.cent.coord.button -anchor w \
-variable ::APBSRun::elec_temp(cgcent_method) -value "coord"
label $pathName.g.cent.coord.xlabel -text "x: "
entry $pathName.g.cent.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cgcent_x)
label $pathName.g.cent.coord.ylabel -text " y: "
entry $pathName.g.cent.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cgcent_y)
label $pathName.g.cent.coord.zlabel -text " z: "
entry $pathName.g.cent.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cgcent_z)
pack $pathName.g.cent.coord.button \
$pathName.g.cent.coord.xlabel $pathName.g.cent.coord.xvalue \
$pathName.g.cent.coord.ylabel $pathName.g.cent.coord.yvalue \
$pathName.g.cent.coord.zlabel $pathName.g.cent.coord.zvalue \
-side left
pack $pathName.g.cent.label $pathName.g.cent.mol $pathName.g.cent.coord \
-side top -anchor e -fill x
pack $pathName.g.cent -side top -anchor w -padx 8 -pady 4
pack $pathName.g -side top -anchor w -pady 4
# nlev
frame $pathName.nlev
label $pathName.nlev.label -text "Number of levels: "
entry $pathName.nlev.entry -width 6 -textvariable ::APBSRun::elec_temp(nlev)
pack $pathName.nlev.label $pathName.nlev.entry -side left -anchor w
pack $pathName.nlev -side top -anchor w -pady 8 -padx 8
}
# Draw the mg_auto frame
proc ::APBSRun::draw_mg_auto {pathName} {
variable elec_temp
variable file_list
frame $pathName
#
# Coarse Grid
#
frame $pathName.cg -relief groove -bd 2
pack [label $pathName.cg.label -text "Coarse Grid Options"] \
-side top -anchor w -padx 8 -pady 4
# cglen
frame $pathName.cg.len
label $pathName.cg.len.label -text "Mesh Lengths:"
frame $pathName.cg.len.coord
label $pathName.cg.len.coord.xlabel -text "x: "
entry $pathName.cg.len.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cglen_x)
label $pathName.cg.len.coord.ylabel -text " y: "
entry $pathName.cg.len.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cglen_y)
label $pathName.cg.len.coord.zlabel -text " z: "
entry $pathName.cg.len.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cglen_z)
pack $pathName.cg.len.coord.xlabel $pathName.cg.len.coord.xvalue \
$pathName.cg.len.coord.ylabel $pathName.cg.len.coord.yvalue \
$pathName.cg.len.coord.zlabel $pathName.cg.len.coord.zvalue \
-side left -anchor w
pack $pathName.cg.len.label $pathName.cg.len.coord \
-side top -anchor w
pack $pathName.cg.len -side top -anchor w -padx 8 -pady 4
# cgcent
frame $pathName.cg.cent
label $pathName.cg.cent.label -text "Center:" -anchor w
frame $pathName.cg.cent.mol
radiobutton $pathName.cg.cent.mol.button -anchor w \
-variable ::APBSRun::elec_temp(cgcent_method) -value "molid"
eval tk_optionMenu $pathName.cg.cent.mol.id \
::APBSRun::elec_temp(cgcent_mol) $file_list
$pathName.cg.cent.mol.id configure -width 12
pack $pathName.cg.cent.mol.button $pathName.cg.cent.mol.id \
-side left
frame $pathName.cg.cent.coord
radiobutton $pathName.cg.cent.coord.button -anchor w \
-variable ::APBSRun::elec_temp(cgcent_method) -value "coord"
label $pathName.cg.cent.coord.xlabel -text "x: "
entry $pathName.cg.cent.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cgcent_x)
label $pathName.cg.cent.coord.ylabel -text " y: "
entry $pathName.cg.cent.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cgcent_y)
label $pathName.cg.cent.coord.zlabel -text " z: "
entry $pathName.cg.cent.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(cgcent_z)
pack $pathName.cg.cent.coord.button \
$pathName.cg.cent.coord.xlabel $pathName.cg.cent.coord.xvalue \
$pathName.cg.cent.coord.ylabel $pathName.cg.cent.coord.yvalue \
$pathName.cg.cent.coord.zlabel $pathName.cg.cent.coord.zvalue \
-side left
pack $pathName.cg.cent.label $pathName.cg.cent.mol $pathName.cg.cent.coord \
-side top -anchor e -fill x
pack $pathName.cg.cent -side top -anchor w -padx 8 -pady 4
pack $pathName.cg -side top -anchor w -pady 4
#
# Fine Grid
#
frame $pathName.fg -relief groove -bd 2
pack [label $pathName.fg.label -text "Fine Grid Options"] \
-side top -anchor w -padx 8 -pady 4
# fglen
frame $pathName.fg.len
label $pathName.fg.len.label -text "Mesh Lengths:"
frame $pathName.fg.len.coord
label $pathName.fg.len.coord.xlabel -text "x: "
entry $pathName.fg.len.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(fglen_x)
label $pathName.fg.len.coord.ylabel -text " y: "
entry $pathName.fg.len.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(fglen_y)
label $pathName.fg.len.coord.zlabel -text " z: "
entry $pathName.fg.len.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(fglen_z)
pack $pathName.fg.len.coord.xlabel $pathName.fg.len.coord.xvalue \
$pathName.fg.len.coord.ylabel $pathName.fg.len.coord.yvalue \
$pathName.fg.len.coord.zlabel $pathName.fg.len.coord.zvalue \
-side left -anchor w
pack $pathName.fg.len.label $pathName.fg.len.coord \
-side top -anchor w
pack $pathName.fg.len -side top -anchor w -padx 8 -pady 4
# fgcent
frame $pathName.fg.cent
label $pathName.fg.cent.label -text "Center:" -anchor w
frame $pathName.fg.cent.mol
radiobutton $pathName.fg.cent.mol.button -anchor w \
-variable ::APBSRun::elec_temp(fgcent_method) -value "molid"
eval tk_optionMenu $pathName.fg.cent.mol.id \
::APBSRun::elec_temp(fgcent_mol) $file_list
$pathName.fg.cent.mol.id configure -width 12
pack $pathName.fg.cent.mol.button $pathName.fg.cent.mol.id \
-side left
frame $pathName.fg.cent.coord
radiobutton $pathName.fg.cent.coord.button -anchor w \
-variable ::APBSRun::elec_temp(fgcent_method) -value "coord"
label $pathName.fg.cent.coord.xlabel -text "x: "
entry $pathName.fg.cent.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(fgcent_x)
label $pathName.fg.cent.coord.ylabel -text " y: "
entry $pathName.fg.cent.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(fgcent_y)
label $pathName.fg.cent.coord.zlabel -text " z: "
entry $pathName.fg.cent.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(fgcent_z)
pack $pathName.fg.cent.coord.button \
$pathName.fg.cent.coord.xlabel $pathName.fg.cent.coord.xvalue \
$pathName.fg.cent.coord.ylabel $pathName.fg.cent.coord.yvalue \
$pathName.fg.cent.coord.zlabel $pathName.fg.cent.coord.zvalue \
-side left
pack $pathName.fg.cent.label $pathName.fg.cent.mol $pathName.fg.cent.coord \
-side top -anchor e -fill x
pack $pathName.fg.cent -side top -anchor w -padx 8 -pady 4
pack $pathName.fg -side top -anchor w -pady 4
}
# Draw the mg_para frame
proc ::APBSRun::draw_mg_para {pathName} {
variable elec_temp
variable file_list
frame $pathName
draw_mg_auto $pathName.mg_auto
pack $pathName.mg_auto -side top -anchor w
# pdime
frame $pathName.pdime
label $pathName.pdime.label -text "Number of Processors:"
frame $pathName.pdime.coord
label $pathName.pdime.coord.xlabel -text "x: "
entry $pathName.pdime.coord.xvalue -width 6 \
-textvariable ::APBSRun::elec_temp(pdime_x)
label $pathName.pdime.coord.ylabel -text " y: "
entry $pathName.pdime.coord.yvalue -width 6 \
-textvariable ::APBSRun::elec_temp(pdime_y)
label $pathName.pdime.coord.zlabel -text " z: "
entry $pathName.pdime.coord.zvalue -width 6 \
-textvariable ::APBSRun::elec_temp(pdime_z)
pack $pathName.pdime.coord.xlabel $pathName.pdime.coord.xvalue \
$pathName.pdime.coord.ylabel $pathName.pdime.coord.yvalue \
$pathName.pdime.coord.zlabel $pathName.pdime.coord.zvalue \
-side left -anchor w
pack $pathName.pdime.label $pathName.pdime.coord \
-side top -anchor w
pack $pathName.pdime -side top -anchor w -pady {8 4} -padx 8
# ofrac
frame $pathName.ofrac
label $pathName.ofrac.label -text "Mesh Overlap:"
entry $pathName.ofrac.entry -width 6 -textvariable ::APBSRun::elec_temp(ofrac)
pack $pathName.ofrac.label $pathName.ofrac.entry -side left -anchor w
pack $pathName.ofrac -side top -anchor w -pady {4 8} -padx 8
}
proc ::APBSRun::is_integer {args} {
if { [llength $args] != 1 } {
return 0
}
set x [lindex $args 0]
if { [catch {incr x 0}] } {
return 0
} else {
return 1
}
}
proc ::APBSRun::is_real {args} {
if { [llength $args] != 1 } {
return 0
}
set n [lindex $args 0]
if { [catch {expr $n + 0}] } {
return 0
} else {
return 1
}
}
proc ::APBSRun::is_valid_dime {args} {
if { ![is_integer $args] } {
return 0
}
set n [lindex $args 0]
if { $n <= 0 ||
[expr pow(2,round(log($n-1)/log(2)))+1] != $n } {
return 0
} else {
return 1
}
}
# Validate the elec statement return 1 on success, 0 on failure
proc ::APBSRun::elec_check {elec_ref} {
upvar $elec_ref elec_statement
# dime - must be 2^n + 1
if { ![is_valid_dime $elec_statement(dime_x)] ||
![is_valid_dime $elec_statement(dime_x)] ||
![is_valid_dime $elec_statement(dime_x)] } {
puts "apbsrun: invalid grid dimension"
return 0
}
# (c)gcent
if { [string equal $elec_statement(cgcent_method) "molid"] } {
if { [catch {molinfo [string index $elec_statement(cgcent_mol) 0] \
get id}] } {
puts "apbsrun: invalid molecule"
return 0
}
} else {
if { ![is_real $elec_statement(cgcent_x)] ||
![is_real $elec_statement(cgcent_y)] ||
![is_real $elec_statement(cgcent_y)] } {
puts "apbsrun: invalid grid center"
return 0
}
}
# (c)glen
if { ![is_real $elec_statement(cglen_x)] ||
($elec_statement(cglen_x) <= 0) ||
![is_real $elec_statement(cglen_y)] ||
($elec_statement(cglen_y) <= 0) ||
![is_real $elec_statement(cglen_z)] ||
($elec_statement(cglen_z) <= 0) } {
puts "apbsrun: invalid grid lengths"
return 0
}
if { [string equal $elec_statement(calc_type) "mg-manual"] ||
[string equal $elec_statement(calc_type) "mg-dummy"] } {
# nlev must be a positive integer
if { ![is_integer $elec_statement(nlev)] ||
($elec_statement(nlev) <= 0) } {
puts "apbsrun: nlev must be a positive integer"
return 0
}
} elseif { [string equal $elec_statement(calc_type) "mg-auto"] ||
[string equal $elec_statement(calc_type) "mg-para"] } {
# fgcent
if { [string equal $elec_statement(fgcent_method) "molid"] } {
if { [catch {molinfo [string index $elec_statement(fgcent_mol) 0] \
get id}] } {
puts "apbsrun: invalid molecule"
return 0
}
} else {
if { ![is_real $elec_statement(fgcent_x)] ||
![is_real $elec_statement(fgcent_y)] ||
![is_real $elec_statement(fgcent_y)] } {
puts "apbsrun: invalid fine grid center"
return 0
}
}
# fglen
if { ![is_real $elec_statement(fglen_x)] ||
($elec_statement(fglen_x) <= 0) ||
![is_real $elec_statement(fglen_y)] ||
($elec_statement(fglen_y) <= 0) ||
![is_real $elec_statement(fglen_z)] ||
($elec_statement(fglen_z) <= 0) } {
puts "apbsrun: invalid fine grid lengths"
return 0
}
if {[string equal $elec_statement(calc_type) "mg-para"]} {
# pdime
if { ![is_integer $elec_statement(pdime_x)] ||
($elec_statement(pdime_x) <= 0) ||
![is_integer $elec_statement(pdime_y)] ||
($elec_statement(pdime_y) <= 0) ||
![is_integer $elec_statement(pdime_z)] ||
($elec_statement(pdime_z) <= 0) } {
puts "apbsrun: invalid processor array"
return 0
}
# ofrac
if { ![is_real $elec_statement(ofrac)] ||
($elec_statement(ofrac) <= 0) || ($elec_statement(ofrac) >= 1) } {
puts "apbsrun: ofrac must be between 0 and 1"
return 0
}
}
} else {
puts "apbsrun: invalid calculation type"
return 0
}
# mol: make sure it's loaded in VMD and has atoms and structure
if { [catch {molinfo [string index $elec_statement(mol) 0] get id}] ||
[molinfo [string index $elec_statement(mol) 0] get numatoms] == 0 ||
[molinfo [string index $elec_statement(mol) 0] get numframes] == 0 } {
puts "apbsrun: invalid molecule"
return 0
}
# TODO: Maybe check these; they should always be valid since they're
# selected from a drop-down menu.
# lpbe
# bcfl
# srfm
# chgm
# pdie sdie srad swin temp gamma
foreach keyword {pdie sdie srad swin temp gamma} {
if { ![is_real $elec_statement($keyword)] } {
puts "apbsrun: $keyword invalid"
}
}
# XXX - TODO: writemat, ion.
return 1
}
# Save the elec statement to current_apbs_config
# add/edit the entry in the elec_list with the given index
proc ::APBSRun::elec_save {elec_ref} {
variable elec_win
variable elec_list
variable elec_index
variable elec_current_index
variable current_apbs_config
variable apbs_type
upvar $elec_ref elec_statement
# Copy the contents of elec_statement into an element in current_apbs_config
if {$elec_current_index == $elec_index} {
# Add an entry to the listbox
lappend elec_list $elec_current_index
incr elec_index
# Append the data to current_apbs_config
lappend current_apbs_config($apbs_type) [array get elec_statement]
} else {
# Change an entry in the listbox
#lset elec_list $index $index
# Change the data in current_apbs_config
lset current_apbs_config($apbs_type) $elec_current_index [array get elec_statement]
}
}
# Prompt the user with a list of the maps created by APBS
proc ::APBSRun::prompt_load_maps {} {
variable main_win
variable map_win
variable output_files
variable load_files
# If already initialized, just turn on
if { [winfo exists $main_win.maps] } {
wm deiconify $map_win
return
}
set map_win [toplevel "$main_win.maps"]
wm title $map_win "Load Maps"
wm resizable $map_win yes yes
# Make this window modal.
grab $map_win
wm transient $map_win $main_win
wm protocol $map_win WM_DELETE_WINDOW {
grab release $::APBSRun::map_win
after idle destroy $::APBSRun::map_win
}
raise $map_win
label $map_win.label -text "Load Maps into VMD"
pack $map_win.label -side top -anchor nw -padx 4 -pady 4
frame $map_win.filelist
array unset load_files
foreach type $output_files {
set ::APBSRun::load_files($type) 1 ;# default "on"
checkbutton $map_win.filelist.$type -width 10 \
-text $type -variable ::APBSRun::load_files($type)
pack $map_win.filelist.$type -side top -anchor w
}
pack $map_win.filelist -side top -anchor nw -padx 4 -pady 4 \
-expand yes -fill x
frame $map_win.buttons
button $map_win.buttons.okay -text "OK" -width 6 \
-command {
::APBSRun::load_maps
grab release $::APBSRun::map_win
after idle destroy $::APBSRun::map_win
}
button $map_win.buttons.cancel -text "Cancel" -width 6 \
-command {
grab release $::APBSRun::map_win
after idle destroy $::APBSRun::map_win
}
pack $map_win.buttons.okay $map_win.buttons.cancel \
-side left -fill x -expand yes
pack $map_win.buttons -side top -anchor nw -padx 4 -pady 4
}
# Load the maps into VMD
proc ::APBSRun::load_maps {} {
variable load_files
variable workdir
foreach file [array names load_files] {
if { $load_files($file) } {
mol new [file join $workdir "$file.dx"] type dx
}
}
}
# This gets called by VMD the first time the menu is opened.
proc apbsrun_tk_cb {} {
variable foobar
# Don't destroy the main window, because we want to register the window
# with VMD and keep reusing it. The window gets iconified instead of
# destroyed when closed for any reason.
#set foobar [catch {after idle destroy $::APBSRun::main_win}] ;# destroy any old windows
::APBSRun::apbsrun ;# start the tool
return $APBSRun::main_win
}