diff options
author | Gary Bressler <garybressler@nc.rr.com> | 2010-04-06 12:45:04 -0400 |
---|---|---|
committer | Gary Bressler <garybressler@nc.rr.com> | 2010-04-06 12:45:04 -0400 |
commit | c7e3aaebdba7bf880534abd91a383b5543cf0be4 (patch) | |
tree | 048977efdaaa3d60e93c3d21ba29c46a0bfe71c3 /unit_trace/viz/graph.py | |
parent | 7fdb4dbbbca577efbeec47cd1364eb319346a0cc (diff) |
Making sure everything committed
Diffstat (limited to 'unit_trace/viz/graph.py')
-rw-r--r-- | unit_trace/viz/graph.py | 657 |
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 @@ | |||
1 | import util | ||
2 | import schedule | ||
3 | from format import * | ||
4 | from canvas import * | ||
5 | |||
6 | """The higher-level components of the rendering engine. The graph classes deal with more abstract dimensions | ||
7 | than the canvas classes (time and task/cpu number rather than plain coordinates). Also, graphs know how to | ||
8 | update themselves, unlike the Canvas which can only overwrite itself.""" | ||
9 | |||
10 | class 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 | |||
290 | class 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 | |||
448 | class 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 | |||