The ‘Cycles’ class

EMD provides a Cycles class to help with more complex cycle comparisons. This class is based on the emd.cycles.get_cycle_vector and emd.cycles.get_cycle_stat functions we used in the previous tutorial, but it does some additional work for you. For example, the Cycles class is a good way to compute and store many different stats from the same cycles and for dynamically working with different subsets of cycles based on user specified conditions. Lets take a closer look…

Getting started

Firstly we will import emd and simulate a signal.

import emd
import numpy as np
import matplotlib.pyplot as plt

# Define and simulate a simple signal
peak_freq = 12
sample_rate = 512
seconds = 60
noise_std = .5
x = emd.utils.ar_simulate(peak_freq, sample_rate, seconds, noise_std=noise_std, random_seed=42, r=.99) * 1e-4
t = np.linspace(0, seconds, seconds*sample_rate)

# Plot the first 5 seconds of data
plt.figure(figsize=(10, 2))
plt.plot(t[:sample_rate*4], x[:sample_rate*4], 'k')

# sphinx_gallery_thumbnail_number = 4
emd tutorial 03 cycle 03 cycleclass

Out:

[<matplotlib.lines.Line2D object at 0x7fee7ac15410>]

We next run a mask sift with the default parameters to isolate the 12Hz oscillation. There is only one clear oscillatory signal in this simulation. This is extracted in IMF-2 whilst the remaining IMFs contain low-amplitude noise.

# Run a mask sift
imf = emd.sift.mask_sift(x)

# Computee frequenecy transforms
IP, IF, IA = emd.spectra.frequency_transform(imf, sample_rate, 'hilbert')

The Cycles class

We next initialise the ‘Cycles’ class with the instantaneous phase of the second IMF.

C = emd.cycles.Cycles(IP[:, 2])

This calls emd.cycles.get_cycle_vect on the phase time course to identify individual cycles and then stores a load of relevant information which we can use later. The cycle vector is stored in the class instance as cycle_vect. Here we plot the cycle vector for the first four seconds of our signal.

plt.figure(figsize=(10, 6))
plt.plot(t[:sample_rate*8], C.cycle_vect[:sample_rate*8], 'k')
emd tutorial 03 cycle 03 cycleclass

Out:

[<matplotlib.lines.Line2D object at 0x7fee5e61fe10>]

The Cycles class has an attached function to help identify when specific cycles occurred in a dataset. The C.get_inds_of_cycle function finds and returns the samples in which the Nth cycle occurred. Here, we run this find and plot three cycles from our simulation. The cycle in the original time-series is plotted in grey and the cycle from the second IMF is in colour.

cycles_to_plot = [5, 23, 42]
plt.figure()
for ii in range(len(cycles_to_plot)):
    inds = C.get_inds_of_cycle(cycles_to_plot[ii])
    xinds = np.arange(len(inds)) + 55*ii
    plt.plot(xinds, x[inds], color=[0.8, 0.8, 0.8])
    plt.plot(xinds, imf[inds, 2])
emd tutorial 03 cycle 03 cycleclass

These cycles contain one complete period of an oscillation and form the basis for a lot of the computations in this tutorial. However there are a couple of shortcomings with this standard cycle. For example, we may want to separately analyse the ascending and descending edges of the oscillation, whilst the descending edge is continuous - the cycles above contain two halves of two separate ascending edges at the start and end of the cycle.

We could adjust the phase to make our cycle identification start at the peak to ensure the ascending edge is continuous, but this will just split another part of the cycle… One way around this is to consider an ‘augmented’ cycle which contains a whole standard cycle plus the last quadrant of the proceeding cycle. These five quarters of a cycle mean that all sections of the cycle are continuously represented, though it does meaen that some parts of the data may be present in more than one cycle.

We can work with augmented cycles by specifying mode='augmented' when finding our cycle indices.

cycles_to_plot = [5, 23, 42]
plt.figure()
for ii in range(len(cycles_to_plot)):
    inds = C.get_inds_of_cycle(cycles_to_plot[ii], mode='augmented')
    xinds = np.arange(len(inds)) + 60*ii
    plt.plot(xinds, x[inds], color=[0.8, 0.8, 0.8])
    plt.plot(xinds, imf[inds, 2])
emd tutorial 03 cycle 03 cycleclass

The cycles class can be used as an input to several other emd.cycles functions to specify which cycles a particular computation should run across.

For example, here we compute the control points across from IMF-3 for each of our cycles.

ctrl = emd.cycles.get_control_points(imf[:, 2], C)

…and here we run phase-alignment.

pa = emd.cycles.phase_align(IP[:, 2], IF[:, 2], C)

Out:

/home/docs/checkouts/readthedocs.org/user_builds/emd/envs/v0.4.0/lib/python3.7/site-packages/scipy/interpolate/interpolate.py:623: RuntimeWarning: divide by zero encountered in true_divide
  slope = (y_hi - y_lo) / (x_hi - x_lo)[:, None]

Computing cycle metrics

We can loop through our cycles using the C.get_inds_of_cycle function to identify a each cycle in turn. Here we run a loop to compute the maximum amplitude of each cycle.

amps = np.zeros((C.ncycles,))
for ii in range(C.ncycles):
    inds = C.get_inds_of_cycle(ii)
    amps[ii] = np.max(IA[inds, 2])

print(amps)

Out:

[0.93349347 1.06113761 1.41745578 1.91619621 1.92547315 1.77475944
 1.55668549 0.99680003 1.34016785 1.4106221  1.37823121 1.10455004
 0.90519556 0.44427642 0.17588317 0.32872342 0.33338757 0.53244097
 0.63943269 0.75849534 0.68738918 0.85663603 1.64384172 2.00430565
 1.99327867 1.77465598 1.56104515 1.6284159  1.50241709 0.77736475
 0.33191213 0.55550017 1.00264303 1.11557011 0.91830562 0.8215583
 0.83045857 0.28976343 0.41444764 0.24263128 0.25155956 0.27373324
 0.71443475 0.85774905 0.81043411 1.10490102 1.36492015 1.56211387
 1.99819227 2.00371013 1.57836281 1.17201351 1.19431156 0.96923985
 1.15490397 1.03181369 0.7348086  1.02015749 1.03434361 0.82790886
 0.78678122 1.2758197  1.59319045 1.58024866 1.04923174 0.94128047
 0.47960894 0.35142257 0.54027415 0.61469989 0.58045291 0.43234756
 0.65340279 0.50052278 0.14976062 0.11317401 0.60274368 0.92904547
 0.90483794 1.10671278 1.22151469 1.35762824 1.49644216 1.42415351
 1.12788468 0.91347902 1.03133397 0.95545841 0.86067832 0.86990815
 1.0572636  1.19789273 1.28301299 1.27655416 0.91880544 1.19327558
 1.6403478  1.67031745 1.75152743 2.03964715 1.95878477 1.76810829
 1.76753241 1.11566434 0.92589067 0.91440358 0.90596261 0.83190393
 0.4735853  0.52297565 0.72138221 0.47660203 0.82237682 0.86039914
 0.85913717 0.65154367 0.28687845 0.47855391 0.90993125 0.92520959
 1.38067752 1.40398999 1.26246417 1.09951816 0.76526662 0.99305326
 0.95202503 1.13920273 0.84598533 0.73887576 0.7664586  0.62616134
 0.62913052 0.96102562 0.95422286 0.48278869 0.49817761 0.85486116
 0.85565333 0.71490404 0.6989355  0.69699202 1.05769516 1.23116852
 1.51315495 1.81820342 1.81671333 1.32575667 1.07916638 0.94916376
 0.56842317 0.99905874 1.1081907  1.11327479 0.99052041 0.48950338
 0.7329039  1.24132107 1.29813268 1.27262803 0.91941813 0.61222081
 0.98986135 0.94160228 0.50198507 0.75694071 0.75215142 0.94083774
 1.18026956 1.23186675 0.86489791 0.44737942 0.54123513 0.52075051
 0.16433773 0.28446679 1.07575248 1.29973068 1.30658586 1.17491515
 0.84453384 0.7321658  0.97054395 0.81525517 0.6141059  0.99684271
 1.30531938 1.42009789 1.80708704 2.44245942 2.72052188 2.66422954
 2.57249708 2.36504987 2.28342716 2.27909172 1.71247406 1.281476
 0.57083725 0.8242854  0.77980296 0.68425203 0.69917534 0.56594715
 0.39426793 0.43122733 0.73333259 0.7368523  0.73910779 0.61011113
 1.03904892 0.93267132 0.86194606 1.23721991 1.43210893 1.72210687
 1.74973603 1.72551207 1.7294179  1.34668213 0.91269439 1.06308591
 1.23260998 1.01999904 0.81296365 0.35372791 0.47728504 0.64981018
 0.64257967 0.56413931 0.9433736  1.04993949 1.11449426 0.50922609
 0.78619004 1.07315802 1.07274866 0.94031927 0.39517246 1.07466627
 1.13132215 0.99977788 0.77330726 0.98185965 0.75996886 0.96380704
 0.97333799 0.42990106 0.20646287 0.05892981 0.08769533 0.17970915
 0.69360369 0.70705629 0.62627689 0.69717601 0.67369808 0.12531829
 0.36014441 0.13673392 0.07713868 0.10417082 0.17642543 0.15065913
 0.37652742 0.3650091  0.6258935  0.73577108 1.13495473 1.63929522
 1.88860382 1.87603795 1.46192317 1.3776335  1.75028044 1.709477
 1.71746103 2.31408112 2.59886559 2.58073243 2.22686066 2.08212422
 1.53729797 0.83164675 0.53704626 0.53688713 0.23661116 0.39313705
 0.97208846 1.1734906  1.12237125 0.84979254 1.14582565 1.1612249
 1.60126211 1.63463948 1.5336484  0.91795636 0.31131994 0.46690795
 0.70591441 0.85978914 0.8914142  0.92674933 1.08848416 1.21244609
 1.16805131 1.02188131 0.69212017 0.83978334 0.9303187  1.11848519
 1.304251   1.22264899 0.97350646 1.08414472 1.06253319 0.75489561
 1.14363149 1.1961463  0.90116843 0.76004134 0.90026411 0.92779558
 0.419145   0.30039638 0.37480663 0.38326425 0.31656912 0.15165787
 0.10489792 0.22547124 0.61124463 0.67086046 0.31070665 0.25861801
 0.43901014 0.70209226 1.0639194  1.16617118 0.80661225 0.77138447
 0.76476737 1.1793655  1.61508654 1.65392741 1.65051983 1.5376782
 1.30713509 1.12641948 1.01441324 0.46602236 0.66841123 0.91520843
 0.96446946 0.73656115 0.83459463 1.35358327 1.86336239 2.15355216
 2.13567753 1.55112103 1.04814109 1.05599752 1.24628908 1.08057265
 0.33867193 0.66375851 0.7817431  0.64687619 0.73699179 0.67582544
 0.97111546 1.10712456 1.04415659 1.07779837 1.04204687 0.88880615
 0.58579785 0.9502273  0.99028346 1.278831   1.55935632 1.55525414
 1.18829935 0.97163668 1.04505163 1.45280016 1.47105286 1.2546522
 1.1265769  1.1752544  1.33307956 1.53529965 1.47683708 1.56141183
 1.37542713 1.01519129 1.09871507 1.38477867 1.37895247 1.35252202
 1.4590906  1.45798294 1.09385805 0.24273077 1.17359185 1.17950318
 0.6845087  0.62652554 0.08258205 0.21007277 0.44324449 0.98382382
 0.96534317 0.86262451 1.15853165 1.16234454 0.87862255 1.48980452
 1.76546941 1.60496217 1.11373832 0.50057361 0.60819226 1.25969622
 1.44492998 1.63352435 1.60969458 1.13899664 0.93451457 0.84461057
 1.30531792 1.67174711 1.67014211 1.66495426 1.67531936 1.63408752
 1.69703215 1.67964635 1.41152025 0.77264497 0.80142732 0.54686773
 0.31062575 0.40384009 1.00479457 1.01405975 0.97509379 0.66560908
 0.67701105 0.44022103 0.25095123 0.15886134 0.47990491 1.53645584
 1.6348652  1.8164731  1.89709102 1.50214021 1.4381205  2.23298118
 2.21091136 2.16354533 2.50083236 1.99734838 1.77243183 1.4389241
 1.1897496  0.88110006 1.42397122 1.97847737 2.1567974  2.20298681
 1.6896556  1.2620131  1.31055826 1.3195239  1.23535282 0.56345619
 0.32147561 0.98474201 1.01554637 0.92091158 2.08216279 2.17717829
 2.29694369 2.24460883 1.9029297  1.80785593 1.17106021 0.62225625
 0.62960558 0.72075382 0.91034151 1.16120409 1.81229601 2.06972035
 2.46814416 2.46360891 1.97697308 1.44692371 0.86649954 0.75331021
 0.88776916 0.87267132 1.2661073  1.27905633 0.83678522 0.48489883
 0.80273092 0.77222133 0.57943955 0.30560792 0.11818733 0.53544502
 0.86380939 0.88686008 0.60852715 0.4791448  0.369035   0.75440497
 0.68433778 0.94397738 0.94269278 0.82617554 0.82773103 0.58817959
 0.46318664 0.69639127 1.01417981 1.26916635 1.4570224  1.37370228
 1.43256704 0.92074888 0.77776834 0.77626909 0.72253036 1.15181269
 1.15751754 0.92846596 0.76611455 0.30242771 0.30468203 0.48781335
 1.02802768 1.31184909 1.16138237 1.0984996  0.7871493  0.5892897
 0.57106841 0.85049463 1.10854273 1.08958663 0.84783242 1.07106493
 1.3307209  1.33754769 1.49676132 1.49488247 1.10457929 1.29334258
 1.57118005 1.85609806 1.85728409 1.57905739 1.46742616 1.77159934
 1.76560744 1.42302701 1.7799913  1.78591087 1.33465069 0.99088232
 1.05683855 0.89577263 1.08914949 1.17628522 1.51993869 1.58370117
 1.57348791 1.45454472 1.46408844 1.30068712 1.30938515 0.89974566
 0.13297835 0.08381908 0.20667871 0.24867941 0.46164132 1.03888535
 1.01853001 1.12904739 1.63664063 2.30780546 2.50752032 2.11339745
 2.10548905 2.10181126 0.9527243  0.8595725  1.51597736 1.8127148
 1.68281319 0.90802446 0.87959621 1.58914421 1.59631979 1.36106468
 0.79294766 0.45556065 0.47720808 0.55511552 0.48140503 0.58191049
 0.89177408 0.9843329  1.25912146 1.3593314  1.45746457 1.98619874
 1.96329085 1.45352029 1.32854701 1.29271984 1.33322543 1.26935608
 1.25158508 1.462845   1.5172038  1.88963395 1.85217966 1.90887912
 1.4064199  0.49145657 0.84086962 0.85374626 0.72806376 1.03580051
 1.07864319 0.6338276  0.75333201 1.43409152 1.68266395 1.87443941
 1.59250163 1.5809525  1.35325309 0.70397388 0.81220288 0.71082421
 0.16774593 0.83192609 1.24003878 1.2338264  0.88474795 0.5937984
 0.24200426 0.16332786 0.41502758 1.21320919 1.55780125 1.55223537
 1.20674198 1.10155905 0.99278464 1.10015646 0.90300417 0.69735086
 0.36186802 0.41462291 0.41376466 0.33945384 0.33741112 0.73639195
 0.77312805 0.7729205  0.52173814 0.11948005 0.57721371 0.87076507
 1.13910257 1.50820467 1.38739282 0.64358706 0.11762309 0.0800235
 0.11945162 0.1097613  0.68480414 0.68373093 0.07863122 0.73944397
 0.7921881  1.3460002  1.57853008 1.83133767 1.8278178  1.36878029
 1.25713842 1.40542319 1.41205507 1.4289058  1.59419895 1.30256317
 1.15886863 1.25979447 1.16115239 1.59466971 1.6925186  1.48871217
 1.14533619 0.70132237 0.50874317 0.27303931 0.33116259 0.75828878
 0.64548553 0.84484794 0.83906344 0.8063034  1.32666173 1.65402542
 1.68498334 1.38510981 0.89898954 0.74157474 0.48558243 0.6695245
 0.73802715 1.06055962 1.08447877 0.95228495 1.44853862 1.5371023
 1.88785177 1.8823055  1.00978756 0.26014401]

