Shapes
Defines the shapes which are used with a ceed.function
to create regions
with time-varying intensity during an experiment ceed.stage
.
PaintCanvasBehavior
provides the widget
functionality such that when a user draws on the screen,
PaintShape
instances are created and added to
it.
CeedPaintCanvasBehavior
provides a more specialized painter canvas.
Specifically, in addition to being able to draw shapes, it adds the ability
to organize shapes into CeedPaintCanvasBehavior.groups
.
Shape plugin
Although Ceed does not offer a plugin for shapes, it’s simple to create shapes and shape groups with a script, dump it to disk as a yaml file, and import it into Ceed from the GUI.
Following is an example using CeedPaintCanvasBehavior
and the methods
of its baseclass PaintCanvasBehavior
as well
as using the Ceed-inherited versions of the shapes;
CeedPaintCircle
(PaintCircle
),
CeedPaintEllipse
(PaintEllipse
),
CeedPaintPolygon
(PaintPolygon
).
Each shape class has a class method create_shape
that can be used to create
the shape, because you should not instantiate the shape class manually because
the resulting shapes may not be valid:
from ceed.shape import CeedPaintCanvasBehavior, CeedPaintCircle, CeedPaintEllipse, CeedPaintPolygon
from ceed.storage.controller import CeedDataWriterBase
# create shape factory to which we'll add shapes
shape_factory = CeedPaintCanvasBehavior()
# create the shapes and name them. We use the Shape classes from Ceed
ellipse = CeedPaintEllipse.create_shape(
center=(250, 450), radius_x=200, radius_y=400, name='ellipse')
circle = CeedPaintCircle.create_shape(
center=(700, 300), radius=200, name='circle')
polygon = CeedPaintPolygon.create_shape(
points=[275, 300, 700, 300, 500, 800], name='polygon')
# add the shapes to factory
shape_factory.add_shape(ellipse)
shape_factory.add_shape(circle)
shape_factory.add_shape(polygon)
# create group, name it, and add shapes to it
group = shape_factory.add_group()
group.name = 'shapes'
group.add_shape(ellipse)
group.add_shape(polygon)
# save it to disk for import later
CeedDataWriterBase.save_config_to_yaml(
filename, shape_factory=shape_factory)
You can also create the shapes by type name using
create_shape()
:
from ceed.shape import CeedPaintCanvasBehavior
from ceed.storage.controller import CeedDataWriterBase
# create shape factory to which we'll add shapes
shape_factory = CeedPaintCanvasBehavior()
# create shape using config, including name
ellipse = shape_factory.create_shape(
'ellipse', center=(250, 450), radius_x=200, radius_y=400,
name='ellipse')
circle = shape_factory.create_shape(
'circle', center=(700, 300), radius=200, name='circle')
polygon = shape_factory.create_shape(
'polygon', points=[275, 300, 700, 300, 500, 800], name='polygon')
# add the shapes to factory
shape_factory.add_shape(ellipse)
shape_factory.add_shape(circle)
shape_factory.add_shape(polygon)
# create group, name it, and add shapes to it
group = shape_factory.add_group()
group.name = 'shapes'
group.add_shape(ellipse)
group.add_shape(polygon)
# save it to disk for import later
CeedDataWriterBase.save_config_to_yaml(
filename, shape_factory=shape_factory)
See save_config_to_yaml()
for a full example with functions/stages.
If you need to create many shapes or groups and importing them in the Ceed GUI
is slow, consider setting its no_display
or
no_display
to True. E.g.
CeedPaintEllipse.create_shape(..., no_display=True)
.
The ProPixx projector used by Ceed has a resolution of 1920x108, so that should
be the maximum extent of the shapes. The exact available drawing area can also
be read/set in the config at
screen_width
and
screen_height
.
- class ceed.shape.CeedPaintCanvasBehavior(**kwargs)
Bases:
kivy_garden.painter.PaintCanvasBehavior
Controller base class for drawing and managing the shapes.
A shape is drawn by the user in the GUI and automatically added by
kivy_garden.painter.PaintCanvasBehavior
to itskivy_garden.painter.PaintCanvasBehavior.shapes
list. This class manages all that without any of the associated GUI components that is shown to the user (e.g. the ability name shapes etc.). The GUI components is added by theCeedPainter
.So when run from the GUI, an instance of
ceed.shape.shape_widgets.CeedPainter
is the class used to manage the shapes. When running during analysis, and instance of this class is used instead as no visualizations is required..In addition to the
kivy_garden.painter.PaintCanvasBehavior.shapes
, the class addsgroups
for grouping shapes; aCeedShapeGroup
simply groups a collection ofCeedShape
by their name.- Events
- on_remove_shape:
Triggered when a
CeedShape
is removed. The first parameter is the shape removed.- on_remove_group:
Triggered when a
CeedShapeGroup
is removed. The first parameter is the group removed.- on_changed:
Triggered whenever a
CeedShape
orCeedShapeGroup
is added or removed, or if a configuration option of the objects is changed.
- groups: List[ceed.shape.CeedShapeGroup]
List of
CeedShapeGroup
instances created in Ceed.
- shape_names: Dict[str, ceed.shape.CeedShape]
The name ->
CeedShape
dict. The key is the shape’s name and the corresponding value is theCeedShape
instance.
- shape_group_names: Dict[str, ceed.shape.CeedShapeGroup]
The name ->
CeedShapeGroup
dict. The key is the group’s name and the corresponding value is theCeedShapeGroup
instance.
- unique_names: ceed.utils.UniqueNames = None
A set that tracks existing shape/group names to help us ensure all shapes/groups have unique names.
- add_shape(shape: ceed.shape.CeedShape)
Add the shape to
shapes
and to the painter.- Parameters
shape –
PaintShape
instance to add.- Returns
A bool indicating whether the shape was successfully added.
- remove_shape(shape: ceed.shape.CeedShape)
Removes the shape from the painter and from
shapes
.- Parameters
shape –
PaintShape
instance to remove.- Returns
A bool indicating whether the shape was successfully removed.
- reorder_shape(shape: ceed.shape.CeedShape, before_shape: Optional[ceed.shape.CeedShape] = None)
Move the shape up or down in depth, in terms of the shape order in
shapes
and in the canvas.This effect whether a shape will obscure another.
- Parameters
shape –
PaintShape
instance to move from it’s current position.before_shape – Where to add it. If None, it is moved at the end, otherwise it is moved after the given
PaintShape
inshapes
.
- move_shape_lower(shape: ceed.shape.CeedShape)
Moves the shape one shape down. I.e. if there are two shapes and this shape is at index 1, it gets moved to index 0.
This changes the depth ordering of the shapes.
- Parameters
shape – The
CeedShape
instance to move. It must exist inshapes
.
- move_shape_upwards(shape: ceed.shape.CeedShape)
Moves the shape one shape up. I.e. if there are two shapes and this shape is at index 0, it gets moved to index 1.
This changes the depth ordering of the shapes.
- Parameters
shape – The
CeedShape
instance to move. It must exist inshapes
.
- add_group(group: Optional[ceed.shape.CeedShapeGroup] = None)
Similar to
add_shape()
but for aCeedShapeGroup
.- Params
- group:
CeedShapeGroup
The group to add. If None, the default, a new
CeedShapeGroup
is created and added.
- group:
- Returns
The
CeedShapeGroup
added.
- remove_group(group: ceed.shape.CeedShapeGroup)
Similar to
remove_shape()
but for aCeedShapeGroup
.- Params
- group:
CeedShapeGroup
The group to remove.
- group:
- Returns
True if the group was removed, False otherwise.
- remove_all_groups()
Removes all the
CeedShapeGroup
instances ingroups
.
- add_selected_shapes_to_group(group: Optional[ceed.shape.CeedShapeGroup] = None)
Adds all the
kivy_garden.painter.PaintCanvasBehavior.selected_shapes
to thegroup
.- Params
- group:
CeedShapeGroup
The group to which to add the shapes. If None, the default, a new
CeedShapeGroup
is created.
- group:
- Returns
The
CeedShapeGroup
passed in or created.
- remove_shape_from_groups(shape: ceed.shape.CeedShape)
Removes the
CeedShape
from all the groups.- Params
- shape:
CeedShape
The shape to remove.
- shape:
- get_state(use_cache=False) dict
Returns a dictionary containing all the configuration data for all the shapes and groups. It is used with
set_state()
to later restore the state.- Parameters
use_cache – If True, it’ll get the state using the cache from previous times the state was read and cached, if the cache exists.
- create_shape_from_state(state: dict, old_name_map: Dict[str, ceed.shape.CeedShape])
Overrides
kivy_garden.painter.PaintCanvasBehavior.create_shape_from_state()
and changes its signature.It takes an additional parameter,
old_name_map
. When a shape is created from the givenstate
, the shape’s new name could have been changed automatically so that it remained unique.old_name_map
is a dict that is filled in so the key is the old name (if present instate
) and the associated value is the actual final shape name.
- set_state(state: dict, old_name_map: Dict[str, Union[ceed.shape.CeedShape, ceed.shape.CeedShapeGroup]])
Takes the dict returned by
get_state()
and adds the shapes and groups created form them.old_name_map
is the same as increate_shape_from_state()
.
- class ceed.shape.CeedShape(paint_widget_size=(0, 0), **kwargs)
Bases:
object
A co-base class used with
kivy_garden.painter.PaintShape
derived classes to add Ceed specific functionality to thekivy_garden.painter.PaintShape
classes.- name: str
A unique name associated with the shape.
- no_display: bool
If set to True, the shape will not be displayed in the GUI, but it will still work like normal shapes during an experiment if it’s in a stage.
Not displaying the shape can make the stage/function/shape config load faster when importing from e.g. a yaml file because we don’t have to display it in the GUI. However, the shapes won’t be able to be added to a stage through the GUI, so you’d need to add it to the stage in the same script that generates the shapes. Or, add them to groups and leave the groups visible so it can be dragged to the stage.
- widget = None
The
WidgetShape
used by ceed to customize the shape in the GUI.
- paint_widget_size = (0, 0)
The size of the area used to draw the shapes. A shape is not allowed to have coordinates outside this area.
- get_cached_state(use_cache=False) Dict
Like
get_state()
, but it caches the result. And next time it is called, ifuse_cache
is True, the cached value will be returned, unless the config changed in between. Helpful for backup so we don’t recompute the full state.- Parameters
use_cache – If True, it’ll get the state using the cache from previous times the state was read and cached, if the cache exists.
- Returns
The state dict.
- get_state() dict
Returns a dict representing the shape.
- property bounding_box
Returns the
(x1, y1, x2, y2)
describing the lower left and upper right points that define a bounding box for the shape.
- property centroid
Returns the estimated
(x, y)
centroid of the shape.
- property area
Returns the estimated area of the shape.
- set_area(area)
Sets the internal area of the shape in pixels. We try to get close to the requested area, but it is not likely to be exact.
- Parameters
area – The area to be set.
- property collider
Returns the collider instance from
kivy_garden.collider
used to manipulate and measure the shapes.
- class ceed.shape.CeedShapeGroup(**kwargs)
Bases:
kivy._event.EventDispatcher
Holds a collection of
CeedShape
instances.It is helpful to group them when the same
ceed.function
is to be applied to multiple shapes.- Events
- on_changed:
Triggered whenever a child
CeedShape
is added or removed, or if a configuration option of the objects is changed.
- paint_widget
The same as
kivy_garden.painter.PaintShape.paint_widget
.
- name: str
The unique name of the group. Similar to
CeedShape.name
.
- no_display: bool
Same as
CeedShape.no_display
, but for this group.
- shapes: List[ceed.shape.CeedShape]
A list that contains the
CeedShape
instances that are part of this group.
- widget = None
The
WidgetShapeGroup
used by ceed to customize the group in the GUI.
- get_cached_state(use_cache=False) Dict
Like
get_state()
, but it caches the result. And next time it is called, ifuse_cache
is True, the cached value will be returned, unless the config changed in between. Helpful for backup so we don’t recompute the full state.- Parameters
use_cache – If True, it’ll get the state using the cache from previous times the state was read and cached, if the cache exists.
use_cache – If True, it’ll get the state using the cache from previous times the state was read and cached, if the cache exists.
- Returns
The state dict.
- get_state() dict
Returns a dict representing the shape group.
- add_shape(shape: ceed.shape.CeedShape)
Adds the shape to the group if it is not already in the group.
- remove_shape(shape: ceed.shape.CeedShape)
Removes the shape from the group (and its
CeedShape.widget
) if it is present.
- remove_all()
Removes all the shapes from the group.
- class ceed.shape.CeedPaintCircle(paint_widget_size=(0, 0), **kwargs)
Bases:
ceed.shape.CeedShape
,kivy_garden.painter.PaintCircle
A circle shape.
- class ceed.shape.CeedPaintEllipse(paint_widget_size=(0, 0), **kwargs)
Bases:
ceed.shape.CeedShape
,kivy_garden.painter.PaintEllipse
An ellipse shape.
- class ceed.shape.CeedPaintPolygon(paint_widget_size=(0, 0), **kwargs)
Bases:
ceed.shape.CeedShape
,kivy_garden.painter.PaintPolygon
A polygonal shape.
- class ceed.shape.CeedPaintFreeformPolygon(paint_widget_size=(0, 0), **kwargs)
Bases:
ceed.shape.CeedShape
,kivy_garden.painter.PaintFreeformPolygon
A polygonal shape drawn using freeform points.