isimple package

Submodules

isimple.config module

class isimple.config.ColorSpace(string: str = None)[source]

Bases: isimple.core.EnforcedStr

class isimple.config.FrameIntervalSetting(string: str = None)[source]

Bases: isimple.core.EnforcedStr

class isimple.config.VideoFileHandlerConfig[source]

Bases: isimple.core.config.BaseConfig

Video file

class isimple.config.FlipConfig[source]

Bases: isimple.core.config.BaseConfig

Flip

class isimple.config.TransformHandlerConfig[source]

Bases: isimple.core.interface.HandlerConfig

Transform

class isimple.config.FilterHandlerConfig[source]

Bases: isimple.core.interface.HandlerConfig

Filter

ready
class isimple.config.MaskConfig[source]

Bases: isimple.core.config.BaseConfig

Mask

ready
class isimple.config.DesignFileHandlerConfig[source]

Bases: isimple.core.config.BaseConfig

Design file

class isimple.config.VideoAnalyzerConfig[source]

Bases: isimple.core.backend.BaseAnalyzerConfig

Video analyzer

classmethod schema(by_alias: bool = True) → Dict[str, Any][source]
isimple.config.load(path: str) → isimple.config.VideoAnalyzerConfig[source]
isimple.config.loads(config: str) → isimple.core.config.BaseConfig[source]
isimple.config.normalize_config(d: dict) → dict[source]

Normalize a configuration dictionary to match the current version of isimple.core.config :param d: configuration dictionary :return:

isimple.config.dump(config: isimple.config.VideoAnalyzerConfig, path: str)[source]
isimple.config.dumps(config: isimple.config.VideoAnalyzerConfig) → str[source]

isimple.db module

class isimple.db.VideoFileModel(path)[source]

Bases: isimple.core.db.FileModel

resolve() → isimple.db.VideoFileModel[source]

Resolve the file by its SHA1 hash. todo: reference to util.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 FileModel instance representing the original database entry.
Return type:FileModel
hash
id
path
used
class isimple.db.DesignFileModel(path)[source]

Bases: isimple.core.db.FileModel

resolve() → isimple.db.DesignFileModel[source]

Resolve the file by its SHA1 hash. todo: reference to util.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 FileModel instance representing the original database entry.
Return type:FileModel
hash
id
path
used
class isimple.db.ConfigModel(**kwargs)[source]

Bases: isimple.core.db.DbModel

id
video
design
analysis
json
added
class isimple.db.ResultsModel(**kwargs)[source]

Bases: isimple.core.db.DbModel

id
analysis
feature

The feature that was analyzed

data

Results of the analysis. In JSON, formatted ~ pandas.DataFrame.to_json(orient='split')

started
finished
elapsed
class isimple.db.AnalysisModel(*args, **kwargs)[source]

Bases: isimple.core.db.BaseAnalysisModel

Database model of an analysis. Contains a reference to a BaseVideoAnalyzer instance.

id
video
design
config
results
name
description
added
modified
get_name() → str[source]

Name of the analysis from the database. Unset names are reset to ‘#{id}’

set_analyzer(analyzer: isimple.core.backend.BaseVideoAnalyzer)[source]
store()[source]

Store analysis information from wrapped BaseVideoAnalyzer to the database.

