use std::{fmt::Display, ops::Deref, sync::Arc};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
#[cfg(feature = "mpi")]
use super::dataset::MpiDatasetLayout;
use super::{Dataset, DatasetMetadata};
use crate::{
variables::Variable,
vectors::{Vec3, Vec4},
};
pub fn test_event() -> EventData {
let pol_magnitude = 0.38562805;
let pol_angle = 0.05708078;
EventData {
p4s: vec![
Vec3::new(0.0, 0.0, 8.747).with_mass(0.0),
Vec3::new(0.119, 0.374, 0.222).with_mass(1.007),
Vec3::new(-0.112, 0.293, 3.081).with_mass(0.498),
Vec3::new(-0.007, -0.667, 5.446).with_mass(0.498),
],
aux: vec![pol_magnitude, pol_angle],
weight: 0.48,
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EventData {
pub p4s: Vec<Vec4>,
pub aux: Vec<f64>,
pub weight: f64,
}
impl Display for EventData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Event:")?;
writeln!(f, " p4s:")?;
for p4 in &self.p4s {
writeln!(f, " {}", p4.to_p4_string())?;
}
writeln!(f, " aux:")?;
for (idx, value) in self.aux.iter().enumerate() {
writeln!(f, " aux[{idx}]: {value}")?;
}
writeln!(f, " weight:")?;
writeln!(f, " {}", self.weight)?;
Ok(())
}
}
impl EventData {
pub fn get_p4_sum<T: AsRef<[usize]>>(&self, indices: T) -> Vec4 {
indices.as_ref().iter().map(|i| self.p4s[*i]).sum::<Vec4>()
}
pub fn boost_to_rest_frame_of<T: AsRef<[usize]>>(&self, indices: T) -> Self {
let frame = self.get_p4_sum(indices);
EventData {
p4s: self
.p4s
.iter()
.map(|p4| p4.boost(&(-frame.beta())))
.collect(),
aux: self.aux.clone(),
weight: self.weight,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ColumnarP4Column {
pub(crate) px: Vec<f64>,
pub(crate) py: Vec<f64>,
pub(crate) pz: Vec<f64>,
pub(crate) e: Vec<f64>,
}
impl ColumnarP4Column {
pub fn with_capacity(capacity: usize) -> Self {
Self {
px: Vec::with_capacity(capacity),
py: Vec::with_capacity(capacity),
pz: Vec::with_capacity(capacity),
e: Vec::with_capacity(capacity),
}
}
pub fn push(&mut self, p4: Vec4) {
self.px.push(p4.x);
self.py.push(p4.y);
self.pz.push(p4.z);
self.e.push(p4.t);
}
pub fn len(&self) -> usize {
self.px.len()
}
pub fn is_empty(&self) -> bool {
self.px.is_empty()
}
pub fn get(&self, event_index: usize) -> Vec4 {
Vec4::new(
self.px[event_index],
self.py[event_index],
self.pz[event_index],
self.e[event_index],
)
}
}
#[derive(Debug, Default)]
pub struct DatasetStorage {
pub(crate) metadata: Arc<DatasetMetadata>,
pub(crate) p4: Vec<ColumnarP4Column>,
pub(crate) aux: Vec<Vec<f64>>,
pub(crate) weights: Vec<f64>,
}
impl Clone for DatasetStorage {
fn clone(&self) -> Self {
Self {
metadata: self.metadata.clone(),
p4: self.p4.clone(),
aux: self.aux.clone(),
weights: self.weights.clone(),
}
}
}
impl DatasetStorage {
pub fn new(
metadata: DatasetMetadata,
p4: Vec<ColumnarP4Column>,
aux: Vec<Vec<f64>>,
weights: Vec<f64>,
) -> Self {
Self {
metadata: Arc::new(metadata),
p4,
aux,
weights,
}
}
pub(crate) fn empty_with_capacity(metadata: Arc<DatasetMetadata>, capacity: usize) -> Self {
Self {
p4: (0..metadata.p4_names().len())
.map(|_| ColumnarP4Column::with_capacity(capacity))
.collect(),
aux: (0..metadata.aux_names().len())
.map(|_| Vec::with_capacity(capacity))
.collect(),
weights: Vec::with_capacity(capacity),
metadata,
}
}
pub(crate) fn push_event_data(&mut self, event: &EventData) {
for (column, p4) in self.p4.iter_mut().zip(&event.p4s) {
column.push(*p4);
}
for (column, value) in self.aux.iter_mut().zip(&event.aux) {
column.push(*value);
}
self.weights.push(event.weight);
}
pub(crate) fn set_metadata(&mut self, metadata: Arc<DatasetMetadata>) {
self.metadata = metadata;
}
pub(crate) fn push_p4_column(&mut self, values: Vec<Vec4>) {
let mut column = ColumnarP4Column::with_capacity(values.len());
for value in values {
column.push(value);
}
self.p4.push(column);
}
pub(crate) fn push_aux_column(&mut self, values: Vec<f64>) {
self.aux.push(values);
}
pub fn to_dataset(&self) -> Dataset {
let events = (0..self.n_events())
.map(|event_index| Arc::new(self.event_data(event_index)))
.collect::<Vec<_>>();
#[cfg(not(feature = "mpi"))]
let dataset = Dataset::new_local(events, self.metadata.clone());
#[cfg(feature = "mpi")]
let mut dataset = Dataset::new_local(events, self.metadata.clone());
#[cfg(feature = "mpi")]
{
if let Some(world) = crate::mpi::get_world() {
dataset.mpi_layout = Some(MpiDatasetLayout::Canonical);
dataset.set_cached_global_event_count_from_world(&world);
dataset.set_cached_global_weighted_sum_from_world(&world);
}
}
dataset
}
pub(crate) fn metadata(&self) -> &DatasetMetadata {
&self.metadata
}
pub(crate) fn n_events(&self) -> usize {
self.weights.len()
}
pub(crate) fn p4(&self, event_index: usize, p4_index: usize) -> Vec4 {
self.p4[p4_index].get(event_index)
}
pub(crate) fn aux(&self, event_index: usize, aux_index: usize) -> f64 {
self.aux[aux_index][event_index]
}
pub(crate) fn weight(&self, event_index: usize) -> f64 {
self.weights[event_index]
}
pub(crate) fn event_data(&self, event_index: usize) -> EventData {
let mut p4s = Vec::with_capacity(self.p4.len());
for p4_index in 0..self.p4.len() {
p4s.push(self.p4(event_index, p4_index));
}
let mut aux = Vec::with_capacity(self.aux.len());
for aux_index in 0..self.aux.len() {
aux.push(self.aux(event_index, aux_index));
}
EventData {
p4s,
aux,
weight: self.weight(event_index),
}
}
fn row_view(&self, event_index: usize) -> ColumnarEventView<'_> {
ColumnarEventView {
storage: self,
event_index,
}
}
#[allow(dead_code)]
pub(crate) fn for_each_event_local<F>(&self, mut op: F)
where
F: FnMut(usize, Event<'_>),
{
for event_index in 0..self.n_events() {
let row = self.row_view(event_index);
let view = Event {
row: EventRow::Columnar(row),
metadata: &self.metadata,
};
op(event_index, view);
}
}
pub(crate) fn event_view(&self, event_index: usize) -> Event<'_> {
let row = self.row_view(event_index);
Event {
row: EventRow::Columnar(row),
metadata: self.metadata(),
}
}
}
#[derive(Debug)]
struct ColumnarEventView<'a> {
storage: &'a DatasetStorage,
event_index: usize,
}
#[allow(dead_code)]
impl ColumnarEventView<'_> {
fn p4(&self, p4_index: usize) -> Vec4 {
self.storage.p4(self.event_index, p4_index)
}
fn aux(&self, aux_index: usize) -> f64 {
self.storage.aux(self.event_index, aux_index)
}
fn weight(&self) -> f64 {
self.storage.weight(self.event_index)
}
}
#[derive(Debug)]
enum EventRow<'a> {
Columnar(ColumnarEventView<'a>),
Owned(&'a EventData),
}
impl EventRow<'_> {
fn p4(&self, p4_index: usize) -> Vec4 {
match self {
Self::Columnar(row) => row.p4(p4_index),
Self::Owned(event) => event.p4s[p4_index],
}
}
fn aux(&self, aux_index: usize) -> f64 {
match self {
Self::Columnar(row) => row.aux(aux_index),
Self::Owned(event) => event.aux[aux_index],
}
}
fn weight(&self) -> f64 {
match self {
Self::Columnar(row) => row.weight(),
Self::Owned(event) => event.weight,
}
}
fn n_p4(&self) -> usize {
match self {
Self::Columnar(row) => row.storage.p4.len(),
Self::Owned(event) => event.p4s.len(),
}
}
fn n_aux(&self) -> usize {
match self {
Self::Columnar(row) => row.storage.aux.len(),
Self::Owned(event) => event.aux.len(),
}
}
}
#[derive(Debug)]
pub struct Event<'a> {
row: EventRow<'a>,
metadata: &'a DatasetMetadata,
}
pub trait EventLike {
fn p4_at(&self, p4_index: usize) -> Vec4;
fn aux_at(&self, aux_index: usize) -> f64;
fn n_p4(&self) -> usize;
fn n_aux(&self) -> usize;
fn weight(&self) -> f64;
fn metadata(&self) -> &DatasetMetadata;
fn p4(&self, name: &str) -> Option<Vec4> {
let selection = self.metadata().p4_selection(name)?;
Some(
selection
.indices()
.iter()
.map(|index| self.p4_at(*index))
.sum(),
)
}
fn aux(&self, name: &str) -> Option<f64> {
let index = self.metadata().aux_index(name)?;
Some(self.aux_at(index))
}
fn get_p4_sum<N>(&self, names: N) -> Option<Vec4>
where
Self: Sized,
N: IntoIterator,
N::Item: AsRef<str>,
{
names
.into_iter()
.map(|name| self.p4(name.as_ref()))
.collect::<Option<Vec<_>>>()
.map(|momenta| momenta.into_iter().sum())
}
}
impl EventLike for Event<'_> {
fn p4_at(&self, p4_index: usize) -> Vec4 {
self.row.p4(p4_index)
}
fn aux_at(&self, aux_index: usize) -> f64 {
self.row.aux(aux_index)
}
fn n_p4(&self) -> usize {
self.row.n_p4()
}
fn n_aux(&self) -> usize {
self.row.n_aux()
}
fn weight(&self) -> f64 {
self.row.weight()
}
fn metadata(&self) -> &DatasetMetadata {
self.metadata
}
}
impl Event<'_> {
pub fn p4_at(&self, p4_index: usize) -> Vec4 {
EventLike::p4_at(self, p4_index)
}
pub fn aux_at(&self, aux_index: usize) -> f64 {
EventLike::aux_at(self, aux_index)
}
pub fn n_p4(&self) -> usize {
EventLike::n_p4(self)
}
pub fn n_aux(&self) -> usize {
EventLike::n_aux(self)
}
pub fn p4(&self, name: &str) -> Option<Vec4> {
EventLike::p4(self, name)
}
pub fn aux(&self, name: &str) -> Option<f64> {
EventLike::aux(self, name)
}
pub fn weight(&self) -> f64 {
EventLike::weight(self)
}
pub fn to_event_data(&self) -> EventData {
EventData {
p4s: (0..self.n_p4()).map(|index| self.p4_at(index)).collect(),
aux: (0..self.n_aux()).map(|index| self.aux_at(index)).collect(),
weight: self.weight(),
}
}
pub fn get_p4_sum<N>(&self, names: N) -> Option<Vec4>
where
N: IntoIterator,
N::Item: AsRef<str>,
{
EventLike::get_p4_sum(self, names)
}
pub fn evaluate<V: Variable>(&self, variable: &V) -> f64 {
variable.value(self)
}
}
impl Display for Event<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Event:")?;
writeln!(f, " p4s:")?;
for index in 0..self.n_p4() {
let label = self
.metadata
.p4_names()
.get(index)
.map_or_else(|| format!("p4[{index}]"), Clone::clone);
writeln!(f, " {label}: {}", self.p4_at(index).to_p4_string())?;
}
writeln!(f, " aux:")?;
for index in 0..self.n_aux() {
let label = self
.metadata
.aux_names()
.get(index)
.map_or_else(|| format!("aux[{index}]"), Clone::clone);
writeln!(f, " {label}: {}", self.aux_at(index))?;
}
writeln!(f, " weight:")?;
writeln!(f, " {}", self.weight())?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct OwnedEvent {
event: Arc<EventData>,
metadata: Arc<DatasetMetadata>,
}
impl OwnedEvent {
pub fn new(event: Arc<EventData>, metadata: Arc<DatasetMetadata>) -> Self {
Self { event, metadata }
}
pub fn data(&self) -> &EventData {
&self.event
}
pub fn data_arc(&self) -> Arc<EventData> {
self.event.clone()
}
pub fn as_event(&self) -> Event<'_> {
Event {
row: EventRow::Owned(&self.event),
metadata: &self.metadata,
}
}
pub fn p4s(&self) -> IndexMap<&str, Vec4> {
let mut map = IndexMap::with_capacity(self.metadata.p4_names.len());
for (idx, name) in self.metadata.p4_names.iter().enumerate() {
if let Some(p4) = self.event.p4s.get(idx) {
map.insert(name.as_str(), *p4);
}
}
map
}
pub fn aux(&self) -> IndexMap<&str, f64> {
let mut map = IndexMap::with_capacity(self.metadata.aux_names.len());
for (idx, name) in self.metadata.aux_names.iter().enumerate() {
if let Some(value) = self.event.aux.get(idx) {
map.insert(name.as_str(), *value);
}
}
map
}
pub fn weight(&self) -> f64 {
self.event.weight
}
pub fn metadata(&self) -> &DatasetMetadata {
&self.metadata
}
pub fn metadata_arc(&self) -> Arc<DatasetMetadata> {
self.metadata.clone()
}
pub fn p4(&self, name: &str) -> Option<Vec4> {
EventLike::p4(self, name)
}
fn resolve_p4_indices<N>(&self, names: N) -> Vec<usize>
where
N: IntoIterator,
N::Item: AsRef<str>,
{
let mut indices = Vec::new();
for name in names {
let name_ref = name.as_ref();
if let Some(selection) = self.metadata.p4_selection(name_ref) {
indices.extend_from_slice(selection.indices());
} else {
panic!("Unknown particle name '{name}'", name = name_ref);
}
}
indices
}
pub fn get_p4_sum<N>(&self, names: N) -> Vec4
where
N: IntoIterator,
N::Item: AsRef<str>,
{
let indices = self.resolve_p4_indices(names);
self.event.get_p4_sum(&indices)
}
pub fn boost_to_rest_frame_of<N>(&self, names: N) -> EventData
where
N: IntoIterator,
N::Item: AsRef<str>,
{
let indices = self.resolve_p4_indices(names);
self.event.boost_to_rest_frame_of(&indices)
}
}
impl EventLike for OwnedEvent {
fn p4_at(&self, p4_index: usize) -> Vec4 {
self.event.p4s[p4_index]
}
fn aux_at(&self, aux_index: usize) -> f64 {
self.event.aux[aux_index]
}
fn n_p4(&self) -> usize {
self.event.p4s.len()
}
fn n_aux(&self) -> usize {
self.event.aux.len()
}
fn weight(&self) -> f64 {
self.event.weight
}
fn metadata(&self) -> &DatasetMetadata {
&self.metadata
}
}
impl Display for OwnedEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_event().fmt(f)
}
}
impl Deref for OwnedEvent {
type Target = EventData;
fn deref(&self) -> &Self::Target {
&self.event
}
}
impl AsRef<EventData> for OwnedEvent {
fn as_ref(&self) -> &EventData {
self.data()
}
}