diff --git a/src/main.rs b/src/main.rs
index a56017be8f7c972165b0cd3e13e2d5aec39d8d26..4511578f8b31b8869603e0ec68df200d1c936f21 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,7 +9,7 @@ mod message_broker;
 mod ui;
 mod utils;
 
-use std::{fs::create_dir_all, sync::LazyLock};
+use std::{fs::create_dir_all, sync::LazyLock, time::Instant};
 
 use error::ErrInstrument;
 use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt};
@@ -19,6 +19,7 @@ use ui::App;
 
 /// ReflectionContext singleton, used to get access to the Mavlink message definitions
 static MAVLINK_PROFILE: LazyLock<ReflectionContext> = LazyLock::new(ReflectionContext::new);
+static APP_START_TIMESTAMP_ORIGIN: LazyLock<Instant> = LazyLock::new(Instant::now);
 
 static APP_NAME: &str = "segs";
 
@@ -59,6 +60,10 @@ fn main() -> Result<(), eframe::Error> {
         ..Default::default()
     };
 
+    // Initialize the starting timestamp
+    let starting_time = &APP_START_TIMESTAMP_ORIGIN;
+    tracing::info!("Starting {} at {:?}", APP_NAME, starting_time);
+
     // CreationContext constains information useful to initilize our app, like storage.
     // Storage allows to store custom data in a way that persist whan you restart the app.
     eframe::run_native(
diff --git a/src/ui/panes/plot.rs b/src/ui/panes/plot.rs
index e4616d1532f060623372344818eeb051332ab105..e3fe6b7173038296e1e9a91b13a6909c6307b4ef 100644
--- a/src/ui/panes/plot.rs
+++ b/src/ui/panes/plot.rs
@@ -1,26 +1,25 @@
+mod fields;
 mod source_window;
 
 use super::PaneBehavior;
 use crate::{
-    MAVLINK_PROFILE,
     error::ErrInstrument,
-    mavlink::{
-        MessageData, ROCKET_FLIGHT_TM_DATA, TimedMessage,
-        reflection::{FieldLike, IndexedField},
-    },
+    mavlink::{MessageData, ROCKET_FLIGHT_TM_DATA, TimedMessage},
     ui::{app::PaneResponse, shortcuts::ShortcutHandler},
     utils::units::UnitOfMeasure,
 };
 use egui::{Color32, Ui, Vec2, Vec2b};
 use egui_plot::{AxisHints, HPlacement, Legend, Line, PlotPoint, log_grid_spacer};
 use serde::{self, Deserialize, Serialize};
-use source_window::sources_window;
 use std::{
     hash::{DefaultHasher, Hash, Hasher},
     iter::zip,
     time::{Duration, Instant},
 };
 
+use fields::{XPlotField, YPlotField};
+use source_window::sources_window;
+
 #[derive(Clone, Default, Debug, Serialize, Deserialize)]
 pub struct Plot2DPane {
     settings: PlotSettings,
@@ -47,31 +46,23 @@ impl PaneBehavior for Plot2DPane {
 
         let ctrl_pressed = ui.input(|i| i.modifiers.ctrl);
 
-        let x_unit = UnitOfMeasure::from(
-            &self
-                .settings
-                .x_field
-                .field()
-                .unit
-                .clone()
-                .unwrap_or_default(),
-        );
+        let x_unit = self.settings.x_field.unit();
         let y_units = self
             .settings
             .y_fields
             .iter()
-            .map(|(field, _)| field.field().unit.as_ref().map(UnitOfMeasure::from))
+            .map(|(field, _)| field.unit())
             .collect::<Vec<_>>();
         // define y_unit as the common unit of the y_fields if they are all the same
-        let y_unit = y_units
-            .iter()
-            .fold(y_units.first().log_unwrap(), |acc, unit| {
-                match (acc, unit) {
-                    (Some(uom), Some(unit)) if uom == unit => acc,
-                    _ => &None,
+        let y_unit = y_units.iter().fold(y_units.first(), |acc, unit| {
+            if let Some(acc) = acc {
+                if acc == unit {
+                    return Some(acc);
                 }
-            });
-        let x_name = self.settings.x_field.field().name.clone();
+            }
+            None
+        });
+        let x_name = self.settings.x_field.name();
 
         let x_axis = match x_unit {
             UnitOfMeasure::Time(ref time_unit) => {
@@ -154,7 +145,7 @@ impl PaneBehavior for Plot2DPane {
                     Line::new(&points[..])
                         .color(settings.color)
                         .width(settings.width)
-                        .name(&field.field().name),
+                        .name(field.name()),
                 );
             }
             plot_ui
@@ -195,10 +186,10 @@ impl PaneBehavior for Plot2DPane {
             .iter()
             .filter(|msg| points_lifespan > &msg.time.elapsed())
         {
-            let x: f64 = x_field.extract_as_f64(&msg.message).log_unwrap();
+            let x: f64 = x_field.extract_from_message(msg).log_unwrap();
             let ys: Vec<f64> = y_fields
                 .iter()
-                .map(|(field, _)| field.extract_as_f64(&msg.message).log_unwrap())
+                .map(|(field, _)| field.extract_from_message(msg).log_unwrap())
                 .collect();
 
             if self.line_data.len() < ys.len() {
@@ -243,9 +234,9 @@ struct PlotSettings {
     /// The message id to plot
     pub(super) plot_message_id: u32,
     /// The field to plot on the x-axis
-    pub(super) x_field: IndexedField,
+    pub(super) x_field: XPlotField,
     /// The fields to plot, with their respective line settings
-    pub(super) y_fields: Vec<(IndexedField, LineSettings)>,
+    pub(super) y_fields: Vec<(YPlotField, LineSettings)>,
     /// Whether to show the axes of the plot
     pub(super) axes_visible: bool,
     /// Points will be shown for this duration before being removed
@@ -253,15 +244,13 @@ struct PlotSettings {
 }
 
 impl PlotSettings {
-    fn add_field(&mut self, field: IndexedField) {
+    fn add_field(&mut self, field: YPlotField) {
         let line_settings = LineSettings::default();
         self.y_fields.push((field, line_settings));
     }
 
     fn clear_fields(&mut self) {
-        self.x_field = 0
-            .to_mav_field(self.plot_message_id, &MAVLINK_PROFILE)
-            .log_unwrap();
+        self.x_field = XPlotField::MsgReceiptTimestamp;
         self.y_fields.clear();
     }
 
@@ -282,11 +271,8 @@ impl PlotSettings {
 impl Default for PlotSettings {
     fn default() -> Self {
         let msg_id = ROCKET_FLIGHT_TM_DATA::ID;
-        let x_field = 0.to_mav_field(msg_id, &MAVLINK_PROFILE).log_unwrap();
-        let y_fields = vec![(
-            1.to_mav_field(msg_id, &MAVLINK_PROFILE).log_unwrap(),
-            LineSettings::default(),
-        )];
+        let x_field = XPlotField::MsgReceiptTimestamp;
+        let y_fields = vec![];
         Self {
             plot_message_id: msg_id,
             x_field,
diff --git a/src/ui/panes/plot/fields.rs b/src/ui/panes/plot/fields.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1b62451e95665d4d4bf831e8b973f94ffe92ef19
--- /dev/null
+++ b/src/ui/panes/plot/fields.rs
@@ -0,0 +1,75 @@
+use serde::{Deserialize, Serialize};
+
+use crate::{
+    APP_START_TIMESTAMP_ORIGIN,
+    mavlink::{TimedMessage, reflection::IndexedField},
+    utils::units::{TimeUnits, UnitOfMeasure},
+};
+
+#[derive(Clone, Debug, PartialEq, Hash, Serialize, Deserialize)]
+pub enum XPlotField {
+    MsgReceiptTimestamp,
+    Field(IndexedField),
+}
+
+impl XPlotField {
+    pub fn unit(&self) -> UnitOfMeasure {
+        match self {
+            XPlotField::MsgReceiptTimestamp => UnitOfMeasure::Time(TimeUnits::Millisecond),
+            XPlotField::Field(field) => UnitOfMeasure::from(field.field().unit.as_ref()),
+        }
+    }
+
+    pub fn name(&self) -> String {
+        match self {
+            XPlotField::MsgReceiptTimestamp => "receival timestamp".to_string(),
+            XPlotField::Field(field) => field.field().name.clone(),
+        }
+    }
+
+    pub fn extract_from_message(&self, message: &TimedMessage) -> Result<f64, String> {
+        match self {
+            XPlotField::MsgReceiptTimestamp => {
+                Ok((message.time - *APP_START_TIMESTAMP_ORIGIN).as_millis() as f64)
+            }
+            XPlotField::Field(field) => field.extract_as_f64(&message.message),
+        }
+    }
+}
+
+impl From<IndexedField> for XPlotField {
+    fn from(field: IndexedField) -> Self {
+        Self::Field(field)
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Hash, Serialize, Deserialize)]
+pub enum YPlotField {
+    Field(IndexedField),
+}
+
+impl YPlotField {
+    pub fn unit(&self) -> UnitOfMeasure {
+        match self {
+            YPlotField::Field(field) => UnitOfMeasure::from(field.field().unit.as_ref()),
+        }
+    }
+
+    pub fn name(&self) -> String {
+        match self {
+            YPlotField::Field(field) => field.field().name.clone(),
+        }
+    }
+
+    pub fn extract_from_message(&self, message: &TimedMessage) -> Result<f64, String> {
+        match self {
+            YPlotField::Field(field) => field.extract_as_f64(&message.message),
+        }
+    }
+}
+
+impl From<IndexedField> for YPlotField {
+    fn from(field: IndexedField) -> Self {
+        Self::Field(field)
+    }
+}
diff --git a/src/ui/panes/plot/source_window.rs b/src/ui/panes/plot/source_window.rs
index c3098783f3ccad53e7ebf0e8e1b4c49ef381e447..3fb52d1c95637aa4d1e989359b51d469d4a6a6f9 100644
--- a/src/ui/panes/plot/source_window.rs
+++ b/src/ui/panes/plot/source_window.rs
@@ -2,7 +2,10 @@ use std::time::Duration;
 
 use crate::{MAVLINK_PROFILE, error::ErrInstrument};
 
-use super::{LineSettings, PlotSettings};
+use super::{
+    LineSettings, PlotSettings,
+    fields::{XPlotField, YPlotField},
+};
 
 #[profiling::function]
 pub fn sources_window(ui: &mut egui::Ui, plot_settings: &mut PlotSettings) {
@@ -50,35 +53,42 @@ pub fn sources_window(ui: &mut egui::Ui, plot_settings: &mut PlotSettings) {
     let fields = MAVLINK_PROFILE
         .get_plottable_fields(plot_settings.plot_message_id)
         .log_expect("Invalid message id");
+    let mut x_fields = vec![XPlotField::MsgReceiptTimestamp];
+    let y_fields = fields
+        .clone()
+        .into_iter()
+        .map(|f| f.into())
+        .collect::<Vec<_>>();
+    x_fields.extend(fields.into_iter().map(|f| f.into()));
     // get the first field that is in the list of fields or the previous if valid
     let x_field = &plot_settings.x_field;
-    let new_field_x = fields
-        .iter()
-        .any(|f| f == x_field)
-        .then(|| x_field.to_owned())
-        .or(fields.first().map(|s| s.to_owned()));
-
-    // if there are no fields, reset the field_x and plot_lines
-    let Some(new_field_x) = new_field_x else {
-        plot_settings.clear_fields();
-        return;
+    let new_field_x = if x_fields.iter().any(|f| f == x_field) {
+        x_field.to_owned()
+    } else {
+        XPlotField::MsgReceiptTimestamp
     };
+
     // update the field_x
     plot_settings.x_field = new_field_x;
 
     // if fields are valid, show the combo boxes for the x_axis
     let x_field = &mut plot_settings.x_field;
     egui::ComboBox::from_label("X Axis")
-        .selected_text(&x_field.field().name)
+        .selected_text(x_field.name())
         .show_ui(ui, |ui| {
-            for msg in fields.iter() {
-                ui.selectable_value(x_field, msg.to_owned(), &msg.field().name);
+            for msg in x_fields.iter() {
+                ui.selectable_value(x_field, msg.to_owned(), msg.name());
             }
         });
 
+    // retain only the fields that are in y_fields
+    plot_settings
+        .y_fields
+        .retain(|(field, _)| y_fields.iter().any(|f: &YPlotField| f == field));
+
     // populate the plot_lines with the first field if it is empty and there are more than 1 fields
-    if plot_settings.y_fields.is_empty() && fields.len() > 1 {
-        plot_settings.add_field(fields[1].to_owned());
+    if plot_settings.y_fields.is_empty() && y_fields.len() > 1 {
+        plot_settings.add_field(y_fields[0].clone());
     }
 
     // check how many fields are left and how many are selected
@@ -95,10 +105,10 @@ pub fn sources_window(ui: &mut egui::Ui, plot_settings: &mut PlotSettings) {
                     "Y Axis".to_owned()
                 };
                 egui::ComboBox::from_label(widget_label)
-                    .selected_text(&field.field().name)
+                    .selected_text(field.name())
                     .show_ui(ui, |ui| {
-                        for msg in fields.iter() {
-                            ui.selectable_value(field, msg.to_owned(), &msg.field().name);
+                        for msg in y_fields.iter() {
+                            ui.selectable_value(field, msg.to_owned(), msg.name());
                         }
                     });
                 ui.color_edit_button_srgba(color);
@@ -114,14 +124,14 @@ pub fn sources_window(ui: &mut egui::Ui, plot_settings: &mut PlotSettings) {
         });
 
     // if we have fields left, show the add button
-    if fields.len().saturating_sub(plot_lines_len + 1) > 0
+    if y_fields.len().saturating_sub(plot_lines_len + 1) > 0
         && ui
             .button("Add Y Axis")
             .on_hover_text("Add another Y axis")
             .clicked()
     {
         // get the first field that is not in the plot_lines
-        let next_field = fields
+        let next_field = y_fields
             .iter()
             .find(|field| !plot_settings.y_fields.iter().any(|(f, _)| f == *field))
             .log_unwrap();
diff --git a/src/utils/units.rs b/src/utils/units.rs
index 98267d98cf45a12f542c22d5d7d2d8366c315867..cf05bc66f4cd7ab79e430b1eaf4d8a9de0772abf 100644
--- a/src/utils/units.rs
+++ b/src/utils/units.rs
@@ -4,14 +4,22 @@ use std::{fmt::Display, str::FromStr};
 pub enum UnitOfMeasure {
     Time(TimeUnits),
     Other(String),
+    Adimensional,
 }
 
-impl<T: AsRef<str>> From<T> for UnitOfMeasure {
-    fn from(s: T) -> Self {
-        if let Ok(unit) = TimeUnits::from_str(s.as_ref()) {
-            UnitOfMeasure::Time(unit)
-        } else {
-            UnitOfMeasure::Other(s.as_ref().to_string())
+impl<T: AsRef<str>> From<Option<T>> for UnitOfMeasure {
+    fn from(s: Option<T>) -> Self {
+        let s = s.as_ref();
+        match s {
+            Some(s) if s.as_ref().is_empty() => UnitOfMeasure::Adimensional,
+            Some(s) => {
+                if let Ok(unit) = TimeUnits::from_str(s.as_ref()) {
+                    UnitOfMeasure::Time(unit)
+                } else {
+                    UnitOfMeasure::Other(s.as_ref().to_string())
+                }
+            }
+            None => UnitOfMeasure::Adimensional,
         }
     }
 }
@@ -21,6 +29,7 @@ impl Display for UnitOfMeasure {
         match self {
             UnitOfMeasure::Time(unit) => write!(f, "{}", unit),
             UnitOfMeasure::Other(unit) => write!(f, "{}", unit),
+            UnitOfMeasure::Adimensional => write!(f, ""),
         }
     }
 }