File indexing completed on 2024-07-18 23:17:44
0001 const kBoxHeight = 15;
0002 const kRowHeight = 20;
0003
0004 const kTypeOffset = 16
0005 const kSourceColor = "#DD00DD";
0006 const typeToColor = [
0007 "#000000",
0008 0,
0009 0,
0010 0,
0011 "#FF0000",
0012 "#FF7777",
0013 "#BBBBBB",
0014 "#FFFFFF",
0015 0,
0016 "#0000BB",
0017 "#0000FF",
0018 "#0000FF",
0019 "#00BB00",
0020 "#00FF00",
0021 "#00FF00",
0022 "#CCCC00",
0023 "#FFFF00",
0024 0,
0025 "#007700",
0026 "#007700",
0027 0,
0028 "#000077",
0029 "#000077",
0030 0,
0031 "#BBBBBB",
0032 "#FFFFFF",
0033 kSourceColor,
0034 "#FF7777",
0035 "#FF0000",
0036 "#00FFFF",
0037 "#007777",
0038 kSourceColor,
0039 "#DD00DD",
0040 "#FF0000",
0041 ]
0042
0043 const overlappingTransitions =[15]
0044
0045 const typeToName = [
0046 "destructor",
0047 0,
0048 0,
0049 0,
0050 "end job",
0051 "end stream",
0052 "write process block",
0053 "end process block",
0054 0,
0055 "write end run",
0056 "global end run",
0057 "stream end run",
0058 "write end lumi",
0059 "global end lumi",
0060 "stream end lumi",
0061 "clear event",
0062 "event",
0063 0,
0064 "stream begin lumi",
0065 "global begin lumi",
0066 0,
0067 "stream begin run",
0068 "global begin run",
0069 0,
0070 "access input process block",
0071 "begin process block",
0072 "open file",
0073 "begin stream",
0074 "begin job",
0075 "EventSetup synch",
0076 "EventSetup sych enqueue",
0077 "find next transition",
0078 "construction",
0079 "startup",
0080 ]
0081
0082 const activityToName = [ "prefetch",
0083 "acquire",
0084 "process",
0085 "delayedGet",
0086 "externalWork"]
0087
0088 const activityToColor = ["#FF5F1F", "#CC7722", null, "#FF4433", "#8B4513"];
0089
0090
0091
0092 window.onload = async() => {
0093
0094 const response = await fetch("modules_data.json");
0095 const data = await response.json();
0096 const left = document.querySelector('.name_div');
0097 const div = document.querySelector('.graph_div');
0098 const bottom = document.querySelector('.time_div');
0099 const graph = document.getElementById('graph_view');
0100 const graph_context = graph.getContext('2d');
0101 const name_view = document.getElementById('name_view');
0102 const name_context = name_view.getContext('2d');
0103 const time_view = document.getElementById('time_view');
0104 const time_context = time_view.getContext('2d');
0105 const selected_view = document.getElementById('selected_paragraph');
0106 const zoom_in_button = document.getElementById('zoom_in');
0107 const zoom_out_button = document.getElementById('zoom_out');
0108 let selected_item = null;
0109 selected_view.innerHTML = "Selected: [click on box in graph]";
0110 let mouse_is_down = false;
0111
0112 let rows = 0;
0113 for( let grouping of data.transitions ) {
0114 for( let slot in grouping.slots ) {
0115 ++rows;
0116 }
0117 }
0118
0119 const max_graph_height = kRowHeight*rows;
0120
0121
0122 let graph_vertical_offset = 0.;
0123 let minVisibleTime = 0.;
0124 let timeZoomFactor = 1.0;
0125
0126 function maxTime() {
0127 let maxTime = 0;
0128 for( let grouping of data.transitions) {
0129 for( let slot of grouping.slots) {
0130 for (let transition of slot) {
0131 if (maxTime < transition.finish) {
0132 maxTime = transition.finish;
0133 }
0134 }
0135 }
0136 }
0137
0138 maxTime = Math.ceil(maxTime);
0139
0140 const digits = maxTime.toString().length;
0141 const digitsToZeroOut = digits -2;
0142 if (digitsToZeroOut > 0) {
0143 for(let i = 0; i < digitsToZeroOut; ++i) {
0144 maxTime /= 10;
0145 }
0146 maxTime *=10;
0147 maxTime +=9;
0148 for( let i = 1; i < digitsToZeroOut; ++i) {
0149 maxTime *=10;
0150 }
0151 maxTime = Math.ceil(maxTime);
0152 }
0153 return maxTime;
0154 }
0155
0156 const kEndTime = maxTime();
0157
0158 function drawNames() {
0159 name_context.setTransform(1,0,0,1,0,0);
0160 name_context.fillStyle = "#AACD6E"
0161 name_context.fillRect(0,0,name_view.width,name_view.height);
0162 name_context.scale(1,1)
0163 name_context.fillStyle = "black"
0164 name_context.strokeStyle = "black"
0165 name_context.font = '9pt monospace';
0166
0167 let offset = kRowHeight/2 + graph_vertical_offset;
0168 for( let grouping of data.transitions ) {
0169 name_context.fillText(grouping.name, 0, offset);
0170 offset += grouping.slots.length*kRowHeight;
0171 }
0172 }
0173
0174 function timeStepPower() {
0175 let timeDecade = 0;
0176 let nSteps = time_view.width/kInitPixelsPerSecond/timeZoomFactor;
0177 while (nSteps < 3) {
0178 --timeDecade;
0179 nSteps *=10.;
0180 }
0181 while (nSteps > 20) {
0182 ++timeDecade;
0183 nSteps /=10.;
0184 }
0185 return timeDecade;
0186 }
0187
0188 function drawTime() {
0189 time_context.save()
0190 time_context.setTransform(1,0,0,1,0,0);
0191 time_context.fillStyle = "#CD6E6E";
0192 time_context.fillRect(0,0,time_view.width,time_view.height);
0193 time_context.restore();
0194 time_context.scale(1,1);
0195 const end = kEndTime;
0196 const timePower = timeStepPower();
0197 const stepSize = Math.pow(10., timePower);
0198 let fixedValue = timePower;
0199 if (fixedValue < 0 ) {
0200 fixedValue *= -1;
0201 }
0202
0203 const tickDistance = stepSize/10.*kInitPixelsPerSecond*timeZoomFactor;
0204 const bigTickDistance = stepSize*kInitPixelsPerSecond*timeZoomFactor;
0205 for( let bigTick = 0; bigTick < end; bigTick +=stepSize) {
0206 let t = (bigTick-minVisibleTime)*kInitPixelsPerSecond*timeZoomFactor;
0207 if ((t + bigTickDistance) < 0 ) continue;
0208 if (t > time_view.width) break;
0209 graph_context.strokeStyle = "black";
0210 time_context.beginPath()
0211 time_context.moveTo(t,0)
0212 time_context.lineTo(t, time_view.height/2);
0213 time_context.stroke()
0214 const sec = bigTick.toFixed(fixedValue);
0215
0216 time_context.fillText(sec.toString()+"s", t, time_view.height*0.75)
0217 for(let tick = 1; tick < 10; ++tick) {
0218 let pos = t+tick*tickDistance;
0219 time_context.beginPath();
0220 time_context.moveTo(pos,0);
0221 time_context.lineTo(pos, time_view.height/4);
0222 time_context.stroke();
0223 }
0224 }
0225 }
0226
0227 function colorToUse(transition) {
0228 if (!transition.isSrc) {
0229 if ( ('act' in transition) && transition.act != 2) {
0230 return activityToColor[transition.act];
0231 } else {
0232 return typeToColor[transition.type+kTypeOffset];
0233 }
0234 }
0235 return kSourceColor;
0236 }
0237
0238 function drawGraph() {
0239 const scale = kInitPixelsPerSecond * timeZoomFactor;
0240 const maxVisibleTime = time_view.width/scale+minVisibleTime;
0241
0242 graph_context.save();
0243 graph_context.setTransform(1,0,0,1,0,0);
0244 graph_context.fillStyle = "#D5D6C6"
0245 graph_context.fillRect(0,0,graph.width,graph.height);
0246 graph_context.restore();
0247
0248 graph_context.strokeStyle = "black";
0249 graph_context.scale(1,1);
0250
0251 let offset = graph_vertical_offset;
0252 for( let grouping of data.transitions) {
0253 if (offset > graph.height) break;
0254 for( let slot of grouping.slots ) {
0255 if (offset > graph.height) break;
0256 if (offset+kBoxHeight >= 0) {
0257 for( let transition of slot) {
0258 if (maxVisibleTime < transition.start) {
0259 break;
0260 }
0261 if (minVisibleTime > transition.finish) {
0262 continue;
0263 }
0264 if(transition == selected_item) {
0265 graph_context.fillStyle = "white";
0266 } else {
0267 graph_context.fillStyle = colorToUse(transition);
0268 }
0269 graph_context.fillRect(scale*(transition.start-minVisibleTime), offset, scale*(transition.finish-transition.start), kBoxHeight);
0270 }
0271 }
0272 offset += kRowHeight;
0273 }
0274 }
0275 drawNames();
0276 drawTime();
0277
0278 }
0279 graph.width = div.clientWidth;
0280 const kInitPixelsPerSecond = graph.width/kEndTime;
0281 const max_graph_width = graph.width;
0282
0283 graph.height = div.clientHeight
0284 name_view.width = left.clientWidth
0285 name_view.height = left.clientHeight
0286 time_view.width = bottom.clientWidth
0287 time_view.height = bottom.clientHeight
0288 drawGraph()
0289
0290 let graph_isDragging = false;
0291 let graph_mouseDown = false;
0292 let graph_mouseDownPosition = {x:0, y:0};
0293 let graph_dragStartPosition = { x: 0, y: 0 };
0294
0295 let time_isDragging = false;
0296 let time_dragStartPosition = 0;
0297
0298 function graph_translate(xDiff, yDiff) {
0299 let original = minVisibleTime;
0300 minVisibleTime -= xDiff/kInitPixelsPerSecond/timeZoomFactor;
0301
0302 const timeEnd = (max_graph_width)/kInitPixelsPerSecond/timeZoomFactor+minVisibleTime;
0303 if (timeEnd > kEndTime) {
0304 minVisibleTime = kEndTime - max_graph_width/kInitPixelsPerSecond/timeZoomFactor;
0305 }
0306 if (minVisibleTime < 0) {
0307 minVisibleTime = 0;
0308 }
0309 original = graph_vertical_offset;
0310 graph_vertical_offset += yDiff;
0311 if (graph_vertical_offset < -max_graph_height) {
0312 graph_vertical_offset = -max_graph_height;
0313 }
0314 if (graph_vertical_offset > 0) {
0315 graph_vertical_offset = 0;
0316 }
0317 }
0318
0319 function getTransformedPoint(x, y) {
0320 const originalPoint = new DOMPoint(x, y);
0321 return graph_context.getTransform().invertSelf().transformPoint(originalPoint);
0322 }
0323
0324 function graph_onMouseDown(event) {
0325 graph_mouseDown = true;
0326 graph_mouseDownPosition = {x:event.offsetX, y:event.offsetY};
0327 graph_dragStartPosition = getTransformedPoint(event.offsetX, event.offsetY);
0328 }
0329
0330 function graph_onMouseMove(event) {
0331 let currentTransformedCursor = getTransformedPoint(event.offsetX, event.offsetY);
0332
0333 if (graph_mouseDown) {
0334 if (Math.abs(graph_mouseDownPosition.x-event.offsetX)> 5 ||
0335 Math.abs(graph_mouseDownPosition.y-event.offsetY)> 5) {
0336 graph_isDragging = true;
0337 }
0338 }
0339 if (graph_isDragging) {
0340 graph_translate(currentTransformedCursor.x - graph_dragStartPosition.x, currentTransformedCursor.y - graph_dragStartPosition.y);
0341 graph_dragStartPosition.x = currentTransformedCursor.x;
0342 graph_dragStartPosition.y = currentTransformedCursor.y;
0343 drawGraph();
0344 }
0345 }
0346
0347 function moduleName(id) {
0348 if (id ==0) {
0349 return "source";
0350 }
0351 return "";
0352 }
0353
0354 function doUnselection() {
0355 selected_view.innerHTML = "Selected: [click on box in graph]";
0356 selected_item = null;
0357 }
0358
0359 function moduleIdToName(id) {
0360 if (id < 0) {
0361 return data.esModules[-1*id];
0362 }
0363 return data.modules[id];
0364 }
0365
0366 function duration(t) {
0367 if (t < 0.001) {
0368 return (t*1000000).toFixed()+"us";
0369 }
0370 if (t < 0.1) {
0371 return (t*1000).toFixed(3)+"ms";
0372 }
0373 return t.toFixed(6)+"s";
0374 }
0375
0376 function updateSelectedView(item) {
0377 if ('isSrc' in item) {
0378 if (item.isSrc) {
0379 if(item.mod) {
0380 selected_view.innerHTML ="Selected: source reading data product: for module "+item.mod+" "+moduleIdToName(item.mod)+ " while "+activityToName[item.act]+" "+typeToName[item.type+kTypeOffset] +" start: "+item.start.toFixed(6)+"s finish: "+item.finish.toFixed(6)+"s duration: "+duration(item.finish-item.start);
0381
0382 } else {
0383 selected_view.innerHTML = "Selected: source "+typeToName[item.type+kTypeOffset]+" id: "+item.id+" run: "+item.sync[0]
0384 +" lumi: "+item.sync[1]+ " event: "+item.sync[2]+" start: "+item.start.toFixed(6)+"s finish:"+item.finish.toFixed(6)+"s duration: "+duration(item.finish-item.start);
0385 }
0386 } else {
0387 selected_view.innerHTML = "Selected: "+typeToName[item.type+kTypeOffset]+" id: "+item.id+" run: "+item.sync[0]
0388 +" lumi: "+item.sync[1]+ " event: "+item.sync[2]+" start: "+item.start.toFixed(6)+"s finish:"+item.finish.toFixed(6)+"s duration: "+duration(item.finish-item.start);
0389 }
0390 } else {
0391 let transform = '';
0392 if (item.call != 0 && item.mod > 0) {
0393 transform = ' transform '
0394 }
0395 selected_view.innerHTML ="Selected: module : "+item.mod+" "+moduleIdToName(item.mod)+ " while "+activityToName[item.act]+transform+" "+typeToName[item.type+kTypeOffset] +" start: "+item.start.toFixed(6)+"s finish: "+item.finish.toFixed(6)+"s duration: "+duration(item.finish-item.start);
0396 }
0397 }
0398 function doSelection(items, x) {
0399 let time = x/kInitPixelsPerSecond/timeZoomFactor+minVisibleTime;
0400
0401 if( time < 0 || time > kEndTime) {
0402 doUnselection();
0403 drawGraph();
0404 return;
0405 }
0406 selected_item = null;
0407 for( let item of items) {
0408 if (time < item.start) {
0409 break;
0410 }
0411 if (time > item.start && time < item.finish) {
0412 selected_item = item;
0413 if ( overlappingTransitions.includes(selected_item.type)) {
0414 continue;
0415 } else {
0416 break;
0417 }
0418 }
0419 }
0420 if (selected_item) {
0421 updateSelectedView(selected_item);
0422 } else {
0423 doUnselection();
0424 }
0425 drawGraph();
0426 }
0427
0428 function graph_onMouseUp(event) {
0429 if (graph_mouseDown && ! graph_isDragging) {
0430
0431 const selectionPoint = getTransformedPoint(event.offsetX, event.offsetY);
0432 const vertIndex = Math.floor((selectionPoint.y-graph_vertical_offset)/kRowHeight);
0433
0434 let presentIndex = 0;
0435 let container = null;
0436 outer: for(let grouping of data.transitions) {
0437 for(let slot of grouping.slots) {
0438 if (presentIndex == vertIndex) {
0439 container = slot;
0440 break outer;
0441 }
0442 ++presentIndex;
0443 }
0444 }
0445 if (!container) {
0446 doUnselection();
0447 drawGraph();
0448 } else {
0449 doSelection(container, selectionPoint.x);
0450 }
0451 }
0452 graph_isDragging = false;
0453 graph_mouseDown = false;
0454 }
0455
0456 function graph_onMouseOut() {
0457 graph_isDragging = false
0458 graph_mouseDown = false;
0459 }
0460 function graph_onWheel(event) {
0461 if (event.ctrlKey) {
0462 let currentTransformedCursor = getTransformedPoint(event.offsetX, event.offsetY);
0463 const zoom = event.deltaY < 0 ? 1.02 : 0.98;
0464 const originalScale = 1./timeZoomFactor/kInitPixelsPerSecond;
0465 timeZoomFactor *= zoom;
0466 const newScale = 1./timeZoomFactor/kInitPixelsPerSecond;
0467
0468 minVisibleTime = minVisibleTime + currentTransformedCursor.x*(originalScale-newScale);
0469 } else {
0470 graph_translate(-1*event.deltaX, -1*event.deltaY);
0471 }
0472 drawGraph();
0473 event.preventDefault()
0474 }
0475
0476 window.addEventListener('resize',function(){
0477 graph_context.canvas.width = graph.clientWidth;
0478 graph_context.canvas.height = graph.clientHeight;
0479 name_context.canvas.width = name_view.clientWidth;
0480 name_context.canvas.height = name_view.clientHeight;
0481 time_context.canvas.width = time_view.clientWidth;
0482 time_context.canvas.height = time_view.clientHeight;
0483 drawGraph();
0484 }, false);
0485 graph.addEventListener('mousedown', graph_onMouseDown)
0486 graph.addEventListener('mousemove', graph_onMouseMove)
0487 graph.addEventListener('mouseup', graph_onMouseUp)
0488 graph.addEventListener('mouseout', graph_onMouseOut)
0489 graph.addEventListener('wheel', graph_onWheel);
0490
0491 function time_onMouseDown(event) {
0492 time_isDragging = true;
0493 time_dragStartPosition = getTransformedPoint(event.offsetX, 0).x;
0494 }
0495
0496 function time_onMouseMove(event) {
0497 let currentTransformedCursor = getTransformedPoint(event.offsetX, 0);
0498
0499 if (time_isDragging) {
0500 graph_translate(currentTransformedCursor.x - time_dragStartPosition, 0);
0501 time_dragStartPosition = currentTransformedCursor.x;
0502 drawGraph();
0503 }
0504 }
0505
0506 function time_onMouseUp() {
0507 time_isDragging = false;
0508 }
0509
0510 function time_onMouseOut() {
0511 time_isDragging = false
0512 }
0513
0514 function time_onWheel(event) {
0515 if (event.ctrlKey) {
0516 let currentTransformedCursor = getTransformedPoint(event.offsetX, event.offsetY);
0517 const zoom = event.deltaY < 0 ? 1.02 : 0.98;
0518 const originalScale = 1./timeZoomFactor/kInitPixelsPerSecond;
0519 timeZoomFactor *= zoom;
0520 const newScale = 1./timeZoomFactor/kInitPixelsPerSecond;
0521
0522 minVisibleTime = minVisibleTime + currentTransformedCursor.x*(originalScale-newScale);
0523 } else {
0524 graph_translate(-1*event.deltaX, 0);
0525 }
0526
0527 drawGraph();
0528 event.preventDefault();
0529
0530 }
0531
0532 time_view.addEventListener('mousedown', time_onMouseDown)
0533 time_view.addEventListener('mousemove', time_onMouseMove)
0534 time_view.addEventListener('mouseup', time_onMouseUp)
0535 time_view.addEventListener('mouseout', time_onMouseOut)
0536 time_view.addEventListener('wheel', time_onWheel);
0537
0538 function zoom_in_click(event) {
0539 const zoom = 1.1;
0540 const originalScale = 1. / timeZoomFactor / kInitPixelsPerSecond;
0541 timeZoomFactor *= zoom;
0542 const newScale = 1. / timeZoomFactor / kInitPixelsPerSecond;
0543
0544 minVisibleTime = minVisibleTime + max_graph_width/2*(originalScale-newScale);
0545 drawGraph();
0546 }
0547 function zoom_out_click(event) {
0548 const zoom = 0.909;
0549 const originalScale = 1. / timeZoomFactor / kInitPixelsPerSecond;
0550 timeZoomFactor *= zoom;
0551 const newScale = 1. / timeZoomFactor / kInitPixelsPerSecond;
0552
0553 minVisibleTime = minVisibleTime + max_graph_width/2*(originalScale-newScale);
0554 drawGraph();
0555 }
0556 zoom_in_button.addEventListener("click", zoom_in_click);
0557 zoom_out_button.addEventListener("click", zoom_out_click);
0558
0559 function name_onWheel(event) {
0560 let offset = 0;
0561 graph_translate(0, -1*event.deltaY);
0562 drawGraph();
0563 event.preventDefault()
0564 }
0565 name_view.addEventListener('wheel', name_onWheel);
0566 }