diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
index 7396be3..b63e309 100644
--- a/.github/CODE_OF_CONDUCT.md
+++ b/.github/CODE_OF_CONDUCT.md
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at info@4r7.ir. All
+reported by contacting the project team at info@samila.site. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
diff --git a/.github/workflows/publish_conda.yaml b/.github/workflows/publish_conda.yaml
new file mode 100644
index 0000000..97751a8
--- /dev/null
+++ b/.github/workflows/publish_conda.yaml
@@ -0,0 +1,18 @@
+name: publish_conda
+
+on:
+ push:
+ # Sequence of patterns matched against refs/tags
+ tags:
+ - '*' # Push events to matching v*, i.e. v1.0, v20.15.10
+
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - name: publish-to-conda
+ uses: sepandhaghighi/conda-package-publish-action@v1.2
+ with:
+ subDir: 'otherfiles'
+ AnacondaToken: ${{ secrets.ANACONDA_TOKEN }}
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish_pypi.yml
similarity index 100%
rename from .github/workflows/publish.yml
rename to .github/workflows/publish_pypi.yml
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 25b00ac..19c4376 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -60,3 +60,6 @@ jobs:
run: |
codecov
if: matrix.python-version == 3.7 && matrix.os == 'ubuntu-latest'
+ - name: cProfile
+ run: |
+ python -m cProfile -s cumtime otherfiles/samila_profile.py
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58b399f..eeb16a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
+## [0.9] - 2022-09-28
+### Added
+- Anaconda workflow
+### Changed
+- `README.md` updated
+- `CODE_OF_CONDUCT.md` updated
+- `demo.ipynb` updated
+- `cmap` parameter added to `plot` method
+- Random mode modified
+- Test system modified
+- `generate` method optimized
+- `samila_help` function updated
+- `load_data` and `load_config` functions error handling updated
## [0.8] - 2022-06-01
### Added
- `INVALID_COLOR_TYPE_ERROR` error
@@ -123,7 +136,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `generate` method
- `nft_storage` method
-[Unreleased]: https://github.com/sepandhaghighi/samila/compare/v0.8...dev
+[Unreleased]: https://github.com/sepandhaghighi/samila/compare/v0.9...dev
+[0.9]: https://github.com/sepandhaghighi/samila/compare/v0.8...v0.9
[0.8]: https://github.com/sepandhaghighi/samila/compare/v0.7...v0.8
[0.7]: https://github.com/sepandhaghighi/samila/compare/v0.6...v0.7
[0.6]: https://github.com/sepandhaghighi/samila/compare/v0.5...v0.6
diff --git a/README.md b/README.md
index 0febb45..1ca9b22 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@
+
@@ -88,7 +89,7 @@ Samila is a generative art generator written in Python, Samila let's you create
### Source code
-- Download [Version 0.8](https://github.com/sepandhaghighi/samila/archive/v0.8.zip) or [Latest Source ](https://github.com/sepandhaghighi/samila/archive/dev.zip)
+- Download [Version 0.9](https://github.com/sepandhaghighi/samila/archive/v0.9.zip) or [Latest Source ](https://github.com/sepandhaghighi/samila/archive/dev.zip)
- Run `pip install -r requirements.txt` or `pip3 install -r requirements.txt` (Need root access)
- Run `python3 setup.py install` or `python setup.py install` (Need root access)
@@ -96,12 +97,17 @@ Samila is a generative art generator written in Python, Samila let's you create
- Check [Python Packaging User Guide](https://packaging.python.org/installing/)
-- Run `pip install samila==0.8` or `pip3 install samila==0.8` (Need root access)
+- Run `pip install samila==0.9` or `pip3 install samila==0.9` (Need root access)
### Easy install
- Run `easy_install --upgrade samila` (Need root access)
+### Conda
+
+- Check [Conda Managing Package](https://conda.io)
+- `conda install -c sepandhaghighi samila` (Need root access)
+
## Usage
@@ -181,9 +187,34 @@ Samila is a generative art generator written in Python, Samila let's you create
4. Random (example: `color="random"`)
5. Complement (example: `color="complement", bgcolor="blue"`)
6. Transparent (example: `bgcolor="transparent"`)
+ 7. List (example: `color=["black", "#fffeef",...]`)
⚠️ **Transparent** mode is only available for background
+⚠️ **List** mode is only available for color
+
+⚠️ In **List** mode, the length of this list must be equal to the lengths of data1 and data2
+
+#### Point Color
+You can make your custom color map and use it in Samila
+
+```pycon
+>>> colorarray = [
+... [0.7, 0.2, 0.2, 1],
+... [0.6, 0.3, 0.2, 1],
+... "black",
+... [0.4, 0.4, 0.3, 1],
+... [0.3, 0.4, 0.4, 1],
+... "#ff2561"]
+>>> g.generate()
+>>> g.seed
+454893
+>>> g.plot(cmap=colorarray, color=g.data2, projection=Projection.POLAR)
+>>> plt.show()
+```
+
+
+
### Regeneration
```pycon
>>> g = GenerativeImage(f1, f2)
@@ -333,7 +364,7 @@ Samila can be used online in interactive Jupyter Notebooks via the Binder or Col
## Issues & bug reports
-Just fill an issue and describe it. We'll check it ASAP!
+Just fill an issue and describe it. We'll check it ASAP! or send an email to [info@samila.site](mailto:info@samila.site "info@samila.site").
- Please complete the issue template
diff --git a/autopep8.bat b/autopep8.bat
index 24dc840..7029efb 100644
--- a/autopep8.bat
+++ b/autopep8.bat
@@ -1,2 +1,2 @@
-python -m autopep8 samila --recursive --aggressive --aggressive --in-place --pep8-passes 2000 --verbose
+python -m autopep8 samila --recursive --aggressive --aggressive --in-place --pep8-passes 2000 --verbose --ignore=E721
python -m autopep8 setup.py --recursive --aggressive --aggressive --in-place --pep8-passes 2000 --verbose
diff --git a/autopep8.sh b/autopep8.sh
index 9b77a9c..5b2f3c6 100644
--- a/autopep8.sh
+++ b/autopep8.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-python -m autopep8 samila --recursive --aggressive --aggressive --in-place --pep8-passes 2000 --verbose
+python -m autopep8 samila --recursive --aggressive --aggressive --in-place --pep8-passes 2000 --verbose --ignore=E721
python -m autopep8 setup.py --recursive --aggressive --aggressive --in-place --pep8-passes 2000 --verbose
diff --git a/dev-requirements.txt b/dev-requirements.txt
index a4fe8ed..4f8ffee 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,5 +1,5 @@
-matplotlib==3.5.2
-art==5.6
+matplotlib==3.5.3
+art==5.7
vulture>=1.0
bandit>=1.5.1
pydocstyle>=3.0.0
diff --git a/examples/demo.ipynb b/examples/demo.ipynb
index 8e32f40..8f0c690 100644
--- a/examples/demo.ipynb
+++ b/examples/demo.ipynb
@@ -134,9 +134,7 @@
"source": [
"## Color\n",
"\n",
- "We can assign colors for both the background as well as the line\n",
- "\n",
- "Supported colors are available in `VALID_COLORS` list\n"
+ "We can assign colors for both the background as well as the line\n"
]
},
{
@@ -155,6 +153,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
+ "* Supported colors are available in `VALID_COLORS` list\n",
"* `color` and `bgcolor` parameters supported formats:\n",
"\n",
" 1. Color name (example: `color=\"yellow\"`)\n",
@@ -163,8 +162,40 @@
" 4. Random (example: `color=\"random\"`)\n",
" 5. Complement (example: `color=\"complement\", bgcolor=\"blue\"`)\n",
" 6. Transparent (example: `bgcolor=\"transparent\"`)\n",
+ " 7. List (example: `color=[\"black\", \"#fffeef\",...]`)\n",
"\n",
- "⚠️ **Transparent** mode is only available for background"
+ "⚠️ **Transparent** mode is only available for background\n",
+ "\n",
+ "⚠️ **List** mode is only available for color\n",
+ "\n",
+ "⚠️ In **List** mode, the length of this list must be equal to the lengths of data1 and data2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Point Color\n",
+ "\n",
+ "You can make your custom color map and use it in Samila"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "colorarray = [\n",
+ " [0.7, 0.2, 0.2, 1],\n",
+ " [0.6, 0.3, 0.2, 1],\n",
+ " \"black\",\n",
+ " [0.4, 0.4, 0.3, 1],\n",
+ " [0.3, 0.4, 0.4, 1],\n",
+ " \"#ff2561\"]\n",
+ "g2.generate()\n",
+ "g2.plot(cmap=colorarray, color=g2.data2, projection=Projection.POLAR)\n",
+ "plt.show()"
]
},
{
@@ -351,8 +382,31 @@
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
+ },
+ "toc": {
+ "base_numbering": 1,
+ "nav_menu": {},
+ "number_sections": false,
+ "sideBar": true,
+ "skip_h1_title": true,
+ "title_cell": "Samila Demo",
+ "title_sidebar": "Samila Demo",
+ "toc_cell": false,
+ "toc_position": {
+ "height": "382px",
+ "left": "10px",
+ "top": "10px",
+ "width": "256px"
+ },
+ "toc_section_display": false,
+ "toc_window_display": true
+ },
+ "vscode": {
+ "interpreter": {
+ "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
+ }
}
},
"nbformat": 4,
"nbformat_minor": 4
-}
\ No newline at end of file
+}
diff --git a/otherfiles/images/8.png b/otherfiles/images/8.png
new file mode 100644
index 0000000..3c74ab8
Binary files /dev/null and b/otherfiles/images/8.png differ
diff --git a/otherfiles/meta.yaml b/otherfiles/meta.yaml
new file mode 100644
index 0000000..7d9c5d1
--- /dev/null
+++ b/otherfiles/meta.yaml
@@ -0,0 +1,37 @@
+{% set name = "samila" %}
+{% set version = "0.9" %}
+
+package:
+ name: {{ name|lower }}
+ version: {{ version }}
+source:
+ git_url: https://github.com/sepandhaghighi/samila
+ git_rev: v{{ version }}
+build:
+ noarch: python
+ number: 0
+ script: {{ PYTHON }} -m pip install . -vv
+requirements:
+ host:
+ - pip
+ - setuptools
+ - python >=3.5
+ run:
+ - art >=1.8
+ - matplotlib >=3.0.0
+ - requests >=2.20.0
+ - python >=3.5
+about:
+ home: https://github.com/sepandhaghighi/samila
+ license: MIT
+ license_family: MIT
+ summary: Generative Art Generator
+ description: |
+ Samila is a generative art generator written in Python, Samila let's you create arts based on many thousand points. The position of every single point is calculated by a formula, which has random parameters. Because of the random numbers, every image looks different.
+
+ Website: https://www.samila.site
+
+ Repo: https://github.com/sepandhaghighi/samila
+extra:
+ recipe-maintainers:
+ - sepandhaghighi
diff --git a/otherfiles/samila_profile.py b/otherfiles/samila_profile.py
new file mode 100644
index 0000000..18a9deb
--- /dev/null
+++ b/otherfiles/samila_profile.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+"""Samila profile."""
+from samila import *
+import random
+import math
+
+
+def f1(x, y):
+ result = random.uniform(-1, 1) * x**2 - math.sin(y**2) + abs(y-x)
+ return result
+
+
+def f2(x, y):
+ result = random.uniform(-1, 1) * y**3 - math.cos(x**2) + 2*x
+ return result
+
+g = GenerativeImage(f1, f2)
+g.generate(seed=200)
+g.plot()
+g.save_image("test.png")
diff --git a/otherfiles/version_check.py b/otherfiles/version_check.py
index 66ca7a4..91ae0ee 100644
--- a/otherfiles/version_check.py
+++ b/otherfiles/version_check.py
@@ -4,7 +4,7 @@ import os
import sys
import codecs
Failed = 0
-SAMILA_VERSION = "0.8"
+SAMILA_VERSION = "0.9"
SETUP_ITEMS = [
@@ -19,9 +19,12 @@ CHANGELOG_ITEMS = [
"https://github.com/sepandhaghighi/samila/compare/v{0}...dev",
"[{0}]:"]
PARAMS_ITEMS = ['SAMILA_VERSION = "{0}"']
+
+META_ITEMS = ['% set version = "{0}" %']
+
FILES = {
"setup.py": SETUP_ITEMS, "README.md": README_ITEMS, "CHANGELOG.md": CHANGELOG_ITEMS, os.path.join(
- "samila", "params.py"): PARAMS_ITEMS}
+ "samila", "params.py"): PARAMS_ITEMS, os.path.join("otherfiles", "meta.yaml"): META_ITEMS}
TEST_NUMBER = len(FILES.keys())
diff --git a/samila/functions.py b/samila/functions.py
index 139e82d..dcd593e 100644
--- a/samila/functions.py
+++ b/samila/functions.py
@@ -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 DATA_TYPE_ERROR, DATA_FORMAT_ERROR, CONFIG_TYPE_ERROR, CONFIG_FORMAT_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
@@ -27,17 +30,22 @@ def random_equation_gen():
:return: equation as str
"""
- num_elements = random.randint(2, len(ELEMENTS_LIST) + 3)
+ num_elements = random.randint(1, len(ELEMENTS_LIST))
result = ""
index = 1
random_coef = random.choice(RANDOM_COEF_LIST)
while(index <= num_elements):
argument = random.choice(ARGUMENTS_LIST)
+ if random.randint(0, 1) == 1:
+ argument = random.choice(ELEMENTS_LIST).format(
+ random_coef, argument)
result = result + \
random.choice(ELEMENTS_LIST).format(random_coef, argument)
if index < num_elements:
result = result + random.choice(OPERATORS_LIST)
index = index + 1
+ if random.randint(0, 1) == 1:
+ result = random.choice(ELEMENTS_LIST).format(random_coef, result)
return result
@@ -106,7 +114,7 @@ def is_valid_color(color):
:type color: any format
:return: result as bool
"""
- if color == None:
+ if color is None:
return True
try:
_ = matplotlib.colors.to_hex(color)
@@ -154,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.
@@ -257,6 +288,7 @@ def plot_params_filter(
g,
color=None,
bgcolor=None,
+ cmap=None,
spot_size=None,
size=None,
projection=None,
@@ -271,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
@@ -287,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)
@@ -297,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:
@@ -307,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(
@@ -405,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
@@ -463,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,
@@ -506,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,
@@ -592,6 +638,7 @@ def samila_help():
:return: None
"""
print(OVERVIEW)
+ print("Website : https://www.samila.site")
print("Repo : https://github.com/sepandhaghighi/samila")
@@ -613,6 +660,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.
@@ -627,12 +712,15 @@ def load_data(g, data):
data = json.load(data)
g.data1 = data.get('data1')
g.data2 = data.get('data2')
+ if g.data1 is None or g.data2 is None:
+ raise samilaDataError(DATA_FORMAT_ERROR)
if 'matplotlib_version' in data:
g.matplotlib_version = data['matplotlib_version']
plot_config = data.get("plot")
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)
@@ -656,6 +744,8 @@ def load_config(g, config):
data = json.load(config)
g.function1_str = data.get("f1")
g.function2_str = data.get("f2")
+ if g.function1_str is None or g.function2_str is None:
+ raise samilaConfigError(CONFIG_FORMAT_ERROR)
if 'matplotlib_version' in data:
g.matplotlib_version = data['matplotlib_version']
generate_config = data.get("generate")
@@ -668,6 +758,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)
diff --git a/samila/genimage.py b/samila/genimage.py
index ab7c23e..064b7a2 100644
--- a/samila/genimage.py
+++ b/samila/genimage.py
@@ -79,8 +79,7 @@ class GenerativeImage:
self.data1 = []
self.data2 = []
range1 = list(float_range(self.start, self.stop, self.step))
- range2 = list(float_range(self.start, self.stop, self.step))
- range_prod = list(itertools.product(range1, range2))
+ range_prod = list(itertools.product(range1, range1))
calc_exception = False
for point in range_prod:
if not fill_data(self, point):
@@ -92,6 +91,7 @@ class GenerativeImage:
self,
color=None,
bgcolor=None,
+ cmap=None,
spot_size=None,
size=None,
projection=None,
@@ -104,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
@@ -120,6 +122,7 @@ class GenerativeImage:
self,
color,
bgcolor,
+ cmap,
spot_size,
size,
projection,
@@ -134,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()
diff --git a/samila/params.py b/samila/params.py
index ec07031..2fa87e7 100644
--- a/samila/params.py
+++ b/samila/params.py
@@ -3,8 +3,9 @@
import math
from enum import Enum
from matplotlib import colors as mcolors
+from matplotlib import cm
-SAMILA_VERSION = "0.8" # pragma: no cover
+SAMILA_VERSION = "0.9" # pragma: no cover
OVERVIEW = '''
Samila is a generative art generator written in Python, Samila let's you
@@ -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)
@@ -35,9 +38,12 @@ FIG_SAVE_SUCCESS_MESSAGE = "Everything seems good."
DATA_SAVE_SUCCESS_MESSAGE = "Everything seems good."
NO_FIG_ERROR_MESSAGE = "No figure was found. First run `generate` and `plot` methods."
DATA_TYPE_ERROR = "Provided data file is not supported. It should be either file or io.IOBase."
+DATA_FORMAT_ERROR = "Provided data file is not supported. It should include data1 and data2."
CONFIG_TYPE_ERROR = "Provided config file is not supported. It should be either file or io.IOBase."
+CONFIG_FORMAT_ERROR = "Provided config file is not supported. It should include f1 and f2."
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."
@@ -98,6 +104,8 @@ ARGUMENTS_LIST = [
"y**2",
"(x**2)*y",
"(y**2)*x",
+ "(y**2)+(x**2)",
+ "(y**2)-(x**2)",
"(x**2)*(y**3)",
"(x**3)*(y**2)",
"x*(y**3)",
diff --git a/setup.py b/setup.py
index 50076d4..bb60154 100644
--- a/setup.py
+++ b/setup.py
@@ -32,14 +32,14 @@ def read_description():
setup(
name='samila',
packages=['samila'],
- version='0.8',
+ version='0.9',
description='Generative ART',
long_description=read_description(),
long_description_content_type='text/markdown',
author='Samila Development Team',
- author_email='info@4r7.ir',
- url='https://github.com/sepandhaghighi/samila',
- download_url='https://github.com/sepandhaghighi/samila/tarball/v0.8',
+ author_email='info@samila.site',
+ url='https://www.samila.site',
+ download_url='https://github.com/sepandhaghighi/samila/tarball/v0.9',
keywords="generative-art art nft file nft-storage",
project_urls={
'Source': 'https://github.com/sepandhaghighi/samila',
diff --git a/test/error_test.py b/test/error_test.py
index fd8008f..5daac68 100644
--- a/test/error_test.py
+++ b/test/error_test.py
@@ -24,8 +24,9 @@ Traceback (most recent call last):
...
samila.errors.samilaPlotError: Plotting process can't be Done because data1 is empty. Use generate method first.
>>> with open("data.json", 'w') as fp:
-... json.dump({'data1': [0]}, fp)
+... json.dump({'data1': [0], 'data2': [0]}, fp)
>>> g = GenerativeImage(data=open('data.json', 'r'))
+>>> g.data2 = None
>>> g.save_data()
Traceback (most recent call last):
...
@@ -39,6 +40,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):
@@ -57,5 +62,30 @@ samila.errors.samilaPlotError: Given color/bgcolor type is not supported.
Traceback (most recent call last):
...
samila.errors.samilaPlotError: Given color/bgcolor type is not supported.
+>>> with open("data.json", 'w') as fp:
+... json.dump({'data1': [0]}, fp)
+>>> g = GenerativeImage(data=open('data.json', 'r'))
+Traceback (most recent call last):
+ ...
+samila.errors.samilaDataError: Provided data file is not supported. It should include data1 and data2.
+>>> with open("data.json", 'w') as fp:
+... json.dump({'data2': [0]}, fp)
+>>> g = GenerativeImage(data=open('data.json', 'r'))
+Traceback (most recent call last):
+ ...
+samila.errors.samilaDataError: Provided data file is not supported. It should include data1 and data2.
+>>> with open("config.json", 'w') as fp:
+... json.dump({'f1': "x"}, fp)
+>>> g = GenerativeImage(config=open('config.json', 'r'))
+Traceback (most recent call last):
+ ...
+samila.errors.samilaConfigError: Provided config file is not supported. It should include f1 and f2.
+>>> with open("config.json", 'w') as fp:
+... json.dump({'f2': "x"}, fp)
+>>> g = GenerativeImage(config=open('config.json', 'r'))
+Traceback (most recent call last):
+ ...
+samila.errors.samilaConfigError: Provided config file is not supported. It should include f1 and f2.
>>> os.remove('data.json')
+>>> os.remove('config.json')
"""
diff --git a/test/function_test.py b/test/function_test.py
index 1cfa537..52d3377 100644
--- a/test/function_test.py
+++ b/test/function_test.py
@@ -88,5 +88,6 @@ create arts based on many thousand points. The position of every single
point is calculated by a formula, which has random parameters.
Because of the random numbers, every image looks different.
+Website : https://www.samila.site
Repo : https://github.com/sepandhaghighi/samila
"""
diff --git a/test/overall_test.py b/test/overall_test.py
index e96a30e..2d13e5e 100644
--- a/test/overall_test.py
+++ b/test/overall_test.py
@@ -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
@@ -196,16 +197,6 @@ True
>>> g.spot_size == g_.spot_size
True
>>> with open("config.json", 'w') as fp:
-... json.dump({'f1': 'x'}, fp)
->>> g = GenerativeImage(config=open("config.json", 'r'))
->>> g.function1_str
-'x'
->>> with open("config.json", 'w') as fp:
-... json.dump({'f2': 'x'}, fp)
->>> g = GenerativeImage(config=open("config.json", 'r'))
->>> g.function2_str
-'x'
->>> with open("config.json", 'w') as fp:
... json.dump({'f1': 'y', 'f2': 'x'}, fp)
>>> g = GenerativeImage(config=open("config.json", 'r'))
>>> g.function1_str
@@ -222,6 +213,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(config=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(config=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(config=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("data.json")
+>>> result["status"]
+True
+>>> g_ = GenerativeImage(data=open("data.json", "r"))
+>>> g_.plot()
+>>> g_.cmap.colors == g.cmap.colors
+True
+>>> g.plot(color=g.data1)
>>> g_ = GenerativeImage()
>>> del(g)
>>> del g_.data1