Skip to content

Commit

Permalink
Merge pull request #63 from sepandhaghighi/data
Browse files Browse the repository at this point in the history
Data Save and Load Structure
  • Loading branch information
sepandhaghighi committed Oct 28, 2021
2 parents 9a83d1f + 5bed09b commit 53bd7be
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,7 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]
### Added
- `load_data` function
- `save_data_file` function
- `save_data` method
### Changed
- `data` parameter added to GenerativeImage `__init__`
- `depth` parameter added to `save_image` method
- `depth` parameter added to `save_fig_file` function
- `save_image` and `nft_storage` methods background bug fixed
Expand Down
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -188,6 +188,18 @@ Save generated image in higher resolutions
{'status': True, 'message': 'Everything seems good'}
```

### Save data
Save generated data into a file

```pycon
>>> g.save_data(file_adr="test.json")
```
So you can load it into a `GenerativeImage` instance later by

```pycon
>>> g = GenerativeImage(data=open('test.json', 'r'))
```

## Mathematical details
Samila is simply a transformation between a square-shaped space from the Cartesian coordinate system to any arbitrary coordination like [Polar coordinate system](https://en.wikipedia.org/wiki/Polar_coordinate_system).

Expand Down
1 change: 1 addition & 0 deletions samila/__init__.py
Expand Up @@ -2,4 +2,5 @@
"""Samila modules."""
from .genimage import GenerativeImage
from .params import Projection, VALID_COLORS, SAMILA_VERSION
from .errors import samilaDataError, samilaGenerateError
__version__ = SAMILA_VERSION
12 changes: 12 additions & 0 deletions samila/errors.py
@@ -1,2 +1,14 @@
# -*- coding: utf-8 -*-
"""Samila errors."""


class samilaDataError(Exception):
"""Data error class."""

pass


class samilaGenerateError(Exception):
"""Generate error class."""

pass
46 changes: 45 additions & 1 deletion samila/functions.py
Expand Up @@ -3,7 +3,9 @@

import requests
import io
from .params import Projection, DEFAULT_PROJECTION, VALID_COLORS, NFT_STORAGE_API, NFT_STORAGE_SUCCESS_MESSAGE, FIG_SAVE_SUCCESS_MESSAGE, NO_FIG_ERROR_MESSAGE, OVERVIEW
import json
from .params import Projection, DEFAULT_PROJECTION, VALID_COLORS, NFT_STORAGE_API, NFT_STORAGE_SUCCESS_MESSAGE, FIG_SAVE_SUCCESS_MESSAGE, NO_FIG_ERROR_MESSAGE, DATA_PARSING_ERROR, DATA_TYPE_ERROR, OVERVIEW, DATA_SAVE_SUCCESS_MESSAGE
from .errors import samilaDataError


def float_range(start, stop, step):
Expand Down Expand Up @@ -113,6 +115,31 @@ def nft_storage_upload(api_key, data):
return result


def save_data_file(data1, data2, file_adr):
"""
Save config as file.
:param data1: data 1
:type data1: list
:param data2: data 2
:type data2: list
:param file_adr: file address
:type file_adr: str
:return: result as dict
"""
data = {}
data['data1'] = data1
data['data2'] = data2
result = {"status": True, "message": DATA_SAVE_SUCCESS_MESSAGE}
try:
with open(file_adr, 'w') as fp:
json.dump(data, fp)
except Exception as e:
result["status"] = False
result["message"] = str(e)
return result


def save_fig_file(figure, file_adr, depth):
"""
Save figure as file.
Expand Down Expand Up @@ -194,3 +221,20 @@ def is_same_data(data1, data2, precision=10**-5):
"""
is_same = map(lambda x, y: abs(x - y) < precision, data1, data2)
return all(is_same)


def load_data(data):
"""
Load data file.
:param data: prior generated data
:type data: (io.IOBase & file)
:return: (data1, data2)
"""
if isinstance(data, io.IOBase):
try:
data = json.load(data)
return data['data1'], data['data2']
except:
raise samilaDataError(DATA_PARSING_ERROR)
raise samilaDataError(DATA_TYPE_ERROR)
27 changes: 25 additions & 2 deletions samila/genimage.py
Expand Up @@ -3,8 +3,10 @@
import random
import itertools
import matplotlib.pyplot as plt
from .functions import float_range, filter_color, filter_projection, nft_storage_upload, save_fig_file, save_fig_buf
from .functions import float_range, filter_color, filter_projection, nft_storage_upload, save_data_file, save_fig_file, save_fig_buf, load_data
from .errors import samilaGenerateError
from .params import *
from warnings import warn


class GenerativeImage:
Expand All @@ -18,15 +20,24 @@ class GenerativeImage:
>>> GI = GenerativeImage(f1, f2)
"""

def __init__(self, function1, function2):
def __init__(self, function1=None, function2=None, data=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)
"""
if function1 is None or function2 is None:
if data is None:
warn(NOTHING_PROVIDED_WARNING, RuntimeWarning)
else:
warn(JUST_DATA_WARNING, RuntimeWarning)
if data is not None:
self.data1, self.data2 = load_data(data)
self.function1 = function1
self.function2 = function2
self.fig = None
Expand All @@ -50,6 +61,8 @@ def generate(
:type stop: float
:return: None
"""
if self.function1 is None or self.function2 is None:
raise samilaGenerateError(NO_FUNCTION_ERROR)
self.data1 = []
self.data2 = []
self.seed = seed
Expand Down Expand Up @@ -133,3 +146,13 @@ def save_image(self, file_adr, depth=1):
:return: result as dict
"""
return save_fig_file(figure=self.fig, file_adr=file_adr, depth=depth)

def save_data(self, file_adr='data.json'):
"""
Save data into a file.
:param file_adr: file addresses
:type file_adr: str
:return: result as dict
"""
return save_data_file(self.data1, self.data2, file_adr)
7 changes: 7 additions & 0 deletions samila/params.py
Expand Up @@ -26,7 +26,14 @@
NFT_STORAGE_API = "https://api.nft.storage/upload"
NFT_STORAGE_SUCCESS_MESSAGE = "Everything seems good."
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_PARSING_ERROR = "Provided data format is wrong. It should be in JSON format including data1 and data2 fields."
NO_FUNCTION_ERROR = "At least one of the given functions are None."
JUST_DATA_WARNING = "Just data is provided, generate method is not available in this mode."
NOTHING_PROVIDED_WARNING = "Neither function nor data is provided."



class Projection(Enum):
Expand Down
26 changes: 26 additions & 0 deletions test/error_test.py
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
"""
>>> from samila import *
>>> import os
>>> from pytest import warns
>>> g = GenerativeImage(data="data.json")
Traceback (most recent call last):
...
samila.errors.samilaDataError: Provided data file is not supported. It should be either file or io.IOBase.
>>> with open('data.json', 'w') as fp:
... result = fp.write('test')
>>> g = GenerativeImage(data=open("data.json", 'r'))
Traceback (most recent call last):
...
samila.errors.samilaDataError: Provided data format is wrong. It should be in JSON format including data1 and data2 fields.
>>> g = GenerativeImage(lambda x,y: 0, lambda x,y: 0)
>>> g.generate(step=0.1)
>>> result = g.save_data('data.json')
>>> with warns(RuntimeWarning, match="Just data is provided, generate method is not available in this mode."):
... g = GenerativeImage(data=open('data.json', 'r'))
>>> g.generate()
Traceback (most recent call last):
...
samila.errors.samilaGenerateError: At least one of the given functions are None.
>>> os.remove('data.json')
"""
3 changes: 3 additions & 0 deletions test/overall_test.py
Expand Up @@ -87,6 +87,9 @@
False
>>> result["message"]
'No internet connection!'
>>> result = g.save_data(file_adr="")
>>> result["status"]
False
>>> os.remove("test.png")
>>> os.remove("test2.png")
"""
18 changes: 18 additions & 0 deletions test/warning_test.py
@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
"""
>>> import os
>>> from samila import *
>>> from pytest import warns
>>> with warns(RuntimeWarning, match="Neither function nor data is provided."):
... g = GenerativeImage()
>>> g = GenerativeImage(lambda x,y: 0, lambda x,y: 0)
>>> g.generate(step=0.1)
>>> result = g.save_data()
>>> with warns(RuntimeWarning, match="Just data is provided, generate method is not available in this mode."):
... g_ = GenerativeImage(data=open('data.json', 'r'))
>>> g_.data1 == g.data1
True
>>> g_.data2 == g.data2
True
>>> os.remove('data.json')
"""

0 comments on commit 53bd7be

Please sign in to comment.