Generic Topology ViewerPygame based display of graph topologies. A simple physics model assists with visual layout. Rendering and physics laws can be customised for specific applications. Example UsageA simple console driven topology viewer: Pipeline( ConsoleReader(), lines_to_tokenlists(), TopologyViewer(), ).run() Then at runtime try typing these commands to change the topology in real time: >>> DEL ALL >>> ADD NODE 1 "1st node" randompos - >>> ADD NODE 2 "2nd node" randompos - >>> ADD NODE 3 "3rd node" randompos - >>> ADD LINK 1 2 >>> ADD LINK 3 2 >>> DEL LINK 1 2 >>> DEL NODE 1 User InterfaceTopologyViewer manifests as a pygame display surface. As it is sent topology information nodes and links between them will appear. You can click a node with the mouse to select it. Depending on the application, this may display additional data or, if integrated into another app, have some other effect. Click and drag with the left mouse button to move nodes around. Note that a simple physics model or repulsion and attraction forces is always active. This causes nodes to move around to help make it visually clearer, however you may still need to drag nodes about to tidy it up. The surface on which the nodes appear is notionally infinite. Scroll around using the arrow keys. Press the 'f' key to toggle between windowed and fullscreen modes. How does it work?TopologyViewer is a specialisation of the Kamaeila.UI.MH.PyGameApp component. See documentation for that component to understand how it obtains and handles events for a pygame display surface. A topology (graph) of nodes and links between them is rendered to the surface. You can specify an initial topology by providing a list of instantiated particles and another list of pairs of those particles to show how they are linked. TopologyViewer reponds to commands arriving at its "inbox" inbox instructing it on how to change the topology. A command is a list/tuple. Commands recognised are:
Commands are processed immediately, in the order in which they arrive. You therefore cannot refer to a node or linkage that has not yet been created, or that has already been destroyed. If a stream of commands arrives in quick succession, rendering and physics will be temporarily stopped, so commands can be processed more quickly. This is necessary because when there is a large number of particles, physics and rendering starts to take a long time, and will therefore bottleneck the handling of commands. However, there is a 1 second timeout, so at least one update of the visual output is guaranteed per second. TopologyViewer sends any output to its "outbox" outbox in the same list/tuple format as used for commands sent to its "inbox" inbox. The following may be output:
TerminationIf a shutdownMicroprocess message is received on this component's "control" inbox this it will pass it on out of its "signal" outbox and immediately terminate. Historical note for short term: this has changed as of May 2008. In the past, this component would also shutdown when it recieved a producerFinished message. This has transpired to be a mistake for a number of different systems, hence the change to only shutting down when it recieves a shutdownMicroprocess message. NOTE: Termination is currently rather cludgy - it raises an exception which will cause the rest of a kamaelia system to halt. Do not rely on this behaviour as it will be changed to provide cleaner termination at some point. Customising the topology viewerYou can customise:
For example, see Kamaelia.Visualisation.Axon.AxonVisualiserServer. This component uses two types of particle - to represent components and inboxes/outboxes. Each has a different visual appearance, and the laws acting between them differ depending on which particle types are involved in the interaction. Use the particleTypes argument of the initialiser to specify classes that should be instantiated to render each type of particle (nodes). particleTypes should be a dictionary mapping names for particle types to the respective classes, for example: { "major" : BigParticle, "minor" : SmallParticle } See below for information on how to write your own particle classes. Layout of the nodes on the surface is assisted by a physics model, provided by an instance of the Kamaelia.Support.Particles.ParticleSystem class. Customise the laws used for each particle type by providing a Kamaelia.Phyics.Simple.MultipleLaws object at initialisation. Writing your own particle classshould inherit from Kamaelia.Support.Particles.Particle and implement the following methods (for rendering purposes):
The coordinates of the particle are updated automatically both due to mouse dragging and due to the physics model. See Kamaelia.Support.Particles.Particle for more information. The render(...) method should return a generator that will render the particle itself and its links/bonds to other particles. Rendering by the TopologyViewer is multi-pass. This is done so that irrespective of the order in which particles are chosen to be rendered, things that need to be rendered before (underneath) other things can be done consistently. The generator should yield the number of the rendering pass it wishes to be next called on. Each time it is subsequently called, it should perform the rendering required for that pass. It then yields the number of the next required pass or completes if there is no more rendering required. Passes go in ascending numerical order. For example, Kamaelia.Visualisation.PhysicsGraph.RenderingParticle renders in two passes: def render(self, surface): yield 1 # render lines for bonds *from* this particle *to* others yield 2 # render a blob and the name label for the particle ...in this case it ensures that the blobs for the particles always appear on top of the lines representing the bonds between them. Note that rendering passes must be coded in ascending order, but the numbering can otherwise be arbitrary: The first pass can be any value you like; subsequent passes can also be any value, provided it is higher. When writing rendering code for particle(s), make sure they all agree on who should render what. It is inefficient if all bonds are being rendered twice. For example, RenderingParticle only renders links from that particle to another, but not in another direction. Kamaelia.Visualisation.PhysicsGraph.TopologyViewer.TopologyViewerclass TopologyViewer(Kamaelia.UI.MH.PyGameApp, Axon.Component.component)TopologyViewer(...) -> new TopologyViewer component. A component that takes incoming topology (change) data and displays it live using pygame. A simple physics model assists with visual layout. Particle types, appearance and physics interactions can be customised. Keyword arguments (in order):
Inboxes
Outboxes
Methods defined hereWarning! You should be using the inbox/outbox interface, not these methods (except construction). This documentation is designed as a roadmap as to their functionalilty for maintainers and new component developers. __init__(self[, screensize][, fullscreen][, caption][, particleTypes][, initialTopology][, laws][, simCyclesPerRedraw][, border][, extraDrawing][, showGrid][, transparency][, position])x.__init__(...) initializes x; see x.__class__.__doc__ for signature _generateXY(self, posSpec)generateXY(posSpec) -> (x,y) or raises ValueError posSpec == "randompos" or "auto" -> random (x,y) within the surface (specified border distance in from the edege) posSpec == "(XXX,YYY)" -> specified x,y (positive or negative integers) addParticle(self, *particles)Add particles to the system breakBond(self, source, dest)Break a bond from source to destination particle, specified by IDs doCommand(self, msg)Proceses a topology command tuple: [ "ADD", "NODE", <id>, <name>, <positionSpec>, <particle type> ] [ "DEL", "NODE", <id> ] [ "ADD", "LINK", <id from>, <id to> ] [ "DEL", "LINK", <id from>, <id to> ] [ "DEL", "ALL" ] [ "GET", "ALL" ] getParticleLabel(self, node_id)getParticleLabel(node_id) -> particle's name Returns the name/label of the specified particle. getTopology(self)getTopology() -> list of command tuples that would build the current topology initialiseComponent(self)Initialises. keyDownHandler(self, event)Handle keypresses: ESCAPE, Q : quits F : toggles fullscreen mode arrows : scroll the view keyUpHandler(self, event)Handle releases of keys mainLoop(self)Main loop. Proceses commands from "inbox" inbox, runs physics simulation, then renders display FIXME: This is massively broken, this component overrides initialiseComponent, and also has a main AND has a mainLoop. makeBond(self, source, dest)Make a bond from source to destination particle, specified by IDs quit(self[, event])Cause termination. removeParticle(self, *ids)Remove particle(s) specified by their ids. Also breaks any bonds to/from that particle. render(self)Render elements to self.screen scroll(self, ('dx', 'dy'))Scroll the contents being displayed on the surface by (dx,dy) left and up. selectParticle(self, particle)Select the specified particle. updateParticleLabel(self, node_id, new_name)updateParticleLabel(node_id, new_name) -> updates the given nodes name & visual label if it exists node_id - an id for an already existing node new_name - a string (may include spaces) defining the new node name FeedbackGot a problem with the documentation? Something unclear that could be clearer? Want to help improve it? Constructive criticism is very welcome - especially if you can suggest a better rewording! Please leave you feedback here in reply to the documentation thread in the Kamaelia blog. -- Automatic documentation generator, 05 Jun 2009 at 03:01:38 UTC/GMT |
Kamaelia
is an open source project originated from and guided by BBC
Research. For more information browse the site or get in
contact.
This is an ongoing community based development site. As a result the contents of this page is the opinions of the contributors of the pages involved not the organisations involved. Specificially, this page may contain personal views which are not the views of the BBC. (the site is powered by a wiki engine)
(C) Copyright 2008 Kamaelia Contributors, including the British Broadcasting Corporation, All Rights Reserved.