From bf43e41b2e3898b5108874257b169fc6b6a02058 Mon Sep 17 00:00:00 2001 From: vmagnin Date: Mon, 12 Feb 2024 12:26:40 +0100 Subject: [PATCH 01/13] Added a shift() method to the Colormap class --- CHANGELOG.md | 1 + src/colormap_class.f90 | 11 ++++++++++- test/check.f90 | 13 ++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf3e18b..2daa813 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to the gtk-fortran project are documented in this file. The ## [forcolormap dev] ### Added +* A `shift()` method to apply a circular shift to a colormap (left is +, right is -). * A private `check()` method in the Colormap class. It checks the validity of the colormap and its parameters, prints warnings, and fixes problems if necessary. * A `colormaps_list/ForColormap.pdf` manual listing all the available colormaps. * A function `bezier(colors, levels)` to create a colormap from continuous Bezier interpolation of control colors, in `src/colormap_class.f90`. The corresponding demo was added in `example/demo.f90`. diff --git a/src/colormap_class.f90 b/src/colormap_class.f90 index 4de515f..e09deb1 100644 --- a/src/colormap_class.f90 +++ b/src/colormap_class.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by vmagnin: 2023-09-26 -! Last modification: gha3mi 2024-01-28 +! Last modification: gha3mi 2024-02-12 !------------------------------------------------------------------------------- @@ -63,6 +63,7 @@ module forcolormap procedure :: print procedure :: colorbar => write_ppm_colorbar procedure, private :: reverse_map + procedure :: shift procedure :: extract procedure, private :: check end type Colormap @@ -820,6 +821,14 @@ pure subroutine reverse_map(self, name) end if end subroutine reverse_map + !> Apply a circular shift to the colormap (left is +, right is -) + pure subroutine shift(self, sh) + class(Colormap), intent(inout) :: self + integer, intent(in) :: sh !! The shift + + self%map(:,:) = cshift(self%map(:,:), sh) + end subroutine shift + ! Normalize the input real array to the range [0, 1] pure function scale_real_real(real_array,a,b) result(real_scaled_array) real(wp), dimension(:), intent(in) :: real_array diff --git a/test/check.f90 b/test/check.f90 index 1f9ec75..bb31fff 100644 --- a/test/check.f90 +++ b/test/check.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by vmagnin: 2023-10-19 -! Last modification: vmagnin 2024-01-11 +! Last modification: vmagnin 2024-02-12 !------------------------------------------------------------------------------- program check @@ -39,9 +39,11 @@ program check 6, 5, 4, & 3, 2, 1 ], & shape(test_colormap), order = [2, 1] ) + integer, dimension(0:6, 3) :: copy_colormap integer :: i call cmap%create("discrete", 0.0_wp, 2.0_wp, test_colormap) + copy_colormap = test_colormap if (cmap%get_levels() /= 7) error stop "ERROR: colormap%get_levels()" if (cmap%get_zmin() /= 0.0_wp) error stop "ERROR: colormap%get_zmin()" @@ -64,6 +66,15 @@ program check if ((red /= test_colormap(6, 1)).or.(green /= test_colormap(6, 2)) & & .or.(blue /= test_colormap(6, 3))) error stop "ERROR: colormap%compute_RGB()" + !! Test the shift() method: + call cmap%shift(+2) ! Toward left + call cmap%get_RGB(0, red, green, blue) + if ((red /= copy_colormap(2, 1)).or.(green /= copy_colormap(2, 2)) & + & .or.(blue /= copy_colormap(2, 3))) error stop "ERROR: colormap%shift()" + call cmap%shift(-1) ! Toward right + call cmap%get_RGB(6, red, green, blue) + if ((red /= copy_colormap(0, 1)).or.(green /= copy_colormap(0, 2)) & + & .or.(blue /= copy_colormap(0, 3))) error stop "ERROR: colormap%shift()" !! Test check() procedure within set() procedure ! Name is not in the list From 97fb840d17b432e4599627ecd82e5e1ee5eb5ff9 Mon Sep 17 00:00:00 2001 From: vmagnin Date: Tue, 13 Feb 2024 16:36:19 +0100 Subject: [PATCH 02/13] TODO.md refactored and renamed ROADMAP.md --- CHANGELOG.md | 1 + ROADMAP.md | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ TODO.md | 15 ------- 3 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 ROADMAP.md delete mode 100644 TODO.md diff --git a/CHANGELOG.md b/CHANGELOG.md index cf3e18b..a566fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ All notable changes to the gtk-fortran project are documented in this file. The * A `colorbar()` type-bound procedure to write a PPM file with the colorbar. ### Changed +* `TODO.md` was refactored and renamed `ROADMAP.md`. * Code refactoring. * Moved `test` subroutine to demo and example1. * Renamed `get_current()` to `get_name()`. diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..7abba87 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,119 @@ +# Roadmap + +## Version 0.9 + +The main goal of v0.9 is to offer a usable library, sufficiently friendly, with a minimalist API documentation. + +### Features + +- [ ] Methods + - [x] Implement a `check()` method to fix colormap parameters if needed. + - [x] Include a few minimalist methods to create or manipulate colormaps. More will be added in subsequent releases. +- [ ] Add facilities to pass 8 or 16-bit integers to C graphical libraries. + - [ ] Test with gtk-fortran and other libraries. +- [x] Introspection (Colormap_info) + - [ ] Include all available colormaps. +- [ ] Add Interpolation functions. + - [ ] Lagrange + - [x] Bezier + +### Examples + +- [ ] Create a `modify` example: + - [ ] For the `shift()` method. + +### Documentation + +- [x] Develop a PDF guide with all colorbars to aid in choosing a colormap. +- [x] Develop a web version guide with all colorbars to aid in choosing a colormap. +- [ ] Create a simple documentation generated with FORD. + +### Continuous Integration (CI) + +- [ ] Integrate fpm tests. +- [ ] Integrate FORD documentation. + +### Building System + +- [x] Implement a CMake building system, allowing installation of a `.so` + - [x] Test on Linux. + - [ ] Test on FreeBSD. + - [ ] Test on Windows (MSYS2). + - [ ] Test on macOS. + +### Others + +- [x] Design a logo. + + + + + +## Version 1.0 + +The main goal of v1.0 is to offer a library with a stable API and a first version of a Diataxis documentation. + +### Documentation + +- [ ] Specify which colormaps are colorblind-friendly, perceptually uniform, B&W print safe, etc. This information could be included in the Diataxis documentation. + +### Deprecation + +- [ ] Consider removing a few naive colormaps (e.g., "fire" is very similar to "black_body") + +### Quality Assurance + +- [ ] Add more automatic tests in `test/check.f90`. + + + +## Version 1.1 + +The main goal of v1.1 is to offer more features and to evolve the Diataxis documentation. + + +# Ideas + +These concepts are open for implementation or consideration. They may or may not be implemented. + +### Features + +- [ ] Methods + - [ ] Colormaps could have an option for logscale. + - [ ] A `get_colorbar()` function could return an `array(:,:,1:3)` containing the RGB image of the colorbar. The arguments could be the width and height, the direction (horizontal/vertical), etc. + - [ ] Add a `save()` or `export()` method + - [ ] Transfer lut file subroutines from ForImage to ForColormap. + - [ ] Add suport `.xml` file for use in ParaView or other softwares. + - [ ] Improve the `shift()` method: + - [ ] `shift_levels()`, `shift_real()` + - [ ] Possibly shifting automatically the colormap according to the [zmin, zmax] range. For example [-6, 3]. + - [ ] `shift_region()`: shifting certain segments of colormaps. + - [ ] `split()` and `combine()` (could be useful to create a multi-sequential colormap) methods. + - [ ] Convert to greyscale (note: convert to grayscale is implemented in ForImage). + - [ ] Create and load colormaps based on other color formats (note: Color conversion is implemented in ForImage). + - [ ] `brighten()` and darken (note: this is implemented in ForImage). + - [ ] `mix()` two colormaps. +- [ ] Develop a GUI using gtk-fortran to load, show, choose, modify, save, etc., colormaps. +- [ ] Add Interpolation functions + - [ ] B-Splines + - [ ] NURBS +- [ ] Colormaps + - [ ] Add more colormaps, only if similar ones are not already available and cannot be easily obtained with the available methods. + +### Examples + +- [ ] An example mixing gtk-fortran and ForColormap (to put in https://github.com/vmagnin/gtk-fortran-extra). + +### Continuous Integration (CI) + +- [ ] Set up continuous integration (CI) to automatically generate PDF files and colormap tables on a monthly basis or after each pull request. + +### Documentation + +- [ ] Include a few images in the `README.md` file. +- [ ] Include real simulation images. + +### Publication + +- [ ] Obtain a DOI from Zenodo, for example. +- [ ] And/or submit a JOSS *(Journal of Open Source Software)* paper similar to https://joss.theoj.org/papers/10.21105/joss.02004 \ No newline at end of file diff --git a/TODO.md b/TODO.md deleted file mode 100644 index a0e24bf..0000000 --- a/TODO.md +++ /dev/null @@ -1,15 +0,0 @@ -# TODO & ideas for further developments - -## Documentation -* [ ] Include a few images in the README.md file? -* [ ] Which colormaps are colorblind friendly, perceptually uniform, B&W print safe, etc. -* [ ] Add in `src/colormaps_info.f90` and `COLORMAPS_LIST.md` the Matplotlib and miscellaneous colormaps. - -## Colormaps -* [ ] Add more colormaps. -* [ ] Colormaps could have an option for logscale. -* [ ] A `get_colorbar()` function could return an `array(:,:,1:3)` containing the RGB image of the colorbar. The arguments could be the width and height, the direction (horizontal/vertical), etc. -* [ ] A `save()` method could save a colormap as RGB values separated by spaces in a `.lut` text file. - -## Development -* [ ] Add more automatic tests in `test/check.f90`. From 9ba68169c7d1d12ce1a27b2c2287bf808a57a9e4 Mon Sep 17 00:00:00 2001 From: Seyed Ali Ghasemi Date: Tue, 13 Feb 2024 21:56:31 +0100 Subject: [PATCH 03/13] Add Lagrange interpolation. (Refs #29) --- example/demo.f90 | 9 ++++-- src/colormap_class.f90 | 65 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/example/demo.f90 b/example/demo.f90 index 89a09d6..520b99b 100644 --- a/example/demo.f90 +++ b/example/demo.f90 @@ -21,11 +21,11 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by vmagnin: 2023-09-26 -! Last modification: gha3mi 2024-01-28 +! Last modification: gha3mi 2024-02-13 !------------------------------------------------------------------------------- program demo - use forcolormap, only: Colormap, colormaps_list, wp, bezier + use forcolormap, only: Colormap, colormaps_list, wp, bezier, lagrange implicit none integer :: i @@ -79,6 +79,11 @@ program demo call custom_cmap%colorbar('custom_colorbar_bezier', encoding='binary') call test_colormap(custom_cmap, 'custom_test_bezier', encoding='binary') + ! You can also create your own colormap using lagrange interpolation: + call custom_cmap%create('custom_lagrange', 0.0_wp, 2.0_wp, lagrange(colors, levels=1024)) ! levels is optional, default is 256 + call custom_cmap%colorbar('custom_colorbar_lagrange', encoding='binary') + call test_colormap(custom_cmap, 'custom_test_lagrange', encoding='binary') + contains subroutine test_colormap(self, filename, encoding) diff --git a/src/colormap_class.f90 b/src/colormap_class.f90 index 4de515f..8394ec6 100644 --- a/src/colormap_class.f90 +++ b/src/colormap_class.f90 @@ -34,7 +34,7 @@ module forcolormap implicit none private - public :: wp, bezier + public :: wp, bezier, lagrange ! List of built-in colormaps: character(*), dimension(*), public, parameter :: colormaps_list = & @@ -939,6 +939,7 @@ pure function bezier(colors, levels) result(map) ! Order of the Bezier curve order = size(colors, 1) - 1 + if (order < 1) error stop "Error: At least two control colors are required for Bezier interpolation." allocate(map_r(levels_,3), map(levels_,3)) ! 3 for RGB do i = 1,levels_ @@ -962,6 +963,68 @@ pure function factorial(n) result(result) end do end function factorial + ! Create colormap from Lagrange interpolation of control colors + pure function lagrange(colors, levels) result(map) + integer, dimension(:,:), intent(in) :: colors + integer, intent(in), optional :: levels + integer, dimension(:,:), allocatable :: map + real(wp), dimension(:,:), allocatable :: map_r + integer :: order, i, j, levels_ + real(wp) :: t + + ! Set default value for levels + if (present(levels)) then + levels_ = levels + else + levels_ = 256 + end if + + ! Order of the Lagrange interpolation. + order = size(colors, 1) - 1 + if (order < 1) error stop "Error: At least two control colors are required for Lagrange interpolation." + + allocate(map_r(levels_,3), map(levels_,3)) ! 3 for RGB + do i = 1, levels_ + t = real(i-1, wp) / real(levels_-1, wp) + map_r(i,:) = 0.0_wp + do j = 0, order + map_r(i,1) = dot_product(lagrange_poly(t,order+1), real(colors(:,1), wp)) + map_r(i,2) = dot_product(lagrange_poly(t,order+1), real(colors(:,2), wp)) + map_r(i,3) = dot_product(lagrange_poly(t,order+1), real(colors(:,3), wp)) + end do + map(i,:) = scale_real_int(map_r(i,:), 0, 255) ! Scale to integer RGB range + end do + end function lagrange + + ! Lagrange polynomial + pure function lagrange_poly(t, n) result(B) + real(wp), intent(in) :: t + integer, intent(in) :: n !! order + 1 + real(wp), allocatable :: B(:) + integer :: i, l + real(wp), dimension(:), allocatable :: Xth + + ! Create an array of n equidistant points between 0 and 1 + allocate(Xth(n), source = 0.0_wp) + do i = 1, n - 1 + Xth(i) = 0.0_wp + real(i - 1, wp) * (1.0_wp - (0.0_wp)) / real(n - 1, wp) + end do + Xth(n) = 1.0_wp + + allocate(B(n), source = 1.0_wp) + l = 0 + i = 0 + do i = 1, n + do l = 1, n + if (l /= i) then + if (abs(Xth(i) - Xth(l)) >= tiny(0.0_wp)) then + B(i) = B(i)*(t - Xth(l))/(Xth(i) - Xth(l)) + end if + end if + end do + end do + end function lagrange_poly + ! Check validity of the colormap and fix it if necessary pure subroutine check(self,check_name, check_zmin, check_zmax, check_levels) use forcolormap_info, only: Colormaps_info From a96eb9fae5d612d1ee4ee5d6f2fef6863d1d53c9 Mon Sep 17 00:00:00 2001 From: Seyed Ali Ghasemi Date: Wed, 14 Feb 2024 07:06:14 +0100 Subject: [PATCH 04/13] Fix RGB values within valid range (Refs #29) - Fix Lagange and Bezier interpolation functions. - Ensure that the RGB values are within the valid range of 0 to 255. --- src/colormap_class.f90 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/colormap_class.f90 b/src/colormap_class.f90 index 8394ec6..f3a1f78 100644 --- a/src/colormap_class.f90 +++ b/src/colormap_class.f90 @@ -949,7 +949,9 @@ pure function bezier(colors, levels) result(map) map_r(i,:) = map_r(i,:) + real(colors(j+1,:), wp)*& real(factorial(order), wp)/(real(factorial(j), wp)*real(factorial(order-j), wp)) * t**j * (1.0_wp-t)**(order-j) end do - map(i,:) = scale_real_int(map_r(i,:), 0, 255) ! Scale to integer RGB range + map(i,1) = min(255, max(0, nint(map_r(i,1)))) + map(i,2) = min(255, max(0, nint(map_r(i,2)))) + map(i,3) = min(255, max(0, nint(map_r(i,3)))) end do end function bezier @@ -992,7 +994,9 @@ pure function lagrange(colors, levels) result(map) map_r(i,2) = dot_product(lagrange_poly(t,order+1), real(colors(:,2), wp)) map_r(i,3) = dot_product(lagrange_poly(t,order+1), real(colors(:,3), wp)) end do - map(i,:) = scale_real_int(map_r(i,:), 0, 255) ! Scale to integer RGB range + map(i,1) = min(255, max(0, nint(map_r(i,1)))) + map(i,2) = min(255, max(0, nint(map_r(i,2)))) + map(i,3) = min(255, max(0, nint(map_r(i,3)))) end do end function lagrange From 3fe57f6e03a08e5fc3bd623d7c320ea4fc4fc09c Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 10:05:07 +0100 Subject: [PATCH 05/13] example/modify.f90 added --- CHANGELOG.md | 1 + example/CMakeLists.txt | 4 ++ example/README.md | 1 + example/modify.f90 | 97 ++++++++++++++++++++++++++++++++++++++++++ fpm.toml | 5 +++ 5 files changed, 108 insertions(+) create mode 100644 example/modify.f90 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2daa813..1d4547f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to the gtk-fortran project are documented in this file. The ### Added * A `shift()` method to apply a circular shift to a colormap (left is +, right is -). + * `example/modify.f90` demonstrates how you can modify a colormap with methods like shift(), in concrete cases. * A private `check()` method in the Colormap class. It checks the validity of the colormap and its parameters, prints warnings, and fixes problems if necessary. * A `colormaps_list/ForColormap.pdf` manual listing all the available colormaps. * A function `bezier(colors, levels)` to create a colormap from continuous Bezier interpolation of control colors, in `src/colormap_class.f90`. The corresponding demo was added in `example/demo.f90`. diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 1c0bcdf..780205f 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -17,3 +17,7 @@ target_link_libraries(extract ${PROJECT_NAME}) # INFO add_executable(info info.f90) target_link_libraries(info ${PROJECT_NAME}) + +# MODIFY +add_executable(modify modify.f90) +target_link_libraries(modify ${PROJECT_NAME}) diff --git a/example/README.md b/example/README.md index 3301991..c30e386 100644 --- a/example/README.md +++ b/example/README.md @@ -7,3 +7,4 @@ They can be launched with the command `fpm run --example name_of_the_example` (w * `example1.f90` demonstrates how ForImage can be used to import/export PPM files. * `extract.f90` demonstrates how to create a specific colormap by extracting a specified number of colors of a colormap. * `info.f90` demonstrates how to obtain information about a colormap using the `Colormaps_info` class. +* `modify.f90` demonstrates how you can modify a colormap with methods like shift(), in concrete cases. diff --git a/example/modify.f90 b/example/modify.f90 new file mode 100644 index 0000000..1420d85 --- /dev/null +++ b/example/modify.f90 @@ -0,0 +1,97 @@ +! The MIT License (MIT) +! +! Copyright (c) 2024 Vincent Magnin +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. +!------------------------------------------------------------------------------- +! Contributed by vmagnin: 2024-02-14 +! Last modification: vmagnin 2024-02-15 +!------------------------------------------------------------------------------- + +!> This example shows how you can modify a colormap with methods like shift(), +!> in concrete cases. +program modify + use forcolormap, only: Colormap, wp + + implicit none + type(Colormap) :: cmap + + !> In the Scientific colour maps collection, all cyclic colormaps have their + !> bright part in the middle. But we can shift the dark part towards the + !> center. + call cmap%set("bamO", 0.0_wp, 2.0_wp) + call cmap%colorbar("bamO", encoding='binary') + call cmap%shift(cmap%get_levels() / 2) + call cmap%colorbar("bamO_shifted", encoding='binary') + print *, "See the bamO.ppm and bamO_shifted.ppm colorbars" + + !> In the Scientific colour maps collection, all categorical colormaps + !> begin with a dark colour, but a shift can be applied to begin with a + !> brighter colour. + call cmap%set("actonS", 0.0_wp, 2.0_wp) + call cmap%colorbar("actonS", encoding='binary') + call cmap%shift(+2) !! Two levels towards left + call cmap%colorbar("actonS_shifted", encoding='binary') + print *, "See the actonS.ppm and actonS_shifted.ppm colorbars" + + !> Starting from a diverging colormap, we can obtain what could be called + !> a diverging multi-sequential colormap. + call cmap%set("bam", 0.0_wp, 2.0_wp) + call cmap%colorbar("bam", encoding='binary') + call cmap%shift(cmap%get_levels() / 2) + call cmap%colorbar("bam_shifted", encoding='binary') + print *, "See the bam.ppm and bam_shifted.ppm colorbars" + + contains + + subroutine test_colormap(self, filename, encoding) + use forimage, only: format_pnm + type(Colormap), intent(inout) :: self + character(*), intent(in) :: filename + integer :: k, j ! Pixbuffer coordinates + integer, parameter :: pixwidth = 600 + integer, parameter :: pixheight = 600 + integer, dimension(pixheight,pixwidth*3) :: rgb_image + integer :: red, green, blue + real(wp) :: z + type(format_pnm) :: ppm + character(*), intent(in) :: encoding + + do k = 0, pixwidth-1 + do j = 0, pixheight-1 + ! Computing a z=f(x,y) function: + z = 1.0_wp + sin(k*j/10000.0_wp) * cos(j/100.0_wp) + ! The corresponding RGB values in our colormap: + call self%compute_RGB(z, red, green, blue) + rgb_image(pixheight-j, 3*(k+1)-2) = red + rgb_image(pixheight-j, 3*(k+1)-1) = green + rgb_image(pixheight-j, 3*(k+1)) = blue + end do + end do + + call ppm%set_pnm(encoding = encoding,& + file_format = 'ppm',& + width = pixwidth,& + height = pixheight,& + max_color = 255,& + comment = 'comment',& + pixels = rgb_image) + call ppm%export_pnm(filename) + end subroutine test_colormap +end program modify diff --git a/fpm.toml b/fpm.toml index 072585f..530a485 100644 --- a/fpm.toml +++ b/fpm.toml @@ -42,6 +42,11 @@ name = "extract" source-dir = "example" main = "extract.f90" +[[example]] +name = "modify" +source-dir = "example" +main = "modify.f90" + [build] auto-executables = true auto-tests = true From 4dabacb73b871ed1f0a30f2fe6f1e7aa6d479c58 Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 13:47:36 +0100 Subject: [PATCH 06/13] example/modify.f90: removed unused test_colormap() --- example/modify.f90 | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/example/modify.f90 b/example/modify.f90 index 1420d85..ddc6484 100644 --- a/example/modify.f90 +++ b/example/modify.f90 @@ -58,40 +58,4 @@ program modify call cmap%colorbar("bam_shifted", encoding='binary') print *, "See the bam.ppm and bam_shifted.ppm colorbars" - contains - - subroutine test_colormap(self, filename, encoding) - use forimage, only: format_pnm - type(Colormap), intent(inout) :: self - character(*), intent(in) :: filename - integer :: k, j ! Pixbuffer coordinates - integer, parameter :: pixwidth = 600 - integer, parameter :: pixheight = 600 - integer, dimension(pixheight,pixwidth*3) :: rgb_image - integer :: red, green, blue - real(wp) :: z - type(format_pnm) :: ppm - character(*), intent(in) :: encoding - - do k = 0, pixwidth-1 - do j = 0, pixheight-1 - ! Computing a z=f(x,y) function: - z = 1.0_wp + sin(k*j/10000.0_wp) * cos(j/100.0_wp) - ! The corresponding RGB values in our colormap: - call self%compute_RGB(z, red, green, blue) - rgb_image(pixheight-j, 3*(k+1)-2) = red - rgb_image(pixheight-j, 3*(k+1)-1) = green - rgb_image(pixheight-j, 3*(k+1)) = blue - end do - end do - - call ppm%set_pnm(encoding = encoding,& - file_format = 'ppm',& - width = pixwidth,& - height = pixheight,& - max_color = 255,& - comment = 'comment',& - pixels = rgb_image) - call ppm%export_pnm(filename) - end subroutine test_colormap end program modify From e65c61efd8fbc4371b559301f762814b5cdb7739 Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 13:52:52 +0100 Subject: [PATCH 07/13] src/colormap_class.f90: fixes an encoding problem in write_ppm_colorbar() --- src/colormap_class.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/colormap_class.f90 b/src/colormap_class.f90 index e09deb1..f14fc99 100644 --- a/src/colormap_class.f90 +++ b/src/colormap_class.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by vmagnin: 2023-09-26 -! Last modification: gha3mi 2024-02-12 +! Last modification: gha3mi 2024-02-12, vmagnin 2024-02-15 !------------------------------------------------------------------------------- @@ -799,7 +799,7 @@ impure subroutine write_ppm_colorbar(self, filename, width, height, encoding) call ppm%set_format('binary') end if - call ppm%set_pnm(encoding = encoding,& + call ppm%set_pnm(encoding = ppm%get_format(),& file_format = 'ppm',& width = pixwidth,& height = pixheight,& From 9f9f53ce72d7b757ff474c6b3f50e4cd11b5da9d Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 13:53:29 +0100 Subject: [PATCH 08/13] example/modify.f90: uses the default binary encoding for PPM files --- example/modify.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/example/modify.f90 b/example/modify.f90 index ddc6484..a3568cd 100644 --- a/example/modify.f90 +++ b/example/modify.f90 @@ -36,26 +36,26 @@ program modify !> bright part in the middle. But we can shift the dark part towards the !> center. call cmap%set("bamO", 0.0_wp, 2.0_wp) - call cmap%colorbar("bamO", encoding='binary') + call cmap%colorbar("bamO") call cmap%shift(cmap%get_levels() / 2) - call cmap%colorbar("bamO_shifted", encoding='binary') + call cmap%colorbar("bamO_shifted") print *, "See the bamO.ppm and bamO_shifted.ppm colorbars" !> In the Scientific colour maps collection, all categorical colormaps !> begin with a dark colour, but a shift can be applied to begin with a !> brighter colour. call cmap%set("actonS", 0.0_wp, 2.0_wp) - call cmap%colorbar("actonS", encoding='binary') + call cmap%colorbar("actonS") call cmap%shift(+2) !! Two levels towards left - call cmap%colorbar("actonS_shifted", encoding='binary') + call cmap%colorbar("actonS_shifted") print *, "See the actonS.ppm and actonS_shifted.ppm colorbars" !> Starting from a diverging colormap, we can obtain what could be called !> a diverging multi-sequential colormap. call cmap%set("bam", 0.0_wp, 2.0_wp) - call cmap%colorbar("bam", encoding='binary') + call cmap%colorbar("bam") call cmap%shift(cmap%get_levels() / 2) - call cmap%colorbar("bam_shifted", encoding='binary') + call cmap%colorbar("bam_shifted") print *, "See the bam.ppm and bam_shifted.ppm colorbars" end program modify From db16e86973868f5de303ddb59de6cce98a63fc39 Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 14:06:54 +0100 Subject: [PATCH 09/13] examples: binary encoding is the default for colorbars --- example/demo.f90 | 12 ++++++------ example/demo_reverse.f90 | 10 +++++----- example/extract.f90 | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/example/demo.f90 b/example/demo.f90 index 89a09d6..b17e6b0 100644 --- a/example/demo.f90 +++ b/example/demo.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by vmagnin: 2023-09-26 -! Last modification: gha3mi 2024-01-28 +! Last modification: gha3mi 2024-01-28, vmagnin 2024-02-15 !------------------------------------------------------------------------------- program demo @@ -47,7 +47,7 @@ program demo ! The built-in z=f(x,y) test function is in the [0, 2] range: do i = 1, size(colormaps_list) call cmap%set(trim(colormaps_list(i)), 0.0_wp, 2.0_wp) - call cmap%colorbar(trim(colormaps_list(i))//'_colorbar', encoding='binary') + call cmap%colorbar(trim(colormaps_list(i))//'_colorbar') call test_colormap(cmap, trim(colormaps_list(i))//'_test', encoding='binary') print '("Colormap ", A30, " has ", I0, " levels")', trim(cmap%get_name()), cmap%get_levels() end do @@ -55,17 +55,17 @@ program demo ! Cubehelix can also accept other parameters (varargs array): call cmap%set("cubehelix", 0.0_wp, 2.0_wp, 1024, [0.5_wp, -1.0_wp, 1.0_wp, 1.0_wp]) ! We change the name for the output test files: - call cmap%colorbar('cubehelix_customized_colorbar', encoding='binary') + call cmap%colorbar('cubehelix_customized_colorbar') call test_colormap(cmap, 'cubehelix_customized_test', encoding='binary') ! You can create your own colormap defined in an array: call custom_cmap%create('discrete', 0.0_wp, 2.0_wp, my_colormap) - call custom_cmap%colorbar('discrete_colorbar', encoding='binary') + call custom_cmap%colorbar('discrete_colorbar') call test_colormap(custom_cmap, 'discrete_test', encoding='binary') ! Or you can download it from a .txt file: call custom_cmap%load("test_map_to_load.txt", 0.0_wp, 2.0_wp) - call custom_cmap%colorbar('a_loaded_colorbar', encoding='binary') + call custom_cmap%colorbar('a_loaded_colorbar') call test_colormap(custom_cmap, 'a_loaded_colormap_test', encoding='binary') call custom_cmap%print() @@ -76,7 +76,7 @@ program demo colors(2,:) = [0, 255, 0] ! Green colors(3,:) = [0, 0, 255] ! Blue call custom_cmap%create('custom_bezier', 0.0_wp, 2.0_wp, bezier(colors, levels=1024)) ! levels is optional, default is 256 - call custom_cmap%colorbar('custom_colorbar_bezier', encoding='binary') + call custom_cmap%colorbar('custom_colorbar_bezier') call test_colormap(custom_cmap, 'custom_test_bezier', encoding='binary') contains diff --git a/example/demo_reverse.f90 b/example/demo_reverse.f90 index 00ca799..505cf46 100644 --- a/example/demo_reverse.f90 +++ b/example/demo_reverse.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by vmagnin: 2023-09-26 -! Last modification: gha3mi 2023-11-01 +! Last modification: gha3mi 2023-11-01, vmagnin 2024-02-15 !------------------------------------------------------------------------------- program demo_reverse @@ -46,7 +46,7 @@ program demo_reverse ! The built-in z=f(x,y) test function is in the [0, 2] range: do i = 1, size(colormaps_list) call cmap%set(trim(colormaps_list(i)), 0.0_wp, 2.0_wp, reverse=.true.) - call cmap%colorbar(trim(colormaps_list(i))//'_reverse_colorbar', encoding='binary') + call cmap%colorbar(trim(colormaps_list(i))//'_reverse_colorbar') call test_colormap(cmap, trim(colormaps_list(i))//'_reverse_test', encoding='binary') print '("Colormap ", A30, " has ", I0, " levels")', trim(cmap%get_name()), cmap%get_levels() end do @@ -54,17 +54,17 @@ program demo_reverse ! Cubehelix can also accept other parameters (varargs array): call cmap%set("cubehelix", 0.0_wp, 2.0_wp, 1024, [0.5_wp, -1.0_wp, 1.0_wp, 1.0_wp], reverse=.true.) ! We change the name for the output test files: - call cmap%colorbar('cubehelix_customized_reverse_colorbar', encoding='binary') + call cmap%colorbar('cubehelix_customized_reverse_colorbar') call test_colormap(cmap, 'cubehelix_customized_reverse_test', encoding='binary') ! You can create your own colormap defined in an array: call custom_cmap%create('discrete', 0.0_wp, 2.0_wp, my_colormap, reverse=.true.) - call custom_cmap%colorbar('discrete_reverse_colorbar', encoding='binary') + call custom_cmap%colorbar('discrete_reverse_colorbar') call test_colormap(custom_cmap, 'discrete_reverse_test', encoding='binary') ! Or you can download it from a .txt file: call custom_cmap%load("test_map_to_load.txt", 0.0_wp, 2.0_wp, reverse=.true.) - call custom_cmap%colorbar('a_loaded_reverse_colorbar', encoding='binary') + call custom_cmap%colorbar('a_loaded_reverse_colorbar') call test_colormap(custom_cmap, 'a_loaded_reverse_colormap_test', encoding='binary') call custom_cmap%print() diff --git a/example/extract.f90 b/example/extract.f90 index 42bc1ee..727ea0b 100644 --- a/example/extract.f90 +++ b/example/extract.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by gha3mi: 2023-11-07 -! Last modification: gha3mi 2023-11-07 +! Last modification: gha3mi 2023-11-07, vmagnin 2024-02-15 !------------------------------------------------------------------------------- ! This example demonstrates the process of extracting a specified number of colors. @@ -42,7 +42,7 @@ program extract ! The extracted colormap will overwrite the existing colormap type (cmap) call cmap%extract(10) - ! Generate a color bar for the extracted colormap with binary encoding - call cmap%colorbar('fes10_ex_colorbar', encoding='binary') - + ! Generate a color bar for the extracted colormap + call cmap%colorbar('fes10_ex_colorbar') + end program extract From 9f709b49e09e1e1deef561b49f042572bc0bdf7d Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 14:22:59 +0100 Subject: [PATCH 10/13] README.md updated with example/modify.f90 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e33659a..1e53a31 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ In the `example` directory, you will find these commented demos: * `example1.f90` demonstrates how ForImage can be used to import/export PPM files. * `extract.f90` demonstrates how to create a specific colormap by extracting a specified number of colors of a colormap. * `info.f90` demonstrates how to obtain information about a colormap using the `Colormaps_info` class. +* `modify.f90` demonstrates how you can modify a colormap with methods like `shift()`, in concrete cases. They can be launched with the command `fpm run --example name_of_the_example` (without the `.f90` extension). From f7a9cdeaa56626f7cd7ad809ffab4729c7b606b7 Mon Sep 17 00:00:00 2001 From: vmagnin Date: Thu, 15 Feb 2024 14:30:02 +0100 Subject: [PATCH 11/13] ROADMAP.md updated --- ROADMAP.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 7abba87..23f38a9 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -16,11 +16,12 @@ The main goal of v0.9 is to offer a usable library, sufficiently friendly, with - [ ] Add Interpolation functions. - [ ] Lagrange - [x] Bezier +- [ ] Add a `Colormap_test` class where the subroutine `test_colormap()` will be moved. ### Examples -- [ ] Create a `modify` example: - - [ ] For the `shift()` method. +- [x] Create a `modify` example: + - [x] For the `shift()` method. ### Documentation From 1ba4872eea838a6ae17431bcd1540f525ae125ef Mon Sep 17 00:00:00 2001 From: vmagnin Date: Fri, 16 Feb 2024 11:58:08 +0100 Subject: [PATCH 12/13] src/colormaps_info.f90: fixes the number of levels for categorical colormaps (100 instead of 256) --- src/colormaps_info.f90 | 46 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/colormaps_info.f90 b/src/colormaps_info.f90 index f819c66..004421d 100644 --- a/src/colormaps_info.f90 +++ b/src/colormaps_info.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by gha3mi: 2023-11-05 -! Last modification: gha3mi 2024-01-06, vmagnin 2024-02-09 +! Last modification: gha3mi 2024-01-06, vmagnin 2024-02-16 !------------------------------------------------------------------------------- module forcolormap_info @@ -539,7 +539,7 @@ pure elemental subroutine set_all(this) family = "acton",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "actonS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -693,7 +693,7 @@ pure elemental subroutine set_all(this) family = "bamako",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "bamakoS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -917,7 +917,7 @@ pure elemental subroutine set_all(this) family = "batlow",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "batlowKS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -931,7 +931,7 @@ pure elemental subroutine set_all(this) family = "batlow",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "batlowS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -1015,7 +1015,7 @@ pure elemental subroutine set_all(this) family = "batlow",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "batlowWS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -1169,7 +1169,7 @@ pure elemental subroutine set_all(this) family = "bilbao",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "bilbaoS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -1393,7 +1393,7 @@ pure elemental subroutine set_all(this) family = "buda",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "budaS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -1687,7 +1687,7 @@ pure elemental subroutine set_all(this) family = "davos",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "davosS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -1771,7 +1771,7 @@ pure elemental subroutine set_all(this) family = "devon",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "devonS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -1925,7 +1925,7 @@ pure elemental subroutine set_all(this) family = "glasgow",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "glasgowS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2009,7 +2009,7 @@ pure elemental subroutine set_all(this) family = "grayC",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "grayCS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2093,7 +2093,7 @@ pure elemental subroutine set_all(this) family = "hawaii",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "hawaiiS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2177,7 +2177,7 @@ pure elemental subroutine set_all(this) family = "imola",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "imolaS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2261,7 +2261,7 @@ pure elemental subroutine set_all(this) family = "lajolla",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "lajollaS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2345,7 +2345,7 @@ pure elemental subroutine set_all(this) family = "lapaz",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "lapazS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2359,7 +2359,7 @@ pure elemental subroutine set_all(this) family = "lipari",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "lipariS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2653,7 +2653,7 @@ pure elemental subroutine set_all(this) family = "navia",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "naviaS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2681,7 +2681,7 @@ pure elemental subroutine set_all(this) family = "navia",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "naviaWS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2821,7 +2821,7 @@ pure elemental subroutine set_all(this) family = "nuuk",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "nuukS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -2975,7 +2975,7 @@ pure elemental subroutine set_all(this) family = "oslo",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "osloS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -3269,7 +3269,7 @@ pure elemental subroutine set_all(this) family = "tokyo",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "tokyoS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& @@ -3353,7 +3353,7 @@ pure elemental subroutine set_all(this) family = "turku",& gradient = "Categorical",& palette = "Continuous",& - levels = 256, & + levels = 100, & colorbar = "turkuS_colorbar.ppm",& package = "Scientific Colour Map",& author = "Fabio Crameri",& From a262a433a36caa49aa28b3296c97629b517bc249 Mon Sep 17 00:00:00 2001 From: Seyed Ali Ghasemi Date: Fri, 16 Feb 2024 13:21:56 +0100 Subject: [PATCH 13/13] Fix zero width, license length, and other improvements --- src/colormaps_info.f90 | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/colormaps_info.f90 b/src/colormaps_info.f90 index 004421d..7ad521e 100644 --- a/src/colormaps_info.f90 +++ b/src/colormaps_info.f90 @@ -21,7 +21,7 @@ ! SOFTWARE. !------------------------------------------------------------------------------- ! Contributed by gha3mi: 2023-11-05 -! Last modification: gha3mi 2024-01-06, vmagnin 2024-02-16 +! Last modification: gha3mi 2024-02-16, vmagnin 2024-02-16 !------------------------------------------------------------------------------- module forcolormap_info @@ -142,8 +142,8 @@ impure subroutine write_info(this, verbose, file_name) 'a,','a', len_trim(this%colorbar),',',23-len_trim(this%colorbar)+2,'x',',',& 'a,','a', len_trim(this%package),',',25-len_trim(this%package)+2,'x',',',& 'a,','a', len_trim(this%author),',',15-len_trim(this%author)+2,'x',',',& - 'a,','a', len_trim(this%license),',',18-len_trim(this%license)+2,'x',',',& - 'a,','a', len_trim(this%url),',',42-len_trim(this%url)+2,'x',',a',& + 'a,','a', len_trim(this%license),',',33-len_trim(this%license)+2,'x',',',& + 'a,','a', max(1, len_trim(this%url)),',',42-max(1, len_trim(this%url))+2,'x',',a',& ')' open (newunit=nunit, file=trim(file_name), access='append', status='unknown', action='write') write (nunit,format_table)& @@ -181,8 +181,8 @@ impure subroutine write_info(this, verbose, file_name) 'a', len_trim(this%colorbar),',',23-len_trim(this%colorbar)+2,'x',',',& 'a', len_trim(this%package),',',25-len_trim(this%package)+2,'x',',',& 'a', len_trim(this%author),',',15-len_trim(this%author)+2,'x',',',& - 'a', len_trim(this%license),',',18-len_trim(this%license)+2,'x',',',& - 'a', len_trim(this%url),',',42-len_trim(this%url)+2,'x',& + 'a', len_trim(this%license),',',33-len_trim(this%license)+2,'x',',',& + 'a', max(1, len_trim(this%url)),',',42-max(1, len_trim(this%url))+2,'x',& ')' print (format_table),& this%name,& @@ -318,16 +318,17 @@ impure subroutine write(this, verbose, name, family, gradient, palette, author, if (present(file_name)) then open(newunit=nunit, file=trim(file_name), access='append', status='unknown', action='write') write(nunit,'(a)')'' ! Print empty line - write(nunit,'(g0,8x,g0,6x,g0,12x,g0,7x,g0,1x,g0,17x,g0,20x,g0,11x,g0,13x,g0)') & + write(nunit,'(g0,8x,g0,6x,g0,12x,g0,7x,g0,1x,g0,17x,g0,20x,g0,11x,g0,28x,g0)') & '|Name', '|Family', '|Gradient', '|Palette', '|Levels', '|Colorbar', '|Package', '|Author', '|Licence', '|URL|' write(nunit,'(a)') '|---|---|---|---|---|---|---|---|---|---|' close(nunit) else print*,'' ! Print empty line - print '(g0,8x,g0,6x,g0,12x,g0,7x,g0,1x,g0,17x,g0,20x,g0,11x,g0,13x,g0)', & + print '(g0,8x,g0,6x,g0,12x,g0,7x,g0,1x,g0,17x,g0,20x,g0,11x,g0,28x,g0)', & 'Name', 'Family', 'Gradient', 'Palette', 'Levels', 'Colorbar', 'Package', 'Author', 'Licence', 'URL' - print'(a)', '**********************************************************************************************& - &*******************************************************************************************' + print'(a)', '*****************************************************************************************& + &*****************************************************************************************************& + &**********************' end if end if