1+ ========
12Tutorial
23========
34
@@ -10,44 +11,320 @@ this tutorial we will discuss the major features of `biosppy` and introduce the
1011terminology used by the package.
1112
1213What are Biosignals?
13- --------------------
14+ ====================
15+
16+ Biosignals, in the most general sense, are measurements of physical properties
17+ of biological systems. These include the measurement of properties at the
18+ cellular level, such as concentrations of molecules, membrane potentials, and
19+ DNA assays. On a higher level, for a group of specialized cells (i.e. an organ)
20+ we are able to measure properties such as cell counts and histology, organ
21+ secretions, and electrical activity (the electrical system of the heart, for
22+ instance). Finally, for complex biological systems like the human being,
23+ biosignals also include blood and urine test measurements, core body
24+ temperature, motion tracking signals, and imaging techniques such as CAT and MRI
25+ scans. However, the term biosignal is most often applied to bioelectrical,
26+ time-varying signals. The following sub-sections briefly describe the biosignals
27+ covered by `biosppy `.
28+
29+
30+
31+ The following biosignals form the focus of `biosppy `:
32+
33+ * Blood Volume Pulse (BVP);
34+ * Electrocardiogram (ECG);
35+ * Electrodermal Activity (EDA);
36+ * Electroencephalogram (EEG);
37+ * Electromyogram (EMG);
38+ * Respiration (Resp).
39+
40+ Bla.
41+
42+ ECG
43+ ---
44+
45+ Bla.
46+
47+ EMG
48+ ---
49+
50+ Bla.
1451
1552A very cool thing [ABCD88a ]_.
1653Another cool thing [ABCD88b ]_.
1754
1855What is Pattern Recognition?
19- ----------------------------
56+ ============================
2057
2158Bla.
2259
23- A Note on Return Types
24- ----------------------
60+ A Note on Return Objects
61+ ========================
2562
26- Bla.
63+ Before we dig into the core aspects of the package, you will quickly notice
64+ that many of the methods and functions defined here return a custom object
65+ class. This return class is defined in :py:class: `biosppy.utils.ReturnTuple `.
66+ The goal of this return class is to strengthen the semantic relationship
67+ between a function's output variables, their names, and what is described in
68+ the documentation. Consider the following function definition:
69+
70+ .. code :: python
71+
72+ def compute (a , b ):
73+ """ Simultaneously compute the sum, subtraction, multiplication and
74+ division between two integers.
75+
76+ Args:
77+ a (int): First input integer.
78+ b (int): Second input integer.
79+
80+ Returns:
81+ (tuple): containing:
82+ sum (int): Sum (a + b).
83+ sub (int): Subtraction (a - b).
84+ mult (int): Multiplication (a * b).
85+ div (int): Integer division (a / b).
86+
87+ """
88+
89+ if b == 0 :
90+ raise ValueError (" Input 'b' cannot be zero." )
91+
92+ v1 = a + b
93+ v2 = a - b
94+ v3 = a * b
95+ v4 = a / b
96+
97+ return v1, v2, v3, v4
98+
99+ Note that Python doesn't actually support returning multiple objects. In this
100+ case, the ``return `` statement packs the objects into a tuple.
101+
102+ .. code :: python
103+
104+ >> > out = compute(4 , 50 )
105+ >> > type (out)
106+ < type ' tuple' >
107+ >> > print out
108+ (54 , - 46 , 200 , 0 )
109+
110+ This is pretty straightforward, yet it shows one disadvantage of the native
111+ Python return pattern: the semantics of the output elements (i.e. what each
112+ variable actually represents) are only implicitly defined with the ordering
113+ of the docstring. If there isn't a dosctring available (yikes!), the only way
114+ to figure out the meaning of the output is by analyzing the code itself.
115+
116+ This is not necessarily a bad thing. One should always try to understand,
117+ at least in broad terms, how any given function works. However, the initial
118+ steps of the data analysis process encompass a lot of experimentation and
119+ interactive exploration of the data. This is important in order to have an
120+ initial sense of the quality of the data and what information we may be able to
121+ extract. In this case, the user typically already knows what a function does,
122+ but it is cumbersome to remember by heart the order of the outputs, without
123+ having to constantly check out the documentation.
124+
125+ For instance, the `numpy.histogram
126+ <http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html> `_
127+ function returns first the edges or the values of the histogram? Maybe it's the
128+ edges first, which correspond to the x axis. Oops, it's actually the other way
129+ around...
130+
131+ In this case, it could be useful to have an explicit reference directly in the
132+ return object to what each variable represents. Returning to the example above,
133+ we would like to have something like:
134+
135+ .. code :: python
136+
137+ >> > out = compute(4 , 50 )
138+ >> > print out
139+ (sum =54 , sub=- 46 , mult=200 , div=0 )
140+
141+ This is exactly what :py:class: `biosppy.utils.ReturnTuple ` accomplishes.
142+ Rewriting the `compute ` function to work with `ReturnTuple ` is simple. Just
143+ construct the return object with a tuple of strings with names for each output
144+ variable:
145+
146+ .. code :: python
147+
148+ from biosppy import utils
149+
150+ def compute_new (a , b ):
151+ """ Simultaneously compute the sum, subtraction, multiplication and
152+ division between two integers.
153+
154+ Args:
155+ a (int): First input integer.
156+ b (int): Second input integer.
157+
158+ Returns:
159+ (ReturnTuple): containing:
160+ sum (int): Sum (a + b).
161+ sub (int): Subtraction (a - b).
162+ mult (int): Multiplication (a * b).
163+ div (int): Integer division (a / b).
164+
165+ """
166+
167+ if b == 0 :
168+ raise ValueError (" Input 'b' cannot be zero." )
169+
170+ v1 = a + b
171+ v2 = a - b
172+ v3 = a * b
173+ v4 = a / b
174+
175+ # build the return object
176+ output = utils.ReturnTuple((v1, v2, v3, v4), (' sum' , ' sub' , ' mult' , ' div' ))
27177
178+ return output
179+
180+ The output now becomes:
181+
182+ .. code :: python
183+
184+ >> > out = compute_new(4 , 50 )
185+ >> > print out
186+ ReturnTuple(sum = 54 , sub = - 46 , mult = 200 , div = 0 )
187+
188+ It allows to access a specific variable by key, like a dictionary:
189+
190+ .. code :: python
191+
192+ >> > out[' sum' ]
193+ 54
194+
195+ And to list all the available keys:
196+
197+ .. code :: python
198+
199+ >> > out.keys()
200+ [' sum' , ' sub' , ' mult' , ' div' ]
201+
202+ It is also possible to convert the object to a more traditional dictionary,
203+ specifically an `OrderedDict <https://docs.python.org/2/library/collections.html#collections.OrderedDict >`_:
204+
205+ .. code :: python
206+
207+ >> > d = out.as_dict()
208+ >> > print d
209+ OrderedDict([(' sum' , 54 ), (' sub' , - 46 ), (' mult' , 200 ), (' div' , 0 )])
210+
211+ Dictionary-like unpacking is supported:
212+
213+ .. code :: python
214+
215+ >> > some_function(** out)
216+
217+ `ReturnTuple ` is heavily inspired by `namedtuple <https://docs.python.org/2/library/collections.html#collections.namedtuple >`_,
218+ but without the dynamic class generation at object creation. It is a subclass
219+ of `tuple `, therefore it maintains compatibility with the native return pattern.
220+ It is still possible to unpack the variables in the usual way:
221+
222+ .. code :: python
223+
224+ >> > a, b, c, d = compute_new(4 , 50 )
225+ >> > print a, b, c, d
226+ 54 - 46 200 0
227+
228+ The behavior is slightly different when only one variable is returned. In this
229+ case it is necessary to explicitly unpack a one-element tuple:
230+
231+ .. code :: python
232+
233+ from biosppy import utils
234+
235+ def foo ():
236+ """ Returns 'bar'."""
237+
238+ out = ' bar'
239+
240+ return utils.ReturnTuple((out, ), (' out' , ))
241+
242+ .. code :: python
243+
244+ >> > out, = foo()
245+ >> > print out
246+ ' bar'
28247
29248 A First Approach
30- ----------------
249+ ================
250+
251+ One of the major goals of `biosppy ` is to provide an easy starting point into
252+ the world of biosignal processing. For that reason, we provide simple turnkey
253+ solutions for each of the supported biosignal types. These functions implement
254+ typical methods to filter, transform, and extract signal features. Let's see
255+ how this works for the example of the ECG signal.
256+
257+ The GitHub repository includes a few example signals (see
258+ `here <https://github.com/PIA-Group/BioSPPy/tree/master/examples >`_). To load
259+ and plot the raw ECG signal follow:
260+
261+ .. code :: python
262+
263+ >> > import numpy as np
264+ >> > import pylab as pl
265+ >> > from biosppy import storage
266+ >> >
267+ >> > signal, mdata = storage.load_txt(' .../examples/ecg.txt' )
268+ >> > Fs = mdata[' sampling_rate' ]
269+ >> > N = len (signal) # number of samples
270+ >> > T = (N - 1 ) / Fs # duration
271+ >> > ts = np.linspace(0 , T, N, endpoint = False ) # relative timestamps
272+ >> > pl.plot(ts, signal, lw = 2 )
273+ >> > pl.grid()
274+ >> > pl.show()
275+
276+ This should produce a similar output to the one shown below.
277+
278+ .. image :: images/ECG_raw.png
279+ :align: center
280+ :width: 80%
281+ :alt: Example of a raw ECG signal.
282+
283+ This signal is a Lead I ECG signal acquired at 1000 Hz, with a resolution of 12
284+ bit. Although of good quality, it exhibits powerline noise interference, has a
285+ DC offset resulting from the acquisition device, and we can also observe the
286+ influence of breathing in the variability of R-peak amplitudes.
287+
288+ We can minimize the effects of these artifacts and extract a bunch of features
289+ with the :py:class: `biosppy.signals.ecg.ecg ` function:
290+
291+ .. code :: python
292+
293+ >> > from biosppy.signals import ecg
294+ >> > out = ecg.ecg(signal = signal, sampling_rate = Fs, show = True )
295+
296+ It should produce a plot like the one below.
297+
298+ .. image :: images/ECG_summary.png
299+ :align: center
300+ :width: 80%
301+ :alt: Example of processed ECG signal.
302+
303+
304+
305+
306+ Signal Processing
307+ =================
31308
32309Bla.
33310
34311Clustering
35- ----------
312+ ==========
36313
37314Bla.
38315
39316Biometrics
40- ----------
317+ ==========
41318
42319Bla.
43320
44321What's Next?
45- ------------
322+ ============
46323
47324Bla.
48325
49326References
50- ----------
327+ ==========
51328
52329.. [ABCD88a ] Reference
53330
0 commit comments