Skip to content

Commit

Permalink
plt_utils bug fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
ARSadri committed Aug 23, 2023
1 parent f7398e1 commit 1d1b96d
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 77 deletions.
7 changes: 6 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,9 @@ History
* default suffix in get_flist is *
* logviewer.get_stack_of_files is only useful for reading data.
* more tests are added.
* moved multichannel_to_frame to utils
* moved multichannel_to_frame to utils

0.9.1 (2023-09-01)
-----------------
* bug removed from plt_utils numbers_as_images_4D.
* bug removed from printprogress when number of steps is very low.
2 changes: 1 addition & 1 deletion lognflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

__author__ = 'Alireza Sadri'
__email__ = '[email protected]'
__version__ = '0.9.0'
__version__ = '0.9.1'

from .lognflow import lognflow
from .logviewer import logviewer
Expand Down
40 changes: 20 additions & 20 deletions lognflow/lognflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,25 @@ def flush_all(self):
for parameter_name in list(self._vars_dict):
self.log_var_flush(parameter_name)

def save(self, parameter_name: str,
parameter_value,
suffix = None,
mat_field = None,
time_tag: bool = None):
return self.log_single(parameter_name = parameter_name,
parameter_value = parameter_value,
suffix = suffix,
mat_field = mat_field,
time_tag = time_tag)

def savez(self, parameter_name: str,
parameter_value,
time_tag: bool = None):
return self.log_single(parameter_name = parameter_name,
parameter_value = parameter_value,
suffix = 'npz',
time_tag = time_tag)

def __call__(self, *args, **kwargs):
"""calling the object
In the case of the following code::
Expand All @@ -1492,23 +1511,4 @@ def __repr__(self):
return f'{self.log_dir}'

def __bool__(self):
return self.log_dir.is_dir()

def save(self, parameter_name: str,
parameter_value,
suffix = None,
mat_field = None,
time_tag: bool = None):
return self.log_single(parameter_name = parameter_name,
parameter_value = parameter_value,
suffix = suffix,
mat_field = mat_field,
time_tag = time_tag)

def savez(self, parameter_name: str,
parameter_value,
time_tag: bool = None):
return self.log_single(parameter_name = parameter_name,
parameter_value = parameter_value,
suffix = 'npz',
time_tag = time_tag)
return self.log_dir.is_dir()
4 changes: 4 additions & 0 deletions lognflow/logviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ def get_stack_of_files(self,
"""
if not flist:
flist = self.get_flist(var_name, suffix)
else:
flist = list(flist)
assert pathlib.Path(flist[0]).is_file(), \
f'File not found: {flist[0]}. You can use logviewer get_flist'

if flist:
n_files = len(flist)
Expand Down
59 changes: 37 additions & 22 deletions lognflow/plt_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .printprogress import printprogress
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
import matplotlib.pyplot as plt
Expand Down Expand Up @@ -41,10 +42,12 @@ def pltfig_to_numpy(fig):
w,h = fig.canvas.get_width_height()
buf = np.frombuffer(fig.canvas.tostring_argb(), dtype=np.ubyte)
buf.shape = (w, h, 4)
buf = np.roll (buf, 3, axis = 2)
return buf
return buf.sum(2)

def numbers_as_images_3D(dataset_shape: tuple, fontsize, verbose = False):
def numbers_as_images_3D(data3D_shape: tuple[int, int, int],
fontsize: int,
text_loc: tuple[int, int] = None,
verbose: bool = True):
""" Numbers3D
This function generates a 4D dataset of images with shape
(n_x, n_r, n_c) where in each image the value "x" is written as a text
Expand All @@ -61,8 +64,12 @@ def numbers_as_images_3D(dataset_shape: tuple, fontsize, verbose = False):
output 3D array.
"""
n_x, n_r, n_c = dataset_shape
dataset = np.zeros(dataset_shape)
n_x, n_r, n_c = data3D_shape

