Skip to content

Commit

Permalink
Merge pull request #1 from davidnabergoj/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
davidnabergoj authored Aug 18, 2022
2 parents e495988 + ab0f364 commit 2716f1f
Show file tree
Hide file tree
Showing 22 changed files with 720 additions and 138 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Supported image output formats include popular formats such as JPG, PNG, BMP. Su
pip install bootplot
```

Alternatively, you can install **bootplot** without PyPI:
Alternatively, you can install **bootplot** using:

```
git clone https://github.com/davidnabergoj/bootplot
Expand Down Expand Up @@ -59,6 +59,8 @@ def plot_regression(data_subset, data_full, ax):
bbox_kwargs = dict(facecolor='none', edgecolor='black', pad=10.0)
ax.text(x=0, y=-8, s=f'RMSE: {rmse:.4f}', fontsize=12, ha='center', bbox=bbox_kwargs)

ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)

if __name__ == '__main__':
np.random.seed(0)
Expand All @@ -74,8 +76,6 @@ if __name__ == '__main__':
dataset,
output_image_path='demo_image.png',
output_animation_path='demo_animation.gif',
xlim=(-10, 10),
ylim=(-10, 10),
verbose=True
)
```
Expand Down
Empty file added bootplot/backend/__init__.py
Empty file.
160 changes: 160 additions & 0 deletions bootplot/backend/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
from abc import abstractmethod, ABC
from typing import Tuple, Union

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from tqdm import tqdm

import bootplot.backend.matplotlib


class Backend(ABC):
def __init__(self,
f: callable,
data: Union[np.ndarray, pd.DataFrame],
m: int,
output_size_px: Tuple[int, int]):
self.output_size_px = output_size_px
self.f = f
self.data = data
self.m = m

@abstractmethod
def create_figure(self):
raise NotImplemented

def plot(self):
indices = np.random.randint(low=0, high=len(self.data), size=len(self.data))
if isinstance(self.data, pd.DataFrame):
return self.f(self.data.iloc[indices], self.data, *self.plot_args)
elif isinstance(self.data, np.ndarray):
return self.f(self.data[indices], self.data, *self.plot_args)

@abstractmethod
def plot_to_array(self) -> np.ndarray:
raise NotImplemented

@abstractmethod
def clear_figure(self):
raise NotImplemented

@abstractmethod
def close_figure(self):
raise NotImplemented

@property
@abstractmethod
def plot_args(self):
raise NotImplemented


class Basic(Backend):
def __init__(self, f: callable, data: Union[np.ndarray, pd.DataFrame], m: int, output_size_px: Tuple[int, int]):
super().__init__(f, data, m, output_size_px)
self.cached_image = None

def plot(self):
self.cached_image = super().plot()

def create_figure(self):
pass

def plot_to_array(self) -> np.ndarray:
return self.cached_image

def clear_figure(self):
pass

def close_figure(self):
pass

@property
def plot_args(self):
return []


class Matplotlib(Backend):
def __init__(self,
f: callable,
data: Union[np.ndarray, pd.DataFrame],
m: int,
output_size_px: Tuple[int, int] = (512, 512)):
self.fig = None
self.ax = None
super().__init__(f, data, m, output_size_px)

def create_figure(self):
self.fig, self.ax = bootplot.backend.matplotlib.create_figure(self.output_size_px)

def plot_to_array(self) -> np.ndarray:
return bootplot.backend.matplotlib.plot_to_array(self.fig)

def clear_figure(self):
bootplot.backend.matplotlib.clear_figure(self.ax)

def close_figure(self):
bootplot.backend.matplotlib.close_figure(None)

@property
def plot_args(self):
return [self.ax]


class GGPlot2(Backend):
def __init__(self,
f: callable,
data: Union[np.ndarray, pd.DataFrame],
m: int,
output_size_px: Tuple[int, int] = (512, 512)):
super().__init__(f, data, m, output_size_px)

def create_figure(self):
raise NotImplemented

def plot_to_array(self) -> np.ndarray:
raise NotImplemented

def clear_figure(self):
raise NotImplemented

def close_figure(self):
raise NotImplemented

@property
def plot_args(self):
raise NotImplemented


class Plotly(Backend):
def __init__(self,
f: callable,
data: Union[np.ndarray, pd.DataFrame],
m: int,
output_size_px: Tuple[int, int] = (512, 512)):
super().__init__(f, data, m, output_size_px)

def create_figure(self):
raise NotImplemented

def plot_to_array(self) -> np.ndarray:
raise NotImplemented

def clear_figure(self):
raise NotImplemented

def close_figure(self):
raise NotImplemented

@property
def plot_args(self):
raise NotImplemented


def create_backend(backend_string, f, data, m, **kwargs):
if backend_string == 'matplotlib':
return Matplotlib(f=f, data=data, m=m, **kwargs)
elif backend_string == 'basic':
return Basic(f=f, data=data, m=m, **kwargs)
else:
raise NotImplemented
31 changes: 31 additions & 0 deletions bootplot/backend/matplotlib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import io
from typing import Tuple

import numpy as np
import matplotlib.pyplot as plt


def plot_to_array(fig):
with io.BytesIO() as buff:
fig.savefig(buff, format='raw')
buff.seek(0)
data = np.frombuffer(buff.getvalue(), dtype=np.uint8)
w, h = fig.canvas.get_width_height()
im = data.reshape((int(h), int(w), -1))
return im


def create_figure(output_size_px: Tuple[int, int]):
px_size_inches = 1 / plt.rcParams['figure.dpi']
fig, ax = plt.subplots(
figsize=(output_size_px[0] * px_size_inches, output_size_px[1] * px_size_inches)
)
return fig, ax


def clear_figure(ax):
ax.cla()


def close_figure(fig):
plt.close(fig)
Loading

0 comments on commit 2716f1f

Please sign in to comment.