5 JSROOT.define([
"painter"], jsrp => {
9 const GO4 = { version:
"6.2.0", id_counter: 1, source_dir:
"" };
12 const pos = go4Script.src.indexOf(
"html/go4.js");
14 GO4.source_dir = go4Script.src.substr(0, pos);
15 console.log(`Set GO4.source_dir to ${GO4.source_dir}, ${GO4.version}`);
21 GO4.ExecuteMethod =
function(painter, method, options) {
23 if (painter.getItemName())
24 prefix = painter.getItemName() +
"/";
26 let fullcom = prefix +
"exe.json?method=" + method + (options ||
"&");
28 return JSROOT.httpRequest(fullcom,
'text');
33 GO4.DrawAnalysisRatemeter =
function(divid, itemname) {
35 function CreateHTML() {
36 let elem = d3.select(
'#'+divid);
38 if (elem.size() == 0)
return null;
39 if (elem.select(
".event_rate").size() > 0)
return elem;
41 let html =
"<div style='padding-top:2px'>";
42 html +=
"<img class='go4_logo' style='vertical-align:middle;margin-left:5px;margin-right:5px;' src='go4sys/icons/go4logorun4.gif' alt='logo'></img>";
43 html +=
"<label class='event_source' style='border: 1px solid gray; font-size:large; vertical-align:middle; padding-left:3px; padding-right:3px;'>file.lmd</label> ";
44 html +=
"<label class='event_rate' style='border: 1px solid gray; font-size:large; vertical-align:middle; background-color: grey'; padding-left:3px; padding-right:3px;>---</label> Ev/s ";
45 html +=
"<label class='aver_rate' style='border: 1px solid gray; font-size:large; vertical-align:middle; padding-left:3px; padding-right:3px;'>---</label> Ev/s ";
46 html +=
"<label class='run_time' style='border: 1px solid gray; font-size:large; vertical-align:middle; padding-left:3px; padding-right:3px;'>---</label> s ";
47 html +=
"<label class='total_events' style='border: 1px solid gray; font-size:large; vertical-align:middle; padding-left:3px; padding-right:3px;'>---</label> Events ";
48 html +=
"<label class='analysis_time' style='border: 1px solid gray; font-size:large; vertical-align:middle; padding-left:3px; padding-right:3px;'>time</label>";
51 elem.style(
'overflow',
'hidden')
52 .style(
'padding-left',
'5px')
53 .style(
'display',
'inline-block')
54 .style(
'white-space',
'nowrap')
58 let brlayout = JSROOT.hpainter ? JSROOT.hpainter.brlayout : null,
59 sz = elem.node().clientHeight + 12;
62 brlayout.adjustSeparators(null, sz,
true);
66 let xreq =
false, was_running = null;
68 function UpdateRatemeter() {
71 let elem = CreateHTML();
75 JSROOT.httpRequest(itemname +
"/root.json.gz",
'object').then(res => {
76 elem.select(
".event_rate").style(
'background-color', res.fbRunning ?
'lightgreen' :
'red');
77 if (was_running != res.fbRunning)
78 elem.select(
".go4_logo").attr(
"src", res.fbRunning ?
'go4sys/icons/go4logorun4.gif' :
'go4sys/icons/go4logo_t.png');
80 was_running = res.fbRunning;
82 elem.select(
".event_source").text(res.fxEventSource ==
"" ?
"<source>" : res.fxEventSource);
83 elem.select(
".event_rate").text(res.fdRate.toFixed(1));
84 elem.select(
".aver_rate").text((res.fdTime > 0 ? res.fuCurrentCount / res.fdTime : 0).toFixed(1));
85 elem.select(
".run_time").text(res.fdTime.toFixed(1));
86 elem.select(
".total_events").text(res.fuCurrentCount);
87 elem.select(
".analysis_time").text(res.fxDateString ==
"" ?
"<datime>" : res.fxDateString);
89 elem.select(
".event_rate").style(
'background-color',
'grey');
97 setInterval(UpdateRatemeter, 2000);
101 GO4.MakeMsgListRequest =
function(hitem, item) {
102 let arg =
"&max=2000";
103 if (
'last-id' in item) arg+=
"&id="+item[
'last-id'];
104 return 'exe.json.gz?method=Select' + arg;
107 GO4.AfterMsgListRequest =
function(hitem, item, obj) {
111 delete item[
'last-id'];
115 if (obj._typename !=
'TList')
return;
117 obj._typename =
"TGo4MsgList";
119 if (obj.arr.length>0) {
120 let duplicate = ((
'last-id' in item) && (item[
'last-id'] == obj.arr[0].fString));
122 item[
'last-id'] = obj.arr[0].fString;
125 if (duplicate) obj.arr.length = 1;
128 if (!(
'clear' in item))
129 item[
'clear'] =
function() {
delete this[
'last-id']; }
133 class MsgListPainter
extends JSROOT.BasePainter {
135 constructor(dom, lst) {
148 if (!this.lst)
return;
150 let frame = this.selectDom();
152 let
main = frame.select(
"div");
154 main = frame.append(
"div")
155 .style(
'max-width',
'100%')
156 .style(
'max-height',
'100%')
157 .style(
'overflow',
'auto');
159 let old = main.selectAll(
"pre");
160 let newsize = old.size() + this.lst.arr.length - 1;
164 old.select(
function(d,i) {
return i < newsize - 2000 ?
this : null; }).
remove();
166 for (let i = this.lst.arr.length-1; i > 0; i--)
167 main.append(
"pre").style(
'margin',
'3px').html(this.lst.arr[i].fString);
171 GO4.DrawMsgList =
function(dom, lst) {
173 let painter =
new MsgListPainter(dom, lst);
177 painter.setTopPainter();
178 return Promise.resolve(painter);
181 class AnalysisTerminalPainter
extends JSROOT.BasePainter {
182 constructor(frame, hpainter, itemname, url) {
184 this.hpainter = hpainter;
185 this.itemname = itemname;
187 this.draw_ready =
true;
188 this.needscroll =
false;
192 if (p) this.log_painter = p;
193 if(this.needscroll) {
194 this.clickScroll(
true);
195 this.needscroll =
false;
197 this.draw_ready =
true;
203 if (this.log_painter) {
204 this.log_painter.cleanup();
205 delete this.log_painter;
208 clearInterval(this.interval);
209 delete this.interval;
215 let subid =
"anaterm_output_container";
217 if (d3.select(
"#" + subid).empty())
218 return this.cleanup();
220 if (!this.draw_ready)
return;
222 let msgitem = this.itemname.replace(
"Control/Terminal",
"Status/Log");
224 this.draw_ready =
false;
226 if (this.log_painter)
227 this.hpainter.display(msgitem,
"update:divid:" + subid).then(() => this.logReady());
229 this.hpainter.display(msgitem,
"divid:" + subid).then(p => this.logReady(p));
233 let command = this.itemname.replace(
"Terminal",
"CmdExecute");
234 this.hpainter.executeCommand(command, null, kind). then(() => { this.needscroll =
true; });
238 d3.select(
"#anaterm_output_container").html(
"");
243 let nodes = d3.select(
"#anaterm_output_container").selectAll(
"pre").nodes();
244 if (nodes) nodes[last ? nodes.length-1 : 0].scrollIntoView();
248 this.setTopPainter();
249 this.interval = setInterval(() => this.processTimer(), 2000);
250 let dom = this.selectDom();
252 dom.select(
".go4_clearterm")
253 .on(
"click", () => this.clickClear())
254 .style(
'background-image',
"url(" + GO4.source_dir +
"icons/clear.png)");
256 dom.select(
".go4_startterm")
257 .on(
"click", () => this.clickScroll(
false))
258 .style(
'background-image',
"url(" + GO4.source_dir +
"icons/shiftup.png)");
260 dom.select(
".go4_endterm")
261 .on(
"click", () => this.clickScroll(
true))
262 .style(
'background-image',
"url(" + GO4.source_dir +
"icons/shiftdown.png)");
264 dom.select(
".go4_printhistos")
265 .on(
"click", () => this.clickCommand(
"@PrintHistograms()"))
266 .style(
'background-image',
"url(" + GO4.source_dir +
"icons/hislist.png)");
268 dom.select(
".go4_printcond")
269 .on(
"click", () => this.clickCommand(
"@PrintConditions()"))
270 .style(
'background-image',
"url(" + GO4.source_dir +
"icons/condlist.png)");
272 dom.select(
".go4_executescript")
273 .style(
'background-image',
"url(" + GO4.source_dir +
"icons/macro_t.png)");
275 dom.select(
".go4_anaterm_cmd_form").on(
"submit", event => {
276 event.preventDefault();
277 let command = this.itemname.replace(
"Terminal",
"CmdExecute");
278 let cmdpar = document.getElementById(
"go4_anaterm_command").value;
279 console.log(
"submit command - " + cmdpar);
280 this.hpainter.executeCommand(command, null, cmdpar).then(() => { this.needscroll =
true; });
286 GO4.drawAnalysisTerminal =
function(hpainter, itemname) {
287 let url = hpainter.getOnlineItemUrl(itemname),
288 mdi = hpainter.getDisplay(),
289 frame = mdi ? mdi.findFrame(itemname,
true) : null;
291 if (!url || !frame)
return null;
293 let elem = d3.select(frame),
294 h = frame.clientHeight,
295 w = frame.clientWidth;
296 if ((h < 10) && (w > 10)) elem.style(
"height", Math.round(w*0.7)+
"px");
298 let player =
new AnalysisTerminalPainter(frame, hpainter, itemname, url);
300 return JSROOT.httpRequest(GO4.source_dir +
"html/terminal.htm",
"text")
303 player.fillDisplay();
325 function getOptValue(pic, indx, typ) {
326 if (!pic || !pic.fxOptIndex)
return null;
327 let srch = indx + 1 + (typ << 16);
328 for (let k = 0; k < pic.fxOptIndex.length; ++k)
329 if (pic.fxOptIndex[k] == srch)
330 return pic.fxOptValue[k];
334 function getOptDouble(pic, indx, typ) {
335 let ivalue = getOptValue(pic, indx, typ);
336 if (ivalue === null)
return null;
337 const buffer =
new ArrayBuffer(16),
338 view =
new DataView(buffer),
339 big = BigInt(ivalue);
340 view.setUint32(0, Number(big >> 32n));
341 view.setUint32(4, Number(big % (2n ** 32n)));
342 return view.getFloat64(0);
345 function drawSpecialObjects(divid, pic, k) {
346 if (!pic.fxSpecialObjects || (k >= pic.fxSpecialObjects.arr.length))
347 return Promise.resolve(
false);
349 return JSROOT.draw(divid, pic.fxSpecialObjects.arr[k], pic.fxSpecialObjects.opt[k]).then(() => drawSpecialObjects(divid, pic, k+1));
352 function drawPictureObjects(divid, pic, k) {
353 if (!divid || !pic.fxNames)
354 return Promise.resolve(
false);
356 let arr = pic.fxNames ? pic.fxNames.arr : null;
357 if (!arr || (k >= arr.length))
358 return drawSpecialObjects(divid, pic, 0);
360 let n = pic.fxNames.arr[k], itemname =
"", isth2 =
false;
362 JSROOT.hpainter.forEachItem(item => {
363 if (item._name == n.fString) {
364 itemname = JSROOT.hpainter.itemFullName(item);
365 if (item._kind && (item._kind.indexOf(
"ROOT.TH2") == 0)) isth2 = true;
370 console.log(
'not found object with name', n.fString);
371 return drawPictureObjects(divid, pic, k+1);
376 let opt = isth2 ?
"col" :
"",
377 iopt = getOptValue(pic, k,
op_Draw);
378 if ((iopt !== null) && pic.fxOptObjects)
379 opt = pic.fxOptObjects.arr[iopt].fString;
380 if (k > 0) opt +=
" same";
382 return JSROOT.hpainter.display(itemname, opt +
"divid:" + divid).then(painter => {
383 if (!painter)
return;
384 let need_redraw =
false;
386 if (painter.lineatt) {
387 let lcol = getOptValue(pic, k, op_LineColor),
388 lwidth = getOptValue(pic, k, op_LineWidth),
389 lstyle = getOptValue(pic, k, op_LineStyle);
390 if ((lcol !== null) && (lwidth !== null) && (lstyle !== null)) {
391 painter.lineatt.change(painter.getColor(lcol), lwidth, lstyle);
396 if (painter.fillatt) {
397 let fcol = getOptValue(pic, k, op_FillColor),
398 fstyle = getOptValue(pic, k, op_FillStyle);
400 if ((fcol !== null) && (fstyle !== null)) {
401 painter.fillatt.change(fcol, fstyle, painter.getCanvSvg());
406 if (typeof painter.getHisto ==
'function' && painter.createHistDrawAttributes && painter.isMainPainter()) {
407 const kNoStats = JSROOT.BIT(9),
408 kNoTitle = JSROOT.BIT(17);
410 let histo = painter.getHisto(),
411 stat = painter.findStat(),
416 has_stats_pos = (sx1 !== null) && (sy1 !== null) && (sx2!==null) && (sy2!==null),
417 istitle = getOptValue(pic, PictureIndex,
op_HisTitle),
418 isstats = getOptValue(pic, PictureIndex,
op_HisStats),
422 if ((istitle !== null) && (!istitle != histo.TestBit(kNoTitle))) {
423 histo.InvertBit(kNoTitle); need_redraw =
true;
425 if ((isstats !== null) && (!isstats != histo.TestBit(kNoStats))) {
426 histo.InvertBit(kNoStats); need_redraw =
true;
428 if (stat && ((statsopt !== null) || (fitopt !== null) || has_stats_pos)) {
429 if (statsopt !== null) stat.fOptStat = statsopt;
430 if (fitopt !== null) stat.fOptFit = fitopt;
431 let pp = painter.getPadPainter(),
432 statpainter = pp ? pp.findPainterFor(stat) : null;
439 if (statpainter) statpainter.redraw();
443 if (need_redraw)
return painter.redraw();
445 }).then(() => drawPictureObjects(divid, pic, k+1));
448 function drawSubPictures(pad_painter, pic, nsub) {
449 let arr = pic && pic.fxSubPictures ? pic.fxSubPictures.arr : null;
450 if (!arr || nsub >= arr.length)
451 return Promise.resolve(pad_painter);
453 let subpic = pic.fxSubPictures.arr[nsub];
455 let subpad_painter = pad_painter.getSubPadPainter(1 + subpic.fiPosY*pic.fiNDivX + subpic.fiPosX);
457 return drawPicture(subpad_painter, subpic).then(() => drawSubPictures(pad_painter, pic, nsub+1));
460 function drawPicture(pad_painter, pic) {
462 return Promise.resolve(
false);
464 let need_divide = pic.fiNDivX * pic.fiNDivY > 1;
466 if (need_divide && !pad_painter.divide) {
467 console.log(
'JSROOT version without TPadPainter.divide');
468 return Promise.resolve(
false);
471 let prev_name = pad_painter.selectCurrentPad(pad_painter.this_pad_name);
474 return pad_painter.divide(pic.fiNDivX, pic.fiNDivY).then(() => drawSubPictures(pad_painter, pic, 0)).then(() => {
475 pad_painter.selectCurrentPad(prev_name);
479 let divid = pad_painter.selectDom().attr(
'id');
481 divid =
"go4picture_div_" + GO4.id_counter++;
482 pad_painter.selectDom().attr(
'id', divid);
483 console.error(
'Drawing must be done on element with id, force ', divid);
486 return drawPictureObjects(divid, pic, 0).then(() => {
487 pad_painter.selectCurrentPad(prev_name);
492 GO4.drawGo4Picture =
function(dom, pic) {
493 if (!JSROOT.hpainter)
return null;
495 let painter =
new JSROOT.ObjectPainter(dom, pic);
497 return JSROOT.require(
'gpad').then(() => jsrp.ensureTCanvas(painter,
false)).then(() => {
498 let pad_painter = painter.getPadPainter();
500 painter.removeFromPadPrimitives();
502 return drawPicture(pad_painter, pic);
503 }).then(() => painter);
508 let canvsrc = GO4.source_dir +
'html/go4canvas.js;';
510 jsrp.addDrawFunc({ name:
"TGo4WinCond", script: canvsrc, func:
'GO4.drawGo4Cond', opt:
";editor" });
511 jsrp.addDrawFunc({ name:
"TGo4PolyCond", script: canvsrc, func:
'GO4.drawGo4Cond', opt:
";editor" });
512 jsrp.addDrawFunc({ name:
"TGo4ShapedCond", script: canvsrc, func:
'GO4.drawGo4Cond', opt:
";editor" });
513 jsrp.addDrawFunc({ name:
"TGo4CondArray", script: canvsrc, func:
'GO4.drawCondArray', opt:
";editor" });
514 jsrp.addDrawFunc({ name:
"TGo4Marker", script: canvsrc, func:
'GO4.drawGo4Marker' });
516 jsrp.addDrawFunc({ name:
"TGo4AnalysisWebStatus", script: GO4.source_dir +
'html/analysiseditor.js', func:
'GO4.drawGo4AnalysisStatus', opt:
"editor" });
518 jsrp.addDrawFunc({ name:
"TGo4MsgList", func: GO4.DrawMsgList });
519 jsrp.addDrawFunc({ name:
"TGo4Picture", func: GO4.drawGo4Picture, icon: GO4.source_dir +
"icons/picture.png" });
521 jsrp.addDrawFunc({ name:
"TGo4MbsEvent", noinspect:
true });
522 jsrp.addDrawFunc({ name:
"TGo4EventElement", noinspect:
true });
524 globalThis.GO4 = GO4;
int main(int argc, char **argv)