Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/test_on_arch_linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Test
on: [pull_request]
jobs:
test_on_arch_linux:
runs-on: ubuntu-latest
container:
image: archlinux:latest
steps:
- uses: actions/checkout@v4
- name: Install Libraries and Rust
run: |
pacman -Syu --noconfirm python-matplotlib rust cargo
- name: Run tests
run: |
cargo test -- --nocapture
6 changes: 2 additions & 4 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
/// For example a circle will show as a circle in the screen and not an ellipse. This function also handles
/// the 3D case which is a little tricky with Matplotlib. In this case (3D), the version of Matplotlib
/// must be greater than 3.3.0.
pub const PYTHON_HEADER: &str = "### file generated by the 'plotpy' Rust crate

import numpy as np
pub const PYTHON_HEADER: &str = "import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tck
import matplotlib.patches as pat
Expand Down Expand Up @@ -152,6 +150,6 @@ mod tests {

#[test]
fn constants_are_correct() {
assert_eq!(PYTHON_HEADER.len(), 2975);
assert_eq!(PYTHON_HEADER.len(), 2928);
}
}
21 changes: 6 additions & 15 deletions src/fileio.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{StrError, PYTHON_HEADER};
use super::StrError;
use std::fs;
use std::fs::File;
use std::io::Write;
Expand All @@ -12,10 +12,6 @@ use std::process::Command;
/// * `python_commands` - Python commands to be written to file
/// * `output_dir` - Output directory to be created
/// * `filename_py` - Filename with extension .py
///
/// # Note
///
/// The contents of [PYTHON_HEADER] are added at the beginning of the file.
pub(crate) fn call_python3(python_exe: &str, python_commands: &String, path: &Path) -> Result<String, StrError> {
// create directory
if let Some(p) = path.parent() {
Expand All @@ -24,7 +20,6 @@ pub(crate) fn call_python3(python_exe: &str, python_commands: &String, path: &Pa

// combine header with commands
let mut contents = String::new();
contents.push_str(PYTHON_HEADER);
contents.push_str(python_commands);

// write file
Expand Down Expand Up @@ -59,7 +54,7 @@ pub(crate) fn call_python3(python_exe: &str, python_commands: &String, path: &Pa

#[cfg(test)]
mod tests {
use super::{call_python3, PYTHON_HEADER};
use super::call_python3;
use std::fs;
use std::path::Path;

Expand All @@ -71,8 +66,7 @@ mod tests {
let path = Path::new("call_python3_works.py");
let output = call_python3("python3", &commands, &path).unwrap();
let data = fs::read_to_string(&path).map_err(|_| "cannot read test file").unwrap();
let mut correct = String::from(PYTHON_HEADER);
correct.push_str(&commands);
let correct = "print(\"Python says: Hello World!\")".to_string();
assert_eq!(data, correct);
assert_eq!(output, "Python says: Hello World!\n");
}
Expand All @@ -83,8 +77,7 @@ mod tests {
let path = Path::new(OUT_DIR).join("call_python3_works.py");
let output = call_python3("python3", &commands, &path).unwrap();
let data = fs::read_to_string(&path).map_err(|_| "cannot read test file").unwrap();
let mut correct = String::from(PYTHON_HEADER);
correct.push_str(&commands);
let correct = "print(\"Python says: Hello World!\")".to_string();
assert_eq!(data, correct);
assert_eq!(output, "Python says: Hello World!\n");
}
Expand All @@ -96,16 +89,14 @@ mod tests {
let commands_first = "print(\"Python says: Hello World!\")".to_string();
let output_first = call_python3("python3", &commands_first, &path).unwrap();
let data_first = fs::read_to_string(&path).map_err(|_| "cannot read test file").unwrap();
let mut correct_first = String::from(PYTHON_HEADER);
correct_first.push_str(&commands_first);
let correct_first = "print(\"Python says: Hello World!\")".to_string();
assert_eq!(data_first, correct_first);
assert_eq!(output_first, "Python says: Hello World!\n");
// second
let commands_second = "print(\"Python says: Hello World! again\")".to_string();
let output_second = call_python3("python3", &commands_second, &path).unwrap();
let data_second = fs::read_to_string(&path).map_err(|_| "cannot read test file").unwrap();
let mut correct_second = String::from(PYTHON_HEADER);
correct_second.push_str(&commands_second);
let correct_second = "print(\"Python says: Hello World! again\")".to_string();
assert_eq!(data_second, correct_second);
assert_eq!(output_second, "Python says: Hello World! again\n");
}
Expand Down
39 changes: 26 additions & 13 deletions src/plot.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{call_python3, generate_list_quoted, vector_to_array, AsVector, Legend, StrError, SuperTitleParams};
use crate::PYTHON_HEADER;
use num_traits::Num;
use std::ffi::OsStr;
use std::fmt::Write;
Expand Down Expand Up @@ -563,37 +564,37 @@ impl Plot {

/// Sets minimum x
pub fn set_xmin(&mut self, xmin: f64) -> &mut Self {
write!(&mut self.buffer, "plt.gca().set_xlim([{},None])\n", xmin).unwrap();
write!(&mut self.buffer, "plt.gca().set_xlim(left={})\n", xmin).unwrap();
self
}

/// Sets maximum x
pub fn set_xmax(&mut self, xmax: f64) -> &mut Self {
write!(&mut self.buffer, "plt.gca().set_xlim([None,{}])\n", xmax).unwrap();
write!(&mut self.buffer, "plt.gca().set_xlim(right={})\n", xmax).unwrap();
self
}

/// Sets minimum y
pub fn set_ymin(&mut self, ymin: f64) -> &mut Self {
write!(&mut self.buffer, "plt.gca().set_ylim([{},None])\n", ymin).unwrap();
write!(&mut self.buffer, "plt.gca().set_ylim(bottom={})\n", ymin).unwrap();
self
}

/// Sets maximum y
pub fn set_ymax(&mut self, ymax: f64) -> &mut Self {
write!(&mut self.buffer, "plt.gca().set_ylim([None,{}])\n", ymax).unwrap();
write!(&mut self.buffer, "plt.gca().set_ylim(top={})\n", ymax).unwrap();
self
}

/// Sets minimum z
pub fn set_zmin(&mut self, zmin: f64) -> &mut Self {
write!(&mut self.buffer, "plt.gca().set_zlim([{},None])\n", zmin).unwrap();
write!(&mut self.buffer, "plt.gca().set_zlim(zmin={})\n", zmin).unwrap();
self
}

/// Sets maximum z
pub fn set_zmax(&mut self, zmax: f64) -> &mut Self {
write!(&mut self.buffer, "plt.gca().set_zlim([None,{}])\n", zmax).unwrap();
write!(&mut self.buffer, "plt.gca().set_zlim(zmax={})\n", zmax).unwrap();
self
}

Expand Down Expand Up @@ -1156,6 +1157,12 @@ impl Plot {
{
// update commands
let fig_path = Path::new(figure_path);
let header = if show {
"#### >>>> file generated by plotpy <<<< ####\n\n".to_string() + PYTHON_HEADER
} else {
"#### >>>> file generated by plotpy <<<< ####\n\nimport matplotlib\nmatplotlib.use('Agg')\n".to_string()
+ PYTHON_HEADER
};
let mut txt = "plt.savefig(fn".to_string();
if self.save_tight {
txt.push_str(",bbox_inches='tight',bbox_extra_artists=EXTRA_ARTISTS");
Expand All @@ -1172,7 +1179,13 @@ impl Plot {
if show {
txt.push_str("\nplt.show()\n");
};
let commands = format!("{}\nfn=r'{}'\n{}", self.buffer, fig_path.to_string_lossy(), txt);
let commands = format!(
"{}{}\nfn=r'{}'\n{}",
header,
self.buffer,
fig_path.to_string_lossy(),
txt
);

// call python
let mut path = Path::new(figure_path).to_path_buf();
Expand Down Expand Up @@ -1405,12 +1418,12 @@ mod tests {
plt.gca().set_xlim([-80,800])\n\
plt.gca().set_ylim([13,130])\n\
plt.gca().set_zlim([44,444])\n\
plt.gca().set_xlim([-3,None])\n\
plt.gca().set_xlim([None,8])\n\
plt.gca().set_ylim([-7,None])\n\
plt.gca().set_ylim([None,33])\n\
plt.gca().set_zlim([12,None])\n\
plt.gca().set_zlim([None,34])\n\
plt.gca().set_xlim(left=-3)\n\
plt.gca().set_xlim(right=8)\n\
plt.gca().set_ylim(bottom=-7)\n\
plt.gca().set_ylim(top=33)\n\
plt.gca().set_zlim(zmin=12)\n\
plt.gca().set_zlim(zmax=34)\n\
plt.gca().get_xaxis().set_ticks([])\n\
plt.gca().get_xaxis().set_major_locator(tck.MaxNLocator(8))\n\
plt.gca().get_yaxis().set_ticks([])\n\
Expand Down
2 changes: 1 addition & 1 deletion tests/test_contour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,6 @@ fn test_contour_colorbar_options() -> Result<(), StrError> {
let buffered = BufReader::new(file);
let lines_iter = buffered.lines();
let n = lines_iter.count();
assert!(n > 2150 && n < 2200);
assert!(n > 2050 && n < 2200);
Ok(())
}
2 changes: 1 addition & 1 deletion tests/test_inset_axes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ fn test_inset_axes_5() -> Result<(), StrError> {
let buffered = BufReader::new(file);
let lines_iter = buffered.lines();
let n = lines_iter.count().clone();
assert!(n > 2400 && n < 2500);
assert!(n > 2300 && n < 2500);
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion tests/test_plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ fn test_plot_3d() -> Result<(), StrError> {
let buffered = BufReader::new(file);
let lines_iter = buffered.lines();
let n_lines = lines_iter.count();
assert!(n_lines > 1800 && n_lines < 1900);
assert!(n_lines > 1800 && n_lines < 1950);
Ok(())
}

Expand Down
4 changes: 2 additions & 2 deletions tests/test_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn test_stream_arrows_1() -> Result<(), StrError> {
let buffered = BufReader::new(file);
let lines_iter = buffered.lines();
let n = lines_iter.count();
assert!(n > 8650 && n < 8730);
assert!(n > 4300 && n < 8730);
Ok(())
}

Expand Down Expand Up @@ -90,6 +90,6 @@ fn test_stream_arrows_2() -> Result<(), StrError> {
let buffered = BufReader::new(file);
let lines_iter = buffered.lines();
let n = lines_iter.count();
assert!(n > 3600 && n < 3680);
assert!(n > 2000 && n < 3680);
Ok(())
}
Loading