Python library¶
- shapeflow.__version__ = '0.4.4'¶
Library version
shapeflow¶
Common elements.
Application settings
Logging
Caching
- shapeflow.ROOTDIR = PosixPath('/home/docs/.local/share/shapeflow')¶
Root directory of the application.
Linux:
/home/<user>/.local/share/shapeflowWindows:
C:\Users\<user>\AppData\Roaming\shapeflow
- class shapeflow._Settings[source]¶
Bases:
pydantic.main.BaseModelAbstract application settings
- override(overrides: dict)[source]¶
Override some parameters of the settings in a context. Settings will only be modified within this context and restored to their previous values afterwards. Usage:
with settings.override({"parameter": "override value"}): <do something>
- Parameters
overrides (dict) – A
dictmapping field names to values with which to override those fields
- class shapeflow.FormatSettings[source]¶
Bases:
shapeflow._SettingsFormatting settings
- datetime_format: str¶
Base
datetimeformat string. Defaults to'%Y/%m/%d %H:%M:%S.%f'.
- datetime_format_fs: str¶
Filesystem-safe
datetimeformat string. Used to append date & time to file names. Defaults to'%Y-%m-%d_%H-%M-%S'.
- class shapeflow.LoggingLevel(value)[source]¶
Bases:
str,enum.EnumLogging level.
- critical = 'critical'¶
Only log critical (unrecoverable) errors
- error = 'error'¶
Only log errors
- warning = 'warning'¶
Only log warnings (or errors)
- info = 'info'¶
Log general information
- debug = 'debug'¶
Log debugging information
- vdebug = 'vdebug'¶
Log verbose debugging information
- property level: int¶
Return the
intlogging level for compatibility with built-inlogginglibrary
- class shapeflow.LogSettings[source]¶
Bases:
shapeflow._SettingsLogging settings
- path: pydantic.types.FilePath¶
The application logs to this file
- dir: pydantic.types.DirectoryPath¶
This is the log directory. Logs from previous runs are stored here.
- keep: int¶
The applications stores a number of old logs.
When the amount of log files in
shapeflow.LogSettings.direxceeds this number, the oldest files are deleted.
- lvl_console: shapeflow.LoggingLevel¶
The level at which the application logs to the Python console.
Defaults to
infoto keep the console from getting too spammy. Set to a lower level such asdebugto show more detailed logs in the console.
- lvl_file: shapeflow.LoggingLevel¶
The level at which the application logs to the log file at
path.Defaults to
shapeflow.LoggingLevel.debug.
- class shapeflow.CacheSettings[source]¶
Bases:
shapeflow._SettingsCaching settings
- do_cache: bool¶
Enables the cache. Set to
Trueby default.Disabling the cache will make the application significantly slower.
- dir: pydantic.types.DirectoryPath¶
Where to keep the cache
- size_limit_gb: float¶
How big the cache is allowed to get
- resolve_frame_number: bool¶
Whether to resolve frame numbers to the nearest requested frame numbers.
Increases seeking performance, but may make it a bit more ‘jumpy’ if a low number of frames is requested for an analysis.
- block_timeout: float¶
How long to keep waiting for data that’s actively being committed to the cache before giving up and computing it instead.
In the rare case that two cachable data requests are being processed at the same time, the first request will block the cache for those specific data and cause the second request to wait until it can grab this data from the cache. This timeout prevents the second request from waiting forever until the first request finishes (for example, in case it crashes).
- reset_on_error: bool¶
Clear the cache if it can’t be opened.
In rare cases,
diskcachemay cache data in a way it can’t read back. To recover from such an error, the cache will be cleared completely. The only downside to this is decreased performance for a short while.
- class shapeflow.RenderSettings[source]¶
Bases:
shapeflow._SettingsRendering settings
- dir: pydantic.types.DirectoryPath¶
The directory where SVG files should be rendered to
- keep: bool¶
Keep rendered images after they’ve been used.
Disabled by default, you may want to enable this if you want to inspect the renders.
- class shapeflow.DatabaseSettings[source]¶
Bases:
shapeflow._SettingsDatabase settings.
- path: pydantic.types.FilePath¶
The path to the database file
- cleanup_interval: int¶
The database can get cluttered after a while, and will be cleaned at this interval
- class shapeflow.ResultSaveMode(value)[source]¶
Bases:
str,enum.EnumWhere (or whether) to save the results of an analysis
- skip = 'skip'¶
Don’t save results at all
- next_to_video = 'next to video file'¶
Save results in the same directory as the video file that was analyzed
- next_to_design = 'next to design file'¶
Save results in the same directory as the design file that was analyzed
- directory = 'in result directory'¶
Save results in their own directory at
shapeflow.ApplicationSettings.result_dir
- class shapeflow.ApplicationSettings[source]¶
Bases:
shapeflow._SettingsApplication settings.
- save_state: bool¶
Whether to save the application state when exiting the application
- load_state: bool¶
Whether to load the application state when starting the application
- state_path: pydantic.types.FilePath¶
Where to save the application state
- recent_files: int¶
The number of recent files to show in the user interface
- video_pattern: str¶
Recognized video file extensions. Defaults to
"*.mp4 *.avi *.mov *.mpv *.mkv".
- design_pattern: str¶
Recognized design file extensions. Defaults to
"*.svg".
- save_result_auto: shapeflow.ResultSaveMode¶
Where or whether to save results after each run of an analysis
- save_result_manual: shapeflow.ResultSaveMode¶
Where or whether to save results that are exported manually via the user interface
- result_dir: pydantic.types.DirectoryPath¶
The path to the result directory
- cancel_on_q_stop: bool¶
Whether to cancel the currently running analysis when stopping a queue.
Defaults to
False, i.e. the currently running analysis will be completed first.
- class shapeflow.Settings[source]¶
Bases:
shapeflow._Settingsshapeflowsettings.app:
ApplicationSettingslog:
LogSettingscache:
CacheSettingsrender:
RenderSettingsformat:
FormatSettingsdb:
DatabaseSettings
- shapeflow.settings = shapeflow.Settings()¶
This global
Settingsobject is used throughout the library
- shapeflow.save_settings(path: str = '/home/docs/.local/share/shapeflow/settings.yaml')[source]¶
Save
settingsto .yaml
- shapeflow.update_settings(s: dict) → dict[source]¶
Update the global settings object.
Note
Just doing
settings = Settings(**new_settings_dict)would prevent other modules from accessing the updated settings!- Parameters
s (dict) – new settings to integrate into the global settings
- Returns
the current global settings as a
dict- Return type
dict
- class shapeflow.Logger(name, level=0)[source]¶
shapeflowlogger.Adds a verbose debug logging level
vdebug()Strips newlines from log output to keep each log event on its own line
- shapeflow.get_logger(name: str) → shapeflow.Logger[source]¶
Get a new
Loggerobject- Parameters
name (str) – name of the logger
- Returns
a fresh logging handle
- Return type
- shapeflow.get_cache(retry: bool = False) → diskcache.core.Cache[source]¶
Get a new
diskcache.Cacheobject In some rare cases this can fail due to a corrupt cache. Ifsettings.cache.reset_on_erroris on, and an exception is raised the cache directory is removed andget_cache()is called again withretryset toTrue.- Parameters
retry (bool) – Whether this call is a “retry call”. Defaults to
False, i.e. a first call- Returns
a fresh cache handle
- Return type
diskcache.Cache
util¶
General utility functions & classes.
- class shapeflow.util.Timing(t0, t1, elapsed)¶
Bases:
tuple- property elapsed¶
Alias for field number 2
- property t0¶
Alias for field number 0
- property t1¶
Alias for field number 1
- shapeflow.util.timed(f, logger: logging.Logger)[source]¶
Function decorator to measure elapsed time. Useful for profiling and debugging.
- Parameters
f – Any function or method
logger (Logger) – A logger to log to
- shapeflow.util.logged(f, logger: logging.Logger)[source]¶
Function decorator to log before & after a function call. Useful for profiling and debugging.
- Parameters
f – Any function or method
logger (Logger) – A logger to log to
- class shapeflow.util.Timer(parent: object, logger: logging.Logger)[source]¶
Bases:
objectA timer context manager. Starts timing on
__enter__and stops on__exit__. Timing info can be retrieved withtiming.- property timing: Optional[tuple]¶
start time, end time, elapsed time.
- Type
Optional[tuple]
- shapeflow.util.restrict(val, minval, maxval)[source]¶
Clamp a value between a minimum and a maximum.
- shapeflow.util.frame_number_iterator(total: int, Nf: Optional[int] = None, dt: Optional[float] = None, fps: Optional[float] = None) → Generator[int, None, None][source]¶
Get an iterator of frame numbers, based on either a number of frames
Nfor a frame intervaldt.- Parameters
total (int) – The total number of frames.
Nf (int) – The number of frames to return. Defaults to
None.dt (float) – The frame interval to return. Defaults to
None. If usingdt,fpsmust also be provided.fps (float) – The framerate. Defaults to
None
- Raises
ValueError – When both
NfanddtareNone- Returns
An iterator that returns the requested frame numbers.
- Return type
Generator
- shapeflow.util.before_version(version_a, version_b)[source]¶
Check whether
version_aprecedesversion_b.Note
Only handles numerics, i.e.
"1.25b.3v7"won’t work.
- shapeflow.util.after_version(version_a, version_b)[source]¶
Check whether
version_asupercedesversion_b.Note
Only handles numerics, i.e.
"1.25b.3v7"won’t work.
- shapeflow.util.hash_file(path: str, blocksize: int = 1024) → queue.Queue[source]¶
Start hashing a file without blocking the current thread.
- Parameters
path (str) – The path of the file to hash.
blocksize (int) – The blocksize step to take when reading the file. Defaults to 1024.
- Returns
A new
queue.Queueobject. Once the hash is ready, it will be pushed to this queue.- Return type
queue.Queue
- shapeflow.util.sizeof_fmt(size, suffix='B')[source]¶
Get a file size in bytes as a human-readable string. For example:
>>> sizeof_fmt(10**3) "1 KB" >>> sizeof_fmt(10**9) "1 GB"
- Parameters
num – A file size in bytes
suffix (str) – The suffix to use. Defaults to
"B".
- Returns
The file size as a human-readable string in decimal bytes.
- Return type
str
- shapeflow.util.ensure_path(path: Union[str, pathlib.Path])[source]¶
A hacky way to allow imports from arbitrary directories. Only use this for testing
sf.pyplease :(
- shapeflow.util.meta.describe_function(f) → str[source]¶
Return a function description. More specific than regular old
__qualname__.Note
For nested functions,
__qualname__contains<locals>.diskcache.Cachecan write keys containing<or>but crashes when trying to read these back. To prevent weird bugs,<and>are replaced with_- Parameters
f – Any function or method
- Returns
A unique name for this method
- Return type
str
- shapeflow.util.meta.bases(c: type) → List[type][source]¶
Returns the bases of a class, including the bases of its bases.
Note
Just in general, don’t do
list(set())if the order is important!- Parameters
c (type) – Any class
- Returns
A list of all bases of
c- Return type
List[type]
- shapeflow.util.meta.unbind(m)[source]¶
Unbind a method from its instance.
- Parameters
m – Any method
- Returns
- Return type
The method
m, not bound to any instance
- shapeflow.util.meta.bind(instance, m)[source]¶
Bind a method to an instance.
https://stackoverflow.com/a/1015405/12259362
- Parameters
instance – An object
m – Any bound or unbound method of the class of
instance
- Returns
The method
m, bound toinstance- Return type
Callable
core¶
- exception shapeflow.core.RootException(*args)[source]¶
Bases:
ExceptionAll
shapeflowexceptions should be subclasses of this one. Automatically logs the exception class and message at theERRORlevel.- msg = ''¶
The message to log
- exception shapeflow.core.DispatchingError(*args)[source]¶
Bases:
shapeflow.core.RootExceptionAn error dispatching a method call or exposing an endpoint.
- class shapeflow.core.EnforcedStr(string: Optional[str] = None)[source]¶
Bases:
strA string that is enforced to be one of several options. Works like a dynamic
Enum– options can be added at runtime.- property options¶
The accepted options
- property descriptions¶
The descriptions of each option
- property describe¶
The description of the currently selected option
- property default¶
The default option for this
EnforcedStr
- classmethod set_default(value: shapeflow.core.EnforcedStr) → None[source]¶
Explicitly sets the default.
- Parameters
value (EnforcedStr) – The default value to set
- class shapeflow.core.Endpoint(signature: _GenericAlias, streaming: shapeflow.core._Streaming = <_Streaming 'off'>)[source]¶
Bases:
objectAn endpoint for an internal method.
- compatible(method: Callable) → bool[source]¶
Checks whether a method is compatible with the endpoint’s signature
- Parameters
method (Callable) – Any method or function
- Returns
Trueif the method is compatible,Falseif it isn’t.- Return type
bool
- expose()[source]¶
Expose a method at this endpoint. Used as a decorator:
@endpoint.expose() def some_method(): pass
- property method: Optional[Callable]¶
The method exposed at this endpoint. Can be
None
- property signature: tuple¶
The signature of this endpoint.
- property streaming: shapeflow.core._Streaming¶
What or whether this endpoint streams.
- property registered: bool¶
Whether this endpoint is registered.
- property name: str¶
The name of this endpoint. Taken from its attribute name in the object where it is registered.
- register(name: str, callback: Callable[[shapeflow.core.Endpoint], None])[source]¶
Register the endpoint in some other object.
- class shapeflow.core.Dispatcher(instance: Optional[object] = None)[source]¶
Bases:
objectDispatches requests to
shapeflow.core.Endpointobjects.- property name: str¶
The name of this dispatcher.
- property dispatchers: Tuple[shapeflow.core.Dispatcher, ...]¶
The dispatchers nested in this dispatcher.
- property endpoints: Tuple[shapeflow.core.Endpoint, ...]¶
The endpoints contained in this dispatcher.
- property address_space: Dict[str, Optional[Callable]]¶
The address-method mapping of this dispatcher.
- dispatch(address: str, *args, **kwargs) → Any[source]¶
Dispatch a request to a method.
- Parameters
address (str) – The address to dispatch to
args – Any positional arguments to pass on to the method
kwargs – Any keyword arguments to pass on to the method
- Returns
Whatever the method returns.
- Return type
Any
- class shapeflow.core.Described[source]¶
Bases:
objectA class with a description.
This description is taken from the first line of the docstring if there is one or set to the name of the class if there isn’t.
- class shapeflow.core.Lockable[source]¶
Bases:
objectWrapper around
threading.Lock&threading.EventDefines a
lockcontext to handle locking and unlocking along with a_canceland_errorevents to communicate withLockableobjects from other threads.Doesn’t need to initialize; lock & events are created when they’re needed.
- lock()[source]¶
Locking context.
If
_lockevent doesn’t exist yet it is instantiated first. Upon exiting the context, thethreading.Lockobject is compared to the original to ensure that no shenanigans took place.
- cancel()[source]¶
Sets the
_cancelevent. If_cancelevent doesn’t exist yet it is instantiated first.
- property canceled: bool¶
Returns
Trueif the_cancelevent is set. If_cancelevent doesn’t exist yet it is instantiated first.
- property errored: bool¶
Returns
Trueif the_errorevent is set. If_errorevent doesn’t exist yet it is instantiated first.
- class shapeflow.core.RootInstance[source]¶
Bases:
shapeflow.core.Lockable
streaming¶
Streaming various data over Flask.
- class shapeflow.core.streaming.BaseStreamer[source]¶
Bases:
abc.ABCAbstract streamer.
- push(value: Any) → None[source]¶
Push something to the stream.
- Parameters
value (Any) – Anything, really. If it doesn’t work, you’ll hear it.
- stream() → Generator[Any, None, None][source]¶
Start a stream.
- Returns
A generator that can be returned as a
Flaskresponse.- Return type
Generator[Any, None, None]
- property headers¶
Get the streamer’s headers (for
Flaskresponse).
- class shapeflow.core.streaming.PlainFileStreamer(path: str)[source]¶
Bases:
shapeflow.core.streaming.BaseStreamerStreams plaintext files. Used to stream logs to the frontend.
- property headers¶
Get the streamer’s headers (for
Flaskresponse).
- class shapeflow.core.streaming.JsonStreamer[source]¶
Bases:
shapeflow.core.streaming.BaseStreamerStreams JSON data.
- class shapeflow.core.streaming.EventStreamer[source]¶
Bases:
shapeflow.core.streaming.JsonStreamerStreams server-sent events with JSON data.
- class shapeflow.core.streaming.FrameStreamer[source]¶
Bases:
shapeflow.core.streaming.BaseStreamerStreams images. Subclasses can define specific encodings, for now
JpegStreamerseems to work best.
- class shapeflow.core.streaming.JpegStreamer[source]¶
Bases:
shapeflow.core.streaming.FrameStreamerStreams JPEG images.
- class shapeflow.core.streaming.StreamHandler(*args, **kwargs)[source]¶
Bases:
shapeflow.core.LockableHandles streaming of method return values
- register(instance: object, method) → shapeflow.core.streaming.BaseStreamer[source]¶
Register an instance/method combination, start a streamer. If this combination has been registered already, return its streamer.
- Parameters
instance (object) – Any instance that contains
methodmethod – Any method of
instancethat’s mapped to a streamingEndpointobject
- Returns
A streamer
- Return type
- is_registered(instance: object, method=None) → bool[source]¶
Check whether an instance/method combo is registered.
- push(instance: object, method, data) → None[source]¶
Push some data, if this instance/method combination is registered.
- Parameters
instance (object) – Any instance that contains
methodmethod – Any method of
instancethat’s mapped to a streamingEndpointobjectdata (Any) – Anything, really. If it doesn’t work, you’ll hear it.
- unregister(instance: object, method=None) → None[source]¶
Unregister an instance/method combination and stop streaming.
- Parameters
instance (object) – Any instance that contains
methodmethod – Any method of
instancethat’s mapped to a streamingEndpointobject. IfNone, unregister all methods for thisinstance.
- shapeflow.core.streaming.streams = <shapeflow.core.streaming.StreamHandler object>¶
Global
StreamHandlerinstance.
- shapeflow.core.streaming.stream(method)[source]¶
Decorator to mark streaming methods.
Only works for methods exposed at
Endpointobjects, should be placed above theexpose()decorator:from shapeflow.core import Endpoint, _Streaming some_endpoint = Endpoint(Callable[[...], ...], _Streaming()) class SomeClass: @stream @some_endpoint.expose() def some_method(self, ...): pass
To actually stream, the wrapped method and an instance should be registered in
shapeflow.core.streaming.streams.
db¶
- class shapeflow.core.db.SessionWrapper[source]¶
Bases:
objectWrapper object for a
SQLAlchemysession factory.- connect(session_wrapper: shapeflow.core.db.SessionWrapper)[source]¶
Share the session factory of another
SessionWrapperinstance
- class shapeflow.core.db.DbModel(**kwargs)[source]¶
Bases:
sqlalchemy.orm.decl_api.Base,shapeflow.core.db.SessionWrapper,shapeflow.core.LockableAbstract database model class.
Subclasses should
- session(add: bool = True)[source]¶
SQLAlchemysession context manager.Opens a
SQLAlchemysession and commits after the block is done. Changes are rolled back if an exception is raised. Usage:with self.session() as s: # interact with the database here
Calls
DbModel._pre()before yielding the session andDbModel._post()after the block is completed.- Parameters
add (bool) – add model(s) after opening the session
- class shapeflow.core.db.FileModel(path: str)[source]¶
Bases:
shapeflow.core.db.DbModelAbstract database model for files.
Files are hashed and resolved in order to keep a single entry per file.
- property resolved: bool¶
Whether the
FileModelhas been resolved
- resolve() → shapeflow.core.db.FileModel[source]¶
Resolve the file by its SHA1 hash ~
hash_file().If the computed hash is new, the file is committed to the database. Otherwise, the original entry is re-used.
- Returns
The current instance if the file is new, or a new
FileModelinstance representing the original database entry.- Return type
- class shapeflow.core.db.BaseAnalysisModel(**kwargs)[source]¶
Bases:
shapeflow.core.db.DbModelAnalysisModel interface.
- abstract load_config(video_path: str, design_path: Optional[str] = None, include: Optional[List[str]] = None) → Optional[dict][source]¶
Load configuration from the database
- abstract get_undo_config(context: Optional[str] = None) → Tuple[Optional[dict], Optional[int]][source]¶
Undo configuration. If a
contextis supplied, ensure that thecontextfield changes, but the other fields remain the same
- abstract get_redo_config(context: Optional[str] = None) → Tuple[Optional[dict], Optional[int]][source]¶
Redo configuration. If a
contextis supplied, ensure that thecontextfield changes, but the other fields remain the same
config¶
- class shapeflow.core.config.Factory(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.EnforcedStrAn enforced string which maps its options to types.
Included types should be subclasses of
Describedin order to generate descriptions for all options.- get() → Type[shapeflow.core.Described][source]¶
Get the type associated with the current string.
- classmethod get_str(mapped_value: Type[shapeflow.core.Described])[source]¶
Get the string for a specific type.
- property options: List[str]¶
The options for this factory.
- property descriptions: Dict[str, str]¶
The descriptions for this factory.
- property default: Optional[str]¶
The default for this factory.
- classmethod extend(key: str, extension: Type[shapeflow.core.Described])[source]¶
Add a new type to this factory. Used to dynamically add options e.g. for including plugins.
- class shapeflow.core.config.extend(factory: Type[shapeflow.core.config.Factory], key: Optional[str] = None)[source]¶
Bases:
objectDecorator to extend
Factoryclasses. Usage:from shapeflow.core.config import extend @extend(SomeFactory) class SomeClass: pass
- shapeflow.core.config.untag(d: dict) → dict[source]¶
Remove the tags from a configuration
dict- Parameters
d (dict) – Any configuration dict
- Returns
The original configuration
dictwithout class and version info- Return type
dict
- class shapeflow.core.config.BaseConfig[source]¶
Bases:
pydantic.main.BaseModel,shapeflow.core.DescribedAbstract configuration class. All other configuration classes should derive from this one.
Usage, where
SomeConfigis a subclass ofBaseConfig:# instantiating config = SomeConfig() config = SomeConfig(field1=1.0, field2='text') config = SomeConfig(**dict_with_fields_and_values) # updating config(field1=1.0, field2='text') config(**dict_with_fields_and_values) # saving dict_with_fields_and_values = config.to_dict()
When writing
BaseConfigsubclasses, use theextenddecorator to make your configuration class accessible through theConfigTypefactory. Configuration fieldsare declared as
pydantic.Fieldinstances and must be type-annotated for type resolution to work properly.Example:
from pydantic import Field from shapeflow.core.config import BaseConfig @extend(ConfigType) class SomeConfig(BaseConfig): field1: int = Field(default=42) field2: SomeNestedConfig = Field(default_factory=SomeOtherConfig)
- classmethod _resolve_enforcedstr(value, field)[source]¶
Resolve
EnforcedStrobjects from regularstrobjects. To be used inpydanticvalidators.
- classmethod _odd_add(value)[source]¶
Make sure a value stays odd by incrementing even values. To be used in
pydanticvalidators.
- classmethod _int_limits(value, field)[source]¶
Enforce
pydanticfield limits (le, lt, ge, gt) forintfields. To be used inpydanticvalidators.
- classmethod _float_limits(value, field)[source]¶
Enforce
pydanticfield limits (le, lt, ge, gt) forfloatfields. To be used inpydanticvalidators.
- class shapeflow.core.config.ConfigType(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.config.FactoryConfiguration type factory
- get() → Type[shapeflow.core.config.BaseConfig][source]¶
Return the configuration type.
- class shapeflow.core.config.Configurable[source]¶
Bases:
shapeflow.core.DescribedA class with an associated configuration type.
- _config_class¶
The configuration class as a class attribute. When subclassing, set this attribute to a specific
BaseConfigtype to associate it with this class.alias of
shapeflow.core.config.BaseConfig
- class shapeflow.core.config.Instance(config: Optional[shapeflow.core.config.BaseConfig] = None)[source]¶
interface¶
- class shapeflow.core.interface.InterfaceType(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.config.FactoryInterface type factory.
- get() → Type[shapeflow.core.config.Configurable][source]¶
Get the interface type.
- class shapeflow.core.interface.Handler[source]¶
Bases:
abc.ABCAbstract class to wrap an interface implementation and its configuration
- class shapeflow.core.interface.HandlerConfig[source]¶
Bases:
shapeflow.core.config.BaseConfig,abc.ABCAbstract handler configuration.
- type: shapeflow.core.interface.InterfaceType¶
The handler’s interface implementation.
- data: shapeflow.core.config.BaseConfig¶
The implementation’s configuration.
- class shapeflow.core.interface.TransformConfig[source]¶
Bases:
shapeflow.core.config.BaseConfigAbstract transform configuration.
- class shapeflow.core.interface.TransformInterface[source]¶
Bases:
shapeflow.core.config.ConfigurableTransform interface. Handles transforming frames based on ROI coordinates.
All transform plugins should derive from this class and implement its methods.
- abstract validate(matrix: Optional[numpy.ndarray]) → bool[source]¶
Check whether a transformation matrix is valid.
- Parameters
matrix (Optional[np.ndarray]) – A transformation matrix or
Noneif not set yet.
- abstract from_coordinates(roi: shapeflow.maths.coordinates.Roi, from_shape: tuple) → numpy.ndarray[source]¶
Make relative video-space coordinates absolute and compatible with
numpy/OpenCV.- Parameters
roi (Roi) – A region of interest in the video (in relative coordinates)
from_shape (tuple) – The dimensions of the video (in pixels)
- Returns
An array of absolute video-space coordinates
- Return type
np.ndarray
- abstract to_coordinates(to_shape: tuple) → numpy.ndarray[source]¶
Get the edges of the design in design-space coordinates
- Parameters
to_shape (tuple) – The dimensions of the design (in pixels)
- Returns
An array of absolute design-space coordinates
- Return type
np.ndarray
- abstract estimate(roi: shapeflow.maths.coordinates.Roi, from_shape: tuple, to_shape: tuple) → Optional[numpy.ndarray][source]¶
Estimate the transformation matrix from
from_coordinates()toto_coordinates()- Parameters
roi (Roi) – A region of interest in the video (in relative coordinates)
from_shape (tuple) – The dimensions of the video (in pixels)
to_shape (tuple) – The dimensions of the design (in pixels)
- Returns
The estimated transformation matrix. Returns
Noneif one of the arguments is invalid or if some other exception occurs.- Return type
Optional[np.ndarry]
- invert(matrix: Optional[numpy.ndarray]) → Optional[numpy.ndarray][source]¶
Invert a transformation matrix
- Parameters
matrix (Optional[np.ndarray]) – The transformation matrix to invert. Can be
Noneif not set yet.- Returns
The inverse transformation matrix. Returns
NoneifmatrixisNoneor if some exception occurs during inversion.- Return type
Optional[np.ndarray]
- abstract transform(matrix: numpy.ndarray, img: numpy.ndarray, shape: Tuple[int, int]) → numpy.ndarray[source]¶
Transform a frame from video-space to design-space.
- Parameters
matrix (np.ndarray) – The transformation matrix
img (np.ndarray) – The frame to transform
shape (tuple) – The shape of the design to transform to
- Returns
The transformed frame
- Return type
np.ndarray
- abstract coordinate(matrix: numpy.ndarray, coordinate: shapeflow.maths.coordinates.ShapeCoo, shape: Tuple[int, int]) → shapeflow.maths.coordinates.ShapeCoo[source]¶
Transform an (x,y) coordinate from video-space to design-space.
- class shapeflow.core.interface.FilterConfig[source]¶
Bases:
shapeflow.core.config.BaseConfigAbstract filter configuration
- property ready¶
Return true if filter can be applied ~ this configuration. Override for specific filter implementations
- class shapeflow.core.interface.FilterInterface[source]¶
Bases:
shapeflow.core.config.ConfigurableFilter interface. Handles filtering color images to binary.
All filter plugins should derive from this class and implement its methods.
- abstract set_filter(filter, color: shapeflow.maths.colors.Color) → shapeflow.core.interface.FilterConfig[source]¶
Set the filter to a specific color.
- Parameters
filter (FilterConfig) – The filter configuration
color (Color) – The color to set the filter to
- Returns
The updated filter configuration
- Return type
- abstract mean_color(filter) → shapeflow.maths.colors.Color[source]¶
Get the mean color from a filter configuration
- Parameters
filter (FilterConfig) – The filter configuration
- Returns
The configuration’s mean color
- Return type
- abstract filter(filter, image: numpy.ndarray, mask: Optional[numpy.ndarray] = None) → numpy.ndarray[source]¶
Filter a frame.
- Parameters
filter (FilterConfig) – The filter configuration
image (np.ndarray) – The frame to filter
mask (Optional[np.ndarray]) – The mask to apply to the frame
- Returns
The filtered frame
- Return type
np.ndarray
- class shapeflow.core.interface.FilterType(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.interface.InterfaceTypeFilter type factory.
- get() → Type[shapeflow.core.interface.FilterInterface][source]¶
Get the filter type.
- class shapeflow.core.interface.TransformType(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.interface.InterfaceTypeTransform type factory.
- get() → Type[shapeflow.core.interface.TransformInterface][source]¶
Get the transform type.
backend¶
- exception shapeflow.core.backend.BackendSetupError(*args)[source]¶
Bases:
shapeflow.core.RootException
- exception shapeflow.core.backend.BackendError(*args)[source]¶
Bases:
shapeflow.core.RootException
- exception shapeflow.core.backend.CacheAccessError(*args)[source]¶
Bases:
shapeflow.core.RootException
- class shapeflow.core.backend.PushEvent(value)[source]¶
Bases:
enum.EnumCategories of server-pushed events.
- class shapeflow.core.backend.AnalyzerState(value)[source]¶
Bases:
enum.IntEnumThe state of an analyzer
- class shapeflow.core.backend.QueueState(value)[source]¶
Bases:
enum.IntEnumThe state of the analysis queue
- class shapeflow.core.backend.CachingInstance(config: Optional[shapeflow.core.config.BaseConfig] = None)[source]¶
Bases:
shapeflow.core.config.InstanceCache method results with
diskcache.Cache- cached_call(method, *args, **kwargs)[source]¶
Call a method or get the result from the cache if available.
- Parameters
method – The method to call
args – Any positional arguments to pass on to the method
kwargs – Any keyword arguments to pass on to the method
- Returns
Whatever the method returns.
- Return type
Any
- class shapeflow.core.backend.FeatureConfig[source]¶
Bases:
shapeflow.core.config.BaseConfigAbstract
Featureparameters
- class shapeflow.core.backend.Feature(elements: Tuple[shapeflow.core.config.Instance, ...], global_config: shapeflow.core.backend.FeatureConfig, config: Optional[dict] = None)[source]¶
Bases:
shapeflow.core.config.ConfigurableA feature implements interactions between BackendElements to produce a certain value
- _label: str = ''¶
Label string, to be used in exported data and the user interface
- _unit: str = ''¶
Unit string, to be used in exported data and the user interface
- calculate(frame: numpy.ndarray, state: Optional[numpy.ndarray] = None) → Tuple[Any, Optional[numpy.ndarray]][source]¶
Calculate the feature for the given frame
- Parameters
frame (np.ndarray) – A video frame
state (Optional[np.ndarray]) – An
np.ndarrayfor the state image. Should have the same dimensions as theframe
- Returns
Any – The calculated feature value
Optional[np.ndarray] – If a state image was provided, return this state frame with the feature’s state frame added onto it. If not, return
None.
- classmethod label() → str[source]¶
The label of this feature. Used in the user interface and results.
- abstract property skip: bool¶
Whether this feature should be skipped
- abstract property ready: bool¶
Whether this feature is ready to be calculated
- property color: shapeflow.maths.colors.Color¶
Color of the feature in figures.
A feature’s color is handled by its
FeatureSetas not to overlap with any other features in that set.
- abstract state(frame: numpy.ndarray, state: numpy.ndarray) → numpy.ndarray[source]¶
Return the feature’s state image for a given frame
- abstract value(frame: numpy.ndarray) → Any[source]¶
Compute the value of the feature for a given frame
- property config¶
The configuration of the feature. Default to the global configuration if no specific one is provided.
- class shapeflow.core.backend.FeatureSet(features: Tuple[shapeflow.core.backend.Feature, ...])[source]¶
Bases:
shapeflow.core.config.ConfigurableA set of
Featureinstances- resolve_colors() → Tuple[shapeflow.maths.colors.Color, ...][source]¶
Resolve the colors of all features in this set so that none of them overlap.
- property colors: Tuple[shapeflow.maths.colors.Color, ...]¶
The resolved colors in this feature set
- property features: Tuple[shapeflow.core.backend.Feature, ...]¶
The features in this feature set
- calculate(frame: numpy.ndarray, state: Optional[numpy.ndarray]) → Tuple[List[Any], Optional[numpy.ndarray]][source]¶
Calculate all features in this set for a given frame
- Parameters
frame (np.ndarray) – An image
state (Optional[np.ndarray]) – An empty
np.ndarrayfor the state image. Should have the same dimensions as theframe
- Returns
List[Any] – The calculated feature values
Optional[np.ndarray] – If a state image was provided, return the composite state image of this feature set. If not, return
None.
- class shapeflow.core.backend.FeatureType(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.interface.InterfaceTypeFeaturefactory- get() → Type[shapeflow.core.backend.Feature][source]¶
Get the
Featurefor this feature type
- class shapeflow.core.backend.BaseAnalyzerConfig[source]¶
Bases:
shapeflow.core.config.BaseConfigAbstract analyzer configuration.
- class shapeflow.core.backend.BaseAnalyzer(config: Optional[shapeflow.core.backend.BaseAnalyzerConfig] = None, eventstreamer: Optional[shapeflow.core.streaming.EventStreamer] = None)[source]¶
Bases:
shapeflow.core.config.Instance,shapeflow.core.RootInstanceAbstract analyzer.
- property model¶
The database model associated with this analyzer.
- property runs¶
The number of runs performed for this analysis.
- property eventstreamer¶
Return the server-sent event streamer.
- set_eventstreamer(eventstreamer: Optional[shapeflow.core.streaming.EventStreamer] = None)[source]¶
Set the server-sent event streamer.
- event(category: shapeflow.core.backend.PushEvent, data: dict) → None[source]¶
Push an event.
- Parameters
category (PushEvent) – The category of event to push
data (dict) – The data to push
- notice(message: str, persist: bool = False) → None[source]¶
Push a notice.
- Parameters
message (str) – The notice message to push
persist (bool) – Whether the notice should be persistent (i.e. stay up on the user interface until dismissed manually)
- state_transition(push: bool = True) → int[source]¶
Handle state transitions.
shapeflow.api._VideoAnalyzerDispatcher.state_transition- Parameters
push (bool) – Whether to push an event once the state is set.
- Returns
The resulting state ~
AnalyzerState- Return type
int
- error() → None[source]¶
Sets the
_errorevent. If_errorevent doesn’t exist yet it is instantiated first.
- abstract property position: float¶
- abstract property cached: bool¶
- abstract property has_results: bool¶
- abstract set_config(config: dict, silent: bool = False) → dict[source]¶
Set the analyzer’s configuration
shapeflow.api._VideoAnalyzerDispatcher.set_config- Parameters
config (dict) – A configuration
dictsilent (bool) – If
True, don’t push server-sent events.Falseby default.
- Returns
The updated configuration
dict. Some fields may have been changed due to incompatibility.- Return type
dict
- launch() → bool[source]¶
Launch the analyzer.
shapeflow.api._VideoAnalyzerDispatcher.launchIf the analyzer’s configuration is sufficiently filled out, the analyzer will instantiate any other objects it needs to start configuring the analysis further.
To launch, the analyzer needs at least
A valid video file
A valid design file
At least one valid feature configuration
- Returns
Whether the launch was successful or not.
- Return type
bool
- class shapeflow.core.backend.AnalyzerType(string: Optional[str] = None)[source]¶
Bases:
shapeflow.core.config.FactoryAnalyzer type factory
- get() → Type[shapeflow.core.backend.BaseAnalyzer][source]¶
Return the analyzer type.
maths¶
colors¶
Some basic tools for working with colors.
For now, only 8-bit integer colors are handled.
- class shapeflow.maths.colors.Color[source]¶
Bases:
shapeflow.core.config.BaseConfigAn abstract color.
A
pydanticdata class; subclasses implementing specific colors should include their channels as three separatepydantic.Fieldattributes.- _colorspace: str = ''¶
The name of this colorspace.
- _conversion_map: Dict[str, int] = {}¶
Conversion map from this color to other colors. Maps
_colorspacestrings toOpenCVconversion method identifiers.
- property np3d: numpy.uint8¶
This color as a 3D
numpyarray. Used withOpenCVconversions and when multiplying with binary images to ‘color’ them.
- property list: List[int]¶
This color as a list.
- convert(colorspace: str) → tuple[source]¶
Convert this color to another colorspace.
- Parameters
colorspace (str) – The name of the colorspace to convert to. Will raise
NotImplementedErrorif not in_conversion_map.- Returns
The converted color as a tuple.
- Return type
tuple
- classmethod from_str(color: str) → shapeflow.maths.colors.Color[source]¶
Deserialize from a formatted string.
- class shapeflow.maths.colors.HsvColor[source]¶
Bases:
shapeflow.maths.colors.ColorHue-Saturation-Value color.
- h: int¶
- s: int¶
- v: int¶
- _colorspace: str = 'hsv'¶
The name of this colorspace.
- _conversion_map: Dict[str, int] = {'bgr': 54, 'rgb': 55}¶
Conversion map from this color to other colors. Maps
_colorspacestrings toOpenCVconversion method identifiers.
- class shapeflow.maths.colors.RgbColor[source]¶
Bases:
shapeflow.maths.colors.ColorRed-Green-Blue color.
- r: int¶
- g: int¶
- b: int¶
- _colorspace: str = 'rgb'¶
The name of this colorspace.
- _conversion_map: Dict[str, int] = {'bgr': 4, 'hsv': 41}¶
Conversion map from this color to other colors. Maps
_colorspacestrings toOpenCVconversion method identifiers.
- class shapeflow.maths.colors.BgrColor[source]¶
Bases:
shapeflow.maths.colors.ColorBlue-Green-Red color. This is the
OpenCVdefault.- b: int¶
- g: int¶
- r: int¶
- _colorspace: str = 'bgr'¶
The name of this colorspace.
- _conversion_map: Dict[str, int] = {'hsv': 40, 'rgb': 4}¶
Conversion map from this color to other colors. Maps
_colorspacestrings toOpenCVconversion method identifiers.
- shapeflow.maths.colors.convert(color: shapeflow.maths.colors.Color, to: Type[shapeflow.maths.colors.Color]) → shapeflow.maths.colors.Color[source]¶
- shapeflow.maths.colors.as_hsv(color: shapeflow.maths.colors.Color) → shapeflow.maths.colors.HsvColor[source]¶
Convert a color to HSV.
- shapeflow.maths.colors.as_bgr(color: shapeflow.maths.colors.Color) → shapeflow.maths.colors.BgrColor[source]¶
Convert a color to BGR.
- shapeflow.maths.colors.as_rgb(color: shapeflow.maths.colors.Color) → shapeflow.maths.colors.RgbColor[source]¶
Convert a color to RGB.
- shapeflow.maths.colors.complementary(color: shapeflow.maths.colors.Color) → shapeflow.maths.colors.Color[source]¶
Get the complementary of a color. Takes a shortcut through HSV.
- shapeflow.maths.colors.css_hex(color: shapeflow.maths.colors.Color) → str[source]¶
Get the color as a CSS-compatible hex RGB string:
>>> css_hex(RgbColor(r=170,g=187,b=204)) "#aabbcc"
coordinates¶
Some basic tools for working with coordinates.
- class shapeflow.maths.coordinates.Coo[source]¶
Bases:
shapeflow.core.config.BaseConfigCoordinates of a point on a 2D image. Relative, and thus independent of the size of the image.
- x: float¶
The x-coordinate.
- y: float¶
The y coordinate.
- property rel: Tuple[float, float]¶
Get the relative coordinates.
- property list: list¶
Get the relative coordinates as a list.
- class shapeflow.maths.coordinates.ShapeCoo[source]¶
Bases:
shapeflow.maths.coordinates.CooCoordinates of a point on a 2D image with a known size.
- shape: Tuple[int, int]¶
The size of the image, from
numpy.ndarray.shape.
- property abs: Tuple[float, float]¶
Get the absolute coordinates.
- property idx: Tuple[int, int]¶
Get (approximate) array indices ~ the absolute coordinate.
- property cv2¶
Get the absolute coordinates for
OpenCV.Note
The order is flipped with respect to
abs()
- class shapeflow.maths.coordinates.Roi[source]¶
Bases:
shapeflow.core.config.BaseConfigA rectangular region of interest, composed of four points as
Cooobjects.- BL: shapeflow.maths.coordinates.Coo¶
The bottom-left corner.
- TL: shapeflow.maths.coordinates.Coo¶
The top-left corner.
- TR: shapeflow.maths.coordinates.Coo¶
The top-right corner.
- BR: shapeflow.maths.coordinates.Coo¶
The bottom-right corner.
images¶
Some basic tools for working with images.
- shapeflow.maths.images.ckernel(size: int) → numpy.ndarray[source]¶
Circular/disk kernel.
- Parameters
size (int) – The size or diameter of the kernel. Should be odd; if an even value is supplied, it will be decremented.
- Returns
A disk kernel as a
numpyarray- Return type
np.ndarray
- shapeflow.maths.images.overlay(frame: numpy.ndarray, overlay: numpy.ndarray, alpha: float = 0.5) → numpy.ndarray[source]¶
Overlay frame image with overlay image. Both images should be in the BGR color space.
- shapeflow.maths.images.crop_mask(mask: numpy.ndarray) → Tuple[numpy.ndarray, numpy.ndarray, Tuple[int, int]][source]¶
Crop a binary mask image array to its minimal (rectangular) size to exclude unnecessary regions.
- shapeflow.maths.images.rect_contains(rect: numpy.ndarray, point: shapeflow.maths.coordinates.ShapeCoo) → bool[source]¶
Check whether a point is contained in a rectangle.
- Parameters
rect (np.ndarray) – An ‘array rectangle’: [first_row, last_row, first_column, last_column]
point (ShapeCoo) – A point on a 2D image with known size
- Returns
Whether the point is contained in the rectangle or not.
- Return type
bool
- shapeflow.maths.images.mask(image: numpy.ndarray, mask: numpy.ndarray, rect: numpy.ndarray) → numpy.ndarray[source]¶
Mask and crop off a part of an image.
- Parameters
image (np.ndarray) – The original image
mask (np.ndarray) – The mask. Should be an
OpenCV-compatible binary image, withFalse -> 0andTrue -> 255rect (np.ndarray) – An ‘array rectangle’: [first_row, last_row, first_column, last_column]. Should correspond to the position of the mask in the original image.
- Returns
The image cropped by
rectand masked bymask- Return type
np.ndarray
- shapeflow.maths.images.area_pixelsum(image: Optional[numpy.ndarray]) → Optional[int][source]¶
Get the total number of
Truepixels in a binary image.- Parameters
image (np.ndarray) – An
OpenCV-compatible binary image, withFalse -> 0andTrue -> 255.- Returns
The number of
255pixels in the image- Return type
int
- shapeflow.maths.images.to_mask(image: numpy.ndarray, kernel: Optional[numpy.ndarray] = None) → numpy.ndarray[source]¶
Convert a PNG image to a binary mask array.
- Parameters
image (np.ndarray) – A
numpyarray representing a full-color PNG image without transparencykernel (Optional[np.ndarray]) – A smoothing kernel. If set to
None, defaults to ackernel()of size 7.
design¶
Design file handling
Adapted from https://github.com/ybnd/OnionSVG
- shapeflow.design.check_design(file: Union[pathlib.Path, str]) → None[source]¶
Check whether the file is a valid design file.
- Parameters
file (Path) – Any file
- Raises
SvgError – If the file can’t be read or parsed
- shapeflow.design.peel(file: Union[pathlib.Path, str], dpi: int, dir: Union[pathlib.Path, str]) → None[source]¶
Render a design layer per layer
- Parameters
file –
dpi –
dir –
onions¶
- exception shapeflow.design.onions.DesignFileError(*args)[source]¶
Bases:
shapeflow.core.RootException
- class shapeflow.design.onions.Layer(root: lxml.etree._Element, label: str)[source]¶
Bases:
objectRepresents a layer within an SVG file
- property label¶
- class shapeflow.design.onions.Peeler(file: pathlib.Path)[source]¶
Bases:
objectRenders an SVG file into multiple PNG files layer-per-layer.
- G = '{http://www.w3.org/2000/svg}g'¶
- LABEL = '{http://www.inkscape.org/namespaces/inkscape}label'¶
- NAMEDVIEW = '{http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd}namedview'¶
- BG_COLOR = 'pagecolor'¶
- BG_OPACITY = '{http://www.inkscape.org/namespaces/inkscape}pageopacity'¶
- file: pathlib.Path¶
Path to the SVG file
render¶
- exception shapeflow.design.render.RendererError(*args)[source]¶
Bases:
shapeflow.core.RootException
- class shapeflow.design.render.Renderer[source]¶
Bases:
objectRenders SVG (as an XML string) to a PNG image. Multiple implementations are provided as a fallback for Windows systems where cairo may be unavailable.
Transparency is handled after importing PNG ~ OpenCV; SVGs are rendered with a white background. The background color of the original SVG file is ignored. Moreover, it’s no longer required to include a “hardcoded” background layer. Layers labelled with _* are ignored for backwards compatibility with legacy design files.
- save(svg: bytes, dpi: int, to: pathlib.Path) → None[source]¶
Save an SVG string to a PNG image. Checks whether this renderer works on the current system before trying.
- Parameters
svg (str) – An SVG image as an XML string
dpi (int) – The DPI (details per inch) to render the SVG at
to (Path) – The file to save to
- property works: bool¶
- class shapeflow.design.render.CairoRenderer[source]¶
Bases:
shapeflow.design.render.RendererFirst-choice renderer: fastest, cleanest interface.
Requires the Python package
cairosvgto be installed, which in turn depends oncairo.Installing
cairoInstalling
cairosvg- DEFAULT_DPI: int = 96¶
- WHITE: str = '#ffffff'¶
- cairosvg: Any¶
- class shapeflow.design.render.WandRenderer[source]¶
Bases:
shapeflow.design.render.RendererSecond-choice renderer: slower, but still a clean interface.
Requires the Python package
Wandto be installed, which in turn depends on ImageMagick.Installing
ImageMagickInstalling
Wand- Image: Any¶
- background: Any¶
- class shapeflow.design.render.InkscapeRenderer[source]¶
Bases:
shapeflow.design.render.RendererFallback renderer: it works, but is hacky and bad.
Requires Inkscape to be installed.
- shell: bool = False¶
- class shapeflow.design.render.WindowsInkscapeRenderer[source]¶
Bases:
shapeflow.design.render.InkscapeRendererFallback renderer for Windows: it works, but is hacky and bad.
Requires Inkscape to be installed.
- INKSCAPE_DIR_CANDIDATES: List[pathlib.Path] = [PosixPath('C:\\Program Files (x86)\\Inkscape\\bin'), PosixPath('C:\\Program Files\\Inkscape\\bin')]¶
- inkscape_dir: pathlib.Path¶
- shell: bool = False¶
- shapeflow.design.render.save_svg(svg: bytes, dpi: int, to: pathlib.Path) → None[source]¶
Save SVG to a PNG image using the renderer selected for this system.
- Parameters
svg (bytes) – An SVG image as XML bytes
dpi (int) – The DPI (dots per inch) to render the SVG at
to (Path) – Where to save the PNG image
- Raises
RendererError – if none of the available renderers work on this system
plugins¶
Transforms¶
PerspectiveTransform¶
- class shapeflow.plugins.PerspectiveTransform._Transform[source]¶
Bases:
shapeflow.core.interface.TransformInterfaceWraps
OpenCV’s getPerspectiveTransform function to estimate the transformation matrix and warpPerspective to apply it to a video frame or a coordinate.- validate(matrix: Optional[numpy.ndarray]) → bool[source]¶
Check whether a transformation matrix is valid.
- Parameters
matrix (Optional[np.ndarray]) – A transformation matrix or
Noneif not set yet.
- from_coordinates(roi: shapeflow.maths.coordinates.Roi, from_shape: tuple) → numpy.ndarray[source]¶
Make relative video-space coordinates absolute and compatible with
numpy/OpenCV.- Parameters
roi (Roi) – A region of interest in the video (in relative coordinates)
from_shape (tuple) – The dimensions of the video (in pixels)
- Returns
An array of absolute video-space coordinates
- Return type
np.ndarray
- to_coordinates(to_shape: tuple) → numpy.ndarray[source]¶
Get the edges of the design in design-space coordinates
- Parameters
to_shape (tuple) – The dimensions of the design (in pixels)
- Returns
An array of absolute design-space coordinates
- Return type
np.ndarray
- estimate(roi: shapeflow.maths.coordinates.Roi, from_shape: tuple, to_shape: tuple) → Optional[numpy.ndarray][source]¶
Estimate the transformation matrix from
from_coordinates()toto_coordinates()- Parameters
roi (Roi) – A region of interest in the video (in relative coordinates)
from_shape (tuple) – The dimensions of the video (in pixels)
to_shape (tuple) – The dimensions of the design (in pixels)
- Returns
The estimated transformation matrix. Returns
Noneif one of the arguments is invalid or if some other exception occurs.- Return type
Optional[np.ndarry]
- transform(matrix: numpy.ndarray, img: numpy.ndarray, shape: tuple) → numpy.ndarray[source]¶
Transform a frame from video-space to design-space.
- Parameters
matrix (np.ndarray) – The transformation matrix
img (np.ndarray) – The frame to transform
shape (tuple) – The shape of the design to transform to
- Returns
The transformed frame
- Return type
np.ndarray
- coordinate(inverse: numpy.ndarray, coordinate: shapeflow.maths.coordinates.ShapeCoo, shape: Tuple[int, int]) → shapeflow.maths.coordinates.ShapeCoo[source]¶
Transform an (x,y) coordinate from video-space to design-space.
Filters¶
HsvRangeFilter¶
- class shapeflow.plugins.HsvRangeFilter._Config[source]¶
Bases:
shapeflow.core.interface.FilterConfigConfiguration for
shapeflow.plugins.HsvRangeFilter._Filter- color: shapeflow.maths.colors.HsvColor¶
The center color.
- range: shapeflow.maths.colors.HsvColor¶
The range around the center color.
The default setting of
HsvColor(h=10,s=75,v=75)works well for most cases, but if you notice false positive or false negative regions you can try adjusting the range.Mixing or separating colors can be handled by increasing the
hvalue (allowing more hues through) and uneven lighting/shadows can be compensated for by increasing thevvalue (lightness of the color).
- close: int¶
Kernel size (circular) of a morphological closing operation.
If
closeis set to 0 (the default), no closing will be performed. This attribute will be coerced to an odd integer below 200 in order to keep performance somewhat reasonable.You may want to configure a higher
closeif you notice that the state image of the corresponding frame includes noise (small objects or colored pixels) outside of its main area.
- open: int¶
Kernel size (circular) of a morphological opening operation.
If
openis set to 0 (the default), no opening will be performed. This attribute will be coerced to an odd integer below 200 in order to keep performance somewhat reasonable.You may want to configure a higher
openif you notice that the state image of the corresponding frame includes noise (small ‘holes’ or non-colored pixels) inside of its main area.
- property ready: bool¶
Return true if filter can be applied ~ this configuration. Override for specific filter implementations
- property c0: shapeflow.maths.colors.HsvColor¶
The center color minus the range.
- property c1: shapeflow.maths.colors.HsvColor¶
The center color plus the range.
- class shapeflow.plugins.HsvRangeFilter._Filter[source]¶
Bases:
shapeflow.core.interface.FilterInterfaceFilters out colors outside of a
HsvColorradius around a center color.- set_filter(filter: shapeflow.plugins.HsvRangeFilter._Config, color: shapeflow.maths.colors.Color) → shapeflow.plugins.HsvRangeFilter._Config[source]¶
Set the filter to a specific color.
- Parameters
filter (FilterConfig) – The filter configuration
color (Color) – The color to set the filter to
- Returns
The updated filter configuration
- Return type
- mean_color(filter: shapeflow.plugins.HsvRangeFilter._Config) → shapeflow.maths.colors.Color[source]¶
Get the mean color from a filter configuration
- Parameters
filter (FilterConfig) – The filter configuration
- Returns
The configuration’s mean color
- Return type
- filter(filter: shapeflow.plugins.HsvRangeFilter._Config, img: numpy.ndarray, mask: Optional[numpy.ndarray] = None) → numpy.ndarray[source]¶
Filter a frame.
- Parameters
filter (FilterConfig) – The filter configuration
image (np.ndarray) – The frame to filter
mask (Optional[np.ndarray]) – The mask to apply to the frame
- Returns
The filtered frame
- Return type
np.ndarray
BackgroundFilter¶
- class shapeflow.plugins.BackgroundFilter._Config[source]¶
Bases:
shapeflow.core.interface.FilterConfigConfiguration for
shapeflow.plugins.BackgroundFilter._Filter- property ready: bool¶
Return true if filter can be applied ~ this configuration. Override for specific filter implementations
- property c0: shapeflow.maths.colors.HsvColor¶
- property c1: shapeflow.maths.colors.HsvColor¶
- class shapeflow.plugins.BackgroundFilter._Filter[source]¶
Bases:
shapeflow.core.interface.FilterInterfaceFilters out colors outside of a
HsvColorradius around a center color and inverts the resulting image.- set_filter(filter: shapeflow.plugins.BackgroundFilter._Config, color: shapeflow.maths.colors.Color) → shapeflow.plugins.BackgroundFilter._Config[source]¶
Set the filter to a specific color.
- Parameters
filter (FilterConfig) – The filter configuration
color (Color) – The color to set the filter to
- Returns
The updated filter configuration
- Return type
- mean_color(filter: shapeflow.plugins.BackgroundFilter._Config) → shapeflow.maths.colors.Color[source]¶
Get the mean color from a filter configuration
- Parameters
filter (FilterConfig) – The filter configuration
- Returns
The configuration’s mean color
- Return type
- filter(filter: shapeflow.plugins.BackgroundFilter._Config, img: numpy.ndarray, mask: Optional[numpy.ndarray] = None) → numpy.ndarray[source]¶
Filter a frame.
- Parameters
filter (FilterConfig) – The filter configuration
image (np.ndarray) – The frame to filter
mask (Optional[np.ndarray]) – The mask to apply to the frame
- Returns
The filtered frame
- Return type
np.ndarray
Features¶
PixelSum¶
- class shapeflow.plugins.PixelSum._Feature(mask: shapeflow.video.Mask, global_config: shapeflow.core.backend.FeatureConfig, config: Optional[dict] = None)[source]¶
Bases:
shapeflow.video.MaskFunctionThe most basic feature: it just returns the number of
Truepixels the filtered frame.
Area_mm2¶
- class shapeflow.plugins.Area_mm2._Feature(mask: shapeflow.video.Mask, global_config: shapeflow.core.backend.FeatureConfig, config: Optional[dict] = None)[source]¶
Bases:
shapeflow.video.MaskFunctionConvert
PixelSumto an area in mm², taking into account the DPI of the design file.
Volume_uL¶
- class shapeflow.plugins.Volume_uL._Config[source]¶
Bases:
shapeflow.core.backend.FeatureConfigConfiguration for
shapeflow.plugins.Volume_uL._Feature- h: float¶
The channel height of the chip.
- class shapeflow.plugins.Volume_uL._Feature(mask: shapeflow.video.Mask, global_config: shapeflow.core.backend.FeatureConfig, config: Optional[dict] = None)[source]¶
Bases:
shapeflow.video.MaskFunctionMultiply
Area_mm2by a channel height in mm to estimate the volume in µL.
api¶
- class shapeflow.api._VideoAnalyzerDispatcher(instance: Optional[object] = None)[source]¶
Bases:
shapeflow.core.DispatcherDispatches
/api/va/<id>/<endpoint>- status = <shapeflow.core.Endpoint object>¶
Get the analyzer’s status
- state_transition = <shapeflow.core.Endpoint object>¶
Trigger a state transition
- can_launch = <shapeflow.core.Endpoint object>¶
Returns
Trueif the analyzer has enough of its configuration set up to launch
- can_analyze = <shapeflow.core.Endpoint object>¶
Returns
Trueif the analyzer has enough of its configuration set up to analyze
- launch = <shapeflow.core.Endpoint object>¶
Launch the analyzer
- commit = <shapeflow.core.Endpoint object>¶
Commit the analyzer to the database
- analyze = <shapeflow.core.Endpoint object>¶
Run an analysis
- cancel = <shapeflow.core.Endpoint object>¶
Cancel an analysis
- get_config = <shapeflow.core.Endpoint object>¶
Return the analyzer’s configuration
- set_config = <shapeflow.core.Endpoint object>¶
Set the analyzer’s configuration
- undo_config = <shapeflow.core.Endpoint object>¶
Undo the latest change to the analyzer’s configuration
- redo_config = <shapeflow.core.Endpoint object>¶
Redo the latest undone change to the analyzer’s configuration
- estimate_transform = <shapeflow.core.Endpoint object>¶
Estimate a transform based on the provided ROI
- turn_cw = <shapeflow.core.Endpoint object>¶
Turn the ROI clockwise
- turn_ccw = <shapeflow.core.Endpoint object>¶
Turn the ROI counter-clockwise
- flip_h = <shapeflow.core.Endpoint object>¶
Flip the ROI horizontally
- flip_v = <shapeflow.core.Endpoint object>¶
Flip the ROI vertically
- clear_roi = <shapeflow.core.Endpoint object>¶
Clear the ROI
- get_overlay_png = <shapeflow.core.Endpoint object>¶
Return the overlay image
- get_frame = <shapeflow.core.Endpoint object>¶
Return the transformed frame at the provided frame number (or the current frame number if
None)
- set_filter_click = <shapeflow.core.Endpoint object>¶
Configure a filter based on a click position (in ROI-relative coordinates)
- get_inverse_transformed_overlay = <shapeflow.core.Endpoint object>¶
Return the inverse transformed overlay image
shapeflow.video.VideoAnalyzer.get_inverse_transformed_overlay()
- get_inverse_overlaid_frame = <shapeflow.core.Endpoint object>¶
Return the inverse overlaid frame at the provided frame number (or the current frame number if
None)
- get_state_frame = <shapeflow.core.Endpoint object>¶
Return the state frame at the provided frame number (or the current frame number if
None)
- get_colors = <shapeflow.core.Endpoint object>¶
Return the color list
- get_db_id = <shapeflow.core.Endpoint object>¶
Return the database ID associated with this analyzer
- clear_filters = <shapeflow.core.Endpoint object>¶
Clear all filter configuration
- seek = <shapeflow.core.Endpoint object>¶
Seek to the provided position (relative, 0-1)
- get_relative_roi = <shapeflow.core.Endpoint object>¶
Return the current ROI in relative coordinates
- get_coordinates = <shapeflow.core.Endpoint object>¶
Return the current relative coordinates
- get_time = <shapeflow.core.Endpoint object>¶
Return the current time in the video in seconds
- get_total_time = <shapeflow.core.Endpoint object>¶
Return the total time of the video file in seconds
- get_fps = <shapeflow.core.Endpoint object>¶
Return the framerate of the video file
- get_raw_frame = <shapeflow.core.Endpoint object>¶
Return the raw frame at the provided frame number (or the current frame number if
None)
- get_seek_position = <shapeflow.core.Endpoint object>¶
Return the current seek position (relative, 0-1)
- class shapeflow.api._VideoAnalyzerManagerDispatcher(instance: Optional[object] = None)[source]¶
Bases:
shapeflow.core.DispatcherDispatches
/api/va/<endpoint>, active analyzers are handled by dispatchers at/api/va/<id>- init = <shapeflow.core.Endpoint object>¶
Initialize a new analyzer
- close = <shapeflow.core.Endpoint object>¶
Close an analyzer
- start = <shapeflow.core.Endpoint object>¶
Start analyzing the queue provided as a list of ID strings
- stop = <shapeflow.core.Endpoint object>¶
Stop the queue
- cancel = <shapeflow.core.Endpoint object>¶
Cancel the queue
- state = <shapeflow.core.Endpoint object>¶
Return the application state
- save_state = <shapeflow.core.Endpoint object>¶
Save the application state to disk
- load_state = <shapeflow.core.Endpoint object>¶
Load the application state from disk
- stream = <shapeflow.core.Endpoint object>¶
Open a new stream for a given analyzer ID and endpoint
- stream_stop = <shapeflow.core.Endpoint object>¶
Close the stream for a given analyzer ID and endpoint
- class shapeflow.api._DatabaseDispatcher(instance: Optional[object] = None)[source]¶
Bases:
shapeflow.core.DispatcherDispatches
/api/db/<endpoint>- get_recent_paths = <shapeflow.core.Endpoint object>¶
Get a list of recent video and design files
- get_result_list = <shapeflow.core.Endpoint object>¶
Get a list of result IDs for a given analyzer ID
- get_result = <shapeflow.core.Endpoint object>¶
Get the result for a given analyzer ID and result ID
- export_result = <shapeflow.core.Endpoint object>¶
Export the result for a given analyzer ID and result ID
- clean = <shapeflow.core.Endpoint object>¶
Clean the database
- forget = <shapeflow.core.Endpoint object>¶
Remove all entries from the database
- class shapeflow.api._FilesystemDispatcher(instance: Optional[object] = None)[source]¶
Bases:
shapeflow.core.DispatcherDispatches
/api/fs/<endpoint>- select_video = <shapeflow.core.Endpoint object>¶
Open a dialog to select a video file
- select_design = <shapeflow.core.Endpoint object>¶
Open a dialog to select a design file
- check_video = <shapeflow.core.Endpoint object>¶
Check whether the given video file is valid
- check_design = <shapeflow.core.Endpoint object>¶
Check whether the given video file is valid
- open_root = <shapeflow.core.Endpoint object>¶
Open the application’s root directory in a file explorer window
- class shapeflow.api._CacheDispatcher(instance: Optional[object] = None)[source]¶
Bases:
shapeflow.core.DispatcherDispatches
/api/cache/<endpoint>- clear = <shapeflow.core.Endpoint object>¶
Clear the cache
shapeflow.main._cache.clear()
- size = <shapeflow.core.Endpoint object>¶
Get the size of the cache on disk
shapeflow.main._Cache.size()
- class shapeflow.api.ApiDispatcher(instance: Optional[object] = None)[source]¶
Bases:
shapeflow.core.DispatcherInvoked by
Flaskserver for requests to/api/- ping = <shapeflow.core.Endpoint object>¶
Ping the backend
- map = <shapeflow.core.Endpoint object>¶
Get API map
- schemas = <shapeflow.core.Endpoint object>¶
Get all schemas
- normalize_config = <shapeflow.core.Endpoint object>¶
Normalize the given config to the current version of the application
- get_settings = <shapeflow.core.Endpoint object>¶
Get the application settings
- set_settings = <shapeflow.core.Endpoint object>¶
Set the application settings
- events = <shapeflow.core.Endpoint object>¶
Open an event stream
- stop_events = <shapeflow.core.Endpoint object>¶
Stop the event stream
- log = <shapeflow.core.Endpoint object>¶
Open a log stream
- stop_log = <shapeflow.core.Endpoint object>¶
Stop the log stream
- unload = <shapeflow.core.Endpoint object>¶
Unload the application. In order to support page reloading, the backend will wait for some time and quit if no further requests come in.
- quit = <shapeflow.core.Endpoint object>¶
Quit without waiting for incoming requests
- restart = <shapeflow.core.Endpoint object>¶
Restart the server
- pid_hash = <shapeflow.core.Endpoint object>¶
Get the hashed process ID. Used to confirm server restart without exposing the actual PID.
- fs = <shapeflow.api._FilesystemDispatcher object>¶
Nested
_FilesystemDispatcher
- db = <shapeflow.api._DatabaseDispatcher object>¶
Nested
_DatabaseDispatcher
- va = <shapeflow.api._VideoAnalyzerManagerDispatcher object>¶
- cache = <shapeflow.api._CacheDispatcher object>¶
Nested
_CacheDispatcher
- shapeflow.api.api = <shapeflow.api.ApiDispatcher object>¶
Global
ApiDispatcherinstance. Endpoints should be exposed against this object. API calls should be dispatched from this object.URLs match object structure:
"/api/va/abc123/analyze"is equivalent toapi.va.abc123.analyze.
- _VideoAnalyzerManagerDispatcher.__id__ = <shapeflow.api._VideoAnalyzerDispatcher object>¶
Prototype
_VideoAnalyzerDispatcherinstance.Endpointinstances exposed against this object will be propagated to all analyzers and bound to their respective instances.
config¶
- class shapeflow.config.TransformHandlerConfig[source]¶
Bases:
shapeflow.core.interface.HandlerConfigTransform handler configuration
- roi: Optional[shapeflow.maths.coordinates.Roi]¶
The region of interest (ROI).
This is the position of the chip in the video in relative coordinates with respect to its resolution.
- flip: shapeflow.config.FlipConfig¶
Flip the selected ROI horizontally/vertically before estimating the transform
- turn: int¶
Turn the ROI a number of clockwise 90° turns before estimating the transform
- class shapeflow.config.FilterHandlerConfig[source]¶
Bases:
shapeflow.core.interface.HandlerConfigFilter handler configuration
- class shapeflow.config.MaskConfig[source]¶
Bases:
shapeflow.core.config.BaseConfigMask configuration
- name: str¶
The name of this mask.
Taken from the name of its layer in the design file.
- skip: bool¶
Whether to skip this mask when analyzing
- filter: shapeflow.config.FilterHandlerConfig¶
Filter configuration for this mask.
- parameters: Tuple[Any, ...]¶
Feature parameter overrides for this mask.
If
None, the global feature parameters are used when computing the feature value.
- property ready¶
Whether this mask is ready to be analyzed
- class shapeflow.config.DesignFileHandlerConfig[source]¶
Bases:
shapeflow.core.config.BaseConfigDesign file handler configuration
- dpi: int¶
The details per inch (DPI) at which to render the design
- overlay_alpha: float¶
Transparency of the overlay
- smoothing: int¶
The smoothing kernel size used when generating masks from renders
- class shapeflow.config.VideoAnalyzerConfig[source]¶
Bases:
shapeflow.core.backend.BaseAnalyzerConfigVideo analyzer configuration
- frame_interval_setting: shapeflow.config.FrameIntervalSetting¶
Determines which parameter to use when requesting a set of frames to analyze.
Nf: requestshapeflow.video.VideoAnalyzerConfig.Nfframes in totaldt: request a frame every secondsshapeflow.video.VideoAnalyzerConfig.dtseconds
- dt: Optional[float]¶
Frame interval in seconds
- Nf: Optional[int]¶
Total number of frames
- video: shapeflow.config.VideoFileHandlerConfig¶
Video file handler configuration
- design: shapeflow.config.DesignFileHandlerConfig¶
Design file handler configuration
- transform: shapeflow.config.TransformHandlerConfig¶
Transform handler configuration
- features: Tuple[shapeflow.core.backend.FeatureType, ...]¶
The features to extract
- feature_parameters: Tuple[shapeflow.core.backend.FeatureConfig, ...]¶
The feature parameters to use
- masks: Tuple[shapeflow.config.MaskConfig, ...]¶
Mask configuration
- shapeflow.config.schemas() → Dict[str, dict][source]¶
Get the JSON schemas of
shapeflow.video.VideoAnalyzerConfig
- shapeflow.config.loads(config: str) → shapeflow.core.config.BaseConfig[source]¶
Load a configuration object from a JSON string.
- Parameters
config (str) – JSON string configuration
- Returns
A configuration object
- Return type
- shapeflow.config.normalize_config(d: dict) → dict[source]¶
Normalize a configuration dictionary to match the current
__version__- Parameters
d (dict) – A configuration
dict- Returns
A normalized configuration
dict- Return type
dict
db¶
- class shapeflow.db.VideoFileModel(path)[source]¶
Bases:
shapeflow.core.db.FileModelDatabase model of a video file.
- resolve() → shapeflow.db.VideoFileModel[source]¶
Resolve the file by its SHA1 hash ~
hash_file().If the computed hash is new, the file is committed to the database. Otherwise, the original entry is re-used.
- Returns
The current instance if the file is new, or a new
FileModelinstance representing the original database entry.- Return type
- class shapeflow.db.DesignFileModel(path)[source]¶
Bases:
shapeflow.core.db.FileModelDatabase model of a design file.
- resolve() → shapeflow.db.DesignFileModel[source]¶
Resolve the file by its SHA1 hash ~
hash_file().If the computed hash is new, the file is committed to the database. Otherwise, the original entry is re-used.
- Returns
The current instance if the file is new, or a new
FileModelinstance representing the original database entry.- Return type
- class shapeflow.db.ConfigModel(**kwargs)[source]¶
Bases:
shapeflow.core.db.DbModelDatabase model of a configuration.
- class shapeflow.db.ResultModel(**kwargs)[source]¶
Bases:
shapeflow.core.db.DbModelDatabase model of a result.
- feature¶
The feature that was analyzed
- data¶
Results of the analysis. In JSON, formatted ~
pandas.DataFrame.to_json(orient='split')
- class shapeflow.db.AnalysisModel(*args, **kwargs)[source]¶
Bases:
shapeflow.core.db.BaseAnalysisModelDatabase model of an analysis.
Contains a reference to a
BaseAnalyzerinstance.- get_name() → str[source]¶
- Returns
Name of the analysis from the database. Empty names are reset to ‘#{id}’
- Return type
str
- store()[source]¶
Store analysis information from the
BaseAnalyzerto the database.
- export_result(run: Optional[int] = None, manual: bool = False)[source]¶
Export a result to disk
- Parameters
run (int) – The run to export
manual (bool) – Whether this export request is manual (i.e. explicitly requested by the user). This setting determines whether to follow
settings.app.save_result_manualorsettings.app.save_result_autowhen choosing where or whether to actually save.
- load_config(video_path: Optional[str] = None, design_path: Optional[str] = None, include: Optional[List[str]] = None) → Optional[dict][source]¶
Load configuration from the database.
- Parameters
video_path (str) – Path to video file
design_path (str) – Path to design file
include (List[str]) – List of fields which must be included in the configuration. If a matching ConfigModel doesn’t provide all of these, the other matches will be parsed to complete it.
- Returns
Configuration dict, if a matching config is found. Otherwise, returns
None- Return type
dict
- get_undo_config(context: Optional[str] = None) → Tuple[Optional[dict], Optional[int]][source]¶
Undo configuration. If a
contextis supplied, ensure that thecontextfield changes, but the other fields remain the same- Parameters
context (str) – Name of a
VideoAnalyzerConfigfield- Raises
ValueError – If
contextis not aVideoAnalyzerfield
- get_redo_config(context: Optional[str] = None) → Tuple[Optional[dict], Optional[int]][source]¶
Redo configuration. If a
contextis supplied, ensure that thecontextfield changes, but the other fields remain the same- Parameters
context (str) – Name of a
VideoAnalyzerConfigfield- Raises
ValueError – If
contextis not aVideoAnalyzerfield
- class shapeflow.db.History(path: Optional[pathlib.Path] = None)[source]¶
Bases:
shapeflow.core.db.SessionWrapper,shapeflow.core.RootInstanceInterface to the history database
- add_video_file(path: str) → shapeflow.db.VideoFileModel[source]¶
Add a video file to the database. Duplicate files are resolved to their original entry.
- Parameters
path (str) – The path of the file to add
- Returns
A database model of the file. Will reference the original entry if the user tried to add a previously used file again.
- Return type
- add_design_file(path: str) → shapeflow.db.DesignFileModel[source]¶
Add a design file to the database. Duplicate files are resolved to their original entry.
- Parameters
path (str) – The path of the file to add
- Returns
A database model of the file. Will reference the original entry if the user tried to add a previously used file again.
- Return type
- add_analysis(analyzer: shapeflow.core.backend.BaseAnalyzer, model: Optional[shapeflow.db.AnalysisModel] = None) → shapeflow.db.AnalysisModel[source]¶
Add a new analysis to the database.
- Parameters
analyzer (BaseAnalyzer) – The analyzer object to add to the database
model (AnalysisModel) – Optionally, an existing model can be specified. Defaults to
None
- Returns
If a
modelis provided, no newAnalysisModelwill be created and theanalyzerwill be linked to the existingmodelinstead.- Return type
- fetch_analysis(id: int) → Optional[shapeflow.db.AnalysisModel][source]¶
Fetch an analysis model from the database.
- Parameters
id (int) – Database id of the analysis to fetch
- get_paths() → Dict[str, List[str]][source]¶
Fetch the latest video and design file paths from the database.
shapeflow.api._DatabaseDispatcher.get_recent_pathsNumber of paths is limited by
settings.app.recent_files
- get_result_list(analysis: int) → dict[source]¶
Fetch the result list for a given analysis
shapeflow.api._DatabaseDispatcher.get_result_list- Parameters
analysis (int) – Database id of the analysis
- Returns
A
dictmapping run idintto result idint- Return type
dict
- get_result(analysis: int, run: int) → dict[source]¶
Fetch the result for a given analysis and run
shapeflow.api._DatabaseDispatcher.get_result- Parameters
analysis (int) – Database id of the analysis
run (int) – Run number of the result to fetch
- Returns
Analysis results, as a
dictformatted ~pandas.DataFrame.to_json(orient='split')- Return type
dict
- export_result(analysis: int, run: Optional[int] = None) → bool[source]¶
Export the result for a given analysis and run
shapeflow.api._DatabaseDispatcher.export_result- Parameters
analysis (int) – Database id of the analysis
run (int) – Run number of the result to fetch
- Returns
Trueif exported,Falseif something went wrong.- Return type
bool
- check() → bool[source]¶
Check the database’s integrity (somewhat). Makes sure that the required tables exist and that their columns match.
- Returns
Trueif everything’s fine,Falseif the database is messed up- Return type
bool
- clean() → None[source]¶
Clean the database.
shapeflow.api._DatabaseDispatcher.cleanremove ‘video_file & ‘design_file’ entries with <null> path
resolve entries with
<null>hash
remove ‘analysis’ entries with
<null>configremove ‘config’ entries with
<null>jsonfor ‘analysis’ entries older than
settings.db.cleanup_intervalremove all non-primary ‘config’ entries
remove all non-primary ‘results’ entries
video¶
- class shapeflow.video.VideoFileHandler(video_path, config: Optional[shapeflow.config.VideoFileHandlerConfig] = None)[source]¶
Bases:
shapeflow.core.backend.CachingInstance,shapeflow.core.LockableInterface to video files ~
OpenCV- path: str¶
Path to the video file
- set_requested_frames(requested_frames: List[int]) → None[source]¶
Add a list of requested frames
Limiting the set of possible frames decreases the disk space cost needed to get a performance advantage through caching.
- read_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]¶
Read a frame from
cv2.VideoCapture.
- exception shapeflow.video.NotEstimatedYet(*args)[source]¶
Bases:
shapeflow.core.RootException
- class shapeflow.video.TransformHandler(video_shape, design_shape, config: shapeflow.config.TransformHandlerConfig)[source]¶
Bases:
shapeflow.core.config.Instance,shapeflow.core.interface.HandlerHandles coordinate transforms
- property is_set: bool¶
Whether the transform matrix is set
- estimate(roi: Optional[shapeflow.maths.coordinates.Roi] = None) → None[source]¶
Estimate the transform matrix from a set of coordinates.
Coordinates should correspond to the corners of the outline of the design, relative to the video frame size: * x in [0,1] ~ width * y in [0,1] ~ height
- coordinate(coordinate: shapeflow.maths.coordinates.ShapeCoo) → Optional[shapeflow.maths.coordinates.ShapeCoo][source]¶
Transform a design coordinate to a video coordinate
- class shapeflow.video.FilterHandler(config: Optional[shapeflow.config.FilterHandlerConfig] = None)[source]¶
Bases:
shapeflow.core.config.Instance,shapeflow.core.interface.HandlerHandles filters
- set(color: Optional[shapeflow.maths.colors.HsvColor] = None) → shapeflow.core.interface.FilterConfig[source]¶
Set the filter to a color.
- class shapeflow.video.Mask(design: shapeflow.video.DesignFileHandler, mask: numpy.ndarray, name: str, config: Optional[shapeflow.config.MaskConfig] = None, filter: Optional[shapeflow.video.FilterHandler] = None)[source]¶
Bases:
shapeflow.core.config.InstanceHandles masks in the context of a video file
- filter: shapeflow.video.FilterHandler¶
The filter associated with this mask
- set_filter(color: Optional[shapeflow.maths.colors.HsvColor])[source]¶
Set the filter of this mask
- contains(coordinate: shapeflow.maths.coordinates.ShapeCoo) → bool[source]¶
Whether a coordinate is contained within this mask
- property rows¶
This mask’s row slice
To crop an image to this mask:
crop = img[mask.rows, mask.cols]
- property cols¶
This mask’s column slice
To crop an image to this mask:
crop = img[mask.rows, mask.cols]
- class shapeflow.video.DesignFileHandler(path: str, config: Optional[shapeflow.config.DesignFileHandlerConfig] = None, mask_config: Optional[Tuple[shapeflow.config.MaskConfig, ...]] = None)[source]¶
Bases:
shapeflow.core.backend.CachingInstanceHandles design files
- peel_design(design_path: str, dpi: int) → numpy.ndarray[source]¶
Render out all of the layers in a design
- read_masks(design_path: str, dpi: int) → Tuple[List[numpy.ndarray], List[str]][source]¶
Load masks from the rendered files
- property shape¶
The
numpy.ndarray.shapeof the design
- overlay_frame(frame: numpy.ndarray) → numpy.ndarray[source]¶
Apply this design’s overlay to a frame
- Parameters
frame (np.ndarray) – An image
- Returns
The image with the overlay laid over it
- Return type
np.ndarray
- property masks: List[shapeflow.video.Mask]¶
The masks of this design
- class shapeflow.video.MaskFunction(mask: shapeflow.video.Mask, global_config: shapeflow.core.backend.FeatureConfig, config: Optional[dict] = None)[source]¶
Bases:
shapeflow.core.backend.FeatureAn abstract feature based on a
Mask- property ready: bool¶
Whether this feature is ready to be calculated
- property skip¶
Whether this feature should be skipped
- px2mm(value)[source]¶
Convert design-space pixels to mm
- Parameters
value (float) – Distance in # of pixels
- Returns
Distance in mm
- Return type
float
- pxsq2mmsq(value)[source]¶
Convert design-space pixels to mm²
- Parameters
value (float) – Area in pixels
- Returns
Area in mm²
- Return type
float
- class shapeflow.video.VideoAnalyzer(config: Optional[shapeflow.config.VideoAnalyzerConfig] = None)[source]¶
Bases:
shapeflow.core.backend.BaseAnalyzerMain video handling class
Load frames from video files
Load mask files
Load/save measurement metadata
- video: shapeflow.video.VideoFileHandler¶
Handles video operations for this analyzer
Reads frames from the video file
- design: shapeflow.video.DesignFileHandler¶
Handles design operations for this analyzer.
Renders the design
Reads in the overlay and mask images
Initializes the
Maskinstances
- transform: shapeflow.video.TransformHandler¶
Handles the transform for this analyzer
- features: Tuple[shapeflow.core.backend.Feature, ...]¶
The features used in this analysis
- results: Dict[str, pandas.core.frame.DataFrame]¶
The results of the current run of this analysis
- property cached: bool¶
- property has_results: bool¶
- property position¶
- set_config(config: dict, silent: bool = False) → dict[source]¶
Set the analyzer’s configuration
shapeflow.api._VideoAnalyzerDispatcher.set_config- Parameters
config (dict) – A configuration
dictsilent (bool) – If
True, don’t push server-sent events.Falseby default.
- Returns
The updated configuration
dict. Some fields may have been changed due to incompatibility.- Return type
dict
- get_transformed_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]¶
Get a video frame transformed to design-space
shapeflow.api._VideoAnalyzerDispatcher.get_transformed_frameCan be streamed to the user interface.
- Parameters
frame_number (Optional[int]) – The frame number to get. If
None, get the current frame number.- Returns
An image (design-space)
- Return type
np.ndarray
- get_inverse_transformed_overlay() → numpy.ndarray[source]¶
Get the design overlay image transformed to video-space
shapeflow.api._VideoAnalyzerDispatcher.get_inverse_transformed_overlayCan be streamed tothe user interface.
- Returns
An image (in video-space)
- Return type
np.ndarray
- get_colors() → Tuple[str, ...][source]¶
Get the list of colors to use for each mask
shapeflow.api._VideoAnalyzerDispatcher.get_colors- Returns
A tuple of CSS-compatible hex RGB strings
- Return type
Tuple[str, …]
- frame_numbers() → Generator[int, None, None][source]¶
Get the requested frame numbers
- Returns
An iterator that returns the requested frame numbers
- Return type
Generator[int, None, None]
- get_inverse_overlaid_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]¶
Get a raw video frame overlaid with the inverse transformed design overlay. Used to evaluate video-design alignment.
shapeflow.api._VideoAnalyzerDispatcher.get_inverse_overlaid_frameCan be streamed tothe user interface.
- Parameters
frame_number (Optional[int]) – The frame number to get. If
None, get the current frame number.- Returns
An image (video-space)
- Return type
np.ndarray
- seek(position: Optional[float] = None) → float[source]¶
Seek the video to a relative position
shapeflow.api._VideoAnalyzerDispatcher.seek- Parameters
position (float) – A relative position in the video, with 0 the start and 1 the end.
- Returns
The resulting relative position. This may differ from the original requested position due to being resolved to the nearest requested frame number. This improves performance if cached frames can be reused.
- Return type
float
- estimate_transform(roi: Optional[dict] = None) → Optional[dict][source]¶
Estimate the video-design transform from a ROI
shapeflow.api._VideoAnalyzerDispatcher.estimate_transform- Parameters
roi (Optional[dict]) – A region of interest as a
dict. Must be compatible withshapeflow.maths.coordinates.Roi. IfNone, the currentshapeflow.config.TransformHandlerConfig.roiwill be used.- Returns
The region of interest that was provided, or the current region of interest if
None.- Return type
Optional[dict]
- turn_cw() → None[source]¶
Add a clockwise 90° turn to this analyzer’s
shapeflow.config.TransformHandlerConfig.turn
- turn_ccw() → None[source]¶
Add a counter-clockwise 90° turn to this analyzer’s
shapeflow.config.TransformHandlerConfig.turn
- flip_h() → None[source]¶
Toggle this analyzer’s
shapeflow.config.TransformHandlerConfig.flip’shorizontal
- flip_v() → None[source]¶
Toggle this analyzer’s
shapeflow.config.TransformHandlerConfig.flip’svertical
- undo_config(context: Optional[str] = None) → dict[source]¶
Undo this analyzer’s last configuration change
shapeflow.api._VideoAnalyzerDispatcher.undo_config- Parameters
context (str) – The context in which to undo. If
contextisNone, the previous configuration will be applied. Ifcontextis e.g."transform", the latest configuration with atransformdifferent from the current one will be applied.- Returns
A configuration
dict- Return type
dict
- redo_config(context: Optional[str] = None) → dict[source]¶
Redo this analyzer’s last undone configuration change
shapeflow.api._VideoAnalyzerDispatcher.redo_config- Parameters
context (str) – The context in which to redo. If
contextisNone, the previous configuration will be applied. Ifcontextis e.g."transform", the latest configuration with atransformdifferent from the current one will be applied.- Returns
A configuration
dict- Return type
dict
- set_filter_click(relative_x: float, relative_y: float) → None[source]¶
Configure a filter by clicking an “in”-pixel on the image
shapeflow.api._VideoAnalyzerDispatcher.set_filter_click- Parameters
relative_x (float) – The ‘x’-position of an “in”-pixel in relative video-space
relative_y (float) – The ‘y’-position of an “in”-pixel in relative video-space
- get_state_frame(frame_number: Optional[int] = None, featureset: Optional[int] = None) → numpy.ndarray[source]¶
Get a state frame. Used to evaluate filter configuration.
shapeflow.api._VideoAnalyzerDispatcher.get_state_frameCan be streamed tothe user interface.
- Parameters
frame_number (Optional[int]) – The frame number to get. If
None, get the current frame number.featureset (Optional[int]) – The index of the
FeatureSetfor which to get the state frame. IfNone, use 0. Feature sets are taken from this analyzer’sfeatures.
- Returns
An image (design-space)
- Return type
np.ndarray
- get_overlay_png() → bytes[source]¶
Get this analyzer’s design overlay
shapeflow.api._VideoAnalyzerDispatcher.get_overlay_png- Returns
The design overlay encoded as PNG
- Return type
bytes
- calculate(frame_number: int) → None[source]¶
Calculate this analyzer’s
featuresfor a frame.- Parameters
frame_number (int) – The frame to calculate for
- Returns
Results are stored in
results- Return type
None
- analyze() → bool[source]¶
Run the configured analysis
shapeflow.api._VideoAnalyzerDispatcher.analyze- Returns
Whether the analysis was successful
- Return type
bool
- get_time(frame_number: Optional[int] = None) → float[source]¶
Get the time corresponding to a video frame number
shapeflow.api._VideoAnalyzerDispatcher.get_time- Parameters
frame_number (Optional[int]) – A frame number. If
None, use the current frame number.- Returns
A time in seconds
- Return type
float
- read_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]¶
Get a raw video frame.
shapeflow.api._VideoAnalyzerDispatcher.get_raw_frameCan be streamed tothe user interface.
- Parameters
frame_number (Optional[int]) – The frame number to get. If
None, get the current frame number.- Returns
An image (video-space)
- Return type
np.ndarray
- get_seek_position() → float[source]¶
Get the current relative seek position in the video
shapeflow.api._VideoAnalyzerDispatcher.get_seek_posititon
server¶
- class shapeflow.server.ServerThread(*args, **kwargs)[source]¶
Bases:
threading.ThreadA thread running a
Flaskapp over awaitressserver.- run()[source]¶
Serve until interrupted or stopped.
If the current address is already in use, the server errors out & stops the current process with
shapeflow.server.ServerThread.stop().
- class shapeflow.server.ShapeflowServer[source]¶
Bases:
shapeflow.main.ShapeflowServerInterfaceWrapper for a
Flaskserver- serve(host: str, port: int, open: bool) → None[source]¶
Serve the application.
Starts a new
ServerThreadand opens a new browser window/tab if requested.This method keeps serving until either
quit()is calledunload()is called and no incoming traffic is received for 5 seconds.The user interrupts the process with
Ctrl+C
- Parameters
host (str) – Host address
port (int) – Host port
open (bool) – Whether to open in a browser window/tab after starting the server
- call_api(address: str) → flask.wrappers.Response[source]¶
Dispatch request to the API.
Arguments are gathered from
Flask’srequest.dataorrequest.argsHandles multiple types of return data:
bytesdata are handled byflask.make_responsefor
shapeflow.core.streaming.BaseStreamerinstances, customflask.Responseobjects are made from theirshapeflow.core.streaming.BaseStreamer.stream()generatorall other data are handled by
flask.jsonify
- Parameters
address (str) – The address of the endpoint to dispatch to
- active() → None[source]¶
If the
_unloadhas been set, cancel it. Should be called for incoming traffic.
- property api: shapeflow.api.ApiDispatcher¶
Get a reference to
shapeflow.api.apiand ensure it has been initialized properly withshapeflow.mainand bound to thisShapeflowServerinstance.This property is used to lazy-load
shapeflow.api.apion the first request. As this takes some time, requests received during loading will be locked out until initialization completes. Subsequent requests bypass this lock.- Returns
A reference to
api- Return type
- property eventstreamer: shapeflow.core.streaming.EventStreamer¶
A reference to the server’s
shapeflow.core.streaming.EventStreamerinstance
main¶
Main functionality of the shapeflow server.
Implements shapeflow.api endpoints related to the global application and
analyzer management.
The classes defined below should not be instantiated individually, but as a
whole using shapeflow.main.load(), because their setup process is not
very intuitive.
- class shapeflow.main._Main(server: shapeflow.main.ShapeflowServerInterface)[source]¶
Bases:
objectImplements root-level
apiendpoints.- ping() → bool[source]¶
Ping the server
shapeflow.api.ApiDispatcher.ping- Returns
If the server is up,
True. If the server is down, a/api/pingrequest will not get any response.- Return type
bool
- map() → Dict[str, List[str]][source]¶
Get the URL map of the API
shapeflow.api.ApiDispatcher.map- Returns
A flat
dictmapping each available URL to a list of accepted HTTP methods- Return type
Dict[str, List[str]]
- schemas() → dict[source]¶
Get the application schemas
shapeflow.api.ApiDispatcher.schemas- Returns
A
dictwith schemas- Return type
dict
- normalize_config(config: dict) → dict[source]¶
Normalize a configuration
dictwithshapeflow.config.normalize_config()shapeflow.api.ApiDispatcher.normalize_config- Parameters
config (dict) – A configuration
dict- Returns
A normalized configuration
dict- Return type
dict
- get_settings() → dict[source]¶
Get the application settings
shapeflow.api.ApiDispatcher.get_settings- Returns
The application settings as a
dict- Return type
dict
- set_settings(settings: dict) → dict[source]¶
Set the application settings
shapeflow.api.ApiDispatcher.set_settings- Parameters
settings (dict) – New application settings as a
dict- Returns
The new application settings
dict, which may have been modified.- Return type
dict
- events() → shapeflow.core.streaming.EventStreamer[source]¶
Get a server-sent event stream
shapeflow.api.ApiDispatcher.events- Returns
A
BaseStreamerobject, to be streamed byFlask- Return type
- log() → shapeflow.core.streaming.PlainFileStreamer[source]¶
Start streaming log file
shapeflow.api.ApiDispatcher.log- Returns
A
BaseStreamerobject, to be streamed byFlask- Return type
- unload() → bool[source]¶
Unload the application. Called when the user closes or refreshes a tab with the user interface.
- pid_hash() → str[source]¶
Get the current
pidhash of the API server.shapeflow.api.ApiDispatcher.pid_hash- Returns
The hash of the current
pid. The actualpidis not given to avoid cheekiness.- Return type
str
- class shapeflow.main._Cache[source]¶
Bases:
objectImplements
cacheendpoints inapi.- cache_size() → str[source]¶
Get the size of the cache
shapeflow.api._CacheDispatcher.size- Returns
The size of the cache in human-readable form
- Return type
str
- class shapeflow.main._Filesystem[source]¶
Bases:
objectImplements
fsendpoints inapi.- select_video() → Optional[str][source]¶
Open a video selection dialog
shapeflow.api._FilesystemDispatcher.select_video- Returns
The path of the selected video file, if any.
- Return type
Optional[str]
- select_design() → Optional[str][source]¶
Open a design selection dialog
shapeflow.api._FilesystemDispatcher.select_design- Returns
The path of the selected design file, if any.
- Return type
Optional[str]
- check_video(path: str) → bool[source]¶
Check if a video file path is valid:
Whether it exists
Whether it’s a valid video file that can be opened with
OpenCV
shapeflow.api._FilesystemDispatcher.check_video- Parameters
path (str) – A path
- Returns
Whether the path is a valid video file
- Return type
bool
- check_design(path: str) → bool[source]¶
Check if a design file path is valid:
Whether it exists
Whether it’s a valid design file
shapeflow.api._FilesystemDispatcher.check_design- Parameters
path (str) – A path
- Returns
Whether the path is a valid design file
- Return type
bool
- open_root() → None[source]¶
Open
shapeflow.ROOTDIRin the file explorer
- class shapeflow.main._VideoAnalyzerManager(server: shapeflow.main.ShapeflowServerInterface)[source]¶
Bases:
objectImplements
vaendpoints inapi.Manages
BaseAnalyzerinstancesAdds / removes instances
Handles saving / loading of application state
Handles analysis queueing
Handles analyzer-specific streams
- ID_LENGTH = 6¶
Length of
idstrings. Kept relatively short for readable URLs.
- notice(message: str, persist: bool = False)[source]¶
Push a notice to the server’s
EventStreamer- Parameters
message (str) – The message to push
- init() → str[source]¶
Initialize a new analyzer.
shapeflow.api._VideoAnalyzerManagerDispatcher.initA short unique
ìdwill be generated. For example, a new analyzer withrG7bgHas itsidcan be addressed via/api/va/rG7bgH.- Returns
The
idstring of the newly added analyzer- Return type
str
- close(id: str) → bool[source]¶
Close an analyzer.
shapeflow.api._VideoAnalyzerManagerDispatcher.close- Parameters
id (str) – The
idstring of the analyzer to remove- Returns
Whether the analyzer was removed successfully
- Return type
bool
- q_start(queue: List[str]) → bool[source]¶
Start analyzing a queue.
shapeflow.api._VideoAnalyzerManagerDispatcher.start- Parameters
queue (List[str]) – List of analyzer
idto queue.
- state() → dict[source]¶
Get the queue state and the status of all analyzers.
shapeflow.api._VideoAnalyzerManagerDispatcher.stateExample:
{ "q_state": 0, # QueueState "ids": ["abc123", "def456"], "status": { "abc123": { "state": 7, # AnalyzerState "busy": True, "cached": True, "results": False, "position": 0.7, "progress": 0.75, }, "def456": { "state": 6, # AnalyzerState "busy": False, "cached": True, "results": False, "position": 0.0, "progress": 0.0, }, } }
With the state
intvalues according to theEnumclassesQueueStateandAnalyzerState.- Returns
A state
dict- Return type
dict
- stream(id: str, endpoint: str) → shapeflow.core.streaming.BaseStreamer[source]¶
Stream something.
shapeflow.api._VideoAnalyzerManagerDispatcher.stream- Parameters
id (str) – The
idof an analyzerendpoint (str) – The endpoint to stream
- Returns
A stream handler object
- Return type
- stream_stop(id: str, endpoint: str) → None[source]¶
Stop streaming something.
shapeflow.api._VideoAnalyzerManagerDispatcher.stream_stop- Parameters
id (str) – The
idof an analyzerendpoint (str) – The endpoint to stop streaming
- shapeflow.main.load(server: shapeflow.main.ShapeflowServerInterface) → shapeflow.api.ApiDispatcher[source]¶
Initialize
apiand return a reference to it.- Parameters
server (ShapeflowServer) – The
shapeflowserver object- Returns
A reference to
api- Return type
cli¶
Tiny commands to be called from sf.py
Calling from the commandline:
python sf.py --do <command name> <arguments>
- class shapeflow.cli.IterCommand(name, bases, namespace, **kwargs)[source]¶
Bases:
abc.ABCMetaCommand iterator metaclass.
Iterates over its subclasses, skipping any without a
__command__. If any of these should remain abstract, they shouldn’t define one.- __command__: str¶
Command name. This is how the command is addressed from the commandline.
- property sub¶
Returns True if this class is a subcommand
- property dict: dict¶
Get a
dictmapping all defined command names to their respective class
- __getitem__(item: str) → shapeflow.cli.IterCommand[source]¶
Get a subcommand by its __command__
- class shapeflow.cli.Command(args: Optional[List[str]] = None)[source]¶
Bases:
abc.ABCAbstract command.
handles argument parsing & execution
subclasses can implement their functionality in
Command.command()
- class shapeflow.cli.Sf(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.CommandCommandline entry point. This is the command that gets called first and calls any subcommands if requested.
- class shapeflow.cli.Serve(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.CommandStarts the
shapeflowserver.- __command__ = 'serve'¶
- HOST = '127.0.0.1'¶
- PORT = 7951¶
- class shapeflow.cli.Dump(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.CommandDump application schemas and settings to JSON
- __command__ = 'dump'¶
- class shapeflow.cli.GitMixin[source]¶
Bases:
abc.ABCMetaclass for commands interacting with the git repository
- URL = 'https://github.com/ybnd/shapeflow/'¶
- property repo: git.repo.base.Repo¶
- property latest: str¶
- property tag: str¶
- property ui_url: str¶
- class shapeflow.cli.Update(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.Command,shapeflow.cli.GitMixinUpdate the application
- __command__ = 'update'¶
- class shapeflow.cli.Checkout(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.Command,shapeflow.cli.GitMixinCheck out a specific version of the application. Please not you will not have access to this command if you check out a version before 0.4.4
- __command__ = 'checkout'¶
- class shapeflow.cli.GetCompiledUi(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.Command,shapeflow.cli.GitMixinGet the compiled UI for the current version
- __command__ = 'get-compiled-ui'¶
- class shapeflow.cli.SetupCairo(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.CommandSet up cairo DLLs (Windows) ~ https://github.com/preshing/cairo-windows/
- __command__ = 'setup-cairo'¶
- URL = 'https://github.com/preshing/cairo-windows/releases/download/with-tee/cairo-windows-1.17.2.zip'¶
- property env: pathlib.Path¶
- class shapeflow.cli.Declutter(args: Optional[List[str]] = None)[source]¶
Bases:
shapeflow.cli.CommandHide clutter files from the repository
- CLUTTER = ['mypy.ini', 'tox.ini', '__pycache__']¶
- __command__ = 'declutter'¶