Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions modules/gpad/TFramePainter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2836,21 +2836,9 @@ class TFramePainter extends FrameInteractive {
}
menu.endsub();

if (pad) {
const member = 'fLog' + kind[0];
menu.sub('SetLog ' + kind[0], () => {
menu.input('Enter log kind: 0 - off, 1 - log10, 2 - log2, 3 - ln, ...', pad[member], 'int', 0, 10000).then(v => {
this.changeAxisLog(kind[0], v);
});
});
menu.addchk(pad[member] === 0, 'linear', () => this.changeAxisLog(kind[0], 0));
menu.addchk(pad[member] === 1, 'log10', () => this.changeAxisLog(kind[0], 1));
menu.addchk(pad[member] === 2, 'log2', () => this.changeAxisLog(kind[0], 2));
menu.addchk(pad[member] === 3, 'ln', () => this.changeAxisLog(kind[0], 3));
menu.addchk(pad[member] === 4, 'log4', () => this.changeAxisLog(kind[0], 4));
menu.addchk(pad[member] === 8, 'log8', () => this.changeAxisLog(kind[0], 8));
menu.endsub();
}
if (pad)
menu.addPadLogMenu(kind[0], pad[`fLog${kind[0]}`], v => this.changeAxisLog(kind[0], v));

menu.addchk(faxis.TestBit(EAxisBits.kMoreLogLabels), 'More log', flag => {
faxis.SetBit(EAxisBits.kMoreLogLabels, flag);
if (hist_painter?.getSnapId() && (kind.length === 1))
Expand Down
82 changes: 49 additions & 33 deletions modules/gui/menu.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,20 @@ class JSRootMenu {
this.endsub();
}

/** @summary Add log scale selection for pad
* @protected */
addPadLogMenu(kind, value, func) {
this.sub('SetLog ' + kind,
() => this.input('Enter log kind: 0 - off, 1 - log10, 2 - log2, 3 - ln, ...', value, 'int', 0, 10000).then(func));
this.addchk(value === 0, 'linear', () => func(0));
this.addchk(value === 1, 'log10', () => func(1));
this.addchk(value === 2, 'log2', () => func(2));
this.addchk(value === 3, 'ln', () => func(3));
this.addchk(value === 4, 'log4', () => func(4));
this.addchk(value === 8, 'log8', () => func(8));
this.endsub();
}

/** @summary Add palette menu entries
* @protected */
addPaletteMenu(curr, set_func) {
Expand Down Expand Up @@ -726,38 +740,40 @@ class JSRootMenu {
faxis.fNdivisions = val; painter.interactiveRedraw('pad', `exec:SetNdivisions(${val})`, kind);
}));

this.sub('Labels');
this.addchk(faxis.TestBit(EAxisBits.kCenterLabels), 'Center',
arg => { faxis.SetBit(EAxisBits.kCenterLabels, arg); painter.interactiveRedraw('pad', `exec:CenterLabels(${arg})`, kind); });
this.addchk(faxis.TestBit(EAxisBits.kLabelsVert), 'Rotate',
arg => { faxis.SetBit(EAxisBits.kLabelsVert, arg); painter.interactiveRedraw('pad', `exec:SetBit(TAxis::kLabelsVert,${arg})`, kind); });
this.addColorMenu('Color', faxis.fLabelColor,
arg => { faxis.fLabelColor = arg; painter.interactiveRedraw('pad', getColorExec(arg, 'SetLabelColor'), kind); });
this.addSizeMenu('Offset', -0.02, 0.1, 0.01, faxis.fLabelOffset,
arg => { faxis.fLabelOffset = arg; painter.interactiveRedraw('pad', `exec:SetLabelOffset(${arg})`, kind); });
let a = faxis.fLabelSize >= 1;
this.addSizeMenu('Size', a ? 2 : 0.02, a ? 30 : 0.11, a ? 2 : 0.01, faxis.fLabelSize,
arg => { faxis.fLabelSize = arg; painter.interactiveRedraw('pad', `exec:SetLabelSize(${arg})`, kind); });

if (frame_painter && (axis_painter?.kind === kAxisLabels) && (faxis.fNbins > 20)) {
this.add('Find label', () => this.input('Label id').then(id => {
if (!id)
return;
for (let bin = 0; bin < faxis.fNbins; ++bin) {
const lbl = axis_painter.formatLabels(bin);
if (lbl === id)
return frame_painter.zoomSingle(kind, Math.max(0, bin - 4), Math.min(faxis.fNbins, bin + 5));
}
}), 'Zoom into region around specific label');
}
if (frame_painter && faxis.fLabels) {
const ignore = `${kind}_ignore_labels`;
this.addchk(!frame_painter[ignore], 'Custom', flag => {
frame_painter[ignore] = !flag;
painter.interactiveRedraw('pad');
}, `Use of custom labels in axis ${kind}`);
if (kind !== 'v') {
this.sub('Labels');
this.addchk(faxis.TestBit(EAxisBits.kCenterLabels), 'Center',
arg => { faxis.SetBit(EAxisBits.kCenterLabels, arg); painter.interactiveRedraw('pad', `exec:CenterLabels(${arg})`, kind); });
this.addchk(faxis.TestBit(EAxisBits.kLabelsVert), 'Rotate',
arg => { faxis.SetBit(EAxisBits.kLabelsVert, arg); painter.interactiveRedraw('pad', `exec:SetBit(TAxis::kLabelsVert,${arg})`, kind); });
this.addColorMenu('Color', faxis.fLabelColor,
arg => { faxis.fLabelColor = arg; painter.interactiveRedraw('pad', getColorExec(arg, 'SetLabelColor'), kind); });
this.addSizeMenu('Offset', -0.02, 0.1, 0.01, faxis.fLabelOffset,
arg => { faxis.fLabelOffset = arg; painter.interactiveRedraw('pad', `exec:SetLabelOffset(${arg})`, kind); });
const a = faxis.fLabelSize >= 1;
this.addSizeMenu('Size', a ? 2 : 0.02, a ? 30 : 0.11, a ? 2 : 0.01, faxis.fLabelSize,
arg => { faxis.fLabelSize = arg; painter.interactiveRedraw('pad', `exec:SetLabelSize(${arg})`, kind); });

if (frame_painter && (axis_painter?.kind === kAxisLabels) && (faxis.fNbins > 20)) {
this.add('Find label', () => this.input('Label id').then(id => {
if (!id)
return;
for (let bin = 0; bin < faxis.fNbins; ++bin) {
const lbl = axis_painter.formatLabels(bin);
if (lbl === id)
return frame_painter.zoomSingle(kind, Math.max(0, bin - 4), Math.min(faxis.fNbins, bin + 5));
}
}), 'Zoom into region around specific label');
}
if (frame_painter && faxis.fLabels) {
const ignore = `${kind}_ignore_labels`;
this.addchk(!frame_painter[ignore], 'Custom', flag => {
frame_painter[ignore] = !flag;
painter.interactiveRedraw('pad');
}, `Use of custom labels in axis ${kind}`);
}
this.endsub();
}
this.endsub();

this.sub('Title');
this.add('SetTitle', () => {
Expand All @@ -784,8 +800,8 @@ class JSRootMenu {
});
this.addSizeMenu('Offset', 0, 3, 0.2, faxis.fTitleOffset,
arg => { faxis.fTitleOffset = arg; painter.interactiveRedraw('pad', `exec:SetTitleOffset(${arg})`, kind); });
a = faxis.fTitleSize >= 1;
this.addSizeMenu('Size', a ? 2 : 0.02, a ? 30 : 0.11, a ? 2 : 0.01, faxis.fTitleSize,
const p = faxis.fTitleSize >= 1;
this.addSizeMenu('Size', p ? 2 : 0.02, p ? 30 : 0.11, p ? 2 : 0.01, faxis.fTitleSize,
arg => { faxis.fTitleSize = arg; painter.interactiveRedraw('pad', `exec:SetTitleSize(${arg})`, kind); });
this.endsub();

Expand Down
30 changes: 16 additions & 14 deletions modules/hist/TH3Painter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ class TH3Painter extends THistPainter {
const histo = this.getHisto(),
fp = this.getFramePainter();

// ensure proper colors
this.resetContour();

let use_lambert = false,
use_helper = false, use_colors = false, use_opacity = 1, exclude_content = -1,
logv = this.getPadPainter()?.getRootPad()?.fLogv,
Expand Down Expand Up @@ -469,19 +472,6 @@ class TH3Painter extends THistPainter {
} else if (use_scale)
use_scale = (this.gminbin || this.gmaxbin) ? 1 / Math.max(Math.abs(this.gminbin), Math.abs(this.gmaxbin)) : 1;

const get_bin_weight = content => {
if ((exclude_content >= 0) && (content < exclude_content))
return 0;
if (!use_scale)
return 1;
if (logv) {
if (content <= 0)
return 0;
content = Math.log(content) - scale_offset;
}
return Math.pow(Math.abs(content * use_scale), 0.3333);
};
// eslint-disable-next-line one-var
const i1 = this.getSelectIndex('x', 'left', 0.5),
i2 = this.getSelectIndex('x', 'right', 0),
j1 = this.getSelectIndex('y', 'left', 0.5),
Expand All @@ -495,7 +485,19 @@ class TH3Painter extends THistPainter {
const cntr = use_colors ? this.getContour() : null,
palette = use_colors ? this.getHistPalette() : null,
bins_matrixes = [], bins_colors = [], bins_ids = [], negative_matrixes = [], bin_opacities = [],
transfer = (this.transferFunc && proivdeEvalPar(this.transferFunc, true)) ? this.transferFunc : null;
transfer = (this.transferFunc && proivdeEvalPar(this.transferFunc, true)) ? this.transferFunc : null,
get_bin_weight = content => {
if ((exclude_content >= 0) && (content < exclude_content))
return 0;
if (!use_scale)
return 1;
if (logv) {
if (content <= 0)
return 0;
content = Math.log(content) - scale_offset;
}
return Math.pow(Math.abs(content * use_scale), 0.3333);
};

for (let i = i1; i < i2; ++i) {
const grx1 = fp.grx(histo.fXaxis.GetBinLowEdge(i + 1)),
Expand Down
87 changes: 73 additions & 14 deletions modules/hist/TPavePainter.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { gStyle, browser, settings, clone, create, isObject, isFunc, isStr, BIT,
clTPave, clTPaveText, clTPavesText, clTPaveStats, clTPaveLabel, clTPaveClass, clTDiamond, clTLegend, clTPaletteAxis,
clTText, clTLatex, clTLine, clTBox, kTitle, isNodeJs, nsSVG } from '../core.mjs';
clTText, clTLatex, clTLine, clTBox, clTAxis,
kTitle, isNodeJs, nsSVG, urlClassPrefix, kNoZoom } from '../core.mjs';
import { select as d3_select, rgb as d3_rgb, pointer as d3_pointer } from '../d3.mjs';
import { Prob } from '../base/math.mjs';
import { floatToString, makeTranslate, compressSVG, svgToImage, addHighlightStyle } from '../base/BasePainter.mjs';
import { ObjectPainter, EAxisBits } from '../base/ObjectPainter.mjs';
import { approximateLabelWidth } from '../base/latex.mjs';
import { showPainterMenu } from '../gui/menu.mjs';
import { showPainterMenu, createMenu } from '../gui/menu.mjs';
import { getColorExec } from '../gui/utils.mjs';
import { TAxisPainter } from '../gpad/TAxisPainter.mjs';
import { addDragHandler } from '../gpad/TFramePainter.mjs';
Expand Down Expand Up @@ -1034,10 +1035,10 @@ class TPavePainter extends ObjectPainter {
height = pp.getPadHeight(),
pad = pp.getRootPad(true),
main = palette.$main_painter || this.getMainPainter(),
is_th3 = isFunc(main.getDimension) && (main.getDimension() === 3),
fp = this.getFramePainter(),
contour = main.getContour(false),
contour = main.getContour(is_th3),
levels = contour?.getLevels(),
is_th3 = isFunc(main.getDimension) && (main.getDimension() === 3),
is_scatter = isFunc(main.getZaxis),
log = pad?.fLogv ?? (is_th3 ? false : pad?.fLogz),
draw_palette = main.getHistPalette(),
Expand All @@ -1047,6 +1048,7 @@ class TPavePainter extends ObjectPainter {
let zmin = 0, zmax = 100, gzmin, gzmax, axis_transform, axis_second = 0;

this.#palette_vertical = (palette.fX2NDC - palette.fX1NDC) < (palette.fY2NDC - palette.fY1NDC);
this.is_th3 = is_th3;

axis.fTickSize = 0.03; // adjust axis ticks size

Expand Down Expand Up @@ -1083,12 +1085,16 @@ class TPavePainter extends ObjectPainter {
}
} else if ((main.gmaxbin !== undefined) && (main.gminbin !== undefined)) {
// this is case of TH2 (needs only for size adjustment)
zmin = main.gminbin;
zmax = main.gmaxbin;
gzmin = zmin = main.gminbin;
gzmax = zmax = main.gmaxbin;
if (contour?.colzmin !== undefined && contour?.colzmax !== undefined) {
zmin = contour.colzmin;
zmax = contour.colzmax;
}
} else if ((main.hmin !== undefined) && (main.hmax !== undefined)) {
// this is case of TH1
zmin = main.hmin;
zmax = main.hmax;
gzmin = zmin = main.hmin;
gzmax = zmax = main.hmax;
}

g.selectAll('rect').style('fill', 'white');
Expand Down Expand Up @@ -1260,6 +1266,17 @@ class TPavePainter extends ObjectPainter {
zoom_rect.attr('x', Math.min(sel1, sel2))
.attr('width', Math.abs(sel2 - sel1));
}
}, zoomPalette = (z1, z2) => {
if (!this.is_th3)
return this.getFramePainter().zoomSingle('z', z1, z2, true);
const maino = this.getMainPainter().options;
if (z1 === z2)
maino.minimum = maino.maximum = kNoZoom;
else {
maino.minimum = z1;
maino.maximum = z2;
}
this.interactiveRedraw('pad');
}, endRectSel = evnt => {
if (!doing_zoom)
return;
Expand All @@ -1271,10 +1288,13 @@ class TPavePainter extends ObjectPainter {
zoom_rect = null;
doing_zoom = false;

if (sel1 === sel2)
return;

const z1 = this.z_handle.revertPoint(sel1),
z2 = this.z_handle.revertPoint(sel2);

this.getFramePainter().zoomSingle('z', Math.min(z1, z2), Math.max(z1, z2), true);
zoomPalette(Math.min(z1, z2), Math.max(z1, z2));
}, startRectSel = evnt => {
// ignore when touch selection is activated
if (doing_zoom)
Expand Down Expand Up @@ -1309,7 +1329,7 @@ class TPavePainter extends ObjectPainter {
if (settings.Zooming) {
this.getG().selectAll('.axis_zoom')
.on('mousedown', startRectSel)
.on('dblclick', () => this.getFramePainter().zoomSingle('z', 0, 0, true));
.on('dblclick', () => zoomPalette(0, 0));
}

if (settings.ZoomWheel) {
Expand All @@ -1318,7 +1338,7 @@ class TPavePainter extends ObjectPainter {
coord = this.#palette_vertical ? (1 - pos[1] / s_height) : pos[0] / s_width,
item = this.z_handle.analyzeWheelEvent(evnt, coord);
if (item?.changed)
this.getFramePainter().zoomSingle('z', item.min, item.max, true);
zoomPalette(item.min, item.max);
});
}
}
Expand Down Expand Up @@ -1523,12 +1543,51 @@ class TPavePainter extends ObjectPainter {

/** @summary Show pave context menu */
paveContextMenu(evnt) {
if (this.z_handle) {
if (!this.z_handle)
return showPainterMenu(evnt, this);
if (!this.is_th3) {
const fp = this.getFramePainter();
if (isFunc(fp?.showContextMenu))
fp.showContextMenu('pal', evnt);
} else
showPainterMenu(evnt, this);
return;
}

const pp = this.getPadPainter(),
pad = pp?.getRootPad(true),
faxis = this.z_handle.getObject(),
hist_painter = this.z_handle.hist_painter || this.getMainPainter(true);

if (!pad || !hist_painter)
return;

if (isFunc(evnt?.stopPropagation)) {
evnt.preventDefault();
evnt.stopPropagation(); // disable main context menu
}

createMenu(evnt, this).then(menu => {
menu.header('V axis', `${urlClassPrefix}${clTAxis}.html`);

menu.addPadLogMenu('v', pad.fLogv || 0, v => {
pad.fLogv = v;
this.interactiveRedraw('pad', 'log');
});

menu.addchk(faxis.TestBit(EAxisBits.kMoreLogLabels), 'More log', flag => {
faxis.SetBit(EAxisBits.kMoreLogLabels, flag);
this.interactiveRedraw('pad');
});
menu.addchk(faxis.TestBit(EAxisBits.kNoExponent), 'No exponent', flag => {
faxis.SetBit(EAxisBits.kNoExponent, flag);
this.interactiveRedraw('pad');
});

hist_painter.fillPaletteMenu(menu, false);

menu.addTAxisMenu(EAxisBits, hist_painter || this, faxis, 'v', this.z_handle, null);

menu.show();
});
}

/** @summary Returns true when stat box is drawn */
Expand Down
8 changes: 7 additions & 1 deletion modules/hist2d/THistPainter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2282,6 +2282,12 @@ class THistPainter extends ObjectPainter {
return cntr;
}

/** @summary Reset contour object
* @private */
resetContour() {
this.#contour = undefined;
}

/** @summary Return Z-scale ranges to create contour */
#getContourRanges(main, fp) {
const o = this.getOptions(),
Expand Down Expand Up @@ -2862,7 +2868,7 @@ class THistPainter extends ObjectPainter {
this.maxbin = this.minbin = 0;

// force recalculation of z levels
this.#contour = undefined;
this.resetContour();

if (args.zrange)
Object.assign(res, this.#getContourRanges(this.getMainPainter(), this.getFramePainter()));
Expand Down