samila/samila/genimage.py

214 wiersze
6.3 KiB
Python

# -*- coding: utf-8 -*-
"""Samila generative image."""
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 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 set_background
from .params import *
from warnings import warn
class GenerativeImage:
"""
Generative Image class.
>>> def f1(x, y):
... return random.uniform(-1, 1) * x**2 - math.sin(y**3)
>>> def f2(x, y):
... return random.uniform(-1, 1) * y**3 - math.cos(x**2)
>>> GI = GenerativeImage(f1, f2)
"""
def __init__(self, function1=None, function2=None, data=None, config=None):
"""
Init method.
:param function1: function 1
:type function1: python or lambda function
:param function2: function 2
:type function2: python or lambda function
:param data: prior generated data
:type data: (io.IOBase & file)
:param config: generative image config
:type config: (io.IOBase & file)
"""
_GI_initializer(self, function1, function2)
if config is not None:
load_config(self, config)
elif data is not None:
load_data(self, data)
if self.matplotlib_version != matplotlib.__version__:
warn(
MATPLOTLIB_VERSION_WARNING.format(
self.matplotlib_version),
RuntimeWarning)
if self.function1 is None:
if self.function1_str is None:
self.function1_str = random_equation_gen()
self.function1 = eval("lambda x,y:" + self.function1_str)
if self.function2 is None:
if self.function2_str is None:
self.function2_str = random_equation_gen()
self.function2 = eval("lambda x,y:" + self.function2_str)
def generate(
self,
seed=None,
start=None,
step=None,
stop=None):
"""
Generate a raw format of art.
:param seed: random seed
:type seed: int
:param start: range start point
:type start: float
:param step: range step size
:type step: float
:param stop: range stop point
:type stop: float
:return: None
"""
generate_params_filter(self, seed, start, step, stop)
self.data1 = []
self.data2 = []
range1 = list(float_range(self.start, self.stop, self.step))
range_prod = list(itertools.product(range1, range1))
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,
color=None,
bgcolor=None,
cmap=None,
spot_size=None,
size=None,
projection=None,
alpha=None,
linewidth=None):
"""
Plot the generated art.
:param color: point colors
: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
:type size: tuple
:param projection: projection type
:type projection: str
:param alpha: point transparency
:type alpha: float
:param linewidth: width of line
:type linewidth: float
:return: None
"""
plot_params_filter(
self,
color,
bgcolor,
cmap,
spot_size,
size,
projection,
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)
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):
"""
Upload image to nft.storage.
:param api_key: API key
:type api_key: str
:param depth: image depth
:type depth: float
:return: result as dict
"""
save_params_filter(self, depth)
response = save_fig_buf(self.fig, self.depth)
if not response["status"]:
return {"status": False, "message": response["message"]}
buf = response["buffer"]
response = nft_storage_upload(api_key=api_key, data=buf.getvalue())
return response
def save_image(self, file_adr, depth=None):
"""
Save generated image.
:param file_adr: file address
:type file_adr: str
:param depth: image depth
:type depth: float
:return: result as dict
"""
save_params_filter(self, depth)
return save_fig_file(self.fig, file_adr, self.depth)
def save_data(self, file_adr='data.json'):
"""
Save data into a file.
:param file_adr: file address
:type file_adr: str
:return: result as dict
"""
return save_data_file(self, file_adr)
def save_config(self, file_adr='config.json'):
"""
Save config into a file.
:param file_adr: file address
:type file_adr: str
:return: result as a dict
"""
return save_config_file(self, file_adr)
def __del__(self):
"""
Destructor.
:return:None
"""
try:
del self.data1
del self.data2
if self.fig is not None:
self.fig.clf()
plt.close(self.fig)
gc.collect()
except Exception:
gc.collect()