if text_loc is None:
text_loc = (n_r//2 - fontsize, n_c//2 - fontsize)

dataset = np.zeros(data3D_shape)
txt_width = int(np.log(n_x)/np.log(n_x)) + 1
number_text_base = '{ind_x:0{width}}}'
if(verbose):
Expand All @@ -71,22 +78,23 @@ def numbers_as_images_3D(dataset_shape: tuple, fontsize, verbose = False):
mat = np.ones((n_r, n_c))
number_text = number_text_base.format(ind_x = ind_x,
width = txt_width)
fig = plt.figure(figsize = (1, 1))
fig = plt.figure(figsize = (n_rr, n_cc), dpi = n_rc)
ax = fig.add_subplot(111)
ax.imshow(mat, cmap = 'gray', vmin = 0, vmax = 1)
ax.text(mat.shape[0]//2 - fontsize, mat.shape[1]//2 ,
ax.text(text_loc[0], text_loc[1],
number_text, fontsize = fontsize)
ax.axis('off')
buf = pltfig_to_numpy(fig)
plt.close()
buf2 = buf[::buf.shape[0]//n_r, ::buf.shape[1]//n_c, :3].mean(2)
buf2 = buf2[:n_r, :n_c]
dataset[ind_x] = buf2.copy()
dataset[ind_x] = buf.copy()
if(verbose):
pBar()
return dataset

def numbers_as_images_4D(dataset_shape: tuple, fontsize, verbose = False):
def numbers_as_images_4D(data4D_shape: tuple[int, int, int, int],
fontsize: int,
text_loc: tuple[int, int] = None,
verbose: bool = True):
""" Numbers4D
This function generates a 4D dataset of images with shape
(n_x, n_y, n_r, n_c) where in each image the value "x, y" is written as a text
Expand All @@ -102,31 +110,38 @@ def numbers_as_images_4D(dataset_shape: tuple, fontsize, verbose = False):
You can provide a logs_root, log_dir or simply select a directory to save the
output 4D array.
:param text__loc:
text_loc should be a tuple of the location of bottom left corner of the
text in the image.
"""
n_x, n_y, n_r, n_c = dataset_shape
n_x, n_y, n_r, n_c = data4D_shape

if text_loc is None:
text_loc = (n_r//2 - fontsize, n_c//2 - fontsize)

dataset = np.zeros((n_x, n_y, n_r, n_c))
txt_width = int(np.log(np.maximum(n_x, n_y))
/np.log(np.maximum(n_x, n_y))) + 1
/ np.log(np.maximum(n_x, n_y))) + 1
number_text_base = '{ind_x:0{width}}, {ind_y:0{width}}'
if(verbose):
pBar = printprogress(n_x * n_y)
for ind_x in range(n_x):
for ind_y in range(n_y):
mat = np.ones((n_r, n_c))
number_text = number_text_base.format(ind_x = ind_x,
ind_y = ind_y,
width = txt_width)
fig = plt.figure(figsize = (1, 1))
number_text = number_text_base.format(
ind_x = ind_x, ind_y = ind_y, width = txt_width)
n_rc = np.minimum(n_r, n_c)
n_rr = n_r / n_rc
n_cc = n_c / n_rc
fig = plt.figure(figsize = (n_rr, n_cc), dpi = n_rc)
ax = fig.add_subplot(111)
ax.imshow(mat, cmap = 'gray', vmin = 0, vmax = 1)
ax.text(mat.shape[0]//2 - fontsize, mat.shape[1]//2 ,
number_text, fontsize = fontsize)
ax.text(text_loc[0], text_loc[1], number_text, fontsize = fontsize)
ax.axis('off')
buf = pltfig_to_numpy(fig)
plt.close()
buf2 = buf[::buf.shape[0]//n_r, ::buf.shape[1]//n_c, :3].mean(2)
buf2 = buf2[:n_r, :n_c]
dataset[ind_x, ind_y] = buf2.copy()
dataset[ind_x, ind_y] = buf.copy()
if(verbose):
pBar()
return dataset
27 changes: 18 additions & 9 deletions lognflow/printprogress.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ def __init__(self,
self.method = method
self.in_print_function = print_function
if(n_steps != int(n_steps)):
self._print_func('textProgBar takes integers no less than 2 ')
self._print_func(
r'printprogress takes integers no less than 2 as n_steps.')
n_steps = int(n_steps)
if(n_steps<2):
n_steps = 2
Expand Down Expand Up @@ -75,6 +76,7 @@ def __init__(self,
self._print_func(' \\')

self._print_func(' ', end = '')
self.len_prog_text = 0

def _print_func(self, text, end='\n'):
if (self.in_print_function is not None):
Expand All @@ -93,7 +95,8 @@ def _calc_ETA(self):

def __call__(self, ck=1):
""" ticking the progress bar
just call the object and the progress bar moves one ahead when ready.
just call the object and the progress bar moves ck steps
ahead when ready.
output
~~~~~~
Expand All @@ -104,12 +107,12 @@ def __call__(self, ck=1):
if(self.FLAG_ended):
if(not self.FLAG_warning):
self.FLAG_warning = True
self._print_func('-' * self.numTicks)
self._print_func('-' * (self.numTicks + 2))
else:
self.ck += ck
if(self.ck <= self.n_steps):
remTimeS = self._calc_ETA() # useful when print_function is None
cProg = int(self.numTicks*self.ck/(self.n_steps-1)/3)
cProg = int(self.numTicks*self.ck/(self.n_steps-1)/3)
#3: because 3 charachters are used
while((self.prog < cProg) & (not self.FLAG_ended)):
self.prog += 1
Expand All @@ -118,27 +121,33 @@ def __call__(self, ck=1):
progStr = "%02d" % int(ceil(remTimeS/86400))
self._print_func(progStr, end='')
self._print_func('d', end='')
self.len_prog_text += 3
elif(remTimeS>5940): # less than 99h and more than 99m
progStr = "%02d" % int(ceil(remTimeS/3600))
self._print_func(progStr, end='')
self._print_func('h', end='')
self.len_prog_text += 3
elif(remTimeS>99): # less than 99m and more than 99s
progStr = "%02d" % int(ceil(remTimeS/60))
self._print_func(progStr, end='')
self._print_func('m', end='')
self.len_prog_text += 3
elif(remTimeS>=0): # less than 99s and more than 0
progStr = "%02d" % int(ceil(remTimeS))
self._print_func(progStr, end='')
self._print_func('s', end='')
self.len_prog_text += 3
else:
self.end()
if(self.ck >= self.n_steps):
self.end()
self._end()
if((self.ck >= self.n_steps) |
(self.len_prog_text >= self.numTicks)):
self._end()
return remTimeS
def end(self):

def _end(self):
if(not self.FLAG_ended):
self._print_func('')
self.FLAG_ended = True

def __del__(self):
self.end()
self._end()
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.8.6
current_version = 0.9.0
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

__author__ = 'Alireza Sadri'
__email__ = '[email protected]'
__version__ = '0.9.0'
__version__ = '0.9.1'

with open('README.rst') as readme_file:
readme = readme_file.read()
Expand Down
1 change: 0 additions & 1 deletion tests/test_lognflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ def test_log_multichannel_by_subplots():
logger.log_multichannel_by_subplots('images', images, (4, 5))

if __name__ == '__main__':

#-----IF RUN BY PYTHON------#
temp_dir = select_directory()
#---------------------------#
Expand Down
27 changes: 6 additions & 21 deletions tests/test_printprogress.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,11 @@
import tempfile
temp_dir = tempfile.gettempdir()

@pytest.fixture
def response():
"""Sample pytest fixture.
See more at: http://doc.pytest.org/en/latest/fixture.html
"""
# import requests
# return requests.get('https://github.com/audreyr/cookiecutter-pypackage')

def test_content(response):
"""Sample pytest test function with the pytest fixture as an argument."""
# from bs4 import BeautifulSoup
# assert 'GitHub' in BeautifulSoup(response.content).title.string

def test_printprogress():
N = 3000000
pprog = printprogress(N)
for _ in range(N):
pprog()
# assert input('Did it show you a progress bar? (y for yes)')=='y'
for N in list([2, 4, 8, 10, 20, 200, 2000, 20000, 20000000]):
pprog = printprogress(N)
for _ in range(N):
pprog()

def test_printprogress_with_logger():
logger = lognflow(temp_dir)
Expand Down Expand Up @@ -62,8 +47,8 @@ def test_specific_timing():
#-----IF RUN BY PYTHON------#
temp_dir = select_directory()
#---------------------------#
test_printprogress()
test_printprogress_ETA()
test_specific_timing()
test_printprogress_with_logger()
test_printprogress()
exit()
exit()

0 comments on commit 1d1b96d

Please sign in to comment.