README.

advertisement
README for Kagaya_Patek_2015JEB_dataset_for_dryad.rdata
To load the dataset and functions in R environment used for the analyses in the paper, "Feed-forward motor
control of ultrafast, ballistic movements" by Katsushi Kagaya and S. N. Patek, type
> load("Kagaya_Patek_2015JEB_dataset_for_dryad.rdata ")
then all dataset and R functions required for the analysis will be loaded to your work space.
Dataset
The data are contained as R objects named for each animal ID. The IDs are, “nb18, nb30, nb500, nb504,
nb520, nb55”. Each object is a nested object. If you want to see the name of sub-contents, type
> names(nb30)
[1] "phys" "spike.df" "contraction"
"strike" "fps.contraction" "fps.strike"
[8] "strike.type" "prop.len"
"gender" "mmperpix" "merus.len"
"id"
then the names for the sub-contents will be returned. The sub-contents are summarized in the table below.
names
phys
spike.df
contraction
strike
fps.contraction
fps.strike
id
strike.type
prop.len
gender
mmperpix
merus.len
sub-contents
EMG data
spike timing data
digitized data of spring compression
digitized data of strike movement
frames per second for contraction
frames per second for strike
animal ID
single strike or double strike (This information is not used in the current study.)
propodus length
gender of the animal
mm per pixel value for the high speed images
merus length
Some of these sub-contents are further nested.
For example, if you want strike kinematics data of the propodus rotation of the first strike of nb18, type
> first.strike.p.kinematics.nb18 <- nb18$strike$output.propodus.rotation[[1]]
then you can store the data in the object “first.strike.p.kinematics.nb18”.
On the other hand, if you want strike kinematics data of the meral-V rotation of the second strike of nb30,
type
> second.strike.m.kinematics.nb30 <- nb30$strike$output.meralV.rotation[[2]]
then you can store the data in the object “second.strike.m.kinematics.nb30”.
The results in the paper can be reproduced by using the functions introduced in the next section.
Functions
The functions are written in three separate scripts; these are available from three URLs and are also included
in this Dryad depository.
script name
Kagaya_Patek_kinem_control_emg.R
Kagaya_Patek_kinem_control_hsv.R
Kagaya_Patek_kinem_control_stat.R
URL
https://gist.github.com/kagaya/36145a370a1da0f4ba0d
https://gist.github.com/kagaya/540596f6d1191c157cb7
https://gist.github.com/kagaya/cbafe0a332e6d6766168
For example, to reproduce the analyses in the study, type
> source(“Kagaya_Patek_kinem_control_stat.R”)
then you are ready for the analyses and visualization using the functions summarized in the three tables.
1.
Kagaya_Patek_kinem_control_emg.R
Functions for preprocessing and spike detection from EMG data.
function name
function
read.phys
read the physiological data from the text file—exported file from chart software
print.phys
show the length of the read phys data
plot.phys
plot phys data
plot.phys.aligned
plot the aligned phys data which is available by align.phys function
align.phys
return time aligned phys data
truncate.phys
truncate the phys data nessary for the analysis
get.spike.timing
return the time stamps of the peaks of spikes in EMG
detect.peak
detect the spike peaks
find.peak
return peak values from one time series data
my.theme
customize ggplot for publication, usage: q + my.theme()
2.
Kagaya_Patek_kinem_control_hsv.R
Functions for preprocessing and obtaining kinematic data.
function name
function
read.one.mdf
read mdf — output of MTrackJ which is a plugin of ImageJ used for digitizing
get.rotation
return rotation data with the current two lines method
get.rotation2
return rotation data with the previous pivot point method
check.rotation
compare the two methods
plot.track
plot digitized points
my.theme
customize ggplot for publication, usage: q + my.theme()
3.
Kagaya_Patek_kinem_control_stat.R
Functions for visualization and statistical modeling of the dataset.
function name
function
generate.data.for.model.selection
generate dataset (stat.df) for statistical modeling
aggregate.stats
return descriptive statistics of stat.df
model.selection
perform model selection and output the AICs and coefficients
fit.input.rotation.vs.number.of.spike visualize the relationship of input spring rotation and # spikes
fit.strike.velocity.vs.number.of.spike visualize the relationship of strike velocity and # spikes
plot.time.diff.acc
plot time intervals between maximum acceleration of propodus
and meral-V
plot.emg.contraction
plot input meral-V rotation and EMG of the extensor
fit.3.kinematics
fit the 10th order polynomial and GAM of 3 strikes
fit.kinematics
my.theme
fit the 10th order polynomial and GAM of a single strike
customize ggplot for publication, usage: q + my.theme()
Usage
Before using these functions, please load the following packages required for the analyses:
> library(ggplot2); library(plyr); library(mgcv); library(nlme)
read.phys
Type,
> phys <- read.phys(“folder_name_containing_text_files_exported_from_labchart_software”)
then EMG data will be stored in the object, phys. Each text file looks like the screen shot below. The
left-most column contains the timestamp, and following columns contain voltage time series data. In this
case, four columns are contained in a text file named ’01.txt’. The folder is expected to contained several
text files in this format and the files are expected to be named as ’01.txt’, ’02.txt’…
print.phys
Type,
> print.phys(phys)
24 physiological data.
or just type,
> phys
24 physiological data.
The class of the phys is phys, so you do not have to type ‘phys’ for print, and plot functions.
plot.phys
Type,
> plot(phys)
then a plot like below will be returned.
It looks the time stamps are aligned. However, the time stamps of the data phys are actually not aligned (see
the x axis of the plot below).
> plot(phys[[1]]$phys$V1, phys[[1]]$phys$V2, type="l")
plot.phys.aligned
align.phys
To align, type,
> phys.aligned <- align.phys(phys)
> plot.phys.aligned(phys.aligned, ch=1)
The ‘align.phys’ will align the time series, and ‘plot.phys.aligned’ will return the plot of the time series data
of the channel set by 'ch'.
truncate.phys
> phys.truncated <- truncate.phys(phys.aligned, my.lim = c(-0.75, 0.01))
> plot.phys.aligned(phys.truncated)
This function truncates phys data by setting the time range. In this case, phys.truncated will be the object
containing the data from -0.75 sec to 0.01 sec.
get.spike.timing
detect.peak
find.peak
To detect the spikes of the EMG data and store the spike timing data, type
> spike.timings <- get.spike.timing(phys.truncated)
then this will give the next plot, such as:
then you are expected to click two points which determine a time range for detecting spikes. If you click the
two points, then a zoomed-in window will appear, and you are expected to select a threshold. The window
will show red open circles to indicate the detected points. The functions "detect.peak" and "find.peak" are
used in the function "get.spike.timing".
After showing the detected points, the function will show three options,
1: next
2: redo
3: no_spikes
Selection:
Select one of these three options to continue. If you repeat this process as many as the number of the strikes,
then the spike timing data will be stored in ' spike.timings '.
read.one.mdf
plot.track
> my.track <- read.one.mdf('file_name_of_digitized_data_using_MTrackJ.mdf')
> plot.track(my.track)
It should be noted that this plot is upside down. The points 1, 2 are on the propodus, and the points 3, 4 are
on the meral-V, and the points 5-8 are on the merus. The point 1 is the trajectory of the tip of propodus.
get.rotation
To get rotation of the two lines (uses the two line method described in the online Supplementary Materials
of Kagaya&Patek).
> my.rotation <- get.rotation(my.track, target.v=nb504$strike$chosen.point$propodus[[1]]$target,
ref.v=nb504$strike$chosen.point$propodus[[1]]$reference)
> plot(my.rotation)
Thus, the function get.rotation will give angular rotation of the propodus.
get.rotation2
To get rotation of a point using previous method (pivot point method), this function can be used.
> my.rotation2 <- get.rotation2(my.track, 212.18, 1)
> plot(my.rotation2)
Since the number of points of my.rotation2 is one less than my.rotation2,
> my.rotation2 <- c(0, my.rotation2)
and, the sign of my.rotation is minus.
> plot(-my.rotation)
> points(my.rotation2, pch=3)
check.rotation
> check.rotation(animal = nb504, strike = 10,
focal.p.m = 3, vlines = c(1, 21, 36, 46, 55))
arm.length = 212.18, focal.p = 1, arm.length.m = 80.63,
generate.data.for.model.selection
> stat.df <- generate.data.for.model.selection(ang=20, time.lim=c(-10,0), nb18, nb30, nb55, nb500, nb504,
nb520)
> names(stat.df)
[1] "id"
"strike.num"
"input.rotation"
[4] "input.rotation2"
"rotational.vel.m.in"
"max.acc.m.in"
[7] "velocity.meralV"
"max.acc.meralV"
"time.at.max.acc.meralV"
[10] "time.diff.max.acc"
"time.at.limit"
"time.at.max.linear.vel"
[13] "time.at.max.acc"
"max.linear.vel"
"linear.vel.at.limit"
[16] "max.linear.acc"
"linear.acc.at.limit"
"max.vel"
[19] "vel.at.limit"
"max.acc"
"acc.at.limit"
[22] "spike.num"
"spike.num.init100"
"spike.num.last100"
[25] "spike.num.100.with.silent" "duration"
"duration2"
[28] "silent"
"spike.num.over.duration"
"spike.num.over.duration2"
column's name
id
strike.num
input.rotation
input.rotation2
rotational.vel.m.in
contents
animal ID
strike event number
input rotation of meral-V (degrees)
input rotation of meral-V offset by the value when the extensor is on (degrees)
maximum angular velocity of loading movement of meral-V (rad/s)
max.acc.m.in
velocity.meralV
max.acc.meralV
time.at.max.acc.meralV
time.diff.max.acc
time.at.limit
time.at.max.linear.vel
time.at.max.acc
max.linear.vel
linear.vel.at.limit
max.linear.acc
linear.acc.at.limit
max.vel
vel.at.limit
max.acc
acc.at.limit
spike.num
spike.num.init100
spike.num.last100
spike.num.100.with.silent
duration
duration2
silent
spike.num.over.duration
spike.num.over.duration2
maximum angular acceleration of loading movement of meral-V (rad/s2)
maximum angular velocity of unloading movement of meral-V (rad/s)
maximum angular acceleration of unloading movement of meral-V (rad/s2)
duration until maximum acceleration of meral-V (ms)
time difference between the max. acc. of meral-V and propodus (ms)
time at the limit set by 'ang' (ms)
time at maximum linear velocity of propodus (ms)
time at maximum acceleration of propodus (ms)
maximum linear velocity of propodus (m/s)
linear velocity when the angular position of propodus is at the limit set by 'ang'
(m/s)
maximum linear acceleration of propodus movement (m/s2)
linear acceleration when the angular position of propodus is at the limit set by
'ang' (m/s)
maximum angular velocity of propodus movement (rad/s)
angular velocity of propodus movement when the angular position of propodus
is at the limit set by 'ang' (rad/s)
maximum angular acceleration of proposed movement (rad/s2)
angular acceleration of propodus when the angular position of propodus is at
the limit set by 'ang' (rad/s2)
number of extensor spikes during co-activation (samples)
number of extensor spikes of initial 100 ms of co-activation (samples)
number of extensor spikes of last 100 ms of co-activation (samples)
number of extensor spikes of 100 ms before initiation including silent phase
(samples)
duration of co-activation phase (s)
duration of co-activation + silent phase (s)
duration of silent phase (s)
number of spikes divided by duration (samples/s)
number of spikes divided by duration2 (samples/s)
aggregate.stats
> aggregate.stats(stat.df, variable="max.linear.vel", my.times=1, my.round=1)
nb18 , 18.8 x 1 +- 3 x 1
nb18 , 11.8 x 1 to 21.6 x 1
nb30 , 11.1 x 1 +- 2.8 x 1
nb30 , 7.9 x 1 to 17.1 x 1
nb55 , 12.3 x 1 +- 2.3 x 1
nb55 , 6.5 x 1 to 16 x 1
nb500 , 5.4 x 1 +- 1.9 x 1
nb500 , 2.8 x 1 to 8.3 x 1
nb504 , 9 x 1 +- 1.3 x 1
nb504 , 6.9 x 1 to 11.2 x 1
Thus, it gives descriptive statistics.
model.selection
> model.selection(stat.df)
> model.selection(stat.df)
explanatory.var AIC.REML
AIC.ML intercept intercept.se
slope
slope.se
(Intercept)
spike.num 463.1411 461.2025 4.206958
1.070857
0.14150328 0.06191333
(Intercept)1
spike.num.init100 485.8613 486.9569 6.465246
2.408308
0.17325476 0.13632150
(Intercept)2
spike.num.last100 480.8463 481.9937 4.629519
1.994123
0.33616079 0.17723701
(Intercept)3 spike.num.100.with.silent 473.7170 475.2103 4.881967
1.425891
0.46282135 0.27857630
(Intercept)4
duration 457.7649 465.4289 3.424693
1.171189 15.30112691 7.19606425
(Intercept)5
silent 464.2328 477.3489 9.830163
4.417432 -45.67679915 81.36731397
(Intercept)6
spike.num.over.duration 485.1200 482.0156 5.005784
1.914403
0.03424507 0.02499605
(Intercept)7 spike.num.over.duration2 480.2285 477.2019 4.144641
1.751028
0.04954904 0.02957959
(Intercept)8
no.random.effects 558.6284
NA 9.487753
1.110818 -0.01942053 0.02624676
(Intercept)9
null 479.6567 482.9029 8.137653
2.141671
0.00000000
NA
pval
(Intercept) 0.02486472
(Intercept)1 0.20734810
(Intercept)2 0.06139211
(Intercept)3 0.10045585
(Intercept)4 0.03648363
(Intercept)5 0.57607942
(Intercept)6 0.17442044
(Intercept)7 0.09772263
(Intercept)8 0.46136296
(Intercept)9
NA
explanatory.var AIC.REML
AIC.ML intercept intercept.se
slope
slope.se
(Intercept)
input.rotation 1252.971 1272.510 1219.572
220.6624
40.287600
15.332805
(Intercept)1
spike.num 1247.850 1265.841 1190.065
235.8550
14.958630
6.292672
(Intercept)2
spike.num.init100 1275.570 1295.804 1627.593
345.8714
-3.395432
13.042795
(Intercept)3
spike.num.last100 1256.628 1278.451 1202.264
359.3402
45.353524
32.317438
(Intercept)4 spike.num.100.with.silent 1253.960 1275.454 1087.739
288.7316
73.569795
32.281425
(Intercept)5
duration 1237.108 1263.766 1035.774
180.5474 1695.300122 616.642632
(Intercept)6
silent 1258.791 1291.468 1798.548
450.6945 -6944.531247 7094.235567
(Intercept)7
spike.num.over.duration 1275.991 1292.390 1334.574
323.0438
2.665808
2.030232
(Intercept)8
spike.num.over.duration2 1272.768 1289.356 1217.518
322.0429
4.263625
2.217593
(Intercept)9
no.random.effects 1410.643
NA 1610.524
157.3805
-1.086799
3.718638
(Intercept)10
null 1276.580 1289.950 1585.320
338.2133
0.000000
NA
pval
(Intercept)
0.010263001
(Intercept)1 0.019775421
(Intercept)2 0.795261786
(Intercept)3 0.164280208
(Intercept)4 0.025265655
(Intercept)5 0.007345858
(Intercept)6 0.330509761
(Intercept)7 0.192826840
(Intercept)8 0.057997769
(Intercept)9 0.770793883
(Intercept)10
NA
fit.input.rotation.vs.number.of.spike
> fit.input.rotation.vs.number.of.spike(stat.df)
* The summary of the constant model:
Linear mixed-effects model fit by REML
Data: ddf
AIC
BIC
logLik
479.6567 487.0544 -236.8283
Random effects:
Formula: ~1 | id
(Intercept) Residual
StdDev:
4.718831 3.305341
Fixed effects: input.rotation ~ 1
Value Std.Error DF t-value p-value
(Intercept) 8.137653 2.141671 83 3.799675
3e-04
Standardized Within-Group Residuals:
Min
Q1
Med
Q3
-2.36873405 -0.58618144 0.01086766 0.56482019
Max
3.64202228
Number of Observations: 88
Number of Groups: 5
* The summary of the correlative model:
Linear mixed-effects model fit by REML
Data: ddf
AIC
BIC
logLik
463.1411 477.8672 -225.5705
Random effects:
Formula: ~1 + spike.num | id
Structure: General positive-definite, Log-Cholesky parametrization
StdDev
Corr
(Intercept) 0.9576121 (Intr)
spike.num 0.1169618 0.9
Residual
2.8136329
Fixed effects: input.rotation ~ spike.num
Value Std.Error DF t-value p-value
(Intercept) 4.206958 1.0708566 82 3.928592 0.0002
spike.num
0.141503 0.0619133 82 2.285506 0.0249
Correlation:
(Intr)
spike.num -0.155
Standardized Within-Group Residuals:
Min
Q1
Med
Q3
Max
-2.46906304 -0.60694381 -0.02264248 0.61118779 3.24939812
Number of Observations: 88
Number of Groups: 5
fit.strike.velocity.vs.number.of.spike
> fit.strike.velocity.vs.number.of.spike(stat.df)
* The summary of the constant model:
Linear mixed-effects model fit by REML
Data: df
AIC
BIC
logLik
1276.58 1283.978 -635.2901
Random effects:
Formula: ~1 | id
(Intercept) Residual
StdDev:
752.2518 314.9232
Fixed effects: vel.at.limit ~ 1
Value Std.Error DF t-value p-value
(Intercept) 1585.32 338.2133 83 4.68734
0
Standardized Within-Group Residuals:
Min
Q1
Med
Q3
-3.47926010 -0.68526185 0.05504432 0.57435227
Max
2.51601954
Number of Observations: 88
Number of Groups: 5
* The summary of the correlative model:
Linear mixed-effects model fit by REML
Data: df
AIC
BIC
logLik
1247.85 1262.576 -617.9249
Random effects:
Formula: ~1 + spike.num | id
Structure: General positive-definite, Log-Cholesky parametrization
StdDev
Corr
(Intercept) 469.73339 (Intr)
spike.num
11.86145 0.443
Residual
259.32414
Fixed effects: vel.at.limit ~ spike.num
Value Std.Error DF t-value p-value
(Intercept) 1190.0646 235.85500 82 5.045747 0.0000
spike.num
14.9586
Correlation:
(Intr)
spike.num 0.111
6.29267 82 2.377151
0.0198
Standardized Within-Group Residuals:
Min
Q1
Med
Q3
-3.44417658 -0.59393938 0.02721824 0.47277176
Number of Observations: 88
Number of Groups: 5
plot.time.diff.acc
> plot.time.diff.acc(stat.df)
Max
2.76723871
plot.emg.contraction
> plot.emg.contraction(nb504, emg.ch=1, strike.num=2)
fit.3.kinematics
> fit.3.kinematics(nb30, my.strikes=c(1,2,3))
fit.kinematics
If you want to see kinematics of the first strike movement by the animal nb18, type
> fit.kinematics(nb30, 1)
Download