Point Colors 🌈 (#143)

* add : `DEFAULT_CMAP` added.

* add : `filter_cmap` added.

* edit : `cmap` added to proper functions accordingly.

* add : `cmap` added to the realted methods.

* log : changes logged. (#75)

* add : `c` added to `plot`, now list of colors are supported.

* add : `cmap` added to save and load (config and data).

* fix : minor bug related to cmap always being `DEFAULT_CMAP` fixed.

* change : minor change in `filter_cmap`.

* fix : `str` type cmap suuport added.

* add : serializing the cmap.

* fix : `Colormap` issue fixed.

* change : `DEFAULT_CMAP`: `viridis` --> `cm.get_cmap("viridis", 256)`.

* fix : minor bugs fixed.

* edit : changes are no applied on all entries of a `cmap.colors`.

* add : minor tests added.

* edit : minor edits in tests.

* fix : minor issues in tests fixed.

* add : `_serialize_color` function.

* test : add few tests.

* fix : trailing whitespace fixed.

* test : a test added.

* edit : minor edit in `filter_cmap`.

* remove : `c` parameter removed.

* fix : minor typo fixed.
pull/146/head
Sadra Sabouri 2022-08-28 00:27:20 +04:30 zatwierdzone przez GitHub
rodzic 9c6fbeafeb
commit d67d69c9dd
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
6 zmienionych plików z 139 dodań i 3 usunięć

Wyświetl plik

@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Changed
- `cmap` parameter added to `plot` method
- Random mode modified
- Test system modified
- `generate` method optimized

Wyświetl plik

@ -8,12 +8,15 @@ import re
import json
import random
import matplotlib
from matplotlib import cm
from matplotlib.colors import ListedColormap
from .params import DEFAULT_START, DEFAULT_STOP, DEFAULT_STEP, DEFAULT_COLOR, DEFAULT_IMAGE_SIZE, DEFAULT_DEPTH
from .params import DEFAULT_CMAP, DEFAULT_CMAP_RANGE
from .params import DEFAULT_BACKGROUND_COLOR, DEFAULT_SPOT_SIZE, DEFAULT_PROJECTION, DEFAULT_ALPHA, DEFAULT_LINEWIDTH
from .params import Projection, VALID_COLORS, HEX_COLOR_PATTERN, NFT_STORAGE_API, NFT_STORAGE_LINK, OVERVIEW
from .params import DATA_TYPE_ERROR, CONFIG_TYPE_ERROR, PLOT_DATA_ERROR, CONFIG_NO_STR_FUNCTION_ERROR
from .params import NO_FIG_ERROR_MESSAGE, FIG_SAVE_SUCCESS_MESSAGE, NFT_STORAGE_SUCCESS_MESSAGE, SAVE_NO_DATA_ERROR
from .params import INVALID_COLOR_TYPE_ERROR
from .params import INVALID_COLOR_TYPE_ERROR, COLOR_SIZE_ERROR
from .params import BOTH_COLOR_COMPLEMENT_WARNING, COLOR_NOT_FOUND_WARNING
from .params import DATA_SAVE_SUCCESS_MESSAGE, SEED_LOWER_BOUND, SEED_UPPER_BOUND
from .params import ELEMENTS_LIST, ARGUMENTS_LIST, OPERATORS_LIST, RANDOM_COEF_LIST
@ -159,6 +162,29 @@ def filter_color(color, bgcolor):
return color, bgcolor
def filter_cmap(cmap):
"""
Filter given cmap.
:param cmap: color map
:type cmap: matplotlib.colors.Colormap or list of colors
:return: filtered version of cmap
"""
if isinstance(cmap, str):
cmap = cm.get_cmap(cmap, 256)
if type(cmap) == matplotlib.colors.Colormap:
cmap = cm.get_cmap(cmap.__getattribute__("name"))
if isinstance(cmap, matplotlib.colors.ListedColormap):
return cmap
if isinstance(cmap, (matplotlib.colors.LinearSegmentedColormap)):
cmap = cmap(range(DEFAULT_CMAP_RANGE))
return ListedColormap(cmap)
if isinstance(cmap, list):
cmap = list(map(select_color, cmap))
return ListedColormap(cmap)
return None
def select_color(color):
"""
Select color and return it.
@ -262,6 +288,7 @@ def plot_params_filter(
g,
color=None,
bgcolor=None,
cmap=None,
spot_size=None,
size=None,
projection=None,
@ -276,6 +303,8 @@ def plot_params_filter(
:type color: str
:param bgcolor: background color
:type bgcolor: str
:param cmap: color map
:type cmap: matplotlib.colors.Colormap or list of colors
:param spot_size: point spot size
:type spot_size: float
:param size: figure size
@ -292,7 +321,13 @@ def plot_params_filter(
raise samilaPlotError(PLOT_DATA_ERROR.format(1))
if g.data2 is None:
raise samilaPlotError(PLOT_DATA_ERROR.format(2))
color, bgcolor = filter_color(color, bgcolor)
if isinstance(color, list):
if len(color) != len(g.data1):
raise samilaPlotError(COLOR_SIZE_ERROR)
bgcolor = select_color(bgcolor)
else:
color, bgcolor = filter_color(color, bgcolor)
cmap = filter_cmap(cmap)
projection = filter_projection(projection)
alpha = filter_float(alpha)
linewidth = filter_float(linewidth)
@ -302,6 +337,8 @@ def plot_params_filter(
color = g.color
if bgcolor is None:
bgcolor = g.bgcolor
if cmap is None:
cmap = g.cmap
if spot_size is None:
spot_size = g.spot_size
if size is None:
@ -312,7 +349,8 @@ def plot_params_filter(
alpha = g.alpha
if linewidth is None:
linewidth = g.linewidth
g.color, g.bgcolor, g.spot_size, g.size, g.projection, g.alpha, g.linewidth = color, bgcolor, spot_size, size, projection, alpha, linewidth
g.color, g.bgcolor, g.cmap, g.spot_size, g.size, g.projection, g.alpha, g.linewidth = \
color, bgcolor, cmap, spot_size, size, projection, alpha, linewidth
def generate_params_filter(
@ -410,6 +448,7 @@ def _GI_initializer(g, function1, function2):
g.data2 = None
g.color = DEFAULT_COLOR
g.bgcolor = DEFAULT_BACKGROUND_COLOR
g.cmap = DEFAULT_CMAP
g.spot_size = DEFAULT_SPOT_SIZE
g.size = DEFAULT_IMAGE_SIZE
g.projection = DEFAULT_PROJECTION
@ -468,6 +507,7 @@ def save_data_file(g, file_adr):
data['plot'] = {
"color": g.color,
"bgcolor": g.bgcolor,
"cmap": _serialize_cmap(g.cmap),
"spot_size": g.spot_size,
"projection": g.projection,
"alpha": g.alpha,
@ -511,6 +551,7 @@ def save_config_file(g, file_adr):
data['plot'] = {
"color": g.color,
"bgcolor": g.bgcolor,
"cmap": _serialize_cmap(g.cmap),
"spot_size": g.spot_size,
"projection": g.projection,
"alpha": g.alpha,
@ -618,6 +659,44 @@ def is_same_data(data1, data2, precision=10**-5):
return all(is_same)
def _serialize_color(color):
"""
Serialize the given color to a json serializable object.
:param color: given color
:type color: str or nd.array
:return: the serializable version of the color
"""
if isinstance(color, str):
return color
return list(color)
def _serialize_cmap(cmap):
"""
Serialize the cmap for saving.
:param cmap: color map
:type cmap: matplotlib.colors.Colormap
:return: list of colors
"""
return list(map(_serialize_color, cmap.colors))
def _load_cmap(config):
"""
Load the cmap from config.
:param config: plot part configuration
:type config: dict or json
:return: ListedColormap from cmap
"""
if "cmap" not in config:
return DEFAULT_CMAP
cmap = config["cmap"]
return ListedColormap(cmap)
def load_data(g, data):
"""
Load data file.
@ -638,6 +717,7 @@ def load_data(g, data):
if plot_config is not None:
g.color = plot_config.get("color", DEFAULT_COLOR)
g.bgcolor = plot_config.get("bgcolor", DEFAULT_BACKGROUND_COLOR)
g.cmap = _load_cmap(plot_config)
g.spot_size = plot_config.get("spot_size", DEFAULT_SPOT_SIZE)
g.projection = plot_config.get("projection", DEFAULT_PROJECTION)
g.alpha = plot_config.get("alpha", DEFAULT_ALPHA)
@ -673,6 +753,7 @@ def load_config(g, config):
if plot_config is not None:
g.color = plot_config.get("color", DEFAULT_COLOR)
g.bgcolor = plot_config.get("bgcolor", DEFAULT_BACKGROUND_COLOR)
g.cmap = _load_cmap(plot_config)
g.spot_size = plot_config.get("spot_size", DEFAULT_SPOT_SIZE)
g.projection = plot_config.get("projection", DEFAULT_PROJECTION)
g.alpha = plot_config.get("alpha", DEFAULT_ALPHA)

Wyświetl plik

@ -91,6 +91,7 @@ class GenerativeImage:
self,
color=None,
bgcolor=None,
cmap=None,
spot_size=None,
size=None,
projection=None,
@ -103,6 +104,8 @@ class GenerativeImage:
:type color: str
:param bgcolor: background color
:type bgcolor: str
:param cmap: color map
:type cmap: matplotlib.colors.Colormap or list of colors
:param spot_size: point spot size
:type spot_size: float
:param size: figure size
@ -119,6 +122,7 @@ class GenerativeImage:
self,
color,
bgcolor,
cmap,
spot_size,
size,
projection,
@ -133,6 +137,7 @@ class GenerativeImage:
self.data1,
alpha=self.alpha,
c=self.color,
cmap=self.cmap,
s=self.spot_size,
lw=self.linewidth)
ax.set_axis_off()

Wyświetl plik

@ -3,6 +3,7 @@
import math
from enum import Enum
from matplotlib import colors as mcolors
from matplotlib import cm
SAMILA_VERSION = "0.8" # pragma: no cover
@ -18,6 +19,8 @@ DEFAULT_STOP = math.pi
DEFAULT_STEP = 0.01
DEFAULT_COLOR = "black"
DEFAULT_BACKGROUND_COLOR = "white"
DEFAULT_CMAP = cm.get_cmap("viridis", 256)
DEFAULT_CMAP_RANGE = 256
DEFAULT_ALPHA = 0.1
DEFAULT_LINEWIDTH = 1.5
DEFAULT_IMAGE_SIZE = (10, 10)
@ -38,6 +41,7 @@ DATA_TYPE_ERROR = "Provided data file is not supported. It should be either file
CONFIG_TYPE_ERROR = "Provided config file is not supported. It should be either file or io.IOBase."
CONFIG_NO_STR_FUNCTION_ERROR = "Config file can't be saved. At least one of the function1_str or function2_str is None."
PLOT_DATA_ERROR = "Plotting process can't be Done because data{0} is empty. Use generate method first."
COLOR_SIZE_ERROR = "Color list size is not equal to the data size."
SAVE_NO_DATA_ERROR = "Data file can't be saved. At least one of the data1 or data2 is None."
INVALID_COLOR_TYPE_ERROR = "Given color/bgcolor type is not supported."
MATPLOTLIB_VERSION_WARNING = "Source matplotlib version({0}) is different from yours, plots may be different."

Wyświetl plik

@ -39,6 +39,10 @@ samila.errors.samilaPlotError: Plotting process can't be Done because data2 is e
Traceback (most recent call last):
...
samila.errors.samilaPlotError: Given color/bgcolor type is not supported.
>>> g.plot(color=[0])
Traceback (most recent call last):
...
samila.errors.samilaPlotError: Color list size is not the equal to the data size.
>>> g = GenerativeImage(lambda x,y: x, lambda x,y: y)
>>> result = g.save_config()
Traceback (most recent call last):

Wyświetl plik

@ -6,6 +6,7 @@
>>> import pickle
>>> import socket
>>> import json
>>> from matplotlib.colors import Colormap, ListedColormap
>>> def guard(*args, **kwargs):
... raise Exception("No internet connection!")
>>> from samila import GenerativeImage, Projection
@ -222,6 +223,46 @@ False
[0]
>>> g.data2
[1]
>>> with open("data.json", 'w') as fp:
... json.dump({'data1': [0], 'data2': [1], 'plot':{}}, fp)
>>> g = GenerativeImage(data=open("data.json", 'r'))
>>> with open("config.json", 'w') as fp:
... json.dump({'f1': "x", 'f2': "y", 'plot':{}}, fp)
>>> g = GenerativeImage(data=open("config.json", 'r'))
>>> g = GenerativeImage()
>>> g.generate()
>>> cm = Colormap(name="Purples")
>>> g.plot(cmap=cm)
>>> result = g.save_config("config.json")
>>> result["status"]
True
>>> g_ = GenerativeImage(data=open("config.json", 'r'))
>>> (g_.cmap.colors == g.cmap.colors).all()
True
>>> cm = ["black", [0.6, 0.2, 0.2, 1], [0.5, 0.2, 0.2, 1], [0.4, 0.2, 0.2, 1], "yellow", [0.2, 0.2, 0.2, 1],]
>>> g.plot(cmap=cm)
>>> result = g.save_config("config.json")
>>> result["status"]
True
>>> g_ = GenerativeImage(data=open("config.json", 'r'))
>>> g_.cmap.colors == g.cmap.colors
True
>>> g.plot(cmap="Purples")
>>> cm = Colormap(name="viridis")
>>> g.plot(cmap=cm)
>>> cmap = [[0.7, 0.2, 0.2, 1], [0.6, 0.2, 0.2, 1], [0.3, 0.2, 0.2, 1], [0.2, 0.2, 0.2, 1]]
>>> g.plot(cmap=ListedColormap(cmap))
>>> g = GenerativeImage()
>>> g.generate()
>>> g.plot(cmap=cmap, color=g.data1)
>>> result = g.save_data("config.json")
>>> result["status"]
True
>>> g_ = GenerativeImage(data=open("config.json", "r"))
>>> g_.plot()
>>> g_.cmap.colors == g.cmap.colors
True
>>> g.plot(color=g.data1)
>>> g_ = GenerativeImage()
>>> del(g)
>>> del g_.data1