Skip to content

Commit

Permalink
Merge branch 'py5coding:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
AsadNizami authored Mar 11, 2023
2 parents c8371b4 + 8eab021 commit 37fa8b8
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 12 deletions.
2 changes: 1 addition & 1 deletion generator/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
(['dirname: str', '*', "filename: str = 'frame_####.png'",
'period: float = 0.0', 'start: int = None', 'limit: int = 0',
'sketch: Sketch = None', 'hook_post_draw: bool = False',
'block: bool = False'], 'None')
'block: bool = False', 'display_progress: bool = True'], 'None')
],
('Py5Tools', 'animated_gif'): [
(['filename: str', 'count: int', 'period: float', 'duration: float', '*',
Expand Down
5 changes: 4 additions & 1 deletion py5_docs/Reference/api_en/Py5Tools_save_frames.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ category = sketch_hooks
subcategory = None

@@ signatures
save_frames(dirname: str, *, filename: str = 'frame_####.png', period: float = 0.0, start: int = None, limit: int = 0, sketch: Sketch = None, hook_post_draw: bool = False, block: bool = False) -> None
save_frames(dirname: str, *, filename: str = 'frame_####.png', period: float = 0.0, start: int = None, limit: int = 0, sketch: Sketch = None, hook_post_draw: bool = False, block: bool = False, display_progress: bool = True) -> None

@@ variables
block: bool = False - method returns immediately (False) or blocks until function returns (True)
dirname: str - directory to save the frames
display_progress: bool = True - display progress as frames are saved
filename: str = 'frame_####.png' - filename template to use for saved frames
hook_post_draw: bool = False - attach hook to Sketch's post_draw method instead of draw
limit: int = 0 - limit the number of frames to save (default 0 means no limit)
Expand All @@ -26,6 +27,8 @@ By default the Sketch will be the currently running Sketch, as returned by [](py

If the `limit` parameter is used, this function will wait to return a list of the filenames. If not, it will return right away as the frames are saved in the background. It will keep doing so as long as the Sketch continues to run.

By default this function will report its progress as frames are saved. If you are using a Jupyter Notebook and happen to be saving tens of thousands of frames, this might cause Jupyter to crash. To avoid that fate, set the `display_progress` parameter to `False`.

If your Sketch has a `post_draw()` method, use the `hook_post_draw` parameter to make this function run after `post_draw()` instead of `draw()`. This is important when using Processing libraries that support `post_draw()` such as Camera3D or ColorBlindness.

@@ example
Expand Down
6 changes: 2 additions & 4 deletions py5_docs/Reference/api_en/Sketch_random_choice.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ category = math
subcategory = random

@@ signatures
random_choice(objects: list[Any], size: int=1, replace: bool=True) -> Any
random_choice(objects: list[Any]) -> Any

@@ variables
objects: list[Any] - list of objects to choose from
replace: bool=True - whether to select random items with or without replacement
size: int=1 - number of random items to select

@@ description
Select random items from a list. The list items can be of any type. If multiple items are selected, this function will by default allow the same item to be selected multiple times. Set the `replace` parameter to `False` to prevent the same item from being selected multiple times.
Select a random item from a list. The list items can be of any type. If the list of objects is empty, `None` will be returned.

This function's randomness can be influenced by [](sketch_random_seed), and makes calls to numpy to select the random items.

Expand Down
26 changes: 26 additions & 0 deletions py5_docs/Reference/api_en/Sketch_random_sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@@ meta
name = random_sample()
type = method
category = math
subcategory = random

@@ signatures
random_sample(objects: list[Any], size: int=1, replace: bool=True) -> list[Any]

@@ variables
objects: list[Any] - list of objects to choose from
replace: bool=True - whether to select random items with or without replacement
size: int=1 - number of random items to select

@@ description
Select random items from a list. The list items can be of any type. If multiple items are selected, this function will by default allow the same item to be selected multiple times. Set the `replace` parameter to `False` to prevent the same item from being selected multiple times.

The returned value will always be a sequence such as a list or numpy array, even if only one item is sampled. If you only want to sample one item, consider using [](sketch_random_choice) instead. If the list of objects is empty, an empty list will be returned.

This function's randomness can be influenced by [](sketch_random_seed), and makes calls to numpy to select the random items.

@@ example
def setup():
words = ["apple", "bear", "cat", "dog"]
word = py5.random_sample(words)
py5.println(word) # Prints one of the four words
1 change: 1 addition & 0 deletions py5_resources/data/sketch.csv
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ norm,norm,,static method,math,calculation,PYTHON,implemented in mixin file math.
random_gaussian,randomGaussian,,method,math,random,PYTHON,implementation uses numpy for performance reasons
random_int,,,method,math,random,PYTHON,implementation uses numpy for performance reasons
random_choice,,,method,math,random,PYTHON,implementation uses numpy for performance reasons
random_sample,,,method,math,random,PYTHON,implementation uses numpy for performance reasons
random_seed,randomSeed,,method,math,random,PYTHON,implementation uses numpy for performance reasons
np_random,,,dynamic variable,math,random,PYTHON,make numpy random number generator available to users
noise_array,noiseArray,,method,math,random,SKIP,vectorized noise for better performance
Expand Down
23 changes: 21 additions & 2 deletions py5_resources/py5_module/py5/mixins/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import warnings
import traceback
from pathlib import Path
import types
from typing import overload, Union, Any

import numpy as np
Expand Down Expand Up @@ -259,9 +260,27 @@ def random_int(self, *args: int) -> int:
types = ','.join([type(a).__name__ for a in args])
raise TypeError(f'No matching overloads found for Sketch.random_int({types})')

def random_choice(self, objects: list[Any], size: int=1, replace: bool=True) -> Any:
def random_choice(self, objects: list[Any]) -> Any:
"""$class_Sketch_random_choice"""
return self._rng.choice(objects, size=size, replace=replace)
if len(objects):
return objects[self._rng.integers(0, len(objects))]
else:
return None

def random_sample(self, objects: list[Any], size: int=1, replace: bool=True) -> list[Any]:
"""$class_Sketch_random_sample"""
if len(objects):
if isinstance(objects, types.GeneratorType):
objects = list(objects)
indices = self._rng.choice(range(len(objects)), size=size, replace=replace)
if not isinstance(objects, list):
try:
return objects[indices]
except:
pass
return [objects[idx] for idx in indices]
else:
return []

@overload
def random_gaussian(self) -> float:
Expand Down
4 changes: 2 additions & 2 deletions py5_resources/py5_module/py5_tools/hooks/frame_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def screenshot(*, sketch: Sketch = None, hook_post_draw: bool = False) -> PIL.Im
def save_frames(dirname: str, *, filename: str = 'frame_####.png',
period: float = 0.0, start: int = None, limit: int = 0,
sketch: Sketch = None, hook_post_draw: bool = False,
block: bool = False) -> None:
block: bool = False, display_progress: bool = True) -> None:
"""$module_Py5Tools_save_frames"""
import py5
if sketch is None:
Expand All @@ -101,7 +101,7 @@ def save_frames(dirname: str, *, filename: str = 'frame_####.png',
if not dirname.exists():
dirname.mkdir(parents=True)

hook = SaveFramesHook(dirname, filename, period, start, limit)
hook = SaveFramesHook(dirname, filename, period, start, limit, display_progress)
sketch._add_post_hook('post_draw' if hook_post_draw else 'draw', hook.hook_name, hook)

if block:
Expand Down
6 changes: 4 additions & 2 deletions py5_resources/py5_module/py5_tools/hooks/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,14 @@ def __call__(self, sketch):

class SaveFramesHook(BaseHook):

def __init__(self, dirname, filename, period, start, limit):
def __init__(self, dirname, filename, period, start, limit, display_progress):
super().__init__('py5save_frames_hook')
self.dirname = dirname
self.filename = filename
self.period = period
self.start = start
self.limit = limit
self.display_progress = display_progress
self.num_offset = None
self.filenames = []
self.last_frame_time = 0
Expand All @@ -99,7 +100,8 @@ def __call__(self, sketch):
self.last_frame_time = time.time()
if len(self.filenames) == self.limit:
self.hook_finished(sketch)
self.status_msg(f'saving frame {len(self.filenames)}' + (f'/{self.limit}' if self.limit else ''))
if self.display_progress:
self.status_msg(f'saving frame {len(self.filenames)}' + (f'/{self.limit}' if self.limit else ''))
except Exception as e:
self.hook_error(sketch, e)

Expand Down

0 comments on commit 37fa8b8

Please sign in to comment.