Skip to content

Commit c00f238

Browse files
committed
Enable specifying colors for contours
1 parent ef648b8 commit c00f238

File tree

1 file changed

+49
-11
lines changed

1 file changed

+49
-11
lines changed

src/lib.rs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ impl Axes {
439439
/// # Example
440440
///
441441
/// ```
442-
/// use matplotlib as plt;
442+
/// use matplotlib::{self as plt, colors::Tab};
443443
/// use ndarray::{Array1, Array2};
444444
/// let x: Array1<f64> = Array1::linspace(-1., 1., 30);
445445
/// let y: Array1<f64> = Array1::linspace(-1., 1., 30);
@@ -452,6 +452,7 @@ impl Axes {
452452
/// let (fig, [[mut ax]]) = plt::subplots()?;
453453
/// ax.contour(x.as_slice().unwrap(), y.as_slice().unwrap(), &z)
454454
/// .levels(&[0.2, 0.5, 0.8])
455+
/// .colors(&[Tab::Red, Tab::Blue, Tab::Olive])
455456
/// .plot();
456457
/// fig.save().to_file("target/contour.pdf")?;
457458
/// # Ok::<(), matplotlib::Error>(())
@@ -465,6 +466,7 @@ impl Axes {
465466
options: PlotOptions::new(),
466467
x, y, z,
467468
levels: None,
469+
colors: None,
468470
}
469471
}
470472

@@ -496,6 +498,7 @@ impl Axes {
496498
n1: 100,
497499
n2: 100,
498500
levels: None,
501+
colors: None,
499502
}
500503
}
501504

@@ -883,6 +886,45 @@ macro_rules! set_contour_options { () => {
883886
self.levels = Some(levels);
884887
self
885888
}
889+
890+
pub fn colors<C: Color>(mut self, colors: impl AsRef<[C]>) -> Self {
891+
let colors = colors.as_ref();
892+
let mut rgbas = Vec::with_capacity(colors.len());
893+
for c in colors {
894+
rgbas.push(c.rgba());
895+
}
896+
self.colors = Some(rgbas);
897+
self
898+
}
899+
900+
fn update_dict(&self, d: &mut Bound<PyDict>) {
901+
let py = d.py();
902+
if let Some(levels) = self.levels {
903+
let n = levels.len();
904+
let levels = levels.to_pyarray_bound(py);
905+
d.set_item("levels", levels).unwrap();
906+
907+
if let Some(colors) = &self.colors {
908+
if colors.len() >= n {
909+
let colors = PyList::new_bound(py, colors);
910+
d.set_item("colors", colors).unwrap();
911+
} else {
912+
let default = self.options.color.unwrap_or([0.,0.,0.,1.]);
913+
let mut colors = colors.clone();
914+
for _ in 0 .. n - colors.len() {
915+
colors.push(default);
916+
}
917+
let colors = PyList::new_bound(py, colors);
918+
d.set_item("colors", colors).unwrap();
919+
}
920+
} else if let Some(color) = self.options.color {
921+
// let colors = std::iter::repeat_n(color, n);
922+
let colors = vec![color; n];
923+
let colors = PyList::new_bound(py, colors);
924+
d.set_item("colors", colors).unwrap();
925+
}
926+
}
927+
}
886928
}}
887929

888930
#[must_use]
@@ -893,6 +935,7 @@ pub struct Contour<'a, D> {
893935
y: D,
894936
z: &'a ndarray::Array2<f64>,
895937
levels: Option<&'a [f64]>,
938+
colors: Option<Vec<[f64; 4]>>,
896939
}
897940

898941
impl<'a, D> Contour<'a, D>
@@ -905,11 +948,8 @@ where D: AsRef<[f64]> {
905948
let x = self.x.as_ref().to_pyarray_bound(py);
906949
let y = self.y.as_ref().to_pyarray_bound(py);
907950
let z = self.z.to_pyarray_bound(py);
908-
let opt = self.options.kwargs(py);
909-
if let Some(levels) = self.levels {
910-
let levels = levels.to_pyarray_bound(py);
911-
opt.set_item("levels", levels).unwrap();
912-
}
951+
let mut opt = self.options.kwargs(py);
952+
self.update_dict(&mut opt);
913953
let contours = self.axes.ax
914954
.call_method_bound(py, intern!(py, "contour"),
915955
(x, y, z),
@@ -931,6 +971,7 @@ pub struct ContourFun<'a, F> {
931971
n1: usize, // FIXME: want to be more versatile than an equispaced grid?
932972
n2: usize,
933973
levels: Option<&'a [f64]>,
974+
colors: Option<Vec<[f64; 4]>>,
934975
}
935976

936977
impl<'a, F> ContourFun<'a, F>
@@ -961,11 +1002,8 @@ where F: FnMut(f64, f64) -> f64 {
9611002
let x = x.to_pyarray_bound(py);
9621003
let y = y.to_pyarray_bound(py);
9631004
let z = z.to_pyarray_bound(py);
964-
let opt = self.options.kwargs(py);
965-
if let Some(levels) = self.levels {
966-
let levels = levels.to_pyarray_bound(py);
967-
opt.set_item("levels", levels).unwrap();
968-
}
1005+
let mut opt = self.options.kwargs(py);
1006+
self.update_dict(&mut opt);
9691007
let contours = self.axes.ax
9701008
.call_method_bound(py, intern!(py, "contour"),
9711009
(x, y, z),

0 commit comments

Comments
 (0)