Chapter 2 Get started
2.1 Download and import OCTA
The OCTA Python toolbox was created in Python 3.8 and is dependent on the following Python libraries: svgwrite, svg.path, svgpathtools, svgutils, jsonpickle, html2image, svglib, reportlab, colour, and IPython. To start using the OCTA Python toolbox, install octa as well as its dependencies.
pip install octa
Once everything is installed, it can be helpful to import specific functions from the octa library:
from octa.Stimulus import Grid, Outline, Concentric, Stimulus
from octa.Positions import Positions
from octa.patterns import GridPattern, Pattern
from octa.shapes import Ellipse, Rectangle, Triangle, Polygon, RegularPolygon, Path, PathSvg, Image, FitImage, Text
from octa.measurements import Order, Complexity
2.2 Stimulus types & characteristics
The first step when creating a stimulus is to define the type of stimulus one wants to create: a Grid stimulus, an Outline stimulus, or a Concentric stimulus. Whereas a Grid stimulus requires a specified number of rows (n_rows) and columns (n_cols), Outline or Concentric stimuli require a specified number of elements (n_elements). Behind the scenes, the stimulus types Outline and Concentric are defined as Grid stimuli with the number of rows equal to one and the number of columns equal to the number of elements.
If desired, the user can specify additional arguments to customize the stimulus. The following features of the stimulus as a whole can be specified: spacing between rows and columns (in case of a Grid stimulus; row_spacing and col_spacing), shape and shape bounding box (in case of an Outline stimulus; shape and shape_boundingbox), horizontal and vertical margin (when automatic sizing method is used; x_margin and y_margin), stimulus size (when fixed size is needed; size), background color (background_color), background shape (background_shape), stimulus orientation (stim_orientation), mirror value for the stimulus as a whole (stim_mirrorvalue), mask to apply for the stimulus as a whole (stim_mask), and link (stim_link), class label (stim_classlabel), and id label (stim_idlabel) for the stimulus.
By default, stimuli will be autocentered with a horizontal and vertical margin of 20 units in the current user coordinate system (i.e., user units), have a white background color, and an orientation of 0°. The Grid category has a default row and column spacing of 50 user units, and the Outline category by default has a circular shape with a bounding box of 150 by 150 user units. For more information on all stimulus characteristics, please visit the section on stimulus characteristics below.
Besides the Grid, Outline, and Concentric stimulus types, a generic Stimulus type (which can be used for all types of stimuli) is available too. To use the generic Stimulus category, all element characteristics need to be manually specified (positions, boundingboxes, etc.). We strongly recommend against using the generic Stimulus type, as the Grid-based stimulus types have been tested more extensively and are more user-friendly.
2.2.1 Stimulus types
2.2.1.1 Grid
The default Grid stimulus will use octagonal Polygon shapes with a boundingbox of (45,45), a blue fillcolor (#1E90FF), an orientation of 0°, an opacity of 1, and no borderwidth, bordercolor, mirrorvalue, link, classlabel, or idlabel.
Minimal Grid example:
= Grid(n_rows = 3, n_cols = 3) stimulus
2.2.1.2 Outline
Minimal Outline example:
= Outline(n_elements = 9) stimulus
2.2.1.3 Concentric
Minimal Concentric example:
= Concentric(n_elements = 9) stimulus
2.2.1.4 Stimulus
= Stimulus(x_margin = 5, y_margin = 5, size = (150,150), background_color = "lightgrey")
stimulus = Positions.CreateCustomPositions(x = (10,35,75),
stimulus.positions = (10,85,45))
y = [(45,45), (45,45), (45,45)]
stimulus.boundingboxes = [Rectangle, Triangle, Ellipse]
stimulus.shapes = ["red", "green", "blue"]
stimulus.fillcolors
= [0,0,0]
stimulus.orientations = ["black", "black", "black"]
stimulus.bordercolors = [0,0,0]
stimulus.borderwidths = [1,1,1]
stimulus.opacities = ["", "", ""]
stimulus.data = ["", "", ""]
stimulus.links = ["", "", ""]
stimulus.classlabels = ["", "", ""]
stimulus.idlabels = ["", "", ""]
stimulus.mirrorvalues = [0,1,2]
stimulus._element_presentation_order = [{},{},{}] stimulus._attribute_overrides
2.2.2 Stimulus characteristics
The different stimulus properties can be specified when defining the stimulus type, but can also be changed dynamically after the stimulus has been created by assigning a new value to each parameter.
= Grid(n_rows = 3, n_cols = 6, background_color = "gainsboro") stimulus
= Grid(3,3)
stimulus = 6
stimulus.n_cols = "gainsboro" stimulus.background_color
2.2.2.1 Add custom row_spacing or col_spacing
= Grid(3, 3, row_spacing = 60, col_spacing = 45, size = (150,200), background_color = "gainsboro") stimulus
2.2.2.2 Add custom shape or shape_boundingbox
= Outline(36, shape = "img/checkmark.svg", shape_boundingbox = (200,200))
stimulus
= GridPattern.RepeatAcrossElements([(15,15)]) stimulus.boundingboxes
2.2.2.3 Add custom x_margin or y_margin
= Grid(3, 3, x_margin = (0,20), y_margin = 20, background_color = "whitesmoke") stimulus
The default sizing of the stimulus takes into account the maximum bounding box present in the pattern and adjusts all margins to be that size (maximum_boundingbox). If the user prefers a tight fit, they can change the _autosize_method
argument to tight_fit.
Default sizing:
= Grid(3,3, background_color = "gainsboro", x_margin = 0, y_margin = 0)
stimulus = GridPattern.RepeatAcrossColumns([(20,20), (40,40)])
stimulus.boundingboxes = "maximum_boundingbox" stimulus._autosize_method
Using tight_fit:
= Grid(3,3, background_color = "gainsboro", x_margin = 0, y_margin = 0)
stimulus = GridPattern.RepeatAcrossColumns([(20,20), (40,40)])
stimulus.boundingboxes = "tight_fit" stimulus._autosize_method
2.2.2.4 Specify custom size
Please be aware that in case size is specified, x_margin and y_margin arguments are not taken into account.
= Grid(3, 3, background_color = "whitesmoke")
stimulus
= Grid(3, 3, size = (200,200), x_margin = 0, background_color = "gainsboro")
stimulus
= Grid(3, 3, x_margin = (0,20), y_margin = 20, background_color = "whitesmoke")
stimulus
= Grid(3, 3, row_spacing = 60, col_spacing = 45, size = (150,200), background_color = "gainsboro") stimulus
2.2.2.5 Add background_color
= Grid(3, 3, background_color = "whitesmoke") stimulus
2.2.2.6 Add background_shape
Adding a background shape clips the stimulus area to a custom shape. This clipping process does not take into account placement of elements outside of the clipping area (these elements will thus become invisible without further notice), so be aware that this process may hamper a correct calculation of the order and complexity measures. The background shape will be centered automatically. The background shape can be given as a character string or an actual shape definition (e.g., Rectangle, Ellipse, Triangle, including a value for the boundingbox property). When the shape name is given as a character string, the bounding box of the background shape is equal to the stimulus size.
= (300,300)
stimsize = Ellipse(position = (stimsize[0]/2,stimsize[1]/2), boundingbox = stimsize)
clipshape = Grid(6,6, background_color = "lightgrey", size = stimsize, background_shape = clipshape) stimulus
= (300,300)
stimsize = "Ellipse"
clipshape = Grid(6,6, background_color = "lightgrey", size = stimsize, background_shape = clipshape) stimulus
2.2.2.7 Add stim_orientation
Adding a stimulus orientation influences the orientation of the stimulus as a whole (make sure to adapt size or margins of the stimulus accordingly to make the full pattern visible in case of orientation changes). Be aware that the background shape (and its color) will rotate along with the stimulus: you may want to choose a circular background_shape or set background_color to ‘none’. For animation options of the stimulus orientation, check the orientation options as element characteristics.
= Grid(4,4, stim_orientation = 45, x_margin = 50, y_margin = 50) stimulus
2.2.2.8 Add stim_mirrorvalue
The stimulus mirrorvalue mirrors the whole stimulus in the horizontal, vertical, or horizontal & vertical dimension.
= Grid(3, 3, x_margin = 5, y_margin = 5, stim_mirrorvalue = "none")
stimulus = Grid(3, 3, x_margin = 5, y_margin = 5, stim_mirrorvalue = "horizontal")
stimulus = Grid(3, 3, x_margin = 5, y_margin = 5, stim_mirrorvalue = "vertical")
stimulus = Grid(3, 3, x_margin = 5, y_margin = 5, stim_mirrorvalue = "horizontalvertical")
stimulus
= GridPattern.RepeatAcrossColumns([Polygon(5), Triangle])
stimulus.shapes = GridPattern.RepeatAcrossColumns([0,0,45,45]) stimulus.orientations
2.2.2.9 Add stim_mask
When a stimulus mask is added, this adds an image ‘filter’ or mask on top of the stimulus. This mask is not taken into account when calculating the order and complexity measures. The stimulus mask will be centered automatically. The stimulus mask can be given as a character string or an actual shape definition (e.g., Rectangle, Ellipse, Triangle, including a value for the boundingbox property and optionally the fillcolor property). When the shape name is given as a character string, the bounding box of the background shape is equal to the stimulus size.
= (300,300)
stimsize = Ellipse(position = (stimsize[0]/2,stimsize[1]/2), boundingbox = (stimsize[0],stimsize[1]), fillcolor = ["radial", "white", "black"])
shapemask = Grid(6,6, background_color = "lightgrey", size = stimsize, background_shape = clipshape, stim_mask = shapemask) stimulus
2.2.2.10 Add stim_link, stim_classlabel, and stim_idlabel
These arguments add a hyperlink (activated on click), a class label, or an id label to the stimulus respectively. Although adding a class or id label has no immediate visual result, it can be used to add javascript animations or css style changes once you use the svg stimulus in an online context.
= Grid(3,3, stim_link = "https://elinevg.shinyapps.io/OCTA_toolbox/") stimulus
Click the stimulus to visit the hyperlink added to the stimulus:
= Grid(4,4, stim_classlabel = "leftstim", stim_idlabel = "blue_octagons")
stimulus1
= Grid(4,4, stim_classlabel = "rightstim", stim_idlabel = "red_squares")
stimulus2 = GridPattern.RepeatAcrossElements([Rectangle])
stimulus2.shapes = GridPattern.RepeatAcrossElements(["red"]) stimulus2.fillcolors
2.3 Element position patterns
Having created the stimulus, the resulting x and y coordinates for the positions of the elements can be requested via stimulus.positions.GetPositions(). 1 The position of an element is determined by the center of the element’s bounding box (i.e., the rectangle ‘bounding’ the size of the element shape). The default position patterns used for Grid, Outline, and Concentric stimuli are a rectangular grid with a row and column spacing of 50 user units, a circle outline with radius 150, and identical (0,0) positions respectively. The user can replace the default position pattern for the stimulus type by a custom one (e.g., a sinewave-shaped grid, a custom shape outline, random positions within a specified rectangle, manually specified positions).
= Grid(3,3, background_color = "gainsboro")
stimulus stimulus.positions.GetPositions()
## ([0, 50, 100, 0, 50, 100, 0, 50, 100], [0, 0, 0, 50, 50, 50, 100, 100, 100])
2.3.1 Rectangular grid
New rectangular grid element positions can be applied using Positions.CreateRectGrid(n_rows, n_cols, row_spacing, col_spacing). The default value for row_spacing and column_spacing is 50. If you have already specified row and column spacing when defining the stimulus type, please define row and column spacing again within this function (it will not take into account your previously defined row and column spacing).
= Positions.CreateRectGrid(1,9) stimulus.positions
2.3.2 Sinewave-shaped grid
Positions for a sinewave-shaped grid can be applied using Positions.CreateSineGrid(n_rows, n_cols, row_spacing, col_spacing, A, f, axis). Parameters A (amplitude), f (frequency), and axis (‘x’, ‘y’, or ‘xy’) have default values of 25, 0.1, and ‘x’ respectively.
= Grid(3,12)
stimulus = Positions.CreateSineGrid(n_rows = 3, n_cols = 12, A = 25, f = .1, axis = "xy") stimulus.positions
2.3.3 Circle outline
To get element positions that form a circle, the function Positions.CreateCircle(radius, n_elements, starting_point = “left”) can be used. The starting point can be set to ‘left’, ‘right’, ‘top’, or ‘bottom’.
= Grid(1,6, background_color = "gainsboro")
stimulus = Positions.CreateCircle(radius = 50, n_elements = 6) stimulus.positions
2.3.4 Custom shape outline
To get element positions that form a specified path, the function Positions.CreateShape(n_elements, src, path, width = 300, height = 300) can be used. The user either provides the name of an svg file that contains the shape to be used or defines an svg path string manually. The starting point of the path shape depends on how the specified path is defined.
= Grid(1,100, background_color = "gainsboro")
stimulus = GridPattern.RepeatAcrossElements([(10,10)])
stimulus.boundingboxes
= Positions.CreateShape(src = "img/checkmark.svg", n_elements = 100, width = 250, height = 250) stimulus.positions
2.3.5 Random positions
To get random element positions for a fixed number of elements, the function Positions.CreateRandomPositions(n_elements, width, height, min_distance, max_iterations) can be used. Default values for width and height are 300. The default minimum distance between all generated positions (min_distance) is 30. The default maximum number of iterations (max_iterations; i.e., how many times the algorithm should try to generate positions if the min_distance criterion can not be satisfied) is 10.
= Grid(1,9, background_color = "whitesmoke")
stimulus = Positions.CreateRandomPositions(n_elements = 9, width = 200, height = 150, min_distance = 30, max_iterations = 10) stimulus.positions
2.3.6 Custom positions
Custom x and y coordinates can be specified using Positions.CreateCustomPositions(x,y):
= [20,20,40, 80,80,100, 160,160,160]
new_x = [20,80,160, 20,80,160, 40,100,160]
new_y = Positions.CreateCustomPositions(x = new_x, y = new_y) stimulus.positions
2.4 Element features
Once the stimulus features and element positions are specified, the pattern types, pattern directions, and pattern values for the different element features can be adjusted. The patterns can be applied to the following element characteristics: shapes, boundingboxes (i.e., the size of the bounding box in which the elements fit), fillcolors, orientations, borderwidths, bordercolors, opacities, mirrorvalues (i.e., whether some of the elements need to be mirrored), links, classlabels, and idlabels.
Later in this section (cf. Feature values) we will give a more detailed overview of all these element features and their value options, but first we detail the different patterns that can be applied to the feature dimensions.
2.4.1 Feature patterns
2.4.1.1 GridPatterns
The values for the different element characteristics are applied to the elements by following a specific pattern type and direction. In Grid and Outline stimuli, one value per element characteristic is repeated across all elements in the stimulus by default. In Concentric stimuli, a pattern with two fillcolors is repeated across all elements in the stimulus by default, and the boundingbox sizes follows a decreasing gradient across elements.
Available pattern types for grid structures include pattern repetition (repeat), element repetition (elementrepeat), mirror symmetry (mirror), and a gradient from a start value to an end value (gradient). These patterns can be applied along the following pattern directions: across elements, across rows, across columns, across the left diagonal, across the right diagonal, and across layers. In addition, more complex patterns can be constructed using the TiledGrid and TiledElementGrid options. Finally, a random application of the values for the element characteristic across the elements is possible too (random). By default, the pattern values in the RandomPattern are repeated until the length is equal to the number of elements in the stimulus. Optionally, a list of frequencies can be provided to determine how many times each pattern value has to be present. In Outline and Concentric stimuli, it is strongly advised to apply patterns across elements (as other pattern directions will not be distinguishable in Outline and Concentric stimuli).
The default direction in which the pattern is applied is from top to bottom and from left to right (“tblr”).
We will show the different pattern options here on the basis of the fillcolor argument.
2.4.1.1.1 RepeatAcrossElements, RepeatAcrossRows, RepeatAcrossColumns, RepeatAcrossLeftDiagonal, RepeatAcrossRightDiagonal, RepeatAcrossLayers
= Grid(12,12, row_spacing = 16, col_spacing = 16)
stimulus = GridPattern.RepeatAcrossElements([(12,12)])
stimulus.boundingboxes
= GridPattern.RepeatAcrossElements(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.RepeatAcrossRows(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.RepeatAcrossColumns(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.RepeatAcrossLeftDiagonal(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.RepeatAcrossRightDiagonal(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.RepeatAcrossLayers(["red", "green", "blue"]) stimulus.fillcolors
2.4.1.1.2 ElementRepeatAcrossElements, ElementRepeatAcrossRows, ElementRepeatAcrossColumns, ElementRepeatAcrossLeftDiagonal, ElementRepeatAcrossRightDiagonal, ElementRepeatAcrossLayers
= Grid(12,12, row_spacing = 16, col_spacing = 16)
stimulus = GridPattern.RepeatAcrossElements([(12,12)])
stimulus.boundingboxes
= GridPattern.ElementRepeatAcrossElements(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.ElementRepeatAcrossRows(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.ElementRepeatAcrossColumns(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.ElementRepeatAcrossLeftDiagonal(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.ElementRepeatAcrossRightDiagonal(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.ElementRepeatAcrossLayers(["red", "green", "blue"]) stimulus.fillcolors
2.4.1.1.3 MirrorAcrossElements, MirrorAcrossRows, MirrorAcrossColumns, MirrorAcrossLeftDiagonal, MirrorAcrossRightDiagonal, MirrorAcrossLayers
= Grid(12,12, row_spacing = 16, col_spacing = 16)
stimulus = GridPattern.RepeatAcrossElements([(12,12)])
stimulus.boundingboxes
= GridPattern.MirrorAcrossElements(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.MirrorAcrossRows(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.MirrorAcrossColumns(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.MirrorAcrossLeftDiagonal(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.MirrorAcrossRightDiagonal(["red", "green", "blue"])
stimulus.fillcolors = GridPattern.MirrorAcrossLayers(["red", "green", "blue"]) stimulus.fillcolors
2.4.1.1.4 GradientAcrossElements, GradientAcrossRows, GradientAcrossColumns, GradientAcrossLeftDiagonal, GradientAcrossRightDiagonal, GradientAcrossLayers
= Grid(12,12, row_spacing = 16, col_spacing = 16)
stimulus = GridPattern.RepeatAcrossElements([(12,12)])
stimulus.boundingboxes
= GridPattern.GradientAcrossElements(start_value = "red", end_value = "green")
stimulus.fillcolors = GridPattern.GradientAcrossRows(start_value = "red", end_value = "green")
stimulus.fillcolors = GridPattern.GradientAcrossColumns(start_value = "red", end_value = "green")
stimulus.fillcolors = GridPattern.GradientAcrossLeftDiagonal(start_value = "red", end_value = "green")
stimulus.fillcolors = GridPattern.GradientAcrossRightDiagonal(start_value = "red", end_value = "green")
stimulus.fillcolors = GridPattern.GradientAcrossLayers(start_value = "red", end_value = "green") stimulus.fillcolors