-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add marker plot key #31
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for your work. This is something that I am definitely interested in including.
I have left some comments on things that I am not sure how to deal with.
src/axis/plot.rs
Outdated
DiamondFilled, | ||
Pentagon, | ||
PentagonFilled, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that there are 2 variants missing here: Asterisk
and Text(String)
.
Also, do you think that it would be good to have a more explicit documentation on how each marker will look like? It could be for example:
/// Set the marker to ⊕.
OPlus,
/// Same as `[Marker::OPlus]` but filled with a color.
OplusFilled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great suggestion, will do :)
src/axis/plot.rs
Outdated
#[derive(Clone, Debug)] | ||
pub enum MarkerOption { | ||
Scale(f32), | ||
Fill(String), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that using a String
to define a color is as much of a hack as using the PlotKey::Custom
.
What do you think about something like (with a better naming):
// See complete list in section 4.6.4 of the PGFPlots manual version 1.4.1
pub enum PredefinedColor {
Red,
Green,
....,
Violet,
}
struct Color {
// A way to mix colors...
// We could have a constructor from `PredefinedColor`
// Other constructor that does e.g. `red!20!white`
// And another constructor that does e.g. `rgb,255:red,231;green,84;blue,121`
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, I will look into this. What do you think of using the crate strum
for an easy Display
derive for enums? We can do something like this:
#[derive(Clone, Copy, Debug, strum::Display)]
#[strum(serialize_all = "lowercase")]
pub enum PredefinedColor {
Red, // "red"
Green, // "green"
Blue, // ...
Cyan,
Magenta,
Yellow,
Black,
Gray,
White,
Darkgray,
Lightgray,
Brown,
Lime,
Olive,
Orange,
Pink,
Purple,
Teal,
Violet,
}
42b15a4
to
6310a52
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, thanks again for your continued work here, I am very happy with the direction we are going.
I have left some comments and some notes to myself.
src/axis/plot.rs
Outdated
@@ -6,6 +8,10 @@ use std::fmt; | |||
#[allow(unused_imports)] | |||
use crate::{Axis, Picture}; | |||
|
|||
use self::color::Color; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self:
Maybe this could be pub use
instead. Not sure though.
It could also even be pub use
in the root lib.rs
(?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opininion pub use
inside src/axis/plot.rs
seems logical, as the user can reference color via use pgfplots::axis::plot::Color
right? If you want to restrict the usage of this color to plots only, this would be the way to go I guess. If not just tell me and I'm happy to shift things around :)
|
||
impl Marker { | ||
pub fn new(shape: MarkShape, options: Vec<MarkOption>) -> Self { | ||
Self { shape, options } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could do something similar to what happens in Plot2D::add_key to get rid of duplicate keys (by discriminant).
The behavior of the plot is exactly the same, but the standalone_string()
is just cleaner if we don't re-write keys that are going to get overwritten anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean duplicate keys inside the Vec<MarkOption>
input or generally speaking duplicate Marker
s in the plot styling?
src/axis/plot.rs
Outdated
#[derive(Clone, Debug, Display)] | ||
pub enum MarkShape { | ||
/// Set the marker to ⃝. | ||
#[strum(serialize = "o")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking through strum
s docs, it looks like we could just add #[strum(serialize_all = "lowercase")]
and then just overwrite the filled variants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, that's a good point. I removed unnecessary macros.
|
||
/// Control the color and scaling of markers. | ||
#[derive(Clone, Debug)] | ||
pub enum MarkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self:
Unless I find a source for all possible MarkOptions
, this enum should be non_exhaustive
(this allows to add more variants without needing a major version bump).
If I don't find a list with all options (this is the most likely scenario), add at least the XScale(f64)
and YScale(f64)
variants. I will look through some more of my plots to see what other weird keys I have used before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the non_exhaustive
macro and those two specific options.
src/axis/plot/color.rs
Outdated
} | ||
|
||
impl Color { | ||
pub fn from_predefined(predefined_color: PredefinedColor) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could replace this method by impl From<PredefinedColor> for Color
. Or we could have both, where one just calls the other; I am OK with ether way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced it, thanks for the suggestion!
src/axis/plot/color.rs
Outdated
pub fn from_mix(mix: Vec<(PredefinedColor, u8)>) -> Self { | ||
let color_mix = mix | ||
.into_iter() | ||
.map(|(color, percentage)| format!("{color}!{percentage}!")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested this, and I don't think it does exactly what one would expect (at least it threw me off a little bit). You can try the following plot:
\documentclass{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
]
\addplot[mark=*, fill=red] coordinates {(0,0.92) (1,0.92)};
\addplot[mark=*, fill=red!70!white] coordinates {(0,0.72) (1,0.72)};
\addplot[mark=*, fill=red!70!white!30!] coordinates {(0,0.42) (1,0.42)};
\end{axis}
\end{tikzpicture}
\end{document}
You can see how red!70!white
which is 70% red and 30% white, is different from the red!70!white!30!
that this code generates.
Maybe it is more clear if we have the from_mix
method to output the format:
{rgb:<Color_1>,<weight_1>;...;<Color_N>,<weight_N>}
which surprisingly works with any color combination, not just Red
, Green
, and Blue
. We could make it even work with already mixed colors.
Something like:
fn from_mix<I, C>(colors: I) -> Self
where
C: Into<Self>,
I: impl IntoIterator<Item=(C, u8)>
{
let mut result = String::new();
result.push_str("rbg:");
for (color, num) in vec {
let color = Color::from(color);
result.push_str(&color.to_string());
result.push(',');
result.push_str(&num.to_string());
result.push(';');
}
result.pop(); // Remove the trailing semicolon
result
}
Using the above with vec![(Red, 70), (White, 30)]
produces the correct color.
It also has the benefit that it is easier to document the u8
s as "weights" rather than "percentages" (given that we won't be checking user input to add to 100%)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :)
#[strum(serialize = "pentagon*")] | ||
PentagonFilled, | ||
/// Set the marker to specified text. | ||
Text(String), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self:
Should this be #[strum(disabled)]
given that you are handling this case explicitly in the Marker
's Display
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True!
88ace36
to
f56e178
Compare
f56e178
to
02c65dd
Compare
02c65dd
to
a6f68f6
Compare
Hey! First things first, I really enjoyed working with this crate! Thanks for your effort.
This PR adds another
PlotKey
, namely themark=...
key. I had the following problem:I wanted to add multiple plots to one graph, but by default all points of the plots had the same symbol:
While I was able to use your
PlotKey::Custom(...)
to achieve my desired output below, I quickly found myself adding an own enum for this and thought that your crate would benefit of it as well.Desired output:
Additionally I added
MarkerOption
to set themark options=...
key. This way we can control the color and the scaling of a marker:What do you think about adding this to your crate? If you approve I'm happy to add this to your documentation! :)