From 232ee9a8bea398339154c7830d911121422eb14a Mon Sep 17 00:00:00 2001 From: Ben Steer Date: Thu, 21 Dec 2023 09:39:44 +0000 Subject: [PATCH] Added date_time history/items to Temporal properties (#1423) added date_time history/items to Temporal properties --- raphtory/src/db/api/properties/internal.rs | 11 +++++++ .../src/db/api/properties/temporal_props.rs | 14 +++++++++ .../src/db/api/view/internal/materialize.rs | 1 + raphtory/src/db/graph/edge.rs | 7 +++++ raphtory/src/db/graph/node.rs | 9 ++++++ raphtory/src/db/graph/views/window_graph.rs | 8 +++++ .../src/db/internal/temporal_properties.rs | 12 ++++++++ raphtory/src/db/task/edge/eval_edge.rs | 4 +++ .../python/graph/properties/temporal_props.rs | 30 +++++++++++++++++++ 9 files changed, 96 insertions(+) diff --git a/raphtory/src/db/api/properties/internal.rs b/raphtory/src/db/api/properties/internal.rs index b71e91982c..b6bd45e816 100644 --- a/raphtory/src/db/api/properties/internal.rs +++ b/raphtory/src/db/api/properties/internal.rs @@ -2,6 +2,7 @@ use crate::{ core::{ArcStr, Prop}, db::api::view::internal::Base, }; +use chrono::NaiveDateTime; use enum_dispatch::enum_dispatch; #[enum_dispatch] @@ -10,6 +11,12 @@ pub trait TemporalPropertyViewOps { self.temporal_values(id).last().cloned() } fn temporal_history(&self, id: usize) -> Vec; + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.temporal_history(id) + .iter() + .map(|t| NaiveDateTime::from_timestamp_millis(*t)) + .collect::>>() + } fn temporal_values(&self, id: usize) -> Vec; fn temporal_value_at(&self, id: usize, t: i64) -> Option { let history = self.temporal_history(id); @@ -82,6 +89,10 @@ where fn temporal_history(&self, id: usize) -> Vec { self.base().temporal_history(id) } + #[inline] + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.base().temporal_history_date_time(id) + } #[inline] fn temporal_values(&self, id: usize) -> Vec { diff --git a/raphtory/src/db/api/properties/temporal_props.rs b/raphtory/src/db/api/properties/temporal_props.rs index 798630f5c8..b68daaf2fe 100644 --- a/raphtory/src/db/api/properties/temporal_props.rs +++ b/raphtory/src/db/api/properties/temporal_props.rs @@ -18,12 +18,26 @@ impl TemporalPropertyView

{ pub fn history(&self) -> Vec { self.props.temporal_history(self.id) } + pub fn history_date_time(&self) -> Option> { + self.props.temporal_history_date_time(self.id) + } pub fn values(&self) -> Vec { self.props.temporal_values(self.id) } pub fn iter(&self) -> impl Iterator { self.into_iter() } + + pub fn histories(&self) -> impl Iterator { + self.iter() + } + + pub fn histories_date_time(&self) -> Option> { + let hist = self.history_date_time()?; + let vals = self.values(); + Some(hist.into_iter().zip(vals)) + } + pub fn at(&self, t: i64) -> Option { self.props.temporal_value_at(self.id, t) } diff --git a/raphtory/src/db/api/view/internal/materialize.rs b/raphtory/src/db/api/view/internal/materialize.rs index f23d69bf82..c9c267bf36 100644 --- a/raphtory/src/db/api/view/internal/materialize.rs +++ b/raphtory/src/db/api/view/internal/materialize.rs @@ -33,6 +33,7 @@ use crate::{ }, prelude::{Layer, Prop}, }; +use chrono::NaiveDateTime; use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; use std::path::Path; diff --git a/raphtory/src/db/graph/edge.rs b/raphtory/src/db/graph/edge.rs index 819639945d..27a6daa209 100644 --- a/raphtory/src/db/graph/edge.rs +++ b/raphtory/src/db/graph/edge.rs @@ -274,6 +274,13 @@ impl<'graph, G: GraphViewOps<'graph>, GH: GraphViewOps<'graph>> TemporalProperty .map(|(t, _)| t) .collect() } + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.graph + .temporal_edge_prop_vec(self.edge, id, self.graph.layer_ids()) + .into_iter() + .map(|(t, _)| NaiveDateTime::from_timestamp_millis(t)) + .collect::>>() + } fn temporal_values(&self, id: usize) -> Vec { let layer_ids = self.graph.layer_ids().constrain_from_edge(self.edge); diff --git a/raphtory/src/db/graph/node.rs b/raphtory/src/db/graph/node.rs index 3bfb5059bb..dc62ebd753 100644 --- a/raphtory/src/db/graph/node.rs +++ b/raphtory/src/db/graph/node.rs @@ -27,6 +27,7 @@ use crate::{ prelude::*, }; +use chrono::NaiveDateTime; use std::{ fmt, hash::{Hash, Hasher}, @@ -210,6 +211,14 @@ impl TemporalPropertyViewOps for NodeView { .collect() } + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.graph + .temporal_node_prop_vec(self.node, id) + .into_iter() + .map(|(t, _)| NaiveDateTime::from_timestamp_millis(t)) + .collect::>>() + } + fn temporal_values(&self, id: usize) -> Vec { self.graph .temporal_node_prop_vec(self.node, id) diff --git a/raphtory/src/db/graph/views/window_graph.rs b/raphtory/src/db/graph/views/window_graph.rs index bc46aa3b34..7c4d7168c9 100644 --- a/raphtory/src/db/graph/views/window_graph.rs +++ b/raphtory/src/db/graph/views/window_graph.rs @@ -60,6 +60,7 @@ use crate::{ }, prelude::GraphViewOps, }; +use chrono::NaiveDateTime; use std::{ cmp::{max, min}, fmt::{Debug, Formatter}, @@ -125,6 +126,13 @@ impl<'graph, G: GraphViewOps<'graph>> TemporalPropertyViewOps for WindowedGraph< .collect() } + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.temporal_prop_vec(id) + .into_iter() + .map(|(t, _)| NaiveDateTime::from_timestamp_millis(t)) + .collect::>>() + } + fn temporal_values(&self, id: usize) -> Vec { self.temporal_prop_vec(id) .into_iter() diff --git a/raphtory/src/db/internal/temporal_properties.rs b/raphtory/src/db/internal/temporal_properties.rs index 2a3e734109..0e07b7a503 100644 --- a/raphtory/src/db/internal/temporal_properties.rs +++ b/raphtory/src/db/internal/temporal_properties.rs @@ -2,6 +2,7 @@ use crate::{ core::{entities::graph::tgraph::InnerTemporalGraph, ArcStr, Prop}, db::api::properties::internal::{TemporalPropertiesOps, TemporalPropertyViewOps}, }; +use chrono::NaiveDateTime; impl TemporalPropertyViewOps for InnerTemporalGraph { fn temporal_value(&self, id: usize) -> Option { @@ -17,6 +18,17 @@ impl TemporalPropertyViewOps for InnerTemporalGraph { .unwrap_or_default() } + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.inner() + .get_temporal_prop(id) + .map(|prop| { + prop.iter() + .map(|(t, _)| NaiveDateTime::from_timestamp_millis(t)) + .collect::>>() + }) + .unwrap_or_default() + } + fn temporal_values(&self, id: usize) -> Vec { self.inner() .get_temporal_prop(id) diff --git a/raphtory/src/db/task/edge/eval_edge.rs b/raphtory/src/db/task/edge/eval_edge.rs index c85220749c..917f9c9135 100644 --- a/raphtory/src/db/task/edge/eval_edge.rs +++ b/raphtory/src/db/task/edge/eval_edge.rs @@ -178,6 +178,10 @@ impl< self.edge.temporal_history(id) } + fn temporal_history_date_time(&self, id: usize) -> Option> { + self.edge.temporal_history_date_time(id) + } + fn temporal_values(&self, id: usize) -> Vec { self.edge.temporal_values(id) } diff --git a/raphtory/src/python/graph/properties/temporal_props.rs b/raphtory/src/python/graph/properties/temporal_props.rs index b225e1d0d7..7f8570ab73 100644 --- a/raphtory/src/python/graph/properties/temporal_props.rs +++ b/raphtory/src/python/graph/properties/temporal_props.rs @@ -23,6 +23,7 @@ use crate::{ utils::{PyGenericIterator, PyTime}, }, }; +use chrono::NaiveDateTime; use itertools::Itertools; use pyo3::{ exceptions::{PyKeyError, PyTypeError}, @@ -121,6 +122,25 @@ impl PyTemporalProperties { .collect() } + /// Get the histories of all properties + /// + /// Returns: + /// dict[str, list[(datetime, Any)]]: the mapping of property keys to histories + fn histories_date_time(&self) -> HashMap>> { + self.props + .iter() + .map(|(k, v)| { + ( + k.clone(), + match v.histories_date_time() { + None => None, + Some(history) => Some(history.collect()), + }, + ) + }) + .collect() + } + /// __getitem__(key: str) -> TemporalProp /// /// Get property value for `key` @@ -213,6 +233,11 @@ impl PyTemporalProp { self.prop.history() } + /// Get the timestamps at which the property was updated + pub fn history_date_time(&self) -> Option> { + self.prop.history_date_time() + } + /// Get the property values for each update pub fn values(&self) -> Vec { self.prop.values() @@ -223,6 +248,11 @@ impl PyTemporalProp { self.prop.iter().collect() } + /// List update timestamps and corresponding property values + pub fn items_date_time(&self) -> Option> { + Some(self.prop.histories_date_time()?.collect()) + } + /// Iterate over `items` pub fn __iter__(&self) -> PyGenericIterator { self.prop.iter().into()