Changeset 5643


Ignore:
Timestamp:
May 31, 2015, 6:09:46 PM (9 years ago)
Author:
ldelgass
Message:

merge r5642 from trunk

Location:
branches/1.4
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/1.4

    • Property svn:mergeinfo changed
      /trunkmerged: 5642
  • branches/1.4/gui/scripts/flowvisviewer.tcl

    r5622 r5643  
    129129    private variable _dlist ""         ;# list of data objects
    130130    private variable _obj2ovride       ;# maps dataobj => style override
    131     private variable _serverDatasets   ;# contains all the dataobj-component
     131    private variable _datasets         ;# contains all the dataobj-component
    132132                                       ;# to volumes in the server
    133     private variable _recvdDatasets    ;# list of data objs to send to server
    134133    private variable _dataset2style    ;# maps dataobj-component to transfunc
    135134    private variable _style2datasets   ;# maps tf back to list of
     
    223222    $_arcball quaternion [ViewToQuaternion]
    224223
    225     set _limits(v) [list 0.0 1.0]
    226224    set _reset 1
    227225
     
    590588# ----------------------------------------------------------------------
    591589itcl::body Rappture::FlowvisViewer::add {dataobj {settings ""}} {
     590    if { ![$dataobj isvalid] } {
     591        return;                         # Object doesn't contain valid data.
     592    }
    592593    array set params {
    593594        -color auto
     
    695696        if { $pos >= 0 } {
    696697            set _dlist [lreplace $_dlist $pos $pos]
    697             array unset _limits $dataobj-*
    698698            array unset _obj2ovride $dataobj-*
    699             array unset _dataset2flow $dataobj-*
    700             array unset _serverDatasets $dataobj-*
    701             array unset _dataset2style $dataobj-*
    702699            set changed 1
    703700        }
     
    705702    # If anything changed, then rebuild the plot
    706703    if {$changed} {
    707         # Repair the reverse lookup
    708         foreach tf [array names _style2datasets] {
    709             set list {}
    710             foreach {dataobj cname} $_style2datasets($tf) break
    711             if { [info exists _serverDatasets($dataobj-$cname)] } {
    712                 lappend list $dataobj $cname
    713             }
    714             if { $list == "" } {
    715                 array unset _style2datasets $tf
    716             } else {
    717                 set _style2datasets($tf) $list
    718             }
    719         }
    720704        $_dispatcher event -idle !rebuild
    721705    }
     
    755739            set _limits($cname) $limits(v)
    756740        }
    757         foreach axis {x y z v} {
     741        foreach axis {x y z} {
    758742            foreach { min max } [$dataobj limits $axis] break
    759743            if {"" != $min && "" != $max} {
     
    831815                }
    832816                default {
    833                     error "bad download format $_downloadPopup(format)"
     817                    error "bad download format \"$_downloadPopup(format)\""
    834818                }
    835819            }
     
    914898
    915899    # disconnected -- no more data sitting on server
    916     array unset _serverDatasets
     900    array unset _datasets
    917901}
    918902
     
    964948    array set info $args
    965949    set bytes [ReceiveBytes $info(-bytes)]
    966     ReceiveEcho <<line "<read $info(-bytes) bytes"
    967     switch -- $info(-type)  {
     950    switch -- $info(-type) {
    968951        "image" {
     952            #puts stderr "received image [image width $_image(plot)]x[image height $_image(plot)]"
    969953            $_image(plot) configure -data $bytes
    970             #puts stderr "image received [image width $_image(plot)] by [image height $_image(plot)]"
    971954        }
    972955        "print" {
     
    979962        }
    980963        default {
    981             puts stderr "unknown download type $info(-type)"
     964            puts stderr "unknown image type $info(-type)"
    982965        }
    983966    }
     
    10551038#       The procedure is the response from the render server to each "data
    10561039#       follows" command.  The server sends back a "data" command invoked our
    1057 #       the slave interpreter.  The purpose is to collect the min/max of the
    1058 #       volume sent to the render server.  Since the client (flowvisviewer)
    1059 #       doesn't parse 3D data formats, we rely on the server (nanovis) to
    1060 #       tell us what the limits are.  Once we've received the limits to all
    1061 #       the data we've sent (tracked by _recvdDatasets) we can then determine
    1062 #       what the transfer functions are for these volumes.
    1063 #
    1064 #
    1065 #       Note: There is a considerable tradeoff in having the server report
    1066 #             back what the data limits are.  It means that much of the code
    1067 #             having to do with transfer-functions has to wait for the data
    1068 #             to come back, since the isomarkers are calculated based upon
    1069 #             the data limits.  The client code is much messier because of
    1070 #             this.  The alternative is to parse any of the 3D formats on the
    1071 #             client side.
     1040#       the slave interpreter.  The purpose was to collect the min/max of the
     1041#       volume sent to the render server.  This is no longer needed since we
     1042#       already know the limits.
    10721043#
    10731044itcl::body Rappture::FlowvisViewer::ReceiveData { args } {
     
    10801051
    10811052    set tag $info(tag)
    1082     set parts [split $tag -]
    1083 
    1084     #
    1085     # Volumes don't exist until we're told about them.
    1086     #
    1087     set dataobj [lindex $parts 0]
    1088     set _serverDatasets($tag) 0
    10891053    set _limits($tag) [list $info(min) $info(max)]
    1090 
    1091     unset _recvdDatasets($tag)
    1092     if { [array size _recvdDatasets] == 0 } {
    1093         updateTransferFunctions
    1094     }
    10951054}
    10961055
     
    11331092
    11341093    set _first ""
    1135     foreach dataobj [get] {
     1094    foreach dataobj [get -objects] {
     1095        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
     1096            set _first $dataobj
     1097        }
    11361098        foreach cname [$dataobj components] {
    11371099            set tag $dataobj-$cname
    1138             if {[$dataobj type] == "dx"} {
    1139                 set data [$dataobj blob $cname]
    1140             } else {
    1141                 set data [$dataobj vtkdata $cname]
    1142             }
    1143             set nbytes [string length $data]
    1144             if { $_reportClientInfo }  {
    1145                 set info {}
    1146                 lappend info "tool_id"       [$dataobj hints toolid]
    1147                 lappend info "tool_name"     [$dataobj hints toolname]
    1148                 lappend info "tool_title"    [$dataobj hints tooltitle]
    1149                 lappend info "tool_command"  [$dataobj hints toolcommand]
    1150                 lappend info "tool_revision" [$dataobj hints toolrevision]
    1151                 lappend info "dataset_label" [$dataobj hints label]
    1152                 lappend info "dataset_size"  $nbytes
    1153                 lappend info "dataset_tag"   $tag
    1154                 SendCmd "clientinfo [list $info]"
    1155             }
    1156             set numComponents [$dataobj numComponents $cname]
    1157             # I have a field. Is a vector field or a volume field?
    1158             if { $numComponents == 1 } {
    1159                 SendCmd "volume data follows $nbytes $tag"
    1160             } else {
    1161                 if {[SendFlowCmd $dataobj $cname $nbytes $numComponents] < 0} {
    1162                     continue
     1100            if { ![info exists _datasets($tag)] } {
     1101                if { [$dataobj type] == "dx" } {
     1102                    set data [$dataobj blob $cname]
     1103                } else {
     1104                    set data [$dataobj vtkdata $cname]
    11631105                }
    1164             }
    1165             SendData $data
    1166             NameTransferFunction $dataobj $cname
    1167             set _recvdDatasets($tag) 1
    1168         }
    1169     }
    1170 
    1171     set _first [lindex [get] 0]
     1106                set nbytes [string length $data]
     1107                if { $_reportClientInfo }  {
     1108                    set info {}
     1109                    lappend info "tool_id"       [$dataobj hints toolid]
     1110                    lappend info "tool_name"     [$dataobj hints toolname]
     1111                    lappend info "tool_title"    [$dataobj hints tooltitle]
     1112                    lappend info "tool_command"  [$dataobj hints toolcommand]
     1113                    lappend info "tool_revision" [$dataobj hints toolrevision]
     1114                    lappend info "dataset_label" [$dataobj hints label]
     1115                    lappend info "dataset_size"  $nbytes
     1116                    lappend info "dataset_tag"   $tag
     1117                    SendCmd "clientinfo [list $info]"
     1118                }
     1119                set numComponents [$dataobj numComponents $cname]
     1120                # I have a field. Is a vector field or a volume field?
     1121                if { $numComponents == 1 } {
     1122                    SendCmd "volume data follows $nbytes $tag"
     1123                } else {
     1124                    if {[SendFlowCmd $dataobj $cname $nbytes $numComponents] < 0} {
     1125                        continue
     1126                    }
     1127                }
     1128                SendData $data
     1129                set _datasets($tag) 1
     1130                NameTransferFunction $dataobj $cname
     1131            }
     1132        }
     1133    }
    11721134
    11731135    # Turn off cutplanes for all volumes
     
    11761138    }
    11771139
    1178     # Reset the camera and other view parameters
    1179     InitSettings -axesvisible -gridvisible \
    1180         -opacity -light2side -isosurfaceshading \
    1181         -light \
    1182         -volume -outlinevisible -cutplanesvisible \
     1140    InitSettings -volume -outlinevisible -cutplanesvisible \
    11831141        -xcutplanevisible -ycutplanevisible -zcutplanevisible \
    11841142        -xcutplaneposition -ycutplaneposition -zcutplaneposition
    11851143
    1186     # nothing to send -- activate the proper volume
     1144    if { $_reset } {
     1145        InitSettings -axesvisible -gridvisible \
     1146            -opacity -light2side -isosurfaceshading \
     1147            -light
     1148
     1149        #
     1150        # Reset the camera and other view parameters
     1151        #
     1152        if {"" != $_first} {
     1153            set axis [$_first hints updir]
     1154            if { "" != $axis } {
     1155                SendCmd "up $axis"
     1156            }
     1157            set location [$_first hints camera]
     1158            if { $location != "" } {
     1159                array set _view $location
     1160            }
     1161        }
     1162        set _settings(-qw)    $_view(-qw)
     1163        set _settings(-qx)    $_view(-qx)
     1164        set _settings(-qy)    $_view(-qy)
     1165        set _settings(-qz)    $_view(-qz)
     1166        set _settings(-xpan)  $_view(-xpan)
     1167        set _settings(-ypan)  $_view(-ypan)
     1168        set _settings(-zoom)  $_view(-zoom)
     1169
     1170        set q [ViewToQuaternion]
     1171        $_arcball quaternion $q
     1172        SendCmd "camera orient $q"
     1173        SendCmd "camera reset"
     1174        PanCamera
     1175        SendCmd "camera zoom $_view(-zoom)"
     1176    }
     1177
    11871178    if {"" != $_first} {
    1188         set axis [$_first hints updir]
    1189         if {"" != $axis} {
    1190             SendCmd "up $axis"
    1191         }
    1192         set location [$_first hints camera]
    1193         if { $location != "" } {
    1194             array set _view $location
    1195         }
    1196     }
    1197     set _settings(-qw)    $_view(-qw)
    1198     set _settings(-qx)    $_view(-qx)
    1199     set _settings(-qy)    $_view(-qy)
    1200     set _settings(-qz)    $_view(-qz)
    1201     set _settings(-xpan)  $_view(-xpan)
    1202     set _settings(-ypan)  $_view(-ypan)
    1203     set _settings(-zoom)  $_view(-zoom)
    1204 
    1205     set q [ViewToQuaternion]
    1206     $_arcball quaternion $q
    1207     SendCmd "camera orient $q"
    1208     SendCmd "camera reset"
    1209     PanCamera
    1210     SendCmd "camera zoom $_view(-zoom)"
    1211 
    1212     foreach dataobj [get] {
    1213         foreach cname [$dataobj components] {
    1214             NameTransferFunction $dataobj $cname
    1215         }
    1216     }
    1217 
    1218     # nothing to send -- activate the proper ivol
    1219     set _first [lindex [get] 0]
    1220     if {"" != $_first} {
    1221         set axis [$_first hints updir]
    1222         if {"" != $axis} {
    1223             SendCmd "up $axis"
    1224         }
    1225         set location [$_first hints camera]
    1226         if { $location != "" } {
    1227             array set _view $location
    1228         }
    12291179        set cname [lindex [$_first components] 0]
    12301180        set _activeTf [lindex $_dataset2style($_first-$cname) 0]
    1231     }
    1232 
    1233     # sync the state of slicers
    1234     set vols [CurrentDatasets -cutplanes]
    1235     foreach axis {x y z} {
    1236         set pos [expr {0.01*$_settings(-${axis}cutplaneposition)}]
    1237         SendCmd "cutplane position $pos $axis $vols"
    1238     }
    1239     SendCmd "volume data state $_settings(-volume)"
    1240     EventuallyRedrawLegend
     1181        # Make sure we display the proper transfer function in the legend.
     1182        updateTransferFunctions
     1183    }
    12411184
    12421185    # Actually write the commands to the server socket.  If it fails, we don't
     
    12561199# ----------------------------------------------------------------------
    12571200itcl::body Rappture::FlowvisViewer::CurrentDatasets {{what -all}} {
    1258     return ""
     1201    set rlist ""
    12591202    if { $_first == "" } {
    12601203        return
    12611204    }
    1262     foreach tag [array names _serverDatasets *-*] {
    1263         if {[string match $_first-* $tag]} {
     1205    foreach cname [$_first components] {
     1206        set tag $_first-$cname
     1207        if { [info exists _datasets($tag)] && $_datasets($tag) } {
    12641208            array set style {
    12651209                -cutplanes 1
    12661210            }
    1267             foreach {dataobj cname} [split $tag -] break
    1268             array set style [lindex [$dataobj components -style $cname] 0]
    1269             if {$what != "-cutplanes" || $style(-cutplanes)} {
    1270                 lappend rlist $_serverDatasets($tag)
     1211            array set style [lindex [$_first components -style $cname] 0]
     1212            if { $what != "-cutplanes" || $style(-cutplanes) } {
     1213                lappend rlist $tag
    12711214            }
    12721215        }
     
    19161859
    19171860itcl::body Rappture::FlowvisViewer::limits { cname } {
    1918     set _limits(v) [list 0.0 1.0]
    1919     if { ![info exists _style2datasets($cname)] } {
    1920         puts stderr "no _style2datasets for cname=($cname)"
    1921         return [array get _limits]
    1922     }
    1923     set min ""; set max ""
    1924     foreach tag [GetDatasetsWithComponent $cname] {
    1925         if { ![info exists _serverDatasets($tag)] } {
    1926             puts stderr "$tag not in _serverDatasets?"
    1927             continue
    1928         }
    1929         if { ![info exists _limits($tag)] } {
    1930             puts stderr "$tag no min?"
    1931             continue
    1932         }
    1933         foreach {vmin vmax} $_limits($tag) break
    1934         if { $min == "" || $min > $vmin } {
    1935             set min $vmin
    1936         }
    1937         if { $max == "" || $max < $vmax } {
    1938             set max $vmax
    1939         }
    1940     }
    1941     if { $min != "" && $max != "" } {
    1942         set _limits(v) [list $min $max]
    1943         set _limits($cname) [list $min $max]
     1861    if { ![info exists _limits($cname)] } {
     1862        puts stderr "no limits for cname=($cname)"
     1863        return [list 0.0 1.0]
    19441864    }
    19451865    return $_limits($cname)
     
    29742894    set list ""
    29752895    foreach tag $_volcomponents($cname) {
    2976         if { ![info exists _serverDatasets($tag)] } {
     2896        if { ![info exists _datasets($tag)] } {
    29772897            continue
    29782898        }
  • branches/1.4/gui/scripts/nanovisviewer.tcl

    r5623 r5643  
    121121    private variable _dlist ""         ;# list of data objects
    122122    private variable _obj2ovride       ;# maps dataobj => style override
    123     private variable _serverDatasets   ;# contains all the dataobj-component
     123    private variable _datasets         ;# contains all the dataobj-component
    124124                                       ;# to volumes in the server
    125     private variable _recvdDatasets    ;# list of data objs to send to server
    126125
    127126    private variable _reset 1          ;# Connection to server has been reset.
     
    196195    $_arcball quaternion [ViewToQuaternion]
    197196
    198     set _limits(v) [list 0.0 1.0]
    199197    set _reset 1
    200198
     
    342340    bind $itk_component(3dview) <ButtonRelease-1> \
    343341        [itcl::code $this Rotate release %x %y]
     342
    344343    bind $itk_component(3dview) <Configure> \
    345344        [itcl::code $this EventuallyResize %w %h]
     
    560559            set _limits($cname) $limits(v)
    561560        }
    562         foreach axis {x y z v} {
     561        foreach axis {x y z} {
    563562            foreach { min max } [$dataobj limits $axis] break
    564563            if {"" != $min && "" != $max} {
     
    629628                    return [$this GetVtkData [lindex $args 0]]
    630629                }
    631             }
    632             return ""
     630                default {
     631                    error "bad download format \"$_downloadPopup(format)\""
     632                }
     633            }
    633634        }
    634635        default {
     
    711712
    712713    # disconnected -- no more data sitting on server
    713     array unset _serverDatasets
     714    array unset _datasets
    714715}
    715716
     
    739740    array set info $args
    740741    set bytes [ReceiveBytes $info(-bytes)]
    741     ReceiveEcho <<line "<read $info(-bytes) bytes"
    742     if { $info(-type) == "image" } {
    743         ReceiveEcho "for [image width $_image(plot)]x[image height $_image(plot)] image>"
    744         $_image(plot) configure -data $bytes
    745     } elseif { $info(-type) == "print" } {
    746         set tag $this-print-$info(-token)
    747         set _hardcopy($tag) $bytes
     742    switch -- $info(-type) {
     743        "image" {
     744            #puts stderr "received image [image width $_image(plot)]x[image height $_image(plot)]"
     745            $_image(plot) configure -data $bytes
     746        }
     747        "print" {
     748            set tag $this-print-$info(-token)
     749            set _hardcopy($tag) $bytes
     750        }
     751        default {
     752            puts stderr "unknown image type $info(-type)"
     753        }
    748754    }
    749755}
     
    820826#       The procedure is the response from the render server to each "data
    821827#       follows" command.  The server sends back a "data" command invoked our
    822 #       the slave interpreter.  The purpose is to collect the min/max of the
    823 #       volume sent to the render server.  Since the client (nanovisviewer)
    824 #       doesn't parse 3D data formats, we rely on the server (nanovis) to
    825 #       tell us what the limits are.  Once we've received the limits to all
    826 #       the data we've sent (tracked by _recvdDatasets) we can then determine
    827 #       what the transfer functions are for these volumes.
    828 #
    829 #
    830 #       Note: There is a considerable tradeoff in having the server report
    831 #             back what the data limits are.  It means that much of the code
    832 #             having to do with transfer-functions has to wait for the data
    833 #             to come back, since the isomarkers are calculated based upon
    834 #             the data limits.  The client code is much messier because of
    835 #             this.  The alternative is to parse any of the 3D formats on the
    836 #             client side.
     828#       the slave interpreter.  The purpose was to collect the min/max of the
     829#       volume sent to the render server.  This is no longer needed since we
     830#       already know the limits.
    837831#
    838832itcl::body Rappture::NanovisViewer::ReceiveData { args } {
     
    845839
    846840    set tag $info(tag)
    847     set parts [split $tag -]
    848 
    849     #
    850     # Volumes don't exist until we're told about them.
    851     #
    852     set dataobj [lindex $parts 0]
    853     set _serverDatasets($tag) 1
    854     if { $_settings(-volumevisible) && $dataobj == $_first } {
    855         SendCmd "volume state 1 $tag"
    856     }
    857     set _limits($tag) [list $info(min)  $info(max)]
    858     set _limits(v)    [list $info(vmin) $info(vmax)]
    859 
    860     unset _recvdDatasets($tag)
    861     if { [array size _recvdDatasets] == 0 } {
    862         updateTransferFunctions
    863     }
     841    set _limits($tag) [list $info(min) $info(max)]
    864842}
    865843
     
    892870    }
    893871
    894     foreach dataobj [get] {
     872    set _first ""
     873    SendCmd "volume state 0"
     874    foreach dataobj [get -objects] {
     875        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
     876            set _first $dataobj
     877        }
    895878        foreach cname [$dataobj components] {
    896879            set tag $dataobj-$cname
    897             if { ![info exists _serverDatasets($tag)] } {
    898                 # Send the data as one huge base64-encoded mess -- yuck!
     880            if { ![info exists _datasets($tag)] } {
    899881                if { [$dataobj type] == "dx" } {
    900                     if { ![$dataobj isvalid] } {
    901                         puts stderr "??? $dataobj is invalid"
    902                     }
    903882                    set data [$dataobj blob $cname]
    904883                } else {
     
    926905                SendCmd "volume data follows $nbytes $tag"
    927906                SendData $data
    928                 set _recvdDatasets($tag) 1
    929                 set _serverDatasets($tag) 0
     907                set _datasets($tag) 1
    930908            }
    931909            SetObjectStyle $dataobj $cname
    932         }
    933     }
    934     set _first [lindex [get] 0]
     910            if { [info exists _obj2ovride($dataobj-raise)] } {
     911                SendCmd "volume state 1 $tag"
     912            }
     913        }
     914    }
    935915    # Outline seems to need to be reset every update.
    936916    InitSettings -outlinevisible -cutplanesvisible
    937917    if { $_reset } {
     918        # Turn off cutplanes for all volumes
     919        foreach axis {x y z} {
     920            SendCmd "cutplane state 0 $axis"
     921        }
     922
     923        InitSettings -axesvisible -gridvisible \
     924            -light2side -isosurfaceshading -opacity \
     925            -light \
     926            -xcutplanevisible -ycutplanevisible -zcutplanevisible \
     927            -current
     928
    938929        #
    939930        # Reset the camera and other view parameters
    940931        #
     932        if {"" != $_first} {
     933            set axis [$_first hints updir]
     934            if { "" != $axis } {
     935                SendCmd "up $axis"
     936            }
     937            set location [$_first hints camera]
     938            if { $location != "" } {
     939                array set _view $location
     940            }
     941        }
    941942        set _settings(-qw)    $_view(-qw)
    942943        set _settings(-qx)    $_view(-qx)
     
    953954        PanCamera
    954955        SendCmd "camera zoom $_view(-zoom)"
    955 
    956         # Turn off cutplanes for all volumes
    957         foreach axis {x y z} {
    958             SendCmd "cutplane state 0 $axis"
    959         }
    960 
    961         InitSettings -axesvisible -gridvisible \
    962             -light2side -isosurfaceshading -opacity \
    963             -light \
    964             -xcutplanevisible -ycutplanevisible -zcutplanevisible \
    965             -current
    966 
    967         if {"" != $_first} {
    968             set axis [$_first hints updir]
    969             if { "" != $axis } {
    970                 SendCmd "up $axis"
    971             }
    972             set location [$_first hints camera]
    973             if { $location != "" } {
    974                 array set _view $location
    975             }
    976         }
    977     }
    978 
    979     # nothing to send -- activate the proper ivol
    980     SendCmd "volume state 0"
     956    }
     957
    981958    if {"" != $_first} {
    982         set datasets [array names _serverDatasets $_first-*]
    983         if { $datasets != "" } {
    984             SendCmd "volume state 1 $datasets"
    985         }
    986         # If the first volume already exists on the server, then make sure
    987         # we display the proper transfer function in the legend.
    988         set cname [lindex [$_first components] 0]
    989         if { [info exists _serverDatasets($_first-$cname)] } {
    990             updateTransferFunctions
    991         }
     959        # Make sure we display the proper transfer function in the legend.
     960        updateTransferFunctions
    992961    }
    993962    # Actually write the commands to the server socket.  If it fails, we don't
     
    1013982    foreach cname [$_first components] {
    1014983        set tag $_first-$cname
    1015         if { [info exists _serverDatasets($tag)] && $_serverDatasets($tag) } {
     984        if { [info exists _datasets($tag)] && $_datasets($tag) } {
    1016985            array set style {
    1017986                -cutplanes 1
     
    13051274        "-volume" {
    13061275            # This is the global volume visibility control.  It controls the
    1307             # visibility of all the all volumes.  Whenever it's changed, you
    1308             # have to synchronize each of the local controls (see below) with
    1309             # this.
     1276            # visibility of all the volumes.  Whenever it's changed, you have
     1277            # to synchronize each of the local controls (see below) with this.
    13101278            set datasets [CurrentDatasets]
    13111279            set bool $_settings($what)
     
    21592127    set list ""
    21602128    foreach tag $_volcomponents($cname) {
    2161         if { ![info exists _serverDatasets($tag)] } {
     2129        if { ![info exists _datasets($tag)] } {
    21622130            continue
    21632131        }
Note: See TracChangeset for help on using the changeset viewer.