Skip to content

Commit

Permalink
Merge pull request #262 from ABRG-Models/246-more-colourmaps
Browse files Browse the repository at this point in the history
Adds colourmaps from CET, Fabio Crameri and William Lenthe
  • Loading branch information
sebjameswml authored Oct 14, 2024
2 parents 7b07eea + a567db9 commit 22842a8
Show file tree
Hide file tree
Showing 22 changed files with 31,492 additions and 2,489 deletions.
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,7 @@ enable_testing()
add_subdirectory(tests)

# incbin for Visual Studio
if(WIN32)
add_subdirectory(buildtools)
endif()

# Install the font files, for the examples, which seek to work with an
# *installed* morphologica, as opposed to an in-tree morphologica.
Expand Down
13 changes: 9 additions & 4 deletions buildtools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# incbin tool
add_executable(incbin incbin.c)


if(WIN32)
# incbin tool
add_executable(incbin incbin.c)
endif()

# Permit #include <morph/header.h>
include_directories(BEFORE ${PROJECT_SOURCE_DIR})
# Colourmap processing
add_executable(process_colourmap process_colourmap.cpp)
add_executable(process_colourtables process_colourtables.cpp)
67 changes: 67 additions & 0 deletions buildtools/process_colourmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Process csv or txt files that contain colourmap tables into header-ready
* code. Written to process Fabio Crameri's tables initially.
*
* Author: Seb James
* Date: Oct 2024
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <morph/tools.h>

int main (int argc, char** argv)
{
std::string fpath ("unknown");
if (argc > 1) { fpath = std::string (argv[1]); }
//std::cout << "Processing file " << fpath << std::endl;

// Obtain name from fpath
std::string name = fpath;
morph::Tools::stripUnixPath (name);
morph::Tools::stripFileSuffix (name);
if (name.empty()) {
std::cerr << "No name.\n";
return -1;
}
//std::cout << "Extracted name: " << name << std::endl;

std::ifstream ifile (fpath, std::ios::in);
if (!ifile.is_open()) {
std::cerr << "Failed opening file " << fpath << "\n";
return -1;
}

unsigned int nlines = 0;
bool commas = false;
for (std::string line; std::getline(ifile, line);) {
// Check first line for commas
if (nlines == 0) {
if (line.find (",") != std::string::npos) {
commas = true;
}
}
++nlines;
}
// reset ifile
ifile.clear();
ifile.seekg(0);

std::cout << "\n constexpr std::array<std::array<float, 3>, " << nlines << "> cm_" << name << " = {{\n";
unsigned int cline = 0;
unsigned int lastline = nlines - 1;
for (std::string line; std::getline(ifile, line);) {
// Process line into csv
std::vector<std::string> tokens = morph::Tools::stringToVector (line, (commas ? "," : " "));
if (tokens.size() != 3) {
std::cerr << "text format error: != 3 values in line '" << line << "', (got "<< tokens.size() << ")\n";
return -1;
}
std::cout << " {"
<< tokens[0] << "," << tokens[1] << "," << tokens[2] << (cline++ < lastline ? "},\n" : "}\n");
}
std::cout << " }}; // cm_" << name << "\n";

return 0;
}
180 changes: 180 additions & 0 deletions buildtools/process_colourtables.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Process all of Fabio Crameri's tables into a header file and also output text for
* ColourMap.h's various functions
*
* Author: Seb James
* Date: Oct 2024
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <morph/tools.h>

enum class ctabletype {
Crameri,
CET,
unknown
};

