Difference between revisions of "AnyWave:WritePythonScripted"

From WikiMEG
Jump to: navigation, search
(getData(start, duration, , ))
(Replaced content with "The Python API is under development to match the new MATLAB API.<br /> We are sorry for the inconvenience.")
Line 1: Line 1:
=Introduction=
+
The Python API is under development to match the new MATLAB API.<br />
This section targets people who have a good knowledge and practice of the Python programming language.<br/>
+
We are sorry for the inconvenience.
The purpose is to explain how to write a Python script that will be the heart of a plug-in executed by AnyWave.<br/>
+
We will also explain how to create a text file to describe our plug-in to AnyWave<br/>
+
 
+
The AnyWave-Python API (Application Programming Interface) consists in a Python module that is automatically imported in the Python environment by AnyWave.
+
 
+
Some packages are also embeded in AnyWave:
+
* numpy
+
* scipy
+
* pyqtgraph
+
* sklearn
+
* nibabel
+
* openGL
+
* matplotlib
+
 
+
=Where to start?=
+
The first thing to do is to create the basic structure for a plug-in.<br/>
+
A Python Scripted plug-in is very simple, it is a folder containing at least two files:
+
* desc.txt (a text file describing the plug-in)
+
* __main__.py (the Python code)
+
 
+
=Writing the desc.txt file=
+
The file must be named '''desc.txt''' and may looks like:
+
<syntaxhighlight lang="text">
+
name = Python plug-in
+
description = I am a Python test plugin
+
category = Process:Python:My Python Plugin
+
</syntaxhighlight>
+
 
+
The category line is optional. It tells AnyWave where the plug-in will appear in the menus. Here we decided to caterogize it as a Process, with a sub category called Python. Finally, the plug-in name will be My Python Plugin.
+
 
+
The category feature is usefull to separate plug-in that won't really do some calculation but convert data to another format on launch external tools.
+
 
+
Three category keywords are recognized:
+
* Process :  The plug-in will be set in the Processes menu with a subcategory and a name, for example 'Process:Correlation:Compute correlation'
+
* File: The plug-in will be set in the File Menu under the Export sub-menu. Example : 'File:Export to Numpy array format'
+
* View: The plug-in will be set in the View Menu. Example : 'View:Launch 3D viewer'
+
 
+
If no category is specified, AnyWave will set the plug-in in the Processes menu using the name defined in the file.
+
 
+
=Copy the folder to the right location=
+
The prefered location is the user's AnyWave directory.
+
[[File:Python location.png|center]]
+
 
+
See that the folder is placed in the Python subfolder. This will allow AnyWave to recognize it as a Python plug-in.
+
 
+
=Check that the plug-in is available=
+
[[File:Loaded_plugin.png|center]]
+
 
+
=The Python module=
+
AnyWave will execute the Python plug-in in a separated Python environment which is embedded in the application.
+
 
+
A Python interpreter will execute the script '__main.py__' of our plug-in.
+
 
+
Before the script is being executed, AnyWave will do some initializing like importing a module named anywave in the Python's environment.
+
 
+
The module provides methods and attributes that will allow interactions between AnyWave and the Python script's environment.
+
 
+
==Attributes==
+
Here is a brief descriptions of available attributes and methods: (parameters between <> are optional)
+
{| class="wikitable"
+
|-
+
! Attributes !! Short description
+
|-
+
| input_channels || The list of input channels set for the plug-in by AnyWave.
+
|-
+
| data_path || A string containing the full path to the data file. (Empty before calling getDataInfo or getData)
+
|-
+
| total_duration || A double value which is the total duration of data in seconds. Set to zero before any call to getData or getDataInfo.
+
|-
+
|}
+
 
+
===input_channels===
+
This attribute is a list of channel objects. A channel object contains the following attributes:
+
* label - a string which is the electrode name
+
* ref - a string with the name of the reference electrode. Can be empty if no reference is set.
+
* data - a numpy array containing the signal.
+
 
+
===markers===
+
AnyWave handle markers that are converted in Python objects.
+
 
+
A marker object is defined with the following attributes:
+
* label - a string which is the label of the marker.
+
* position - double value marking the position in seconds in data.
+
* duration - double value indicating the duration of the marker. Can be 0. for simple markers.
+
* value - a integer value optionaly associated with the marker.
+
* targets - a tuple of strings which is a list of targeted channels.
+
 
