\

\section{\sofa \ Python API}

\subsection{The \textcode{Sofa} module}

The core of this plugin is the \textcode{Sofa} Python module available to python scripts from within the SofaPython components (they are not available outside Sofa environment, in the command-line \textcode{python} binary for example).

Therefore, each python script to be imbedded in \sofa should include the following line if it wants to interact with the \sofa framework:

\begin{code_python}
import Sofa
\end{code_python}

This module provides a wide range of methods and types, bound to essential \sofa \ framework features.

These can be used from python within scripts loaded by the components provided by this plugin.

%Module methods 
\subsection{Module methods}

SofaPython provides several module methods, for general purpose (not linked to a particular node or component, for example).

\begin{itemize}
\item \textcode{sendGUIMessage(msgType,msgValue)} 
\item \textcode{createObject(type[, datafield=value [,...] ])} creates an object. ex: \textcode{node.createObject('UniformMass',totalmass=1)} See "Creating graph objects in Python" section for more info.
\end{itemize}

%Class Hierarchy
\subsection{Types hierarchy}

The class hierarchy in the \textcode{Sofa} module is quite different from the C++ \sofa \ class hierarchy. Not all \sofa \ classes are bound in Python, and some levels in the hierarchy are skipped.

Despite the ability of Python to support multi-heritage, this feature has not been implemented in the \textcode{Sofa} module, for code simplicity.


\begin{figure}[htbp]
\begin{center}
\Tree [.Base [.BaseContext [.Context [.BaseNode Node ] ] ] 
			[.BaseObject [.BaseState [.BaseMechanicalState MechanicalObject ] ] [.BaseLoader MeshLoader ] 
			[.Topology [.BaseMeshTopology [.MeshTopology GridTopoligy ] ] ] ] ]
\Tree [.Vector3 ]
\Tree [.LinearSpring ]
\Tree [.Data DisplayFlagsData ]
\caption{Sofa python types hierarchy}
\label{default}
\end{center}
\end{figure}

\newpage

%Sofa.Vector3
\subsubsection{Sofa.Vector3}
Attributes :
\begin{itemize}
\item \textcode{x} 
\item \textcode{y}
\item \textcode{z}
\end{itemize}

%Sofa.LinearSpring
\subsubsection{Sofa.LinearSpring}
Attributes :
\begin{itemize}
\item \textcode{Index1} : the first extremity of the spring
\item \textcode{Index2} : the second extremity of the spring
\item \textcode{Ks} : spring stiffness
\item \textcode{Kd} : damping factor
\item \textcode{L} : rest length of the spring
\end{itemize}

%Sofa.Topology
\subsubsection{Sofa.Topology}
Methods :
\begin{itemize}
\item \textcode{haspos()} 
\item \textcode{getNbPoints()}
\item \textcode{setNbPoints(n)}
\item \textcode{getPX(i)} 
\item \textcode{getPY(i)} 
\item \textcode{getPZ(i)} 
\end{itemize}

%Sofa.BaseMeshTopology
\subsubsection{Sofa.BaseMeshTopology}
Methods :
\begin{itemize}
\item \textcode{getNbEdges()} 
\item \textcode{getNbTriangles()}
\item \textcode{getNbQuads()}
\item \textcode{getNbTetrahedra()}
\item \textcode{getNbHexahedra()}
\end{itemize}

%Sofa.GridTopology
\subsubsection{Sofa.GridTopology}
Methods :
\begin{itemize}
\item \textcode{setSize(nx,ny,nz)} 
\item \textcode{setNumVertices(nx,ny,nz)} 
\item \textcode{getNx()}
\item \textcode{getNy()}
\item \textcode{getNz()}
\item \textcode{setNx(n)}
\item \textcode{setNy(n)}
\item \textcode{setNz(n)}
\end{itemize}

%Sofa.RegularGridTopology
\subsubsection{Sofa.RegularGridTopology}
Methods :
\begin{itemize}
\item \textcode{setPos(xmin,xmax,ymin,ymax,zmin,zmax))} 
\end{itemize}

%BASE
\subsubsection{Sofa.Base}
Methods :
\begin{itemize}
\item \textcode{findData(name)} returns a \textcode{Sofa.Data} object (if it exists)
\end{itemize}
Attributes:
\begin{itemize}
\item \textcode{name} 
\end{itemize}

\subsubsection{Sofa.BaseObject}
Methods :
\begin{itemize}
\item \textcode{init()}
\item \textcode{bwdInit()}
\item \textcode{reinit()}
\item \textcode{storeResetState()}
\item \textcode{reset()}
\item \textcode{cleanup()}
\item \textcode{getContext() returns a \textcode{Sofa.BaseContext} object}
\item \textcode{getMaster() returns a \textcode{Sofa.BaseObject} object}
\item \textcode{setSrc(valueString, loader)} use a \textcode{Sofa.BaseLoader} to initialize the object
\end{itemize}

\subsubsection{Sofa.BaseState}
Methods :
\begin{itemize}
\item \textcode{resize(size)}
\end{itemize}

\subsubsection{Sofa.BaseMechanicalState}
Methods :
\begin{itemize}
\item \textcode{applyTranslation(x,y,z)}
\item \textcode{applyRotation(x,y,z)} Euler angles in degrees.
\item \textcode{applyScale(x,y,z)} 
\end{itemize}

\subsubsection{Sofa.MechanicalObject}
Methods :
\begin{itemize}
\item \textcode{setTranslation(x,y,z)} Initial transformations accessor.
\item \textcode{setRotation(x,y,z)} Initial transformations accessor. Euler angles in degrees.
\item \textcode{setScale(x,y,z)} Initial transformations accessor.
\item \textcode{getTranslation()} returns a \textcode{Sofa.Vector3} object. Initial transformations accessor.
\item \textcode{getRotation()} returns a \textcode{Sofa.Vector3} object. Initial transformations accessor. Euler angles in degrees.
\item \textcode{getScale()} returns a \textcode{Sofa.Vector3} object. Initial transformations accessor.
\end{itemize}