load_config(video_path: str = None, design_path: str = None, include: 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_config_json() → Optional[str][source]

Get the current configuration in JSON

undo_config(context: str = None)[source]

Undo configuration. If a context is supplied, ensure that the context field changes, but the other fields remain the same

Parameters:context (str) – Name of a VideoAnalyzerConfig field
Raises:ValueError – If context is not a VideoAnalyzer field
redo_config(context: str = None)[source]

Redo configuration. If a context is supplied, ensure that the context field changes, but the other fields remain the same

Parameters:context (str) – Name of a VideoAnalyzerConfig field
Raises:ValueError – If context is not a VideoAnalyzer field
class isimple.db.History(path: pathlib.Path = None)[source]

Bases: isimple.core.db.SessionWrapper

Interface to the history database

add_video_file(path: str) → isimple.db.VideoFileModel[source]

Add a video file to the database. Duplicate files are resolved to the original entry.

add_design_file(path: str) → isimple.db.DesignFileModel[source]

Add a design file to the database. Duplicate files are resolved to the original entry.

add_analysis(analyzer: isimple.core.backend.BaseVideoAnalyzer, model: isimple.db.AnalysisModel = None) → isimple.db.AnalysisModel[source]
fetch_analysis(id: int) → Optional[isimple.db.AnalysisModel][source]
fetch_paths() → Dict[str, list][source]

Fetch the latest video and design file paths from the database. Number of paths is limited by settings.app.recent_files

clean() → None[source]

Clean the database

  • remove ‘analysis’ entries with <null> config

  • remove ‘config’ entries with <null> json

  • for ‘analysis’ entries older than settings.db.cleanup_interval

    • remove all non-primary ‘config’ entries
    • remove all non-primary ‘results’ entries
forget() → None[source]

Remove everything.

isimple.endpoints module

class isimple.endpoints.BackendRegistry(endpoints: isimple.core.InstanceRegistry = None)[source]

Bases: isimple.core.ImmutableRegistry

status = <isimple.core.Endpoint object>
state_transition = <isimple.core.Endpoint object>
can_launch = <isimple.core.Endpoint object>
can_analyze = <isimple.core.Endpoint object>
launch = <isimple.core.Endpoint object>
commit = <isimple.core.Endpoint object>
cache = <isimple.core.Endpoint object>
analyze = <isimple.core.Endpoint object>
cancel = <isimple.core.Endpoint object>
is_caching = <isimple.core.Endpoint object>
cancel_caching = <isimple.core.Endpoint object>
get_value = <isimple.core.Endpoint object>
get_state = <isimple.core.Endpoint object>
get_config = <isimple.core.Endpoint object>
set_config = <isimple.core.Endpoint object>
get_results = <isimple.core.Endpoint object>
get_relative_roi = <isimple.core.Endpoint object>
undo_config = <isimple.core.Endpoint object>
redo_config = <isimple.core.Endpoint object>
get_name = <isimple.core.Endpoint object>
seek = <isimple.core.Endpoint object>
get_seek_position = <isimple.core.Endpoint object>
get_raw_frame = <isimple.core.Endpoint object>
set_transform_implementation = <isimple.core.Endpoint object>
transform = <isimple.core.Endpoint object>
estimate_transform = <isimple.core.Endpoint object>
turn_cw = <isimple.core.Endpoint object>
turn_ccw = <isimple.core.Endpoint object>
flip_h = <isimple.core.Endpoint object>
flip_v = <isimple.core.Endpoint object>
clear_roi = <isimple.core.Endpoint object>
get_coordinates = <isimple.core.Endpoint object>
get_mask_name = <isimple.core.Endpoint object>
get_mask_names = <isimple.core.Endpoint object>
get_filter_mean_color = <isimple.core.Endpoint object>
get_overlay_png = <isimple.core.Endpoint object>
get_frame = <isimple.core.Endpoint object>
get_masked_frame = <isimple.core.Endpoint object>
set_filter_click = <isimple.core.Endpoint object>
filter = <isimple.core.Endpoint object>
mask = <isimple.core.Endpoint object>
get_filtered_frame = <isimple.core.Endpoint object>
get_filtered_masked_frame = <isimple.core.Endpoint object>
overlay_frame = <isimple.core.Endpoint object>
get_overlaid_frame = <isimple.core.Endpoint object>
get_inverse_transformed_overlay = <isimple.core.Endpoint object>
get_inverse_overlaid_frame = <isimple.core.Endpoint object>
get_state_frame = <isimple.core.Endpoint object>
get_colors = <isimple.core.Endpoint object>
get_time = <isimple.core.Endpoint object>
get_total_time = <isimple.core.Endpoint object>
get_fps = <isimple.core.Endpoint object>
get_h = <isimple.core.Endpoint object>
get_dpi = <isimple.core.Endpoint object>
get_mask_rects = <isimple.core.Endpoint object>

isimple.main module

isimple.main.respond(*args) → str[source]
isimple.main.restart_server(host: str, port: int)[source]
class isimple.main.ServerThread(app, host, port)[source]

Bases: threading.Thread

run()[source]

Method representing the thread’s activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.

stop()[source]
class isimple.main.QueueState[source]

Bases: enum.IntEnum

An enumeration.

STOPPED = 0
RUNNING = 1
PAUSED = 2
class isimple.main.Main[source]

Bases: isimple.core.Lockable

serve(host, port)[source]

Serve the application

Parameters:
  • host (str) – Host address
  • port (int) – Host port
check_video_path(path: str) → bool[source]

Check whether the path is a valid video and add it to the history database

check_design_path(path: str) → bool[source]

Check whether the path is a valid design and add it to the history database

add_instance(type: isimple.core.backend.AnalyzerType = None) → str[source]

Add a new analyzer instance

Parameters:type (AnalyzerType) – Type of BaseVideoAnalyzer to instantiate
Returns:The id of the new analyzer
Return type:str
remove_instance(id: str) → bool[source]

Remove a analyzer instance

Parameters:id (str) – The id of the analyzer to remove
q_start(q: List[str]) → bool[source]

Queue analysis

Parameters:q (List[str]) – List of analyzer id to queue.
q_stop()[source]

Stop analysis queue

save_state()[source]

Save application state to isimple.settings.app.state_path

load_state()[source]

Load application state from isimple.settings.app.state_path

call(id: str, endpoint: str, data: dict = None) → Any[source]

Call an analyzer endpoint

Parameters:
stream(id: str, endpoint: str) → Optional[isimple.core.streaming.BaseStreamer][source]
stop_stream(id: str, endpoint: str)[source]
valid(id)[source]
events

isimple.video module

exception isimple.video.VideoFileTypeError(*args)[source]

Bases: isimple.core.backend.BackendSetupError

msg = 'Unrecognized video file type'
class isimple.video.VideoFileHandler(video_path, config: isimple.config.VideoFileHandlerConfig = None)[source]

Bases: isimple.core.backend.CachingInstance, isimple.core.Lockable

Interface to video files ~ OpenCV

config
shape
cached
check_cached() → Optional[bool][source]
set_requested_frames(requested_frames: List[int]) → None[source]

Add a list of requested frames. Used to determine which frames to cache in the background and in _resolve_frame

cache_frames(progress_callback: Callable[[float], None], state_callback: Callable[[int], None])[source]
get_time(frame_number: int = None) → float[source]
get_fps() → float[source]
get_total_time() → float[source]
read_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]

Wrapper for _read_frame. Enables caching (if in a caching context!) and provides the video file’s path to determine the cache key.

seek(position: float = None) → float[source]

Seek to the relative position ~ [0,1]

get_seek_position() → float[source]

Get current relative position ~ [0,1]

class isimple.video.TransformHandler(video_shape, design_shape, config: isimple.config.TransformHandlerConfig)[source]

Bases: isimple.core.config.Instance, isimple.core.backend.Handler

Handles coordinate transforms.

config
set_implementation(implementation: str = None) → str[source]
set(matrix: Optional[numpy.ndarray])[source]

Set the transform matrix

is_set
get_relative_roi() → dict[source]
estimate(roi: isimple.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
adjust(roi: isimple.maths.coordinates.Roi) → isimple.maths.coordinates.Roi[source]

Adjust ROI (90° turns & flips)

clear() → None[source]
get_coordinates() → Optional[list][source]
coordinate(coordinate: isimple.maths.coordinates.ShapeCoo) → isimple.maths.coordinates.ShapeCoo[source]

Transform a design coordinate to a video coordinate

inverse(img: numpy.ndarray) → numpy.ndarray[source]
class isimple.video.FilterHandler(config: isimple.config.FilterHandlerConfig = None)[source]

Bases: isimple.core.config.Instance, isimple.core.backend.Handler

config
set_config(config: dict) → None[source]
implementation
mean_color() → isimple.maths.colors.Color[source]
set(color: isimple.maths.colors.HsvColor = None) → isimple.core.interface.FilterConfig[source]
set_implementation(implementation: str = None) → str[source]
class isimple.video.Mask(design: isimple.video.DesignFileHandler, mask: numpy.ndarray, name: str, config: isimple.config.MaskConfig = None, filter: isimple.video.FilterHandler = None)[source]

Bases: isimple.core.config.Instance

Handles masks in the context of a video file

config
set_config(config: dict) → None[source]
set_filter(color: isimple.maths.colors.HsvColor)[source]
contains(coordinate: isimple.maths.coordinates.ShapeCoo) → bool[source]
design
rows
cols
name
part
rect
ready
skip
class isimple.video.DesignFileHandler(path: str, config: isimple.config.DesignFileHandlerConfig = None, mask_config: Tuple[isimple.config.MaskConfig, ...] = None)[source]

Bases: isimple.core.backend.CachingInstance

config
peel_design(design_path: str, dpi: int) → numpy.ndarray[source]
read_masks(design_path: str, dpi: int) → Tuple[List[numpy.ndarray], List[str]][source]
shape
overlay() → numpy.ndarray[source]
overlay_frame(frame: numpy.ndarray) → numpy.ndarray[source]
masks
class isimple.video.MaskFunction(mask: isimple.video.Mask, global_config: isimple.core.backend.FeatureConfig, config: Optional[dict] = None)[source]

Bases: isimple.core.backend.Feature

name
feature_type
ready
skip
px2mm(value)[source]

Convert design-space pixels to mm :param value: # of pixels :return:

pxsq2mmsq(value)[source]

Convert design-space pixels to mm² :param value: :return:

value(frame) → Any[source]

Compute the value of the Feature instance for a given frame

state(frame: numpy.ndarray, state: numpy.ndarray) → numpy.ndarray[source]

Generate a state image (BGR)

class isimple.video.VideoAnalyzer(config: isimple.config.VideoAnalyzerConfig = None)[source]

Bases: isimple.core.backend.BaseVideoAnalyzer

Main video handling class * Load frames from video files * Load mask files * Load/save measurement metadata

config
cached
has_results
can_launch() → bool[source]
can_filter() → bool[source]
can_analyze() → bool[source]
position
set_config(config: dict, silent: bool = False) → dict[source]
get_transformed_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]
get_inverse_transformed_overlay() → numpy.ndarray[source]
get_frame_overlay(frame_number: int) → numpy.ndarray[source]
get_colors() → Dict[str, Tuple[str, ...]][source]
frame_numbers() → Generator[int, None, None][source]
get_inverse_overlaid_frame(frame_number: Optional[int] = None) → numpy.ndarray[source]
seek(position: float = None) → float[source]
estimate_transform(roi: dict = None) → Optional[dict][source]
clear_roi() → None[source]
turn_cw()[source]
turn_ccw()[source]
flip_h()[source]
flip_v()[source]
undo_config(context: str = None) → dict[source]
redo_config(context: str = None) → dict[source]
set_filter_click(relative_x: float, relative_y: float) → dict[source]
get_state_frame(frame_number: Optional[int] = None, featureset: Optional[int] = None) → numpy.ndarray[source]
get_overlay_png() → bytes[source]
get_mask_rects() → Dict[str, numpy.ndarray][source]
calculate(frame_number: int)[source]

Return a state image for each FeatureSet

analyze()[source]
export()[source]

Export video analysis results & metadata to .xlsx

get_result() → dict[source]
load_config()[source]

Load video analysis configuration from history database

isimple.video.init(config: isimple.core.backend.BaseAnalyzerConfig) → isimple.core.backend.BaseVideoAnalyzer[source]

Module contents

class isimple.FormatSettings[source]

Bases: isimple._Settings

class isimple.LoggingLevel[source]

Bases: str, enum.Enum

An enumeration.

critical = 'critical'
error = 'error'
warning = 'warning'
info = 'info'
debug = 'debug'
vdebug = 'vdebug'
class isimple.LogSettings[source]

Bases: isimple._Settings

class isimple.CacheSettings[source]

Bases: isimple._Settings

class isimple.RenderSettings[source]

Bases: isimple._Settings

class isimple.DatabaseSettings[source]

Bases: isimple._Settings

class isimple.ResultSaveMode[source]

Bases: str, enum.Enum

An enumeration.

skip = 'skip'
next_to_video = 'next to video file'
next_to_design = 'next to design file'
directory = 'in result directory'
class isimple.ApplicationSettings[source]

Bases: isimple._Settings

class isimple.Settings[source]

Bases: isimple._Settings

classmethod from_dict(settings: dict)[source]
isimple.save_settings(settings: isimple.Settings, path: str = '/home/docs/.local/share/isimple/settings.yaml')[source]
isimple.update_settings(new_settings: dict)[source]

Update global settings ~ dict Note: doing settings = Settings(**new_settings) would prevent importing modules from accessing the updated settings!

class isimple.Logger(name, level=0)[source]

Bases: logging.Logger

debug(msg, *args, **kwargs)[source]

Log ‘msg % args’ with severity ‘DEBUG’.

To pass exception information, use the keyword argument exc_info with a true value, e.g.

logger.debug(“Houston, we have a %s”, “thorny problem”, exc_info=1)

info(msg, *args, **kwargs)[source]

Log ‘msg % args’ with severity ‘INFO’.

To pass exception information, use the keyword argument exc_info with a true value, e.g.

logger.info(“Houston, we have a %s”, “interesting problem”, exc_info=1)

warning(msg, *args, **kwargs)[source]

Log ‘msg % args’ with severity ‘WARNING’.

To pass exception information, use the keyword argument exc_info with a true value, e.g.

logger.warning(“Houston, we have a %s”, “bit of a problem”, exc_info=1)

error(msg, *args, **kwargs)[source]

Log ‘msg % args’ with severity ‘ERROR’.

To pass exception information, use the keyword argument exc_info with a true value, e.g.

logger.error(“Houston, we have a %s”, “major problem”, exc_info=1)

critical(msg, *args, **kwargs)[source]

Log ‘msg % args’ with severity ‘CRITICAL’.

To pass exception information, use the keyword argument exc_info with a true value, e.g.

logger.critical(“Houston, we have a %s”, “major disaster”, exc_info=1)

vdebug(message, *args, **kwargs)[source]
isimple.get_cache(settings: isimple.Settings = Settings(log=LogSettings(path='/home/docs/.local/share/isimple/current.log', dir='/home/docs/.local/share/isimple/log', keep=16, lvl_console=<LoggingLevel.debug: 'debug'>, lvl_file=<LoggingLevel.debug: 'debug'>), cache=CacheSettings(dir='/home/docs/.local/share/isimple/cache', size_limit_gb=4, do_cache=True, resolve_frame_number=True, block_timeout=0.1), render=RenderSettings(dir='/home/docs/.local/share/isimple/render', keep=False), format=FormatSettings(datetime_format='%Y/%m/%d %H:%M:%S.%f', datetime_format_fs='%Y-%m-%d_%H-%M-%S'), db=DatabaseSettings(path='/home/docs/.local/share/isimple/history.db', cleanup_interval=7), app=ApplicationSettings(save_state=True, load_state=False, state_path='/home/docs/.local/share/isimple/state', recent_files=16, save_result=<ResultSaveMode.next_to_video: 'next to video file'>, result_dir='/home/docs/.local/share/isimple/results'))) → diskcache.core.Cache[source]
isimple.get_logger(name: str, settings: isimple.LogSettings = LogSettings(path='/home/docs/.local/share/isimple/current.log', dir='/home/docs/.local/share/isimple/log', keep=16, lvl_console=<LoggingLevel.debug: 'debug'>, lvl_file=<LoggingLevel.debug: 'debug'>)) → isimple.Logger[source]