Skip to content

Commit 8add20a

Browse files
authored
Merge pull request #23 from rpl-cmu/easton/printing
Printing Upgrades
2 parents 34a6964 + 6da53e5 commit 8add20a

File tree

19 files changed

+562
-126
lines changed

19 files changed

+562
-126
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ paste = "1.0.15"
2525
downcast-rs = "1.2.1"
2626
log = "0.4.22"
2727
factrs-proc = { version = "0.1.0", path = "./factrs-proc" }
28+
pad-adapter = "0.1.1"
2829

2930
# numerical
3031
faer = { version = "0.19.4", default-features = false, features = [

examples/serde.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn main() {
2424

2525
// Convert the JSON string back to a Point.
2626
let deserialized: Values = serde_json::from_str(&serialized).unwrap();
27-
println!("deserialized = {:#?}", deserialized);
27+
println!("deserialized = {:#}", deserialized);
2828

2929
// ------------------------- Serialize graph ------------------------- //
3030
let prior = PriorResidual::new(x);

src/containers/factor.rs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use super::{Symbol, TypedSymbol};
1+
use pad_adapter::PadAdapter;
2+
3+
use super::{DefaultSymbolHandler, KeyFormatter, Symbol, TypedSymbol};
24
use crate::{
35
containers::{Key, Values},
46
dtype,
@@ -9,6 +11,11 @@ use crate::{
911
robust::{RobustCost, L2},
1012
};
1113

14+
use std::{
15+
fmt::{self, Write},
16+
marker::PhantomData,
17+
};
18+
1219
/// Main structure to represent a factor in the graph.
1320
///
1421
/// $$ \blue{\rho_i}(||\purple{r_i}(\green{\Theta})||_{\red{\Sigma_i}} ) $$
@@ -48,7 +55,6 @@ use crate::{
4855
/// let factor = FactorBuilder::new1(residual,
4956
/// X(0)).noise(noise).robust(robust).build();
5057
/// ```
51-
#[derive(Debug)]
5258
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5359
pub struct Factor {
5460
keys: Vec<Key>,
@@ -107,6 +113,69 @@ impl Factor {
107113
}
108114
}
109115

116+
impl fmt::Debug for Factor {
117+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118+
FactorFormatter::<DefaultSymbolHandler>::new(self).fmt(f)
119+
}
120+
}
121+
122+
/// Formatter for a factor
123+
///
124+
/// Specifically, this can be used if custom symbols are desired. See `tests/custom_key` for examples.
125+
pub struct FactorFormatter<'f, KF> {
126+
factor: &'f Factor,
127+
kf: PhantomData<KF>,
128+
}
129+
130+
impl<'f, KF> FactorFormatter<'f, KF> {
131+
pub fn new(factor: &'f Factor) -> Self {
132+
Self {
133+
factor,
134+
kf: Default::default(),
135+
}
136+
}
137+
}
138+
139+
impl<'f, KF: KeyFormatter> fmt::Debug for FactorFormatter<'f, KF> {
140+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141+
if f.alternate() {
142+
f.write_str("Factor {\n")?;
143+
let mut pad = PadAdapter::new(f);
144+
// Keys
145+
pad.write_str("key: [")?;
146+
for (i, key) in self.factor.keys().iter().enumerate() {
147+
if i > 0 {
148+
pad.write_str(", ")?;
149+
}
150+
KF::fmt(&mut pad, *key)?;
151+
}
152+
pad.write_str("]\n")?;
153+
// Residual
154+
writeln!(pad, "res: {:#?}", self.factor.residual)?;
155+
// Noise
156+
writeln!(pad, "noi: {:#?}", self.factor.noise)?;
157+
// Robust
158+
writeln!(pad, "rob: {:#?}", self.factor.robust)?;
159+
f.write_str("}")?;
160+
} else {
161+
f.write_str("Factor { ")?;
162+
for (i, key) in self.factor.keys().iter().enumerate() {
163+
if i > 0 {
164+
f.write_str(", ")?;
165+
}
166+
KF::fmt(f, *key)?;
167+
}
168+
write!(
169+
f,
170+
"], residual: {:?}, noise: {:?}, robust: {:?} }}",
171+
self.factor.residual, self.factor.noise, self.factor.robust
172+
)?;
173+
}
174+
175+
Ok(())
176+
}
177+
}
178+
110179
/// Builder for a factor.
111180
///
112181
/// If the noise model or robust kernel aren't set, they default to [UnitNoise]

src/containers/graph.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1+
use pad_adapter::PadAdapter;
2+
use std::{
3+
fmt::{Debug, Write},
4+
marker::PhantomData,
5+
};
6+
7+
// Once "debug_closure_helpers" is stabilized, we won't need this anymore
8+
// Need custom debug to handle pretty key printing at the moment
9+
// Pad adapter helps with the pretty printing
10+
use crate::containers::factor::FactorFormatter;
11+
112
use faer::sparse::SymbolicSparseColMat;
213

3-
use super::{Idx, Values, ValuesOrder};
14+
use super::{DefaultSymbolHandler, Idx, KeyFormatter, Values, ValuesOrder};
415
use crate::{containers::Factor, dtype, linear::LinearGraph};
516

617
/// Structure to represent a nonlinear factor graph
@@ -27,7 +38,7 @@ use crate::{containers::Factor, dtype, linear::LinearGraph};
2738
/// let mut graph = Graph::new();
2839
/// graph.add_factor(factor);
2940
/// ```
30-
#[derive(Default, Debug)]
41+
#[derive(Default)]
3142
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3243
pub struct Graph {
3344
factors: Vec<Factor>,
@@ -97,6 +108,48 @@ impl Graph {
97108
}
98109
}
99110

111+
impl Debug for Graph {
112+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113+
GraphFormatter::<DefaultSymbolHandler>::new(self).fmt(f)
114+
}
115+
}
116+
117+
/// Formatter for a graph
118+
///
119+
/// Specifically, this can be used if custom symbols are desired. See `tests/custom_key` for examples.
120+
pub struct GraphFormatter<'g, KF> {
121+
graph: &'g Graph,
122+
kf: PhantomData<KF>,
123+
}
124+
125+
impl<'g, KF> GraphFormatter<'g, KF> {
126+
pub fn new(graph: &'g Graph) -> Self {
127+
Self {
128+
graph,
129+
kf: Default::default(),
130+
}
131+
}
132+
}
133+
134+
impl<'g, KF: KeyFormatter> Debug for GraphFormatter<'g, KF> {
135+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136+
if f.alternate() {
137+
f.write_str("Graph [\n")?;
138+
let mut pad = PadAdapter::new(f);
139+
for factor in self.graph.factors.iter() {
140+
writeln!(pad, "{:#?},", FactorFormatter::<KF>::new(factor))?;
141+
}
142+
f.write_str("]")
143+
} else {
144+
f.write_str("Graph [ ")?;
145+
for factor in self.graph.factors.iter() {
146+
write!(f, "{:?}, ", FactorFormatter::<KF>::new(factor))?;
147+
}
148+
f.write_str("]")
149+
}
150+
}
151+
}
152+
100153
/// Simple structure to hold the order of the graph
101154
///
102155
/// Specifically this is used to cache linearization results such as the order

src/containers/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
//! Various containers for storing variables, residuals, factors, etc.
22
33
mod symbol;
4-
pub use symbol::{DefaultSymbol, Key, Symbol, TypedSymbol};
4+
pub use symbol::{DefaultSymbolHandler, Key, KeyFormatter, Symbol, TypedSymbol};
55

66
mod values;
7-
pub use values::Values;
7+
pub use values::{Values, ValuesFormatter};
88

99
mod order;
1010
pub use order::{Idx, ValuesOrder};
1111

1212
mod graph;
13-
pub use graph::{Graph, GraphOrder};
13+
pub use graph::{Graph, GraphFormatter, GraphOrder};
1414

1515
mod factor;
16-
pub use factor::{Factor, FactorBuilder};
16+
pub use factor::{Factor, FactorBuilder, FactorFormatter};

0 commit comments

Comments
 (0)