kopia lustrzana https://github.com/sepandhaghighi/samila
commit
7e66936dc2
|
@ -11,8 +11,8 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
python-version: [3.5, 3.6, 3.7, 3.8, 3.9, 3.10.0]
|
||||
os: [ubuntu-20.04, windows-latest]
|
||||
python-version: [3.5, 3.6, 3.7, 3.8, 3.9, 3.10.0, 3.11.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
|
@ -40,26 +40,26 @@ jobs:
|
|||
python -m pytest test --cov=samila --cov-report=term
|
||||
env:
|
||||
NFT_STORAGE_API_KEY: ${{ secrets.NFT_STORAGE_API_KEY }}
|
||||
if: matrix.python-version == 3.7 && matrix.os == 'ubuntu-latest'
|
||||
if: matrix.python-version == 3.8 && matrix.os == 'ubuntu-20.04'
|
||||
- name: Version check
|
||||
run: |
|
||||
python otherfiles/version_check.py
|
||||
if: matrix.python-version == 3.7
|
||||
if: matrix.python-version == 3.8
|
||||
- name: Other tests
|
||||
run: |
|
||||
python -m vulture samila/ setup.py --min-confidence 65 --exclude=__init__.py --sort-by-size
|
||||
python -m bandit -r samila -s B311,B307
|
||||
python -m pydocstyle -v --match-dir=samila
|
||||
if: matrix.python-version == 3.7
|
||||
if: matrix.python-version == 3.8
|
||||
- name: Notebook check
|
||||
run: |
|
||||
pip install notebook>=5.2.2
|
||||
python otherfiles/notebook_check.py
|
||||
if: matrix.python-version == 3.7 && matrix.os == 'ubuntu-latest'
|
||||
if: matrix.python-version == 3.8 && matrix.os == 'ubuntu-20.04'
|
||||
- name: Codecov
|
||||
run: |
|
||||
codecov
|
||||
if: matrix.python-version == 3.7 && matrix.os == 'ubuntu-latest'
|
||||
if: matrix.python-version == 3.8 && matrix.os == 'ubuntu-20.04'
|
||||
- name: cProfile
|
||||
run: |
|
||||
python -m cProfile -s cumtime otherfiles/samila_profile.py
|
||||
|
|
20
CHANGELOG.md
20
CHANGELOG.md
|
@ -5,6 +5,23 @@ 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]
|
||||
## [1.0] - 2022-12-14
|
||||
### Added
|
||||
- `Marker` enum
|
||||
- `get_data` function
|
||||
- `get_config` function
|
||||
### Changed
|
||||
- `marker` parameter added to `plot` method
|
||||
- `upload_data` parameter added to `nft_storage` method
|
||||
- `upload_config` parameter added to `nft_storage` method
|
||||
- `generate` method optimized
|
||||
- Test system modified
|
||||
- `README.md` updated
|
||||
- `Python 3.11` added to `test.yml`
|
||||
- `plot` method warning bug fixed
|
||||
- Random mode modified
|
||||
### Removed
|
||||
- `fill_data` function
|
||||
## [0.9] - 2022-09-28
|
||||
### Added
|
||||
- Anaconda workflow
|
||||
|
@ -136,7 +153,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.9...dev
|
||||
[Unreleased]: https://github.com/sepandhaghighi/samila/compare/v1.0...dev
|
||||
[1.0]: https://github.com/sepandhaghighi/samila/compare/v0.9...v1.0
|
||||
[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
|
||||
|
|
46
README.md
46
README.md
|
@ -25,7 +25,6 @@
|
|||
* [Mathematical Details](https://github.com/sepandhaghighi/samila#mathematical-details)
|
||||
* [Try Samila in Your Browser](https://github.com/sepandhaghighi/samila#try-samila-in-your-browser)
|
||||
* [Issues & Bug Reports](https://github.com/sepandhaghighi/samila#issues--bug-reports)
|
||||
* [Dependencies](https://github.com/sepandhaghighi/samila#dependencies)
|
||||
* [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)
|
||||
|
@ -39,7 +38,7 @@
|
|||
## Overview
|
||||
|
||||
<p align="justify">
|
||||
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.
|
||||
Samila is a generative art generator written in Python, Samila lets you create images 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.
|
||||
</p>
|
||||
|
||||
|
||||
|
@ -89,7 +88,7 @@ Samila is a generative art generator written in Python, Samila let's you create
|
|||
|
||||
|
||||
### Source code
|
||||
- Download [Version 0.9](https://github.com/sepandhaghighi/samila/archive/v0.9.zip) or [Latest Source ](https://github.com/sepandhaghighi/samila/archive/dev.zip)
|
||||
- Download [Version 1.0](https://github.com/sepandhaghighi/samila/archive/v1.0.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)
|
||||
|
||||
|
@ -97,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.9` or `pip3 install samila==0.9` (Need root access)
|
||||
- Run `pip install samila==1.0` or `pip3 install samila==1.0` (Need root access)
|
||||
|
||||
### Easy install
|
||||
|
||||
|
@ -156,6 +155,21 @@ Samila is a generative art generator written in Python, Samila let's you create
|
|||
* Supported projections : `RECTILINEAR`, `POLAR`, `AITOFF`, `HAMMER`, `LAMBERT`, `MOLLWEIDE` and `RANDOM`
|
||||
* Default projection is `RECTILINEAR`
|
||||
|
||||
### Marker
|
||||
```pycon
|
||||
>>> from samila import Marker
|
||||
>>> g = GenerativeImage(f1, f2)
|
||||
>>> g.generate()
|
||||
>>> g.plot(marker=Marker.CIRCLE, spot_size=10)
|
||||
>>> g.seed
|
||||
448742
|
||||
>>> plt.show()
|
||||
```
|
||||
<img src="https://github.com/sepandhaghighi/samila/raw/master/otherfiles/images/9.png">
|
||||
|
||||
* Supported markers : `POINT`, `PIXEL`, `CIRCLE`, `TRIANGLE_DOWN`, `TRIANGLE_UP`, `TRIANGLE_LEFT`, `TRIANGLE_RIGHT`, `TRI_DOWN`, `TRI_UP`, `TRI_LEFT`, `TRI_RIGHT`, `OCTAGON`, `SQUARE`, `PENTAGON`, `PLUS`, `PLUS_FILLED`, `STAR`, `HEXAGON_VERTICAL`, `HEXAGON_HORIZONTAL`, `X`, `X_FILLED`, `DIAMOND`, `DIAMON_THIN`, `VLINE`, `HLINE` and `RANDOM`
|
||||
* Default marker is `POINT`
|
||||
|
||||
### Range
|
||||
```pycon
|
||||
>>> g = GenerativeImage(f1, f2)
|
||||
|
@ -232,6 +246,17 @@ Upload generated image directly to [NFT.storage](https://NFT.storage)
|
|||
{'status': True, 'message': 'FILE_LINK'}
|
||||
```
|
||||
|
||||
You can also upload your config/data to nft storage as follows:
|
||||
```pycon
|
||||
>>> g.nft_storage(api_key="API_KEY", upload_config=True)
|
||||
{'status': {'image': True, 'config':True}, 'message': {'image':'IMAGE_FILE_LINK', 'config':'CONFIG_FILE_LINK'}
|
||||
```
|
||||
or
|
||||
```pycon
|
||||
>>> g.nft_storage(api_key="API_KEY", upload_data=True)
|
||||
{'status': {'image': True, 'data':True}, 'message': {'image':'IMAGE_FILE_LINK', 'data':'DATA_FILE_LINK'}
|
||||
```
|
||||
|
||||
### Save image
|
||||
Save generated image
|
||||
|
||||
|
@ -375,19 +400,6 @@ You can also join our discord server
|
|||
</a>
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">master</td>
|
||||
<td align="center">dev</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://requires.io/github/sepandhaghighi/samila/requirements/?branch=master"><img src="https://requires.io/github/sepandhaghighi/samila/requirements.svg?branch=master" alt="Requirements Status" /></a></td>
|
||||
<td align="center"><a href="https://requires.io/github/sepandhaghighi/samila/requirements/?branch=dev"><img src="https://requires.io/github/sepandhaghighi/samila/requirements.svg?branch=dev" alt="Requirements Status" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Social media
|
||||
|
||||
1. [Instagram](https://www.instagram.com/samila_arts)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
matplotlib==3.5.3
|
||||
art==5.7
|
||||
matplotlib==3.6.2
|
||||
art==5.8
|
||||
vulture>=1.0
|
||||
bandit>=1.5.1
|
||||
pydocstyle>=3.0.0
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
"import matplotlib.pyplot as plt\n",
|
||||
"import random\n",
|
||||
"import math\n",
|
||||
"from samila import GenerativeImage, Projection"
|
||||
"from samila import GenerativeImage, Projection, Marker"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -107,6 +107,32 @@
|
|||
" plt.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Marker\n",
|
||||
"We can use the `marker` attribute to change the plotting marker.\n",
|
||||
"\n",
|
||||
"The available markers are `POINT`, `PIXEL`, `CIRCLE`, `TRIANGLE_DOWN`, `TRIANGLE_UP`, `TRIANGLE_LEFT`, `TRIANGLE_RIGHT`, `TRI_DOWN`, `TRI_UP`, `TRI_LEFT`, `TRI_RIGHT`, `OCTAGON`, `SQUARE`, `PENTAGON`, `PLUS`, `PLUS_FILLED`, `STAR`, `HEXAGON_VERTICAL`, `HEXAGON_HORIZONTAL`, `X`, `X_FILLED`, `DIAMOND`, `DIAMON_THIN`, `VLINE`, `HLINE` and `RANDOM`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"g2 = GenerativeImage(f1, f2)\n",
|
||||
"g2.generate()\n",
|
||||
"\n",
|
||||
"for m in list(Marker):\n",
|
||||
" print(m)\n",
|
||||
" g2.plot(marker=m, spot_size=100)\n",
|
||||
" plt.show()\n",
|
||||
" plt.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
|
@ -363,11 +389,36 @@
|
|||
"source": [
|
||||
"g1.nft_storage(api_key=\"YOUR_API_KEY\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can also upload your config/data to nft storage as follows:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"g1.nft_storage(api_key=\"YOUR_API_KEY\", upload_config=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"g1.nft_storage(api_key=\"YOUR_API_KEY\", upload_data=True)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"display_name": "Python 3.8.10 64-bit",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
|
@ -381,7 +432,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.5.2"
|
||||
"version": "3.8.10"
|
||||
},
|
||||
"toc": {
|
||||
"base_numbering": 1,
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 169 KiB |
|
@ -1,5 +1,5 @@
|
|||
{% set name = "samila" %}
|
||||
{% set version = "0.9" %}
|
||||
{% set version = "1.0" %}
|
||||
|
||||
package:
|
||||
name: {{ name|lower }}
|
||||
|
|
|
@ -4,7 +4,7 @@ import os
|
|||
import sys
|
||||
import codecs
|
||||
Failed = 0
|
||||
SAMILA_VERSION = "0.9"
|
||||
SAMILA_VERSION = "1.0"
|
||||
|
||||
|
||||
SETUP_ITEMS = [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Samila modules."""
|
||||
from .genimage import GenerativeImage
|
||||
from .params import Projection, VALID_COLORS, SAMILA_VERSION
|
||||
from .params import Projection, Marker, VALID_COLORS, SAMILA_VERSION
|
||||
from .errors import samilaDataError, samilaGenerateError
|
||||
__version__ = SAMILA_VERSION
|
||||
|
|
|
@ -10,16 +10,16 @@ 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_MARKER, 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 Projection, Marker, VALID_COLORS, HEX_COLOR_PATTERN, NFT_STORAGE_API, NFT_STORAGE_LINK, OVERVIEW
|
||||
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, 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
|
||||
from .params import ELEMENTS_LIST, ARGUMENTS_LIST, OPERATORS_LIST, RANDOM_COEF_LIST, RANDOM_EQUATION_GEN_COMPLEXITY
|
||||
from .errors import samilaDataError, samilaPlotError, samilaConfigError
|
||||
from warnings import warn
|
||||
|
||||
|
@ -30,7 +30,7 @@ def random_equation_gen():
|
|||
|
||||
:return: equation as str
|
||||
"""
|
||||
num_elements = random.randint(1, len(ELEMENTS_LIST))
|
||||
num_elements = random.randint(1, RANDOM_EQUATION_GEN_COMPLEXITY)
|
||||
result = ""
|
||||
index = 1
|
||||
random_coef = random.choice(RANDOM_COEF_LIST)
|
||||
|
@ -257,6 +257,24 @@ def filter_projection(projection):
|
|||
return None
|
||||
|
||||
|
||||
def filter_marker(marker):
|
||||
"""
|
||||
Filter given marker.
|
||||
|
||||
:param marker: given marker
|
||||
:type marker: Marker enum
|
||||
:return: filtered version of marker
|
||||
"""
|
||||
if isinstance(marker, Marker):
|
||||
marker_value = marker.value
|
||||
if marker_value == "random":
|
||||
marker_list = list(Marker)
|
||||
marker_list.remove(Marker.RANDOM)
|
||||
marker_value = random.choice(marker_list).value
|
||||
return marker_value
|
||||
return None
|
||||
|
||||
|
||||
def filter_float(value):
|
||||
"""
|
||||
Filter given float value.
|
||||
|
@ -292,6 +310,7 @@ def plot_params_filter(
|
|||
spot_size=None,
|
||||
size=None,
|
||||
projection=None,
|
||||
marker=None,
|
||||
alpha=None,
|
||||
linewidth=None):
|
||||
"""
|
||||
|
@ -311,6 +330,8 @@ def plot_params_filter(
|
|||
:type size: tuple
|
||||
:param projection: projection type
|
||||
:type projection: str
|
||||
:param marker: marker type
|
||||
:type marker: str
|
||||
:param alpha: point transparency
|
||||
:type alpha: float
|
||||
:param linewidth: width of line
|
||||
|
@ -329,6 +350,7 @@ def plot_params_filter(
|
|||
color, bgcolor = filter_color(color, bgcolor)
|
||||
cmap = filter_cmap(cmap)
|
||||
projection = filter_projection(projection)
|
||||
marker = filter_marker(marker)
|
||||
alpha = filter_float(alpha)
|
||||
linewidth = filter_float(linewidth)
|
||||
spot_size = filter_float(spot_size)
|
||||
|
@ -345,12 +367,14 @@ def plot_params_filter(
|
|||
size = g.size
|
||||
if projection is None:
|
||||
projection = g.projection
|
||||
if marker is None:
|
||||
marker = g.marker
|
||||
if alpha is None:
|
||||
alpha = g.alpha
|
||||
if linewidth is None:
|
||||
linewidth = g.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
|
||||
g.color, g.bgcolor, g.cmap, g.spot_size, g.size, g.projection, g.marker, g.alpha, g.linewidth = \
|
||||
color, bgcolor, cmap, spot_size, size, projection, marker, alpha, linewidth
|
||||
|
||||
|
||||
def generate_params_filter(
|
||||
|
@ -388,27 +412,6 @@ 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.
|
||||
|
@ -452,9 +455,11 @@ def _GI_initializer(g, function1, function2):
|
|||
g.spot_size = DEFAULT_SPOT_SIZE
|
||||
g.size = DEFAULT_IMAGE_SIZE
|
||||
g.projection = DEFAULT_PROJECTION
|
||||
g.marker = DEFAULT_MARKER
|
||||
g.alpha = DEFAULT_ALPHA
|
||||
g.linewidth = DEFAULT_LINEWIDTH
|
||||
g.depth = DEFAULT_DEPTH
|
||||
g.missed_points_number = 0
|
||||
|
||||
|
||||
def nft_storage_upload(api_key, data):
|
||||
|
@ -498,6 +503,26 @@ def save_data_file(g, file_adr):
|
|||
:type file_adr: str
|
||||
:return: result as dict
|
||||
"""
|
||||
data = get_data(g)
|
||||
result = {"status": True, "message": DATA_SAVE_SUCCESS_MESSAGE}
|
||||
try:
|
||||
with open(file_adr, 'w') as fp:
|
||||
json.dump(data, fp)
|
||||
result["message"] = os.path.abspath(file_adr)
|
||||
except Exception as e:
|
||||
result["status"] = False
|
||||
result["message"] = str(e)
|
||||
return result
|
||||
|
||||
|
||||
def get_data(g):
|
||||
"""
|
||||
Return data.
|
||||
|
||||
:param g: generative image instance
|
||||
:type g: GenerativeImage
|
||||
:return: data as a dict
|
||||
"""
|
||||
matplotlib_version = matplotlib.__version__
|
||||
data = {}
|
||||
if g.data1 is None or g.data2 is None:
|
||||
|
@ -510,20 +535,48 @@ def save_data_file(g, file_adr):
|
|||
"cmap": _serialize_cmap(g.cmap),
|
||||
"spot_size": g.spot_size,
|
||||
"projection": g.projection,
|
||||
"marker": g.marker,
|
||||
"alpha": g.alpha,
|
||||
"linewidth": g.linewidth,
|
||||
"depth": g.depth
|
||||
}
|
||||
data['matplotlib_version'] = matplotlib_version
|
||||
result = {"status": True, "message": DATA_SAVE_SUCCESS_MESSAGE}
|
||||
try:
|
||||
with open(file_adr, 'w') as fp:
|
||||
json.dump(data, fp)
|
||||
result["message"] = os.path.abspath(file_adr)
|
||||
except Exception as e:
|
||||
result["status"] = False
|
||||
result["message"] = str(e)
|
||||
return result
|
||||
return data
|
||||
|
||||
|
||||
def get_config(g):
|
||||
"""
|
||||
Return config.
|
||||
|
||||
:param g: generative image instance
|
||||
:type g: GenerativeImage
|
||||
:return: config as a dict
|
||||
"""
|
||||
matplotlib_version = matplotlib.__version__
|
||||
config = {}
|
||||
if g.function1_str is None or g.function2_str is None:
|
||||
raise samilaConfigError(CONFIG_NO_STR_FUNCTION_ERROR)
|
||||
config['f1'] = g.function1_str
|
||||
config['f2'] = g.function2_str
|
||||
config['generate'] = {
|
||||
"seed": g.seed,
|
||||
"start": g.start,
|
||||
"step": g.step,
|
||||
"stop": g.stop
|
||||
}
|
||||
config['plot'] = {
|
||||
"color": g.color,
|
||||
"bgcolor": g.bgcolor,
|
||||
"cmap": _serialize_cmap(g.cmap),
|
||||
"spot_size": g.spot_size,
|
||||
"projection": g.projection,
|
||||
"marker": g.marker,
|
||||
"alpha": g.alpha,
|
||||
"linewidth": g.linewidth,
|
||||
"depth": g.depth
|
||||
}
|
||||
config['matplotlib_version'] = matplotlib_version
|
||||
return config
|
||||
|
||||
|
||||
def save_config_file(g, file_adr):
|
||||
|
@ -536,33 +589,11 @@ def save_config_file(g, file_adr):
|
|||
:type file_adr: str
|
||||
:return: result as dict
|
||||
"""
|
||||
matplotlib_version = matplotlib.__version__
|
||||
data = {}
|
||||
if g.function1_str is None or g.function2_str is None:
|
||||
raise samilaConfigError(CONFIG_NO_STR_FUNCTION_ERROR)
|
||||
data['f1'] = g.function1_str
|
||||
data['f2'] = g.function2_str
|
||||
data['generate'] = {
|
||||
"seed": g.seed,
|
||||
"start": g.start,
|
||||
"step": g.step,
|
||||
"stop": g.stop
|
||||
}
|
||||
data['plot'] = {
|
||||
"color": g.color,
|
||||
"bgcolor": g.bgcolor,
|
||||
"cmap": _serialize_cmap(g.cmap),
|
||||
"spot_size": g.spot_size,
|
||||
"projection": g.projection,
|
||||
"alpha": g.alpha,
|
||||
"linewidth": g.linewidth,
|
||||
"depth": g.depth
|
||||
}
|
||||
data['matplotlib_version'] = matplotlib_version
|
||||
config = get_config(g)
|
||||
result = {"status": True, "message": DATA_SAVE_SUCCESS_MESSAGE}
|
||||
try:
|
||||
with open(file_adr, 'w') as fp:
|
||||
json.dump(data, fp, indent=4)
|
||||
json.dump(config, fp, indent=4)
|
||||
result["message"] = os.path.abspath(file_adr)
|
||||
except Exception as e:
|
||||
result["status"] = False
|
||||
|
@ -723,6 +754,7 @@ def load_data(g, data):
|
|||
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.marker = plot_config.get("marker", DEFAULT_MARKER)
|
||||
g.alpha = plot_config.get("alpha", DEFAULT_ALPHA)
|
||||
g.linewidth = plot_config.get("linewidth", DEFAULT_LINEWIDTH)
|
||||
g.depth = plot_config.get("depth", DEFAULT_DEPTH)
|
||||
|
@ -761,6 +793,7 @@ def load_config(g, config):
|
|||
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.marker = plot_config.get("marker", DEFAULT_MARKER)
|
||||
g.alpha = plot_config.get("alpha", DEFAULT_ALPHA)
|
||||
g.linewidth = plot_config.get("linewidth", DEFAULT_LINEWIDTH)
|
||||
g.depth = plot_config.get("depth", DEFAULT_DEPTH)
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Samila generative image."""
|
||||
import json
|
||||
import random
|
||||
import gc
|
||||
import itertools
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
from .functions import _GI_initializer, plot_params_filter, generate_params_filter, save_params_filter
|
||||
from .functions import get_config, get_data
|
||||
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, fill_data
|
||||
from .functions import load_data, load_config, random_equation_gen, nft_storage_upload
|
||||
from .functions import set_background
|
||||
from .params import *
|
||||
from warnings import warn
|
||||
from warnings import warn, catch_warnings, simplefilter
|
||||
|
||||
|
||||
class GenerativeImage:
|
||||
|
@ -78,13 +80,19 @@ class GenerativeImage:
|
|||
generate_params_filter(self, seed, start, step, stop)
|
||||
self.data1 = []
|
||||
self.data2 = []
|
||||
self.missed_points_number = 0
|
||||
range1 = list(float_range(self.start, self.stop, self.step))
|
||||
range_prod = list(itertools.product(range1, range1))
|
||||
calc_exception = False
|
||||
range_prod = itertools.product(range1, range1)
|
||||
for point in range_prod:
|
||||
if not fill_data(self, point):
|
||||
calc_exception = True
|
||||
if calc_exception:
|
||||
random.seed(self.seed)
|
||||
try:
|
||||
data1_ = self.function1(point[0], point[1]).real
|
||||
data2_ = self.function2(point[0], point[1]).real
|
||||
self.data1.append(data1_)
|
||||
self.data2.append(data2_)
|
||||
except Exception:
|
||||
self.missed_points_number += 1
|
||||
if len(self.data1) < (len(range1) ** 2):
|
||||
warn(CALCULATION_EXCEPTION_WARNING, RuntimeWarning)
|
||||
|
||||
def plot(
|
||||
|
@ -95,6 +103,7 @@ class GenerativeImage:
|
|||
spot_size=None,
|
||||
size=None,
|
||||
projection=None,
|
||||
marker=None,
|
||||
alpha=None,
|
||||
linewidth=None):
|
||||
"""
|
||||
|
@ -112,6 +121,8 @@ class GenerativeImage:
|
|||
:type size: tuple
|
||||
:param projection: projection type
|
||||
:type projection: str
|
||||
:param marker: marker type
|
||||
:type marker: str
|
||||
:param alpha: point transparency
|
||||
:type alpha: float
|
||||
:param linewidth: width of line
|
||||
|
@ -126,31 +137,44 @@ class GenerativeImage:
|
|||
spot_size,
|
||||
size,
|
||||
projection,
|
||||
marker,
|
||||
alpha,
|
||||
linewidth)
|
||||
fig = plt.figure()
|
||||
fig.set_size_inches(self.size[0], self.size[1])
|
||||
ax = fig.add_subplot(111, projection=self.projection)
|
||||
set_background(self.bgcolor, fig, ax)
|
||||
ax.scatter(
|
||||
self.data2,
|
||||
self.data1,
|
||||
alpha=self.alpha,
|
||||
c=self.color,
|
||||
cmap=self.cmap,
|
||||
s=self.spot_size,
|
||||
lw=self.linewidth)
|
||||
with catch_warnings():
|
||||
simplefilter("ignore")
|
||||
ax.scatter(
|
||||
self.data2,
|
||||
self.data1,
|
||||
alpha=self.alpha,
|
||||
c=self.color,
|
||||
cmap=self.cmap,
|
||||
s=self.spot_size,
|
||||
lw=self.linewidth,
|
||||
marker=self.marker)
|
||||
ax.set_axis_off()
|
||||
ax.patch.set_zorder(-1)
|
||||
ax.add_artist(ax.patch)
|
||||
self.fig = fig
|
||||
|
||||
def nft_storage(self, api_key, depth=None):
|
||||
def nft_storage(
|
||||
self,
|
||||
api_key,
|
||||
upload_data=False,
|
||||
upload_config=False,
|
||||
depth=None):
|
||||
"""
|
||||
Upload image to nft.storage.
|
||||
|
||||
:param api_key: API key
|
||||
:type api_key: str
|
||||
:param upload_data: upload data flag
|
||||
:type upload_data: bool
|
||||
:param upload_config: upload config flag
|
||||
:type upload_config: bool
|
||||
:param depth: image depth
|
||||
:type depth: float
|
||||
:return: result as dict
|
||||
|
@ -161,7 +185,22 @@ class GenerativeImage:
|
|||
return {"status": False, "message": response["message"]}
|
||||
buf = response["buffer"]
|
||||
response = nft_storage_upload(api_key=api_key, data=buf.getvalue())
|
||||
return response
|
||||
if upload_config == False and upload_data == False:
|
||||
return response
|
||||
result = {key: {'image': value} for key, value in response.items()}
|
||||
if upload_config:
|
||||
response = nft_storage_upload(
|
||||
api_key=api_key,
|
||||
data=json.dumps(get_config(self)))
|
||||
for key, value in response.items():
|
||||
result[key]['config'] = value
|
||||
if upload_data:
|
||||
response = nft_storage_upload(
|
||||
api_key=api_key,
|
||||
data=json.dumps(get_data(self)))
|
||||
for key, value in response.items():
|
||||
result[key]['data'] = value
|
||||
return result
|
||||
|
||||
def save_image(self, file_adr, depth=None):
|
||||
"""
|
||||
|
|
|
@ -5,7 +5,7 @@ from enum import Enum
|
|||
from matplotlib import colors as mcolors
|
||||
from matplotlib import cm
|
||||
|
||||
SAMILA_VERSION = "0.9" # pragma: no cover
|
||||
SAMILA_VERSION = "1.0" # pragma: no cover
|
||||
|
||||
OVERVIEW = '''
|
||||
Samila is a generative art generator written in Python, Samila let's you
|
||||
|
@ -27,6 +27,7 @@ DEFAULT_IMAGE_SIZE = (10, 10)
|
|||
DEFAULT_SPOT_SIZE = 0.01
|
||||
DEFAULT_DEPTH = 1
|
||||
DEFAULT_PROJECTION = "rectilinear"
|
||||
DEFAULT_MARKER = "."
|
||||
SEED_LOWER_BOUND = 0
|
||||
SEED_UPPER_BOUND = 2**20
|
||||
VALID_COLORS = list(dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS).keys())
|
||||
|
@ -69,6 +70,42 @@ class Projection(Enum):
|
|||
RANDOM = "random"
|
||||
|
||||
|
||||
class Marker(Enum):
|
||||
"""
|
||||
Samila Marker type class.
|
||||
|
||||
>>> marker = samila.Marker.POINT
|
||||
"""
|
||||
|
||||
DEFAULT = DEFAULT_MARKER
|
||||
POINT = "."
|
||||
PIXEL = ","
|
||||
CIRCLE = "o"
|
||||
TRIANGLE_DOWN = "v"
|
||||
TRIANGLE_UP = "^"
|
||||
TRIANGLE_LEFT = "<"
|
||||
TRIANGLE_RIGHT = ">"
|
||||
TRI_DOWN = "1"
|
||||
TRI_UP = "2"
|
||||
TRI_LEFT = "3"
|
||||
TRI_RIGHT = "4"
|
||||
OCTAGON = "8"
|
||||
SQUARE = "s"
|
||||
PENTAGON = "p"
|
||||
PLUS = "+"
|
||||
PLUS_FILLED = "P"
|
||||
STAR = "*"
|
||||
HEXAGON_VERTICAL = "h"
|
||||
HEXAGON_HORIZONTAL = "H"
|
||||
X = "x"
|
||||
X_FILLED = "X"
|
||||
DIAMOND = "D"
|
||||
DIAMON_THIN = "d"
|
||||
VLINE = "|"
|
||||
HLINE = "_"
|
||||
RANDOM = "random"
|
||||
|
||||
|
||||
RANDOM_COEF_LIST = [
|
||||
"random.uniform(-1,1)",
|
||||
"random.gauss(0,1)",
|
||||
|
@ -86,6 +123,7 @@ ELEMENTS_LIST = [
|
|||
"{0}*math.tanh({1})",
|
||||
"{0}*math.cos({1})",
|
||||
"{0}*math.sin({1})",
|
||||
"{0}*math.tan({1})",
|
||||
"{0}*{1}",
|
||||
"{0}*abs({1})",
|
||||
"{0}*math.ceil({1})",
|
||||
|
@ -112,3 +150,5 @@ ARGUMENTS_LIST = [
|
|||
"y*(x**3)"]
|
||||
|
||||
OPERATORS_LIST = ["+", "-", "*", "/"]
|
||||
|
||||
RANDOM_EQUATION_GEN_COMPLEXITY = len(ELEMENTS_LIST) + 1
|
||||
|
|
10
setup.py
10
setup.py
|
@ -6,7 +6,8 @@ except ImportError:
|
|||
from distutils.core import setup
|
||||
|
||||
|
||||
MINIMAL_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.'''
|
||||
MINIMAL_DESCRIPTION = '''Samila is a generative art generator written in Python, Samila lets you create images 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.'''
|
||||
|
||||
|
||||
def get_requires():
|
||||
|
@ -32,14 +33,14 @@ def read_description():
|
|||
setup(
|
||||
name='samila',
|
||||
packages=['samila'],
|
||||
version='0.9',
|
||||
version='1.0',
|
||||
description='Generative ART',
|
||||
long_description=read_description(),
|
||||
long_description_content_type='text/markdown',
|
||||
author='Samila Development Team',
|
||||
author_email='info@samila.site',
|
||||
url='https://www.samila.site',
|
||||
download_url='https://github.com/sepandhaghighi/samila/tarball/v0.9',
|
||||
download_url='https://github.com/sepandhaghighi/samila/tarball/v1.0',
|
||||
keywords="generative-art art nft file nft-storage",
|
||||
project_urls={
|
||||
'Source': 'https://github.com/sepandhaghighi/samila',
|
||||
|
@ -49,7 +50,7 @@ setup(
|
|||
install_requires=get_requires(),
|
||||
python_requires='>=3.5',
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Natural Language :: English',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
|
@ -67,6 +68,7 @@ setup(
|
|||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Programming Language :: Python :: 3.11',
|
||||
],
|
||||
license='MIT',
|
||||
include_package_data=True
|
||||
|
|
|
@ -75,6 +75,15 @@ False
|
|||
>>> projection2 = filter_projection(Projection.RANDOM)
|
||||
>>> projection1 == projection2
|
||||
False
|
||||
>>> filter_marker(3)
|
||||
>>> filter_marker(Marker.POINT)
|
||||
'.'
|
||||
>>> random.seed(2)
|
||||
>>> marker1 = filter_marker(Marker.RANDOM)
|
||||
>>> random.seed(3)
|
||||
>>> marker2 = filter_marker(Marker.RANDOM)
|
||||
>>> marker1 == marker2
|
||||
False
|
||||
>>> distance_calc("test","test1")
|
||||
1
|
||||
>>> distance_calc("te1st","test")
|
||||
|
|
|
@ -20,4 +20,26 @@
|
|||
... time.sleep(10)
|
||||
>>> status
|
||||
True
|
||||
>>> status = False
|
||||
>>> counter = 0
|
||||
>>> while(status == False and counter<try_limit):
|
||||
... result = g.nft_storage(api_key=NFT_STORAGE_API_KEY, upload_config=True)
|
||||
... counter = counter + 1
|
||||
... status = all(result["status"].values())
|
||||
... time.sleep(10)
|
||||
>>> result['status']["image"]
|
||||
True
|
||||
>>> result['status']["config"]
|
||||
True
|
||||
>>> status = False
|
||||
>>> counter = 0
|
||||
>>> while(status == False and counter<try_limit):
|
||||
... result = g.nft_storage(api_key=NFT_STORAGE_API_KEY, upload_data=True)
|
||||
... counter = counter + 1
|
||||
... status = all(result["status"].values())
|
||||
... time.sleep(10)
|
||||
>>> result['status']["image"]
|
||||
True
|
||||
>>> result['status']["data"]
|
||||
True
|
||||
"""
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
>>> from matplotlib.colors import Colormap, ListedColormap
|
||||
>>> def guard(*args, **kwargs):
|
||||
... raise Exception("No internet connection!")
|
||||
>>> from samila import GenerativeImage, Projection
|
||||
>>> from samila import GenerativeImage, Projection, Marker
|
||||
>>> from samila.functions import is_same_data
|
||||
>>> import pickle
|
||||
>>> def f1(x,y):
|
||||
|
@ -29,6 +29,8 @@ True
|
|||
True
|
||||
>>> isinstance(g.data2, list)
|
||||
True
|
||||
>>> g.missed_points_number == 0
|
||||
True
|
||||
>>> g.generate(seed=10, start=-2*math.pi, step=0.1, stop=math.pi/2)
|
||||
>>> g.seed
|
||||
10
|
||||
|
@ -53,7 +55,6 @@ True
|
|||
True
|
||||
>>> isinstance(result["message"], str)
|
||||
True
|
||||
>>> from samila import GenerativeImage, Projection
|
||||
>>> g.plot(projection=Projection.POLAR, color='red', bgcolor='black')
|
||||
>>> g.color
|
||||
'red'
|
||||
|
@ -84,11 +85,15 @@ True
|
|||
'#555555'
|
||||
>>> g.bgcolor
|
||||
'#aaaaaa'
|
||||
>>> g.plot(projection=Projection.POLAR, color="complement", bgcolor="complement")
|
||||
>>> g.plot(projection=Projection.POLAR, color="complement", bgcolor="complement", marker=Marker.X, spot_size=100)
|
||||
>>> g.color
|
||||
'#555555'
|
||||
>>> g.bgcolor
|
||||
'#aaaaaa'
|
||||
>>> g.marker
|
||||
'x'
|
||||
>>> g.spot_size
|
||||
100
|
||||
>>> g.plot(bgcolor=(.1, .2, .8), spot_size=0.1)
|
||||
>>> g.plot(size=(20, 20))
|
||||
>>> g.size
|
||||
|
@ -99,17 +104,19 @@ True
|
|||
>>> 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
|
||||
>>> g.plot(color="random", bgcolor="random", projection=Projection.RANDOM, marker=Marker.RANDOM)
|
||||
>>> color1, bgcolor1, projection1, marker1 = g.color, g.bgcolor, g.projection, g.marker
|
||||
>>> random.seed(3)
|
||||
>>> g.plot(color="random", bgcolor="random", projection=Projection.RANDOM)
|
||||
>>> color2, bgcolor2, projection2 = g.color, g.bgcolor, g.projection
|
||||
>>> g.plot(color="random", bgcolor="random", projection=Projection.RANDOM, marker=Marker.RANDOM)
|
||||
>>> color2, bgcolor2, projection2, marker2 = g.color, g.bgcolor, g.projection, g.marker
|
||||
>>> color1 == color2
|
||||
False
|
||||
>>> bgcolor1 == bgcolor2
|
||||
False
|
||||
>>> projection1 == projection2
|
||||
False
|
||||
>>> marker1 == marker2
|
||||
False
|
||||
>>> result = g.nft_storage(api_key="")
|
||||
>>> result['status']
|
||||
False
|
||||
|
@ -165,7 +172,7 @@ True
|
|||
>>> g.plot(color="white", bgcolor="transparent")
|
||||
>>> g.bgcolor == "TRANSPARENT"
|
||||
True
|
||||
>>> g.plot(color="white", bgcolor="black", spot_size=0.1)
|
||||
>>> g.plot()
|
||||
>>> result = g.save_config()
|
||||
>>> result["status"]
|
||||
True
|
||||
|
@ -189,6 +196,16 @@ True
|
|||
True
|
||||
>>> g.spot_size == g_.spot_size
|
||||
True
|
||||
>>> g.projection == g_.projection
|
||||
True
|
||||
>>> g.marker == g_.marker
|
||||
True
|
||||
>>> g.alpha == g_.alpha
|
||||
True
|
||||
>>> g.linewidth == g_.linewidth
|
||||
True
|
||||
>>> g.depth == g_.depth
|
||||
True
|
||||
>>> g_ = GenerativeImage(data=open("data.json", 'r'))
|
||||
>>> g.color == g_.color
|
||||
True
|
||||
|
@ -196,6 +213,67 @@ True
|
|||
True
|
||||
>>> g.spot_size == g_.spot_size
|
||||
True
|
||||
>>> g.projection == g_.projection
|
||||
True
|
||||
>>> g.marker == g_.marker
|
||||
True
|
||||
>>> g.alpha == g_.alpha
|
||||
True
|
||||
>>> g.linewidth == g_.linewidth
|
||||
True
|
||||
>>> g.depth == g_.depth
|
||||
True
|
||||
>>> g.plot(color="white", bgcolor="black", spot_size=2, projection=Projection.POLAR, marker=Marker.X, alpha=0.2, linewidth=1)
|
||||
>>> result = g.save_config()
|
||||
>>> result["status"]
|
||||
True
|
||||
>>> isinstance(result["message"], str)
|
||||
True
|
||||
>>> result = g.save_data()
|
||||
>>> result["status"]
|
||||
True
|
||||
>>> isinstance(result["message"], str)
|
||||
True
|
||||
>>> g_ = GenerativeImage(config=open("config.json", 'r'))
|
||||
>>> g_.seed == g.seed
|
||||
True
|
||||
>>> g_.function1_str == g.function1_str
|
||||
True
|
||||
>>> g_.function2_str == g.function2_str
|
||||
True
|
||||
>>> g.color == g_.color
|
||||
True
|
||||
>>> g.bgcolor == g_.bgcolor
|
||||
True
|
||||
>>> g.spot_size == g_.spot_size
|
||||
True
|
||||
>>> g.projection == g_.projection
|
||||
True
|
||||
>>> g.marker == g_.marker
|
||||
True
|
||||
>>> g.alpha == g_.alpha
|
||||
True
|
||||
>>> g.linewidth == g_.linewidth
|
||||
True
|
||||
>>> g.depth == g_.depth
|
||||
True
|
||||
>>> g_ = GenerativeImage(data=open("data.json", 'r'))
|
||||
>>> g.color == g_.color
|
||||
True
|
||||
>>> g.bgcolor == g_.bgcolor
|
||||
True
|
||||
>>> g.spot_size == g_.spot_size
|
||||
True
|
||||
>>> g.projection == g_.projection
|
||||
True
|
||||
>>> g.marker == g_.marker
|
||||
True
|
||||
>>> g.alpha == g_.alpha
|
||||
True
|
||||
>>> g.linewidth == g_.linewidth
|
||||
True
|
||||
>>> g.depth == g_.depth
|
||||
True
|
||||
>>> with open("config.json", 'w') as fp:
|
||||
... json.dump({'f1': 'y', 'f2': 'x'}, fp)
|
||||
>>> g = GenerativeImage(config=open("config.json", 'r'))
|
||||
|
|
|
@ -23,6 +23,8 @@ True
|
|||
>>> 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)
|
||||
>>> g.missed_points_number > 0
|
||||
True
|
||||
>>> with warns(RuntimeWarning, match=r"It is not possible to set color and bgcolor to 'complement' at the same time! Both are automatically set to the previous or default selection."):
|
||||
... g.plot(color='complement', bgcolor='complement')
|
||||
>>> with warns(RuntimeWarning, match=r"color 'rad' not found. Replacing it with 'red'"):
|
||||
|
|
Ładowanie…
Reference in New Issue