mirror of
https://gitlab.cern.ch/wotsubo/psboard-qaqc-postprocess.git
synced 2025-07-02 01:29:28 +09:00
new: CSV output
This commit is contained in:
parent
a14eb4ea48
commit
eff62d7f09
5 changed files with 368 additions and 36 deletions
149
src/main.rs
149
src/main.rs
|
@ -1,10 +1,9 @@
|
|||
use core::{panic, str};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{BufRead, BufReader, Write},
|
||||
io::{BufRead, BufReader},
|
||||
path::{self, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
|
@ -15,17 +14,8 @@ use clap::Parser;
|
|||
use log::{debug, error, info, trace, warn};
|
||||
use regex::Regex;
|
||||
use semver::Version;
|
||||
|
||||
fn get_default_output_path() -> PathBuf {
|
||||
PathBuf::from_str("outpu.csv").expect("Error")
|
||||
}
|
||||
fn get_default_log_path() -> PathBuf {
|
||||
let mut path = env::current_exe().unwrap();
|
||||
path.pop();
|
||||
path.push("log");
|
||||
path.push("debug.log");
|
||||
path
|
||||
}
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, DisplayFromStr};
|
||||
|
||||
/// Parse master jathub logfile for PS Board QAQC and write out to CSV.
|
||||
#[derive(Parser, Debug)]
|
||||
|
@ -145,7 +135,7 @@ impl FromStr for PsbId {
|
|||
/// Temporary stores raw values.
|
||||
/// TODO: specify each filed types.(maybe multi values)
|
||||
#[derive(Debug)]
|
||||
struct BoardResult {
|
||||
struct MasterBoardResult {
|
||||
id: PsbId,
|
||||
qspif: u8,
|
||||
qspip: u8,
|
||||
|
@ -158,11 +148,12 @@ struct BoardResult {
|
|||
|
||||
/// Full result for a single QAQC run from a log file on JATHub master.
|
||||
#[derive(Debug)]
|
||||
struct MasterLogResult {
|
||||
pub struct MasterLogResult {
|
||||
version: Version,
|
||||
datetime: DateTime<Utc>,
|
||||
shifter: String,
|
||||
board_results: HashMap<Position, BoardResult>,
|
||||
board_results: HashMap<Position, MasterBoardResult>,
|
||||
filename: String,
|
||||
}
|
||||
|
||||
/// Get version of shift script.
|
||||
|
@ -193,7 +184,7 @@ fn extract_position_id(line: &str) -> Result<(Position, PsbId)> {
|
|||
|
||||
impl MasterLogResult {
|
||||
/// Parse log file on master jathub.
|
||||
fn parse_file(file: impl BufRead) -> Result<MasterLogResult> {
|
||||
fn parse_file(file: impl BufRead, filename: String) -> Result<MasterLogResult> {
|
||||
let mut lines = file.lines();
|
||||
|
||||
let version = {
|
||||
|
@ -322,7 +313,7 @@ impl MasterLogResult {
|
|||
.context(format!("No board on pos {}", pos))?
|
||||
.clone();
|
||||
|
||||
let result = BoardResult {
|
||||
let result = MasterBoardResult {
|
||||
id: psbid,
|
||||
qspif: parts
|
||||
.get(1)
|
||||
|
@ -370,17 +361,70 @@ impl MasterLogResult {
|
|||
datetime,
|
||||
shifter,
|
||||
board_results,
|
||||
filename,
|
||||
})
|
||||
}
|
||||
|
||||
fn write(&self, f: impl Write) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn check_csv_header(f: impl BufRead) -> Result<()> {
|
||||
// f.lines()
|
||||
todo!()
|
||||
/// All information on QAQC stored in the database.
|
||||
///
|
||||
/// Everything without `Option` is available from master log.
|
||||
///
|
||||
/// TODO: use pos? shifter? version?
|
||||
#[serde_as]
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct PsbQaqcResult {
|
||||
motherboard_id: u32,
|
||||
daughterboard_id: Option<u32>,
|
||||
#[serde_as(as = "DisplayFromStr")]
|
||||
position: Position,
|
||||
qspif: u8,
|
||||
qspip: u8,
|
||||
recov: u8,
|
||||
clock: u8,
|
||||
regac: u8,
|
||||
asdtp: u8,
|
||||
qaqc_result: u32,
|
||||
lvds_tx_skew: Option<u32>,
|
||||
ppl_lock_reset_count: Option<i32>,
|
||||
timestamp: DateTime<Utc>,
|
||||
qaqc_log_file: String,
|
||||
firmware_ver: Option<Version>,
|
||||
parameter_ver: Option<Version>,
|
||||
fpga_dna: Option<u64>,
|
||||
comment: String,
|
||||
}
|
||||
|
||||
impl PsbQaqcResult {
|
||||
/// Expand [`MasterLogResult`] to [`PsbQaqcResult`].
|
||||
/// Filling unavailable fileds with [`None`]s.
|
||||
pub fn from_masterlogresult(result: MasterLogResult) -> Vec<Self> {
|
||||
let mut converted = vec![];
|
||||
for (pos, boardresult) in result.board_results {
|
||||
let new = PsbQaqcResult {
|
||||
motherboard_id: boardresult.id.id,
|
||||
daughterboard_id: None,
|
||||
position: pos,
|
||||
qspif: boardresult.qspif,
|
||||
qspip: boardresult.qspip,
|
||||
recov: boardresult.recov,
|
||||
clock: boardresult.clock,
|
||||
regac: boardresult.regac,
|
||||
asdtp: boardresult.asdtp,
|
||||
qaqc_result: boardresult.done.into(),
|
||||
lvds_tx_skew: None,
|
||||
ppl_lock_reset_count: None,
|
||||
timestamp: result.datetime,
|
||||
qaqc_log_file: result.filename.clone(),
|
||||
firmware_ver: None,
|
||||
parameter_ver: None,
|
||||
fpga_dna: None,
|
||||
comment: "".to_string(),
|
||||
};
|
||||
converted.push(new);
|
||||
}
|
||||
converted
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
|
@ -397,9 +441,17 @@ fn main() -> Result<()> {
|
|||
);
|
||||
|
||||
let result = {
|
||||
let file = File::open(args.master_log)?;
|
||||
let file = File::open(args.master_log.clone())?;
|
||||
let reader = BufReader::new(file);
|
||||
MasterLogResult::parse_file(reader)?
|
||||
MasterLogResult::parse_file(
|
||||
reader,
|
||||
args.master_log
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
)?
|
||||
};
|
||||
debug!("{:?}", result);
|
||||
|
||||
|
@ -407,8 +459,36 @@ fn main() -> Result<()> {
|
|||
// let file = File::options()
|
||||
// .read(true)
|
||||
// .open(args.outfile)?;
|
||||
// }
|
||||
//
|
||||
// let mut rdr = csv::Reader::from_reader(file);
|
||||
// rdr.records();
|
||||
// }
|
||||
|
||||
let expanded_results = PsbQaqcResult::from_masterlogresult(result);
|
||||
|
||||
let mut wtr = match args.outfile.exists() {
|
||||
true => {
|
||||
let file = File::options().read(true).append(true).open(args.outfile)?;
|
||||
csv::WriterBuilder::new()
|
||||
.has_headers(false)
|
||||
.from_writer(file)
|
||||
}
|
||||
false => {
|
||||
println!("Creating new file: {}", args.outfile.display());
|
||||
let file = File::options()
|
||||
.create_new(true)
|
||||
.write(true)
|
||||
.open(args.outfile)?;
|
||||
csv::WriterBuilder::new()
|
||||
.has_headers(true)
|
||||
.from_writer(file)
|
||||
}
|
||||
};
|
||||
for result in expanded_results {
|
||||
wtr.serialize(result)?;
|
||||
}
|
||||
wtr.flush()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -417,8 +497,11 @@ mod test {
|
|||
use std::str::FromStr;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use semver::Version;
|
||||
|
||||
use crate::{extract_position_id, extract_shifter_line, Position, PositionLayer, PsbId};
|
||||
use crate::{
|
||||
extract_position_id, extract_shifter_line, extract_version, Position, PositionLayer, PsbId,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn parse_position() {
|
||||
|
@ -454,6 +537,14 @@ mod test {
|
|||
assert!(DateTime::parse_from_str("Date: 2024-06-20T08:42:01+0000", "Date: %+").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_version() {
|
||||
assert_eq!(
|
||||
extract_version("Shift script: 1.0.0").unwrap(),
|
||||
Version::new(1, 0, 0)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_shifter_line() {
|
||||
assert_eq!(extract_shifter_line("Shifters: foo").unwrap(), "foo");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue