fish2eod package

Subpackages

Submodules

fish2eod.math module

class fish2eod.math.BoundaryCondition(value, label)

Bases: object

Helper named tuple for boundary conditions.

value is the value of the boundary condition; it can be a number, a string-like expression i.e. “1+x[0]” or a full dolfin expression

label is the boundary label to apply the value to

label: int
to_dirichlet_condition(v, boundaries)
to_fenics_representation()
Return type:

Expression

to_neumann_condition(v, ds)
Return type:

Form

value: Union[float, str, Expression]

fish2eod.models module

Templates for solving finite element problems.

Model is the base class which defines an interface for creating geometry, meshing, labeling and solving without a full implementation

QESModel adds quasi-electrostatic physics to the Model class

BaseFishModel is the template class for electric fish simulations by specifying convenience api calls for adding geometry, and voltage/current sources while also defining and handling the fish objects

class fish2eod.models.BaseFishModel(ground_radius=0.5, ground_location=(- 20, 20), tank_size=70)

Bases: QESModel

Main class that should be used for all fish simulations.

Defines fish, tank, and ground electrode) along with properties need to solve them. This should be subclassed to implement custom geometries or sources.

BODY_CONDUCTIVITY = 0.00356
GROUND_CONDUCTIVITY = 727.0
ORGAN_CONDUCTIVITY = 0.0092717
WATER_CONDUCTIVITY = 0.00023
add_boundary_assignement_rules()

Add rules for assigning boundaries

If defining new boundaries with custom labels this method should be overwritten

Return type:

Tuple[Callable[[int, int], Tuple[bool, int]]]

Returns:

List of BoundaryBarkers

add_current_sources(**kwargs)

User extendable function to add a current source (constant current).

Overwrite this method and implement something of the form

return [BoundaryCondition(value=0, label=’some_domain’),

BoundaryCondition(value=3, label=’some_other_domain’), …]

You can add additional arguments to represent model parameters which you can use in the condition definition

Parameters:

kwargs – Catchall for remaining parameters

Return type:

Tuple[BoundaryCondition, ...]

add_geometry(**kwargs)

User extendable function to add to the geometry.

Overwrite this method and implement something of the form

self.model_geometry.add_domain(“Domain name”, obj1, obj2, …)

You can add additional arguments to represent model parameters which you can use in the object definition

Parameters:

kwargs – Catchall for remaining parameters

add_voltage_sources(**kwargs)

User extendable function to add a voltage source (constant voltage).

Overwrite this method and implement something of the form

return [BoundaryCondition(value=0, label=self.model_geometry[‘some domain’]),

BoundaryCondition(value=3, label=self.model_geometry[‘some other domain’]), …]

You can add additional arguments to represent model parameters which you can use in the condition definition

Parameters:

kwargs – Catchall for remaining parameters

Return type:

Tuple[BoundaryCondition, ...]

create_geometry(fish_x, fish_y, species='apteronotus', **kwargs)

Create the model geometry by making a fish, tank and ground and adding any additional user geometry.

Parameters:
  • fish_x (Sequence[float]) – x coordinates (head->tail) for the fish

  • fish_y (Sequence[float]) – y coordinates (head->tail) for the fish

  • species (str) – Name of the species

  • kwargs – Catchall for the remaining parameters

generate_save_data()

Add model solution and fish geometry to save data.

Return type:

Tuple

Returns:

Fish specific data: skin geometry, transdermal potential (optional image data) and all parent data

get_boundary_markers()

Get the boundary markers for a model.

A marker is a list of two function with the same signature b1,b2,x,y where b1 is the domain id of the first domain, and b2 is the domain id of the second domain. x, and y are the coordinates of the midpoint of the boundary. Using whatever criteria you wish, a true or false is returned if that boundary follows the criteria. The second function with the same signature b1,b2,x,y returns the boundary ID you want to assign the target boundary.

Return type:

Tuple[Callable[[int, int], Tuple[bool, int]], ...]

Returns:

List of the boundary markers

get_dirichlet_conditions(**kwargs)

Create the dirichlet conditions on the ground electrode and get user conditions.

Parameters:

kwargs – Model parameters to feed into add_voltage_sources

Return type:

Tuple[BoundaryCondition, ...]

get_eod_functions(eod_phase)

Convert the EOD phase into a set of EOD functions to evaluate

Parameters:

eod_phase (Union[float, Sequence[float]]) – The EOD phase for the fish(es)

Return type:

Iterable[CubicSpline]

Returns:

List of evaluable EOD functions

