{"id":13808600,"url":"https://github.com/cpmech/plotpy","last_synced_at":"2025-12-27T06:49:42.864Z","repository":{"id":38498416,"uuid":"396345460","full_name":"cpmech/plotpy","owner":"cpmech","description":"Rust plotting library using Python (Matplotlib)","archived":false,"fork":false,"pushed_at":"2025-02-09T22:29:50.000Z","size":1610,"stargazers_count":75,"open_issues_count":0,"forks_count":8,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-07-29T20:41:52.837Z","etag":null,"topics":["drawing","matplotlib","plot","plotting","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cpmech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-08-15T12:35:44.000Z","updated_at":"2025-06-16T12:14:56.000Z","dependencies_parsed_at":"2024-03-23T04:25:58.238Z","dependency_job_id":"4566a1d7-6fd8-49b4-9c73-02d3843260ab","html_url":"https://github.com/cpmech/plotpy","commit_stats":{"total_commits":501,"total_committers":3,"mean_commits":167.0,"dds":0.03792415169660679,"last_synced_commit":"0d40b4f42089fa3e1ff290a158022945f91f09d3"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"purl":"pkg:github/cpmech/plotpy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpmech%2Fplotpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpmech%2Fplotpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpmech%2Fplotpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpmech%2Fplotpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cpmech","download_url":"https://codeload.github.com/cpmech/plotpy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpmech%2Fplotpy/sbom","scorecard":{"id":306675,"data":{"date":"2025-08-11","repo":{"name":"github.com/cpmech/plotpy","commit":"e2094ec4ee34d996e62f148585080d0c158bf369"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/6 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test_and_coverage.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test_and_coverage.yml:7: update your workflow using https://app.stepsecurity.io/secureworkflow/cpmech/plotpy/test_and_coverage.yml/main?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 26 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T22:13:32.844Z","repository_id":38498416,"created_at":"2025-08-17T22:13:32.844Z","updated_at":"2025-08-17T22:13:32.844Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272773339,"owners_count":24990526,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-29T02:00:10.610Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drawing","matplotlib","plot","plotting","rust"],"created_at":"2024-08-04T01:01:47.159Z","updated_at":"2025-12-27T06:49:42.803Z","avatar_url":"https://github.com/cpmech.png","language":"Rust","funding_links":[],"categories":["Libraries"],"sub_categories":["Data visualization"],"readme":"# Rust plotting library using Python (Matplotlib) \u003c!-- omit from toc --\u003e \n\n[![documentation](https://img.shields.io/badge/plotpy-documentation-blue)](https://docs.rs/plotpy)\n[![Track Awesome List](https://www.trackawesomelist.com/badge.svg)](https://www.trackawesomelist.com/rust-unofficial/awesome-rust/)\n\n[![Test \u0026 Coverage](https://github.com/cpmech/plotpy/actions/workflows/test_and_coverage.yml/badge.svg)](https://github.com/cpmech/plotpy/actions/workflows/test_and_coverage.yml)\n\n\n## Contents \u003c!-- omit from toc --\u003e \n\n- [Introduction](#introduction)\n- [Installation](#installation)\n- [Setting Cargo.toml](#setting-cargotoml)\n- [Use of Jupyter via evcxr](#use-of-jupyter-via-evcxr)\n- [Examples](#examples)\n  - [Barplot](#barplot)\n  - [Boxplot](#boxplot)\n  - [Canvas](#canvas)\n  - [Contour](#contour)\n  - [Curve](#curve)\n  - [Histogram](#histogram)\n  - [Image](#image)\n  - [InsetAxes](#insetaxes)\n  - [Surface](#surface)\n  - [Text](#text)\n\n\n## Introduction\n\nThis crate implements high-level functions to generate plots and drawings. Although we use Python/Matplotlib, the goal is to provide a convenient Rust library that is **different** than Matplotlib. The difference happens because we want **convenience** for the Rust developer while getting the **fantastic quality of Matplotlib** 😀.\n\nPlotpy is more verbose than Matplotlib because we aim to minimize the need to memorize the functionality by taking advantage of the intelligence of the IDE (e.g., VS Code) on auto-completing the code.\n\nInternally, we use [Matplotlib](https://matplotlib.org/) via a Python 3 script. First, we generate a python code in a directory of your choice (e.g., `/tmp/plotpy`), and then we call **python3** using Rust's `std::process::Command`.\n\nFor more information (and examples), check out the [plotpy documentation on docs.rs](https://docs.rs/plotpy).\n\nSee also the [examples directory](https://github.com/cpmech/plotpy/tree/main/examples) with the output of the [integration tests](https://github.com/cpmech/plotpy/tree/main/tests).\n\n\n\n## Installation\n\n*This code is mainly tested on Debian/Ubuntu/Linux.*\n\nThis crate needs Python3 and Matplotlib, of course.\n\nOn Debian/Ubuntu/Linux, run:\n\n```bash\nsudo apt install python3-matplotlib\n```\n\n**Important:** The Rust code will call `python3` via `std::process::Command`. However, there is an option to call a different python executable; for instance (the code below is no tested):\n\n```text\nlet mut plot = Plot::new();\nplot.set_python_exe(\"C:\\Windows11\\WhereIs\\python.exe\")\n    .add(...)\n    .save(...)?;\n```\n\n\n\n## Setting Cargo.toml\n\n[![Crates.io](https://img.shields.io/crates/v/plotpy.svg)](https://crates.io/crates/plotpy)\n\n👆 Check the crate version and update your Cargo.toml accordingly:\n\n```toml\n[dependencies]\nplotpy = \"*\"\n```\n\n\n\n## Use of Jupyter via evcxr\n\nPlotpy can be used with Jupyter via [evcxr](https://github.com/evcxr/evcxr). Thus, it can interactively display the plots in a Jupyter Notebook. This feature requires the installation of `evcxr`. See the [Jupyter/evcxr article](https://depth-first.com/articles/2020/09/21/interactive-rust-in-a-repl-and-jupyter-notebook-with-evcxr/).\n\nThe following code shows a minimal example (not tested)\n\n```text\n// set the python path\nlet python = \"where-is-my/python\";\n\n// set the figure path and name to be saved\nlet path = \"my-figure.svg\";\n\n// plot and show in a Jupyter notebook\nlet mut plot = Plot::new();\nplot.set_python_exe(python)\n    .set_label_x(\"x\")\n    .set_label_y(\"y\")\n    .show_in_jupyter(path)?;\n```\n\n\n\n## Examples\n\n\n\n### Barplot\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Barplot.html)\n\n```rust\nuse plotpy::{Barplot, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // data\n    let fruits = [\"Apple\", \"Banana\", \"Orange\"];\n    let prices = [10.0, 20.0, 30.0];\n    let errors = [3.0, 2.0, 1.0];\n\n    // barplot object and options\n    let mut bar = Barplot::new();\n    bar.set_errors(\u0026errors)\n        .set_horizontal(true)\n        .set_with_text(\"edge\")\n        .draw_with_str(\u0026fruits, \u0026prices);\n\n    // save figure\n    let mut plot = Plot::new();\n    plot.set_inv_y()\n        .add(\u0026bar)\n        .set_title(\"Fruits\")\n        .set_label_x(\"price\");\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_barplot_3.svg\")?;\n    Ok(())\n}\n```\n\n![barplot.svg](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_barplot_3.svg)\n\n\n\n### Boxplot\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Boxplot.html)\n\n```rust\nuse plotpy::{Boxplot, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // data (as a nested list)\n    let data = vec![\n        vec![1, 2, 3, 4, 5],              // A\n        vec![2, 3, 4, 5, 6, 7, 8, 9, 10], // B\n        vec![3, 4, 5, 6],                 // C\n        vec![4, 5, 6, 7, 8, 9, 10],       // D\n        vec![5, 6, 7],                    // E\n    ];\n\n    // x ticks and labels\n    let n = data.len();\n    let ticks: Vec\u003c_\u003e = (1..(n + 1)).into_iter().collect();\n    let labels = [\"A\", \"B\", \"C\", \"D\", \"E\"];\n\n    // boxplot object and options\n    let mut boxes = Boxplot::new();\n    boxes.draw(\u0026data);\n\n    // save figure\n    let mut plot = Plot::new();\n    plot.add(\u0026boxes)\n        .set_title(\"boxplot documentation test\")\n        .set_ticks_x_labels(\u0026ticks, \u0026labels);\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_boxplot_2.svg\")?;\n    Ok(())\n}\n```\n\n![boxplot.svg](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_boxplot_2.svg)\n\n\n\n### Canvas\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Canvas.html)\n\n```rust\nuse plotpy::{Canvas, Plot, PolyCode, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // codes\n    let data = [\n        (3.0, 0.0, PolyCode::MoveTo),\n        (1.0, 1.5, PolyCode::Curve4),\n        (0.0, 4.0, PolyCode::Curve4),\n        (2.5, 3.9, PolyCode::Curve4),\n        (3.0, 3.8, PolyCode::LineTo),\n        (3.5, 3.9, PolyCode::LineTo),\n        (6.0, 4.0, PolyCode::Curve4),\n        (5.0, 1.5, PolyCode::Curve4),\n        (3.0, 0.0, PolyCode::Curve4),\n    ];\n\n    // polycurve\n    let mut canvas = Canvas::new();\n    canvas.set_face_color(\"#f88989\").set_edge_color(\"red\");\n    canvas.polycurve_begin();\n    for (x, y, code) in data {\n        canvas.polycurve_add(x, y, code);\n    }\n    canvas.polycurve_end(true);\n\n    // add canvas to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026canvas);\n\n    // save figure\n    plot.set_range(1.0, 5.0, 0.0, 4.0)\n        .set_frame_borders(false)\n        .set_hide_axes(true)\n        .set_equal_axes(true)\n        .set_show_errors(true);\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_canvas_polycurve.svg\")?;\n    Ok(())\n}\n```\n\n![canvas.svg](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_canvas_polycurve.svg)\n\n\n\n### Contour\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Contour.html)\n\n```rust\nuse plotpy::{generate3d, Contour, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // generate (x,y,z) matrices\n    let n = 21;\n    let (x, y, z) = generate3d(-2.0, 2.0, -2.0, 2.0, n, n, |x, y| x * x - y * y);\n\n    // configure contour\n    let mut contour = Contour::new();\n    contour\n        .set_colorbar_label(\"temperature\")\n        .set_colormap_name(\"terrain\")\n        .set_selected_level(0.0, true);\n\n    // draw contour\n    contour.draw(\u0026x, \u0026y, \u0026z);\n\n    // add contour to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026contour)\n        .set_labels(\"x\", \"y\");\n\n    // plot.save(\"/tmp/plotpy/readme_contour.svg\")?;\n    Ok(())\n}\n```\n\n![contour.svg](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/readme_contour.svg)\n\n\n\n### Curve\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Curve.html)\n\n```rust\nuse plotpy::{linspace, Curve, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // generate (x,y) points\n    let x = linspace(-1.0, 1.0, 21);\n    let y: Vec\u003c_\u003e = x.iter().map(|v| 1.0 / (1.0 + f64::exp(-5.0 * *v))).collect();\n\n    // configure curve\n    let mut curve = Curve::new();\n    curve\n        .set_label(\"logistic function\")\n        .set_line_alpha(0.8)\n        .set_line_color(\"#5f9cd8\")\n        .set_line_style(\"-\")\n        .set_line_width(5.0)\n        .set_marker_color(\"#eeea83\")\n        .set_marker_every(5)\n        .set_marker_line_color(\"#da98d1\")\n        .set_marker_line_width(2.5)\n        .set_marker_size(20.0)\n        .set_marker_style(\"*\");\n\n    // draw curve\n    curve.draw(\u0026x, \u0026y);\n\n    // add curve to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026curve)\n        .set_num_ticks_y(11)\n        .grid_labels_legend(\"x\", \"y\");\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_curve.svg\")?;\n    Ok(())\n}\n```\n\n![curve.svg](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_curve_vector.svg)\n\n\n### Histogram\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Histogram.html)\n\n```rust\nuse plotpy::{Histogram, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // set values\n    let values = vec![\n        vec![1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 5, 6], // first series\n        vec![-1, -1, 0, 1, 2, 3],                    // second series\n        vec![5, 6, 7, 8],                            // third series\n    ];\n\n    // set labels\n    let labels = [\"first\", \"second\", \"third\"];\n\n    // configure and draw histogram\n    let mut histogram = Histogram::new();\n    histogram.set_colors(\u0026[\"#9de19a\", \"#e7eca3\", \"#98a7f2\"])\n        .set_line_width(10.0)\n        .set_stacked(true)\n        .set_style(\"step\");\n    histogram.draw(\u0026values, \u0026labels);\n\n    // add histogram to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026histogram)\n        .set_frame_border(true, false, true, false)\n        .grid_labels_legend(\"values\", \"count\");\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_histogram.svg\")?;\n    Ok(())\n}\n```\n\n![histogram](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_histogram.svg)\n\n\n### Image\n\n```rust\nuse plotpy::{Image, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // set values\n    let data = [\n        [0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],\n        [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],\n        [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],\n        [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],\n        [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],\n        [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],\n        [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3],\n    ];\n\n    // image plot and options\n    let mut img = Image::new();\n    img.set_colormap_name(\"hsv\").draw(\u0026data);\n\n    // save figure\n    let mut plot = Plot::new();\n    plot.add(\u0026img);\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_image_1.svg\")?;\n    Ok(())\n}\n```\n\n![image](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_image_1.svg)\n\n\n### InsetAxes\n\n```rust\nuse plotpy::{Curve, InsetAxes, Plot, StrError};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // draw curve\n    let mut curve = Curve::new();\n    curve.draw(\u0026[0.0, 1.0, 2.0], \u0026[0.0, 1.0, 4.0]);\n\n    // allocate inset and add curve to it\n    let mut inset = InsetAxes::new();\n    inset\n        .add(\u0026curve) // add curve to inset\n        .set_range(0.5, 1.5, 0.5, 1.5) // set the range of the inset\n        .draw(0.5, 0.5, 0.4, 0.3);\n\n    // add curve and inset to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026curve)\n        .set_range(0.0, 5.0, 0.0, 5.0)\n        .add(\u0026inset); // IMPORTANT: add inset after setting the range\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_inset_axes_add.svg\")?;\n    Ok(())\n}\n```\n\n![inset_axes](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_inset_axes_add.svg)\n\n\n### Surface\n\n[See the documentation](https://docs.rs/plotpy/latest/plotpy/struct.Surface.html)\n\n```rust\nuse plotpy::{Plot, StrError, Surface};\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // star\n    let r = \u0026[1.0, 1.0, 1.0];\n    let c = \u0026[-1.0, -1.0, -1.0];\n    let k = \u0026[0.5, 0.5, 0.5];\n    let mut star = Surface::new();\n    star.set_colormap_name(\"jet\")\n        .draw_superquadric(c, r, k, -180.0, 180.0, -90.0, 90.0, 40, 20)?;\n\n    // pyramids\n    let c = \u0026[1.0, -1.0, -1.0];\n    let k = \u0026[1.0, 1.0, 1.0];\n    let mut pyramids = Surface::new();\n    pyramids\n        .set_colormap_name(\"inferno\")\n        .draw_superquadric(c, r, k, -180.0, 180.0, -90.0, 90.0, 40, 20)?;\n\n    // rounded cube\n    let c = \u0026[-1.0, 1.0, 1.0];\n    let k = \u0026[4.0, 4.0, 4.0];\n    let mut cube = Surface::new();\n    cube.set_surf_color(\"#ee29f2\")\n        .draw_superquadric(c, r, k, -180.0, 180.0, -90.0, 90.0, 40, 20)?;\n\n    // sphere\n    let c = \u0026[0.0, 0.0, 0.0];\n    let k = \u0026[2.0, 2.0, 2.0];\n    let mut sphere = Surface::new();\n    sphere\n        .set_colormap_name(\"rainbow\")\n        .draw_superquadric(c, r, k, -180.0, 180.0, -90.0, 90.0, 40, 20)?;\n\n    // sphere (direct)\n    let mut sphere_direct = Surface::new();\n    sphere_direct.draw_sphere(\u0026[1.0, 1.0, 1.0], 1.0, 40, 20)?;\n\n    // add features to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026star)\n        .add(\u0026pyramids)\n        .add(\u0026cube)\n        .add(\u0026sphere)\n        .add(\u0026sphere_direct);\n\n    // save figure\n    plot.set_equal_axes(true)\n        .set_figure_size_points(600.0, 600.0);\n\n    // plot.save(\"/tmp/plotpy/readme_superquadric.svg\")?;\n    Ok(())\n}\n```\n\n![readme_superquadric.svg](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/readme_superquadric.svg)\n\n\n### Text\n\n```rust\nuse plotpy::{Plot, Text, StrError};\nuse std::path::Path;\n\nfn main() -\u003e Result\u003c(), StrError\u003e {\n    // configure text\n    let mut text = Text::new();\n    text.set_color(\"purple\")\n        .set_align_horizontal(\"center\")\n        .set_align_vertical(\"center\")\n        .set_fontsize(30.0)\n        .set_bbox(true)\n        .set_bbox_facecolor(\"pink\")\n        .set_bbox_edgecolor(\"black\")\n        .set_bbox_alpha(0.3)\n        .set_bbox_style(\"roundtooth,pad=0.3,tooth_size=0.2\");\n\n    // draw text\n    text.draw_3d(0.5, 0.5, 0.5, \"Hello World!\");\n\n    // add text to plot\n    let mut plot = Plot::new();\n    plot.add(\u0026text);\n\n    // plot.save(\"/tmp/plotpy/doc_tests/doc_text.svg\")?;\n    Ok(())\n}\n```\n\n![text](https://raw.githubusercontent.com/cpmech/plotpy/main/figures/doc_text.svg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpmech%2Fplotpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcpmech%2Fplotpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpmech%2Fplotpy/lists"}