The Cycles class has a handy method to help automate this process. Simply specify a metric name, some values to compute a per-cycle metric on and a function and C.compute_cycle_metric will loop across all cycles and store the result for you.

C.compute_cycle_metric('max_amp', IA[:, 2], func=np.max)

This is always computed for every cycle in the dataset, we can include or exclude cycles based on different conditions later.

For another example we compute the length of each cycle in samples.

# Compute the length of each cycle
C.compute_cycle_metric('duration', IA[:, 2], len)

Cycle metrics can also be computed on the augmented cycles. Lets compute the standard deviation of amplitude values for each augmented cycle.

C.compute_cycle_metric('ampSD', IA[:, 2], np.std, mode='augmented')

We have now computed four different metrics across our cycles.

print(C)

Out:

<class 'emd.cycles.Cycles'> (742 cycles 4 metrics)

These values are now stored in the metrics dictionary along with the good cycle values.

print(C.metrics.keys())

print(C.metrics['is_good'])
print(C.metrics['max_amp'])
print(C.metrics['duration'])

Out:

dict_keys(['is_good', 'max_amp', 'duration', 'ampSD'])
[0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1
 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1
 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1
 0 0]
[0.93349347 1.06113761 1.41745578 1.91619621 1.92547315 1.77475944
 1.55668549 0.99680003 1.34016785 1.4106221  1.37823121 1.10455004
 0.90519556 0.44427642 0.17588317 0.32872342 0.33338757 0.53244097
 0.63943269 0.75849534 0.68738918 0.85663603 1.64384172 2.00430565
 1.99327867 1.77465598 1.56104515 1.6284159  1.50241709 0.77736475
 0.33191213 0.55550017 1.00264303 1.11557011 0.91830562 0.8215583
 0.83045857 0.28976343 0.41444764 0.24263128 0.25155956 0.27373324
 0.71443475 0.85774905 0.81043411 1.10490102 1.36492015 1.56211387
 1.99819227 2.00371013 1.57836281 1.17201351 1.19431156 0.96923985
 1.15490397 1.03181369 0.7348086  1.02015749 1.03434361 0.82790886
 0.78678122 1.2758197  1.59319045 1.58024866 1.04923174 0.94128047
 0.47960894 0.35142257 0.54027415 0.61469989 0.58045291 0.43234756
 0.65340279 0.50052278 0.14976062 0.11317401 0.60274368 0.92904547
 0.90483794 1.10671278 1.22151469 1.35762824 1.49644216 1.42415351
 1.12788468 0.91347902 1.03133397 0.95545841 0.86067832 0.86990815
 1.0572636  1.19789273 1.28301299 1.27655416 0.91880544 1.19327558
 1.6403478  1.67031745 1.75152743 2.03964715 1.95878477 1.76810829
 1.76753241 1.11566434 0.92589067 0.91440358 0.90596261 0.83190393
 0.4735853  0.52297565 0.72138221 0.47660203 0.82237682 0.86039914
 0.85913717 0.65154367 0.28687845 0.47855391 0.90993125 0.92520959
 1.38067752 1.40398999 1.26246417 1.09951816 0.76526662 0.99305326
 0.95202503 1.13920273 0.84598533 0.73887576 0.7664586  0.62616134
 0.62913052 0.96102562 0.95422286 0.48278869 0.49817761 0.85486116
 0.85565333 0.71490404 0.6989355  0.69699202 1.05769516 1.23116852
 1.51315495 1.81820342 1.81671333 1.32575667 1.07916638 0.94916376
 0.56842317 0.99905874 1.1081907  1.11327479 0.99052041 0.48950338
 0.7329039  1.24132107 1.29813268 1.27262803 0.91941813 0.61222081
 0.98986135 0.94160228 0.50198507 0.75694071 0.75215142 0.94083774
 1.18026956 1.23186675 0.86489791 0.44737942 0.54123513 0.52075051
 0.16433773 0.28446679 1.07575248 1.29973068 1.30658586 1.17491515
 0.84453384 0.7321658  0.97054395 0.81525517 0.6141059  0.99684271
 1.30531938 1.42009789 1.80708704 2.44245942 2.72052188 2.66422954
 2.57249708 2.36504987 2.28342716 2.27909172 1.71247406 1.281476
 0.57083725 0.8242854  0.77980296 0.68425203 0.69917534 0.56594715
 0.39426793 0.43122733 0.73333259 0.7368523  0.73910779 0.61011113
 1.03904892 0.93267132 0.86194606 1.23721991 1.43210893 1.72210687
 1.74973603 1.72551207 1.7294179  1.34668213 0.91269439 1.06308591
 1.23260998 1.01999904 0.81296365 0.35372791 0.47728504 0.64981018
 0.64257967 0.56413931 0.9433736  1.04993949 1.11449426 0.50922609
 0.78619004 1.07315802 1.07274866 0.94031927 0.39517246 1.07466627
 1.13132215 0.99977788 0.77330726 0.98185965 0.75996886 0.96380704
 0.97333799 0.42990106 0.20646287 0.05892981 0.08769533 0.17970915
 0.69360369 0.70705629 0.62627689 0.69717601 0.67369808 0.12531829
 0.36014441 0.13673392 0.07713868 0.10417082 0.17642543 0.15065913
 0.37652742 0.3650091  0.6258935  0.73577108 1.13495473 1.63929522
 1.88860382 1.87603795 1.46192317 1.3776335  1.75028044 1.709477
 1.71746103 2.31408112 2.59886559 2.58073243 2.22686066 2.08212422
 1.53729797 0.83164675 0.53704626 0.53688713 0.23661116 0.39313705
 0.97208846 1.1734906  1.12237125 0.84979254 1.14582565 1.1612249
 1.60126211 1.63463948 1.5336484  0.91795636 0.31131994 0.46690795
 0.70591441 0.85978914 0.8914142  0.92674933 1.08848416 1.21244609
 1.16805131 1.02188131 0.69212017 0.83978334 0.9303187  1.11848519
 1.304251   1.22264899 0.97350646 1.08414472 1.06253319 0.75489561
 1.14363149 1.1961463  0.90116843 0.76004134 0.90026411 0.92779558
 0.419145   0.30039638 0.37480663 0.38326425 0.31656912 0.15165787
 0.10489792 0.22547124 0.61124463 0.67086046 0.31070665 0.25861801
 0.43901014 0.70209226 1.0639194  1.16617118 0.80661225 0.77138447
 0.76476737 1.1793655  1.61508654 1.65392741 1.65051983 1.5376782
 1.30713509 1.12641948 1.01441324 0.46602236 0.66841123 0.91520843
 0.96446946 0.73656115 0.83459463 1.35358327 1.86336239 2.15355216
 2.13567753 1.55112103 1.04814109 1.05599752 1.24628908 1.08057265
 0.33867193 0.66375851 0.7817431  0.64687619 0.73699179 0.67582544
 0.97111546 1.10712456 1.04415659 1.07779837 1.04204687 0.88880615
 0.58579785 0.9502273  0.99028346 1.278831   1.55935632 1.55525414
 1.18829935 0.97163668 1.04505163 1.45280016 1.47105286 1.2546522
 1.1265769  1.1752544  1.33307956 1.53529965 1.47683708 1.56141183
 1.37542713 1.01519129 1.09871507 1.38477867 1.37895247 1.35252202
 1.4590906  1.45798294 1.09385805 0.24273077 1.17359185 1.17950318
 0.6845087  0.62652554 0.08258205 0.21007277 0.44324449 0.98382382
 0.96534317 0.86262451 1.15853165 1.16234454 0.87862255 1.48980452
 1.76546941 1.60496217 1.11373832 0.50057361 0.60819226 1.25969622
 1.44492998 1.63352435 1.60969458 1.13899664 0.93451457 0.84461057
 1.30531792 1.67174711 1.67014211 1.66495426 1.67531936 1.63408752
 1.69703215 1.67964635 1.41152025 0.77264497 0.80142732 0.54686773
 0.31062575 0.40384009 1.00479457 1.01405975 0.97509379 0.66560908
 0.67701105 0.44022103 0.25095123 0.15886134 0.47990491 1.53645584
 1.6348652  1.8164731  1.89709102 1.50214021 1.4381205  2.23298118
 2.21091136 2.16354533 2.50083236 1.99734838 1.77243183 1.4389241
 1.1897496  0.88110006 1.42397122 1.97847737 2.1567974  2.20298681
 1.6896556  1.2620131  1.31055826 1.3195239  1.23535282 0.56345619
 0.32147561 0.98474201 1.01554637 0.92091158 2.08216279 2.17717829
 2.29694369 2.24460883 1.9029297  1.80785593 1.17106021 0.62225625
 0.62960558 0.72075382 0.91034151 1.16120409 1.81229601 2.06972035
 2.46814416 2.46360891 1.97697308 1.44692371 0.86649954 0.75331021
 0.88776916 0.87267132 1.2661073  1.27905633 0.83678522 0.48489883
 0.80273092 0.77222133 0.57943955 0.30560792 0.11818733 0.53544502
 0.86380939 0.88686008 0.60852715 0.4791448  0.369035   0.75440497
 0.68433778 0.94397738 0.94269278 0.82617554 0.82773103 0.58817959
 0.46318664 0.69639127 1.01417981 1.26916635 1.4570224  1.37370228
 1.43256704 0.92074888 0.77776834 0.77626909 0.72253036 1.15181269
 1.15751754 0.92846596 0.76611455 0.30242771 0.30468203 0.48781335
 1.02802768 1.31184909 1.16138237 1.0984996  0.7871493  0.5892897
 0.57106841 0.85049463 1.10854273 1.08958663 0.84783242 1.07106493
 1.3307209  1.33754769 1.49676132 1.49488247 1.10457929 1.29334258
 1.57118005 1.85609806 1.85728409 1.57905739 1.46742616 1.77159934
 1.76560744 1.42302701 1.7799913  1.78591087 1.33465069 0.99088232
 1.05683855 0.89577263 1.08914949 1.17628522 1.51993869 1.58370117
 1.57348791 1.45454472 1.46408844 1.30068712 1.30938515 0.89974566
 0.13297835 0.08381908 0.20667871 0.24867941 0.46164132 1.03888535
 1.01853001 1.12904739 1.63664063 2.30780546 2.50752032 2.11339745
 2.10548905 2.10181126 0.9527243  0.8595725  1.51597736 1.8127148
 1.68281319 0.90802446 0.87959621 1.58914421 1.59631979 1.36106468
 0.79294766 0.45556065 0.47720808 0.55511552 0.48140503 0.58191049
 0.89177408 0.9843329  1.25912146 1.3593314  1.45746457 1.98619874
 1.96329085 1.45352029 1.32854701 1.29271984 1.33322543 1.26935608
 1.25158508 1.462845   1.5172038  1.88963395 1.85217966 1.90887912
 1.4064199  0.49145657 0.84086962 0.85374626 0.72806376 1.03580051
 1.07864319 0.6338276  0.75333201 1.43409152 1.68266395 1.87443941
 1.59250163 1.5809525  1.35325309 0.70397388 0.81220288 0.71082421
 0.16774593 0.83192609 1.24003878 1.2338264  0.88474795 0.5937984
 0.24200426 0.16332786 0.41502758 1.21320919 1.55780125 1.55223537
 1.20674198 1.10155905 0.99278464 1.10015646 0.90300417 0.69735086
 0.36186802 0.41462291 0.41376466 0.33945384 0.33741112 0.73639195
 0.77312805 0.7729205  0.52173814 0.11948005 0.57721371 0.87076507
 1.13910257 1.50820467 1.38739282 0.64358706 0.11762309 0.0800235
 0.11945162 0.1097613  0.68480414 0.68373093 0.07863122 0.73944397
 0.7921881  1.3460002  1.57853008 1.83133767 1.8278178  1.36878029
 1.25713842 1.40542319 1.41205507 1.4289058  1.59419895 1.30256317
 1.15886863 1.25979447 1.16115239 1.59466971 1.6925186  1.48871217
 1.14533619 0.70132237 0.50874317 0.27303931 0.33116259 0.75828878
 0.64548553 0.84484794 0.83906344 0.8063034  1.32666173 1.65402542
 1.68498334 1.38510981 0.89898954 0.74157474 0.48558243 0.6695245
 0.73802715 1.06055962 1.08447877 0.95228495 1.44853862 1.5371023
 1.88785177 1.8823055  1.00978756 0.26014401]