int main ()
{
ctabletype tt = ctabletype::unknown;
// First get a directory listing and make sure we're in the Crameri folder
if (morph::Tools::fileExists ("+README_ScientificColourMaps.pdf")) {
tt = ctabletype::Crameri;
} else if (morph::Tools::fileExists ("CET-C1.csv")) {
tt = ctabletype::CET;
} else {
std::cerr << "Run this program within the Crameri OR CET colour table directories\n";
return -1;
}

// Get directories
std::vector<std::string> dirs;
std::vector<std::string> table_files;
std::string basedir = "./";
std::string subdir = "";
morph::Tools::readDirectoryTree (dirs, basedir, subdir);
if (tt == ctabletype::Crameri) {
for (auto dir : dirs) {
std::cerr << "Got file " << dir << std::endl;
if (dir.find (".txt") != std::string::npos
&& dir.find ("DiscretePalettes") == std::string::npos
&& dir.find ("CategoricalPalettes") == std::string::npos) {
table_files.push_back (dir);
}
}
std::cerr << table_files.size() << " Crameri maps to process\n";
} else if (tt == ctabletype::CET) {
for (auto dir : dirs) {
std::cerr << "Got file " << dir << std::endl;
if (dir.find (".csv") != std::string::npos) {
table_files.push_back (dir);
}
}
}

std::ofstream hpp ((tt == ctabletype::Crameri ? "colourmaps_crameri.h" : "colourmaps_cet.h"), std::ios::out|std::ios::trunc);
std::ofstream cpp_content0 ("colourmap_enum.cpp", std::ios::out|std::ios::trunc);
std::ofstream cpp_content1 ("colourmap_colourMapTypeToStr.cpp", std::ios::out|std::ios::trunc);
std::ofstream cpp_content2 ("colourmap_strToColourMapType.cpp", std::ios::out|std::ios::trunc);
std::ofstream cpp_content3 ("colourmap_convert_switch.cpp", std::ios::out|std::ios::trunc);
std::ofstream cpp_content4 ("colourmap_example.cpp", std::ios::out|std::ios::trunc);

cpp_content0 << "// Section for ColourMapType enum\n";
cpp_content1 << "// Section for morph::ColourMap::colourMapTypeToStr\n";
cpp_content2 << "// Section for morph::ColourMap::strToColourMapType\n";
cpp_content3 << "// Section for morph::ColourMap::convert switch\n";
cpp_content4 << "// Section for examples/colourmaps_crameri.cpp\n";
if (tt == ctabletype::Crameri) {
hpp << "// Scientific Colour Maps from Fabio Crameri (see https://zenodo.org/records/8409685)\n"
<< "// Converted into C++ lookup tables for morphologica by Seb James\n\n"
<< "#pragma once\n\n"
<< "#include <array>\n\n"
<< "namespace morph {\n"
<< " namespace crameri {\n";
} else {
hpp << "// CET Colour maps from https://colorcet.com/gallery.html\n"
<< "// Converted into C++ lookup tables for morphologica by Seb James\n\n"
<< "#pragma once\n\n"
<< "#include <array>\n\n"
<< "namespace morph {\n"
<< " namespace cet {\n";
}

std::string nspacename = (tt == ctabletype::Crameri ? "crameri" : "cet");

for (auto fpath : table_files) {
std::cerr << "Got table file " << fpath << std::endl;

// Obtain name from fpath
std::string name = fpath;
morph::Tools::stripUnixPath (name);
morph::Tools::stripFileSuffix (name);
if (name.empty()) {
std::cerr << "No name.\n";
return -1;
}
std::string name_lower = name;
morph::Tools::toLowerCase (name_lower);

std::ifstream ifile (fpath, std::ios::in);
if (!ifile.is_open()) {
std::cerr << "Failed opening file " << fpath << "\n";
return -1;
}

unsigned int nlines = 0;
bool commas = false;
for (std::string line; std::getline(ifile, line);) {
// Check first line for commas
if (nlines == 0) {
if (line.find (",") != std::string::npos) {
commas = true;
}
}
++nlines;
}
// reset ifile
ifile.clear();
ifile.seekg(0);

std::string name_upperfirst = name;
// Upper-case first character
std::transform (name_upperfirst.begin(), name_upperfirst.begin()+1, name_upperfirst.begin(), morph::to_upper());
// Replace non-allowed chars with _
std::string::size_type ptr = std::string::npos;
while ((ptr = name_upperfirst.find_last_not_of (CHARS_NUMERIC_ALPHA"_", ptr)) != std::string::npos) {
name_upperfirst[ptr] = '_';
ptr--;
}

hpp << "\n constexpr std::array<std::array<float, 3>, " << nlines << "> cm_" << name_upperfirst << " = {{\n";
unsigned int cline = 0;
unsigned int lastline = nlines - 1;
for (std::string line; std::getline(ifile, line);) {
// Process line into csv
std::vector<std::string> tokens = morph::Tools::stringToVector (line, (commas ? "," : " "));
if (tokens.size() != 3) {
std::cerr << "text format error: != 3 values in line '" << line << "', (got "<< tokens.size() << ")\n";
return -1;
}
hpp << " {"
<< tokens[0] << "," << tokens[1] << "," << tokens[2] << (cline++ < lastline ? "},\n" : "}\n");
}
hpp << " }}; // cm_" << name_upperfirst << "\n";

// Content output.
cpp_content0 << " " << name_upperfirst << ",\n";

cpp_content1 << " case morph::ColourMapType::" << name_upperfirst << ":\n"
<< " {\n"
<< " s = \"" << name_lower << "\";\n"
<< " break;\n"
<< " }\n";

cpp_content2 << " } else if (_s == \"" << name_lower << "\") {\n"
<< " cmt = morph::ColourMapType::" << name_upperfirst << ";\n";

cpp_content3 << " case ColourMapType::"<< name_upperfirst << ":\n"
<< " {\n"
<< " size_t datum_i = static_cast<size_t>( std::abs (std::round (datum * static_cast<float>(morph::" << nspacename << "::cm_"<< name_upperfirst << ".size()-1))));\n"
<< " c = morph::" << nspacename << "::cm_" << name_upperfirst << "[datum_i];\n"
<< " break;\n"
<< " }\n";

cpp_content4 << " cmap_types.push_back (morph::ColourMapType::" << name_upperfirst << ");\n";
}
hpp << " } // namespace " << nspacename << "\n";
hpp << "} // namespace morph\n";

hpp.close();
cpp_content0.close();
cpp_content1.close();
cpp_content2.close();
cpp_content3.close();
cpp_content4.close();

return 0;
}
36 changes: 30 additions & 6 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ if(ARMADILLO_FOUND)
target_link_libraries(hexgrid GLEW::GLEW)
endif()

