Merge pull request #128 from sepandhaghighi/dev

Version 0.7
pull/129/head v0.7
Sepand Haghighi 2022-05-04 16:45:55 +04:30 zatwierdzone przez GitHub
commit 8cb4f6b369
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
13 zmienionych plików z 206 dodań i 28 usunięć

Wyświetl plik

@ -5,6 +5,20 @@ 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.7] - 2022-05-04
### Added
- `fill_data` function
- `random_hex_color_gen` function
- `color`,`bgcolor` and `projection` parameters random mode
### Changed
- Calculation warning added to `generate` method
- Hex color support for `color` and `bgcolor` parameters
- Test system modified
- Random mode modified
- `filter_color` function modified
- `filter_projection` function modified
- `is_same_data` function modified
- `README.md` updated
## [0.6] - 2022-04-13
### Added
- `save_params_filter` function
@ -95,7 +109,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.6...dev
[Unreleased]: https://github.com/sepandhaghighi/samila/compare/v0.7...dev
[0.7]: https://github.com/sepandhaghighi/samila/compare/v0.6...v0.7
[0.6]: https://github.com/sepandhaghighi/samila/compare/v0.5...v0.6
[0.5]: https://github.com/sepandhaghighi/samila/compare/v0.4...v0.5
[0.4]: https://github.com/sepandhaghighi/samila/compare/v0.3...v0.4

Wyświetl plik

