summaryrefslogtreecommitdiffstats
path: root/unit_trace/viz/graph.py
diff options
context:
space:
mode:
Diffstat (limited to 'unit_trace/viz/graph.py')
-rw-r--r--unit_trace/viz/graph.py657
1 files changed, 657 insertions, 0 deletions
diff --git a/unit_trace/viz/graph.py b/unit_trace/viz/graph.py
new file mode 100644
index 0000000..6982e7c
--- /dev/null
+++ b/unit_trace/viz/graph.py
@@ -0,0 +1,657 @@
1import util
2import schedule
3from format import *
4from canvas import *
5
6"""The higher-level components of the rendering engine. The graph classes deal with more abstract dimensions
7than the canvas classes (time and task/cpu number rather than plain coordinates). Also, graphs know how to
8update themselves, unlike the Canvas which can only overwrite itself."""
9
10class Graph(object):
11 DEF_BAR_PLIST = [Pattern([(0.0, 0.9, 0.9)]), Pattern([(0.9, 0.3, 0.0)]), Pattern([(0.9, 0.7, 0.0)]),
12 Pattern([(0.0, 0.0, 0.8)]), Pattern([(0.0, 0.2, 0.9)]), Pattern([(0.0, 0.6, 0.6)]),
13 Pattern([(0.75, 0.75, 0.75)])]
14 DEF_ITEM_CLIST = [(0.3, 0.0, 0.0), (0.0, 0.3, 0.0), (0.0, 0.0, 0.3), (0.3, 0.3, 0.0), (0.0, 0.3, 0.3),
15 (0.3, 0.0, 0.3)]
16
17 def __init__(self, CanvasType, surface, start_time, end_time, y_item_list, attrs=GraphFormat(),
18 item_clist=DEF_ITEM_CLIST, bar_plist=DEF_BAR_PLIST):
19 # deal with possibly blank schedules
20 if start_time is None:
21 start_time = 0
22 if end_time is None:
23 end_time = 0
24
25 if start_time > end_time:
26 raise ValueError("Litmus is not a time machine")
27
28 self.attrs = attrs
29 self.start_time = start_time
30 self.end_time = end_time
31 self.y_item_list = y_item_list
32 self.num_maj = int(math.ceil((self.end_time - self.start_time) * 1.0 / self.attrs.time_per_maj)) + 1
33
34 width = self.num_maj * self.attrs.maj_sep + GraphFormat.X_AXIS_MEASURE_OFS + GraphFormat.WIDTH_PAD
35 height = (len(self.y_item_list) + 1) * self.attrs.y_item_size + GraphFormat.HEIGHT_PAD
36
37 # We need to stretch the width in order to fit the y-axis labels. To do this we need
38 # the extents information, but we haven't set up a surface yet, so we just use a
39 # temporary one.
40 extra_width = 0.0
41 dummy_surface = surface.__class__()
42 dummy_surface.renew(10, 10)
43
44 dummy_surface.ctx.select_font_face(self.attrs.item_fopts.name, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
45 dummy_surface.ctx.set_font_size(self.attrs.item_fopts.size)
46 for item in self.y_item_list:
47 dummy_surface.ctx.set_source_rgb(0.0, 0.0, 0.0)
48 te = dummy_surface.ctx.text_extents(item)
49 cur_width = te[2]
50 if cur_width > extra_width:
51 extra_width = cur_width
52
53 width += extra_width
54
55 self.origin = (extra_width + GraphFormat.WIDTH_PAD / 2.0, height - GraphFormat.HEIGHT_PAD / 2.0)
56
57 self.width = width
58 self.height = height
59
60 #if surface.ctx is None:
61 # surface.renew(width, height)
62
63 self.canvas = CanvasType(width, height, item_clist, bar_plist, surface)
64
65 def get_selected_regions(self, real_x, real_y, width, height):
66 return self.canvas.get_selected_regions(real_x, real_y, width, height)
67
68 def get_width(self):
69 return self.width
70
71 def get_height(self):
72 return self.height
73
74 def get_origin(self):
75 return self.origin
76
77 def get_attrs(self):
78 return self.attrs
79
80 def add_sel_region(self, region):
81 self.canvas.add_sel_region(region)
82
83 def get_sel_region(self, event):
84 return self.canvas.get_sel_region(event)
85
86 def has_sel_region(self, event):
87 return self.canvas.has_sel_region(event)
88
89 def update_view(self, x, y, width, height, scale, ctx):
90 """Proxy into the surface's pan."""
91 self.canvas.surface.pan(x, y, width, height)
92 self.canvas.set_scale(scale)
93 self.canvas.surface.change_ctx(ctx)
94
95 def _recomp_min_max(self, start_time, end_time, start_item, end_item):
96 if self.min_time is None or start_time < self.min_time:
97 self.min_time = start_time
98 if self.max_time is None or end_time > self.max_time:
99 self.max_time = end_time
100 if self.min_item is None or start_item < self.min_item:
101 self.min_item = start_item
102 if self.max_item is None or end_item > self.max_item:
103 self.max_item = end_item
104
105 def _get_time_xpos(self, time):
106 """get x so that x is at instant ``time'' on the graph"""
107 return self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + 1.0 * (time - self.start_time) / self.attrs.time_per_maj * self.attrs.maj_sep
108
109 def _get_item_ypos(self, item_no):
110 """get y so that y is where the top of a bar would be in item #n's area"""
111 return self.origin[1] - self._get_y_axis_height() + self.attrs.y_item_size * (item_no + 0.5 - GraphFormat.BAR_SIZE_FACTOR / 2.0)
112
113 def _get_bar_width(self, start_time, end_time):
114 return 1.0 * (end_time - start_time) / self.attrs.time_per_maj * self.attrs.maj_sep
115
116 def _get_bar_height(self):
117 return self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR
118
119 def _get_mini_bar_height(self):
120 return self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR
121
122 def _get_mini_bar_ofs(self):
123 return self.attrs.y_item_size * (GraphFormat.MINI_BAR_SIZE_FACTOR + GraphFormat.BAR_MINI_BAR_GAP_FACTOR)
124
125 def _get_y_axis_height(self):
126 return (len(self.y_item_list) + 1) * self.attrs.y_item_size
127
128 def _get_bottom_tick(self, time):
129 return int(math.floor((time - self.start_time) / self.attrs.time_per_maj))
130
131 def _get_top_tick(self, time):
132 return int(math.ceil((time - self.start_time) / self.attrs.time_per_maj))
133
134 def get_surface(self):
135 """Gets the underlying surface."""
136 return self.canvas.get_surface()
137
138 def xcoor_to_time(self, x):
139 #x = self.origin[0] + GraphFormat.X_AXIS_MEASURE_OFS + (time - self.start) / self.attrs.time_per_maj * self.attrs.maj_sep
140 return (x - self.origin[0] - GraphFormat.X_AXIS_MEASURE_OFS) / self.attrs.maj_sep \
141 * self.attrs.time_per_maj + self.start_time
142
143 def ycoor_to_item_no(self, y):
144 return int((y - self.origin[1] + self._get_y_axis_height()) // self.attrs.y_item_size)
145
146 def get_offset_params(self, real_x, real_y, width, height):
147 x_start, y_start = self.canvas.surface.get_virt_coor_unscaled(real_x, real_y)
148 x_end, y_end = self.canvas.surface.get_virt_coor_unscaled(real_x + width, real_y + height)
149
150 start_time = self.xcoor_to_time(x_start)
151 end_time = self.xcoor_to_time(x_end)
152
153 start_item = self.ycoor_to_item_no(y_start)
154 end_item = 1 + self.ycoor_to_item_no(y_end)
155
156 return (start_time, end_time, start_item, end_item)
157
158 def draw_skeleton(self, start_time, end_time, start_item, end_item):
159 self.draw_grid_at_time(start_time, end_time, start_item, end_item)
160 self.draw_x_axis_with_labels_at_time(start_time, end_time)
161 self.draw_y_axis_with_labels()
162
163 def render_surface(self, sched, regions, selectable=False):
164 raise NotImplementedError
165
166 def render_all(self, schedule):
167 raise NotImplementedError
168
169 def get_events_to_render(self, sched, regions, selectable=False):
170 raise NotImplementedError
171
172 def render_surface(self, sched, regions, selectable=False):
173 if not selectable:
174 self.canvas.whiteout()
175 else:
176 self.canvas.clear_selectable_regions()
177 self.render_events(self.get_events_to_render(sched, regions, selectable), selectable)
178
179 def render_events(self, events, selectable=False):
180 for layer in Canvas.LAYERS:
181 prev_events = {}
182 if layer in events:
183 for event in events[layer]:
184 event.render(self, layer, prev_events, selectable)
185
186 def draw_axes(self, x_axis_label, y_axis_label):
187 """Draws and labels the axes according to the parameters that we were initialized
188 with."""
189 self.draw_grid_at_time(self.start_time, self.end_time, 0, len(self.attrs.y_item_list) - 1)
190
191 self.canvas.draw_x_axis(self.origin[0], self.origin[1], self.num_maj, self.attrs.maj_sep, self.attrs.min_per_maj)
192 self.canvas.draw_y_axis(self.origin[0], self.origin[1], self._get_y_axis_height())
193 self.canvas.draw_x_axis_labels(self.origin[0], self.origin[1], 0, self.num_maj - 1,\
194 self.attrs.maj_sep, self.attrs.min_per_maj, self.start_time, \
195 self.attrs.time_per_maj, self.attrs.show_min, self.attrs.majfopts, self.attrs.minfopts)
196 self.canvas.draw_y_axis_labels(self.origin[0], self.origin[1], self._get_y_axis_height(), self.y_item_list, \
197 self.attrs.y_item_size, self.attrs.item_fopts)
198
199 def draw_grid_at_time(self, start_time, end_time, start_item, end_item):
200 """Draws the grid, but only in a certain time and item range."""
201 start_tick = max(0, self._get_bottom_tick(start_time))
202 end_tick = min(self.num_maj - 1, self._get_top_tick(end_time))
203
204 start_item = max(0, start_item)
205 end_item = min(len(self.y_item_list), end_item)
206
207 self.canvas.draw_grid(self.origin[0], self.origin[1], self._get_y_axis_height(),
208 start_tick, end_tick, start_item, end_item, self.attrs.maj_sep, self.attrs.y_item_size, \
209 self.attrs.min_per_maj, True)
210
211 def draw_x_axis_with_labels_at_time(self, start_time, end_time):
212 start_tick = max(0, self._get_bottom_tick(start_time))
213 end_tick = min(self.num_maj - 1, self._get_top_tick(end_time))
214
215 self.canvas.draw_x_axis(self.origin[0], self.origin[1], start_tick, end_tick, \
216 self.attrs.maj_sep, self.attrs.min_per_maj)
217 self.canvas.draw_x_axis_labels(self.origin[0], self.origin[1], start_tick, \
218 end_tick, self.attrs.maj_sep, self.attrs.min_per_maj,
219 self.start_time + start_tick * self.attrs.time_per_maj,
220 self.attrs.time_per_maj, False)
221
222 def draw_y_axis_with_labels(self):
223 self.canvas.draw_y_axis(self.origin[0], self.origin[1], self._get_y_axis_height())
224 self.canvas.draw_y_axis_labels(self.origin[0], self.origin[1], self._get_y_axis_height(), \
225 self.y_item_list, self.attrs.y_item_size)
226
227 def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False):
228 """Draws a suspension symbol for a dcertain task at an instant in time."""
229 raise NotImplementedError
230
231 def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event):
232 """Same as above, except instead of drawing adds a selectable region at
233 a certain time."""
234 raise NotImplementedError
235
236 def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False):
237 """Draws a resumption symbol for a certain task at an instant in time."""
238 raise NotImplementedError
239
240 def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event):
241 """Same as above, except instead of drawing adds a selectable region at
242 a certain time."""
243 raise NotImplementedError
244
245 def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False):
246 """Draws a completion marker for a certain task at an instant in time."""
247 raise NotImplementedError
248
249 def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event):
250 """Same as above, except instead of drawing adds a selectable region at
251 a certain time."""
252 raise NotImplementedError
253
254 def draw_release_arrow_at_time(self, time, task_no, job_no, selected=False):
255 """Draws a release arrow at a certain time for some task and job"""
256 raise NotImplementedError
257
258 def add_sel_release_arrow_at_time(self, time, task_no, event):
259 """Same as above, except instead of drawing adds a selectable region at
260 a certain time."""
261 raise NotImplementedError
262
263 def draw_deadline_arrow_at_time(self, time, task_no, job_no, selected=False):
264 """Draws a deadline arrow at a certain time for some task and job"""
265 raise NotImplementedError
266
267 def add_sel_deadline_arrow_at_time(self, time, task_no, event):
268 """Same as above, except instead of drawing adds a selectable region at
269 a certain time."""
270 raise NotImplementedError
271
272 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None):
273 """Draws a bar over a certain time period for some task, optionally labelling it."""
274 raise NotImplementedError
275
276 def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event):
277 """Same as above, except instead of drawing adds a selectable region at
278 a certain time."""
279 raise NotImplementedError
280
281 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, clip_side=None, job_no=None):
282 """Draws a mini bar over a certain time period for some task, optionally labelling it."""
283 raise NotImplementedError
284
285 def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event):
286 """Same as above, except instead of drawing adds a selectable region at
287 a certain time."""
288 raise NotImplementedError
289
290class TaskGraph(Graph):
291 def get_events_to_render(self, sched, regions, selectable=False):
292 slots = {}
293
294 self.min_time, self.max_time, self.min_item, self.max_item = None, None, None, None
295 for region in regions:
296 x, y, width, height = region
297 start_time, end_time, start_item, end_item = self.get_offset_params(x, y, width, height)
298 self._recomp_min_max(start_time, end_time, start_item, end_item)
299
300 sched.get_time_slot_array().get_slots(slots,
301 start_time, end_time, start_item, end_item,
302 schedule.TimeSlotArray.TASK_LIST)
303
304
305 if not selectable:
306 self.draw_skeleton(self.min_time, self.max_time,
307 self.min_item, self.max_item)
308
309 events_to_render = {}
310 for layer in Canvas.LAYERS:
311 events_to_render[layer] = {}
312
313 for event in sched.get_time_slot_array().get_events(slots,
314 schedule.TimeSlotArray.TASK_LIST,
315 schedule.EVENT_LIST):
316 events_to_render[event.get_layer()][event] = None
317
318 return events_to_render
319
320 def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False):
321 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
322 x = self._get_time_xpos(time)
323 y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0
324 self.canvas.draw_suspend_triangle(x, y, height, selected)
325
326 def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event):
327 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
328 x = self._get_time_xpos(time)
329 y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0
330
331 self.canvas.add_sel_suspend_triangle(x, y, height, event)
332
333 def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False):
334 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
335 x = self._get_time_xpos(time)
336 y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0
337
338 self.canvas.draw_resume_triangle(x, y, height, selected)
339
340 def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event):
341 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
342 x = self._get_time_xpos(time)
343 y = self._get_item_ypos(task_no) + self._get_bar_height() / 2.0 - height / 2.0
344
345 self.canvas.add_sel_resume_triangle(x, y, height, event)
346
347 def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False):
348 height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR
349 x = self._get_time_xpos(time)
350 y = self._get_item_ypos(task_no) + self._get_bar_height() - height
351
352 self.canvas.draw_completion_marker(x, y, height, selected)
353
354 def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event):
355 height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR
356
357 x = self._get_time_xpos(time)
358 y = self._get_item_ypos(task_no) + self._get_bar_height() - height
359
360 self.canvas.add_sel_completion_marker(x, y, height, event)
361
362 def draw_release_arrow_at_time(self, time, task_no, job_no=None, selected=False):
363 height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR
364
365 x = self._get_time_xpos(time)
366 y = self._get_item_ypos(task_no) + self._get_bar_height() - height
367
368 self.canvas.draw_release_arrow_big(x, y, height, selected)
369
370 def add_sel_release_arrow_at_time(self, time, task_no, event):
371 height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR
372
373 x = self._get_time_xpos(time)
374 y = self._get_item_ypos(task_no) + self._get_bar_height() - height
375
376 self.canvas.add_sel_release_arrow_big(x, y, height, event)
377
378 def draw_deadline_arrow_at_time(self, time, task_no, job_no=None, selected=False):
379 height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR
380
381 x = self._get_time_xpos(time)
382 y = self._get_item_ypos(task_no)
383
384 self.canvas.draw_deadline_arrow_big(x, y, height, selected)
385
386 def add_sel_deadline_arrow_at_time(self, time, task_no, event):
387 height = self._get_bar_height() * GraphFormat.BIG_ARROW_FACTOR
388
389 x = self._get_time_xpos(time)
390 y = self._get_item_ypos(task_no)
391
392 self.canvas.add_sel_deadline_arrow_big(x, y, height, event)
393
394 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
395 if start_time > end_time:
396 raise ValueError("Litmus is not a time machine")
397
398 x = self._get_time_xpos(start_time)
399 y = self._get_item_ypos(task_no)
400 width = self._get_bar_width(start_time, end_time)
401 height = self._get_bar_height()
402
403 self.canvas.draw_bar(x, y, width, height, cpu_no, clip_side, selected)
404
405 # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively
406 if job_no is not None:
407 x += GraphFormat.BAR_LABEL_OFS
408 y += self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR / 2.0
409 self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \
410 GraphFormat.DEF_FOPTS_BAR, GraphFormat.DEF_FOPTS_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER)
411
412 def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event):
413 if start_time > end_time:
414 raise ValueError("Litmus is not a time machine")
415
416 x = self._get_time_xpos(start_time)
417 y = self._get_item_ypos(task_no)
418 width = self._get_bar_width(start_time, end_time)
419 height = self._get_bar_height()
420
421 self.canvas.add_sel_bar(x, y, width, height, event)
422
423 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
424 if start_time > end_time:
425 raise ValueError("Litmus is not a time machine")
426
427 x = self._get_time_xpos(start_time)
428 y = self._get_item_ypos(task_no) - self._get_mini_bar_ofs()
429 width = self._get_bar_width(start_time, end_time)
430 height = self._get_mini_bar_height()
431
432 self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, clip_side, selected)
433
434 if job_no is not None:
435 x += GraphFormat.MINI_BAR_LABEL_OFS
436 y += self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR / 2.0
437 self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \
438 GraphFormat.DEF_FOPTS_MINI_BAR, GraphFormat.DEF_FOPTS_MINI_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER)
439
440 def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event):
441 x = self._get_time_xpos(start_time)
442 y = self._get_item_ypos(task_no) - self._get_mini_bar_ofs()
443 width = self._get_bar_width(start_time, end_time)
444 height = self._get_mini_bar_height()
445
446 self.canvas.add_sel_mini_bar(x, y, width, height, event)
447
448class CpuGraph(Graph):
449 def get_events_to_render(self, sched, regions, selectable=False):
450 BOTTOM_EVENTS = [schedule.ReleaseEvent, schedule.DeadlineEvent, schedule.InversionStartEvent,
451 schedule.InversionEndEvent, schedule.InversionDummy]
452 TOP_EVENTS = [schedule.SuspendEvent, schedule.ResumeEvent, schedule.CompleteEvent,
453 schedule.SwitchAwayEvent, schedule.SwitchToEvent, schedule.IsRunningDummy]
454
455 if not regions:
456 return {}
457
458 top_slots = {}
459 bottom_slots = {}
460
461 self.min_time, self.max_time, self.min_item, self.max_item = None, None, None, None
462 for region in regions:
463 x, y, width, height = region
464 start_time, end_time, start_item, end_item = self.get_offset_params(x, y, width, height)
465 self._recomp_min_max(start_time, end_time, start_item, end_item)
466
467 sched.get_time_slot_array().get_slots(top_slots,
468 start_time, end_time, start_item, end_item,
469 schedule.TimeSlotArray.CPU_LIST)
470
471 if end_item >= len(self.y_item_list):
472 # we are far down enough that we should render the releases and deadlines and inversions,
473 # which appear near the x-axis
474 sched.get_time_slot_array().get_slots(bottom_slots,
475 start_time, end_time, 0, sched.get_num_cpus(),
476 schedule.TimeSlotArray.CPU_LIST)
477
478 if not selectable:
479 self.draw_skeleton(self.min_time, self.max_time,
480 self.min_item, self.max_item)
481
482 events_to_render = {}
483 for layer in Canvas.LAYERS:
484 events_to_render[layer] = {}
485
486 for event in sched.get_time_slot_array().get_events(top_slots,
487 schedule.TimeSlotArray.CPU_LIST,
488 TOP_EVENTS):
489 events_to_render[event.get_layer()][event] = None
490 for event in sched.get_time_slot_array().get_events(bottom_slots,
491 schedule.TimeSlotArray.CPU_LIST,
492 BOTTOM_EVENTS):
493 events_to_render[event.get_layer()][event] = None
494
495 return events_to_render
496
497 def render(self, schedule, start_time=None, end_time=None):
498 if end_time < start_time:
499 raise ValueError('start must be less than end')
500
501 if start_time is None:
502 start_time = self.start
503 if end_time is None:
504 end_time = self.end
505 start_slot = self.get_time_slot(start_time)
506 end_slot = min(len(self.time_slots), self.get_time_slot(end_time) + 1)
507
508 for layer in Canvas.LAYERS:
509 prev_events = {}
510 for i in range(start_slot, end_slot):
511 for event in self.time_slots[i]:
512 event.render(graph, layer, prev_events)
513
514 def draw_suspend_triangle_at_time(self, time, task_no, cpu_no, selected=False):
515 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
516 x = self._get_time_xpos(time)
517 y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0
518 self.canvas.draw_suspend_triangle(x, y, height, selected)
519
520 def add_sel_suspend_triangle_at_time(self, time, task_no, cpu_no, event):
521 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
522 x = self._get_time_xpos(time)
523 y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0
524
525 self.canvas.add_sel_suspend_triangle(x, y, height, event)
526
527 def draw_resume_triangle_at_time(self, time, task_no, cpu_no, selected=False):
528 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
529 x = self._get_time_xpos(time)
530 y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0
531
532 self.canvas.draw_resume_triangle(x, y, height, selected)
533
534 def add_sel_resume_triangle_at_time(self, time, task_no, cpu_no, event):
535 height = self._get_bar_height() * GraphFormat.BLOCK_TRIANGLE_FACTOR
536 x = self._get_time_xpos(time)
537 y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0
538
539 self.canvas.add_sel_resume_triangle(x, y, height, event)
540
541 def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False):
542 height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR
543 x = self._get_time_xpos(time)
544 y = self._get_item_ypos(cpu_no) + self._get_bar_height() - height
545
546 self.canvas.draw_completion_marker(x, y, height, selected)
547
548 def add_sel_completion_marker_at_time(self, time, task_no, cpu_no, event):
549 height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR
550
551 x = self._get_time_xpos(time)
552 y = self._get_item_ypos(cpu_no) + self._get_bar_height() - height
553
554 self.canvas.add_sel_completion_marker(x, y, height, event)
555
556 def draw_release_arrow_at_time(self, time, task_no, job_no=None, selected=False):
557 if job_no is None and task_no is not None:
558 raise ValueError("Must specify a job number along with the task number")
559
560 height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR
561
562 x = self._get_time_xpos(time)
563 y = self.origin[1] - height
564
565 self.canvas.draw_release_arrow_small(x, y, height, selected)
566
567 if task_no is not None:
568 y -= GraphFormat.ARROW_LABEL_OFS
569 self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \
570 GraphFormat.DEF_FOPTS_ARROW, GraphFormat.DEF_FOPTS_ARROW_SSCRIPT, \
571 AlignMode.CENTER, AlignMode.BOTTOM)
572
573 def add_sel_release_arrow_at_time(self, time, task_no, event):
574 height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR
575
576 x = self._get_time_xpos(time)
577 y = self.origin[1] - height
578
579 self.canvas.add_sel_release_arrow_small(x, y, height, event)
580
581 def draw_deadline_arrow_at_time(self, time, task_no, job_no=None, selected=False):
582 if job_no is None and task_no is not None:
583 raise ValueError("Must specify a job number along with the task number")
584
585 height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR
586
587 x = self._get_time_xpos(time)
588 y = self.origin[1] - height
589
590 self.canvas.draw_deadline_arrow_small(x, y, height, selected)
591
592 if task_no is not None:
593 y -= GraphFormat.ARROW_LABEL_OFS
594 self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \
595 GraphFormat.DEF_FOPTS_ARROW, GraphFormat.DEF_FOPTS_ARROW_SSCRIPT, \
596 AlignMode.CENTER, AlignMode.BOTTOM)
597
598 def add_sel_deadline_arrow_at_time(self, time, task_no, event):
599 height = self._get_bar_height() * GraphFormat.SMALL_ARROW_FACTOR
600
601 x = self._get_time_xpos(time)
602 y = self.origin[1] - height
603
604 self.canvas.add_sel_deadline_arrow_small(x, y, height, event)
605
606 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
607 if start_time > end_time:
608 raise ValueError("Litmus is not a time machine")
609
610 x = self._get_time_xpos(start_time)
611 y = self._get_item_ypos(cpu_no)
612 width = self._get_bar_width(start_time, end_time)
613 height = self._get_bar_height()
614
615 self.canvas.draw_bar(x, y, width, height, task_no, clip_side, selected)
616
617 # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively
618 if job_no is not None:
619 x += GraphFormat.BAR_LABEL_OFS
620 y += self.attrs.y_item_size * GraphFormat.BAR_SIZE_FACTOR / 2.0
621 self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \
622 GraphFormat.DEF_FOPTS_BAR, GraphFormat.DEF_FOPTS_BAR_SSCRIPT, \
623 AlignMode.LEFT, AlignMode.CENTER)
624
625 def add_sel_bar_at_time(self, start_time, end_time, task_no, cpu_no, event):
626 x = self._get_time_xpos(start_time)
627 y = self._get_item_ypos(cpu_no)
628 width = self._get_bar_width(start_time, end_time)
629 height = self._get_bar_height()
630
631 self.canvas.add_sel_bar(x, y, width, height, event)
632
633 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
634 if start_time > end_time:
635 raise ValueError("Litmus is not a time machine")
636
637 x = self._get_time_xpos(start_time)
638 y = self._get_item_ypos(len(self.y_item_list))
639 width = self._get_bar_width(start_time, end_time)
640 height = self._get_mini_bar_height()
641
642 self.canvas.draw_mini_bar(x, y, width, height, task_no, clip_side, selected)
643
644 if job_no is not None:
645 x += GraphFormat.MINI_BAR_LABEL_OFS
646 y += self.attrs.y_item_size * GraphFormat.MINI_BAR_SIZE_FACTOR / 2.0
647 self.canvas.draw_label_with_sscripts('T', str(task_no), str(job_no), x, y, \
648 GraphFormat.DEF_FOPTS_MINI_BAR, GraphFormat.DEF_FOPTS_MINI_BAR_SSCRIPT, AlignMode.LEFT, AlignMode.CENTER)
649
650 def add_sel_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, event):
651 x = self._get_time_xpos(start_time)
652 y = self._get_item_ypos(len(self.y_item_list))
653 width = self._get_bar_width(start_time, end_time)
654 height = self._get_mini_bar_height()
655
656 self.canvas.add_sel_mini_bar(x, y, width, height, event)
657