+
==Methods==
+
{| class="wikitable"
+
|-
+
! Methods !! Short description
+
|-
+
| [[#getData(start, duration, <keyword>, <filtering options>)|getData(start, duration, <keyword>, <filtering options>]] || get data for input channels.
+
|-
+
| [[#getDataInfo()|getDataInfo()]] || get data information (fill the data_path and total_duration attributes)
+
|-
+
| [[#getInputChannels()|getInputChannels()]] || get information about input channels. Set the input_channels attibutes.
+
|-
+
| [[#getMarkers(filter, <keywords>)|getMarkers(filter, <keywords>)]] || get markers.
+
|-
+
| [[#addMarker(keywords)|addMarker(keywords)]] || add a new marker.
+
|}
+
 
+
===getData(start, duration, <keyword>, <filtering options>)===
+
This method will request data for input channels.
+
 
+
start must be the starting position in data, in seconds.
+
 
+
duration must be the duration of data in seconds or -1 for all the data after the starting position.
+
 
+
Optional parameters can be provided to ask for specific filtering options on data. If no optional parameter is provided, data will be filtered depending on the filtering options set in AnyWave.
+
 
+
keyword can be:
+
* 'No Filtering' - means that we don't want AnyWave to apply any filter on data.
+
* 'User Filtering Options' - means that we want to set the filtering options on data.
+
 
+
 
+
Getting data as they are filtered by AnyWave:
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
# Get data and filter them as they are filtered in AnyWave.
+
anywave.getData(0, -1)
+
 
+
# data are part of input_channels objects.
+
# Accessing first channel's data
+
data = anywave.input_channels[0].data
+
</syntaxhighlight>
+
 
+
Getting data with no filtering applied:
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
# Get data and ask AnyWave to NOT filter them.
+
anywave.getData(0, -1, 'No Filtering')
+
 
+
# data are part of input_channels objects.
+
# Accessing first channel's data
+
data = anywave.input_channels[0].data
+
</syntaxhighlight>
+
 
+
Getting data with specific filtering options:
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
# define our filtering options:
+
filters = {'eeg hp' : 1, 'eeg lp' : 10}
+
# We ask for EEG filtering with High Pass at 1Hz and Low Pass at 10Hz
+
# If input channels are of type EEG they will be filtered as requested by AnyWave
+
 
+
# Get data
+
anywave.getData(0, -1, 'User Filtering Options', filters)
+
 
+
# data are part of input_channels objects.
+
# Accessing first channel's data
+
data = anywave.input_channels[0].data
+
</syntaxhighlight>
+
 
+
===getDataInfo()===
+
This method will set the data_path and total_duration attributes.
+
 
+
This method is automatically called by getData().
+
 
+
=== getInputChannels()===
+
This method will get the list of channel objects set as input channels for the plug-in.
+
The attribute input_channels is updated after calling this method.
+
 
+
'''Warning''': Calling this method '''AFTER''' a call to getData will erase the data as the channel objects are destroyed and replaced by new ones.
+
 
+
===getMarkers(filter, <keywords>)===
+
This method will get markers that are currently set in AnyWave.
+
 
+
The filter parameter is a string indicating what kind of markers we want to retreive.
+
filter can be:
+
* 'all markers' - Get all the markers.
+
* 'by label' - Get markers depending on label
+
* 'by value' - Get markers depending on value
+
 
+
 
+
Example of a script which gets all the markers and dump the list:
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
markers = anywave.getMarkers('all markers')
+
for marker in markers:
+
    print marker.label
+
    print marker.position
+
    print marker.value
+
    print marker.targets
+
    print '\n'
+
</syntaxhighlight>
+
 
+
 
+
Example of a script which only gets markers named '''Marker 1'''
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
markers = anywave.getMarkers('by label', 'Marker 1')
+
# markers can be an empty list if no markers match the label Marker 1 in AnyWave.
+
for marker in markers: 
+
    print marker.label
+
    print marker.position
+
    print marker.value
+
    print marker.targets
+
    print '\n'
+
</syntaxhighlight>
+
 
+
 
+
Example of a script which only gets markers with a value of '''5'''
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
markers = anywave.getMarkers('by value', 5)
+
# markers can be an empty list if no markers got the corresponding value.
+
for marker in markers: 
+
    print marker.label
+
    print marker.position
+
    print marker.value
+
    print marker.targets
+
    print '\n'
+
</syntaxhighlight>
+
 
+
===addMarker(keywords)===
+
This method adds a marker to the ones currently set in AnyWave.
+
 
+
Two parameters or keywords must be provided:
+
* the label.
+
* the position in file.
+
 
+
Example of a script adding different markers:
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
 
+
# add a marker at position 10s
+
anywave.addMarker('My Marker', position  = 10.)
+
 
+
# add a marker at position 15 with a value of 4
+
anywave.addMarker('My Marker 2', position = 15., value = 4)
+
 
+
# add a marker at position 25.3s which targets channels A1 and A2 only
+
anywave.addMarker('My Marker', position = 25.3, targets = ('A1', 'A2',))
+
 
+
# add a marker at position 32s with a duration of 10s (Marking 10s of data starting at 32s)
+
anywave.addMarker('My Selection', position = 32., duration = 10.)
+
</syntaxhighlight>
+
 
+
=Example=
+
 
+
Here is a script that will display the first input channel using a simple Qt application.
+
<syntaxhighlight lang="python">
+
#
+
# The AnyWave python module is automatically imported, so we don't need to import it again
+
#
+
import numpy as np
+
import pyqtgraph as pg
+
from PySide import QtGui
+
 
+
# get all the data with current AnyWave filtering options
+
anywave.getData(0, -1)
+
 
+
data = anywave.input_channels[0].data
+
y = data
+
x = np.arange(data.size)
+
 
+
app = QtGui.QApplication([])
+
w = QtGui.QWidget()
+
plot = pg.PlotWidget()
+
layout = QtGui.QGridLayout()
+
w.setLayout(layout)
+
layout.addWidget(plot, 0, 0)
+
 
+
pg.plot(x, y)
+
app.exec_()
+
app.exit()
+
</syntaxhighlight>
+

Revision as of 11:57, 24 March 2016

The Python API is under development to match the new MATLAB API.
We are sorry for the inconvenience.