@ -28,6 +28,7 @@
* [Social Media](https://github.com/sepandhaghighi/samila#social-media)
* [Contribution](https://github.com/sepandhaghighi/samila/blob/master/.github/CONTRIBUTING.md)
* [References](https://github.com/sepandhaghighi/samila#references)
* [Acknowledgments](https://github.com/sepandhaghighi/samila#acknowledgments)
* [Authors](https://github.com/sepandhaghighi/samila/blob/master/AUTHORS.md)
* [License](https://github.com/sepandhaghighi/samila/blob/master/LICENSE)
* [Show Your Support](https://github.com/sepandhaghighi/samila#show-your-support)
@ -87,7 +88,7 @@ Samila is a generative art generator written in Python, Samila let's you create
### Source code
- Download [Version 0.6](https://github.com/sepandhaghighi/samila/archive/v0.6.zip) or [Latest Source ](https://github.com/sepandhaghighi/samila/archive/dev.zip)
- Download [Version 0.7](https://github.com/sepandhaghighi/samila/archive/v0.7.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)
@ -95,7 +96,7 @@ 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.6` or `pip3 install samila==0.6` (Need root access)
- Run `pip install samila==0.7` or `pip3 install samila==0.7` (Need root access)
### Easy install
@ -146,7 +147,7 @@ Samila is a generative art generator written in Python, Samila let's you create
```
<img src="https://github.com/sepandhaghighi/samila/raw/master/otherfiles/images/2.png">
* Supported projections : `RECTILINEAR`, `POLAR`, `AITOFF`, `HAMMER`, `LAMBERT` and `MOLLWEIDE`
* Supported projections : `RECTILINEAR`, `POLAR`, `AITOFF`, `HAMMER`, `LAMBERT`, `MOLLWEIDE` and `RANDOM`
* Default projection is `RECTILINEAR`
### Range
@ -172,7 +173,12 @@ Samila is a generative art generator written in Python, Samila let's you create
<img src="https://github.com/sepandhaghighi/samila/raw/master/otherfiles/images/4.png">
* Supported colors are available in `VALID_COLORS` list
* `color` and `bgcolor` parameters support color name and RGB/RGBA formats
* `color` and `bgcolor` parameters supported formats:
1. Color name (example: `yellow`)
2. RGB/RGBA (example: `(0.1,0.1,0.1)`, `(0.1,0.1,0.1,0.1)`)
3. Hex (example: `#eeefff`)
4. Random (example: `random`)
### Regeneration
```pycon
@ -362,7 +368,10 @@ You can also join our discord server
<blockquote>2- <a href="https://github.com/cutterkom/generativeart">Create Generative Art with R</a></blockquote>
<blockquote>3- <a href="https://nft.storage/">NFT.storage : Free decentralized storage and bandwidth for NFTs</a></blockquote>
## Acknowledgments
This project was funded through the **Next Step Microgrant**, a program established by [Protocol Labs](https://protocol.ai/).
## Show your support

Wyświetl plik

@ -1,5 +1,5 @@
matplotlib==3.5.1
art==5.5
art==5.6
vulture>=1.0
bandit>=1.5.1
pydocstyle>=3.0.0

Wyświetl plik

@ -88,7 +88,7 @@
"## Projection\n",
"We can use the `projection` attribute to define the coordinate system to transform our functions\n",
"\n",
"The avaliable projections are `RECTILINEAR`, `POLAR`, `AITOFF`, `HAMMER`, `LAMBERT` and `MOLLWEIDE`"
"The avaliable projections are `RECTILINEAR`, `POLAR`, `AITOFF`, `HAMMER`, `LAMBERT`, `MOLLWEIDE` and `RANDOM`"
]
},
{
@ -151,6 +151,18 @@
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* `color` and `bgcolor` parameters supported formats:\n",
"\n",
" 1. Color name (example: `yellow`)\n",
" 2. RGB/RGBA (example: `(0.1,0.1,0.1)`, `(0.1,0.1,0.1,0.1)`)\n",
" 3. Hex (example: `#eeefff`)\n",
" 4. Random (example: `random`)"
]
},
{
"cell_type": "markdown",
"metadata": {},

Wyświetl plik

@ -4,7 +4,7 @@ import os
import sys
import codecs
Failed = 0
SAMILA_VERSION = "0.6"
SAMILA_VERSION = "0.7"
SETUP_ITEMS = [

Wyświetl plik

@ -4,16 +4,17 @@
import requests
import io
import os
import re
import json
import random
import matplotlib
from .params import DEFAULT_START, DEFAULT_STOP, DEFAULT_STEP, DEFAULT_COLOR, DEFAULT_IMAGE_SIZE, DEFAULT_DEPTH
from .params import DEFAULT_BACKGROUND_COLOR, DEFAULT_SPOT_SIZE, DEFAULT_PROJECTION, DEFAULT_ALPHA, DEFAULT_LINEWIDTH
from .params import Projection, VALID_COLORS, NFT_STORAGE_API, NFT_STORAGE_LINK, OVERVIEW
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 DATA_SAVE_SUCCESS_MESSAGE, SEED_LOWER_BOUND, SEED_UPPER_BOUND
from .params import ELEMENTS_LIST, ARGUMENTS_LIST, OPERATORS_LIST
from .params import ELEMENTS_LIST, ARGUMENTS_LIST, OPERATORS_LIST, RANDOM_COEF_LIST
from .errors import samilaDataError, samilaPlotError, samilaConfigError
@ -26,7 +27,7 @@ def random_equation_gen():
num_elements = random.randint(2, len(ELEMENTS_LIST) + 3)
result = ""
index = 1
random_coef = "random.uniform(-1,1)"
random_coef = random.choice(RANDOM_COEF_LIST)
while(index <= num_elements):
argument = random.choice(ARGUMENTS_LIST)
result = result + \
@ -37,6 +38,16 @@ def random_equation_gen():
return result
def random_hex_color_gen():
"""
Generate random hex color code.
:return: color code as str
"""
random_color = "#%06x" % random.randint(0, 0xFFFFFF)
return random_color
def float_range(start, stop, step):
"""
Generate float range.
@ -95,6 +106,10 @@ def filter_color(color):
if isinstance(color, tuple):
return color
if isinstance(color, str):
if color.upper() == "RANDOM":
return random_hex_color_gen()
if re.match(HEX_COLOR_PATTERN, color):
return color
distance_list = list(map(lambda x: distance_calc(color, x),
VALID_COLORS))
min_distance = min(distance_list)
@ -111,7 +126,12 @@ def filter_projection(projection):
:return: filtered version of projection
"""
if isinstance(projection, Projection):
return projection.value
projection_value = projection.value
if projection_value == "random":
projection_list = list(Projection)
projection_list.remove(Projection.RANDOM)
projection_value = random.choice(projection_list).value
return projection_value
return None
@ -234,6 +254,27 @@ def generate_params_filter(
g.seed, g.start, g.step, g.stop = seed, start, step, stop
def fill_data(g, point):
"""
Fill data with functions in given points.
:param g: generative image instance
:type g: GenerativeImage
:param point: given point
:type point: tuple
:return: false if some exception occurred
"""
random.seed(g.seed)
try:
data1_ = g.function1(point[0], point[1]).real
data2_ = g.function2(point[0], point[1]).real
except Exception:
return False
g.data1.append(data1_)
g.data2.append(data2_)
return True
def save_params_filter(g, depth=None):
"""
Filter save_image method parameters.
@ -475,6 +516,8 @@ def is_same_data(data1, data2, precision=10**-5):
:type precision: float
:return: True if they are the same
"""
if len(data1) != len(data2):
return False
is_same = map(lambda x, y: abs(x - y) < precision, data1, data2)
return all(is_same)

Wyświetl plik

@ -7,7 +7,7 @@ import matplotlib
import matplotlib.pyplot as plt
from .functions import _GI_initializer, plot_params_filter, generate_params_filter, save_params_filter
from .functions import float_range, save_data_file, save_fig_file, save_fig_buf, save_config_file
from .functions import load_data, load_config, random_equation_gen, nft_storage_upload
from .functions import load_data, load_config, random_equation_gen, nft_storage_upload, fill_data
from .params import *
from warnings import warn
@ -80,10 +80,12 @@ class GenerativeImage:
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))
for item in range_prod:
random.seed(self.seed)
self.data1.append(self.function1(item[0], item[1]).real)
self.data2.append(self.function2(item[0], item[1]).real)
calc_exception = False
for point in range_prod:
if not fill_data(self, point):
calc_exception = True
if calc_exception:
warn(CALCULATION_EXCEPTION_WARNING, RuntimeWarning)
def plot(
self,

Wyświetl plik

@ -4,7 +4,7 @@ import math
from enum import Enum
from matplotlib import colors as mcolors
SAMILA_VERSION = "0.6" # pragma: no cover
SAMILA_VERSION = "0.7" # pragma: no cover
OVERVIEW = '''
Samila is a generative art generator written in Python, Samila let's you
@ -27,6 +27,7 @@ DEFAULT_PROJECTION = "rectilinear"
SEED_LOWER_BOUND = 0
SEED_UPPER_BOUND = 2**20
VALID_COLORS = list(dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS).keys())
HEX_COLOR_PATTERN = r'^#(?:[0-9a-fA-F]{3}){1,2}$'
NFT_STORAGE_API = "https://api.nft.storage/upload"
NFT_STORAGE_LINK = "https://ipfs.io/ipfs/{}"
NFT_STORAGE_SUCCESS_MESSAGE = "Everything seems good."
@ -39,6 +40,7 @@ CONFIG_NO_STR_FUNCTION_ERROR = "Config file can't be saved. At least one of the
PLOT_DATA_ERROR = "Plotting process can't be Done because data{0} is empty. Use generate method first."
SAVE_NO_DATA_ERROR = "Data file can't be saved. At least one of the data1 or data2 is None."
MATPLOTLIB_VERSION_WARNING = "Source matplotlib version({0}) is different from yours, plots may be different."
CALCULATION_EXCEPTION_WARNING = "The given functions are undefined at some points. Your plot may not be complete."
class Projection(Enum):
@ -55,9 +57,20 @@ class Projection(Enum):
LAMBERT = "lambert"
MOLLWEIDE = "mollweide"
RECTILINEAR = "rectilinear"
RANDOM = "random"
RANDOM_COEF_LIST = [
"random.uniform(-1,1)",
"random.gauss(0,1)",
"random.betavariate(1,1)",
"random.gammavariate(1,1)",
"random.lognormvariate(0,1)"]
ELEMENTS_LIST = [
"{0}*math.asinh({1})",
"{0}*math.acosh(abs({1})+1)",
"{0}*math.erf({1})",
"{0}*math.sqrt(abs({1}))",
"{0}*math.log(abs({1})+1)",
"{0}*math.tanh({1})",

Wyświetl plik

@ -32,14 +32,14 @@ def read_description():
setup(
name='samila',
packages=['samila'],
version='0.6',
version='0.7',
description='Generative ART',
long_description=read_description(),
long_description_content_type='text/markdown',
author='Sepand Haghighi',
author='Samila Development Team',
author_email='info@4r7.ir',
url='https://github.com/sepandhaghighi/samila',
download_url='https://github.com/sepandhaghighi/samila/tarball/v0.6',
download_url='https://github.com/sepandhaghighi/samila/tarball/v0.7',
keywords="generative-art art nft file nft-storage",
project_urls={
'Source': 'https://github.com/sepandhaghighi/samila',

Wyświetl plik

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
"""
>>> import random
>>> from samila.functions import *
>>> s = list(float_range(1,1.5,0.1))
>>> s
@ -8,16 +9,47 @@
True
>>> is_same_data([1,1.1,1.2,1.3,1.4],[1,1.11,1.3,1.4,1.5])
False
>>> is_same_data(s,[1,1.1,1.2,1.3,1.4,1.5,1.6])
False
>>> is_same_data(s,[])
False
>>> filter_color("yellow")
'yellow'
>>> filter_color((0.2,0.3,0.4))
(0.2, 0.3, 0.4)
>>> filter_color("#FFFFFF")
'#FFFFFF'
>>> random.seed(2)
>>> color1 = filter_color("random")
>>> random.seed(3)
>>> color2 = filter_color("RANDOM")
>>> color1 == color2
False
>>> random.seed(2)
>>> color1 = random_hex_color_gen()
>>> random.seed(3)
>>> color2 = random_hex_color_gen()
>>> color1 == color2
False
>>> len(color1)
7
>>> len(color2)
7
>>> filter_color(2)
>>> filter_color(4)
>>> filter_size(2)
>>> filter_size((2, 'test'))
>>> filter_size((2, 3.5))
(2, 3.5)
>>> filter_projection(2)
>>> filter_projection(Projection.POLAR)
'polar'
>>> random.seed(2)
>>> projection1 = filter_projection(Projection.RANDOM)
>>> random.seed(3)
>>> projection2 = filter_projection(Projection.RANDOM)
>>> projection1 == projection2
False
>>> distance_calc("test","test1")
1
>>> distance_calc("te1st","test")

Wyświetl plik

@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
"""
>>> import os
>>> import math
>>> import random
>>> import time
>>> from samila import GenerativeImage, Projection
>>> from samila.params import VALID_COLORS
@ -11,10 +9,7 @@
>>> g.plot()
>>> NFT_STORAGE_API_KEY = os.environ["NFT_STORAGE_API_KEY"]
>>> g.generate()
>>> random_projection = random.choice(list(Projection))
>>> random_color = random.choice(VALID_COLORS)
>>> random_bgcolor = random.choice(VALID_COLORS)
>>> g.plot(projection=random_projection,color=random_color,bgcolor=random_bgcolor)
>>> g.plot(projection=Projection.RANDOM, color="random", bgcolor="random")
>>> counter = 0
>>> try_limit = 10
>>> status = False

Wyświetl plik

@ -54,9 +54,46 @@ True
True
>>> from samila import GenerativeImage, Projection
>>> g.plot(projection=Projection.POLAR, color='red', bgcolor='black')
>>> g.color
'red'
>>> g.bgcolor
'black'
>>> g.plot(projection=Projection.POLAR, color='rod', bgcolor='blacc')
>>> g.color
'red'
>>> g.bgcolor
'black'
>>> g.plot(projection=Projection.POLAR, color="#EEE245", bgcolor="#000000")
>>> g.projection
'polar'
>>> g.color
'#EEE245'
>>> g.bgcolor
'#000000'
>>> g.plot(projection=Projection.POLAR, color=(.1, .2, .8))
>>> g.color
(0.1, 0.2, 0.8)
>>> g.plot(bgcolor=(.1, .2, .8), spot_size=0.1)
>>> g.plot(size=(20, 20))
>>> g.size
(20, 20)
>>> g.plot(alpha=0.5, linewidth=2.2)
>>> g.alpha
0.5
>>> g.linewidth
2.2
>>> random.seed(2)
>>> g.plot(color="random", bgcolor="random", projection=Projection.RANDOM)
>>> color1, bgcolor1, projection1 = g.color, g.bgcolor, g.projection
>>> random.seed(3)
>>> g.plot(color="random", bgcolor="random", projection=Projection.RANDOM)
>>> color2, bgcolor2, projection2 = g.color, g.bgcolor, g.projection
>>> color1 == color2
False
>>> bgcolor1 == bgcolor2
False
>>> projection1 == projection2
False
>>> result = g.nft_storage(api_key="")
>>> result['status']
False
@ -169,7 +206,24 @@ False
[1]
>>> g_ = GenerativeImage()
>>> del(g)
>>> del g_.data1
>>> del(g_)
>>> g1 = GenerativeImage()
>>> function1 = eval("lambda x, y:" + g1.function1_str)
>>> function2 = eval("lambda x, y:" + g1.function2_str)
>>> g2 = GenerativeImage(function1=function1, function2=function2)
>>> g1.generate(seed=22)
>>> g2.generate(seed=22)
>>> is_same_data(g1.data1, g2.data1)
True
>>> is_same_data(g1.data2, g2.data2)
True
>>> len(g1.data1) > 0
True
>>> len(g1.data2) > 0
True
>>> del(g1)
>>> del(g2)
>>> os.remove("test.png")
>>> os.remove("test2.png")
>>> os.remove("data.json")

Wyświetl plik

@ -20,6 +20,9 @@ True
... json.dump({'f1': 'x', 'f2': 'y', 'matplotlib_version': '0'}, fp)
>>> with warns(RuntimeWarning, match=r"Source matplotlib version(.*) is different from yours, plots may be different."):
... g = GenerativeImage(config=open('config.json', 'r'))
>>> g = GenerativeImage(lambda x, y: 1 / x, lambda x, y: 1 / (y - 1))
>>> with warns(RuntimeWarning, match=r"The given functions are undefined at some points. Your plot may not be complete."):
... g.generate(start=0, stop=2, step=0.1)
>>> os.remove('data.json')
>>> os.remove('config.json')
"""