2 from __future__
import division
5 LAYOUT_ALGORITHM =
'neato'
6 REPRESENT_CHANNELS_AS_NODES = 1
7 DEFAULT_NODE_SIZE = 3.0
8 DEFAULT_TRANSMISSIONS_MEMORY = 5
13 PRIORITY_UPDATE_MODEL = -100
14 PRIORITY_UPDATE_VIEW = 200
17 if platform.system() ==
"Windows":
18 SHELL_FONT =
"Lucida Console 9"
20 SHELL_FONT =
"Luxi Mono 10"
45 from higcontainer
import HIGContainer
46 gobject.threads_init()
51 except ImportError, _import_error:
52 import dummy_threading
as threading
61 from base
import InformationWindow, PyVizObject, Link, lookup_netdevice_traits, PIXELS_PER_METER
62 from base
import transform_distance_simulation_to_canvas, transform_point_simulation_to_canvas
63 from base
import transform_distance_canvas_to_simulation, transform_point_canvas_to_simulation
64 from base
import load_plugins, register_plugin, plugins
67 PI_TIMES_2 = math.pi*2
109 'query-extra-tooltip-info': (gobject.SIGNAL_RUN_LAST,
None, (object,)),
113 """ Initialize function.
114 @param self The object pointer.
115 @param visualizer: visualizer object
116 @param node_index: node index
123 self.canvas_item.set_data(
"pyviz-object", self)
141 def set_svg_icon(self, file_base_name, width=None, height=None, align_x=0.5, align_y=0.5):
143 Set a background SVG icon for the node.
145 @param file_base_name: base file name, including .svg
146 extension, of the svg file. Place the file in the folder
147 src/contrib/visualizer/resource.
149 @param width: scale to the specified width, in meters
150 @param height: scale to the specified height, in meters
152 @param align_x: horizontal alignment of the icon relative to
153 the node position, from 0 (icon fully to the left of the node)
154 to 1.0 (icon fully to the right of the node)
156 @param align_y: vertical alignment of the icon relative to the
157 node position, from 0 (icon fully to the top of the node) to
158 1.0 (icon fully to the bottom of the node)
160 @return a ValueError exception if invalid dimensions.
163 if width
is None and height
is None:
164 raise ValueError(
"either width or height must be given")
165 rsvg_handle = svgitem.rsvg_handle_factory(file_base_name)
166 x = self.canvas_item.props.center_x
167 y = self.canvas_item.props.center_y
169 self.svg_item.props.parent = self.visualizer.canvas.get_root_item()
170 self.svg_item.props.pointer_events = 0
171 self.svg_item.lower(
None)
172 self.svg_item.props.visibility = goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD
173 if width
is not None:
175 if height
is not None:
189 Set a label for the node.
191 @param self: class object.
192 @param label: label to set
194 @return: an exception if invalid parameter.
196 assert isinstance(label, basestring)
204 @param self: class object.
209 w = self.svg_item.width
210 h = self.svg_item.height
211 self.svg_item.set_properties(x=(x - (1-self.
svg_align_x)*w),
219 @param self: class object.
220 @param tooltip: tooltip
223 self.visualizer.simulation.lock.acquire()
225 ns3_node = ns.network.NodeList.GetNode(self.
node_index)
226 ipv4 = ns3_node.GetObject(ns.internet.Ipv4.GetTypeId())
227 ipv6 = ns3_node.GetObject(ns.internet.Ipv6.GetTypeId())
229 name =
'<b><u>Node %i</u></b>' % self.
node_index
230 node_name = ns.core.Names.FindName (ns3_node)
231 if len(node_name)!=0:
232 name +=
' <b>(' + node_name +
')</b>'
237 self.emit(
"query-extra-tooltip-info", lines)
239 mob = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
241 lines.append(
' <b>Mobility Model</b>: %s' % mob.GetInstanceTypeId().GetName())
243 for devI
in range(ns3_node.GetNDevices()):
245 lines.append(
' <u>NetDevice %i:</u>' % devI)
246 dev = ns3_node.GetDevice(devI)
247 name = ns.core.Names.FindName(dev)
249 lines.append(
' <b>Name:</b> %s' % name)
250 devname = dev.GetInstanceTypeId().GetName()
251 lines.append(
' <b>Type:</b> %s' % devname)
254 ipv4_idx = ipv4.GetInterfaceForDevice(dev)
257 '%s/%s' % (ipv4.GetAddress(ipv4_idx, i).GetLocal(),
258 ipv4.GetAddress(ipv4_idx, i).GetMask())
259 for i
in range(ipv4.GetNAddresses(ipv4_idx))]
260 lines.append(
' <b>IPv4 Addresses:</b> %s' %
'; '.join(addresses))
263 ipv6_idx = ipv6.GetInterfaceForDevice(dev)
266 '%s/%s' % (ipv6.GetAddress(ipv6_idx, i).GetAddress(),
267 ipv6.GetAddress(ipv6_idx, i).GetPrefix())
268 for i
in range(ipv6.GetNAddresses(ipv6_idx))]
269 lines.append(
' <b>IPv6 Addresses:</b> %s' %
'; '.join(addresses))
271 lines.append(
' <b>MAC Address:</b> %s' % (dev.GetAddress(),))
273 tooltip.set_markup(
'\n'.join(lines))
275 self.visualizer.simulation.lock.release()
279 On Enter event handle.
281 @param self: class object.
283 @param target: target
290 On Leave event handle.
292 @param self: class object.
294 @param target: target
302 Set selected function.
304 @param self: class object.
305 @param value: selected value
312 Get selected function.
314 @param self: class object.
315 @return selected status
319 selected = property(_get_selected, _set_selected)
323 Set highlighted function.
325 @param self: class object.
326 @param value: selected value
333 Get highlighted function.
335 @param self: class object.
336 @return highlighted status
340 highlighted = property(_get_highlighted, _set_highlighted)
346 @param self: class object.
347 @param size: selected size
355 Update the node aspect to reflect the selected/highlighted state
357 @param self: class object.
366 fill_color_rgba = (self.
_color & 0xffffff00) | alpha
367 self.canvas_item.set_properties(radius_x=size, radius_y=size,
368 fill_color_rgba=fill_color_rgba)
372 line_width = size*.15
374 stroke_color =
'yellow'
376 stroke_color =
'black'
377 self.canvas_item.set_properties(line_width=line_width, stroke_color=stroke_color)
379 if self.
_label is not None:
382 font=
"Sans Serif 10",
383 fill_color_rgba=0x808080ff,
384 alignment=pango.ALIGN_CENTER,
386 parent=self.visualizer.canvas.get_root_item(),
388 self._label_canvas_item.lower(
None)
390 self._label_canvas_item.set_properties(visibility=goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD,
396 Set position function.
398 @param self: class object.
403 self.canvas_item.set_property(
"center_x", x)
404 self.canvas_item.set_property(
"center_y", y)
408 for link
in self.
links:
412 self._label_canvas_item.set_properties(x=x, y=(y+self.
_size*3))
416 Get position function.
418 @param self: class object.
419 @return x and y position
421 return (self.canvas_item.get_property(
"center_x"), self.canvas_item.get_property(
"center_y"))
425 Update position function.
427 @param self: class object.
437 @param self: class object.
438 @param color: color to set.
441 if isinstance(color, str):
442 color = gtk.gdk.color_parse(color)
443 color = ((color.red>>8) << 24) | ((color.green>>8) << 16) | ((color.blue>>8) << 8) | 0xff
451 @param self: class object.
452 @param link: link to add.
455 assert isinstance(link, Link)
456 self.links.append(link)
460 Remove link function.
462 @param self: class object.
463 @param link: link to add.
466 assert isinstance(link, Link)
467 self.links.remove(link)
472 Has mobility function.
474 @param self: class object.
475 @return modility option
478 node = ns.network.NodeList.GetNode(self.
node_index)
479 mobility = node.GetObject(ns.mobility.MobilityModel.GetTypeId())
495 Initializer function.
497 @param self: class object.
498 @param channel: channel.
504 stroke_color=
"grey", line_width=2.0,
505 line_dash=goocanvas.LineDash([10.0, 10.0 ]),
506 visibility=goocanvas.ITEM_VISIBLE)
507 self.canvas_item.set_data(
"pyviz-object", self)
512 Initializer function.
514 @param self: class object.
515 @param x: x position.
516 @param y: y position.
519 self.canvas_item.set_property(
"center_x", x)
520 self.canvas_item.set_property(
"center_y", y)
522 for link
in self.
links:
527 Initializer function.
529 @param self: class object.
530 @return x / y position.
532 return (self.canvas_item.get_property(
"center_x"), self.canvas_item.get_property(
"center_y"))
546 Initializer function.
548 @param self: class object.
549 @param node1: class object.
550 @param node2: class object.
553 assert isinstance(node1, Node)
554 assert isinstance(node2, (Node, Channel))
557 self.
canvas_item = goocanvas.Path(line_width=1.0, stroke_color=
"black")
558 self.canvas_item.set_data(
"pyviz-object", self)
559 self.node1.links.append(self)
560 self.node2.links.append(self)
564 Update points function.
566 @param self: class object.
569 pos1_x, pos1_y = self.node1.get_position()
570 pos2_x, pos2_y = self.node2.get_position()
571 self.canvas_item.set_property(
"data",
"M %r %r L %r %r" % (pos1_x, pos1_y, pos2_x, pos2_y))
592 Initializer function.
594 @param self: class object.
595 @param viz: class object.
598 super(SimulationThread, self).
__init__()
599 assert isinstance(viz, Visualizer)
602 self.
go = threading.Event()
611 Set nodes of interest function.
613 @param self: class object.
614 @param nodes: class object.
619 self.sim_helper.SetNodesOfInterest(nodes)
625 Initializer function.
627 @param self: class object.
641 if ns3.core.Simulator.IsFinished():
642 self.viz.play_button.set_sensitive(
False)
647 self.sim_helper.SimulatorRunUntil(ns.core.Seconds(self.
target_time))
649 self.pause_messages.extend(self.sim_helper.GetPauseMessages())
650 gobject.idle_add(self.viz.update_model, priority=PRIORITY_UPDATE_MODEL)
677 if _import_error
is None:
681 'populate-node-menu': (gobject.SIGNAL_RUN_LAST,
None, (object, gtk.Menu,)),
685 'simulation-periodic-update': (gobject.SIGNAL_RUN_LAST,
None, ()),
688 'topology-scanned': (gobject.SIGNAL_RUN_LAST,
None, ()),
691 'update-view': (gobject.SIGNAL_RUN_LAST,
None, ()),
697 Initializer function.
699 @param self: class object.
702 assert Visualizer.INSTANCE
is None
703 Visualizer.INSTANCE = self
739 for plugin
in plugins:
744 Set show transmission mode.
746 @param self: class object.
747 @param mode: mode to set.
750 assert isinstance(mode, ShowTransmissionsMode)
753 self.simulation.set_nodes_of_interest(range(ns.network.NodeList.GetNNodes()))
755 self.simulation.set_nodes_of_interest([])
758 self.simulation.set_nodes_of_interest([])
760 self.simulation.set_nodes_of_interest([self.selected_node.node_index])
764 Create advanced controls.
766 @param self: class object.
769 expander = gtk.Expander(
"Advanced")
772 main_vbox = gobject.new(gtk.VBox, border_width=8, visible=
True)
773 expander.add(main_vbox)
775 main_hbox1 = gobject.new(gtk.HBox, border_width=8, visible=
True)
776 main_vbox.pack_start(main_hbox1)
778 show_transmissions_group = HIGContainer(
"Show transmissions")
779 show_transmissions_group.show()
780 main_hbox1.pack_start(show_transmissions_group,
False,
False, 8)
782 vbox = gtk.VBox(
True, 4)
784 show_transmissions_group.add(vbox)
786 all_nodes = gtk.RadioButton(
None)
787 all_nodes.set_label(
"All nodes")
788 all_nodes.set_active(
True)
792 selected_node = gtk.RadioButton(all_nodes)
794 selected_node.set_label(
"Selected node")
795 selected_node.set_active(
False)
796 vbox.add(selected_node)
798 no_node = gtk.RadioButton(all_nodes)
800 no_node.set_label(
"Disabled")
801 no_node.set_active(
False)
805 if radio.get_active():
807 all_nodes.connect(
"toggled", toggled)
810 if radio.get_active():
812 no_node.connect(
"toggled", toggled)
815 if radio.get_active():
817 selected_node.connect(
"toggled", toggled)
821 misc_settings_group = HIGContainer(
"Misc Settings")
822 misc_settings_group.show()
823 main_hbox1.pack_start(misc_settings_group,
False,
False, 8)
824 settings_hbox = gobject.new(gtk.HBox, border_width=8, visible=
True)
825 misc_settings_group.add(settings_hbox)
828 vbox = gobject.new(gtk.VBox, border_width=0, visible=
True)
829 scale = gobject.new(gtk.HScale, visible=
True, digits=2)
830 vbox.pack_start(scale,
True,
True, 0)
831 vbox.pack_start(gobject.new(gtk.Label, label=
"Node Size", visible=
True),
True,
True, 0)
832 settings_hbox.pack_start(vbox,
False,
False, 6)
834 def node_size_changed(adj):
835 for node
in self.nodes.itervalues():
836 node.set_size(adj.value)
837 self.node_size_adjustment.connect(
"value-changed", node_size_changed)
838 self.node_size_adjustment.set_all(DEFAULT_NODE_SIZE, 0.01, 20, 0.1)
841 vbox = gobject.new(gtk.VBox, border_width=0, visible=
True)
842 scale = gobject.new(gtk.HScale, visible=
True, digits=1)
843 vbox.pack_start(scale,
True,
True, 0)
844 vbox.pack_start(gobject.new(gtk.Label, label=
"Tx. Smooth Factor (s)", visible=
True),
True,
True, 0)
845 settings_hbox.pack_start(vbox,
False,
False, 6)
847 self.transmissions_smoothing_adjustment.set_all(DEFAULT_TRANSMISSIONS_MEMORY*0.1, 0.1, 10, 0.1)
855 __slots__ = [
'initial_mouse_pos',
'initial_canvas_pos',
'motion_signal']
859 Set show trnamission mode.
861 @param self: class object.
862 @param mode: mode to set.
865 self.canvas.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
867 x, y, dummy = widget.window.get_pointer()
868 self._panning_state.initial_mouse_pos = (x, y)
869 x = self._scrolled_window.get_hadjustment().value
870 y = self._scrolled_window.get_vadjustment().value
871 self._panning_state.initial_canvas_pos = (x, y)
872 self._panning_state.motion_signal = self.canvas.connect(
"motion-notify-event", self.
_panning_motion)
876 End panning function.
878 @param self: class object.
879 @param event: active event.
884 self.canvas.window.set_cursor(
None)
885 self.canvas.disconnect(self._panning_state.motion_signal)
890 Panning motion function.
892 @param self: class object.
893 @param widget: widget.
895 @return true if successful
899 x, y, dummy = widget.window.get_pointer()
901 x, y = event.x, event.y
903 hadj = self._scrolled_window.get_hadjustment()
904 vadj = self._scrolled_window.get_vadjustment()
905 mx0, my0 = self._panning_state.initial_mouse_pos
906 cx0, cy0 = self._panning_state.initial_canvas_pos
910 hadj.value = cx0 - dx
911 vadj.value = cy0 - dy
915 if event.button == 2:
921 if event.button == 2:
927 if event.direction == gtk.gdk.SCROLL_UP:
928 self.zoom.value *= 1.25
930 elif event.direction == gtk.gdk.SCROLL_DOWN:
931 self.zoom.value /= 1.25
936 return self._scrolled_window.get_hadjustment()
938 return self._scrolled_window.get_vadjustment()
941 self.
window = gtk.Window()
942 vbox = gtk.VBox(); vbox.show()
943 self.window.add(vbox)
946 self.
canvas = goocanvas.Canvas()
950 self.canvas.props.has_tooltip =
True
953 sw = gtk.ScrolledWindow(); sw.show()
956 vbox.pack_start(sw,
True,
True, 4)
957 self.canvas.set_size_request(600, 450)
958 self.canvas.set_bounds(-10000, -10000, 10000, 10000)
959 self.canvas.scroll_to(0, 0)
962 self.canvas.get_root_item().add_child(self.
links_group)
963 self.links_group.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
966 self.channels_group.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
969 self.canvas.get_root_item().add_child(self.
nodes_group)
970 self.nodes_group.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
975 hbox = gtk.HBox(); hbox.show()
976 vbox.pack_start(hbox,
False,
False, 4)
979 zoom_adj = gtk.Adjustment(1.0, 0.01, 10.0, 0.02, 1.0, 0)
981 def _zoom_changed(adj):
982 self.canvas.set_scale(adj.value)
983 zoom_adj.connect(
"value-changed", _zoom_changed)
984 zoom = gtk.SpinButton(zoom_adj)
987 hbox.pack_start(gobject.new(gtk.Label, label=
" Zoom:", visible=
True),
False,
False, 4)
988 hbox.pack_start(zoom,
False,
False, 4)
989 _zoom_changed(zoom_adj)
992 speed_adj = gtk.Adjustment(1.0, 0.01, 10.0, 0.02, 1.0, 0)
993 def _speed_changed(adj):
994 self.
speed = adj.value
997 speed_adj.connect(
"value-changed", _speed_changed)
998 speed = gtk.SpinButton(speed_adj)
1001 hbox.pack_start(gobject.new(gtk.Label, label=
" Speed:", visible=
True),
False,
False, 4)
1002 hbox.pack_start(speed,
False,
False, 4)
1003 _speed_changed(speed_adj)
1006 self.
time_label = gobject.new(gtk.Label, label=
" Speed:", visible=
True)
1007 self.time_label.set_width_chars(20)
1008 hbox.pack_start(self.
time_label,
False,
False, 4)
1011 screenshot_button = gobject.new(gtk.Button,
1013 relief=gtk.RELIEF_NONE, focus_on_click=
False,
1015 hbox.pack_start(screenshot_button,
False,
False, 4)
1017 def load_button_icon(button, icon_name):
1021 sys.stderr.write(
"Could not load icon %s due to missing gnomedesktop Python module\n" % icon_name)
1023 icon = gnomedesktop.find_icon(gtk.icon_theme_get_default(), icon_name, 16, 0)
1024 if icon
is not None:
1025 button.props.image = gobject.new(gtk.Image, file=icon, visible=
True)
1027 load_button_icon(screenshot_button,
"applets-screenshooter")
1031 if ipython_view
is not None:
1032 shell_button = gobject.new(gtk.Button,
1034 relief=gtk.RELIEF_NONE, focus_on_click=
False,
1036 hbox.pack_start(shell_button,
False,
False, 4)
1037 load_button_icon(shell_button,
"gnome-terminal")
1042 image=gobject.new(gtk.Image, stock=gtk.STOCK_MEDIA_PLAY, visible=
True),
1043 label=
"Simulate (F3)",
1044 relief=gtk.RELIEF_NONE, focus_on_click=
False,
1045 use_stock=
True, visible=
True)
1046 accel_group = gtk.AccelGroup()
1047 self.window.add_accel_group(accel_group)
1048 self.play_button.add_accelerator(
"clicked", accel_group,
1049 gtk.keysyms.F3, 0, gtk.ACCEL_VISIBLE)
1051 hbox.pack_start(self.
play_button,
False,
False, 4)
1060 print "scanning topology: %i nodes..." % (ns.network.NodeList.GetNNodes(),)
1061 graph = pygraphviz.AGraph()
1063 for nodeI
in range(ns.network.NodeList.GetNNodes()):
1065 if seen_nodes == 100:
1066 print "scan topology... %i nodes visited (%.1f%%)" % (nodeI, 100*nodeI/ns.network.NodeList.GetNNodes())
1068 node = ns.network.NodeList.GetNode(nodeI)
1069 node_name =
"Node %i" % nodeI
1072 mobility = node.GetObject(ns.mobility.MobilityModel.GetTypeId())
1073 if mobility
is not None:
1074 node_view.set_color(
"red")
1075 pos = mobility.GetPosition()
1079 graph.add_node(node_name)
1081 for devI
in range(node.GetNDevices()):
1082 device = node.GetDevice(devI)
1084 if device_traits.is_wireless:
1086 if device_traits.is_virtual:
1088 channel = device.GetChannel()
1089 if channel.GetNDevices() > 2:
1090 if REPRESENT_CHANNELS_AS_NODES:
1092 if mobility
is None:
1093 channel_name =
"Channel %s" % id(channel)
1094 graph.add_edge(node_name, channel_name)
1099 for otherDevI
in range(channel.GetNDevices()):
1100 otherDev = channel.GetDevice(otherDevI)
1101 otherNode = otherDev.GetNode()
1102 otherNodeView = self.
get_node(otherNode.GetId())
1103 if otherNode
is not node:
1104 if mobility
is None and not otherNodeView.has_mobility:
1105 other_node_name =
"Node %i" % otherNode.GetId()
1106 graph.add_edge(node_name, other_node_name)
1109 for otherDevI
in range(channel.GetNDevices()):
1110 otherDev = channel.GetDevice(otherDevI)
1111 otherNode = otherDev.GetNode()
1112 otherNodeView = self.
get_node(otherNode.GetId())
1113 if otherNode
is not node:
1114 if mobility
is None and not otherNodeView.has_mobility:
1115 other_node_name =
"Node %i" % otherNode.GetId()
1116 graph.add_edge(node_name, other_node_name)
1119 print "scanning topology: calling graphviz layout"
1120 graph.layout(LAYOUT_ALGORITHM)
1121 for node
in graph.iternodes():
1123 node_type, node_id = node.split(
' ')
1124 pos_x, pos_y = [float(s)
for s
in node.attr[
'pos'].split(
',')]
1125 if node_type ==
'Node':
1126 obj = self.
nodes[int(node_id)]
1127 elif node_type ==
'Channel':
1129 obj.set_position(pos_x, pos_y)
1131 print "scanning topology: all done."
1132 self.emit(
"topology-scanned")
1136 return self.
nodes[index]
1138 node =
Node(self, index)
1139 self.
nodes[index] = node
1140 self.nodes_group.add_child(node.canvas_item)
1147 return self.
channels[id(ns3_channel)]
1149 channel =
Channel(ns3_channel)
1150 self.
channels[id(ns3_channel)] = channel
1151 self.channels_group.add_child(channel.canvas_item)
1156 self.links_group.add_child(link.canvas_item)
1157 link.canvas_item.lower(
None)
1162 self.time_label.set_text(
"Time: %f s" % ns.core.Simulator.Now().GetSeconds())
1173 self.emit(
"update-view")
1176 for node
in self.nodes.itervalues():
1177 if node.has_mobility:
1178 ns3_node = ns.network.NodeList.GetNode(node.node_index)
1179 mobility = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
1180 if mobility
is not None:
1181 pos = mobility.GetPosition()
1183 node.set_position(x, y)
1185 hadj = self._scrolled_window.get_hadjustment()
1186 vadj = self._scrolled_window.get_vadjustment()
1187 px, py = self.canvas.convert_to_pixels(x, y)
1188 hadj.value = px - hadj.page_size/2
1189 vadj.value = py - vadj.page_size/2
1192 if isinstance(node, ns.network.Node):
1193 node = self.
nodes[node.GetId()]
1194 elif isinstance(node, (int, long)):
1195 node = self.
nodes[node]
1196 elif isinstance(node, Node):
1199 raise TypeError(
"expected int, viz.Node or ns.network.Node, not %r" % node)
1201 x, y = node.get_position()
1202 hadj = self._scrolled_window.get_hadjustment()
1203 vadj = self._scrolled_window.get_vadjustment()
1204 px, py = self.canvas.convert_to_pixels(x, y)
1205 hadj.value = px - hadj.page_size/2
1206 vadj.value = py - vadj.page_size/2
1210 self.simulation.lock.acquire()
1212 self.emit(
"simulation-periodic-update")
1214 self.simulation.lock.release()
1217 smooth_factor = int(self.transmissions_smoothing_adjustment.value*10)
1219 transmissions = self.simulation.sim_helper.GetTransmissionSamples()
1220 self._last_transmissions.append(transmissions)
1222 self._last_transmissions.pop(0)
1224 drops = self.simulation.sim_helper.GetPacketDropSamples()
1225 self._last_drops.append(drops)
1227 self._last_drops.pop(0)
1230 hadj = self._scrolled_window.get_hadjustment()
1231 vadj = self._scrolled_window.get_vadjustment()
1232 bounds_x1, bounds_y1 = self.canvas.convert_from_pixels(hadj.value, vadj.value)
1233 bounds_x2, bounds_y2 = self.canvas.convert_from_pixels(hadj.value + hadj.page_size,
1234 vadj.value + vadj.page_size)
1235 pos1_x, pos1_y, pos2_x, pos2_y = ns.visualizer.PyViz.LineClipping(bounds_x1, bounds_y1,
1236 bounds_x2, bounds_y2,
1239 return (pos1_x + pos2_x)/2, (pos1_y + pos2_y)/2
1242 transmissions_average = {}
1244 for transmission
in transmission_set:
1245 key = (transmission.transmitter.GetId(), transmission.receiver.GetId())
1246 rx_bytes, count = transmissions_average.get(key, (0, 0))
1247 rx_bytes += transmission.bytes
1249 transmissions_average[key] = rx_bytes, count
1252 for arrow, label
in old_arrows:
1253 arrow.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
1254 label.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
1257 k = self.node_size_adjustment.value/5
1259 for (transmitter_id, receiver_id), (rx_bytes, rx_count)
in transmissions_average.iteritems():
1260 transmitter = self.
get_node(transmitter_id)
1261 receiver = self.
get_node(receiver_id)
1263 arrow, label = old_arrows.pop()
1265 arrow = goocanvas.Polyline(line_width=2.0, stroke_color_rgba=0x00C000C0, close_path=
False, end_arrow=
True)
1266 arrow.set_property(
"parent", self.canvas.get_root_item())
1267 arrow.props.pointer_events = 0
1270 label = goocanvas.Text(parent=self.canvas.get_root_item(), pointer_events=0)
1273 arrow.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
1274 line_width =
max(0.1, math.log(float(rx_bytes)/rx_count/self.
sample_period)*k)
1275 arrow.set_property(
"line-width", line_width)
1277 pos1_x, pos1_y = transmitter.get_position()
1278 pos2_x, pos2_y = receiver.get_position()
1279 points = goocanvas.Points([(pos1_x, pos1_y), (pos2_x, pos2_y)])
1280 arrow.set_property(
"points", points)
1283 label.set_properties(visibility=goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD,
1284 visibility_threshold=0.5,
1285 font=(
"Sans Serif %f" % int(1+BITRATE_FONT_SIZE*k)))
1286 angle = math.atan2((pos2_y - pos1_y), (pos2_x - pos1_x))
1287 if -PI_OVER_2 <= angle <= PI_OVER_2:
1288 label.set_properties(text=(
"%.2f kbit/s →" % (kbps,)),
1289 alignment=pango.ALIGN_CENTER,
1290 anchor=gtk.ANCHOR_S,
1291 x=0, y=-line_width/2)
1295 label.set_transform(M)
1297 label.set_properties(text=(
"← %.2f kbit/s" % (kbps,)),
1298 alignment=pango.ALIGN_CENTER,
1299 anchor=gtk.ANCHOR_N,
1300 x=0, y=line_width/2)
1305 label.set_transform(M)
1307 new_arrows.append((arrow, label))
1315 for drop
in drop_set:
1316 key = drop.transmitter.GetId()
1317 drop_bytes, count = drops_average.get(key, (0, 0))
1318 drop_bytes += drop.bytes
1320 drops_average[key] = drop_bytes, count
1323 for arrow, label
in old_arrows:
1324 arrow.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
1325 label.set_property(
"visibility", goocanvas.ITEM_HIDDEN)
1329 vadjustment = self._scrolled_window.get_vadjustment()
1330 bottom_y = vadjustment.value + vadjustment.page_size
1331 dummy, edge_y = self.canvas.convert_from_pixels(0, bottom_y)
1333 k = self.node_size_adjustment.value/5
1335 for transmitter_id, (drop_bytes, drop_count)
in drops_average.iteritems():
1336 transmitter = self.
get_node(transmitter_id)
1338 arrow, label = old_arrows.pop()
1340 arrow = goocanvas.Polyline(line_width=2.0, stroke_color_rgba=0xC00000C0, close_path=
False, end_arrow=
True)
1341 arrow.props.pointer_events = 0
1342 arrow.set_property(
"parent", self.canvas.get_root_item())
1345 label = goocanvas.Text()
1346 label.props.pointer_events = 0
1347 label.set_property(
"parent", self.canvas.get_root_item())
1350 arrow.set_property(
"visibility", goocanvas.ITEM_VISIBLE)
1351 arrow.set_property(
"line-width",
max(0.1, math.log(float(drop_bytes)/drop_count/self.
sample_period)*k))
1352 pos1_x, pos1_y = transmitter.get_position()
1353 pos2_x, pos2_y = pos1_x, edge_y
1354 points = goocanvas.Points([(pos1_x, pos1_y), (pos2_x, pos2_y)])
1355 arrow.set_property(
"points", points)
1357 label.set_properties(visibility=goocanvas.ITEM_VISIBLE_ABOVE_THRESHOLD,
1358 visibility_threshold=0.5,
1359 font=(
"Sans Serif %i" % int(1+BITRATE_FONT_SIZE*k)),
1360 text=(
"%.2f kbit/s" % (float(drop_bytes*8)/1e3/drop_count/self.
sample_period,)),
1361 alignment=pango.ALIGN_CENTER,
1362 x=(pos1_x + pos2_x)/2,
1363 y=(pos1_y + pos2_y)/2)
1365 new_arrows.append((arrow, label))
1374 while not self.simulation.lock.acquire(
False):
1375 while gtk.events_pending():
1376 gtk.main_iteration()
1377 pause_messages = self.simulation.pause_messages
1378 self.simulation.pause_messages = []
1381 self.simulation.target_time = ns.core.Simulator.Now ().GetSeconds () + self.
sample_period
1384 self.simulation.lock.release()
1388 dialog = gtk.MessageDialog(parent=self.
window, flags=0, type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_OK,
1389 message_format=
'\n'.join(pause_messages))
1390 dialog.connect(
"response",
lambda d, r: d.destroy())
1392 self.play_button.set_active(
False)
1395 if not self.play_button.get_active():
1400 self.simulation.go.set()
1410 priority=PRIORITY_UPDATE_VIEW)
1413 if button.get_active():
1423 self.simulation.quit =
True
1424 self.simulation.go.set()
1425 self.simulation.join()
1435 original_runcode = self.ipython.runcode
1436 def runcode(ip, *args):
1438 self.simulation.lock.acquire()
1440 return original_runcode(*args)
1443 self.simulation.lock.release()
1445 self.ipython.runcode = types.MethodType(runcode, self.
ipython)
1451 positions = [node.get_position()
for node
in self.nodes.itervalues()]
1452 min_x, min_y =
min(x
for (x,y)
in positions),
min(y
for (x,y)
in positions)
1453 max_x, max_y =
max(x
for (x,y)
in positions),
max(y
for (x,y)
in positions)
1454 min_x_px, min_y_px = self.canvas.convert_to_pixels(min_x, min_y)
1455 max_x_px, max_y_px = self.canvas.convert_to_pixels(max_x, max_y)
1458 dx_px = max_x_px - min_x_px
1459 dy_px = max_y_px - min_y_px
1460 hadj = self._scrolled_window.get_hadjustment()
1461 vadj = self._scrolled_window.get_vadjustment()
1462 new_dx, new_dy = 1.5*dx_px, 1.5*dy_px
1464 if new_dx == 0
or new_dy == 0:
1467 self.zoom.value =
min(hadj.page_size/new_dx, vadj.page_size/new_dy)
1469 x1, y1 = self.canvas.convert_from_pixels(hadj.value, vadj.value)
1470 x2, y2 = self.canvas.convert_from_pixels(hadj.value+hadj.page_size, vadj.value+vadj.page_size)
1473 center_x = (min_x + max_x) / 2
1474 center_y = (min_y + max_y) / 2
1476 self.canvas.scroll_to(center_x - width/2, center_y - height/2)
1482 self.window.connect(
"delete-event", self.
_quit)
1485 self.simulation.start()
1498 if event.button == 1:
1503 if event.button == 1:
1506 elif event.button == 3:
1509 elif event.button == 2:
1515 if event.button == 2:
1521 def __init__(self, canvas_x0, canvas_y0, sim_x0, sim_y0):
1529 self.simulation.lock.acquire()
1531 ns3_node = ns.network.NodeList.GetNode(node.node_index)
1532 mob = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
1537 pos = mob.GetPosition()
1539 self.simulation.lock.release()
1540 x, y, dummy = self.canvas.window.get_pointer()
1541 x0, y0 = self.canvas.convert_from_pixels(x, y)
1543 self.node_drag_state.motion_signal = node.canvas_item.connect(
"motion-notify-event", self.
node_drag_motion, node)
1546 self.simulation.lock.acquire()
1548 ns3_node = ns.network.NodeList.GetNode(node.node_index)
1549 mob = ns3_node.GetObject(ns.mobility.MobilityModel.GetTypeId())
1554 x, y, dummy = self.canvas.window.get_pointer()
1555 canvas_x, canvas_y = self.canvas.convert_from_pixels(x, y)
1556 dx = (canvas_x - self.node_drag_state.canvas_x0)
1557 dy = (canvas_y - self.node_drag_state.canvas_y0)
1558 pos = mob.GetPosition()
1562 mob.SetPosition(pos)
1565 self.simulation.lock.release()
1571 node.canvas_item.disconnect(self.node_drag_state.motion_signal)
1576 self.emit(
"populate-node-menu", node, menu)
1577 menu.popup(
None,
None,
None, event.button, event.time)
1591 self.simulation.lock.acquire()
1593 ns3_node = ns.network.NodeList.GetNode(self.selected_node.node_index)
1595 self.simulation.lock.release()
1596 self.ipython.updateNamespace({
'selected_node': ns3_node})
1600 if isinstance(node, ns.network.Node):
1601 node = self.
nodes[node.GetId()]
1602 elif isinstance(node, (int, long)):
1603 node = self.
nodes[node]
1604 elif isinstance(node, Node):
1609 raise TypeError(
"expected None, int, viz.Node or ns.network.Node, not %r" % node)
1615 self.selected_node.selected =
False
1618 self.selected_node.selected =
True
1622 self.simulation.set_nodes_of_interest([])
1624 self.simulation.set_nodes_of_interest([self.selected_node.node_index])
1630 self.information_windows.append(info_win)
1631 self.simulation.lock.acquire()
1635 self.simulation.lock.release()
1638 self.information_windows.remove(info_win)
1642 hadj = self._scrolled_window.get_hadjustment()
1643 vadj = self._scrolled_window.get_vadjustment()
1644 x, y = self.canvas.convert_from_pixels(hadj.value + x, vadj.value + y)
1645 item = self.canvas.get_item_at(x, y,
True)
1649 while item
is not None:
1650 obj = item.get_data(
"pyviz-object")
1652 obj.tooltip_query(tooltip)
1654 item = item.props.parent
1658 sel = gtk.FileChooserDialog(
"Save...", self.canvas.get_toplevel(),
1659 gtk.FILE_CHOOSER_ACTION_SAVE,
1660 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
1661 gtk.STOCK_SAVE, gtk.RESPONSE_OK))
1662 sel.set_default_response(gtk.RESPONSE_OK)
1663 sel.set_local_only(
True)
1664 sel.set_do_overwrite_confirmation(
True)
1665 sel.set_current_name(
"Unnamed.pdf")
1667 filter = gtk.FileFilter()
1668 filter.set_name(
"Embedded PostScript")
1669 filter.add_mime_type(
"image/x-eps")
1670 sel.add_filter(filter)
1672 filter = gtk.FileFilter()
1673 filter.set_name(
"Portable Document Graphics")
1674 filter.add_mime_type(
"application/pdf")
1675 sel.add_filter(filter)
1677 filter = gtk.FileFilter()
1678 filter.set_name(
"Scalable Vector Graphics")
1679 filter.add_mime_type(
"image/svg+xml")
1680 sel.add_filter(filter)
1683 if resp != gtk.RESPONSE_OK:
1687 file_name = sel.get_filename()
1694 if file_name
is None:
1698 x1 = self._scrolled_window.get_hadjustment().value
1699 y1 = self._scrolled_window.get_vadjustment().value
1700 x2 = x1 + self._scrolled_window.get_hadjustment().page_size
1701 y2 = y1 + self._scrolled_window.get_vadjustment().page_size
1702 bounds = goocanvas.Bounds()
1703 bounds.x1, bounds.y1 = self.canvas.convert_from_pixels(x1, y1)
1704 bounds.x2, bounds.y2 = self.canvas.convert_from_pixels(x2, y2)
1705 dest_width = bounds.x2 - bounds.x1
1706 dest_height = bounds.y2 - bounds.y1
1709 dummy, extension = os.path.splitext(file_name)
1710 extension = extension.lower()
1711 if extension ==
'.eps':
1712 surface = cairo.PSSurface(file_name, dest_width, dest_height)
1713 elif extension ==
'.pdf':
1714 surface = cairo.PDFSurface(file_name, dest_width, dest_height)
1715 elif extension ==
'.svg':
1716 surface = cairo.SVGSurface(file_name, dest_width, dest_height)
1718 dialog = gtk.MessageDialog(parent = self.canvas.get_toplevel(),
1719 flags = gtk.DIALOG_DESTROY_WITH_PARENT,
1720 type = gtk.MESSAGE_ERROR,
1721 buttons = gtk.BUTTONS_OK,
1722 message_format =
"Unknown extension '%s' (valid extensions are '.eps', '.svg', and '.pdf')"
1729 cr = cairo.Context(surface)
1730 cr.translate(-bounds.x1, -bounds.y1)
1731 self.canvas.render(cr, bounds, self.zoom.value)
1736 if isinstance(node, ns.network.Node):
1737 node = self.
nodes[node.GetId()]
1742 self.shell_window.present()
1746 self.shell_window.set_size_request(750,550)
1747 self.shell_window.set_resizable(
True)
1748 scrolled_window = gtk.ScrolledWindow()
1749 scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
1751 self.ipython.modify_font(pango.FontDescription(SHELL_FONT))
1752 self.ipython.set_wrap_mode(gtk.WRAP_CHAR)
1754 scrolled_window.add(self.
ipython)
1755 scrolled_window.show()
1756 self.shell_window.add(scrolled_window)
1757 self.shell_window.show()
1761 self.ipython.updateNamespace({
'viz': self})
1768 initialization_hooks = []
1772 Adds a callback to be called after
1773 the visualizer is initialized, like this::
1774 initialization_hook(visualizer, *args)
1776 global initialization_hooks
1777 initialization_hooks.append((hook, args))
1786 viz.canvas.set_bounds(cx1, cy1, cx2, cy2)
1791 assert Visualizer.INSTANCE
is None
1792 if _import_error
is not None:
1794 print >> sys.stderr,
"No visualization support (%s)." % (str(_import_error),)
1795 ns.core.Simulator.Run()
1799 for hook, args
in initialization_hooks:
1800 gobject.idle_add(hook, viz, *args)
1801 ns.network.Packet.EnablePrinting()
def _canvas_scroll_event(self, dummy_widget, event)
_label_canvas_item
label canvas
def on_enter_notify_event(self, view, target, event)
On Enter event handle.
def _on_shell_window_destroy(self, window)
def transform_distance_simulation_to_canvas(d)
def _start_update_timer(self)
def _end_panning(self, event)
End panning function.
def __init__(self, viz)
Initializer function.
def _set_selected(self, value)
Set selected function.
_highlighted
is highlighted
def _on_play_button_toggled(self, button)
def _monkey_patch_ipython(self)
def set_position(self, x, y)
Set position function.
def __init__(self, channel)
Initializer function.
def on_root_button_press_event(self, view, target, event)
def remove_information_window(self, info_win)
def add_link(self, link)
Add link function.
def on_node_button_release_event(self, view, target, event, node)
def add_information_window(self, info_win)
def select_node(self, node)
def _quit(self, dummy_args)
def set_label(self, label)
Set a label for the node.
def _create_advanced_controls(self)
Create advanced controls.
def _update_svg_position(self, x, y)
Update svg position.
def _update_appearance(self)
Update the node aspect to reflect the selected/highlighted state.
def _canvas_button_release(self, dummy_widget, event)
def __init__(self, node1, node2)
Initializer function.
def get_vadjustment(self)
def create_link(self, node, node_or_channel)
def get_position(self)
Get position function.
pause_messages
pause messages
def on_leave_notify_event(self, view, target, event)
On Leave event handle.
def _begin_panning(self, widget, event)
Set show trnamission mode.
def set_show_transmissions_mode(self, mode)
Set show transmission mode.
def transform_point_simulation_to_canvas(x, y)
_has_mobility
has mobility model
def get_node(self, index)
def set_bounds(x1, y1, x2, y2)
highlighted
highlighted property
def _update_position(self)
Update position function.
def _update_node_positions(self)
def on_node_button_press_event(self, view, target, event, node)
visualizer
visualier object
transmissions_smoothing_adjustment
def get_position(self)
Initializer function.
def node_drag_motion(self, item, targe_item, event, node)
def remove_link(self, link)
Remove link function.
def _get_highlighted(self)
Get highlighted function.
def __init__(self, canvas_x0, canvas_y0, sim_x0, sim_y0)
def _canvas_button_press(self, widget, event)
def add_initialization_hook(hook, args)
def begin_node_drag(self, node)
def update_points(self)
Update points function.
def tooltip_query(self, tooltip)
Query tooltip.
def get_hadjustment(self)
def __init__(self, visualizer, node_index)
def set_svg_icon
Set a background SVG icon for the node.
def _update_transmissions_view(self)
def center_on_node(self, node)
def set_position(self, x, y)
Initializer function.
def set_color(self, color)
Set color function.
def _get_export_file_name(self)
def update_view_timeout(self)
def _panning_motion(self, widget, event)
Panning motion function.
def _take_screenshot(self, dummy_button)
def set_follow_node(self, node)
def do_simulation_periodic_update(self)
def _update_drops_view(self)
def lookup_netdevice_traits(class_type)
def __init__(self)
Initializer function.
def _start_shell(self, dummy_button)
def _get_selected(self)
Get selected function.
sim_helper
helper function
def _get_label_over_line_position(self, pos1_x, pos1_y, pos2_x, pos2_y)
def _set_highlighted(self, value)
Set highlighted function.
def end_node_drag(self, node)
def _update_ipython_selected_node(self)
def set_nodes_of_interest(self, nodes)
Set nodes of interest function.
def has_mobility(self)
Has mobility function.
def run(self)
Initializer function.
def _canvas_tooltip_cb(self, canvas, x, y, keyboard_mode, tooltip)
def set_size(self, size)
Set size function.
def transform_distance_canvas_to_simulation(d)
def popup_node_menu(self, node, event)
def get_channel(self, ns3_channel)