diff --git a/js/views/oneToMany.js b/js/views/oneToMany.js deleted file mode 100644 index 07cd179e..00000000 --- a/js/views/oneToMany.js +++ /dev/null @@ -1,71 +0,0 @@ -import { canvas } from "../main.js"; - -// One to Many relation between two collections -export function oneToManyView( - viewCurrentObjects, - fromCollectionName, - toCollectionName, - relationName -) { - const fromCollection = - viewCurrentObjects.datatypes[fromCollectionName].collection; - - const toCollection = - viewCurrentObjects.datatypes[toCollectionName].collection; - - if (fromCollection.length === 0 || toCollection.length === 0) { - alert("No association found!"); - return; - } - - const fromWidth = fromCollection[0].width; - const fromHeight = fromCollection[0].height; - const fromVerticalGap = 0.3 * fromHeight; - const fromHorizontalGap = 0.3 * fromWidth; - - const toWidth = toCollection[0].width; - const toHeight = toCollection[0].height; - const toVerticalGap = 0.3 * toHeight; - const toHorizontalGap = 0.3 * toWidth; - - const gap = 2 * (fromWidth + toWidth); - const totalWidth = gap + fromWidth + toWidth; - - const fromTotalHeight = - fromCollection.length * (fromHeight + fromVerticalGap) + fromVerticalGap; - - const toTotalHeight = - toCollection.length * (toHeight + toVerticalGap) + toVerticalGap; - - canvas.height = - fromTotalHeight > toTotalHeight ? fromTotalHeight : toTotalHeight; - - canvas.width = - totalWidth > window.innerWidth ? totalWidth : window.innerWidth; - - const width = canvas.width; - - const fromX = width / 2 - fromWidth - fromHorizontalGap; - const toX = width / 2 + toHorizontalGap; - - let toCount = 0; - - fromCollection.forEach((fromObject) => { - const objectRelations = fromObject.oneToManyRelations[relationName]; - const length = objectRelations.length; - - objectRelations.forEach((relation) => { - const toObject = relation.to; - - toObject.x = toX; - toObject.y = toVerticalGap + toCount * (toHeight + toVerticalGap); - toCount++; - }); - - fromObject.x = fromX; - const firstY = objectRelations[0].to.y; - const lastY = objectRelations[length - 1].to.y; - - fromObject.y = parseInt((firstY + lastY) / 2); - }); -} diff --git a/js/views/pre-filter.js b/js/views/pre-filter.js index af2a4fd1..8334ee6b 100644 --- a/js/views/pre-filter.js +++ b/js/views/pre-filter.js @@ -37,24 +37,3 @@ export function preFilterTree( currentObjects.datatypes[collectionName].oneToMany[relationName]; }); } - -export function preFilterOneToMany( - currentObjects, - viewObjects, - fromCollectionName, - toCollectionName, - relationName -) { - emptyCopyObject(currentObjects, viewObjects); - - const relations = - currentObjects.datatypes[fromCollectionName].oneToMany[relationName]; - - viewObjects.datatypes[fromCollectionName].oneToMany[relationName] = relations; - - const fromCollection = relations.map((relation) => relation.from); - const toCollection = relations.map((relation) => relation.to); - - viewObjects.datatypes[fromCollectionName].collection = fromCollection; - viewObjects.datatypes[toCollectionName].collection = toCollection; -} diff --git a/js/views/recocluster.js b/js/views/recocluster.js deleted file mode 100644 index 72b92e17..00000000 --- a/js/views/recocluster.js +++ /dev/null @@ -1,21 +0,0 @@ -import { preFilterOneToMany } from "./pre-filter.js"; -import { oneToManyView } from "./oneToMany.js"; - -export function recoClusterView(viewCurrentObjects) { - oneToManyView( - viewCurrentObjects, - "edm4hep::ReconstructedParticle", - "edm4hep::Cluster", - "clusters" - ); -} - -export function preFilterRecoCluster(currentObjects, viewObjects) { - preFilterOneToMany( - currentObjects, - viewObjects, - "edm4hep::ReconstructedParticle", - "edm4hep::Cluster", - "clusters" - ); -} diff --git a/js/views/recoclustertrack.js b/js/views/recoclustertrack.js new file mode 100644 index 00000000..1ecee9fd --- /dev/null +++ b/js/views/recoclustertrack.js @@ -0,0 +1,154 @@ +import { canvas } from "../main.js"; +import { emptyCopyObject } from "../lib/copy.js"; + +export function recoClusterTrack(viewObjects) { + const recoParticles = + viewObjects.datatypes["edm4hep::ReconstructedParticle"].collection; + + if (recoParticles.length === 0) { + alert("No reconstructed particles found!"); + return; + } + + const findFirstObject = (relationName) => { + const object = recoParticles.find((particle) => { + const relation = particle.oneToManyRelations[relationName]; + if (relation.length > 0) { + return relation[0].to; + } + }); + return object; + }; + + const firstRecoParticle = recoParticles[0]; + const recoHeight = firstRecoParticle.height; + const recoVerticalGap = parseInt(recoHeight * 0.3); + const recoVerticalSpace = recoHeight + recoVerticalGap; + const recoHalfHeight = parseInt(recoHeight / 2); + const recoWidth = firstRecoParticle.width; + const recoHorizontalGap = recoWidth * 0.3; + + const firstCluster = findFirstObject("clusters"); + const clusterHeight = firstCluster.height; + const clusterVerticalGap = clusterHeight * 0.3; + const clusterWidth = firstCluster.width; + const firstTrack = findFirstObject("tracks"); + const trackHeight = firstTrack.height; + const trackVerticalGap = trackHeight * 0.3; + const trackWidth = firstTrack.width; + + const widestObject = Math.max(clusterWidth, trackWidth); + const widestGap = widestObject * 0.3; + + const totalHorizontalGap = + 2 * recoHorizontalGap + recoWidth + widestObject + 2 * widestGap; + + const width = + totalHorizontalGap > window.innerWidth + ? totalHorizontalGap + : window.innerWidth; + + canvas.width = width; + + const recoX = width / 2 - recoWidth; + + const otherX = width / 2 + widestGap; + + let totalHeight = 0; + + recoParticles.forEach((particle) => { + const clusterRelations = particle.oneToManyRelations["clusters"]; + const trackRelations = particle.oneToManyRelations["tracks"]; + + const relationsHeight = parseInt( + clusterRelations.length * (clusterHeight + clusterVerticalGap) + + trackRelations.length * (trackHeight + trackVerticalGap) + ); + + const height = + recoVerticalSpace > relationsHeight ? recoVerticalSpace : relationsHeight; + + const recoY = totalHeight + height / 2 - recoHalfHeight; + particle.y = recoY; + particle.x = recoX; + + const initialGap = (height - relationsHeight) / 2; + + let accumulatedRelationsHeight = initialGap + totalHeight; + + clusterRelations.forEach((clusterRelation) => { + const cluster = clusterRelation.to; + cluster.x = otherX; + + const y = clusterVerticalGap / 2 + accumulatedRelationsHeight; + cluster.y = y; + accumulatedRelationsHeight += clusterHeight + clusterVerticalGap / 2; + }); + + trackRelations.forEach((trackRelation) => { + const track = trackRelation.to; + track.x = otherX; + + const y = trackVerticalGap / 2 + accumulatedRelationsHeight; + track.y = y; + accumulatedRelationsHeight += trackHeight + trackVerticalGap / 2; + }); + + totalHeight += height; + }); + + canvas.height = totalHeight; +} + +export function preFilterRecoClusterTrack(currentObjects, viewObjects) { + emptyCopyObject(currentObjects, viewObjects); + + const fromDatatype = + currentObjects.datatypes["edm4hep::ReconstructedParticle"]; + + const fromCollection = fromDatatype.collection; + + const recoParticles = []; + const clusters = []; + const tracks = []; + + fromCollection.forEach((particle) => { + const clusterRelations = particle.oneToManyRelations["clusters"]; + const trackRelations = particle.oneToManyRelations["tracks"]; + + const total = clusterRelations.length + trackRelations.length; + + if (total === 0) { + return; + } + + clusterRelations.forEach((clusterRelation) => { + const cluster = clusterRelation.to; + clusters.push(cluster); + }); + + trackRelations.forEach((trackRelation) => { + const track = trackRelation.to; + tracks.push(track); + }); + + recoParticles.push(particle); + }); + + viewObjects.datatypes["edm4hep::ReconstructedParticle"].collection = + recoParticles; + viewObjects.datatypes["edm4hep::ReconstructedParticle"].oneToMany[ + "clusters" + ] = + currentObjects.datatypes["edm4hep::ReconstructedParticle"].oneToMany[ + "clusters" + ]; + viewObjects.datatypes["edm4hep::ReconstructedParticle"].oneToMany["tracks"] = + currentObjects.datatypes["edm4hep::ReconstructedParticle"].oneToMany[ + "tracks" + ]; + + viewObjects.datatypes["edm4hep::Cluster"].collection = clusters; + + viewObjects.datatypes["edm4hep::Track"].collection = tracks; +} diff --git a/js/views/recotrack.js b/js/views/recotrack.js deleted file mode 100644 index 39b1793a..00000000 --- a/js/views/recotrack.js +++ /dev/null @@ -1,21 +0,0 @@ -import { preFilterOneToMany } from "./pre-filter.js"; -import { oneToManyView } from "./oneToMany.js"; - -export function recoTrackView(viewCurrentObjects) { - oneToManyView( - viewCurrentObjects, - "edm4hep::ReconstructedParticle", - "edm4hep::Track", - "tracks" - ); -} - -export function preFilterRecoTrack(currentObjects, viewObjects) { - preFilterOneToMany( - currentObjects, - viewObjects, - "edm4hep::ReconstructedParticle", - "edm4hep::Track", - "tracks" - ); -} diff --git a/js/views/views-dictionary.js b/js/views/views-dictionary.js index df43922b..80384920 100644 --- a/js/views/views-dictionary.js +++ b/js/views/views-dictionary.js @@ -10,8 +10,10 @@ import { preFilterMCCluster, mcClusterAssociation, } from "./mcclusterassociation.js"; -import { recoTrackView, preFilterRecoTrack } from "./recotrack.js"; -import { recoClusterView, preFilterRecoCluster } from "./recocluster.js"; +import { + recoClusterTrack, + preFilterRecoClusterTrack, +} from "./recoclustertrack.js"; export const views = { "Monte Carlo Particle Tree": { @@ -38,17 +40,11 @@ export const views = { scrollFunction: scrollTopCenter, preFilterFunction: preFilterClusterTree, }, - "Reconstructed Particle-Cluster": { - filters: () => {}, - viewFunction: recoClusterView, - scrollFunction: scrollTopCenter, - preFilterFunction: preFilterRecoCluster, - }, - "Reconstructed Particle-Track": { + "Reco Particle-Cluster-Track": { filters: () => {}, - viewFunction: recoTrackView, + viewFunction: recoClusterTrack, scrollFunction: scrollTopCenter, - preFilterFunction: preFilterRecoTrack, + preFilterFunction: preFilterRecoClusterTrack, }, "Monte Carlo-Reconstructed Particle": { filters: () => {},