feat: initial commit
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# Matplotlib.ColorMaps
|
||||
|
||||
This code is based on the [SciColorMaps](https://github.com/ar1st0crat/SciColorMaps) project by Tim Sharii,
|
||||
which in turn is based on the [matplotlib](https://matplotlib.org/3.5.0/tutorials/colors/colormaps.html)
|
||||
Python colormap implementation(s).
|
||||
|
||||
## Run
|
||||
|
||||
`dotnet run`
|
||||
|
||||
63
SciColorMaps/.gitattributes
vendored
63
SciColorMaps/.gitattributes
vendored
@@ -1,63 +0,0 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
252
SciColorMaps/.gitignore
vendored
252
SciColorMaps/.gitignore
vendored
@@ -1,252 +0,0 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Tim
|
||||
|
||||
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.
|
||||
@@ -1,258 +0,0 @@
|
||||
# SciColorMaps
|
||||
|
||||
[](https://opensource.org/licenses/MIT)
|
||||

|
||||
|
||||
Simple and convenient library providing custom .NET color maps (user-defined or imported from matplotlib) for scientific visualization.
|
||||
|
||||
Library comes in two versions (also available as NuGet packages):
|
||||
|
||||
- **SciColorMaps.Portable.dll** does not rely on any framework-dependent color structure (like ```System.Drawing.Color``` or ```System.Windows.Media.Color```). It operates with pure byte arrays, so it can be used in any .NET project.
|
||||
|
||||
- **SciColorMaps.dll** provides some additional functions that handle GDI+ colors, so it can be used in WinForms and WPF projects.
|
||||
|
||||
*NuGet packages contain binaries with all 75 matplotlib colormaps included. In most cases only a small subset of them is what is really needed. Luckily, SciColorMaps can be customized and recompiled quite easily. This repo includes special helper script for making your own SciColorMaps dll. Please [read instructions here](#compiling-scicolormaps) how to use it.*
|
||||
|
||||
|
||||
## Base ColorMap class
|
||||
|
||||
Usage example:
|
||||
|
||||
```C#
|
||||
// create 'viridis' colormap with 256 colors, mapping values from range [0, 1]
|
||||
var cmap1 = new ColorMap();
|
||||
|
||||
// create 'rainbow' colormap with 256 colors, mapping values from range [0, 1]
|
||||
var cmap2 = new ColorMap("rainbow");
|
||||
|
||||
// create 'gnuplot' colormap with 256 colors, mapping values from range [-7.5, 7.5]
|
||||
var cmap3 = new ColorMap("gnuplot", -7.5, 7.5);
|
||||
|
||||
// create 'coolwarm' colormap with 64 colors, mapping values from range [10, 100]
|
||||
var cmap = new ColorMap("coolwarm", 10, 100, 64);
|
||||
|
||||
// get color corresponding to value 25
|
||||
var color = cmap[25];
|
||||
|
||||
// print names of all available predefined palettes
|
||||
foreach (var palette in ColorMap.Palettes)
|
||||
{
|
||||
Console.WriteLine(palette);
|
||||
}
|
||||
|
||||
// prints full set of 75 matplotlib colormaps:
|
||||
// accent
|
||||
// afmhot
|
||||
// autumn
|
||||
// ...
|
||||
// ylorbr
|
||||
// ylorrd
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## User-defined colormaps
|
||||
|
||||
Users can create their own color palettes, like this:
|
||||
|
||||
```C#
|
||||
// === works for both versions of SciColorMaps ===
|
||||
|
||||
var rgbs = new [] {
|
||||
new byte[] {0, 0, 0},
|
||||
new byte[] {192, 0, 0},
|
||||
new byte[] {255, 224, 255}
|
||||
};
|
||||
var positions = new float[] { 0, 0.4f, 1 };
|
||||
|
||||
// 1) static factory method with default colormap parameters:
|
||||
var cmap1 = ColorMap.CreateFromColors(rgbs, positions);
|
||||
|
||||
// 2) static factory method, full set of parameters:
|
||||
var cmap2 = ColorMap.CreateFromColors(rgbs, positions, 10, 100, 32);
|
||||
|
||||
// 3) ColorMap constructor:
|
||||
var cmap3 = new ColorMap("my_own_colormap", -2, 2, 128, rgbs, positions);
|
||||
|
||||
|
||||
// === won't compile for SciColorMaps.Portable ===
|
||||
|
||||
var colors = new Color[] { Color.Black, Color.Blue, Color.White };
|
||||
|
||||
// 4) static factory method with default colormap parameters:
|
||||
var cmap4 = ColorMap.CreateFromColors(colors, positions);
|
||||
|
||||
// 5) static factory method, full set of parameters:
|
||||
var cmap5 = ColorMap.CreateFromColors(colors, positions, 10, 100, 32);
|
||||
|
||||
// 6) ColorMap constructor:
|
||||
var cmap6 = new ColorMap("fancy_colormap", 10, 100, 32, colors, positions);
|
||||
|
||||
```
|
||||
|
||||
Options 3 and 6 allow user setting the name of the custom colormap. Otherwise the name is set by default: "user".
|
||||
|
||||
Note also, the first color position should be 0.0f and last position should be 1.0f (otherwise an ArgumentException will be thrown).
|
||||
|
||||
*Byte arrays can be easily converted to any framework-specific color structures/classes.*
|
||||
|
||||
For example, in WPF the following extension method can be used:
|
||||
|
||||
```C#
|
||||
using SciColorMaps.Portable;
|
||||
|
||||
public static class ColorUtils
|
||||
{
|
||||
public static Color ToMediaColor(this byte[] rgb)
|
||||
{
|
||||
return Color.FromRgb(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
var cmap = new ColorMap("ocean");
|
||||
var color = cmap[0.3].ToMediaColor();
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
## Grayscale colormaps
|
||||
|
||||
SciColorMaps provides the ```GrayColorMap``` decorator class. This class replaces base palette with its grayscale analog during construction.
|
||||
|
||||
Usage example:
|
||||
|
||||
```C#
|
||||
// upper sreenshot
|
||||
var cmap1 = new GrayColorMap(new ColorMap("gnuplot2", min, max));
|
||||
|
||||
// lower screenshot
|
||||
var cmap2 = new GrayColorMap(new ColorMap("gnuplot2", min, max), GrayScaleOptions.Lightness);
|
||||
|
||||
|
||||
// the three simple algorithms for conversion are implemented
|
||||
// (as in GIMP: https://docs.gimp.org/2.6/en/gimp-tool-desaturate.html)
|
||||
|
||||
// public enum GrayScaleOptions
|
||||
// {
|
||||
// Luminosity, // gray = 0.21*R + 0.72*G + 0.07*B
|
||||
// Lightness, // gray = (max(R, G, B) + min(R, G, B)) / 2
|
||||
// Average // gray = (R + G + B) / 3
|
||||
// }
|
||||
|
||||
// GrayScaleOptions.Luminosity is used by default
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
## Mirrored colormaps
|
||||
|
||||
SciColorMaps also provides the ```MirrorColorMap``` decorator class. This class replaces base palette with its mirrored analog during construction.
|
||||
|
||||
Usage example:
|
||||
|
||||
```C#
|
||||
// mirrored colors
|
||||
var cmap = new MirrorColorMap(new ColorMap("ocean"));
|
||||
|
||||
```
|
||||
|
||||
|
||||
## WinForms demo app
|
||||
|
||||
Left button click on surface 2d area -> change colormap to its mirrored version.
|
||||
|
||||
Right button click on surface 2d area -> change colormap to its grayscale version.
|
||||
|
||||
Left button click on colormap strip -> open dialog for constructing your own palette.
|
||||
|
||||
|
||||
## WPF demo app
|
||||
|
||||
Shows how to use SciColorMaps.Portable.
|
||||
|
||||

|
||||
|
||||
|
||||
## UWP demo app
|
||||
|
||||
Shows how to use SciColorMaps.Portable in UWP projects.
|
||||
|
||||
The app allows loading sound from wav/mp3/mp4 files as well as recording sound from any input device (most likely, the microphone). When the audio signal is loaded, the app evaluates and visualizes its spectrogram in 2D and 3D. The visualization is based on the colormap selected in the left panel of a main page. Check it out: 3D-spectrogram with 'blues' colormap looks just like mountains in the fog ))
|
||||
|
||||

|
||||
|
||||
|
||||
## Compiling SciColorMaps
|
||||
|
||||
All customizable parameters are contained in ```Palette.cs``` file. So there's a helper script that can generate this file according to particular needs. Here's how to use it:
|
||||
|
||||
1) Download or clone this repo
|
||||
|
||||
2) Go to ```matplotlib``` folder and edit ```colormaps.txt``` text file, e.g.:
|
||||
|
||||
```
|
||||
ocean
|
||||
hot
|
||||
coolwarm
|
||||
```
|
||||
|
||||
Basically you include here only colormaps you really need. You can view all available colormap names in ```colormaps``` subfolder. If you specify non-existing colormap it'll be simply ignored.
|
||||
|
||||
Note also that 'viridis' will be included to the list anyway since it's the default modern colormap.
|
||||
|
||||
3) run ```generate_cs.py``` script:
|
||||
|
||||
```
|
||||
python generate_cs.py [-r 16] [-p] [-a]
|
||||
```
|
||||
|
||||
```-r``` - colormap resolution (number of base colors; should be 8, 16, 32, 64, 128 or 256)
|
||||
|
||||
```-p``` - if specified then generate cs file for portable SciColorMaps version
|
||||
|
||||
```-a``` - if specified then generate cs file with all palettes found in ```colormaps``` folder (ignoring ```colormaps.txt``` input file)
|
||||
|
||||
Examples:
|
||||
```
|
||||
// generate cs file with all palettes found in colormaps folder
|
||||
// (ignore colormaps.txt) and resolution = 8 base colors
|
||||
|
||||
python generate_cs.py -r 8 -a
|
||||
|
||||
|
||||
// generate cs file for portable version
|
||||
// (with default resolution = 16 base colors)
|
||||
|
||||
python generate_cs.py -p
|
||||
```
|
||||
|
||||
4) go to ```cs``` subfolder and copy generated ```Palette.cs``` file to ```SciColorMaps``` or ```SciColorMaps.Portable``` project folder.
|
||||
|
||||
5) open ```SciColorMaps.sln``` in Visual Studio and compile new dll.
|
||||
|
||||
|
||||
**RECTANGULAR conditional compilation symbol**
|
||||
|
||||
Accessing elements in jagged arrays is significantly faster (up to **40%**) compared to rectangular arrays, hence the jagged arrays are used and compiled by default. If an efficient memory management is of more importance then compile SciColorMaps with the 'RECTANGULAR' conditional compilation symbol.
|
||||
|
||||
| compilation | dll size |
|
||||
----------------|-----------
|
||||
| default | ~95kb |
|
||||
| RECTANGULAR | ~29kb |
|
||||
|
||||
Also, if you are worried about the memory usage, please note that palette arrays are instantiated *lazily* in the calling code, e.g.:
|
||||
|
||||
```C#
|
||||
var palette = Palette.GnuPlot.Value;
|
||||
|
||||
```
|
||||
@@ -1,311 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SciColorMaps.Portable
|
||||
{
|
||||
/// <summary>
|
||||
/// Color map
|
||||
/// 1) uses particular color palette (as in matplotlib or user-defined),
|
||||
/// 2) automatically calculates color by value and range,
|
||||
/// 3) can work with any number of colors in range [2, 256]
|
||||
///
|
||||
/// Usage example:
|
||||
///
|
||||
/// var cmap = new ColorMap("coolwarm", -0.5, 0.5));
|
||||
/// ...
|
||||
/// var color = cmap[0.3];
|
||||
///
|
||||
/// var viridis = new ColorMap();
|
||||
///
|
||||
/// var cm = new ColorMap("ocean", 10, 100, 32 /*colors*/)
|
||||
///
|
||||
///
|
||||
/// All standard matplotlib palettes are available including:
|
||||
/// bone, cool, coolwarm, gist_earth, gnuplot, gnuplot2, hot, inferno,
|
||||
/// jet, ocean, rainbow, seismic, spectral, terrain, viridis (default), etc.
|
||||
///
|
||||
/// Users can create their own palettes, like this:
|
||||
///
|
||||
/// var colors = new [] {
|
||||
/// new byte[] {0, 0, 0},
|
||||
/// new byte[] {192, 0, 0},
|
||||
/// new byte[] {255, 224, 255}
|
||||
/// };
|
||||
/// var positions = new [] { 0, 0.4f, 1 };
|
||||
///
|
||||
/// // 1) static factory method with default colormap parameters:
|
||||
/// var cmap1 = ColorMap.CreateFromColors(colors, positions);
|
||||
///
|
||||
/// // 2) static factory method, full set of parameters:
|
||||
/// var cmap2 = ColorMap.CreateFromColors(colors, positions, 10, 100, 32);
|
||||
///
|
||||
/// // 3) ColorMap constructor:
|
||||
/// var cmap3 = new ColorMap("my_own_colormap", 10, 100, 32, colors, positions);
|
||||
///
|
||||
/// // Option 3 allows user setting the name of the custom colormap
|
||||
/// // Otherwise the name is set by default: "user"
|
||||
///
|
||||
/// </summary>
|
||||
public class ColorMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Color palette is an array of predefined RGB values
|
||||
/// </summary>
|
||||
protected byte[][] _palette;
|
||||
|
||||
/// <summary>
|
||||
/// Number of colors in colormap
|
||||
/// </summary>
|
||||
private readonly int _colorCount;
|
||||
|
||||
/// <summary>
|
||||
/// Lower bound of the colormap range
|
||||
/// </summary>
|
||||
private readonly double _lower;
|
||||
|
||||
/// <summary>
|
||||
/// Upper bound of the colormap range
|
||||
/// </summary>
|
||||
private readonly double _upper;
|
||||
|
||||
/// <summary>
|
||||
/// Range of values corresponding to one color in the colormap
|
||||
/// (is calculated in the constructor based on given parameters)
|
||||
/// </summary>
|
||||
private readonly double _colorRange;
|
||||
|
||||
/// <summary>
|
||||
/// Number of palette colors corresponding to one color in the colormap
|
||||
/// (is calculated in the constructor based on given parameters)
|
||||
/// </summary>
|
||||
private readonly double _colorBinSize;
|
||||
|
||||
/// <summary>
|
||||
/// Palette name ("jet", "viridis", "terrain", etc.)
|
||||
/// </summary>
|
||||
public string PaletteName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of interpolated colors in palettes (full palette)
|
||||
/// (currently 256, but it is customizable)
|
||||
/// </summary>
|
||||
public const int PaletteColors = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Return collection of available palettes
|
||||
/// </summary>
|
||||
public static IEnumerable<string> Palettes => Palette.Names;
|
||||
|
||||
private const string DefaultPalette = "viridis";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor creates Viridis colormap
|
||||
/// </summary>
|
||||
public ColorMap() : this(DefaultPalette)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="colorMap">Copied colormap</param>
|
||||
public ColorMap(ColorMap colorMap)
|
||||
{
|
||||
PaletteName = colorMap.PaletteName;
|
||||
_palette = colorMap._palette;
|
||||
_lower = colorMap._lower;
|
||||
_upper = colorMap._upper;
|
||||
_colorCount = colorMap._colorCount;
|
||||
_colorRange = colorMap._colorRange;
|
||||
_colorBinSize = colorMap._colorBinSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct new colormap
|
||||
/// </summary>
|
||||
/// <param name="name">Palette name</param>
|
||||
/// <param name="lower">Lower bound of the colormap range (optional)</param>
|
||||
/// <param name="upper">Upper bound of the colormap range (optional)</param>
|
||||
/// <param name="colorCount">Number of colors in colormap (optional)</param>
|
||||
/// <param name="colors">User-defined collection of colors (optional)</param>
|
||||
/// <param name="positions">User-defined collection of color positions in palette (optional)</param>
|
||||
/// <exception cref="ArgumentException">Thrown if:
|
||||
/// 1) Palette name is null
|
||||
/// 2) Number of colors is less than 2 or greater than number of colors in palette
|
||||
/// 3) Lower bound is greater than the upper one
|
||||
/// </exception>
|
||||
public ColorMap(string name,
|
||||
double lower = 0.0,
|
||||
double upper = 1.0,
|
||||
int colorCount = PaletteColors,
|
||||
IEnumerable<byte[]> colors = null,
|
||||
IEnumerable<float> positions = null)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentException("Palette name should not be null!");
|
||||
}
|
||||
|
||||
if (colorCount <= 1 || colorCount > PaletteColors)
|
||||
{
|
||||
throw new ArgumentException(string.Format(
|
||||
"Number of colors should be in range [2, {0}]!", PaletteColors));
|
||||
}
|
||||
|
||||
if (lower >= upper)
|
||||
{
|
||||
throw new ArgumentException("Upper bound should be greater than the lower one!");
|
||||
}
|
||||
|
||||
_colorCount = colorCount;
|
||||
_lower = lower;
|
||||
_upper = upper;
|
||||
_colorRange = (_upper - _lower) / _colorCount;
|
||||
_colorBinSize = PaletteColors / (_colorCount - 1 + 1.0 / PaletteColors);
|
||||
|
||||
// create colormap from a predefined palette:
|
||||
if (colors == null)
|
||||
{
|
||||
PaletteName = name.ToLower();
|
||||
|
||||
if (!Palette.ByName.ContainsKey(PaletteName))
|
||||
{
|
||||
PaletteName = DefaultPalette;
|
||||
}
|
||||
|
||||
positions = Enumerable.Range(0, Palette.Resolution)
|
||||
.Select(pos => (float)pos / (Palette.Resolution - 1))
|
||||
.ToArray();
|
||||
|
||||
CreatePalette(Palette.ByName[PaletteName].Value, positions);
|
||||
}
|
||||
// create colormap from user-defined colors:
|
||||
else
|
||||
{
|
||||
CreatePalette(colors, positions);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static factory method for creating user-defined palette
|
||||
/// </summary>
|
||||
/// <param name="colors">Collection of colors as byte[3] arrays</param>
|
||||
/// <returns>ColorMap object</returns>
|
||||
public static ColorMap CreateFromColors(IEnumerable<byte[]> colors,
|
||||
IEnumerable<float> positions,
|
||||
double lower = 0.0,
|
||||
double upper = 1.0,
|
||||
int colorCount = PaletteColors)
|
||||
{
|
||||
return new ColorMap("user", lower, upper, colorCount, colors, positions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method performs a simple RGB color interpolation for creating user-defined palette
|
||||
/// </summary>
|
||||
/// <param name="colors">Collection of colors</param>
|
||||
/// <param name="positions">Collection of color positions</param>
|
||||
/// <exception cref="ArgumentException">Thrown if:
|
||||
/// 1) Collection of colors or color positions is null
|
||||
/// 2) Number of colors is not the same as the number of color positions
|
||||
/// 3) Number of colors is not in the range [2, PaletteColors]
|
||||
/// 4) First color position is not 0.0f or last position is not 1.0f
|
||||
/// </exception>
|
||||
private void CreatePalette(IEnumerable<byte[]> colors, IEnumerable<float> positions)
|
||||
{
|
||||
if (colors == null || positions == null)
|
||||
{
|
||||
throw new ArgumentException("Collections of colors and positions should not be null!");
|
||||
}
|
||||
|
||||
if (colors.Count() != positions.Count())
|
||||
{
|
||||
throw new ArgumentException("Number of colors should be the same as the number of color positions!");
|
||||
}
|
||||
|
||||
if (colors.Count() <= 1 || colors.Count() > PaletteColors)
|
||||
{
|
||||
throw new ArgumentException(string.Format(
|
||||
"Number of colors should be in range [2, {0}]!", PaletteColors));
|
||||
}
|
||||
|
||||
if (positions.First().CompareTo(0) != 0 || positions.Last().CompareTo(1) != 0)
|
||||
{
|
||||
throw new ArgumentException("First color position should be 0.0f and last position should be 1.0f!");
|
||||
}
|
||||
|
||||
if (colors.Any(c => c.Length != 3))
|
||||
{
|
||||
throw new ArgumentException("Each color should be an array of 3 bytes!");
|
||||
}
|
||||
|
||||
_palette = new byte[PaletteColors][];
|
||||
|
||||
var groups = positions.Select(pos => (int)(pos * PaletteColors)).ToList();
|
||||
|
||||
var i = 0;
|
||||
for (var group = 0; group < groups.Count - 1; group++)
|
||||
{
|
||||
var color1 = colors.ElementAt(group);
|
||||
var color2 = colors.ElementAt(group + 1);
|
||||
|
||||
var groupSize = groups[group + 1] - groups[group];
|
||||
|
||||
for (var j = 0; j < groupSize; j++)
|
||||
{
|
||||
_palette[i] = new byte[3];
|
||||
|
||||
_palette[i][0] = (byte)(color1[0] + (double)(color2[0] - color1[0]) * j / groupSize);
|
||||
_palette[i][1] = (byte)(color1[1] + (double)(color2[1] - color1[1]) * j / groupSize);
|
||||
_palette[i][2] = (byte)(color1[2] + (double)(color2[2] - color1[2]) * j / groupSize);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method returns colorCount-sized collection of base colors covering entire palette
|
||||
/// </summary>
|
||||
/// <returns>Collection of colors</returns>
|
||||
public IEnumerable<byte[]> Colors()
|
||||
{
|
||||
for (var i = 0; i < _colorCount; i++)
|
||||
{
|
||||
var idx = (int)(i * _colorBinSize);
|
||||
yield return _palette[idx];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get RGB values corresponding to a given domain value
|
||||
/// </summary>
|
||||
/// <param name="value">Particular domain value</param>
|
||||
/// <returns>Array of 3 bytes (R, G, B)</returns>
|
||||
public byte[] this[double value]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (value <= _lower)
|
||||
{
|
||||
return _palette[0];
|
||||
}
|
||||
|
||||
if (value >= _upper)
|
||||
{
|
||||
return _palette[PaletteColors - 1];
|
||||
}
|
||||
|
||||
// get position of the closest color with current resolution
|
||||
var pos = (int)((value - _lower) / _colorRange);
|
||||
|
||||
// get the index of this color in palette
|
||||
var idx = (int)(pos * _colorBinSize);
|
||||
|
||||
return _palette[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace SciColorMaps.Portable
|
||||
{
|
||||
/// <summary>
|
||||
/// ColorMap decorator that converts all colors of decorated colormap to grayscale
|
||||
///
|
||||
/// Usage example:
|
||||
///
|
||||
/// var cmap = new GrayColorMap(new ColorMap("viridis", -0.5, 0.5));
|
||||
/// ...
|
||||
/// var color = cmap[0.3];
|
||||
///
|
||||
/// Important:
|
||||
/// Method allocates NEW memory for palette array
|
||||
/// so that it doesn't affect predefined palettes
|
||||
///
|
||||
/// </summary>
|
||||
public class GrayColorMap : ColorMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Grayscale conversion options
|
||||
/// </summary>
|
||||
private readonly GrayScaleOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Recalculate palette colors each using one of 3 simple formulae
|
||||
/// </summary>
|
||||
private void MakePaletteGrayscale()
|
||||
{
|
||||
var prevPalette = _palette;
|
||||
|
||||
// important: create new array for palette
|
||||
_palette = new byte[PaletteColors][];
|
||||
|
||||
Func<byte[], byte> convertToGray;
|
||||
|
||||
switch (_options)
|
||||
{
|
||||
case GrayScaleOptions.Lightness:
|
||||
convertToGray = color => (byte)((color.Max() + color.Min()) / 2);
|
||||
break;
|
||||
case GrayScaleOptions.Average:
|
||||
convertToGray = color => (byte)((color[0] + color[1] + color[2]) / 3);
|
||||
break;
|
||||
default:
|
||||
convertToGray = color => (byte)(color[0] * 0.21 + color[1] * 0.72 + color[2] * 0.07);
|
||||
break;
|
||||
}
|
||||
|
||||
for (var i = 0; i < PaletteColors; i++)
|
||||
{
|
||||
var gray = convertToGray(prevPalette[i]);
|
||||
|
||||
_palette[i] = new [] { gray, gray, gray };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor (also calls copy constructor of the base ColorMap class)
|
||||
///
|
||||
/// We gently substitute ordinary palette with grayscale palette
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="colorMap">Decorated colormap</param>
|
||||
/// <param name="options">Luminosity conversion by default</param>
|
||||
public GrayColorMap(ColorMap colorMap,
|
||||
GrayScaleOptions options = GrayScaleOptions.Luminosity)
|
||||
: base(colorMap)
|
||||
{
|
||||
_options = options;
|
||||
|
||||
// magic goes on here:
|
||||
MakePaletteGrayscale();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace SciColorMaps.Portable
|
||||
{
|
||||
/// <summary>
|
||||
/// Three options for how to convert RGB color to grayscale
|
||||
/// (as used in GIMP: https://docs.gimp.org/2.6/en/gimp-tool-desaturate.html)
|
||||
/// </summary>
|
||||
public enum GrayScaleOptions
|
||||
{
|
||||
Luminosity,
|
||||
Lightness,
|
||||
Average
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
namespace SciColorMaps.Portable
|
||||
{
|
||||
/// <summary>
|
||||
/// ColorMap decorator that mirrors colors of decorated colormap
|
||||
///
|
||||
/// Usage example:
|
||||
///
|
||||
/// var cmap = new MirrorColorMap(new ColorMap("ocean"));
|
||||
/// ...
|
||||
/// var color = cmap[0.3];
|
||||
///
|
||||
/// Important:
|
||||
/// Method allocates NEW memory for palette array
|
||||
/// so that it doesn't affect predefined palettes
|
||||
///
|
||||
/// </summary>
|
||||
public class MirrorColorMap : ColorMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Recalculate palette colors
|
||||
/// </summary>
|
||||
private void MakeMirroredPalette()
|
||||
{
|
||||
var prevPalette = _palette;
|
||||
|
||||
// important: create new array for palette
|
||||
_palette = new byte[PaletteColors][];
|
||||
|
||||
for (var i = 0; i < PaletteColors; i++)
|
||||
{
|
||||
var rgb = prevPalette[PaletteColors - 1 - i];
|
||||
|
||||
_palette[i] = new [] { rgb[0], rgb[1], rgb[2] };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor (also calls copy constructor of the base ColorMap class)
|
||||
///
|
||||
/// We gently substitute ordinary palette with mirrored palette
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="colorMap">Decorated colormap</param>
|
||||
public MirrorColorMap(ColorMap colorMap) : base(colorMap)
|
||||
{
|
||||
MakeMirroredPalette();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{CAA31C40-C298-4AB3-B022-3134A08BE626}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SciColorMaps.Portable</RootNamespace>
|
||||
<AssemblyName>SciColorMaps.Portable</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile92</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ColorMap.cs" />
|
||||
<Compile Include="GrayColorMap.cs" />
|
||||
<Compile Include="GrayScaleOptions.cs" />
|
||||
<Compile Include="MirrorColorMap.cs" />
|
||||
<Compile Include="Palette.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -1,4 +0,0 @@
|
||||
ocean
|
||||
cool
|
||||
coolwarm
|
||||
accent
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SciColorMaps{%PORTABLE%}
|
||||
{
|
||||
#if !RECTANGULAR
|
||||
|
||||
/// <summary>
|
||||
/// Class containing colormaps (palettes) imported from matplotlib
|
||||
///
|
||||
/// =========================== IMPORTANT NOTES! ==========================
|
||||
///
|
||||
/// 1)
|
||||
/// Accessing elements in jagged arrays is significantly faster(up to 40%)
|
||||
/// compared to rectangular arrays, so the following code is compiled by default.
|
||||
/// If an efficient memory management is of more importance then compile
|
||||
/// with the 'RECTANGULAR' conditional symbol.
|
||||
///
|
||||
/// 2)
|
||||
/// Palette arrays are instantiated LAZILY in the calling code, e.g.:
|
||||
/// var palette = Palette.GnuPlot.Value;
|
||||
///
|
||||
/// 3)
|
||||
/// All palettes are READONLY arrays. That means they are NOT consts
|
||||
/// and can be modified by calling code. It is AGAINST the contract,
|
||||
/// however for the sake of performance there are currently no
|
||||
/// additional checks or converting to ReadOnlyCollection in the code.
|
||||
///
|
||||
/// </summary>
|
||||
static class Palette
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of base colors in palette
|
||||
/// </summary>
|
||||
public const int Resolution = {%RESOLUTION%};
|
||||
|
||||
#region palettes
|
||||
{%COLORMAP%}
|
||||
/// <summary>
|
||||
/// Colormap "{%COLORMAP_NAME%}" taken from matplotlib
|
||||
/// </summary>
|
||||
public static readonly Lazy<byte[][]> {%COLORMAP_NAME_TITLE%} = new Lazy<byte[][]>(() => new []
|
||||
{
|
||||
{%BYTE[][]%}
|
||||
});{%COLORMAP%}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Convenient dictionary for mapping palette names onto palette byte arrays
|
||||
/// </summary>
|
||||
public static readonly Dictionary<string, Lazy<byte[][]>>
|
||||
ByName = new Dictionary<string, Lazy<byte[][]>>
|
||||
{{%COLORMAP_PAIRS%}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate all available palettes / colormaps
|
||||
/// </summary>
|
||||
public static IEnumerable<string> Names => ByName.Keys;
|
||||
}
|
||||
|
||||
#else
|
||||
public static class Palette
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of base colors in palette
|
||||
/// </summary>
|
||||
public const int Resolution = {%RESOLUTION%};
|
||||
|
||||
#region palettes
|
||||
{%COLORMAP%}
|
||||
/// <summary>
|
||||
/// Colormap "{%COLORMAP_NAME%}" taken from matplotlib
|
||||
/// </summary>
|
||||
public static readonly Lazy<byte[,]> {%COLORMAP_NAME_TITLE%} = new Lazy<byte[,]>(() => new byte[,]
|
||||
{
|
||||
{%BYTE[,]%}
|
||||
});{%COLORMAP%}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Convenient dictionary for mapping palette names onto palette byte arrays
|
||||
/// </summary>
|
||||
public static readonly Dictionary<string, Lazy<byte[,]>>
|
||||
ByName = new Dictionary<string, Lazy<byte[,]>>
|
||||
{{%COLORMAP_PAIRS%}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate all available palettes / colormaps
|
||||
/// </summary>
|
||||
public static IEnumerable<string> Names => ByName.Keys;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
22
matplotlib/colormaps/convert.sh
Normal file
22
matplotlib/colormaps/convert.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
echo "module Matplotlib.ColorMaps.ColorMaps"
|
||||
echo
|
||||
|
||||
for i in *.txt; do
|
||||
cm=$(basename $i .txt)
|
||||
echo "let $cm ="
|
||||
echo " [|"
|
||||
cat $i \
|
||||
| sed -rn '/Jagged.*/,${s/new byte\[\] \{ *([0-9]+), *([0-9]+), *([0-9]+)\},? */ \1uy, \2uy, \3uy\n/gp}' \
|
||||
| sed -r '/^$/d'
|
||||
echo " |]"
|
||||
echo
|
||||
done
|
||||
|
||||
echo "let colormaps ="
|
||||
echo " [|"
|
||||
for i in *.txt; do
|
||||
cm=$(basename $i .txt)
|
||||
echo " \"$cm\", $cm"
|
||||
done
|
||||
echo " |] |> Map.ofArray"
|
||||
|
||||
74
src/ColorMap.fs
Normal file
74
src/ColorMap.fs
Normal file
@@ -0,0 +1,74 @@
|
||||
namespace Matplotlib.ColorMaps
|
||||
|
||||
module ColorMap =
|
||||
type ColorMap(palette: Palette, ?min: float, ?max: float) =
|
||||
let lower = defaultArg min 0.0
|
||||
let upper = defaultArg max 1.0
|
||||
|
||||
let nColors = palette.Length
|
||||
let nColors' = float palette.Length
|
||||
let colorRange = (upper - lower) / float nColors
|
||||
|
||||
do
|
||||
if nColors <= 1 then
|
||||
failwith "Number of colors should be larger than 1!"
|
||||
if lower >= upper then
|
||||
failwith "Upper bound should be greater than the lower one!"
|
||||
|
||||
new (name: string, ?min: float, ?max: float, ?numColors: int) =
|
||||
let paletteName = name.ToLower()
|
||||
let nColors = defaultArg numColors 256
|
||||
let palette =
|
||||
if Map.containsKey paletteName Palette16.palettes |> not then
|
||||
failwith $"Unknown prefefined palette {name}"
|
||||
else
|
||||
ColorMap.makePalette (Palette16.palettes[paletteName], nColors)
|
||||
let lower = defaultArg min 0.0
|
||||
let upper = defaultArg max 1.0
|
||||
ColorMap(palette, lower, upper)
|
||||
|
||||
member val PaletteName = "" with get, set
|
||||
|
||||
member x.Palette = palette
|
||||
|
||||
member x.color (v: float) =
|
||||
let v = // clamp
|
||||
if v < lower then
|
||||
lower
|
||||
elif v > upper then
|
||||
upper
|
||||
else v
|
||||
let idx = (v - lower) / colorRange * nColors' |> int
|
||||
palette[idx]
|
||||
|
||||
static member makePalette (colors: Palette, positions: float [], ?numColors) : Palette =
|
||||
if positions[0] <> 0.0 || positions[^0] <> 1.0 then
|
||||
failwith "First color position should be 0.0f and last position should be 1.0f!"
|
||||
let nColors = defaultArg numColors 256 |> float
|
||||
let groups = positions |> Array.map (fun pos -> pos * nColors |> int)
|
||||
let c2d (r, g, b) = double r, double g, double b
|
||||
|
||||
groups |> Array.collect (fun idx ->
|
||||
let r1, g1, b1 = colors[idx] |> c2d
|
||||
let r2, g2, b2 = colors[idx + 1] |> c2d
|
||||
let groupSize = groups[idx + 1] - groups[idx]
|
||||
let groupSize' = double groupSize
|
||||
[|
|
||||
for j = 0 to groupSize do
|
||||
let j' = double j / groupSize'
|
||||
let r = (r1 + (r2 - r1) * j') |> byte
|
||||
let g = (g1 + (g2 - g1) * j') |> byte
|
||||
let b = (b1 + (b2 - b1) * j') |> byte
|
||||
r, g, b
|
||||
|]
|
||||
)
|
||||
|
||||
static member makePalette (colors: Palette, ?numColors: int) : Palette =
|
||||
let nPalette = defaultArg numColors 256
|
||||
let nColors' = colors.Length |> float
|
||||
let positions =
|
||||
[| 0 .. nPalette - 1 |]
|
||||
|> Array.map (fun pos -> float pos / nColors')
|
||||
ColorMap.makePalette (colors, positions, nPalette)
|
||||
|
||||
|
||||
75
src/GrayColorMap.fs
Normal file
75
src/GrayColorMap.fs
Normal file
@@ -0,0 +1,75 @@
|
||||
namespace Matplotlib.ColorMaps
|
||||
|
||||
open System
|
||||
|
||||
module Gray =
|
||||
// Three options for how to convert RGB color to grayscale
|
||||
// (as used in GIMP: https://docs.gimp.org/2.6/en/gimp-tool-desaturate.html)
|
||||
type GrayScaleOptions =
|
||||
| Luminosity = 0
|
||||
| Lightness = 1
|
||||
| Average = 2
|
||||
|
||||
// ColorMap decorator that converts all colors of decorated colormap to grayscale
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// var cmap = new GrayColorMap(new ColorMap("viridis", -0.5, 0.5))
|
||||
// ...
|
||||
// var color = cmap[0.3]
|
||||
//
|
||||
// Important:
|
||||
// Method allocates NEW memory for palette array
|
||||
// so that it doesn't affect predefined palettes
|
||||
//
|
||||
// public class GrayColorMap : ColorMap
|
||||
// // Grayscale conversion options
|
||||
//
|
||||
// private readonly GrayScaleOptions _options
|
||||
//
|
||||
// // Recalculate palette colors each open one of 3 simple formulae
|
||||
// private void MakePaletteGrayscale()
|
||||
//
|
||||
// var prevPalette = _palette
|
||||
//
|
||||
// // important: create new array for palette
|
||||
// _palette = new byte[PaletteColors][]
|
||||
//
|
||||
// Func<byte[], byte> convertToGray
|
||||
//
|
||||
// switch (_options)
|
||||
//
|
||||
// case GrayScaleOptions.Lightness:
|
||||
// convertToGray = color => (byte)((color.Max() + color.Min()) / 2)
|
||||
// break
|
||||
// case GrayScaleOptions.Average:
|
||||
// convertToGray = color => (byte)((color[0] + color[1] + color[2]) / 3)
|
||||
// break
|
||||
// default:
|
||||
// convertToGray = color => (byte)(color[0] * 0.21 + color[1] * 0.72 + color[2] * 0.07)
|
||||
// break
|
||||
//
|
||||
//
|
||||
// for (var i = 0 i < PaletteColors; i++)
|
||||
//
|
||||
// var gray = convertToGray(prevPalette[i])
|
||||
//
|
||||
// _palette[i] = new [] gray, gray, gray
|
||||
|
||||
|
||||
|
||||
// Constructor (also calls copy constructor of the base ColorMap class)
|
||||
//
|
||||
// We gently substitute ordinary palette with grayscale palette
|
||||
//
|
||||
// public GrayColorMap(ColorMap colorMap,
|
||||
// GrayScaleOptions options = GrayScaleOptions.Luminosity)
|
||||
// : base(colorMap)
|
||||
//
|
||||
// _options = options
|
||||
//
|
||||
// // magic goes on here:
|
||||
// MakePaletteGrayscale()
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
module Matplotlib.ColorMaps
|
||||
|
||||
open System
|
||||
|
||||
let id a = a
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
@@ -9,12 +9,15 @@
|
||||
<Authors></Authors>
|
||||
<Company></Company>
|
||||
<Version>0.0.1</Version>
|
||||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Library.fs" />
|
||||
<Compile Include="GrayColorMap.fs" />
|
||||
<Compile Include="MirrorColorMap.fs" />
|
||||
<Compile Include="Palette.fs" />
|
||||
<Compile Include="ColorMap.fs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FSharp.Data" Version="4.2.7" />
|
||||
<PackageReference Include="FSharpPlus" Version="1.2.2" />
|
||||
<Content Include="*.fsproj; *.fs" PackagePath="fable/" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
42
src/MirrorColorMap.fs
Normal file
42
src/MirrorColorMap.fs
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace Matplotlib.ColorMaps
|
||||
|
||||
module Mirror =
|
||||
|
||||
// ColorMap decorator that mirrors colors of decorated colormap
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// var cmap = new MirrorColorMap(new ColorMap("ocean"))
|
||||
// ...
|
||||
// var color = cmap[0.3]
|
||||
//
|
||||
// Important:
|
||||
// Method allocates NEW memory for palette array
|
||||
// so that it doesn't affect predefined palettes
|
||||
//
|
||||
// public class MirrorColorMap : ColorMap
|
||||
//
|
||||
// // Recalculate palette colors
|
||||
// private void MakeMirroredPalette()
|
||||
//
|
||||
// var prevPalette = _palette
|
||||
//
|
||||
// // important: create new array for palette
|
||||
// _palette = new byte[PaletteColors][]
|
||||
//
|
||||
// for (var i = 0 i < PaletteColors; i++)
|
||||
//
|
||||
// var rgb = prevPalette[PaletteColors - 1 - i]
|
||||
//
|
||||
// _palette[i] = new [] rgb[0], rgb[1], rgb[2]
|
||||
|
||||
|
||||
|
||||
// Constructor (also calls copy constructor of the base ColorMap class)
|
||||
//
|
||||
// We gently substitute ordinary palette with mirrored palette
|
||||
//
|
||||
// public MirrorColorMap(ColorMap colorMap) : base(colorMap)
|
||||
//
|
||||
// MakeMirroredPalette()
|
||||
let mirror = ()
|
||||
1791
src/Palette.fs
Normal file
1791
src/Palette.fs
Normal file
File diff suppressed because it is too large
Load Diff
19583
src/Palette256.fs
Normal file
19583
src/Palette256.fs
Normal file
File diff suppressed because it is too large
Load Diff
13
src/packages.lock.json
Normal file
13
src/packages.lock.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net6.0": {
|
||||
"FSharp.Core": {
|
||||
"type": "Direct",
|
||||
"requested": "[6.0.1, )",
|
||||
"resolved": "6.0.1",
|
||||
"contentHash": "VrFAiW8dEEekk+0aqlbvMNZzDvYXmgWZwAt68AUBqaWK8RnoEVUNglj66bZzhs4/U63q0EfXlhcEKnH1sTYLjw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user