[26 39 44 44 43 42 42 39 44 44 45 44 44 33 35 37 35 38 41 47 46 50 47 42
 44 40 42 41 43 51 39 32 45 38 38 43 48 46 27 37 29 33 43 47 49 43 44 45
 44 42 47 44 45 42 43 44 38 39 46 39 34 45 42 40 38 42 33 41 45 38 44 42
 50 43  6  5 39 48 41 43 44 40 41 43 40 35 41 39 47 44 39 44 41 43 42 46
 43 42 39 43 43 43 46 47 48 42 40 42 37 42 41 44 46 50 40 38 40 42 48 39
 40 42 40 40 36 44 41 44 45 44 42 41 41 45 48 44 42 39 47 42 39 44 45 42
 43 42 44 40 44 46 45 47 45 43 43 38 34 40 45 40 35 36 44 40 41 44 35 43
 41 44 43 32 41 43 43 23 46 42 40 41 43 53 45 39 33 37 43 43 46 44 43 42
 42 42 42 44 43 43 42 41 49 46 51 51 53 40 41 43 48 48 45 42 42 45 45 45
 44 44 41 48 47 48 40 48 38 44 40 44 46 47 47 42 44 41 41 43 43 41 33 47
 41 42 43 40 41 42 47 47 42  7 15 39 50 51 40 46 39 25 35  6  4 22 27 21
 29 38 39 49 41 42 42 41 40 38 44 42 44 46 43 42 43 43 45 41 40 47 48 37
 45 51 42 47 44 42 42 41 45 37 34 33 43 41 43 41 42 46 42 46 40 46 39 45
 43 42 42 42 50 46 44 44 38 41 44 43 35 41 41 53 25 27 12 26 43 38 30 33
 41 46 40 44 41 43 41 43 48 41 44 44 43 46 41 45 48 42 49 45 40 42 44 45
 42 44 48 52 43 46 43 50 41 44 45 38 42 45 40 40 43 44 47 45 47 44 42 45
 41 42 46 44 44 42 43 45 42 42 41 44 42 37 43 44 40 44 45 45 43 23 43 45
 44 33 20 20 40 44 39 39 43 42 39 40 44 44 40 31 33 45 42 45 43 45 44 49
 44 44 40 43 37 42 41 43 39 45 43 42 30 41 44 42 46 46 39 30 32 30 37 43
 43 41 43 43 38 42 42 43 46 42 45 45 46 40 42 40 45 44 44 47 46 41 42 41
 53 47 48 46 46 44 44 42 42 46 43 42 42 39 44 43 44 43 43 44 44 43 44 45
 41 42 42 40 38 33 44 42 41 37 22 35 42 43 43 44 38 39 43 40 43 42 41 44
 39 42 46 47 44 40 43 43 39 42 41 42 41 45 38 43 36 37 45 44 43 47 42 39
 45 43 39 44 43 38 44 43 42 44 46 44 45 43 41 43 44 45 48 44 44 43 45 45
 52 46 43 40 41 41 43 43 44 45 44 37 18 22 29 35 44 43 46 43 45 43 45 43
 42 42 36 36 44 43 42 41 37 40 44 40 44 36 45 46 49 42 41 42 40 41 40 44
 43 44 40 40 44 42 44 47 45 42 44 46 45 37 38 49 46 41 45 41 53 50 43 43
 46 48 46 46 53 46 22 42 43 43 42 36 26 26 37 44 44 43 41 37 39 41 48 40
 44 45 42 28 32 45 43 42 33 32 39 43 44 45 48 42  6  4 24 29 43 34 27 41
 44 48 48 42 43 43 42 46 44 41 42 41 39 43 37 42 39 38 44 37 34 35 36 39
 44 41 45 47 45 45 42 45 51 42 44 45 38 44 43 42 43 41 42 44 35 18]

