Making Collaborations

October, 2001

Introduction

When you want to share your applications in a collaboration where more than one person can view and/or manipulate the displays, VisAD's inherent use of RMI and the easy-to-use interfaces that Dave Glowacki put together are just what you need.

In this section, we'll modify the so-called "T7" example to act as a server, and then create two clients:

  1. will be only able to look at the brightness vs. element graph
  2. will be able to fully interact with the display

 

The changes to the T7 example to make a server

What is needed is to create a server and add to it both the Displays and all the necessary DataReference objects. Just add this code to the bottom of the Python source code:
from visad.util import ClientServer
# add everything to the server
server = ClientServer.startServer("Jython")
server.addDisplay(d1)
server.addDisplay(d2)
server.addDataReference(refimg)
server.addDataReference(userline)

The startServer() method creates the needed object and tags it with a unique name ("Jython" in this case) that is used to connect the server and clients.

The addDisplay() and addDataReference() methods make the Displays and DataReferences previously defined available to the clients. The ones that are named here are just those required for the collaboration programs we want to make.

 

The smallest useful VisAD application ever written (?)

The "listen-only" client is almost trivial to code:
from visad.python.JPythonMethods import *
import subs
from visad.util import ClientServer

# fetch everything from the server
client = ClientServer.connectToServer("localhost", "Jython")
d2 = ClientServer.getClientDisplay(client, 1)

#show it
showAxesScales(d2,1)
subs.showDisplay(d2,500,500,"T8 listener")


Seriously, that is all it takes!!

The connectToServer() method will go to the machine named (in this case, it is just localhost, since this is run on the same machine as the server for testing; normally, you would name the host machine as the first paramter. For example:

client = ClientServer.connectToServer("allegro.ssec.wisc.edu", "Jython")

The getClientDisplay() method will fetch any of the DisplayImpls defined in the server. In this case, we want the right-most DisplayImpl, which was the second one added (see previous section).

The rest of this "program" consists of turning on the axes scales and then simply showing the display. What could be easier?

 

A more interactive client

While the listen-only mode may be appropriate in some cases, one can certainly define a full-blown interactive client as well. Here's the code:

from visad.python.JPythonMethods import *
from visad.util import VisADSlider, ClientServer
from javax.swing import JFrame, JPanel
from java.awt import BorderLayout, GridLayout, Font

# fetch everything from the server
client = ClientServer.connectToServer("localhost", "Jython")
d1 = ClientServer.getClientDisplay(client, 0)
d2 = ClientServer.getClientDisplay(client, 1)
refimg = client.getDataReference(0)
userline = client.getDataReference(1)

image = refimg.getData()

dom = getDomain(image)
LINES = dom.getY().getLength()

d = domainType(image)
slide = VisADSlider("imgline",0,LINES,0,1.0,userline,d[1])

showAxesScales(d2,1)

# display everything...
frame = JFrame("Test T8 Client")
pane = frame.getContentPane()
pane.setLayout(BorderLayout())
panel = JPanel(GridLayout(1,2,5,5))
panel.add(d1.getComponent())
panel.add(d2.getComponent())
pane.add("Center",panel)
pane.add("North",slide)
frame.setSize(800,500)
frame.setVisible(1)


Again, it is not too long, is it? We want to create a more specialized display, so we must use the Java Swing approach (all that Panel and JFrame stuff at the end - which you will note is identical to what is in the "server"). Up to that point, however, we are using only the necessary pieces from the server's Display and DataReferences to allow us to make the slider and show both panels.

The need: we want to make a two panel display. On the left panel should be an image that we import, and it will have a movable horizontal line. On the right, the brightness values will be plotted on a 2D graph, for the image line corresponding to the position of the moveable horizontal line on the left.

The VisADSlider requires the number of lines in the image, and a reference to the userline so that it can automatically communicate changes back to the server. In order to do that, we must get the domain and the domain type from the original image. Fortunately, the getDataReference() method gets us the reference from which we can obtain this information.

The server

Here is the revised code for the T7 example which makes it a "server":

from visad.python.JPythonMethods import *
import subs
from visad.java2d import *
from visad import DataReferenceImpl,CellImpl,Real, AxisScale
 
from visad.util import VisADSlider
from javax.swing import JFrame, JPanel
from java.awt import BorderLayout, GridLayout, Font

image = load("../data/mcidas/AREA0001")
#image=load("adde://image?")
print "Done reading data..."

dom = getDomain(image)
d = domainType(image)
r = rangeType(image)

# max lines & elements of image
NELE = dom.getX().getLength()
LINES = dom.getY().getLength()

# subs for image in display-1
m = subs.makeMaps(d[0],"x",d[1],"y",r[0],"rgb")
d1 = subs.makeDisplay(m)
# add the image to the display
refimg = subs.addData("image", image, d1)

# now the second panel
m2 = subs.makeMaps(d[0],"x",r[0],"y",d[1],"selectvalue")
m2[0].setRange(0,NELE-1)
m2[1].setRange(0,255)
d2 = subs.makeDisplay(m2)

# get the desired format of the Data (line->(element->value))
byline = domainFactor(image,d[1])
ref2 = subs.addData("imageline", byline, d2)

# also, set up a dummy reference so we can put the line onto the display
usref = subs.addData("line", None, d1)

# define an inner-type CellImpl class to handle changes
class MyCell(CellImpl):
 def doAction(this):
  line = (LINES-1) - (userline.getData()).getValue()
  pts = subs.makeLine( (d[1], d[0]), ((line,line),(0,NELE)))
  usref.setData(pts)
  ff = byline.evaluate(Real(line))
  ref2.setData(ff)

# make a DataReference that we can use later to change the value of "line"
userline = DataReferenceImpl("userline")
slide = VisADSlider("imgline",0,LINES,0,1.0,userline,d[1])

cell = MyCell();
cell.addReference(userline)

# change the scale label on x axis
xscale=AxisScale(m2[0],label="Element position in image")
showAxesScales(d2,1)

subs.setBoxSize(d1,.80)
subs.setBoxSize(d2,.80)

# display everything...
frame = JFrame("Test T8 Server")
pane = frame.getContentPane()
pane.setLayout(BorderLayout())
panel = JPanel(GridLayout(1,2,5,5))
panel.add(d1.getComponent())
panel.add(d2.getComponent())
pane.add("Center",panel)
pane.add("North",slide)
frame.setSize(800,500)
frame.setVisible(1)

from visad.util import ClientServer
# add everything to the server
server = ClientServer.startServer("Jython")
server.addDisplay(d1)
server.addDisplay(d2)
server.addDataReference(refimg)
server.addDataReference(userline)
server.addDataReference(ref2)
server.addDataReference(usref)



Back to the home page