get_neumann_conditions(eod_phase=0.24, **model_parameters)

Generate the Neumann conditions for the model.

By default this is the EOD from the organ but can be extended with BCs from add_current_sourced

Parameters:
  • eod_phase (Union[float, Sequence[float]]) – EOD phase (0<=phase<=1)

  • model_parameters – Catchall for the remaining parameters

inner_skin_rule(b1, b2)

Mark the boundary for inner skin.

Parameters:
  • b1 – Name of lower domain

  • b2 – Name of upper domain

Return type:

Tuple[bool, int]

Returns:

If the boundary should be marked and the label

organ_rule(b1, b2)

Mark the boundary for organ.

Parameters:
  • b1 – Name of lower domain

  • b2 – Name of upper domain

Return type:

Tuple[bool, int]

Returns:

If the boundary should be marked and the label

setup_fish(fish_x, fish_y, species='apteronotus')

Create the fish given coordinates and species.

Parameters:
  • fish_x (Union[Sequence[Sequence[float]], Sequence[float]]) – X coordinates of the fish(es) spine

  • fish_y (Union[Sequence[Sequence[float]], Sequence[float]]) – Y coordinates of the fish(es) spine

  • species (str) – Species of fish to use

solve(image=None, **model_parameters)

Solve the fish model.

Parameters:

model_parameters – all model parameters

update_for_image(null_properties, model_parameters)
class fish2eod.models.Model

Bases: ABC

Model interface for meshing, properties and plotting.

Models are physics and geometry agnostic and knows nothing about these things - this is an internal class and would only be subclassed to develop new physics modules.

abstract build_equations(**model_parameters)

Build the equations to solve.

Must be overwritten in subclasses to define physics :param model_parameters: kwargs catch all for model parameters

compile(n_refine=0, refine_domains=None, recompute_mesh=True, **model_parameters)

Create model mesh, label domains/boundaries and build model equations.

Needs to be called before solving the models

Parameters:
  • n_refine (int) – Number of times to refine the mesh

  • refine_domains (Optional[List[str]]) – Name of domains to refine

  • model_parameters – Model parameter dictionary.

  • recompute_mesh – kwargs catch all for model parameters

Return type:

None

abstract create_geometry(**kwargs)

Create the model geometry

Must be overwritten in subclasses to define geometry

abstract generate_save_data()

Generate save data for the base model.

Subsequent physics specialization should super() and concat their data to save so all relevant is saved

Return type:

Tuple

Returns:

solution, domains, boundaries, and outline

get_boundary_markers()

Get the boundary markers for a model.

A marker is a list of two function with the same signature b1,b2,x,y where b1 is the domain id of the first domain, and b2 is the domain id of the second domain. x, and y are the coordinates of the midpoint of the boundary. Using whatever criteria you wish, a true or false is returned if that boundary follows the criteria. The second function with the same signature b1,b2,x,y returns the boundary ID you want to assign the target boundary.

Return type:

Tuple[Callable[[int, int], Tuple[bool, int]], ...]

Returns:

List of the boundary markers

get_property(property_name)

Get the property object of a named property.

Parameters:

property_name (str) – Name of the property (typically sigma)

Return type:

Property

Returns:

The property object

plot_domains(color='viridis')

Plot labeled domains with color corresponding to their label.

Parameters:

color – Name of the colormap to use

plot_geometry(color='Dark2', legend=False)

Draw geometry.

Parameters:
  • color (str) – Colormap of edges

  • legend (bool) – Whether to label edges in legend

plot_mesh(color='grey')

Draw mesh.

Parameters:

color – Color of edges, defaults to ‘grey’

plot_solution(**kwargs)
refine(refine_domains)

Refine mesh should be overwritten in developed model class as default behaviour is to do nothing.

Parameters:
  • n_refine – Number of times to refine the mesh

  • refine_domains – Name of domains to refine

property solution
abstract solve(**model_parameters)

Solve the system.

Must be overwritten in subclasses to define how to solve :param model_parameters: kwargs catch all for model parameters

structural_compilation()

Perform the actual compilation (tagging, labeling).

structure_to_dataset(structure)
property topology_0d: ndarray

Get mesh node coordinates

Return type:

ndarray

Returns:

Mesh nodes

property topology_1d: ndarray

Get mesh edge topology (edges)

Return type:

ndarray

Returns:

1D topology

property topology_2d: ndarray

Get mesh cell topology (triangles)

Return type:

ndarray

Returns:

2D topology

update_parameter(domain_label, parameter_name, parameter_value, **model_parameters)

