use std::path::PathBuf;
use clap::Parser;
use rapid_structure_rs::TableOcrResolution;
use rapid_structure_rs::evaluation::table::run::{
DEFAULT_MODEL_RELATIVE, TableContentSource, TableEvalConfig, TableEvalEvent,
run_table_evaluation,
};
#[derive(Debug, Parser)]
#[command(
name = "table_eval",
about = "Run the table-structure model over TabRecSet val and emit TEDS predictions"
)]
struct Cli {
#[arg(long, default_value = "datasets/table/tabrecset")]
dataset: PathBuf,
#[arg(long, default_value = DEFAULT_MODEL_RELATIVE)]
model: PathBuf,
#[arg(long, default_value = "Temp/table-pred-val.json")]
predictions: PathBuf,
#[arg(long, default_value = "Temp/table-report-val.json")]
report: PathBuf,
#[arg(long, default_value_t = 0)]
limit: usize,
#[arg(long, default_value_t = 488)]
side_len: usize,
#[arg(long)]
no_fix_shape: bool,
#[arg(long)]
intra_threads: Option<usize>,
#[arg(long)]
fail_fast: bool,
#[arg(
long,
default_value = "structure-only",
value_parser = ["structure-only", "page-reuse", "crop-control"]
)]
content: String,
#[arg(long)]
ocr_config: Option<PathBuf>,
#[arg(long)]
ocr_cache: Option<PathBuf>,
#[arg(long, default_value_t = TableOcrResolution::default().limit_side_len)]
ocr_limit_side_len: usize,
#[arg(long, default_value_t = TableOcrResolution::default().limit_type, value_parser = ["min", "max"])]
ocr_limit_type: String,
#[arg(long, default_value_t = TableOcrResolution::default().max_side_len)]
ocr_max_side_len: usize,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let content = match cli.content.as_str() {
"page-reuse" => TableContentSource::PageReuse {
config: cli.ocr_config,
cache: cli.ocr_cache,
},
"crop-control" => TableContentSource::CropControl {
config: cli.ocr_config,
},
_ => TableContentSource::StructureOnly,
};
let config = TableEvalConfig {
dataset: cli.dataset,
model: cli.model,
predictions: cli.predictions,
limit: cli.limit,
side_len: cli.side_len,
fix_input_shape: !cli.no_fix_shape,
intra_threads: cli.intra_threads,
fail_fast: cli.fail_fast,
content,
ocr_resolution: TableOcrResolution {
limit_side_len: cli.ocr_limit_side_len,
limit_type: cli.ocr_limit_type,
max_side_len: cli.ocr_max_side_len,
},
};
let outcome = run_table_evaluation(&config, &mut |event| match event {
TableEvalEvent::Message(text) => eprintln!("{text}"),
TableEvalEvent::Progress { done, total } => eprintln!(" {done}/{total}"),
})?;
if let Some(parent) = cli.report.parent()
&& !parent.as_os_str().is_empty()
{
std::fs::create_dir_all(parent)?;
}
std::fs::write(&cli.report, serde_json::to_vec_pretty(&outcome.report)?)?;
eprintln!(
"wrote {} ({} selected, {} failed)",
cli.report.display(),
outcome.selected,
outcome.failed
);
eprintln!(
"score it with: python tools/table_teds.py --true {} --pred {}{}",
rapid_structure_rs::evaluation::table::DEFAULT_GT_HTML_RELATIVE,
config.predictions.display(),
if config.content.uses_engine() {
""
} else {
" --structure-only"
}
);
Ok(())
}