diff --git a/CMakeLists.txt b/CMakeLists.txt index 98446d08..b84c6adb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.24) project( fplot LANGUAGES Fortran - VERSION 1.8.12 + VERSION 1.9.0 ) diff --git a/README.md b/README.md index 053362c6..757ee239 100644 --- a/README.md +++ b/README.md @@ -12,22 +12,66 @@ This library is tailored to write script files for GNUPLOT. As such, GNUPLOT is ## Documentation Documentation can be found [here](https://jchristopherson.github.io/fplot/) -## Building FPLOT -[CMake](https://cmake.org/)This library can be built using CMake. For instructions see [Running CMake](https://cmake.org/runningcmake/). +## Building +FPLOT requires a Fortran compiler with Fortran 2003 support and [Gnuplot](http://www.gnuplot.info/) on your `PATH` to render plots. The CMake and FPM builds retrieve the Fortran library dependencies automatically. + +### CMake +Configure and build the library with CMake 3.24 or newer: +```sh +cmake -S . -B build -DBUILD_TESTING=ON -DBUILD_FPLOT_EXAMPLES=ON +cmake --build build --parallel +ctest --test-dir build --output-on-failure +``` + +Install it to a prefix of your choice: +```sh +cmake --install build --prefix /path/to/install +``` + +To build a shared library, add `-DBUILD_SHARED_LIBS=ON` to the configure command. Set `BUILD_TESTING` or `BUILD_FPLOT_EXAMPLES` to `OFF` when those targets are not needed. -[FPM](https://github.com/fortran-lang/fpm) can also be used to build this library using the provided fpm.toml. -```txt +### FPM +[FPM](https://github.com/fortran-lang/fpm) can build and test the checked-out repository directly: +```sh fpm build +fpm test ``` -The FPLOT library can be used within your FPM project by adding the following to your fpm.toml file. + +Add FPLOT to another FPM project with: ```toml [dependencies] fplot = { git = "https://github.com/jchristopherson/fplot" } ``` +## Getting Started +Import `fplot_core` for the primary types, styling constants, and helper routines such as `linspace` and `meshgrid`. A basic 2D plot follows four steps: initialize a plot object, configure its appearance, add one or more data series, and draw it. + +```fortran +use, intrinsic :: iso_fortran_env +use fplot_core + +type(plot_2d) :: plt +real(real64) :: x(100), y(100) + +x = linspace(0.0_real64, 10.0_real64, size(x)) +y = sin(x) + +call plt%initialize() +call plt%set_title("Sine wave") +call plt%set_x_axis_title("x") +call plt%set_y_axis_title("sin(x)") +call plt%push(x, y, lw = 2.0, name = "sin(x)") +call plt%draw() +``` + +`plot_2d%push` creates a line data series directly from `x` and `y`. For more control, create a `plot_data_2d` object, call `define_data`, set properties such as its name, line style, markers, or color, and then pass it to `plot_2d%push`. + +Use `plot_3d` for 3D curves and scatter data, `surface_plot` for gridded surfaces, and `plot_polar` for polar coordinates. `plot_data_error_bars`, `plot_data_histogram`, `plot_data_bar`, and `vector_field_plot_data` provide specialized series types. Axis and legend objects are available through `get_x_axis`, `get_y_axis`, and `get_legend` for detailed layout control. Invalid input and allocation failures print a diagnostic and terminate with an `fplot_errors` error code. + +The [examples](examples) directory contains complete programs for 2D and 3D plots, surfaces, histograms, error bars, vector fields, and output terminals. + ## External Libraries The FPLOT library depends upon the following libraries. -- [FERROR](https://github.com/jchristopherson/ferror) - [COLLECTIONS](https://github.com/jchristopherson/collections) - [FSTRING](https://github.com/jchristopherson/fstring) - [GEOMPACK](https://github.com/jchristopherson/geompack) @@ -47,54 +91,22 @@ program example ! Local Variables real(real64), dimension(n) :: x, y1, y2 type(plot_2d) :: plt - type(plot_data_2d) :: d1, d2 - class(plot_axis), pointer :: xAxis, yAxis - type(legend), pointer :: leg ! Initialize the plot object call plt%initialize() - - ! Define titles + call plt%show_legend(.true.) call plt%set_title("Example Plot") - call plt%set_font_size(14) - - xAxis => plt%get_x_axis() - call xAxis%set_title("X Axis") - - yAxis => plt%get_y_axis() - call yAxis%set_title("Y Axis") - - ! Establish legend properties - leg => plt%get_legend() - call leg%set_is_visible(.true.) - call leg%set_draw_inside_axes(.false.) - call leg%set_horizontal_position(LEGEND_CENTER) - call leg%set_vertical_position(LEGEND_BOTTOM) - call leg%set_draw_border(.false.) + call plt%set_x_axis_title("X Axis") + call plt%set_y_axis_title("Y Axis") ! Define the data, and then add it to the plot x = linspace(0.0d0, 10.0d0, n) y1 = sin(5.0d0 * x) y2 = 2.0d0 * cos(2.0d0 * x) - call d1%define_data(x, y1) - call d2%define_data(x, y2) - - ! Define properties for each data set - call d1%set_name("Data Set 1") - call d1%set_draw_markers(.true.) - call d1%set_marker_frequency(10) - call d1%set_marker_style(MARKER_EMPTY_CIRCLE) - call d1%set_marker_scaling(2.0) - - call d2%set_name("Data Set 2") - call d2%set_line_style(LINE_DASHED) - call d2%set_line_width(2.0) - - ! Add the data sets to the plot - call plt%push(d1) - call plt%push(d2) - + call plt%push(x, y1, lw = 2.0, name = "Data Set 1") + call plt%push(x, y2, lw = 2.0, ls = LINE_DASHED, name = "Data Set 2") + ! Let GNUPLOT draw the plot call plt%draw() end program @@ -103,10 +115,8 @@ This is the plot resulting from the above program. ![](images/example_2d_plot_1.png?raw=true) ## Example 2 -Another example of a similar two-dimensional plot to the plot in example 1 is given below. This plot shifts the x-axis to the zero point along the y-axis. +Another example of a similar two-dimensional plot to the plot in example 1 is given below. This plot shifts the x-axis to the zero point along the y-axis. Additionally, this example highlights the use of the plot_axis, legend, and plot_data_2d types to gain more control over the plot. ```fortran -! fplot_2d_2.f90 - program example use, intrinsic :: iso_fortran_env use fplot_core @@ -178,7 +188,7 @@ The following example illustrates how to create a three-dimensional surface plot program example use fplot_core use iso_fortran_env - use forcolormap, only : colormaps_list + use forcolormap implicit none ! Parameters @@ -190,8 +200,6 @@ program example real(real64), pointer, dimension(:,:) :: x, y real(real64), dimension(m, n) :: z type(surface_plot) :: plt - type(surface_plot_data) :: d1 - class(plot_axis), pointer :: xAxis, yAxis, zAxis type(custom_colormap) :: map type(cmap) :: colors @@ -207,6 +215,10 @@ program example ! Initialize the plot call plt%initialize() call plt%set_colormap(map) + call plt%set_x_axis_title("X Axis") + call plt%set_y_axis_title("Y Axis") + call plt%set_z_axis_title("Z Axis") + call plt%set_title("Custom Colormap") ! Establish lighting call plt%set_use_lighting(.true.) @@ -214,23 +226,10 @@ program example ! Set the orientation of the plot call plt%set_elevation(20.0d0) call plt%set_azimuth(30.0d0) - - ! Define titles - call plt%set_title("Example Plot") - - xAxis => plt%get_x_axis() - call xAxis%set_title("X Axis") - - yAxis => plt%get_y_axis() - call yAxis%set_title("Y Axis") - - zAxis => plt%get_z_axis() - call zAxis%set_title("Z Axis") ! Define the function to plot z = sqrt(x**2 + y**2) * sin(x**2 + y**2) - call d1%define_data(x, y, z) - call plt%push(d1) + call plt%push(x, y, z) ! Draw the plot call plt%draw() @@ -279,7 +278,6 @@ program example ! Create the plot call plt%initialize() - call plt%set_font_size(14) xAxis => plt%get_x_axis() yAxis => plt%get_y_axis() @@ -330,7 +328,6 @@ program example real(real64), parameter :: pi = 2.0d0 * acos(0.0d0) real(real64) :: t(npts), x(npts) type(plot_polar) :: plt - type(plot_data_2d) :: pd ! Create a function to plot t = linspace(-2.0d0 * pi, 2.0d0 * pi, npts) @@ -342,10 +339,7 @@ program example call plt%set_title("Polar Plot Example") call plt%set_autoscale(.false.) call plt%set_radial_limits([0.0d0, 6.0d0]) - - call pd%define_data(t, x) - call pd%set_line_width(2.0) - call plt%push(pd) + call plt%push(t, x, lw = 2.0) call plt%draw() end program ``` diff --git a/configure/template.cmake b/configure/template.cmake index 24808c57..8473c872 100644 --- a/configure/template.cmake +++ b/configure/template.cmake @@ -1,7 +1,6 @@ @PACKAGE_INIT@ include(CMakeFindDependencyMacro) -find_dependency(ferror QUIET) find_dependency(collections QUIET) find_dependency(geompack QUIET) find_dependency(fstring QUIET) diff --git a/doc/src/fplot_colormap.f90 b/doc/src/fplot_colormap.f90 index 17469e79..da4ec14c 100644 --- a/doc/src/fplot_colormap.f90 +++ b/doc/src/fplot_colormap.f90 @@ -4,7 +4,6 @@ module fplot_colormap use iso_fortran_env use fplot_plot_object use strings - use ferror use fplot_errors use fplot_colors use forcolormap, cmap => Colormap ! avoid conflict with the internally defined colormap type diff --git a/doc/src/fplot_delaunay_tri_surface.f90 b/doc/src/fplot_delaunay_tri_surface.f90 index 68efc630..1d6b1982 100644 --- a/doc/src/fplot_delaunay_tri_surface.f90 +++ b/doc/src/fplot_delaunay_tri_surface.f90 @@ -5,7 +5,6 @@ module fplot_delaunay_tri_surface use ieee_arithmetic use fplot_triangulations_delaunay_2d use fplot_errors - use ferror implicit none private public :: delaunay_tri_surface diff --git a/doc/src/fplot_errors.f90 b/doc/src/fplot_errors.f90 index 39fb79ed..7300a370 100644 --- a/doc/src/fplot_errors.f90 +++ b/doc/src/fplot_errors.f90 @@ -1,8 +1,12 @@ module fplot_errors use iso_fortran_env - use ferror implicit none + type :: errors + contains + procedure :: report_error + end type + ! ****************************************************************************** ! ERROR CODES ! ------------------------------------------------------------------------------ @@ -19,6 +23,17 @@ module fplot_errors !! Occurs if there is a GNUPLOT file error. contains +! ------------------------------------------------------------------------------ +subroutine report_error(this, fcn, msg, code) + class(errors), intent(inout) :: this + character(len = *), intent(in) :: fcn + character(len = *), intent(in) :: msg + integer(int32), intent(in) :: code + + write(error_unit, '(A)') trim(fcn) // ': ' // trim(msg) + error stop code +end subroutine + ! ------------------------------------------------------------------------------ subroutine report_memory_error(err, fcn, flag) !! Reports a memory allocation error. @@ -33,7 +48,7 @@ subroutine report_memory_error(err, fcn, flag) character(len = 256) :: msg ! Define the error message - write(100, msg) "Memory allocation error returning flag ", flag, "." + write(msg, 100) "Memory allocation error returning flag ", flag, "." call err%report_error(fcn, trim(msg), PLOT_OUT_OF_MEMORY_ERROR) ! Formatting @@ -56,7 +71,7 @@ subroutine report_file_create_error(err, fcn, fname, flag) character(len = 2048) :: msg ! Define the error message - write(100, msg) "File ", fname, " could not be created. The error flag ", & + write(msg, 100) "File ", fname, " could not be created. The error flag ", & flag, " was returned." call err%report_error(fcn, trim(msg), PLOT_GNUPLOT_FILE_ERROR) @@ -82,7 +97,7 @@ subroutine report_array_size_mismatch_error(err, fcn, name, expected, actual) character(len = 256) :: msg ! Define the message - write(100, msg) "Array ", name, " was found to be of length ", actual, & + write(msg, 100) "Array ", name, " was found to be of length ", actual, & ", but was expected to be of length ", expected, "." call err%report_error(fcn, trim(msg), PLOT_ARRAY_SIZE_MISMATCH_ERROR) @@ -113,7 +128,7 @@ subroutine report_matrix_size_mismatch_error(err, fcn, name, mexp, nexp, & character(len = 256) :: msg ! Define the error - write(100, msg) "Matrix ", name, " was expected to be of size ", mexp, & + write(msg, 100) "Matrix ", name, " was expected to be of size ", mexp, & "-by-", nexp, ", but was found to be of size ", mact, "-by-", nact, "." call err%report_error(fcn, trim(msg), PLOT_ARRAY_SIZE_MISMATCH_ERROR) diff --git a/doc/src/fplot_filled_plot_data.f90 b/doc/src/fplot_filled_plot_data.f90 index 08bb0c4e..60e3cd68 100644 --- a/doc/src/fplot_filled_plot_data.f90 +++ b/doc/src/fplot_filled_plot_data.f90 @@ -5,7 +5,6 @@ module fplot_filled_plot_data use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/doc/src/fplot_multiplot.f90 b/doc/src/fplot_multiplot.f90 index 571eb6fb..e11c6472 100644 --- a/doc/src/fplot_multiplot.f90 +++ b/doc/src/fplot_multiplot.f90 @@ -13,7 +13,6 @@ module fplot_multiplot use fplot_constants use fplot_errors use collections - use ferror use strings implicit none private diff --git a/doc/src/fplot_plot.f90 b/doc/src/fplot_plot.f90 index 5bfab48a..ae1f1d18 100644 --- a/doc/src/fplot_plot.f90 +++ b/doc/src/fplot_plot.f90 @@ -18,7 +18,6 @@ module fplot_plot use fplot_label use fplot_arrow use fplot_plot_data_function - use ferror use strings use collections implicit none diff --git a/doc/src/fplot_plot_2d.f90 b/doc/src/fplot_plot_2d.f90 index dbc5f7e2..eae17e38 100644 --- a/doc/src/fplot_plot_2d.f90 +++ b/doc/src/fplot_plot_2d.f90 @@ -6,7 +6,6 @@ module fplot_plot_2d use fplot_errors use fplot_plot_axis use fplot_legend - use ferror use strings implicit none private @@ -110,7 +109,6 @@ subroutine p2d_init(this, term, fname, err) ! Initialize the base class ! call plt_init(this, term, fname, errmgr) call this%plot%initialize(term, fname, errmgr) - if (errmgr%has_error_occurred()) return ! Process flag = 0 diff --git a/doc/src/fplot_plot_3d.f90 b/doc/src/fplot_plot_3d.f90 index 51c351e5..bf89bc34 100644 --- a/doc/src/fplot_plot_3d.f90 +++ b/doc/src/fplot_plot_3d.f90 @@ -8,7 +8,6 @@ module fplot_plot_3d use fplot_constants use fplot_plot_data use fplot_legend - use ferror use strings implicit none private @@ -112,7 +111,6 @@ subroutine p3d_init(this, term, fname, err) ! Initialize the base class ! call plt_init(this, term, fname, errmgr) call this%plot%initialize(term, fname, errmgr) - if (errmgr%has_error_occurred()) return ! Process flag = 0 diff --git a/doc/src/fplot_plot_data.f90 b/doc/src/fplot_plot_data.f90 index 49fc3ac1..894a77b6 100644 --- a/doc/src/fplot_plot_data.f90 +++ b/doc/src/fplot_plot_data.f90 @@ -6,7 +6,6 @@ module fplot_plot_data use fplot_constants use fplot_colors use strings - use ferror use fplot_errors implicit none private diff --git a/doc/src/fplot_plot_data_2d.f90 b/doc/src/fplot_plot_data_2d.f90 index cb997ac3..c1a36395 100644 --- a/doc/src/fplot_plot_data_2d.f90 +++ b/doc/src/fplot_plot_data_2d.f90 @@ -3,7 +3,6 @@ module fplot_plot_data_2d use fplot_plot_data use fplot_simplify use fplot_errors - use ferror use strings implicit none private diff --git a/doc/src/fplot_plot_data_3d.f90 b/doc/src/fplot_plot_data_3d.f90 index 1a6feb9d..a1ae3eac 100644 --- a/doc/src/fplot_plot_data_3d.f90 +++ b/doc/src/fplot_plot_data_3d.f90 @@ -3,7 +3,6 @@ module fplot_plot_data_3d use fplot_plot_data use fplot_errors use fplot_simplify - use ferror use strings implicit none private diff --git a/doc/src/fplot_plot_data_bar.f90 b/doc/src/fplot_plot_data_bar.f90 index ecabaad2..06516f73 100644 --- a/doc/src/fplot_plot_data_bar.f90 +++ b/doc/src/fplot_plot_data_bar.f90 @@ -6,7 +6,6 @@ module fplot_plot_data_bar use fplot_errors use fplot_colors use strings - use ferror implicit none private public :: plot_data_bar diff --git a/doc/src/fplot_plot_data_box_whisker.f90 b/doc/src/fplot_plot_data_box_whisker.f90 index 0f83579d..b01bd549 100644 --- a/doc/src/fplot_plot_data_box_whisker.f90 +++ b/doc/src/fplot_plot_data_box_whisker.f90 @@ -3,7 +3,6 @@ module fplot_plot_data_box_whisker use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/doc/src/fplot_plot_data_error_bars.f90 b/doc/src/fplot_plot_data_error_bars.f90 index bcb2d909..7482de2f 100644 --- a/doc/src/fplot_plot_data_error_bars.f90 +++ b/doc/src/fplot_plot_data_error_bars.f90 @@ -5,7 +5,6 @@ module fplot_plot_data_error_bars use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/doc/src/fplot_plot_data_histogram.f90 b/doc/src/fplot_plot_data_histogram.f90 index 1e4e2733..4b2d8309 100644 --- a/doc/src/fplot_plot_data_histogram.f90 +++ b/doc/src/fplot_plot_data_histogram.f90 @@ -4,7 +4,6 @@ module fplot_plot_data_histogram use iso_fortran_env use fplot_plot_data use fplot_errors - use ferror use strings use fplot_colors implicit none diff --git a/doc/src/fplot_plot_polar.f90 b/doc/src/fplot_plot_polar.f90 index c08d2575..2a9a0ee8 100644 --- a/doc/src/fplot_plot_polar.f90 +++ b/doc/src/fplot_plot_polar.f90 @@ -8,7 +8,6 @@ module fplot_plot_polar use fplot_constants use fplot_legend use fplot_plot_data - use ferror use strings implicit none private @@ -90,7 +89,6 @@ subroutine plr_init(this, term, fname, err) ! Initialize the base class ! call plt_init(this, term, fname, errmgr) call this%plot%initialize(term, fname, errmgr) - if (errmgr%has_error_occurred()) return ! Initialize the rest of the object this%m_thetaStart = POLAR_THETA_RIGHT diff --git a/doc/src/fplot_simplify.f90 b/doc/src/fplot_simplify.f90 index f2c03bf5..5164f861 100644 --- a/doc/src/fplot_simplify.f90 +++ b/doc/src/fplot_simplify.f90 @@ -6,7 +6,6 @@ module fplot_simplify use iso_fortran_env - use ferror use fplot_errors implicit none private diff --git a/doc/src/fplot_stats_plots.f90 b/doc/src/fplot_stats_plots.f90 index 6e5871ac..a6ea17df 100644 --- a/doc/src/fplot_stats_plots.f90 +++ b/doc/src/fplot_stats_plots.f90 @@ -13,7 +13,6 @@ module fplot_stats_plots use fplot_plot_axis use collections use strings - use ferror implicit none private public :: correlation_plot @@ -100,7 +99,6 @@ subroutine cp_init(this, x, labels, term, width, height, err) n = size(x, 2) call this%m_plt%initialize(n, n, term = term, width = width, & height = height, err = errmgr) - if (errmgr%has_error_occurred()) return allocate(plts(n * n), stat = flag) if (flag /= 0) then call report_memory_error(errmgr, "cp_init", flag) @@ -125,21 +123,17 @@ subroutine cp_init(this, x, labels, term, width, height, err) call pdata%set_marker_scaling(0.5) call mdata%set_line_width(2.0) call mdata%set_line_color(CLR_BLACK) - if (errmgr%has_error_occurred()) return do j = 1, n do i = 1, n k = k + 1 call plts(k)%initialize(err = errmgr) - if (errmgr%has_error_occurred()) return if (i == j) then ! Plot a histogram of the data call hdata%define_data(x(:,i), err = errmgr) - if (errmgr%has_error_occurred()) return call plts(k)%push(hdata) else ! Plot a scatter plot call pdata%define_data(x(:,j), x(:,i), err = errmgr) - if (errmgr%has_error_occurred()) return call plts(k)%push(pdata) ! Fit a line to the data @@ -148,7 +142,6 @@ subroutine cp_init(this, x, labels, term, width, height, err) ! Plot the fitted line call mdata%define_data(x(:,j), mdl, err = err) - if (errmgr%has_error_occurred()) return call plts(k)%push(mdata) end if diff --git a/doc/src/fplot_surface_plot.f90 b/doc/src/fplot_surface_plot.f90 index 06d1f291..08172c20 100644 --- a/doc/src/fplot_surface_plot.f90 +++ b/doc/src/fplot_surface_plot.f90 @@ -5,7 +5,6 @@ module fplot_surface_plot use fplot_plot_3d use fplot_errors use fplot_legend - use ferror use strings implicit none private diff --git a/doc/src/fplot_surface_plot_data.f90 b/doc/src/fplot_surface_plot_data.f90 index 16b8f3db..667bc564 100644 --- a/doc/src/fplot_surface_plot_data.f90 +++ b/doc/src/fplot_surface_plot_data.f90 @@ -1,7 +1,6 @@ module fplot_surface_plot_data use iso_fortran_env use fplot_plot_data - use ferror use fplot_errors use strings implicit none diff --git a/doc/src/fplot_triangulations_delaunay_2d.f90 b/doc/src/fplot_triangulations_delaunay_2d.f90 index d0086500..bf52fee8 100644 --- a/doc/src/fplot_triangulations_delaunay_2d.f90 +++ b/doc/src/fplot_triangulations_delaunay_2d.f90 @@ -1,7 +1,6 @@ module fplot_triangulations_delaunay_2d use iso_fortran_env use geompack - use ferror use fplot_errors implicit none private diff --git a/doc/src/fplot_vector_field_plot_data.f90 b/doc/src/fplot_vector_field_plot_data.f90 index 73ed2990..b8917e07 100644 --- a/doc/src/fplot_vector_field_plot_data.f90 +++ b/doc/src/fplot_vector_field_plot_data.f90 @@ -9,7 +9,6 @@ module fplot_vector_field_plot_data use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index feda8369..14b67898 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -158,6 +158,10 @@ target_link_libraries(jitter_plot_example fplot) add_executable(function_plot_example function_plot_example.f90) target_link_libraries(function_plot_example fplot) +# Example 41 +add_executable(polar_plot_simplified_example polar_plot_simplified_example.f90) +target_link_libraries(polar_plot_simplified_example fplot) + if (${BUILD_SHARED_LIBS} AND WIN32) add_custom_command( TARGET generic_2d_plot diff --git a/examples/custom_colormap_example.f90 b/examples/custom_colormap_example.f90 index 3c92c2df..7a99f352 100644 --- a/examples/custom_colormap_example.f90 +++ b/examples/custom_colormap_example.f90 @@ -13,8 +13,6 @@ program example real(real64), pointer, dimension(:,:) :: x, y real(real64), dimension(m, n) :: z type(surface_plot) :: plt - type(surface_plot_data) :: d1 - class(plot_axis), pointer :: xAxis, yAxis, zAxis type(custom_colormap) :: map type(cmap) :: colors @@ -30,6 +28,10 @@ program example ! Initialize the plot call plt%initialize() call plt%set_colormap(map) + call plt%set_x_axis_title("X Axis") + call plt%set_y_axis_title("Y Axis") + call plt%set_z_axis_title("Z Axis") + call plt%set_title("Custom Colormap") ! Establish lighting call plt%set_use_lighting(.true.) @@ -37,23 +39,10 @@ program example ! Set the orientation of the plot call plt%set_elevation(20.0d0) call plt%set_azimuth(30.0d0) - - ! Define titles - call plt%set_title("Example Plot") - - xAxis => plt%get_x_axis() - call xAxis%set_title("X Axis") - - yAxis => plt%get_y_axis() - call yAxis%set_title("Y Axis") - - zAxis => plt%get_z_axis() - call zAxis%set_title("Z Axis") ! Define the function to plot z = sqrt(x**2 + y**2) * sin(x**2 + y**2) - call d1%define_data(x, y, z) - call plt%push(d1) + call plt%push(x, y, z) ! Draw the plot call plt%draw() diff --git a/examples/generic_2d_plot.f90 b/examples/generic_2d_plot.f90 index f41170b6..ac4baafe 100644 --- a/examples/generic_2d_plot.f90 +++ b/examples/generic_2d_plot.f90 @@ -9,54 +9,22 @@ program example ! Local Variables real(real64), dimension(n) :: x, y1, y2 type(plot_2d) :: plt - type(plot_data_2d) :: d1, d2 - class(plot_axis), pointer :: xAxis, yAxis - type(legend), pointer :: leg ! Initialize the plot object call plt%initialize() - - ! Define titles + call plt%show_legend(.true.) call plt%set_title("Example Plot") - call plt%set_font_size(14) - - xAxis => plt%get_x_axis() - call xAxis%set_title("X Axis") - - yAxis => plt%get_y_axis() - call yAxis%set_title("Y Axis") - - ! Establish legend properties - leg => plt%get_legend() - call leg%set_is_visible(.true.) - call leg%set_draw_inside_axes(.false.) - call leg%set_horizontal_position(LEGEND_CENTER) - call leg%set_vertical_position(LEGEND_BOTTOM) - call leg%set_draw_border(.false.) + call plt%set_x_axis_title("X Axis") + call plt%set_y_axis_title("Y Axis") ! Define the data, and then add it to the plot x = linspace(0.0d0, 10.0d0, n) y1 = sin(5.0d0 * x) y2 = 2.0d0 * cos(2.0d0 * x) - call d1%define_data(x, y1) - call d2%define_data(x, y2) - - ! Define properties for each data set - call d1%set_name("Data Set 1") - call d1%set_draw_markers(.true.) - call d1%set_marker_frequency(10) - call d1%set_marker_style(MARKER_EMPTY_CIRCLE) - call d1%set_marker_scaling(2.0) - - call d2%set_name("Data Set 2") - call d2%set_line_style(LINE_DASHED) - call d2%set_line_width(2.0) - - ! Add the data sets to the plot - call plt%push(d1) - call plt%push(d2) - + call plt%push(x, y1, lw = 2.0, name = "Data Set 1") + call plt%push(x, y2, lw = 2.0, ls = LINE_DASHED, name = "Data Set 2") + ! Let GNUPLOT draw the plot call plt%draw() end program \ No newline at end of file diff --git a/examples/meson.build b/examples/meson.build deleted file mode 100644 index 0c3d1cac..00000000 --- a/examples/meson.build +++ /dev/null @@ -1,37 +0,0 @@ -examples = [ - ['fplot_2d_1','fplot_2d_1.f90'], - ['fplot_2d_2','fplot_2d_2.f90'], - ['fplot_2d_3','fplot_2d_3.f90'], - ['fplot_2d_4','fplot_2d_4.f90'], - ['fplot_2d_5','fplot_2d_5.f90'], - ['fplot_2d_6','fplot_2d_6.f90'], - ['fplot_2d_7','fplot_2d_7.f90'], - ['fplot_2d_8','fplot_2d_8.f90'], - ['fplot_2d_9','fplot_2d_9.f90'], - ['fplot_2d_clr_1','fplot_2d_clr_1.f90'], - ['fplot_3d_1','fplot_3d_1.f90'], - ['fplot_3d_clr_1','fplot_3d_clr_1.f90'], - ['fplot_clear_1','fplot_clear_1.f90'], - ['fplot_d2d_1','fplot_d2d_1.f90'], - ['fplot_d2d_2','fplot_d2d_2.f90'], - ['fplot_err_1','fplot_err_1.f90'], - ['fplot_fill_1','fplot_fill_1.f90'], - ['fplot_fill_2','fplot_fill_2.f90'], - ['fplot_log_1','fplot_log_1.f90'], - ['fplot_multi_1','fplot_multi_1.f90'], - ['fplot_multi_2','fplot_multi_2.f90'], - ['fplot_multi_3','fplot_multi_3.f90'], - ['fplot_png_1','fplot_png_1.f90'], - ['fplot_polar_1','fplot_polar_1.f90'], - ['fplot_surf_1','fplot_surf_1.f90'], - ['fplot_surf_2','fplot_surf_2.f90'], - ['fplot_surf_3','fplot_surf_3.f90'], - ['fplot_tri_surf_1','fplot_tri_surf_1.f90'], - ['fplot_vector_1','fplot_vector_1.f90'], - ['fplot_vector_2','fplot_vector_2.f90'] - ] - -foreach example : examples - executable(example[0], example[1], - dependencies: fplot_dep) -endforeach diff --git a/examples/polar_plot_simplified_example.f90 b/examples/polar_plot_simplified_example.f90 new file mode 100644 index 00000000..6043e304 --- /dev/null +++ b/examples/polar_plot_simplified_example.f90 @@ -0,0 +1,28 @@ +! Contrast this example to polar_plot_example.f90 to see how the "add" +! procedure simplifies creation of a plot. The plot_data_2d object is not +! needed. Behind the scenes, the plot_data_2d object is created and can still +! be accessed, but this approach simplifies the interface for most typical +! use cases. +program example + use iso_fortran_env + use fplot_core + + ! Local Variables + integer(int32), parameter :: npts = 1000 + real(real64), parameter :: pi = 2.0d0 * acos(0.0d0) + real(real64) :: t(npts), x(npts) + type(plot_polar) :: plt + + ! Create a function to plot + t = linspace(-2.0d0 * pi, 2.0d0 * pi, npts) + x = t * sin(t) + + ! Plot the function + call plt%initialize() + call plt%set_font_size(14) + call plt%set_title("Polar Plot Example") + call plt%set_autoscale(.false.) + call plt%set_radial_limits([0.0d0, 6.0d0]) + call plt%push(t, x, lw = 2.0) + call plt%draw() +end program \ No newline at end of file diff --git a/fpm.toml b/fpm.toml index df2a1500..2bcfe2b1 100644 --- a/fpm.toml +++ b/fpm.toml @@ -1,5 +1,5 @@ name = "fplot" -version = "1.8.12" +version = "1.9.0" license = "GPL-3.0" author = "Jason Christopherson" maintainer = "Jason Christopherson" @@ -11,7 +11,6 @@ homepage = "https://github.com/jchristopherson/fplot" source-dir = "src" [dependencies] -ferror = { git = "https://github.com/jchristopherson/ferror" } collections = { git = "https://github.com/jchristopherson/collections" } fstring = { git = "https://github.com/jchristopherson/fstring" } geompack = { git = "https://github.com/jchristopherson/geompack" } diff --git a/images/custom_colormap.png b/images/custom_colormap.png index c09d6a39..5308a529 100644 Binary files a/images/custom_colormap.png and b/images/custom_colormap.png differ diff --git a/images/example_2d_plot_1.png b/images/example_2d_plot_1.png index 7128220d..c5c5cbc3 100644 Binary files a/images/example_2d_plot_1.png and b/images/example_2d_plot_1.png differ diff --git a/meson.build b/meson.build deleted file mode 100644 index 4291b8c0..00000000 --- a/meson.build +++ /dev/null @@ -1,16 +0,0 @@ -project('fplot', 'fortran') - -fcore_proj = subproject('fcore') -fcore_dep = fcore_proj.get_variable('fcore_dep') - -ferror_proj = subproject('ferror') -ferror_dep = ferror_proj.get_variable('ferror_dep') - -subdir('src') - -fplot_lib = static_library('fplot', sources, - dependencies: [fcore_dep, ferror_dep]) - -fplot_dep = declare_dependency(link_with: fplot_lib) - -subdir('examples') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 248004c0..a575f867 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,23 +49,9 @@ set(FPLOT_SOURCES ${FPLOT_SOURCES} PARENT_SCOPE) # Dependencies include(FetchContent) -find_package(ferror QUIET) find_package(collections 1.1.0 QUIET) find_package(geompack QUIET) find_package(fstring QUIET) -if (NOT ferror_FOUND) - message(STATUS "FERROR could not be found. A reference version will be employed.") - FetchContent_Declare( - ferror - GIT_REPOSITORY "https://github.com/jchristopherson/ferror" - ) - FetchContent_MakeAvailable(ferror) - set(FERROR_LIBRARIES ferror) - set(BUILD_FERROR TRUE) -else() - set(FERROR_LIBRARIES ferror::ferror) - set(BUILD_FERROR FALSE) -endif() if (NOT collections_FOUND) message(STATUS "COLLECTIONS could not be found. A reference version will be employed.") @@ -124,7 +110,6 @@ add_library(${PROJECT_NAME} ${FPLOT_SOURCES}) target_link_libraries( ${PROJECT_NAME} PUBLIC - ${FERROR_LIBRARIES} ${COLLECTIONS_LIBRARIES} ${GEOMPACK_LIBRARIES} ${FSTRING_LIBRARIES} @@ -165,11 +150,6 @@ install(DIRECTORY ${FPLOT_MOD_DIR} DESTINATION ${CMAKE_INSTALL_MODULEDIR}) # For static libraries, install dependency libraries if(${BUILD_SHARED_LIBS}) - if(${BUILD_FERROR}) - install(TARGETS ${FERROR_LIBRARIES} - ARCHIVE DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() if(${BUILD_COLLECTIONS}) install(TARGETS ${COLLECTIONS_LIBRARIES} ARCHIVE DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -186,11 +166,6 @@ if(${BUILD_SHARED_LIBS}) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() else() - if(${BUILD_FERROR}) - install(TARGETS ${FERROR_LIBRARIES} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - endif() if(${BUILD_COLLECTIONS}) install(TARGETS ${COLLECTIONS_LIBRARIES} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/fplot_colormap.f90 b/src/fplot_colormap.f90 index 17469e79..da4ec14c 100644 --- a/src/fplot_colormap.f90 +++ b/src/fplot_colormap.f90 @@ -4,7 +4,6 @@ module fplot_colormap use iso_fortran_env use fplot_plot_object use strings - use ferror use fplot_errors use fplot_colors use forcolormap, cmap => Colormap ! avoid conflict with the internally defined colormap type diff --git a/src/fplot_delaunay_tri_surface.f90 b/src/fplot_delaunay_tri_surface.f90 index 68efc630..1d6b1982 100644 --- a/src/fplot_delaunay_tri_surface.f90 +++ b/src/fplot_delaunay_tri_surface.f90 @@ -5,7 +5,6 @@ module fplot_delaunay_tri_surface use ieee_arithmetic use fplot_triangulations_delaunay_2d use fplot_errors - use ferror implicit none private public :: delaunay_tri_surface diff --git a/src/fplot_errors.f90 b/src/fplot_errors.f90 index 39fb79ed..7300a370 100644 --- a/src/fplot_errors.f90 +++ b/src/fplot_errors.f90 @@ -1,8 +1,12 @@ module fplot_errors use iso_fortran_env - use ferror implicit none + type :: errors + contains + procedure :: report_error + end type + ! ****************************************************************************** ! ERROR CODES ! ------------------------------------------------------------------------------ @@ -19,6 +23,17 @@ module fplot_errors !! Occurs if there is a GNUPLOT file error. contains +! ------------------------------------------------------------------------------ +subroutine report_error(this, fcn, msg, code) + class(errors), intent(inout) :: this + character(len = *), intent(in) :: fcn + character(len = *), intent(in) :: msg + integer(int32), intent(in) :: code + + write(error_unit, '(A)') trim(fcn) // ': ' // trim(msg) + error stop code +end subroutine + ! ------------------------------------------------------------------------------ subroutine report_memory_error(err, fcn, flag) !! Reports a memory allocation error. @@ -33,7 +48,7 @@ subroutine report_memory_error(err, fcn, flag) character(len = 256) :: msg ! Define the error message - write(100, msg) "Memory allocation error returning flag ", flag, "." + write(msg, 100) "Memory allocation error returning flag ", flag, "." call err%report_error(fcn, trim(msg), PLOT_OUT_OF_MEMORY_ERROR) ! Formatting @@ -56,7 +71,7 @@ subroutine report_file_create_error(err, fcn, fname, flag) character(len = 2048) :: msg ! Define the error message - write(100, msg) "File ", fname, " could not be created. The error flag ", & + write(msg, 100) "File ", fname, " could not be created. The error flag ", & flag, " was returned." call err%report_error(fcn, trim(msg), PLOT_GNUPLOT_FILE_ERROR) @@ -82,7 +97,7 @@ subroutine report_array_size_mismatch_error(err, fcn, name, expected, actual) character(len = 256) :: msg ! Define the message - write(100, msg) "Array ", name, " was found to be of length ", actual, & + write(msg, 100) "Array ", name, " was found to be of length ", actual, & ", but was expected to be of length ", expected, "." call err%report_error(fcn, trim(msg), PLOT_ARRAY_SIZE_MISMATCH_ERROR) @@ -113,7 +128,7 @@ subroutine report_matrix_size_mismatch_error(err, fcn, name, mexp, nexp, & character(len = 256) :: msg ! Define the error - write(100, msg) "Matrix ", name, " was expected to be of size ", mexp, & + write(msg, 100) "Matrix ", name, " was expected to be of size ", mexp, & "-by-", nexp, ", but was found to be of size ", mact, "-by-", nact, "." call err%report_error(fcn, trim(msg), PLOT_ARRAY_SIZE_MISMATCH_ERROR) diff --git a/src/fplot_filled_plot_data.f90 b/src/fplot_filled_plot_data.f90 index 08bb0c4e..60e3cd68 100644 --- a/src/fplot_filled_plot_data.f90 +++ b/src/fplot_filled_plot_data.f90 @@ -5,7 +5,6 @@ module fplot_filled_plot_data use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/src/fplot_multiplot.f90 b/src/fplot_multiplot.f90 index 571eb6fb..d1dbb0ef 100644 --- a/src/fplot_multiplot.f90 +++ b/src/fplot_multiplot.f90 @@ -13,7 +13,6 @@ module fplot_multiplot use fplot_constants use fplot_errors use collections - use ferror use strings implicit none private @@ -52,6 +51,7 @@ module fplot_multiplot procedure, public :: set_font_name => mp_set_font procedure, public :: get_font_size => mp_get_font_size procedure, public :: set_font_size => mp_set_font_size + procedure, public :: set_window_size => mp_set_window_size end type contains @@ -59,7 +59,7 @@ module fplot_multiplot function mp_get_command(this) result(x) !! Gets the GNUPLOT commands for this object. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. character(len = :), allocatable :: x !! The command string. @@ -108,7 +108,7 @@ function mp_get_command(this) result(x) subroutine mp_init(this, m, n, term, width, height, err) !! Initializes the multiplot object. class(multiplot), intent(inout) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32), intent(in) :: m !! The number of rows of plots. integer(int32), intent(in) :: n @@ -207,7 +207,7 @@ subroutine mp_init(this, m, n, term, width, height, err) subroutine mp_clean(this) !! Cleans up resources held by the multiplot object. type(multiplot), intent(inout) :: this - !! The multiplot object. + !! The [[multiplot]] object. if (associated(this%m_terminal)) deallocate(this%m_terminal) nullify(this%m_terminal) end subroutine @@ -216,7 +216,7 @@ subroutine mp_clean(this) pure function mp_get_rows(this) result(x) !! Gets the number of rows of plots. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32) :: x !! The row count. x = this%m_rows @@ -226,7 +226,7 @@ pure function mp_get_rows(this) result(x) pure function mp_get_cols(this) result(x) !! Gets the number of columns of plots. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32) :: x !! The column count. x = this%m_cols @@ -236,7 +236,7 @@ pure function mp_get_cols(this) result(x) pure function mp_get_count(this) result(x) !! Gets the total number of plots. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32) :: x !! The plot count. x = this%m_plots%count() @@ -246,7 +246,7 @@ pure function mp_get_count(this) result(x) function mp_get_title(this) result(x) !! Gets the multiplot's title. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. character(len = :), allocatable :: x !! The title. x = this%m_title @@ -256,7 +256,7 @@ function mp_get_title(this) result(x) subroutine mp_set_title(this, x) !! Sets the multiplot's title. class(multiplot), intent(inout) :: this - !! The multiplot object. + !! The [[multiplot]] object. character(len = *), intent(in) :: x !! The title. @@ -279,7 +279,7 @@ subroutine mp_draw(this, persist, err) !! Launches GNUPLOT and draws the multiplot per the current state of !! the command list. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. logical, intent(in), optional :: persist !! An optional parameter that can be used to keep GNUPLOT open. !! Set to true to force GNUPLOT to remain open; else, set to false @@ -337,7 +337,7 @@ subroutine mp_draw(this, persist, err) function mp_get(this, i, j) result(x) !! Gets the requested plot object. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32), intent(in) :: i !! The row index of the plot to retrieve. integer(int32), intent(in) :: j @@ -364,7 +364,7 @@ function mp_get(this, i, j) result(x) subroutine mp_set(this, i, j, x) !! Replaces the specified plot. class(multiplot), intent(inout) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32), intent(in) :: i !! The row index of the plot to replace. integer(int32), intent(in) :: j @@ -385,7 +385,7 @@ pure function mp_has_title(this) result(x) !! Gets a value determining if a title has been defined for the !! multiplot object. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. logical :: x !! Returns true if a title has been defined for this multiplot; !! else, returns false. @@ -396,7 +396,7 @@ pure function mp_has_title(this) result(x) function mp_get_term(this) result(x) !! Gets the GNUPLOT terminal object. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. class(terminal), pointer :: x !! A pointer to the terminal object. x => this%m_terminal @@ -406,7 +406,7 @@ function mp_get_term(this) result(x) subroutine mp_save(this, fname, err) !! Saves a GNUPLOT command file. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. character(len = *), intent(in) :: fname !! The filename. class(errors), intent(inout), optional, target :: err @@ -442,7 +442,7 @@ subroutine mp_save(this, fname, err) function mp_get_font(this) result(x) !! Gets the name of the font used for plot text. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. character(len = :), allocatable :: x !! The font name. class(terminal), pointer :: term @@ -454,7 +454,7 @@ function mp_get_font(this) result(x) subroutine mp_set_font(this, x) !! Sets the name of the font used for plot text. class(multiplot), intent(inout) :: this - !! The multiplot object. + !! The [[multiplot]] object. character(len = *), intent(in) :: x !! The font name. class(terminal), pointer :: term @@ -466,7 +466,7 @@ subroutine mp_set_font(this, x) function mp_get_font_size(this) result(x) !! Gets the size of the font used by the plot. class(multiplot), intent(in) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32) :: x !! The font size. class(terminal), pointer :: term @@ -478,7 +478,7 @@ function mp_get_font_size(this) result(x) subroutine mp_set_font_size(this, x) !! Sets the size of the font used by the plot. class(multiplot), intent(inout) :: this - !! The multiplot object. + !! The [[multiplot]] object. integer(int32), intent(in) :: x !! The font size. class(terminal), pointer :: term @@ -486,5 +486,23 @@ subroutine mp_set_font_size(this, x) call term%set_font_size(x) end subroutine +! ****************************************************************************** +! ADDED AUG. 16, 2026 - V1.9.0 +! ------------------------------------------------------------------------------ + subroutine mp_set_window_size(this, width, height) + !! Sets the height and width of the plot window. + class(multiplot), intent(inout) :: this + !! The [[multiplot]] object. + integer(int32), intent(in) :: width + !! The plot window width. + integer(int32), intent(in) :: height + !! The plot window height. + + if (associated(this%m_terminal)) then + call this%m_terminal%set_window_width(width) + call this%m_terminal%set_window_height(height) + end if + end subroutine + ! ------------------------------------------------------------------------------ end module diff --git a/src/fplot_plot.f90 b/src/fplot_plot.f90 index de6cf50e..b22e81b7 100644 --- a/src/fplot_plot.f90 +++ b/src/fplot_plot.f90 @@ -18,7 +18,6 @@ module fplot_plot use fplot_label use fplot_arrow use fplot_plot_data_function - use ferror use strings use collections implicit none @@ -68,7 +67,8 @@ module fplot_plot procedure, public :: is_title_defined => plt_has_title procedure, public :: get_legend => plt_get_legend procedure, public :: get_count => plt_get_count - procedure, public :: push => plt_push_data + procedure, public :: plt_push_data + generic, public :: push => plt_push_data procedure, public :: pop => plt_pop_data procedure, public :: clear_all => plt_clear_all procedure, public :: get => plt_get @@ -113,6 +113,8 @@ module fplot_plot procedure, public :: set_top_margin => plt_set_top_margin procedure, public :: get_bottom_margin => plt_get_bottom_margin procedure, public :: set_bottom_margin => plt_set_bottom_margin + procedure, public :: show_legend => plt_show_legend + procedure, public :: set_window_size => plt_set_window_size end type contains @@ -139,7 +141,7 @@ subroutine plt_clean_up(this) !! classes are expected to call this routine to free internally held !! resources. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. if (associated(this%m_terminal)) then deallocate(this%m_terminal) nullify(this%m_terminal) @@ -158,7 +160,7 @@ subroutine plt_clean_up(this) subroutine plt_init(this, term, fname, err) !! Initializes the plot object. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in), optional :: term !! An optional input that is used to define the terminal. !! The default terminal is a WXT terminal. The acceptable inputs @@ -242,7 +244,7 @@ subroutine plt_init(this, term, fname, err) function plt_get_title(this) result(txt) !! Gets the plot's title. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. character(len = :), allocatable :: txt !! The title. integer(int32) :: n @@ -255,7 +257,7 @@ function plt_get_title(this) result(txt) subroutine plt_set_title(this, txt) !! Sets the plot's title. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. character(len = *), intent(in) :: txt !! The title. integer :: n @@ -274,7 +276,7 @@ pure function plt_has_title(this) result(x) !! Gets a value determining if a title has been defined for the plot !! object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical :: x !! Returns true if a title has been defined for this plot; else, !! returns false. @@ -285,7 +287,7 @@ pure function plt_has_title(this) result(x) function plt_get_legend(this) result(x) !! Gets the plot's legend object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. type(legend), pointer :: x !! A pointer to the legend object. x => this%m_legend @@ -295,7 +297,7 @@ function plt_get_legend(this) result(x) pure function plt_get_count(this) result(x) !! Gets the number of stored plot_data objects. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32) :: x !! The number of plot_data objects. x = this%m_data%count() @@ -305,7 +307,7 @@ pure function plt_get_count(this) result(x) subroutine plt_push_data(this, x, err) !! Pushes a plot_data object onto the stack. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. class(plot_data), intent(inout) :: x !! The plot_data object. class(errors), intent(inout), optional, target :: err @@ -330,7 +332,7 @@ subroutine plt_push_data(this, x, err) subroutine plt_pop_data(this) !! Pops the last plot_data object from the stack. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. ! Process call this%m_data%pop() @@ -340,7 +342,7 @@ subroutine plt_pop_data(this) subroutine plt_clear_all(this) !! Removes all plot_data objects from the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. ! Process this%m_colorIndex = 1 @@ -351,7 +353,7 @@ subroutine plt_clear_all(this) function plt_get(this, i) result(x) !! Gets a pointer to the requested plot_data object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: i !! The index of the plot_data object. class(plot_data), pointer :: x @@ -375,7 +377,7 @@ function plt_get(this, i) result(x) subroutine plt_set(this, i, x) !! Sets the requested plot_data object into the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: i !! The index of the plot_data object. class(plot_data), intent(in) :: x @@ -387,7 +389,7 @@ subroutine plt_set(this, i, x) function plt_get_term(this) result(x) !! Gets the GNUPLOT terminal object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. class(terminal), pointer :: x !! A pointer to the GNUPLOT terminal object. x => this%m_terminal @@ -397,7 +399,7 @@ function plt_get_term(this) result(x) pure function plt_get_show_grid(this) result(x) !! Gets a flag determining if the grid lines should be shown. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical :: x !! Returns true if the grid lines should be shown; else, false. x = this%m_showGrid @@ -407,7 +409,7 @@ pure function plt_get_show_grid(this) result(x) subroutine plt_set_show_grid(this, x) !! Sets a flag determining if the grid lines should be shown. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. logical, intent(in) :: x !! Set to true if the grid lines should be shown; else, false. this%m_showGrid = x @@ -418,7 +420,7 @@ subroutine plt_draw(this, persist, err) !! Launches GNUPLOT and draws the plot per the current state of !! the command list. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical, intent(in), optional :: persist !! An optional parameter that can be used to keep GNUPLOT open. !! Set to true to force GNUPLOT to remain open; else, set to false @@ -476,7 +478,7 @@ subroutine plt_draw(this, persist, err) subroutine plt_save(this, fname, err) !! Saves a GNUPLOT command file. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. character(len = *), intent(in) :: fname !! The filename. class(errors), intent(inout), optional, target :: err @@ -512,7 +514,7 @@ subroutine plt_save(this, fname, err) function plt_get_font(this) result(x) !! Gets the name of the font used for plot text. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. character(len = :), allocatable :: x !! The font name. class(terminal), pointer :: term @@ -524,7 +526,7 @@ function plt_get_font(this) result(x) subroutine plt_set_font(this, x) !! Sets the name of the font used for plot text. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. character(len = *), intent(in) :: x !! The font name. class(terminal), pointer :: term @@ -536,7 +538,7 @@ subroutine plt_set_font(this, x) function plt_get_font_size(this) result(x) !! Gets the size of the font used by the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32) :: x !! The size of the font, in points. class(terminal), pointer :: term @@ -548,7 +550,7 @@ function plt_get_font_size(this) result(x) subroutine plt_set_font_size(this, x) !! Sets the size of the font used by the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: x !! The font size, in points. If a value of zero is provided, !! the font size is reset to its default value; or, if a negative @@ -563,7 +565,7 @@ subroutine plt_set_font_size(this, x) pure function plt_get_tics_in(this) result(x) !! Gets a value determining if the axis tic marks should point inwards. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical :: x !! Returns true if the tic marks should point inwards; else, false !! if the tic marks should point outwards. @@ -574,7 +576,7 @@ pure function plt_get_tics_in(this) result(x) subroutine plt_set_tics_in(this, x) !! Sets a value determining if the axis tic marks should point inwards. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. logical, intent(in) :: x !! Set to true if the tic marks should point inwards; else, false !! if the tic marks should point outwards. @@ -585,7 +587,7 @@ subroutine plt_set_tics_in(this, x) pure function plt_get_draw_border(this) result(x) !! Gets a value determining if the border should be drawn. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical :: x !! Returns true if the border should be drawn; else, false. x = this%m_drawBorder @@ -595,7 +597,7 @@ pure function plt_get_draw_border(this) result(x) subroutine plt_set_draw_border(this, x) !! Sets a value determining if the border should be drawn. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. logical, intent(in) :: x !! Set to true if the border should be drawn; else, false. this%m_drawBorder = x @@ -607,7 +609,7 @@ subroutine plt_set_draw_border(this, x) subroutine plt_push_label(this, lbl, err) !! Adds a label to the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. class(plot_label), intent(in) :: lbl !! The plot label. class(errors), intent(inout), optional, target :: err @@ -621,7 +623,7 @@ subroutine plt_push_label(this, lbl, err) subroutine plt_pop_label(this) !! Removes the last label from the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. call this%m_labels%pop() end subroutine @@ -629,7 +631,7 @@ subroutine plt_pop_label(this) function plt_get_label(this, i) result(x) !! Gets the requested plot_label from the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: i !! The index of the plot_label object to retrieve. class(plot_label), pointer :: x @@ -652,7 +654,7 @@ function plt_get_label(this, i) result(x) subroutine plt_set_label(this, i, x) !! Sets the specified plot_label object. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: i !! The index of the plot_label to replace. class(plot_label), intent(in) :: x @@ -664,7 +666,7 @@ subroutine plt_set_label(this, i, x) pure function plt_get_label_count(this) result(x) !! Gets the number of plot_label objects belonging to the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32) :: x !! The number of plot_label objects. x = this%m_labels%count() @@ -674,7 +676,7 @@ pure function plt_get_label_count(this) result(x) subroutine plt_clear_labels(this) !! Clears all plot_label objects from the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. call this%m_labels%clear() end subroutine @@ -684,7 +686,7 @@ subroutine plt_clear_labels(this) pure function plt_get_axis_equal(this) result(rst) !! Gets a flag determining if the axes should be equally scaled. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical :: rst !! Returns true if the axes should be scaled equally; else, false. rst = this%m_axisEqual @@ -694,7 +696,7 @@ pure function plt_get_axis_equal(this) result(rst) subroutine plt_set_axis_equal(this, x) !! Sets a flag determining if the axes should be equally scaled. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. logical, intent(in) :: x !! Set to true if the axes should be scaled equally; else, false. this%m_axisEqual = x @@ -706,7 +708,7 @@ subroutine plt_set_axis_equal(this, x) function plt_get_colormap(this) result(x) !! Gets a pointer to the colormap object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. class(colormap), pointer :: x !! A pointer to the colormap object. If no colormap is defined, a !! null pointer is returned. @@ -717,7 +719,7 @@ function plt_get_colormap(this) result(x) subroutine plt_set_colormap(this, x, err) !! Sets the colormap object. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. class(colormap), intent(in) :: x !! The colormap object. Notice, a copy of this object is !! stored, and the plot object then manages the lifetime of the @@ -751,7 +753,7 @@ subroutine plt_set_colormap(this, x, err) pure function plt_get_show_colorbar(this) result(x) !! Gets a value determining if the colorbar should be shown. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. logical :: x !! Returns true if the colorbar should be drawn; else, false. x = this%m_showColorbar @@ -761,7 +763,7 @@ pure function plt_get_show_colorbar(this) result(x) subroutine plt_set_show_colorbar(this, x) !! Sets a value determining if the colorbar should be shown. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. logical, intent(in) :: x !! Set to true if the colorbar should be drawn; else, false. this%m_showColorbar = x @@ -771,7 +773,7 @@ subroutine plt_set_show_colorbar(this, x) function plt_get_cmd(this) result(x) !! Gets the GNUPLOT command string to represent this plot object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. character(len = :), allocatable :: x !! The command string. @@ -824,7 +826,7 @@ function plt_get_cmd(this) result(x) subroutine plt_push_arrow(this, x, err) !! Pushes a new @ref plot_arrow object onto the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. class(plot_arrow), intent(in) :: x !! The plot_arrow object. class(errors), intent(inout), optional, target :: err @@ -836,7 +838,7 @@ subroutine plt_push_arrow(this, x, err) subroutine plt_pop_arrow(this) !! Pops the last plot_arrow object from the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. call this%m_arrows%pop() end subroutine @@ -844,7 +846,7 @@ subroutine plt_pop_arrow(this) function plt_get_arrow(this, i) result(rst) !! Gets a pointer to the requested plot_arrow object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: i !! The index of the plot_arrow to retrieve. class(plot_arrow), pointer :: rst @@ -864,7 +866,7 @@ function plt_get_arrow(this, i) result(rst) subroutine plt_set_arrow(this, i, x) !! Sets a plot_arrow into the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. integer(int32), intent(in) :: i !! The index of the plot_arrow object to replace. class(plot_arrow), intent(in) :: x @@ -876,7 +878,7 @@ subroutine plt_set_arrow(this, i, x) pure function plt_get_arrow_count(this) result(rst) !! Gets the number of plot_arrow objects held by the plot object. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. integer(int32) :: rst !! The plot_arrow objects count. rst = this%m_arrows%count() @@ -886,7 +888,7 @@ pure function plt_get_arrow_count(this) result(rst) subroutine plt_clear_arrows(this) !! Clears all plot_arrow objects from the plot. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. call this%m_arrows%clear() end subroutine @@ -896,7 +898,7 @@ subroutine plt_clear_arrows(this) pure function plt_get_left_margin(this) result(x) !! Gets the left margin of the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. real(real32) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -908,7 +910,7 @@ subroutine plt_set_left_margin(this, x) !! Sets the left margin of the plot. If the value is negative, the !! default margin is used. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. real(real32), intent(in) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -919,7 +921,7 @@ subroutine plt_set_left_margin(this, x) pure function plt_get_right_margin(this) result(x) !! Gets the right margin of the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. real(real32) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -931,7 +933,7 @@ subroutine plt_set_right_margin(this, x) !! Sets the right margin of the plot. If the value is negative, the !! default margin is used. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. real(real32), intent(in) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -942,7 +944,7 @@ subroutine plt_set_right_margin(this, x) pure function plt_get_top_margin(this) result(x) !! Gets the top margin of the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. real(real32) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -954,7 +956,7 @@ subroutine plt_set_top_margin(this, x) !! Sets the top margin of the plot. If the value is negative, the !! default margin is used. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. real(real32), intent(in) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -965,7 +967,7 @@ subroutine plt_set_top_margin(this, x) pure function plt_get_bottom_margin(this) result(x) !! Gets the bottom margin of the plot. class(plot), intent(in) :: this - !! The plot object. + !! The [[plot]] object. real(real32) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. @@ -977,12 +979,43 @@ subroutine plt_set_bottom_margin(this, x) !! Sets the bottom margin of the plot. If the value is negative, the !! default margin is used. class(plot), intent(inout) :: this - !! The plot object. + !! The [[plot]] object. real(real32), intent(in) :: x !! The margin, in percent of screen. A negative value indicates the !! default margin is used. this%m_bottomMargin = x end subroutine +! ****************************************************************************** +! ADDED AUG. 16, 2026 - V1.9.0 +! ------------------------------------------------------------------------------ + subroutine plt_show_legend(this, x) + !! Sets a value determining the legend should be shown. + class(plot), intent(inout) :: this + !! The [[plot]] object. + logical, intent(in) :: x + !! Set to true to show the legend; else, set to false. + + if (associated(this%m_legend)) then + call this%m_legend%set_is_visible(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine plt_set_window_size(this, width, height) + !! Sets the height and width of the plot window. + class(plot), intent(inout) :: this + !! The [[plot]] object. + integer(int32), intent(in) :: width + !! The plot window width. + integer(int32), intent(in) :: height + !! The plot window height. + + if (associated(this%m_terminal)) then + call this%m_terminal%set_window_width(width) + call this%m_terminal%set_window_height(height) + end if + end subroutine + ! ------------------------------------------------------------------------------ end module \ No newline at end of file diff --git a/src/fplot_plot_2d.f90 b/src/fplot_plot_2d.f90 index dbc5f7e2..345f1fb9 100644 --- a/src/fplot_plot_2d.f90 +++ b/src/fplot_plot_2d.f90 @@ -6,7 +6,8 @@ module fplot_plot_2d use fplot_errors use fplot_plot_axis use fplot_legend - use ferror + use fplot_plot_data_2d + use fplot_colors use strings implicit none private @@ -47,6 +48,11 @@ module fplot_plot_2d procedure, public :: set_jitter_overlap => p2d_set_jitter_overlap procedure, public :: get_jitter_spread => p2d_get_jitter_spread procedure, public :: set_jitter_spread => p2d_set_jitter_spread + procedure, public :: set_x_axis_title => p2d_set_x_axis_title + procedure, public :: set_y_axis_title => p2d_set_y_axis_title + procedure, public :: set_y2_axis_title => p2d_set_y2_axis_title + procedure, public :: p2d_push_data + generic, public :: push => p2d_push_data end type contains @@ -54,7 +60,7 @@ module fplot_plot_2d subroutine p2d_clean_up(this) !! Cleans up resources held by the plot_2d object. type(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. call this%free_resources() if (associated(this%m_xAxis)) then deallocate(this%m_xAxis) @@ -74,7 +80,7 @@ subroutine p2d_clean_up(this) subroutine p2d_init(this, term, fname, err) !! Initializes the plot_2d object. class(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. integer(int32), intent(in), optional :: term !! An optional input that is used to define the terminal. !! The default terminal is a WXT terminal. The acceptable inputs @@ -110,7 +116,6 @@ subroutine p2d_init(this, term, fname, err) ! Initialize the base class ! call plt_init(this, term, fname, errmgr) call this%plot%initialize(term, fname, errmgr) - if (errmgr%has_error_occurred()) return ! Process flag = 0 @@ -135,7 +140,7 @@ subroutine p2d_init(this, term, fname, err) function p2d_get_cmd(this) result(x) !! Gets the GNUPLOT command string to represent this plot_2d object. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. character(len = :), allocatable :: x !! The command string. @@ -332,7 +337,7 @@ function p2d_get_cmd(this) result(x) function p2d_get_x_axis(this) result(ptr) !! Gets the x-axis object. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. class(plot_axis), pointer :: ptr !! A pointer to the x-axis object. ptr => this%m_xAxis @@ -342,7 +347,7 @@ function p2d_get_x_axis(this) result(ptr) function p2d_get_y_axis(this) result(ptr) !! Gets the y-axis object. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. class(plot_axis), pointer :: ptr !! A pointer to the y-axis object. ptr => this%m_yAxis @@ -352,7 +357,7 @@ function p2d_get_y_axis(this) result(ptr) function p2d_get_y2_axis(this) result(ptr) !! Gets the secondary y-axis object. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. class(plot_axis), pointer :: ptr !! A pointer to the secondary y-axis object. ptr => this%m_y2Axis @@ -363,7 +368,7 @@ pure function p2d_get_use_y2(this) result(x) !! Gets a flag determining if the secondary y-axis should be !! displayed. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. logical :: x !! Returns true if the axis should be displayed; else, false. x = this%m_useY2 @@ -374,7 +379,7 @@ subroutine p2d_set_use_y2(this, x) !! Sets a flag determining if the secondary y-axis should be !! displayed. class(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. logical, intent(in) :: x !! Set to true if the axis should be displayed; else, false. this%m_useY2 = x @@ -385,7 +390,7 @@ pure function p2d_get_square_axes(this) result(rst) !! Gets a logical flag determining if the axes size should be squared !! off. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. logical :: rst !! Returns true if the axes are to be sized to a square; else, !! false. @@ -397,7 +402,7 @@ subroutine p2d_set_square_axes(this, x) !! Sets a logical flag determining if the axes size should be !! squared off. class(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. logical, intent(in) :: x !! Set to true if the axes are to be sized to a square; else, !! false. @@ -408,7 +413,7 @@ subroutine p2d_set_square_axes(this, x) pure function p2d_get_use_jitter(this) result(rst) !! Gets a logical value determining if jittering should be used. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. logical :: rst !! True if jittering should be used; else, false. rst = this%m_useJitter @@ -418,7 +423,7 @@ pure function p2d_get_use_jitter(this) result(rst) subroutine p2d_set_use_jitter(this, x) !! Sets a logical value determining if jittering should be used. class(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. logical, intent(in) :: x !! Set to true if jittering should be used; else, false. this%m_useJitter = x @@ -428,7 +433,7 @@ subroutine p2d_set_use_jitter(this, x) pure function p2d_get_jitter_overlap(this) result(rst) !! Gets the jitter overalp. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. real(real32) :: rst !! The jitter overlap. rst = this%m_jitterOverlap @@ -438,7 +443,7 @@ pure function p2d_get_jitter_overlap(this) result(rst) subroutine p2d_set_jitter_overlap(this, x) !! Sets the jitter overlap. class(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. real(real32), intent(in) :: x !! The jitter overlap. this%m_jitterOverlap = x @@ -448,7 +453,7 @@ subroutine p2d_set_jitter_overlap(this, x) pure function p2d_get_jitter_spread(this) result(rst) !! Gets the jitter horizontal spread. class(plot_2d), intent(in) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. real(real32) :: rst !! The jitter horizontal spread. rst = this%m_jitterSpread @@ -458,11 +463,87 @@ pure function p2d_get_jitter_spread(this) result(rst) subroutine p2d_set_jitter_spread(this, x) !! Sets the jitter horizontal spread. class(plot_2d), intent(inout) :: this - !! The plot_2d object. + !! The [[plot_2d]] object. real(real32), intent(in) :: x !! The jitter horizontal spread. this%m_jitterSpread = x end subroutine +! ------------------------------------------------------------------------------ + subroutine p2d_set_x_axis_title(this, x) + !! Sets the title associated with the plot's x-axis. + class(plot_2d), intent(inout) :: this + !! The [[plot_2d]] object. + character(len = *), intent(in) :: x + !! The title. + + if (associated(this%m_xAxis)) then + call this%m_xAxis%set_title(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine p2d_set_y_axis_title(this, x) + !! Sets the title associated with the plot's y-axis. + class(plot_2d), intent(inout) :: this + !! The [[plot_2d]] object. + character(len = *), intent(in) :: x + !! The title. + + if (associated(this%m_yAxis)) then + call this%m_yAxis%set_title(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine p2d_set_y2_axis_title(this, x) + !! Sets the title associated with the plot's secondary y-axis. + class(plot_2d), intent(inout) :: this + !! The [[plot_2d]] object. + character(len = *), intent(in) :: x + !! The title. + + if (associated(this%m_y2Axis)) then + call this%m_y2Axis%set_title(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine p2d_push_data(this, x, y, lw, name, ls, lc) + !! Adds a data set to the plot. + class(plot_2d), intent(inout) :: this + !! The [[plot_2d]] object. + real(real64), intent(in), dimension(:) :: x + !! The x-values. + real(real64), intent(in), dimension(size(x)) :: y + !! The y-values. + real(real32), intent(in), optional :: lw + !! The line width. + character(len = *), intent(in), optional :: name + !! A name to associate with the data set. + integer(int32), intent(in), optional :: ls + !! The line style. The line style must be one of the following. + !! + !! - LINE_DASHED + !! + !! - LINE_DASH_DOTTED + !! + !! - LINE_DASH_DOT_DOT + !! + !! - LINE_DOTTED + !! + !! - LINE_SOLID + type(color), intent(in), optional :: lc + !! The line color. + + type(plot_data_2d) :: pd + call pd%define_data(x, y) + if (present(lw)) call pd%set_line_width(lw) + if (present(name)) call pd%set_name(name) + if (present(ls)) call pd%set_line_style(ls) + if (present(lc)) call pd%set_line_color(lc) + call this%push(pd) + end subroutine + ! ------------------------------------------------------------------------------ end module diff --git a/src/fplot_plot_3d.f90 b/src/fplot_plot_3d.f90 index 51c351e5..33dd1740 100644 --- a/src/fplot_plot_3d.f90 +++ b/src/fplot_plot_3d.f90 @@ -8,7 +8,8 @@ module fplot_plot_3d use fplot_constants use fplot_plot_data use fplot_legend - use ferror + use fplot_plot_data_3d + use fplot_colors use strings implicit none private @@ -49,6 +50,11 @@ module fplot_plot_3d procedure, public :: set_use_map_view => p3d_set_use_map_view procedure, public :: get_coordinate_system => p3d_get_csys procedure, public :: set_coordinate_system => p3d_set_csys + procedure, public :: set_x_axis_title => p3d_set_x_axis_title + procedure, public :: set_y_axis_title => p3d_set_y_axis_title + procedure, public :: set_z_axis_title => p3d_set_z_axis_title + procedure, public :: p3d_push_data + generic, public :: push => p3d_push_data end type contains @@ -112,7 +118,6 @@ subroutine p3d_init(this, term, fname, err) ! Initialize the base class ! call plt_init(this, term, fname, errmgr) call this%plot%initialize(term, fname, errmgr) - if (errmgr%has_error_occurred()) return ! Process flag = 0 @@ -476,5 +481,83 @@ subroutine p3d_set_csys(this, x) end if end subroutine +! ------------------------------------------------------------------------------ + subroutine p3d_set_x_axis_title(this, x) + !! Sets the title associated with the plot's x-axis. + class(plot_3d), intent(inout) :: this + !! The [[plot_3d]] object. + character(len = *), intent(in) :: x + !! The title. + + if (associated(this%m_xAxis)) then + call this%m_xAxis%set_title(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine p3d_set_y_axis_title(this, x) + !! Sets the title associated with the plot's y-axis. + class(plot_3d), intent(inout) :: this + !! The [[plot_3d]] object. + character(len = *), intent(in) :: x + !! The title. + + if (associated(this%m_yAxis)) then + call this%m_yAxis%set_title(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine p3d_set_z_axis_title(this, x) + !! Sets the title associated with the plot's z-axis. + class(plot_3d), intent(inout) :: this + !! The [[plot_3d]] object. + character(len = *), intent(in) :: x + !! The title. + + if (associated(this%m_zAxis)) then + call this%m_zAxis%set_title(x) + end if + end subroutine + +! ------------------------------------------------------------------------------ + subroutine p3d_push_data(this, x, y, z, lw, name, ls, lc) + !! Adds a data set to the plot. + class(plot_3d), intent(inout) :: this + !! The [[plot_3d]] object. + real(real64), intent(in), dimension(:) :: x + !! The x-values. + real(real64), intent(in), dimension(size(x)) :: y + !! The y-values. + real(real64), intent(in), dimension(size(x)) :: z + !! The z-values. + real(real32), intent(in), optional :: lw + !! The line width. + character(len = *), intent(in), optional :: name + !! A name to associate with the data set. + integer(int32), intent(in), optional :: ls + !! The line style. The line style must be one of the following. + !! + !! - LINE_DASHED + !! + !! - LINE_DASH_DOTTED + !! + !! - LINE_DASH_DOT_DOT + !! + !! - LINE_DOTTED + !! + !! - LINE_SOLID + type(color), intent(in), optional :: lc + !! The line color. + + type(plot_data_3d) :: pd + call pd%define_data(x, y, z) + if (present(lw)) call pd%set_line_width(lw) + if (present(name)) call pd%set_name(name) + if (present(ls)) call pd%set_line_style(ls) + if (present(lc)) call pd%set_line_color(lc) + call this%push(pd) + end subroutine + ! ------------------------------------------------------------------------------ end module diff --git a/src/fplot_plot_data.f90 b/src/fplot_plot_data.f90 index 49fc3ac1..894a77b6 100644 --- a/src/fplot_plot_data.f90 +++ b/src/fplot_plot_data.f90 @@ -6,7 +6,6 @@ module fplot_plot_data use fplot_constants use fplot_colors use strings - use ferror use fplot_errors implicit none private diff --git a/src/fplot_plot_data_2d.f90 b/src/fplot_plot_data_2d.f90 index cb997ac3..c1a36395 100644 --- a/src/fplot_plot_data_2d.f90 +++ b/src/fplot_plot_data_2d.f90 @@ -3,7 +3,6 @@ module fplot_plot_data_2d use fplot_plot_data use fplot_simplify use fplot_errors - use ferror use strings implicit none private diff --git a/src/fplot_plot_data_3d.f90 b/src/fplot_plot_data_3d.f90 index 1a6feb9d..a1ae3eac 100644 --- a/src/fplot_plot_data_3d.f90 +++ b/src/fplot_plot_data_3d.f90 @@ -3,7 +3,6 @@ module fplot_plot_data_3d use fplot_plot_data use fplot_errors use fplot_simplify - use ferror use strings implicit none private diff --git a/src/fplot_plot_data_bar.f90 b/src/fplot_plot_data_bar.f90 index ecabaad2..06516f73 100644 --- a/src/fplot_plot_data_bar.f90 +++ b/src/fplot_plot_data_bar.f90 @@ -6,7 +6,6 @@ module fplot_plot_data_bar use fplot_errors use fplot_colors use strings - use ferror implicit none private public :: plot_data_bar diff --git a/src/fplot_plot_data_box_whisker.f90 b/src/fplot_plot_data_box_whisker.f90 index 0f83579d..b01bd549 100644 --- a/src/fplot_plot_data_box_whisker.f90 +++ b/src/fplot_plot_data_box_whisker.f90 @@ -3,7 +3,6 @@ module fplot_plot_data_box_whisker use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/src/fplot_plot_data_error_bars.f90 b/src/fplot_plot_data_error_bars.f90 index bcb2d909..7482de2f 100644 --- a/src/fplot_plot_data_error_bars.f90 +++ b/src/fplot_plot_data_error_bars.f90 @@ -5,7 +5,6 @@ module fplot_plot_data_error_bars use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/src/fplot_plot_data_histogram.f90 b/src/fplot_plot_data_histogram.f90 index 1e4e2733..4b2d8309 100644 --- a/src/fplot_plot_data_histogram.f90 +++ b/src/fplot_plot_data_histogram.f90 @@ -4,7 +4,6 @@ module fplot_plot_data_histogram use iso_fortran_env use fplot_plot_data use fplot_errors - use ferror use strings use fplot_colors implicit none diff --git a/src/fplot_plot_polar.f90 b/src/fplot_plot_polar.f90 index c08d2575..2f22eef5 100644 --- a/src/fplot_plot_polar.f90 +++ b/src/fplot_plot_polar.f90 @@ -8,7 +8,8 @@ module fplot_plot_polar use fplot_constants use fplot_legend use fplot_plot_data - use ferror + use fplot_plot_data_2d + use fplot_colors use strings implicit none private @@ -40,6 +41,8 @@ module fplot_plot_polar procedure, public :: set_theta_start_position => plr_set_theta_start procedure, public :: get_theta_direction => plr_get_theta_direction procedure, public :: set_theta_direction => plr_set_theta_direction + procedure, public :: plr_push_data + generic, public :: push => plr_push_data end type contains @@ -90,7 +93,6 @@ subroutine plr_init(this, term, fname, err) ! Initialize the base class ! call plt_init(this, term, fname, errmgr) call this%plot%initialize(term, fname, errmgr) - if (errmgr%has_error_occurred()) return ! Initialize the rest of the object this%m_thetaStart = POLAR_THETA_RIGHT @@ -371,5 +373,42 @@ subroutine plr_set_theta_direction(this, x) end if end subroutine +! ------------------------------------------------------------------------------ + subroutine plr_push_data(this, angle, radial, lw, name, ls, lc) + !! Adds a data set to the plot. + class(plot_polar), intent(inout) :: this + !! The [[plot_polar]] object. + real(real64), intent(in), dimension(:) :: angle + !! The angular values. + real(real64), intent(in), dimension(size(angle)) :: radial + !! The radial values. + real(real32), intent(in), optional :: lw + !! The line width. + character(len = *), intent(in), optional :: name + !! A name to associate with the data set. + integer(int32), intent(in), optional :: ls + !! The line style. The line style must be one of the following. + !! + !! - LINE_DASHED + !! + !! - LINE_DASH_DOTTED + !! + !! - LINE_DASH_DOT_DOT + !! + !! - LINE_DOTTED + !! + !! - LINE_SOLID + type(color), intent(in), optional :: lc + !! The line color. + + type(plot_data_2d) :: pd + call pd%define_data(angle, radial) + if (present(lw)) call pd%set_line_width(lw) + if (present(name)) call pd%set_name(name) + if (present(ls)) call pd%set_line_style(ls) + if (present(lc)) call pd%set_line_color(lc) + call this%push(pd) + end subroutine + ! ------------------------------------------------------------------------------ end module diff --git a/src/fplot_simplify.f90 b/src/fplot_simplify.f90 index f2c03bf5..5164f861 100644 --- a/src/fplot_simplify.f90 +++ b/src/fplot_simplify.f90 @@ -6,7 +6,6 @@ module fplot_simplify use iso_fortran_env - use ferror use fplot_errors implicit none private diff --git a/src/fplot_stats_plots.f90 b/src/fplot_stats_plots.f90 index 6e5871ac..a6ea17df 100644 --- a/src/fplot_stats_plots.f90 +++ b/src/fplot_stats_plots.f90 @@ -13,7 +13,6 @@ module fplot_stats_plots use fplot_plot_axis use collections use strings - use ferror implicit none private public :: correlation_plot @@ -100,7 +99,6 @@ subroutine cp_init(this, x, labels, term, width, height, err) n = size(x, 2) call this%m_plt%initialize(n, n, term = term, width = width, & height = height, err = errmgr) - if (errmgr%has_error_occurred()) return allocate(plts(n * n), stat = flag) if (flag /= 0) then call report_memory_error(errmgr, "cp_init", flag) @@ -125,21 +123,17 @@ subroutine cp_init(this, x, labels, term, width, height, err) call pdata%set_marker_scaling(0.5) call mdata%set_line_width(2.0) call mdata%set_line_color(CLR_BLACK) - if (errmgr%has_error_occurred()) return do j = 1, n do i = 1, n k = k + 1 call plts(k)%initialize(err = errmgr) - if (errmgr%has_error_occurred()) return if (i == j) then ! Plot a histogram of the data call hdata%define_data(x(:,i), err = errmgr) - if (errmgr%has_error_occurred()) return call plts(k)%push(hdata) else ! Plot a scatter plot call pdata%define_data(x(:,j), x(:,i), err = errmgr) - if (errmgr%has_error_occurred()) return call plts(k)%push(pdata) ! Fit a line to the data @@ -148,7 +142,6 @@ subroutine cp_init(this, x, labels, term, width, height, err) ! Plot the fitted line call mdata%define_data(x(:,j), mdl, err = err) - if (errmgr%has_error_occurred()) return call plts(k)%push(mdata) end if diff --git a/src/fplot_surface_plot.f90 b/src/fplot_surface_plot.f90 index 06d1f291..246eecb5 100644 --- a/src/fplot_surface_plot.f90 +++ b/src/fplot_surface_plot.f90 @@ -5,7 +5,7 @@ module fplot_surface_plot use fplot_plot_3d use fplot_errors use fplot_legend - use ferror + use fplot_surface_plot_data use strings implicit none private @@ -43,6 +43,8 @@ module fplot_surface_plot procedure, public :: set_specular_intensity => surf_set_specular_intensity procedure, public :: get_transparency => surf_get_transparency procedure, public :: set_transparency => surf_set_transparency + procedure, public :: surf_push_data + generic, public :: push => surf_push_data end type contains @@ -50,7 +52,7 @@ module fplot_surface_plot subroutine surf_init(this, term, fname, err) !! Initializes the surface_plot object. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. integer(int32), intent(in), optional :: term !! An optional input that is used to define the terminal. !! The default terminal is a WXT terminal. The acceptable inputs @@ -86,7 +88,7 @@ subroutine surf_init(this, term, fname, err) pure function surf_get_show_hidden(this) result(x) !! Gets a value indicating if hidden lines should be shown. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical :: x !! Returns true if hidden lines should be shown; else, false. x = this%m_showHidden @@ -96,7 +98,7 @@ pure function surf_get_show_hidden(this) result(x) subroutine surf_set_show_hidden(this, x) !! Sets a value indicating if hidden lines should be shown. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical, intent(in) :: x !! Set to true if hidden lines should be shown; else, false. this%m_showHidden = x @@ -107,7 +109,7 @@ function surf_get_cmd(this) result(x) !! Gets the GNUPLOT command string to represent this plot_3d !! object. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. character(len = :), allocatable :: x !! The command string. @@ -219,7 +221,7 @@ pure function surf_get_smooth(this) result(x) !! Gets a value determining if the plotted surfaces should be !! smoothed. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical :: x !! Returns true if the surface should be smoothed; else, false. x = this%m_smooth @@ -230,7 +232,7 @@ subroutine surf_set_smooth(this, x) !! Sets a value determining if the plotted surfaces should be !! smoothed. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical, intent(in) :: x !! Set to true if the surface should be smoothed; else, false. this%m_smooth = x @@ -241,7 +243,7 @@ pure function surf_get_show_contours(this) result(x) !! Gets a value determining if a contour plot should be drawn in !! conjunction with the surface plot. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical :: x !! Returns true if the contour plot should be drawn; else, false to !! only draw the surface. @@ -253,7 +255,7 @@ subroutine surf_set_show_contours(this, x) !! Sets a value determining if a contour plot should be drawn in !! conjunction with the surface plot. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical, intent(in) :: x !! Set to true if the contour plot should be drawn; else, false to !! only draw the surface. @@ -279,7 +281,7 @@ pure function surf_get_use_lighting(this) result(x) !! Gets a value indicating if lighting, beyond the ambient !! light source, is to be used. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical :: x !! True if lighting should be used; else, false. x = this%m_useLighting @@ -290,7 +292,7 @@ subroutine surf_set_use_lighting(this, x) !! Sets a value indicating if lighting, beyond the ambient !! light source, is to be used. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. logical, intent(in) :: x !! True if lighting should be used; else, false. this%m_useLighting = x @@ -301,7 +303,7 @@ pure function surf_get_light_intensity(this) result(x) !! Gets the ratio of the strength of the light source relative !! to the ambient light. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. real(real32) :: x !! The light intensity ratio. x = this%m_lightIntensity @@ -312,7 +314,7 @@ subroutine surf_set_light_intensity(this, x) !! Sets the ratio of the strength of the light source relative !! to the ambient light. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. real(real32), intent(in) :: x !! The light intensity ratio. The value must exist in the !! set [0, 1]; else, it will be clipped to lie within the range. @@ -330,7 +332,7 @@ pure function surf_get_specular_intensity(this) result(x) !! Gets the ratio of the strength of the specular light source !! relative to the ambient light. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. real(real32) :: x !! The specular light intensity ratio. x = this%m_specular @@ -341,7 +343,7 @@ subroutine surf_set_specular_intensity(this, x) !! Sets the ratio of the strength of the specular light source !! relative to the ambient light. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. real(real32), intent(in) :: x !! The specular light intensity ratio. The value must exist in the !! set [0, 1]; else, it will be clipped to lie within the range. @@ -358,7 +360,7 @@ subroutine surf_set_specular_intensity(this, x) pure function surf_get_transparency(this) result(x) !! Gets a factor defining the transparency of plotted surfaces. class(surface_plot), intent(in) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. real(real32) :: x !! A value existing on the set (0 1] defining the level of !! transparency. A value of 1 indicates a fully opaque surface. @@ -369,7 +371,7 @@ pure function surf_get_transparency(this) result(x) subroutine surf_set_transparency(this, x) !! Sets a factor defining the transparency of plotted surfaces. class(surface_plot), intent(inout) :: this - !! The surface_plot object. + !! The [[surface_plot]] object. real(real32), intent(in) :: x !! A value existing on the set (0 1] defining the level of !! transparency. A value of 1 indicates a fully opaque surface. @@ -385,4 +387,21 @@ subroutine surf_set_transparency(this, x) end subroutine ! ------------------------------------------------------------------------------ -end module \ No newline at end of file + subroutine surf_push_data(this, x, y, z) + !! Adds a data set to the plot. + class(surface_plot), intent(inout) :: this + !! The [[surface_plot]] object. + real(real64), intent(in), dimension(:,:) :: x + !! An M-by-N matrix containing the x-coordinate data. + real(real64), intent(in), dimension(size(x,1), size(x,2)) :: y + !! An M-by-N matrix containing the y-coordinate data. + real(real64), intent(in), dimension(size(x,1), size(x,2)) :: z + !! An M-by-N matrix containing the z-coordinate data. + + type(surface_plot_data) :: pd + call pd%define_data(x, y, z) + call this%push(pd) + end subroutine + +! ------------------------------------------------------------------------------ +end module diff --git a/src/fplot_surface_plot_data.f90 b/src/fplot_surface_plot_data.f90 index 16b8f3db..667bc564 100644 --- a/src/fplot_surface_plot_data.f90 +++ b/src/fplot_surface_plot_data.f90 @@ -1,7 +1,6 @@ module fplot_surface_plot_data use iso_fortran_env use fplot_plot_data - use ferror use fplot_errors use strings implicit none diff --git a/src/fplot_triangulations_delaunay_2d.f90 b/src/fplot_triangulations_delaunay_2d.f90 index d0086500..bf52fee8 100644 --- a/src/fplot_triangulations_delaunay_2d.f90 +++ b/src/fplot_triangulations_delaunay_2d.f90 @@ -1,7 +1,6 @@ module fplot_triangulations_delaunay_2d use iso_fortran_env use geompack - use ferror use fplot_errors implicit none private diff --git a/src/fplot_vector_field_plot_data.f90 b/src/fplot_vector_field_plot_data.f90 index 73ed2990..b8917e07 100644 --- a/src/fplot_vector_field_plot_data.f90 +++ b/src/fplot_vector_field_plot_data.f90 @@ -9,7 +9,6 @@ module fplot_vector_field_plot_data use fplot_plot_data use fplot_errors use fplot_colors - use ferror use strings implicit none private diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index a57dca49..00000000 --- a/src/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -sources = files( -'fplot_axis.f90', -'fplot_colormap.f90', -'fplot_colors.f90', -'fplot_core.f90', -'fplot_core_routines.f90', -'fplot_delaunay_tri_surface.f90', -'fplot_filled_plot_data.f90', -'fplot_label.f90', -'fplot_latex_terminal.f90', -'fplot_legend.f90', -'fplot_multiplot.f90', -'fplot_plot_2d.f90', -'fplot_plot_3d.f90', -'fplot_plot_axis.f90', -'fplot_plot_bar.f90', -'fplot_plot_data_2d.f90', -'fplot_plot_data_3d.f90', -'fplot_plot_data_bar.f90', -'fplot_plot_data_colored.f90', -'fplot_plot_data_error_bars.f90', -'fplot_plot_data.f90', -'fplot_plot_data_histogram.f90', -'fplot_plot_data_tri_2d.f90', -'fplot_plot.f90', -'fplot_plot_polar.f90', -'fplot_png_terminal.f90', -'fplot_qt_terminal.f90', -'fplot_scatter_plot_data.f90', -'fplot_simplify.f90', -'fplot_surface_plot_data.f90', -'fplot_surface_plot.f90', -'fplot_terminal.f90', -'fplot_tri_surface_plot_data.f90', -'fplot_vector_field_plot_data.f90', -'fplot_windows_terminal.f90', -'fplot_wxt_terminal.f90', -'geompack.f', -'tripack.f', -'fplot_string_builder.f90', -'fplot_string_builder_implementation.f90', -'fplot_triangulations_delaunay_2d.f90' - )