From 8c4950e277d0227795baae16c5cd9ed3e28e352d Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Fri, 31 May 2024 16:51:23 -0500 Subject: [PATCH 01/25] remove unnecessary import --- js/menu/filter/filter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index 93d9c08f..a7b4a0c2 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -1,4 +1,3 @@ -import { Link } from "../../objects.js"; import { drawAll } from "../../draw.js"; import { parentLinks, childrenLinks, infoBoxes, ctx } from "../../main.js"; import { Range, Checkbox, buildCriteriaFunction } from "./parameters.js"; From f381347c259bcea5412ee8ca097b20fa95318dcf Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Fri, 31 May 2024 17:12:13 -0500 Subject: [PATCH 02/25] make filters more compact --- css/main.css | 9 +++++++++ js/menu/filter/parameters.js | 36 ++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/css/main.css b/css/main.css index 92b54659..6b7406b1 100644 --- a/css/main.css +++ b/css/main.css @@ -8,3 +8,12 @@ body { .manipulation-tool { display: none; } + +input[type="number"]::-webkit-outer-spin-button, +input[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} +input[type="number"] { + -moz-appearance: textfield; +} diff --git a/js/menu/filter/parameters.js b/js/menu/filter/parameters.js index 60f1d6d6..76b52e37 100644 --- a/js/menu/filter/parameters.js +++ b/js/menu/filter/parameters.js @@ -15,6 +15,16 @@ class FilterParameter { } } +function createNumberInput(container, placeholder) { + const input = document.createElement("input"); + input.type = "number"; + input.placeholder = placeholder; + input.style.width = "50px"; + + container.appendChild(input); + return input; +} + export class Range extends FilterParameter { min; max; @@ -24,22 +34,24 @@ export class Range extends FilterParameter { } render(container) { + const title = document.createElement("div"); const label = document.createElement("label"); label.textContent = this.property; - container.appendChild(label); - - const inputMin = document.createElement("input"); - inputMin.type = "number"; - inputMin.placeholder = "min"; - container.appendChild(inputMin); + title.appendChild(label); + const content = document.createElement("div"); + const inputMin = createNumberInput(container, "min"); const separator = document.createTextNode(" - "); - container.appendChild(separator); - - const inputMax = document.createElement("input"); - inputMax.type = "number"; - inputMax.placeholder = "max"; - container.appendChild(inputMax); + const inputMax = createNumberInput(container, "max"); + content.appendChild(inputMin); + content.appendChild(separator); + content.appendChild(inputMax); + content.style.display = "flex"; + content.style.flexDirection = "row"; + content.style.justifyContent = "space-around"; + + container.appendChild(title); + container.appendChild(content); inputMin.addEventListener("input", () => { this.min = inputMin.value; From 7085a38535d2fb910ad73c06795aef89c2433e11 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Fri, 31 May 2024 17:34:37 -0500 Subject: [PATCH 03/25] populate simulation status options based on file --- js/main.js | 5 +++++ js/menu/filter/filter.js | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/js/main.js b/js/main.js index 2f342da6..7a30b2ef 100644 --- a/js/main.js +++ b/js/main.js @@ -1,6 +1,7 @@ import { errorMsg, loadMCParticles } from "./tools.js"; import { PdgToggle } from "./menu/show-pdg.js"; import { drawAll } from "./draw.js"; +import { bits } from "./menu/filter/filter.js"; const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); @@ -329,6 +330,10 @@ document tool.style.display = "flex"; } + infoBoxes.forEach((infoBox) => bits.add(infoBox.simStatus)); + bits.setCheckBoxes(); + bits.render(); + const pdgToggle = new PdgToggle("show-pdg"); pdgToggle.init(() => { pdgToggle.toggle(infoBoxes, () => { diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index a7b4a0c2..98e7fbbc 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -34,15 +34,19 @@ parametersRange = parametersRange.map((parameter) => new Range(parameter)); parametersRange.forEach((parameter) => parameter.render(filters)); -let bitsCheckbox = [23, 24, 25, 26, 27, 28, 29, 30]; - -bitsCheckbox = bitsCheckbox.map((bit) => new Checkbox("simStatus", bit)); - -bitsCheckbox.forEach((checkbox) => checkbox.render(filters)); +let bits = { + simStatuses: new Set(), + add: (simStatus) => bits.simStatuses.add(simStatus), + checkBoxes: [], + toCheckBox: () => + Array.from(bits.simStatuses).map((bit) => new Checkbox("simStatus", bit)), + setCheckBoxes: () => (bits.checkBoxes = bits.toCheckBox()), + render: () => bits.checkBoxes.forEach((checkbox) => checkbox.render(filters)), +}; apply.addEventListener("click", () => { const rangeFunctions = Range.buildFilter(parametersRange); - const checkboxFunctions = Checkbox.buildFilter(bitsCheckbox); + const checkboxFunctions = Checkbox.buildFilter(bits.checkBoxes); const criteriaFunction = buildCriteriaFunction( rangeFunctions, @@ -70,8 +74,10 @@ reset.addEventListener("click", () => { parameter.render(filters); }); - bitsCheckbox.forEach((checkbox) => { + bits.checkBoxes.forEach((checkbox) => { checkbox.checked = false; checkbox.render(filters); }); }); + +export { bits }; From 4f6fd31cfbc2c6bc6833601c83a2524173424038 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Sat, 1 Jun 2024 13:43:30 -0500 Subject: [PATCH 04/25] apply sort of dependecy inversion, so elements are taken passed dynamically (particles and links) --- js/draw.js | 33 +++++- js/events.js | 169 ++++++++++++++++++++++++++++ js/main.js | 235 +++++++++++---------------------------- js/menu/filter/filter.js | 12 +- 4 files changed, 272 insertions(+), 177 deletions(-) create mode 100644 js/events.js diff --git a/js/draw.js b/js/draw.js index 09aa8a6b..40ce4818 100644 --- a/js/draw.js +++ b/js/draw.js @@ -1,4 +1,8 @@ -export function drawAll(ctx, parentLinks, childrenLinks, infoBoxes) { +import { canvas, ctx } from "./main.js"; + +export function drawAll(ctx, particlesHandler) { + const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; + ctx.clearRect(0, 0, canvas.width, canvas.height); // console.time("drawParentLinks"); for (const link of parentLinks) { @@ -16,3 +20,30 @@ export function drawAll(ctx, parentLinks, childrenLinks, infoBoxes) { } // console.timeEnd("drawBoxes"); } + +export function drawVisible(visibleParticles, particlesHandler) { + const { + infoBoxes: visibleBoxes, + parentLinks: visibleParentLinks, + childrenLinks: visibleChildrenLinks, + } = visibleParticles; + + const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; + + const boundigClientRect = canvas.getBoundingClientRect(); + ctx.clearRect( + 0 - boundigClientRect.x, + 0 - boundigClientRect.y, + window.innerWidth, + window.innerHeight + ); + for (const linkId of visibleParentLinks) { + parentLinks[linkId].draw(ctx, infoBoxes); + } + for (const linkId of visibleChildrenLinks) { + childrenLinks[linkId].draw(ctx, infoBoxes); + } + for (const boxId of visibleBoxes) { + infoBoxes[boxId].draw(ctx); + } +} diff --git a/js/events.js b/js/events.js new file mode 100644 index 00000000..d2de797f --- /dev/null +++ b/js/events.js @@ -0,0 +1,169 @@ +import { canvas, ctx } from "./main.js"; +import { drawAll, drawVisible } from "./draw.js"; + +const mouseDown = function ( + event, + particlesHandler, + visibleParticles, + dragTools +) { + event.preventDefault(); + const boundigClientRect = canvas.getBoundingClientRect(); + const mouseX = parseInt(event.clientX - boundigClientRect.x); + const mouseY = parseInt(event.clientY - boundigClientRect.y); + + dragTools.prevMouseX = mouseX; + dragTools.prevMouseY = mouseY; + + const visibleBoxes = visibleParticles.infoBoxes; + const infoBoxes = particlesHandler.infoBoxes; + for (let i = visibleBoxes.length - 1; i >= 0; i--) { + if (infoBoxes[visibleBoxes[i]].isHere(mouseX, mouseY)) { + dragTools.draggedInfoBox = visibleBoxes[i]; + dragTools.isDragging = true; + return; + } + } +}; + +const mouseUp = function (event, dragTools, particlesHandler) { + if (!dragTools.isDragging) { + return; + } + + event.preventDefault(); + dragTools.isDragging = false; + + // console.time("drawAll"); + drawAll(ctx, particlesHandler); + // console.timeEnd("drawAll"); +}; + +const mouseOut = function (event, dragTools) { + if (!dragTools.isDragging) { + return; + } + + event.preventDefault(); + dragTools.isDragging = false; +}; + +const mouseMove = function ( + event, + particlesHandler, + visibleParticles, + dragTools +) { + if (!dragTools.isDragging) { + return; + } + event.preventDefault(); + + const boundigClientRect = canvas.getBoundingClientRect(); + const mouseX = parseInt(event.clientX - boundigClientRect.x); + const mouseY = parseInt(event.clientY - boundigClientRect.y); + + const dx = mouseX - dragTools.prevMouseX; + const dy = mouseY - dragTools.prevMouseY; + + const infoBox = particlesHandler.infoBoxes[dragTools.draggedInfoBox]; + infoBox.x += dx; + infoBox.y += dy; + + // console.time("drawVisible"); + drawVisible(visibleParticles, particlesHandler); + // console.timeEnd("drawVisible"); + + dragTools.prevMouseX = mouseX; + dragTools.prevMouseY = mouseY; +}; + +const getVisible = function (particlesHandler, visibleParticles) { + const boundigClientRect = canvas.getBoundingClientRect(); + + const { infoBoxes, parentLinks, childrenLinks } = particlesHandler; + + let visibleBoxes = []; + let visibleParentLinks = []; + let visibleChildrenLinks = []; + + for (const box of infoBoxes) { + if ( + box.isVisible( + 0 - boundigClientRect.x, + 0 - boundigClientRect.y, + window.innerWidth, + window.innerHeight + ) + ) { + visibleBoxes.push(box.id); + } + } + + for (const boxId of visibleBoxes) { + for (const linkId of infoBoxes[boxId].parentLinks) { + visibleParentLinks.push(linkId); + } + for (const parentBoxId of infoBoxes[boxId].parents) { + for (const linkId of infoBoxes[parentBoxId].childrenLinks) { + visibleChildrenLinks.push(linkId); + } + } + } + for (const link of parentLinks) { + if ( + link.isVisible( + 0 - boundigClientRect.x, + 0 - boundigClientRect.y, + window.innerWidth, + window.innerHeight, + infoBoxes + ) + ) { + visibleParentLinks.push(link.id); + } + } + + for (const boxId of visibleBoxes) { + for (const linkId of infoBoxes[boxId].childrenLinks) { + visibleChildrenLinks.push(linkId); + } + for (const childrenBoxId of infoBoxes[boxId].children) { + for (const linkId of infoBoxes[childrenBoxId].parentLinks) { + visibleParentLinks.push(linkId); + } + } + } + for (const link of childrenLinks) { + if ( + link.isVisible( + 0 - boundigClientRect.x, + 0 - boundigClientRect.y, + window.innerWidth, + window.innerHeight, + infoBoxes + ) + ) { + visibleChildrenLinks.push(link.id); + } + } + + visibleParentLinks = [...new Set(visibleParentLinks)]; + visibleChildrenLinks = [...new Set(visibleChildrenLinks)]; + + /* + console.log("Visible boxes: ", visibleBoxes); + console.log("Visible parentLinks: ", visibleParentLinks); + console.log("Visible childrenLinks: ", visibleChildrenLinks); + */ + + visibleParticles.infoBoxes = visibleBoxes; + visibleParticles.parentLinks = visibleParentLinks; + visibleParticles.childrenLinks = visibleChildrenLinks; +}; + +const onScroll = function (particlesHandler, visibleParticles) { + getVisible(particlesHandler, visibleParticles); +}; + +export { mouseDown, mouseUp, mouseOut, mouseMove, getVisible, onScroll }; diff --git a/js/main.js b/js/main.js index 7a30b2ef..d2f5ab7e 100644 --- a/js/main.js +++ b/js/main.js @@ -2,6 +2,14 @@ import { errorMsg, loadMCParticles } from "./tools.js"; import { PdgToggle } from "./menu/show-pdg.js"; import { drawAll } from "./draw.js"; import { bits } from "./menu/filter/filter.js"; +import { + mouseDown, + mouseUp, + mouseOut, + mouseMove, + getVisible, + onScroll, +} from "./events.js"; const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); @@ -20,182 +28,43 @@ let jsonData = {}; const infoBoxes = []; const parentLinks = []; const childrenLinks = []; + +let currentInfoBoxes = []; +let currentParentLinks = []; +let currentChildrenLinks = []; + let visibleBoxes = []; let visibleParentLinks = []; let visibleChildrenLinks = []; -const mouseDown = function (event) { - event.preventDefault(); - - const boundigClientRect = canvas.getBoundingClientRect(); - const mouseX = parseInt(event.clientX - boundigClientRect.x); - const mouseY = parseInt(event.clientY - boundigClientRect.y); - - prevMouseX = mouseX; - prevMouseY = mouseY; - - for (let i = visibleBoxes.length - 1; i >= 0; i--) { - if (infoBoxes[visibleBoxes[i]].isHere(mouseX, mouseY)) { - draggedInfoBox = visibleBoxes[i]; - isDragging = true; - return; - } - } +const dragTools = { + draggedInfoBox: draggedInfoBox, + isDragging: isDragging, + prevMouseX: prevMouseX, + prevMouseY: prevMouseY, }; -const mouseUp = function (event) { - if (!isDragging) { - return; - } - - event.preventDefault(); - isDragging = false; - - // console.time("drawAll"); - drawAll(ctx, parentLinks, childrenLinks, infoBoxes); - // console.timeEnd("drawAll"); -}; - -const mouseOut = function (event) { - if (!isDragging) { - return; - } - - event.preventDefault(); - isDragging = false; +const particlesHandler = { + infoBoxes: infoBoxes, + parentLinks: parentLinks, + childrenLinks: childrenLinks, }; -const mouseMove = function (event) { - if (!isDragging) { - return; - } - event.preventDefault(); - - const boundigClientRect = canvas.getBoundingClientRect(); - const mouseX = parseInt(event.clientX - boundigClientRect.x); - const mouseY = parseInt(event.clientY - boundigClientRect.y); - - const dx = mouseX - prevMouseX; - const dy = mouseY - prevMouseY; - - const infoBox = infoBoxes[draggedInfoBox]; - infoBox.x += dx; - infoBox.y += dy; - - // console.time("drawVisible"); - drawVisible(visibleParentLinks, visibleChildrenLinks, visibleBoxes); - // console.timeEnd("drawVisible"); - - prevMouseX = mouseX; - prevMouseY = mouseY; +const currentParticles = { + infoBoxes: currentInfoBoxes, + parentLinks: currentParentLinks, + childrenLinks: currentChildrenLinks, }; -const onScroll = function () { - getVisible(); +const visibleParticles = { + infoBoxes: visibleBoxes, + parentLinks: visibleParentLinks, + childrenLinks: visibleChildrenLinks, }; -const getVisible = function () { - const boundigClientRect = canvas.getBoundingClientRect(); - - visibleBoxes = []; - visibleParentLinks = []; - visibleChildrenLinks = []; +function start(particlesHandler, visibleParticles) { + const { infoBoxes } = particlesHandler; - for (const box of infoBoxes) { - if ( - box.isVisible( - 0 - boundigClientRect.x, - 0 - boundigClientRect.y, - window.innerWidth, - window.innerHeight - ) - ) { - visibleBoxes.push(box.id); - } - } - - for (const boxId of visibleBoxes) { - for (const linkId of infoBoxes[boxId].parentLinks) { - visibleParentLinks.push(linkId); - } - for (const parentBoxId of infoBoxes[boxId].parents) { - for (const linkId of infoBoxes[parentBoxId].childrenLinks) { - visibleChildrenLinks.push(linkId); - } - } - } - for (const link of parentLinks) { - if ( - link.isVisible( - 0 - boundigClientRect.x, - 0 - boundigClientRect.y, - window.innerWidth, - window.innerHeight, - infoBoxes - ) - ) { - visibleParentLinks.push(link.id); - } - } - - for (const boxId of visibleBoxes) { - for (const linkId of infoBoxes[boxId].childrenLinks) { - visibleChildrenLinks.push(linkId); - } - for (const childrenBoxId of infoBoxes[boxId].children) { - for (const linkId of infoBoxes[childrenBoxId].parentLinks) { - visibleParentLinks.push(linkId); - } - } - } - for (const link of childrenLinks) { - if ( - link.isVisible( - 0 - boundigClientRect.x, - 0 - boundigClientRect.y, - window.innerWidth, - window.innerHeight, - infoBoxes - ) - ) { - visibleChildrenLinks.push(link.id); - } - } - - visibleParentLinks = [...new Set(visibleParentLinks)]; - visibleChildrenLinks = [...new Set(visibleChildrenLinks)]; - - /* - console.log("Visible boxes: ", visibleBoxes); - console.log("Visible parentLinks: ", visibleParentLinks); - console.log("Visible childrenLinks: ", visibleChildrenLinks); - */ -}; - -const drawVisible = function ( - visibleParentLinks, - visibleChildrenLinks, - visibleBoxes -) { - const boundigClientRect = canvas.getBoundingClientRect(); - ctx.clearRect( - 0 - boundigClientRect.x, - 0 - boundigClientRect.y, - window.innerWidth, - window.innerHeight - ); - for (const linkId of visibleParentLinks) { - parentLinks[linkId].draw(ctx, infoBoxes); - } - for (const linkId of visibleChildrenLinks) { - childrenLinks[linkId].draw(ctx, infoBoxes); - } - for (const boxId of visibleBoxes) { - infoBoxes[boxId].draw(ctx); - } -}; - -function start() { if (!infoBoxes) { return; } @@ -260,16 +129,26 @@ function start() { } } - drawAll(ctx, parentLinks, childrenLinks, infoBoxes); + drawAll(ctx, particlesHandler); - getVisible(); + getVisible(particlesHandler, visibleParticles); } -canvas.onmousedown = mouseDown; -canvas.onmouseup = mouseUp; -canvas.onmouseout = mouseOut; -canvas.onmousemove = mouseMove; -window.onscroll = onScroll; +canvas.onmousedown = (event) => { + mouseDown(event, particlesHandler, visibleParticles, dragTools); +}; +canvas.onmouseup = (event) => { + mouseUp(event, dragTools, particlesHandler); +}; +canvas.onmouseout = (event) => { + mouseOut(event, dragTools); +}; +canvas.onmousemove = (event) => { + mouseMove(event, particlesHandler, visibleParticles, dragTools); +}; +window.onscroll = () => { + onScroll(particlesHandler, visibleParticles); +}; /* function showInputModal() { @@ -314,6 +193,9 @@ document .addEventListener("click", (event) => { event.preventDefault(); const eventNum = document.getElementById("event-number").value; + + const { infoBoxes, parentLinks, childrenLinks } = particlesHandler; + loadMCParticles(jsonData, eventNum, infoBoxes, parentLinks, childrenLinks); if (infoBoxes.length === 0) { errorMsg("Provided file does not contain any MC particle tree!"); @@ -322,7 +204,7 @@ document for (const eventNum in jsonData) { delete jsonData[eventNum]; } - start(); + start(particlesHandler, visibleParticles); hideInputModal(); window.scroll((canvas.width - window.innerWidth) / 2, 0); @@ -337,9 +219,16 @@ document const pdgToggle = new PdgToggle("show-pdg"); pdgToggle.init(() => { pdgToggle.toggle(infoBoxes, () => { - drawAll(ctx, parentLinks, childrenLinks, infoBoxes); + drawAll(ctx, particlesHandler); }); }); }); -export { parentLinks, childrenLinks, infoBoxes, ctx }; +export { + canvas, + ctx, + dragTools, + visibleParticles, + particlesHandler, + currentParticles, +}; diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index 98e7fbbc..a7bb6007 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -1,5 +1,5 @@ import { drawAll } from "../../draw.js"; -import { parentLinks, childrenLinks, infoBoxes, ctx } from "../../main.js"; +import { ctx, particlesHandler } from "../../main.js"; import { Range, Checkbox, buildCriteriaFunction } from "./parameters.js"; import { reconnect } from "./reconnect.js"; @@ -53,6 +53,8 @@ apply.addEventListener("click", () => { checkboxFunctions ); + const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; + const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, parentLinks, @@ -60,11 +62,15 @@ apply.addEventListener("click", () => { infoBoxes ); - drawAll(ctx, newParentLinks, newChildrenLinks, filteredParticles); + drawAll(ctx, { + parentLinks: newParentLinks, + childrenLinks: newChildrenLinks, + infoBoxes: filteredParticles, + }); }); reset.addEventListener("click", () => { - drawAll(ctx, parentLinks, childrenLinks, infoBoxes); + drawAll(ctx, particlesHandler); filters.innerHTML = ""; From 9c643f22935a05701e046dcc8b28f3aa61797f87 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Sat, 1 Jun 2024 13:47:48 -0500 Subject: [PATCH 05/25] apply same technique for filters --- js/menu/filter/filter.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index a7bb6007..0253ca57 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -44,7 +44,7 @@ let bits = { render: () => bits.checkBoxes.forEach((checkbox) => checkbox.render(filters)), }; -apply.addEventListener("click", () => { +function applyFilter(particlesHandler) { const rangeFunctions = Range.buildFilter(parametersRange); const checkboxFunctions = Checkbox.buildFilter(bits.checkBoxes); @@ -67,9 +67,9 @@ apply.addEventListener("click", () => { childrenLinks: newChildrenLinks, infoBoxes: filteredParticles, }); -}); +} -reset.addEventListener("click", () => { +function removeFilter(particlesHandler) { drawAll(ctx, particlesHandler); filters.innerHTML = ""; @@ -84,6 +84,9 @@ reset.addEventListener("click", () => { checkbox.checked = false; checkbox.render(filters); }); -}); +} + +apply.addEventListener("click", () => applyFilter(particlesHandler)); +reset.addEventListener("click", () => removeFilter(particlesHandler)); export { bits }; From e67e6eb7b4ae032b1ab7a9a226028a6001412ae3 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Sat, 1 Jun 2024 20:10:15 -0500 Subject: [PATCH 06/25] [FIX] when filtering particles, these are maintained even if boxes are dragged --- js/draw.js | 14 ++++--- js/events.js | 50 +++++++------------------ js/main.js | 74 ++++++++++++++----------------------- js/menu/filter/filter.js | 46 +++++++++++++++-------- js/menu/filter/reconnect.js | 30 +++++++++------ js/objects.js | 9 ----- js/tools.js | 10 ++--- 7 files changed, 101 insertions(+), 132 deletions(-) diff --git a/js/draw.js b/js/draw.js index 40ce4818..6bfdd8ae 100644 --- a/js/draw.js +++ b/js/draw.js @@ -1,7 +1,7 @@ import { canvas, ctx } from "./main.js"; -export function drawAll(ctx, particlesHandler) { - const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; +export function drawAll(ctx, currentParticles) { + const { parentLinks, childrenLinks, infoBoxes } = currentParticles; ctx.clearRect(0, 0, canvas.width, canvas.height); // console.time("drawParentLinks"); @@ -21,14 +21,14 @@ export function drawAll(ctx, particlesHandler) { // console.timeEnd("drawBoxes"); } -export function drawVisible(visibleParticles, particlesHandler) { +export function drawVisible(currentParticles, visibleParticles) { const { infoBoxes: visibleBoxes, parentLinks: visibleParentLinks, childrenLinks: visibleChildrenLinks, } = visibleParticles; - const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; + const { parentLinks, childrenLinks, infoBoxes } = currentParticles; const boundigClientRect = canvas.getBoundingClientRect(); ctx.clearRect( @@ -38,10 +38,12 @@ export function drawVisible(visibleParticles, particlesHandler) { window.innerHeight ); for (const linkId of visibleParentLinks) { - parentLinks[linkId].draw(ctx, infoBoxes); + if (parentLinks[linkId] !== undefined) + parentLinks[linkId].draw(ctx, infoBoxes); } for (const linkId of visibleChildrenLinks) { - childrenLinks[linkId].draw(ctx, infoBoxes); + if (childrenLinks[linkId] !== undefined) + childrenLinks[linkId].draw(ctx, infoBoxes); } for (const boxId of visibleBoxes) { infoBoxes[boxId].draw(ctx); diff --git a/js/events.js b/js/events.js index d2de797f..193d71e9 100644 --- a/js/events.js +++ b/js/events.js @@ -3,7 +3,7 @@ import { drawAll, drawVisible } from "./draw.js"; const mouseDown = function ( event, - particlesHandler, + currentParticles, visibleParticles, dragTools ) { @@ -15,8 +15,8 @@ const mouseDown = function ( dragTools.prevMouseX = mouseX; dragTools.prevMouseY = mouseY; + const infoBoxes = currentParticles.infoBoxes; const visibleBoxes = visibleParticles.infoBoxes; - const infoBoxes = particlesHandler.infoBoxes; for (let i = visibleBoxes.length - 1; i >= 0; i--) { if (infoBoxes[visibleBoxes[i]].isHere(mouseX, mouseY)) { dragTools.draggedInfoBox = visibleBoxes[i]; @@ -26,7 +26,7 @@ const mouseDown = function ( } }; -const mouseUp = function (event, dragTools, particlesHandler) { +const mouseUp = function (event, particlesHandler, dragTools) { if (!dragTools.isDragging) { return; } @@ -50,7 +50,7 @@ const mouseOut = function (event, dragTools) { const mouseMove = function ( event, - particlesHandler, + currentParticles, visibleParticles, dragTools ) { @@ -66,28 +66,29 @@ const mouseMove = function ( const dx = mouseX - dragTools.prevMouseX; const dy = mouseY - dragTools.prevMouseY; - const infoBox = particlesHandler.infoBoxes[dragTools.draggedInfoBox]; + const infoBox = currentParticles.infoBoxes[dragTools.draggedInfoBox]; infoBox.x += dx; infoBox.y += dy; // console.time("drawVisible"); - drawVisible(visibleParticles, particlesHandler); + drawVisible(currentParticles, visibleParticles); // console.timeEnd("drawVisible"); dragTools.prevMouseX = mouseX; dragTools.prevMouseY = mouseY; }; -const getVisible = function (particlesHandler, visibleParticles) { +const getVisible = function (currentParticles, visibleParticles) { const boundigClientRect = canvas.getBoundingClientRect(); - const { infoBoxes, parentLinks, childrenLinks } = particlesHandler; + const { infoBoxes, parentLinks, childrenLinks } = currentParticles; - let visibleBoxes = []; - let visibleParentLinks = []; - let visibleChildrenLinks = []; + const visibleBoxes = []; + const visibleParentLinks = []; + const visibleChildrenLinks = []; for (const box of infoBoxes) { + if (box === null) continue; if ( box.isVisible( 0 - boundigClientRect.x, @@ -100,16 +101,6 @@ const getVisible = function (particlesHandler, visibleParticles) { } } - for (const boxId of visibleBoxes) { - for (const linkId of infoBoxes[boxId].parentLinks) { - visibleParentLinks.push(linkId); - } - for (const parentBoxId of infoBoxes[boxId].parents) { - for (const linkId of infoBoxes[parentBoxId].childrenLinks) { - visibleChildrenLinks.push(linkId); - } - } - } for (const link of parentLinks) { if ( link.isVisible( @@ -124,16 +115,6 @@ const getVisible = function (particlesHandler, visibleParticles) { } } - for (const boxId of visibleBoxes) { - for (const linkId of infoBoxes[boxId].childrenLinks) { - visibleChildrenLinks.push(linkId); - } - for (const childrenBoxId of infoBoxes[boxId].children) { - for (const linkId of infoBoxes[childrenBoxId].parentLinks) { - visibleParentLinks.push(linkId); - } - } - } for (const link of childrenLinks) { if ( link.isVisible( @@ -148,9 +129,6 @@ const getVisible = function (particlesHandler, visibleParticles) { } } - visibleParentLinks = [...new Set(visibleParentLinks)]; - visibleChildrenLinks = [...new Set(visibleChildrenLinks)]; - /* console.log("Visible boxes: ", visibleBoxes); console.log("Visible parentLinks: ", visibleParentLinks); @@ -162,8 +140,8 @@ const getVisible = function (particlesHandler, visibleParticles) { visibleParticles.childrenLinks = visibleChildrenLinks; }; -const onScroll = function (particlesHandler, visibleParticles) { - getVisible(particlesHandler, visibleParticles); +const onScroll = function (currentParticles, visibleParticles) { + getVisible(currentParticles, visibleParticles); }; export { mouseDown, mouseUp, mouseOut, mouseMove, getVisible, onScroll }; diff --git a/js/main.js b/js/main.js index d2f5ab7e..adcabe69 100644 --- a/js/main.js +++ b/js/main.js @@ -19,47 +19,31 @@ const manipulationTools = document.getElementsByClassName("manipulation-tool"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; -let draggedInfoBox = -1; -let isDragging = false; -let prevMouseX = 0; -let prevMouseY = 0; - let jsonData = {}; -const infoBoxes = []; -const parentLinks = []; -const childrenLinks = []; - -let currentInfoBoxes = []; -let currentParentLinks = []; -let currentChildrenLinks = []; - -let visibleBoxes = []; -let visibleParentLinks = []; -let visibleChildrenLinks = []; const dragTools = { - draggedInfoBox: draggedInfoBox, - isDragging: isDragging, - prevMouseX: prevMouseX, - prevMouseY: prevMouseY, + draggedInfoBox: -1, + isDragging: false, + prevMouseX: 0, + prevMouseY: 0, }; const particlesHandler = { - infoBoxes: infoBoxes, - parentLinks: parentLinks, - childrenLinks: childrenLinks, + infoBoxes: [], + parentLinks: [], + childrenLinks: [], }; const currentParticles = { - infoBoxes: currentInfoBoxes, - parentLinks: currentParentLinks, - childrenLinks: currentChildrenLinks, + infoBoxes: [], + parentLinks: [], + childrenLinks: [], }; const visibleParticles = { - infoBoxes: visibleBoxes, - parentLinks: visibleParentLinks, - childrenLinks: visibleChildrenLinks, + infoBoxes: [], + parentLinks: [], + childrenLinks: [], }; function start(particlesHandler, visibleParticles) { @@ -135,19 +119,19 @@ function start(particlesHandler, visibleParticles) { } canvas.onmousedown = (event) => { - mouseDown(event, particlesHandler, visibleParticles, dragTools); + mouseDown(event, currentParticles, visibleParticles, dragTools); }; canvas.onmouseup = (event) => { - mouseUp(event, dragTools, particlesHandler); + mouseUp(event, currentParticles, dragTools); }; canvas.onmouseout = (event) => { mouseOut(event, dragTools); }; canvas.onmousemove = (event) => { - mouseMove(event, particlesHandler, visibleParticles, dragTools); + mouseMove(event, currentParticles, visibleParticles, dragTools); }; window.onscroll = () => { - onScroll(particlesHandler, visibleParticles); + onScroll(currentParticles, visibleParticles); }; /* @@ -194,17 +178,20 @@ document event.preventDefault(); const eventNum = document.getElementById("event-number").value; - const { infoBoxes, parentLinks, childrenLinks } = particlesHandler; + loadMCParticles(jsonData, eventNum, particlesHandler); - loadMCParticles(jsonData, eventNum, infoBoxes, parentLinks, childrenLinks); - if (infoBoxes.length === 0) { + currentParticles.infoBoxes = particlesHandler.infoBoxes; + currentParticles.parentLinks = particlesHandler.parentLinks; + currentParticles.childrenLinks = particlesHandler.childrenLinks; + + if (particlesHandler.infoBoxes.length === 0) { errorMsg("Provided file does not contain any MC particle tree!"); return; } for (const eventNum in jsonData) { delete jsonData[eventNum]; } - start(particlesHandler, visibleParticles); + start(currentParticles, visibleParticles); hideInputModal(); window.scroll((canvas.width - window.innerWidth) / 2, 0); @@ -212,6 +199,8 @@ document tool.style.display = "flex"; } + const { infoBoxes } = currentParticles; + infoBoxes.forEach((infoBox) => bits.add(infoBox.simStatus)); bits.setCheckBoxes(); bits.render(); @@ -219,16 +208,9 @@ document const pdgToggle = new PdgToggle("show-pdg"); pdgToggle.init(() => { pdgToggle.toggle(infoBoxes, () => { - drawAll(ctx, particlesHandler); + drawAll(ctx, currentParticles); }); }); }); -export { - canvas, - ctx, - dragTools, - visibleParticles, - particlesHandler, - currentParticles, -}; +export { canvas, ctx, visibleParticles, particlesHandler, currentParticles }; diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index 0253ca57..e7149c0c 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -1,7 +1,13 @@ import { drawAll } from "../../draw.js"; -import { ctx, particlesHandler } from "../../main.js"; +import { + ctx, + particlesHandler, + currentParticles, + visibleParticles, +} from "../../main.js"; import { Range, Checkbox, buildCriteriaFunction } from "./parameters.js"; import { reconnect } from "./reconnect.js"; +import { getVisible } from "../../events.js"; const filterButton = document.getElementById("filter-button"); const openFilter = document.getElementById("open-filter"); @@ -44,7 +50,7 @@ let bits = { render: () => bits.checkBoxes.forEach((checkbox) => checkbox.render(filters)), }; -function applyFilter(particlesHandler) { +function applyFilter(particlesHandler, currentParticles, visibleParticles) { const rangeFunctions = Range.buildFilter(parametersRange); const checkboxFunctions = Checkbox.buildFilter(bits.checkBoxes); @@ -53,24 +59,28 @@ function applyFilter(particlesHandler) { checkboxFunctions ); - const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; - const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - infoBoxes + particlesHandler ); - drawAll(ctx, { - parentLinks: newParentLinks, - childrenLinks: newChildrenLinks, - infoBoxes: filteredParticles, - }); + currentParticles.parentLinks = newParentLinks; + currentParticles.childrenLinks = newChildrenLinks; + currentParticles.infoBoxes = filteredParticles; + + drawAll(ctx, currentParticles); + + getVisible(currentParticles, visibleParticles); } -function removeFilter(particlesHandler) { - drawAll(ctx, particlesHandler); +function removeFilter(particlesHandler, currentParticles, visibleParticles) { + currentParticles.parentLinks = particlesHandler.parentLinks; + currentParticles.childrenLinks = particlesHandler.childrenLinks; + currentParticles.infoBoxes = particlesHandler.infoBoxes; + + drawAll(ctx, currentParticles); + + getVisible(currentParticles, visibleParticles); filters.innerHTML = ""; @@ -86,7 +96,11 @@ function removeFilter(particlesHandler) { }); } -apply.addEventListener("click", () => applyFilter(particlesHandler)); -reset.addEventListener("click", () => removeFilter(particlesHandler)); +apply.addEventListener("click", () => + applyFilter(particlesHandler, currentParticles, visibleParticles) +); +reset.addEventListener("click", () => + removeFilter(particlesHandler, currentParticles, visibleParticles) +); export { bits }; diff --git a/js/menu/filter/reconnect.js b/js/menu/filter/reconnect.js index 97f6c35e..54cc71f0 100644 --- a/js/menu/filter/reconnect.js +++ b/js/menu/filter/reconnect.js @@ -1,18 +1,13 @@ import { Link } from "../../objects.js"; -export function reconnect( - criteriaFunction, - parentLinks, - childrenLinks, - particles -) { +export function reconnect(criteriaFunction, particlesHandler) { + const { parentLinks, childrenLinks, infoBoxes: particles } = particlesHandler; + const newParentLinks = []; const newChildrenLinks = []; const filteredParticles = []; for (const particle of particles) { - if (!particle) continue; - if (!criteriaFunction(particle)) { filteredParticles.push(null); @@ -48,19 +43,30 @@ export function reconnect( for (const parentLinkId of particle.parentLinks) { const parentLink = parentLinks[parentLinkId]; - if (!parentLink) continue; const parent = particles[parentLink.from]; if (criteriaFunction(parent)) { - newParentLinks.push(parentLink); + const parentLinkCopy = new Link( + newParentLinks.length, + parentLink.from, + parentLink.to + ); + parentLinkCopy.xShift = 3; + newParentLinks.push(parentLinkCopy); } } for (const childrenLinkId of particle.childrenLinks) { const childrenLink = childrenLinks[childrenLinkId]; - if (!childrenLink) continue; const child = particles[childrenLink.to]; if (criteriaFunction(child)) { - newChildrenLinks.push(childrenLink); + const childrenLinkCopy = new Link( + newChildrenLinks.length, + childrenLink.from, + childrenLink.to + ); + childrenLinkCopy.color = "#0A0"; + childrenLinkCopy.xShift = -3; + newChildrenLinks.push(childrenLinkCopy); } } } diff --git a/js/objects.js b/js/objects.js index c9bef14e..7249e2b9 100644 --- a/js/objects.js +++ b/js/objects.js @@ -159,15 +159,6 @@ export class Link { const boxFrom = infoBoxes[this.from]; const boxTo = infoBoxes[this.to]; - if ( - boxFrom === null || - boxTo === null || - boxFrom === undefined || - boxTo === undefined - ) { - return; - } - const fromX = boxFrom.x + boxFrom.width / 2; const fromY = boxFrom.y + boxFrom.height; const toX = boxTo.x + boxTo.width / 2; diff --git a/js/tools.js b/js/tools.js index 99e40a3a..680e3dc9 100644 --- a/js/tools.js +++ b/js/tools.js @@ -15,13 +15,9 @@ export function errorMsg(msg) { msgDiv.innerHTML = "

ERROR: " + msg + "

"; } -export function loadMCParticles( - jsonData, - eventNum, - infoBoxes, - parentLinks, - childrenLinks -) { +export function loadMCParticles(jsonData, eventNum, particlesHandler) { + const { infoBoxes, parentLinks, childrenLinks } = particlesHandler; + const eventData = jsonData["Event " + eventNum]; try { const mcParticles = Object.values(eventData).find( From 489bf69cc2381eb51ad42c912d364117b14cb596 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Sat, 1 Jun 2024 20:29:41 -0500 Subject: [PATCH 07/25] [FIX] update test based on new filtering logic (new id's for links) --- js/menu/filter/reconnect.js | 12 +++--- test/filter.test.js | 78 +++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/js/menu/filter/reconnect.js b/js/menu/filter/reconnect.js index 54cc71f0..c60b2f1f 100644 --- a/js/menu/filter/reconnect.js +++ b/js/menu/filter/reconnect.js @@ -1,13 +1,13 @@ import { Link } from "../../objects.js"; export function reconnect(criteriaFunction, particlesHandler) { - const { parentLinks, childrenLinks, infoBoxes: particles } = particlesHandler; + const { parentLinks, childrenLinks, infoBoxes } = particlesHandler; const newParentLinks = []; const newChildrenLinks = []; const filteredParticles = []; - for (const particle of particles) { + for (const particle of infoBoxes) { if (!criteriaFunction(particle)) { filteredParticles.push(null); @@ -15,13 +15,13 @@ export function reconnect(criteriaFunction, particlesHandler) { const childrenParticles = []; for (const parent of particle.parents) { - if (criteriaFunction(particles[parent])) { + if (criteriaFunction(infoBoxes[parent])) { parentParticles.push(parent); } } for (const child of particle.children) { - if (criteriaFunction(particles[child])) { + if (criteriaFunction(infoBoxes[child])) { childrenParticles.push(child); } } @@ -43,7 +43,7 @@ export function reconnect(criteriaFunction, particlesHandler) { for (const parentLinkId of particle.parentLinks) { const parentLink = parentLinks[parentLinkId]; - const parent = particles[parentLink.from]; + const parent = infoBoxes[parentLink.from]; if (criteriaFunction(parent)) { const parentLinkCopy = new Link( newParentLinks.length, @@ -57,7 +57,7 @@ export function reconnect(criteriaFunction, particlesHandler) { for (const childrenLinkId of particle.childrenLinks) { const childrenLink = childrenLinks[childrenLinkId]; - const child = particles[childrenLink.to]; + const child = infoBoxes[childrenLink.to]; if (criteriaFunction(child)) { const childrenLinkCopy = new Link( newChildrenLinks.length, diff --git a/test/filter.test.js b/test/filter.test.js index 01e08c5f..04981236 100644 --- a/test/filter.test.js +++ b/test/filter.test.js @@ -8,7 +8,7 @@ import { const parentLinks = []; const childrenLinks = []; -const particles = []; +const infoBoxes = []; beforeAll(() => { for (let i = 0; i < 5; i++) { @@ -17,7 +17,7 @@ beforeAll(() => { particle.charge = i; particle.mass = i * 10; particle.simStatus = i + 23; - particles.push(particle); + infoBoxes.push(particle); } parentLinks.push(new Link(0, 0, 1)); @@ -32,28 +32,34 @@ beforeAll(() => { childrenLinks.push(new Link(3, 2, 4)); childrenLinks.push(new Link(4, 3, 4)); - particles[0].children = [1, 2]; - particles[0].childrenLinks = [0, 1]; + infoBoxes[0].children = [1, 2]; + infoBoxes[0].childrenLinks = [0, 1]; - particles[1].parents = [0]; - particles[1].children = [3]; - particles[1].parentLinks = [0]; - particles[1].childrenLinks = [2]; + infoBoxes[1].parents = [0]; + infoBoxes[1].children = [3]; + infoBoxes[1].parentLinks = [0]; + infoBoxes[1].childrenLinks = [2]; - particles[2].parents = [0]; - particles[2].children = [4]; - particles[2].parentLinks = [1]; - particles[2].childrenLinks = [3]; + infoBoxes[2].parents = [0]; + infoBoxes[2].children = [4]; + infoBoxes[2].parentLinks = [1]; + infoBoxes[2].childrenLinks = [3]; - particles[3].parents = [1]; - particles[3].children = [4]; - particles[3].parentLinks = [3]; - particles[3].childrenLinks = [4]; + infoBoxes[3].parents = [1]; + infoBoxes[3].children = [4]; + infoBoxes[3].parentLinks = [3]; + infoBoxes[3].childrenLinks = [4]; - particles[4].parents = [2, 3]; - particles[4].parentLinks = [2, 4]; + infoBoxes[4].parents = [2, 3]; + infoBoxes[4].parentLinks = [2, 4]; }); +const particlesHandler = { + parentLinks, + childrenLinks, + infoBoxes, +}; + describe("filter by ranges", () => { it("filter by a single range parameter", () => { const momentum = new Range("momentum"); @@ -64,13 +70,11 @@ describe("filter by ranges", () => { const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - particles + particlesHandler ); - expect(newChildrenLinks.map((link) => link.id)).toEqual([4]); - expect(newParentLinks.map((link) => link.id)).toEqual([4]); + expect(newChildrenLinks.map((link) => link.id)).toEqual([0]); + expect(newParentLinks.map((link) => link.id)).toEqual([0]); expect( filteredParticles.filter((p) => p).map((particle) => particle.id) ).toEqual([3, 4]); @@ -87,13 +91,11 @@ describe("filter by ranges", () => { const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - particles + particlesHandler ); - expect(newChildrenLinks.map((link) => link.id)).toEqual([4]); - expect(newParentLinks.map((link) => link.id)).toEqual([4]); + expect(newChildrenLinks.map((link) => link.id)).toEqual([0]); + expect(newParentLinks.map((link) => link.id)).toEqual([0]); expect( filteredParticles.filter((p) => p).map((particle) => particle.id) ).toEqual([3, 4]); @@ -109,9 +111,7 @@ describe("filter by checkboxes", () => { const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - particles + particlesHandler ); expect(newChildrenLinks.map((link) => link.id)).toEqual([]); @@ -137,13 +137,11 @@ describe("filter by checkboxes", () => { const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - particles + particlesHandler ); - expect(newChildrenLinks.map((link) => link.id)).toEqual([0, 1, 4]); - expect(newParentLinks.map((link) => link.id)).toEqual([0, 1, 4]); + expect(newChildrenLinks.map((link) => link.id)).toEqual([0, 1, 2]); + expect(newParentLinks.map((link) => link.id)).toEqual([0, 1, 2]); expect( filteredParticles.filter((p) => p).map((particle) => particle.id) ).toEqual([0, 3, 4]); @@ -163,9 +161,7 @@ describe("filter by ranges and checkboxes", () => { const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - particles + particlesHandler ); expect(newParentLinks.map((link) => link.id).sort()).toEqual([ @@ -193,9 +189,7 @@ describe("filter by ranges and checkboxes", () => { const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( criteriaFunction, - parentLinks, - childrenLinks, - particles + particlesHandler ); expect(newChildrenLinks.map((link) => link.id)).toEqual([]); From 67bfb6d8d444d759a8817c6a436c7d4f778ad190 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Mon, 3 Jun 2024 15:14:21 -0500 Subject: [PATCH 08/25] create filter for generator status --- js/main.js | 9 +++++++-- js/menu/filter/filter.js | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/js/main.js b/js/main.js index adcabe69..25aca284 100644 --- a/js/main.js +++ b/js/main.js @@ -1,7 +1,7 @@ import { errorMsg, loadMCParticles } from "./tools.js"; import { PdgToggle } from "./menu/show-pdg.js"; import { drawAll } from "./draw.js"; -import { bits } from "./menu/filter/filter.js"; +import { bits, genStatus } from "./menu/filter/filter.js"; import { mouseDown, mouseUp, @@ -201,9 +201,14 @@ document const { infoBoxes } = currentParticles; - infoBoxes.forEach((infoBox) => bits.add(infoBox.simStatus)); + infoBoxes.forEach((infoBox) => { + bits.add(infoBox.simStatus); + genStatus.add(infoBox.genStatus); + }); bits.setCheckBoxes(); + genStatus.setCheckBoxes(); bits.render(); + genStatus.render(); const pdgToggle = new PdgToggle("show-pdg"); pdgToggle.init(() => { diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index e7149c0c..d2821893 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -40,23 +40,40 @@ parametersRange = parametersRange.map((parameter) => new Range(parameter)); parametersRange.forEach((parameter) => parameter.render(filters)); -let bits = { - simStatuses: new Set(), - add: (simStatus) => bits.simStatuses.add(simStatus), - checkBoxes: [], - toCheckBox: () => - Array.from(bits.simStatuses).map((bit) => new Checkbox("simStatus", bit)), - setCheckBoxes: () => (bits.checkBoxes = bits.toCheckBox()), - render: () => bits.checkBoxes.forEach((checkbox) => checkbox.render(filters)), -}; +class CheckboxBuilder { + constructor(name) { + this.uniqueValues = new Set(); + this.checkBoxes = []; + this.name = name; + } + + add(val) { + this.uniqueValues.add(val); + } + + setCheckBoxes() { + this.checkBoxes = Array.from(this.uniqueValues).map( + (option) => new Checkbox(this.name, option) + ); + } + + render() { + this.checkBoxes.forEach((checkbox) => checkbox.render(filters)); + } +} + +const bits = new CheckboxBuilder("simStatus"); +const genStatus = new CheckboxBuilder("genStatus"); function applyFilter(particlesHandler, currentParticles, visibleParticles) { const rangeFunctions = Range.buildFilter(parametersRange); const checkboxFunctions = Checkbox.buildFilter(bits.checkBoxes); + const genStatusFunctions = Checkbox.buildFilter(genStatus.checkBoxes); const criteriaFunction = buildCriteriaFunction( rangeFunctions, - checkboxFunctions + checkboxFunctions, + genStatusFunctions ); const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect( @@ -103,4 +120,4 @@ reset.addEventListener("click", () => removeFilter(particlesHandler, currentParticles, visibleParticles) ); -export { bits }; +export { bits, genStatus }; From 5c6833a67a1e44136d484deada5cf0371477206a Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Mon, 3 Jun 2024 15:24:23 -0500 Subject: [PATCH 09/25] add units to range parameters --- js/menu/filter/filter.js | 27 ++++++++++++++++++++++++++- js/menu/filter/parameters.js | 5 +++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index d2821893..2178bc51 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -34,7 +34,32 @@ const filters = document.getElementById("filters"); const apply = document.getElementById("filter-apply"); const reset = document.getElementById("filter-reset"); -let parametersRange = ["momentum", "vertex", "time", "mass", "charge"]; +let parametersRange = [ + { + property: "momentum", + unit: "GeV", + }, + { + property: "mass", + unit: "GeV", + }, + { + property: "charge", + unit: "e", + }, + { + property: "vertex", + unit: "mm", + }, + { + property: "time", + unit: "ns", + }, +]; + +parametersRange = parametersRange.sort((a, b) => + a.property.localeCompare(b.property) +); parametersRange = parametersRange.map((parameter) => new Range(parameter)); diff --git a/js/menu/filter/parameters.js b/js/menu/filter/parameters.js index 76b52e37..60f4a4f5 100644 --- a/js/menu/filter/parameters.js +++ b/js/menu/filter/parameters.js @@ -29,14 +29,15 @@ export class Range extends FilterParameter { min; max; - constructor(property) { + constructor({ property, unit }) { super(property); + this.unit = unit; } render(container) { const title = document.createElement("div"); const label = document.createElement("label"); - label.textContent = this.property; + label.textContent = `${this.property} (${this.unit})`; title.appendChild(label); const content = document.createElement("div"); From 1eed533f5898c6afc39c97797e013422c743ebe4 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Mon, 3 Jun 2024 15:30:38 -0500 Subject: [PATCH 10/25] update filters for ranges to require an object --- test/filter.test.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/test/filter.test.js b/test/filter.test.js index 04981236..a4046fc3 100644 --- a/test/filter.test.js +++ b/test/filter.test.js @@ -62,7 +62,10 @@ const particlesHandler = { describe("filter by ranges", () => { it("filter by a single range parameter", () => { - const momentum = new Range("momentum"); + const momentum = new Range({ + property: "momentum", + unit: "GeV", + }); momentum.min = 300; momentum.max = 1000; const rangeFilters = Range.buildFilter([momentum]); @@ -81,9 +84,15 @@ describe("filter by ranges", () => { }); it("filter by a combination of ranges", () => { - const charge = new Range("charge"); + const charge = new Range({ + property: "charge", + unit: "e", + }); charge.min = 3; - const mass = new Range("mass"); + const mass = new Range({ + property: "mass", + unit: "GeV", + }); mass.min = 20; mass.max = 40; const rangeFilters = Range.buildFilter([mass, charge]); @@ -150,7 +159,10 @@ describe("filter by checkboxes", () => { describe("filter by ranges and checkboxes", () => { it("show all particles when no kind of filter is applied", () => { - const charge = new Range("charge"); + const charge = new Range({ + property: "charge", + unit: "e", + }); const simulatorStatus = new Checkbox("simStatus", 26); const rangeFilters = Range.buildFilter([charge]); const checkboxFilters = Checkbox.buildFilter([simulatorStatus]); @@ -176,7 +188,10 @@ describe("filter by ranges and checkboxes", () => { }); it("filter by a combination of ranges and checkboxes", () => { - const charge = new Range("charge"); + const charge = new Range({ + property: "charge", + unit: "e", + }); charge.max = 3; const simulatorStatus = new Checkbox("simStatus", 23); simulatorStatus.checked = true; From 83580b743586c78f76a0b1ebc81f90709816d556 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Tue, 4 Jun 2024 15:04:23 -0500 Subject: [PATCH 11/25] trigger filter when enter key is pressed --- js/menu/filter/filter.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/js/menu/filter/filter.js b/js/menu/filter/filter.js index 2178bc51..eca13c42 100644 --- a/js/menu/filter/filter.js +++ b/js/menu/filter/filter.js @@ -141,6 +141,13 @@ function removeFilter(particlesHandler, currentParticles, visibleParticles) { apply.addEventListener("click", () => applyFilter(particlesHandler, currentParticles, visibleParticles) ); + +document.addEventListener("keydown", (event) => { + if (event.key === "Enter" && active) { + applyFilter(particlesHandler, currentParticles, visibleParticles); + } +}); + reset.addEventListener("click", () => removeFilter(particlesHandler, currentParticles, visibleParticles) ); From d3be20b955b2c91d704a496506db4f6d5a7cccd8 Mon Sep 17 00:00:00 2001 From: Braulio Rivas Abad Date: Tue, 4 Jun 2024 15:05:04 -0500 Subject: [PATCH 12/25] remove exclamation mark --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 450c5126..b320acd8 100644 --- a/index.html +++ b/index.html @@ -17,9 +17,9 @@