Update non-geometric parameters such as conductivity without recomputing mesh.

Parameters:
  • domain_label (int) – Label of domain to update parameter on

  • parameter_name (str) – Name of parameter: for example: sigma

  • parameter_value (float) – New value of parameter

  • model_parameters – Catchall for model parameters

Return type:

None

property verboseness

Get the verboseness level of the model.

class fish2eod.models.QESModel(allow_overlaps=True)

Bases: Model, ABC

FEM framework for solving quasi electrostatic models.

Extends model QES physics work and the ability to add Neumann and Dirichelet conditions

Parameters:

allow_overlaps (bool) – Should the geometry fail if two objects overlap (not including background)

build_equations(**model_parameters)

Create equations in weak form to solve with included sources (neumann conditions).

Parameters:

model_parameters – Catchall kwarg for model parameters

generate_save_data()

Get save data for the model.

Return type:

Tuple

Returns:

None

get_dirichlet_conditions(**model_parameters)

Return the Dirichlet conditions (voltage sources).

By default the external boundaries are grounded. This should be overridden in your model subclass to implement if wanted

Parameters:

model_parameters – Catchall kwarg for model parameters

Return type:

Tuple[BoundaryCondition]

get_neumann_conditions(**model_parameters)

Return the Neumann conditions (current sources).

By default there are none. This should be overridden in your model subclass to implement if wanted

Parameters:

model_parameters – Catchall kwarg for model parameters

Return type:

Tuple[BoundaryCondition]

solve(**model_parameters)

Solve the system.

Parameters:

model_parameters – kwargs of the model parameters

fish2eod.properties module

Helpers for defining complex properties on a fenics domain.

Properties are UserExpressions for performing specific tasks

SplineExpression defines a function on a boundary mapped [start,stop] -> [0, 1] Property defines a scalar on a set of domains by domain_id (e.g. conductivity)

class fish2eod.properties.Property(domains, f, **kwargs)

Bases: UserExpression

Class to handle assigning a property across domains.

Parameters:
  • domains (MeshFunctionSizet) – Labeled domains

  • f (SpatialFunction) – Dictionary with keys being a domain and value being either a value or a function taking x,y

eval_cell(values, x, cell)

Evaluate the property at a coordinate.

Parameters:
  • values (List[float]) – Implicit return: set values[0]=some_number to return

  • x (Tuple[float, float]) – x, y coordinates of the cell

  • cell – Geometry cell (element) the function is being accessed on

static value_shape()

Inform dolfin this expression is a scalar.

Return type:

Tuple

class fish2eod.properties.SpatialFunction

Bases: object

class fish2eod.properties.SplineExpression(boundary, f, **kwargs)

Bases: UserExpression

Assign a spline across a boundary.

Parameters:
  • boundary (LineString) – Linestring representing the boundary

  • f (Callable[[float], float]) – A 1D spline function

eval(values, x)

Evaluate expression at a coordinate.

This function doesn’t return but mutates the array argument as per dolfin requirements

Parameters:
  • values (List[float]) – Implicit return: set values[0]=some_number to return

  • x (Tuple[float, float]) – x, y coordinates

Return type:

None

static value_shape()

Inform dolfin this expression is a scalar.

fish2eod.sweep module

Solve a model repeatedly for multiple versions of parameters (parametric sweeps).

ParameterSet is a generic set of parameters for multiple parameters swept in serial (i.e. (x0, y0), (x1, y1), …) EODPhase is a parameterSet for sweeping the eod phase (0<=p<=1). No other parameters can be added to this FishPosition is a ParameterSet for sweeping the position of the fish

ParameterSweep takes one or more parameter sets and generates the model parameters for all combinations of the sets IterativeSolver iterates over parameter sweep and generates, solves and saves the model

class fish2eod.sweep.EODPhase(phases, set_name='EODPhase')

Bases: ParameterSet

Convenience class for sweeping EOD Phase.

Parameters:
  • phases (Sequence) – Set of phases to use

  • set_name – Name of the parameter set (Default is EODPhase)

add_parameter_set(new_parameter_set)

Overwrite add_parameter_set to disable it.

At the “time-scale” of EOD phase it doesn’t make sense to sweep any other parameters so disable functionality

Return type:

None

validate(parameters)

Validate shape of parameters

Parameters:

parameters (Dict[str, Sequence]) – Dictionary (name: value) of parameters to sweep

Returns:

None

Raises:

Assertion error if parameters are invalid shape

class fish2eod.sweep.FishPosition(fish_x, fish_y, set_name='FishPosition')

