Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Make sure you are using the latest version of stable rust by running `rustup upd

On Linux you need to first run:

`sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libgtk-3-dev`
`sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libgtk-3-dev sshpass`

On Fedora Rawhide you need to run:

Expand Down
4 changes: 2 additions & 2 deletions etc/archivist.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/bin/bash

RUNNO=$1
BINARYDIR=/Users/alconley/Projects/CatrinaTests/DAQ/run_$RUNNO/UNFILTERED
BINARYDIR=/home/alconley/Projects/January_2025_207Bi/DAQ/run_$RUNNO/UNFILTERED

ARCHIVE=/Users/alconley/Projects/CatrinaTests/WorkingDir/raw_binary/run_$RUNNO.tar.gz
ARCHIVE=/home/alconley/Projects/January_2025_207Bi/WorkingDir/raw_binary/run_$RUNNO.tar.gz

echo "Running archivist for binary data in $BINARYDIR to archive $ARCHIVE..."

Expand Down
252 changes: 252 additions & 0 deletions src/evb/archivist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
use std::path::PathBuf;
use std::process::Command;

#[derive(serde::Deserialize, serde::Serialize, Debug)]
pub struct SSH {
pub enabled: bool,
pub user: String,
pub host: String,
pub password: String,
}

impl Default for SSH {
fn default() -> Self {
Self {
enabled: false,
user: "spieker-group".to_string(),
host: "spiekerlab.physics.fsu.edu".to_string(),
password: "".to_string(),
}
}
}

#[derive(serde::Deserialize, serde::Serialize, Debug, Default)]
pub struct Archivist {
pub compass_path: String,
pub output_path: String,
pub min_run: u32,
pub max_run: u32,
pub multiple_runs: bool,
pub ssh: SSH,
}

impl Archivist {
pub fn run_archive(&self, run_no: u32) {
let output_path = PathBuf::from(&self.output_path);
if !output_path.exists() {
log::error!("Output path {:?} does not exist", output_path);
return;
}

let archive_path = format!("{}/run_{}.tar.gz", self.output_path, run_no);
let archive_path = PathBuf::from(&archive_path);

let binary_dir = format!("{}/DAQ/run_{}/UNFILTERED", self.compass_path, run_no);
let binary_dir = PathBuf::from(&binary_dir);
if !binary_dir.exists() {
log::error!("Binary data directory {:?} does not exist", binary_dir);
return;
}

println!(
"Running archivist for binary data in {:?} to archive {:?}...",
binary_dir, archive_path
);

let output = Command::new("bash")
.arg("-c")
.arg(format!(
"cd {:?} && tar -cvzf {:?} ./*.BIN && cd -",
binary_dir.display(),
archive_path.display()
))
.output();

if let Err(e) = output {
log::error!("Failed to run command: {}", e);
return;
}

let output = output.unwrap();
if !output.status.success() {
log::error!(
"Error during archiving: {}",
String::from_utf8_lossy(&output.stderr)
);
} else {
// print the stdout
println!("{}", String::from_utf8_lossy(&output.stdout));
}
}

pub fn run_archive_ssh(&self, run_no: u32) {
if !self.ssh.enabled {
log::error!("SSH is not enabled in the configuration.");
return;
}

let archive_path = format!("{}/run_{}.tar.gz", self.output_path, run_no);
let binary_dir = format!("{}/DAQ/run_{}/UNFILTERED", self.compass_path, run_no);

println!(
"Running archivist over SSH for binary data in {:?} to create archive {:?}...",
binary_dir, archive_path
);

// Step 1: Tar the files on the remote server
let remote_archive_path = format!("/tmp/run_{}.tar.gz", run_no);
let ssh_tar_command = format!(
"sshpass -p '{}' ssh {}@{} \"cd {} && tar -cvzf {} ./*.BIN\"",
self.ssh.password, self.ssh.user, self.ssh.host, binary_dir, remote_archive_path
);

let tar_output = Command::new("bash")
.arg("-c")
.arg(&ssh_tar_command)
.output();

if let Err(e) = tar_output {
log::error!("Failed to run SSH tar command: {}", e);
return;
}

let tar_output = tar_output.unwrap();
if !tar_output.status.success() {
log::error!(
"Error during remote tar creation: {}",
String::from_utf8_lossy(&tar_output.stderr)
);
return;
}

println!(
"\tRemote tarball created successfully at {:?}.",
remote_archive_path
);

// Step 2: Copy the tarball from the remote server to the local machine
let scp_command = format!(
"sshpass -p '{}' scp {}@{}:{} {}",
self.ssh.password, self.ssh.user, self.ssh.host, remote_archive_path, archive_path
);

let scp_output = Command::new("bash").arg("-c").arg(&scp_command).output();

if let Err(e) = scp_output {
log::error!("Failed to run SCP command: {}", e);
return;
}

let scp_output = scp_output.unwrap();
if !scp_output.status.success() {
log::error!(
"Error during SCP: {}",
String::from_utf8_lossy(&scp_output.stderr)
);
return;
}

println!(
"\tTarball successfully copied to local path {:?}.",
archive_path
);

// Step 3: Optionally clean up the remote tarball
let ssh_cleanup_command = format!(
"sshpass -p '{}' ssh {}@{} \"rm -f {}\"",
self.ssh.password, self.ssh.user, self.ssh.host, remote_archive_path
);

let cleanup_output = Command::new("bash")
.arg("-c")
.arg(&ssh_cleanup_command)
.output();

if let Err(e) = cleanup_output {
log::warn!("Failed to clean up remote tarball: {}", e);
} else {
let cleanup_output = cleanup_output.unwrap();
if !cleanup_output.status.success() {
log::warn!(
"Error during remote cleanup: {}",
String::from_utf8_lossy(&cleanup_output.stderr)
);
} else {
println!("\tRemote tarball cleaned up successfully.");
}
}
}

fn archive(&self) {
if self.ssh.enabled {
if self.multiple_runs {
for run_no in self.min_run..=self.max_run {
self.run_archive_ssh(run_no);
}
} else {
self.run_archive_ssh(self.min_run);
}
} else if self.multiple_runs {
for run_no in self.min_run..=self.max_run {
self.run_archive(run_no);
}
} else {
self.run_archive(self.min_run);
}
}

pub fn ui(&mut self, ui: &mut egui::Ui) {
ui.horizontal(|ui| {
ui.label(
egui::RichText::new("Archivist")
.color(egui::Color32::LIGHT_BLUE)
.size(18.0),
);
ui.checkbox(&mut self.ssh.enabled, "SSH enabled");
});

ui.horizontal(|ui| {
if self.ssh.enabled {
ui.horizontal(|ui| {
ui.label("SSH:");
ui.add(egui::TextEdit::singleline(&mut self.ssh.user).hint_text("User"));
});
ui.label("@");
ui.add(egui::TextEdit::singleline(&mut self.ssh.host).hint_text("Host"));
ui.label(":");
}
});

if self.ssh.enabled {
ui.add(
egui::TextEdit::singleline(&mut self.ssh.password)
.hint_text("SSH password")
.password(true),
);
}

ui.horizontal(|ui| {
ui.label("Compass DAQ Folder");
ui.add(egui::TextEdit::singleline(&mut self.compass_path).clip_text(false));
ui.label("/DAQ/run_#/UNFLITERED/*.BIN");
});

ui.horizontal(|ui| {
ui.label("Local Output Folder");
ui.add(egui::TextEdit::singleline(&mut self.output_path).clip_text(false));
});

ui.horizontal(|ui| {
ui.add(egui::DragValue::new(&mut self.min_run).prefix("Min run: "));
ui.add_enabled(
self.multiple_runs,
egui::DragValue::new(&mut self.max_run).prefix("Max run: "),
);
ui.checkbox(&mut self.multiple_runs, "Multiple runs");
});

if ui.button("Archive").clicked() {
self.archive();
}
}
}
32 changes: 11 additions & 21 deletions src/evb/kinematics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,17 @@ impl KineParameters {

//Returns z-offset of focal plane in cm
fn calculate_z_offset(params: &KineParameters, nuc_map: &MassMap) -> Option<f64> {
let target = match nuc_map.get_data(&params.target_z, &params.target_a) {
Some(data) => data,
None => return None,
};

let target = nuc_map.get_data(&params.target_z, &params.target_a)?;
info!("Target: {:?}", target);
let projectile = match nuc_map.get_data(&params.projectile_z, &params.projectile_a) {
Some(data) => data,
None => return None,
};
let ejectile = match nuc_map.get_data(&params.ejectile_z, &params.ejectile_a) {
Some(data) => data,
None => return None,
};
let residual = match nuc_map.get_data(&params.get_residual_z(), &params.get_residual_a()) {
Some(data) => data,
None => return None,
};

let projectile = nuc_map.get_data(&params.projectile_z, &params.projectile_a)?;
info!("Projectile: {:?}", projectile);

let ejectile = nuc_map.get_data(&params.ejectile_z, &params.ejectile_a)?;
info!("Ejectile: {:?}", ejectile);

let residual = nuc_map.get_data(&params.get_residual_z(), &params.get_residual_a())?;
info!("Residual: {:?}", residual);

let angle_rads = params.sps_angle.to_radians();
let q_val = target.mass + projectile.mass - ejectile.mass - residual.mass;
Expand Down Expand Up @@ -150,10 +143,7 @@ fn calculate_z_offset(params: &KineParameters, nuc_map: &MassMap) -> Option<f64>
//Calculate weights for correcting focal plane position for kinematic shift
//Returns tuple of weights where should be used like xavg = x1 * result.0 + x2 * result.1
pub fn calculate_weights(params: &KineParameters, nuc_map: &MassMap) -> Option<(f64, f64)> {
let z_offset = match calculate_z_offset(params, nuc_map) {
Some(z) => z,
None => return None,
};
let z_offset = calculate_z_offset(params, nuc_map)?;
let w1 = 0.5 - z_offset / SPS_DETECTOR_WIRE_DIST;
let w2 = 1.0 - w1;
Some((w1, w2))
Expand Down
1 change: 1 addition & 0 deletions src/evb/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod archivist;
pub mod channel_data;
pub mod channel_map;
pub mod compass_data;
Expand Down
14 changes: 14 additions & 0 deletions src/ui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use eframe::egui::{self, Color32, RichText};
use eframe::App;

use super::ws::{Workspace, WorkspaceError};
use crate::evb::archivist::Archivist;
use crate::evb::channel_map::Board;
use crate::evb::compass_run::{process_runs, ProcessParams};
use crate::evb::error::EVBError;
Expand Down Expand Up @@ -49,6 +50,7 @@ impl Default for EvbAppParams {

#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum ActiveTab {
Archivist,
MainTab,
Kinematics,
ChannelMap,
Expand All @@ -68,6 +70,7 @@ pub struct EVBApp {
progress: Arc<Mutex<f32>>,

parameters: EvbAppParams,
archivist: Archivist,
rxn_eqn: String,
active_tab: ActiveTab,

Expand All @@ -89,6 +92,7 @@ impl EVBApp {
EVBApp {
progress: Arc::new(Mutex::new(0.0)),
parameters: EvbAppParams::default(),
archivist: Archivist::default(),
active_tab: ActiveTab::MainTab,
rxn_eqn: String::from("None"),
mass_map: MassMap::new().expect("Could not open amdc data, shutting down!"),
Expand Down Expand Up @@ -403,6 +407,12 @@ impl EVBApp {
fn ui_tabs(&mut self, ui: &mut egui::Ui) {
egui::TopBottomPanel::top("cebra_sps_top_panel").show_inside(ui, |ui| {
ui.horizontal(|ui| {
if ui
.selectable_label(matches!(self.active_tab, ActiveTab::Archivist), "Archivist")
.clicked()
{
self.active_tab = ActiveTab::Archivist;
}
if ui
.selectable_label(
matches!(self.active_tab, ActiveTab::MainTab),
Expand Down Expand Up @@ -449,6 +459,7 @@ impl EVBApp {
});

egui::ScrollArea::both().show(ui, |ui| match self.active_tab {
ActiveTab::Archivist => self.archivist.ui(ui),
ActiveTab::MainTab => self.main_tab_ui(ui),
ActiveTab::Kinematics => self.kinematics_ui(ui),
ActiveTab::ChannelMap => self.channel_map_ui(ui),
Expand All @@ -458,6 +469,9 @@ impl EVBApp {
}

fn progress_ui(&mut self, ui: &mut egui::Ui) {
if self.active_tab == ActiveTab::Archivist {
return;
}
egui::TopBottomPanel::bottom("cebra_sps_bottom_panel").show_inside(ui, |ui| {
ui.add(
egui::widgets::ProgressBar::new(match self.progress.lock() {
Expand Down
Loading