These values can be accessed and used for further analyses as needed. The metrics can be copied into a pandas dataframe for further analysis if convenient.

df = C.get_metric_dataframe()
print(df)

Out:

     is_good   max_amp  duration     ampSD
0          0  0.933493        26       NaN
1          1  1.061138        39  0.049164
2          1  1.417456        44  0.132679
3          1  1.916196        44  0.165706
4          1  1.925473        43  0.049547
..       ...       ...       ...       ...
737        1  1.537102        41  0.047038
738        1  1.887852        42  0.163623
739        1  1.882306        44  0.259681
740        0  1.009788        35  0.305678
741        0  0.260144        18  0.048993

[742 rows x 4 columns]

We can extract a cycle vector for only the good cycles using the get_matching_cycles method attached to the Cycles class. This function takes a list of one or more conditions and returns a booleaen vector indicating which cycles match the conditions. These conditions specify the name of a cycle metric, a standard comparator (such as ==, > or <) and a comparison value.

Here, we will identify which cycles are passing our good cycle checks.

good_cycles = C.get_matching_cycles(['is_good==1'])
print(good_cycles)

Out:

[False  True  True  True  True  True  True  True  True  True  True  True
  True  True False  True  True  True  True  True  True False  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True False  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True False  True  True  True  True
  True  True False False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True False  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True False  True  True False
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True False  True  True
  True False  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True False False  True
  True  True  True  True  True  True  True False False False  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True False False  True  True False  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True False  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True False  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
 False  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True False
  True False  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True False False  True  True  True False  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True False  True
  True  True  True  True  True  True  True  True  True  True False  True
  True  True  True  True  True  True  True  True False False]