add_executable(colourbars colourbars.cpp)
target_link_libraries(colourbars OpenGL::GL glfw Freetype::Freetype)
add_executable(colourbar colourbar.cpp)
target_link_libraries(colourbar OpenGL::GL glfw Freetype::Freetype)
if(USE_GLEW)
target_link_libraries(colourbars GLEW::GLEW)
target_link_libraries(colourbar GLEW::GLEW)
endif()

add_executable(unicode_coordaxes unicode_coordaxes.cpp)
Expand All @@ -223,10 +223,34 @@ if(ARMADILLO_FOUND)

endif(ARMADILLO_FOUND)

add_executable(colourmaps colourmaps.cpp)
target_link_libraries(colourmaps OpenGL::GL glfw Freetype::Freetype)
add_executable(colourmaps_other colourmaps_other.cpp)
target_link_libraries(colourmaps_other OpenGL::GL glfw Freetype::Freetype)
if(USE_GLEW)
target_link_libraries(colourmaps GLEW::GLEW)
target_link_libraries(colourmaps_other GLEW::GLEW)
endif()

add_executable(colourmaps_crameri colourmaps_crameri.cpp)
target_link_libraries(colourmaps_crameri OpenGL::GL glfw Freetype::Freetype)
if(USE_GLEW)
target_link_libraries(colourmaps_crameri GLEW::GLEW)
endif()

add_executable(colourmaps_cet colourmaps_cet.cpp)
target_link_libraries(colourmaps_cet OpenGL::GL glfw Freetype::Freetype)
if(USE_GLEW)
target_link_libraries(colourmaps_cet GLEW::GLEW)
endif()

add_executable(colourmaps_lenthe colourmaps_lenthe.cpp)
target_link_libraries(colourmaps_lenthe OpenGL::GL glfw Freetype::Freetype)
if(USE_GLEW)
target_link_libraries(colourmaps_lenthe GLEW::GLEW)
endif()

add_executable(colourmaps_matplotlib colourmaps_matplotlib.cpp)
target_link_libraries(colourmaps_matplotlib OpenGL::GL glfw Freetype::Freetype)
if(USE_GLEW)
target_link_libraries(colourmaps_matplotlib GLEW::GLEW)
endif()

# On MacOS 13 as a github runner, HAVE_STD_FORMAT gets set to 1, but
Expand Down
File renamed without changes.
Loading

0 comments on commit 22842a8

Please sign in to comment.