Bases: ParameterSet

Convenience class for sweeping fish positions.

Parameters:
  • fish_x (Sequence[Sequence]) – Set of x positions to use

  • fish_y (Sequence[Sequence]) – Set of y positions to use

  • set_name – Name of the parameter set (Default is FishPosition)

validate(parameters)

Validate shape of parameters

Parameters:

parameters (Dict[str, Sequence]) – Dictionary (name: value) of parameters to sweep

Returns:

None

Raises:

Assertion error if parameters are invalid shape

class fish2eod.sweep.IterativeSolver(name, save_path, model, parameter_sweep, **fixed_parameters)

Bases: object

Wrapper to take a model and run it for multiple versions parameter.

Given a parameter sweep (set unique parameters to run through) the IterativeSolver will reset and re-run the model for each parameter set only remeshing when geometric features are changed for optimal performance.

Parameters:
  • model (Type[Model]) – Class of model to create: NOT AN INSTANCE

  • parameter_sweep (ParameterSweep) – parametric sweep to run

  • fixed_parameters – kwarg parameters that are fixed (fish_x / fish_y for example if not sweeping)

run()

Iterate over parameter sweep and solve model with the given parameters.

Return type:

None

run_step(p, do_mesh, parameter_level)

Solve model for a particular parameter step(set).

Parameters:
  • p (Dict[str, float]) – Parameter set to solve the model for

  • do_mesh (bool) – Should the model have its mesh computed

  • parameter_level (Dict[str, int]) – Map of parameter and which version (1,2,3,…) it is

Return type:

None

class fish2eod.sweep.ParameterSet(name, rebuild_mesh=False, **parameters)

Bases: object

Set of parameters to be swept together. For example an x/y coordinate pair need to be kept together.

Validates parameters and will fail if invalid shapes. A given parameter may be of any type as long as internal methods can handle. Exceptions are

Fish coordinates must be numeric arrays [x1, x2, …] for example EODPhase must be a number s.t. 0 <= p <= 1 [p1, p2, …] for example

For a generic parameter or parameter shared across all fish the format is

[p1, p2, p3, …]

For a parameter given individually for each fish the format is

[[p1_fish1, p1_fish2, …] , [p2_fish1, p2_fish2, …] , …]

Parameters:
  • parameters (Sequence) – dictionary of parameter name and list of its parameters

  • name (str) – Name of the parameter set

  • rebuild_mesh – Does the geometry change when parameters do? Yes for geometry parameters no if conductivity

add_parameter_set(new_parameter_set)

Join two existing parameter sets. Only the parent’s name is kept.

Parameters:

new_parameter_set (ParameterSet) – The parameter set to join

Return type:

None

Returns:

None

property parameters: Tuple[str, ...]

Get the names of the parameters inside the ParameterSet.

return: Tuple of the names (order is irrelevant)

Return type:

Tuple[str, ...]

to_sweep()

Convert parameter set to a sweep if only parameter set.

Convenience method to convert this parameter set into a sweep to avoid an extra boilerplate line

Return type:

ParameterSweep

Returns:

The parameter sweep

validate(parameters)

Validate shape of parameters

Parameters:

parameters (Dict[str, Sequence]) – Dictionary (name: value) of parameters to sweep

Return type:

None

Returns:

None

Raises:

Assertion error if parameters are invalid shape

class fish2eod.sweep.ParameterSweep(*parameter_sets)

Bases: object

Generate all combinations of parameter sets.

Parameters:

parameter_set – An arbitrary (>0) number of parameter sets

property remesh_index: int

Get the “canary” index for remeshing.

Considering the ordered ParameterSets’ remesh flags i.e. [True, True, True, False]. When the sets are run through sequentially the right-most remesh_flag containing parameter set will change indicating that the mesh needs to be recomputed

Return type:

int

Returns:

The index of the canary or -1 if there is no remesh

should_remesh(canary_value, new_value)

Determine if the next simulation should be remeshed

Check the canary value against the new value. If it’s changed then remesh the simulation

Parameters:
  • canary_value – The value of the remesh index the last time the simulation was remeshed

  • new_value – The value of the remesh index for the next simulation

Return type:

bool

Returns:

If the simulation should be remeshed

fish2eod.sweep.sort_parameter_sets(parameter_sets)

Get the parameter sets in their efficient order.

Ideally all of the non-remesh parameters would be run sequentially only re-meshing when needed the order should be

Order is remeshable, non-remeshable

Return type:

Sequence[ParameterSet]

Returns:

Parameter sets in their efficient order