This returns a boolean array indicating which cycles meet the specified conditions.

print('{0} matching cycles found'.format(np.sum(good_cycles)))

Out:

708 matching cycles found

and which cycles are failing…

bad_cycles = C.get_matching_cycles(['is_good==0'])
print('{0} matching cycles found'.format(np.sum(bad_cycles)))
print(bad_cycles)

Out:

34 matching cycles found
[ True False False False False False False False False False False False
 False False  True False False False False False False  True False False
 False False False False False False False False False False False False
 False  True False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False  True False False False False
 False False  True  True False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False  True False False False False False False False False False False
 False False False False False False False False  True False False  True
 False False False False False False False False False False False False
 False False False False False False False False False  True False False
 False  True False False False False False False False False False False
 False False False False False False False False False  True  True False
 False False False False False False False  True  True  True False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False  True  True False False  True False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False  True False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False  True False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False  True False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
  True False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False  True False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False  True
 False  True False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False  True  True False False False  True False False
 False False False False False False False False False False False False
 False False False False False False False False False False  True False
 False False False False False False False False False False  True False
 False False False False False False False False  True  True]

Several conditions can be specified in a list

good_cycles = C.get_matching_cycles(['is_good==1', 'duration>40', 'max_amp>1'])
print('{0} matching cycles found'.format(np.sum(good_cycles)))
print(good_cycles)

Out:

322 matching cycles found
[False False  True  True  True  True  True False  True  True  True  True
 False False False False False False False False False False  True  True
  True False  True  True  True False False False  True False False False
 False False False False False False False False False  True  True  True
  True  True  True  True  True False  True  True False False  True False
 False  True  True False False False False False False False False False
 False False False False False False False  True  True False  True  True
 False False  True False False False False  True  True  True False  True
  True  True False  True  True  True  True  True False False False False
 False False False False False False False False False False False False
 False  True False False False False False  True False False False False
 False False False False False False False False False False  True  True
  True  True  True False  True False False False  True  True False False
 False False  True False False False False False False False False False
  True  True False False False False False False  True  True False  True
 False False False False False False  True  True  True  True  True  True
  True  True  True  True  True  True False False False False False False
 False False False False False False  True False False  True  True  True
  True  True  True  True False  True False  True False False False False
 False False False  True  True False False  True  True False False  True
  True False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False  True  True  True  True False False  True  True
  True  True  True  True  True  True  True False False False False False
 False  True  True False  True  True  True  True  True False False False
 False False False False  True  True  True  True False False False  True
  True  True False  True  True False  True  True False False False False
 False False False False False False False False False False False False
 False False False  True False False False  True  True  True  True  True
  True  True  True False False False False False False  True  True  True
  True  True  True  True  True  True False False False False False False
 False  True False False  True False False False False  True  True  True
  True False  True  True  True  True  True  True  True  True  True  True
  True False  True  True False  True  True  True  True False  True  True
 False False False False False False False False  True  True False False
  True  True False False False  True  True  True  True  True False False
  True  True False  True False  True  True  True False False False False
 False False  True  True False False False False False False False  True
  True  True  True  True False  True  True  True  True  True  True  True
  True False  True False  True  True  True  True  True  True  True False
 False False  True False  True  True  True  True  True  True  True False
 False False False  True  True  True  True  True  True  True False False
 False False  True False False False False False False False False False
 False False False False False False False False False False False False
 False False  True  True  True False  True False False False False  True
  True False False False False False  True  True  True  True False False
 False False False  True False False  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True False
  True False  True False  True  True  True  True  True  True  True False
 False False False False False  True  True  True  True  True  True  True
  True  True False False  True  True  True False False False  True False
 False False False False False False False False False  True False  True
  True  True False False  True  True  True  True  True  True  True  True
  True False False False False  True  True False False  True  True  True
  True  True  True False False False False False  True  True False False
 False False False  True  True  True  True False False  True False False
 False False False False False False False False False False False False
  True  True  True False False False False False False False False False
 False  True  True  True  True  True  True  True  True  True  True  True
 False  True False  True False False  True False False False False False
 False False False False  True  True  True  True False False False False
 False  True  True False  True  True  True  True False False]

