# Sample Entropy calculation?

Thu, 10/18/2018 - 09:56 am

I am interested in calculating the sample entropy of a mostly sinusoidal signal:

Richman, J. S., and J. R. Moorman. “Physiological Time-Series Analysis Using Approximate Entropy and Sample Entropy.” American Journal of Physiology. Heart and Circulatory Physiology 278, no. 6 (June 2000): H2039-2049. https://doi.org/10.1152/ajpheart.2000.278.6.H2039

The signal consists of the angular velocity of a person's wrist during repetitive pronation-supination movements. There are intermittent "breaks" in the movement, in which the velocity has a handful (2-5) small peaks between the major, regularly occurring peaks. I'd like to measure these as irregularities in the signal. Sample entropy seems like an appropriate quantity for this purpose. Does Igor have functions to calculate sample entropy or some related measure of signal regularity/complexity?

Pietro

Screenshot of sample signal attached.

October 18, 2018 at 09:59 am - Permalink

Hello Pietro,

I found the reference that you provided to be almost unreadable. If you can send me a reference with readable equations I'd be interested in looking at the an Igor implementation.

At a simplified level, I found the following: http://daedalus.scl.sztaki.hu/phdws2004/abstract/phdws2004_abstract_4.p… which provides two "algorithms" that are very easy to formulate using MatrixOP. Specifically, the second algorithm for entropy2 can be formulated for an input signal in inWave:

Wave inWave

MatrixOP/O/FREE quo=abs(subtractMean(inWave,0))

MatrixOP/O/FREE ent=sum(quo*log(quo))

return -ent[0]

End

I hope this helps,

A.G.

October 18, 2018 at 12:54 pm - Permalink

I am glad i am not alone in finding that article difficult. It is the original article in which sample entropy was introduced, as a modification of approximate entropy (Pincus). I found a later chapter by the same authors that seems more readable (attached). The Wikipedia entry for Sample Entropy (https://en.wikipedia.org/wiki/Sample_entropy) has an outline of a Python routine. If you are interested enough, perhaps you can make something from this info. I will look at the option you suggested.

Thank you!

Pietro

October 18, 2018 at 02:26 pm - Permalink

Hello Pietro,

I think the wiki text is more readable, particularly the Definition section. In any event, below is a quick sample of code that I wrote for this definition. I have not tested it but I think it should be clear how to use or modify it for other definitions of distance functions. I also did not make any effort to get efficient performance.

I hope this helps,

A.G.

Wave inWave

Variable em // embedding dimension

Variable rTol // tolerance

Variable AA=sampEnM(inWave,em+1,rTol)

Variable BB=sampEnM(inWave,em,rTol)

return -log(AA/BB)

End

Function sampEnM(inWave,em,rTol)

Wave inWave

Variable em

Variable rTol

Variable rows=DimSize(inWave,0)

// create all possible contiguous vectors of length em

Variable numVectors=rows-em+1

Variable count=0

Variable i,j,row

for(i=0;i<numVectors;i+=1)

for(j=i+1;j<numVectors;j+=1)

MatrixOP/O/FREE V1=sum(abs(subrange(inWave,i,0,em)-subrange(inWave,j,0,em)))

if(V1[0]<rTol)

count+=1

endif

endfor

endfor

return count

End

October 19, 2018 at 01:12 pm - Permalink

Wow, that is so nice of you, A.G.! Thanks! I'll try this out.

You must really enjoy your work. I really appreciate it.

Pietro

October 19, 2018 at 01:27 pm - Permalink

I had to attend to other work and I am only trying to implement this function for the first time today. Unfortunately, I am getting an error that I can't figure out. Here are the steps I took starting with A.G.'s code above:

- The code as written above gave me a compile-time error, "Expected operand", at the line:

MatrixOP/O/FREE V1=sum(abs(subrange(inWave,i,0,em)-subrange(inWave,j,0,em)))

- I read that the sum function expects a range, and so I added the range -inf, inf:

- I tested the function on the attached time series, velF_O1. I chose values m = 1, rTol = 200, based on the following comment in Richman and Moorman's 2004 chapter:

(Richman, Joshua S., Douglas E. Lake, and J. Randall Moorman. “Sample Entropy.” In

Methods in Enzymology, 384:172–84. Numerical Computer Methods, Part E. Academic Press, 2004. https://doi.org/10.1016/S0076-6879(04)84011-4.):- So I tried:

print sampEn(velF_O1, 1, 200)

- This gave me the runtime error: "Wrong number of parameters" at the line

MatrixOP/O/FREE V1=sum(abs(subrange(inWave,i,0,em)-subrange(inWave,j,0,em) ), -inf , inf )

I will appreciate any suggestions. I have very limited experience using MatrixOp functions and maybe I am missing something obvious to others.

Pietro

November 6, 2018 at 12:58 pm - Permalink

UPDATE:

I was able to use the Python code given in the Wikipedia page (see code below). I don't suppose that Igor has the functionality yet to call Python scripts and receive results from them? Or at least to run Unix commands in the Mac's Terminal app?

....[EDIT]: I see I can use Applescript to run shell commands. Still, it would be great if Igor 9 included a more direct interface with Python scripts...

------

import numpy as np

#import pylab as pl

def SampEn(U, m, r):

def _maxdist(x_i, x_j):

result = max([abs(ua - va) for ua, va in zip(x_i, x_j)])

return result

def _phi(m):

x = [[U[j] for j in range(i, i + m - 1 + 1)] for i in range(N - m + 1)]

C = [len([1 for j in range(len(x)) if i != j and _maxdist(x[i], x[j]) <= r]) for i in range(len(x))]

return sum(C)

N = len(U)

return -np.log(_phi(m+1) / _phi(m))

November 6, 2018 at 01:45 pm - Permalink

In reply to I had to attend to other… by pmazzoni

I believe the initial error message refers to the MatrixOP subRange command, which expects a wave and both start and end rows and columns. Is inWave 1D or 2D? sum() within MatrixOP doesn't require a range.

November 7, 2018 at 02:08 am - Permalink

Thanks for the clarification. I removed -inf, inf and returned the line to the version that AG originally wrote:

My wave is 1D. Does it sound like subrange is missing an argument, or that it has en extra argument? I am embarrassed that I am trying to implement a function I do not fully understand myself.

Note that the compile error with this line highlights that last right parentheses and says "Expected operand". That's why I thought that the missing operand was for sum().

November 7, 2018 at 10:16 am - Permalink

Hello Pietro,

Please don't confuse the sum() function in MatrixOP and the with the standard sum() function. The one in MatrixOP operates on a whole matrix token. The matrix token used in my code was created from the abs() function applied to two subrange() calls. Here the syntax should be subRange(w,rs,re,cs,ce) where rs is the starting row, re is the end row, cs is the starting column and ce is the end column. Clearly, one argument was missing in the original code. If you have a single column then cs=ce=0 and the command should be something like:

MatrixOP/O/FREE V1=sum(abs(subrange(inWave,i,i+em1,0,0)-subrange(inWave,j,j+em1,0,0)))

I apologize for the confusion.

November 7, 2018 at 11:30 am - Permalink

It works now. Thank you!

November 8, 2018 at 02:25 pm - Permalink