\subsubsection{Sofa.BaseContext}
Methods :
\begin{itemize}
\item \textcode{getRootContext()} 
\item \textcode{getTime()} 
\item \textcode{getDt()} 
\item \textcode{getGravity()} returns a \textcode{Sofa.vec3} object
\item \textcode{setGravity(Vec3)} 
\item \textcode{createObject(type[, datafield=value [,...] ])} creates an object. ex: \textcode{node.createObject('UniformMass',totalmass=1)} See "Creating graph objects in Python" section for more info.
\item \textcode{getObject(path)}
\item \textcode{getObjects()}  returns the list of components in this context (locally) 
\end{itemize}
Attributes:
\begin{itemize}
\item \textcode{active}  (boolean)
\item \textcode{animate}  (boolean)
\end{itemize}


\subsubsection{Sofa.Context}
(empty)
\subsubsection{Sofa.Node}
\begin{itemize}
\item \textcode{createChild(childName)} 
\item \textcode{getRoot()} returns the root node of the graph (if any) 
\item \textcode{getChild(path)} returns a child node, given its path (if any) 
\item \textcode{getChildren()} returns the list of children 
\item \textcode{getParents()} returns the list of parents
\item \textcode{executeVisitor(visitor)} executes a python visitor from this node. See "Visitors" section for more infos.
\item \textcode{simulationStep(dt)} executes ONE step of simulation, using dt (in seconds, float) as delta time. 
\item \textcode{init()} Initialize the scene 
\item \textcode{reset()} Reset the scene 
\item \textcode{addObject(object)} 
\item \textcode{removeObject(object)} 
\item \textcode{addChild(childNode)} 
\item \textcode{removeChild(childNode)} 
\item \textcode{moveChild(childNode)} 
\item \textcode{detachFromGraph()} 
\item \textcode{sendScriptEvent(eventName, data)} propagates a script event from this node; eventName is the name of the event (string) and data is whatever you want: scalar, float, array, ... as long as it is a python object or structure. Other PythonScriptController will then receive the correponding \textcode{onScriptEvent(senderName, eventName, data)}. Useful for inter-script communications (see ScriptEvent.scn sample scene in the examples folder).
\end{itemize}


%DATA
\subsubsection{Sofa.Data}
Attributes :
\begin{itemize}
\item value
\item name
\end{itemize}
Methods :
\begin{itemize}
\item getValue(index)
\item setValue(index,value)
\end{itemize}

%DATA
\subsubsection{Sofa.DisplayFlagsData}

This class is always used in a "VisualStyle' object in the root node; see example below. It is used to control what should be displayed.

Attributes :
\begin{itemize}
\item showAll
\item showVisual
\item showVisualModels
\item showBehavior
\item showBehaviorModels
\item showForceFields
\item showInteractionForceFields
\item showCollision
\item showCollisionModels
\item showBoundingCollisionModels
\item showMapping
\item showMappings
\item showMechanicalMappings
\item showOptions
\item showWireFrame
\item showNormals
\end{itemize}
Unlike in C++ code, all these attributes are boolean values for simplicity.
Some attributes (like showAll) are hierarchicaly above others: setting them to \textcode{True} or \textcode{False} will set children attributes also; reading them will return \textcode{True} if their real C++ state is true or neutral.

\begin{figure}[htbp]
\begin{center}
\Tree [.All [.Visual VisualModels  ] 
			[ .Behavior BehaviorModels ForceFields Interactions ]
			[ .Collision CollisionModels BoundingCollisionModels ]
			[ .Mapping Mappings MechanicalMappings ]
			[ .Options Wireframe Normals ] ]
\caption{display flags hierarchy}
\label{default}
\end{center}
\end{figure}



Simple example of use:
\begin{code_python}
 style = node.getRoot().createObject('VisualStyle')
 style.findData('displayFlags').showBehaviorModels = True
\end{code_python}


\subsubsection{Data members: the most important thing in \sofa Python API}

The most important class is \textcode{Sofa.Base}, and its associated method \textcode{findData}.
ALMOST EVERYTHING in \sofa is stored in Datas, and with the only \textcode{Sofa.Base.findData} method, almost everything is possible.
Through the \textcode{Sofa.Data class} (returned by \textcode{Sofa.Base.findData(name)} ) it is possible to read or write almost any object value, thus interact with the simulation in real-time.

This way, even if a specific component isn't bound to python, it's possible to access it by its \textcode{Sofa.Base} heritage.

\textcode{Data.value} attribute has a versatile behavior, depending on the Data type.

On read, \textcode{Data.value} can return either an integer, a float, a string, or even a list of one of these 3 types.
On write, you have to set EXACTLY the proper type, or you can set a string (same format as in the *.scn xml files).

Examples:

\begin{code_python}
print str(node.findData('gravity').value
\end{code_python}
will output the text conversion of a list of 3 floats :
\begin{code_bash}
[0.0, -9.81, 0.0]
\end{code_bash}

You can set it in two ways ; the native version :
\begin{code_python}
node.findData('gravity').value = [0.0, -9.81, 0.0]
\end{code_python}
or by the text version:
\begin{code_python}
node.findData('gravity').value = '0.0  -9.81 0.0'
\end{code_python}

Use of any other type will result in an error.
The following won't work for example :
\begin{code_python}
node.findData('gravity').value = 9.81
\end{code_python}