The conditions can also be used to specify which cycles to include in a pandas dataframe.

df = C.get_metric_dataframe(conditions=['is_good==1', 'duration>40', 'max_amp>1'])
print(df)

Out:

     index  is_good   max_amp  duration     ampSD
0        2        1  1.417456        44  0.132679
1        3        1  1.916196        44  0.165706
2        4        1  1.925473        43  0.049547
3        5        1  1.774759        42  0.078999
4        6        1  1.556685        42  0.172443
..     ...      ...       ...       ...       ...
317    734        1  1.084479        43  0.046493
318    736        1  1.448539        43  0.228107
319    737        1  1.537102        41  0.047038
320    738        1  1.887852        42  0.163623
321    739        1  1.882306        44  0.259681

[322 rows x 5 columns]

Adding custom metrics

Any function that takes a vector input and returns a single value can be used to compute cycle metrics. Here we make a complex user-defined function which computes the degree-of-nonlinearity of each cycle.

def degree_nonlinearity(x):
    """Compute degree of nonlinearity. Eqn 3 in
    https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0168108"""
    y = np.sum(((x-x.mean()) / x.mean())**2)
    return np.sqrt(y / len(x))


C.compute_cycle_metric('DoN', IF[:, 2], degree_nonlinearity)

Custom metrics which take multiple time-series arguments can also be defined. In these cases a tuple of vectors is passed into compute_cycle_metric and the samples for each cycle are indexed out of each vector and passed to the function. For example, here we compute the correlation between the IMF-3 and the raw time-course for each cycle.

def my_corr(x, y):
    return np.corrcoef(x, y)[0, 1]


C.compute_cycle_metric('raw_corr', (imf[:, 2], x[:, 0]), my_corr)

We can also store arbitrary cycle stats in the dictionary - as long as there is one value for every cycle. This might include external values or more complex stats that are beyond the scope of emd.cycles.get_cycle_stat. These can be stored using the Cycles.add_cycle_metric method.

Let’s compute and store the time of the peak and trough in each cycle in milliseconds.

ctrl = emd.cycles.get_control_points(imf[:, 2], C)

peak_time_ms = ctrl[:, 1]/sample_rate * 1000
trough_time_ms = ctrl[:, 3]/sample_rate * 1000

C.add_cycle_metric('peak_time_ms', peak_time_ms)
C.add_cycle_metric('trough_time_ms', trough_time_ms)

Once we have this many cycle metrics, the dictionary storage can be tricky to visualise (though it works well in the internal code). If you have python-pandas installed, you can export the metrics into a DataFrame which is easier to summarise and visualise.

df = C.get_metric_dataframe()
print(df)

Out:

     is_good   max_amp  duration  ...  raw_corr  peak_time_ms  trough_time_ms
0          0  0.933493        26  ...  0.855530           NaN       29.296875
1          1  1.061138        39  ...  0.883864     21.484375       56.640625
2          1  1.417456        44  ...  0.943150       23.4375       64.453125
3          1  1.916196        44  ...  0.960583      19.53125       64.453125
4          1  1.925473        43  ...  0.961683     21.484375            62.5
..       ...       ...       ...  ...       ...           ...             ...
737        1  1.537102        41  ...  0.943542     17.578125       56.640625
738        1  1.887852        42  ...  0.959368      19.53125       60.546875
739        1  1.882306        44  ...  0.968023     17.578125       64.453125
740        0  1.009788        35  ...  0.816109     17.578125       52.734375
741        0  0.260144        18  ...  0.255071      11.71875             NaN

[742 rows x 8 columns]

The summary table for the DataFrame gives a convenient summary description of the cycle metrics.

print(df.describe())

Out:

          is_good     max_amp    duration       ampSD         DoN    raw_corr
count  742.000000  742.000000  742.000000  741.000000  742.000000  742.000000
mean     0.954178    1.060086   41.401617    0.120325    0.400541    0.790279
std      0.209240    0.522938    6.275105    0.073874    3.167948    0.205654
min      0.000000    0.058930    4.000000    0.008349    0.007688   -0.200272
25%      1.000000    0.699712   40.000000    0.065334    0.058293    0.739847
50%      1.000000    1.001210   43.000000    0.104010    0.095077    0.860042
75%      1.000000    1.406171   44.000000    0.155551    0.153249    0.928256
max      1.000000    2.720522   53.000000    0.470968   55.428794    0.984493

Cycle chain analysis

Finally, we can use the emd.cycles.Cycles class to help with cycle chain analyses. This illustrates one of the most complex use-cases for the Cycles object! Computing metrics from groups of cycles and mapping these back to cycle-level metrics can involve some difficult indexing.

Lets extract the big-long-good cycles and compute the continuous chains of cycles within this subset.

C.pick_cycle_subset(['max_amp>1', 'duration>30', 'is_good==1'])

This computes two additional variables. Firstly, a subset_vect which maps cycles into ‘good’ cycles matching our conditions with -1 indicating a cycle which was removed.

print(C.subset_vect)

Out:

[ -1   0   1   2   3   4   5  -1   6   7   8   9  -1  -1  -1  -1  -1  -1
  -1  -1  -1  -1  10  11  12  13  14  15  16  -1  -1  -1  17  18  -1  -1
  -1  -1  -1  -1  -1  -1  -1  -1  -1  19  20  21  22  23  24  25  26  -1
  27  28  -1  29  30  -1  -1  31  32  33  34  -1  -1  -1  -1  -1  -1  -1
  -1  -1  -1  -1  -1  -1  -1  35  36  37  38  39  40  -1  41  -1  -1  -1
  42  43  44  45  -1  46  47  48  49  50  51  52  53  54  -1  -1  -1  -1
  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  55  56  57  58  -1  -1
  -1  59  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  60  61
  62  63  64  65  66  -1  -1  -1  67  68  -1  -1  -1  69  70  71  -1  -1
  -1  -1  -1  -1  -1  -1  72  73  -1  -1  -1  -1  -1  -1  74  75  76  77
  -1  -1  -1  -1  -1  -1  78  79  80  81  82  83  84  85  86  87  88  89
  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  90  -1  -1  91  92  93
  94  95  96  97  -1  98  99 100  -1  -1  -1  -1  -1  -1  -1 101 102  -1
  -1 103 104  -1  -1 105 106  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1 107 108
 109 110 111 112 113 114 115 116 117 118 119 120 121  -1  -1  -1  -1  -1
  -1 122 123  -1 124 125 126 127 128  -1  -1  -1  -1  -1  -1  -1 129 130
 131 132  -1  -1  -1 133 134 135  -1 136 137  -1 138 139  -1  -1  -1  -1
  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1 140 141  -1  -1
  -1 142 143 144 145 146 147 148 149  -1  -1  -1  -1  -1  -1 150 151 152
 153 154 155 156 157 158  -1  -1  -1  -1  -1  -1  -1 159 160 161 162  -1
  -1  -1  -1 163 164 165 166  -1 167 168 169 170 171 172 173 174 175 176
 177 178 179 180 181 182 183 184 185  -1 186 187  -1  -1  -1  -1  -1  -1
  -1  -1 188 189  -1 190 191 192 193  -1  -1 194 195 196 197 198  -1  -1
 199 200 201 202 203 204 205 206 207  -1  -1  -1  -1  -1 208 209  -1  -1
  -1  -1  -1  -1  -1 210 211 212 213 214 215 216 217 218 219 220 221 222
 223  -1 224 225 226 227 228 229 230 231 232  -1  -1  -1 233  -1 234 235
 236 237 238 239 240  -1  -1  -1  -1 241 242 243 244 245 246 247  -1  -1
  -1  -1 248 249  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
  -1  -1  -1  -1  -1  -1  -1  -1 250 251 252 253 254  -1  -1  -1  -1 255
 256  -1  -1  -1  -1  -1 257 258 259 260  -1  -1  -1  -1 261 262  -1 263
 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280  -1
 281  -1 282 283 284 285 286 287 288 289 290  -1  -1  -1  -1  -1  -1 291
 292 293 294 295 296 297 298 299  -1  -1 300 301 302  -1  -1 303 304 305
  -1  -1  -1  -1  -1  -1  -1  -1 306 307 308 309 310 311 312 313 314 315
 316 317 318 319 320 321 322  -1  -1  -1  -1 323 324  -1  -1 325 326 327
 328 329 330  -1  -1  -1  -1  -1 331 332  -1  -1  -1  -1  -1 333 334 335
 336 337  -1 338  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
 339 340 341  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1 342 343 344 345 346
 347 348 349 350 351 352 353 354 355 356 357 358 359  -1  -1  -1  -1  -1
  -1  -1  -1  -1 360 361 362 363  -1  -1  -1  -1  -1 364 365  -1 366 367
 368 369  -1  -1]

Secondly, a chain_vect defines which groups of cycles in the subset form continuous chains.

print(C.chain_vect)

Out:

[ 0  0  0  0  0  0  1  1  1  1  2  2  2  2  2  2  2  3  3  4  4  4  4  4
  4  4  4  5  5  6  6  7  7  7  7  8  8  8  8  8  8  9 10 10 10 10 11 11
 11 11 11 11 11 11 11 12 12 12 12 13 14 14 14 14 14 14 14 15 15 16 16 16
 17 17 18 18 18 18 19 19 19 19 19 19 19 19 19 19 19 19 20 21 21 21 21 21
 21 21 22 22 22 23 23 24 24 25 25 26 26 26 26 26 26 26 26 26 26 26 26 26
 26 26 27 27 28 28 28 28 28 29 29 29 29 30 30 30 31 31 32 32 33 33 34 34
 34 34 34 34 34 34 35 35 35 35 35 35 35 35 35 36 36 36 36 37 37 37 37 38
 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 39 39 40 40 41 41
 41 41 42 42 42 42 42 43 43 43 43 43 43 43 43 43 44 44 45 45 45 45 45 45
 45 45 45 45 45 45 45 45 46 46 46 46 46 46 46 46 46 47 48 48 48 48 48 48
 48 49 49 49 49 49 49 49 50 50 51 51 51 51 51 52 52 53 53 53 53 54 54 55
 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 56 57 57 57 57 57 57
 57 57 57 58 58 58 58 58 58 58 58 58 59 59 59 60 60 60 61 61 61 61 61 61
 61 61 61 61 61 61 61 61 61 61 61 62 62 63 63 63 63 63 63 64 64 65 65 65
 65 65 66 67 67 67 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68
 69 69 69 69 70 70 71 71 71 71]

There is a helper function in the Cycles object which computes a set of simple chain timing metrics. These are ‘chain_ind’, chain_start, chain_end, chain_len_samples, chain_len_cycles and chain_position. Each metric is computed and a value saved out for each cycle.

C.compute_chain_timings()

df = C.get_metric_dataframe(subset=True)
print(df)

Out:

     index  is_good  ...  chain_len_cycles  chain_position
0        1        1  ...                 6               0
1        2        1  ...                 6               1
2        3        1  ...                 6               2
3        4        1  ...                 6               3
4        5        1  ...                 6               4
..     ...      ...  ...               ...             ...
365    734        1  ...                 2               1
366    736        1  ...                 4               0
367    737        1  ...                 4               1
368    738        1  ...                 4               2
369    739        1  ...                 4               3

[370 rows x 15 columns]

We can also compute chain specific metrics similar to how we compute cycle metrics. Each chain metric is saved out for each cycle within the chain. Here we compute the maximum amplitude for each chain and plot its relationship with chain length.

C.compute_chain_metric('chain_max_amp', IA[:, 2], np.max)
df = C.get_metric_dataframe(subset=True)

plt.figure()
plt.plot(df['chain_len_samples'], df['chain_max_amp'], '.')
plt.xlabel('Chain Length (samples)')
plt.ylabel('Chain Max-Amplitude')
emd tutorial 03 cycle 03 cycleclass

Out:

Text(33.972222222222214, 0.5, 'Chain Max-Amplitude')

We can then select the cycle metrics from the cycles in a single chain by specifying the chain index as a condition.

df = C.get_metric_dataframe(conditions='chain_ind==42')
print(df)

Out:

   index  is_good   max_amp  ...  chain_len_cycles  chain_position  chain_max_amp
0    425        1  1.259696  ...                 5               0       1.633524
1    426        1  1.444930  ...                 5               1       1.633524
2    427        1  1.633524  ...                 5               2       1.633524
3    428        1  1.609695  ...                 5               3       1.633524
4    429        1  1.138997  ...                 5               4       1.633524

[5 rows x 16 columns]

Total running time of the script: ( 0 minutes 2.990 seconds)

Gallery generated by Sphinx-Gallery