burst_summary_algorithm_LAa.R 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. # Laura Aarnos 190213
  2. # meaRtools: write burst summary
  3. # original functions from meaRtools 2018, modification made by LAa and marked with _mod
  4. # code for write_plate_summary_for_bursts
  5. write_plate_summary_for_bursts_mod <- function(s, outputdir) {
  6. master_sum <- .get_mean_burst_info_per_well_mod(s)
  7. csvwell <- paste(outputdir, "/", get_project_plate_name(s[[1]]$file),
  8. "_well_bursts.csv", sep = "")
  9. for (i in 1:length(s)) {
  10. div <- .get_div(s[[i]])
  11. basename <- get_file_basename(s[[i]]$file)
  12. csvfile <- paste(outputdir, "/", basename, "_bursts.csv", sep = "")
  13. ########## data frame summarized over well
  14. # get number of object in master_sum[[1]] list
  15. tempdf <- c(); tempcolnames <- c()
  16. for (j in 2:length(master_sum[[i]])) {
  17. tempc <- unlist(master_sum[[i]][j])
  18. tempdf <- cbind(tempdf, tempc)
  19. tempcolnames <- c(tempcolnames, names(master_sum[[i]][j]))
  20. } # end of loop through master_sum list objects
  21. # need to switch around columns so first columns come first
  22. if (dim(tempdf)[2] > 20) {
  23. if (dim(tempdf)[1] == 1) {
  24. df <- cbind(t(tempdf[, 21:25]), t(tempdf[, 1:20]))
  25. } else {
  26. df <- cbind(tempdf[, 21:25], tempdf[, 1:20])
  27. }
  28. colnames <- c(tempcolnames[21:25], tempcolnames[1:20])
  29. colnames(df) <- colnames
  30. }
  31. ################## channel by channel burst summary
  32. # meta data and misc
  33. # get vector of which wells are active
  34. wellindex <- which(is.element(names(s[[i]]$treatment),
  35. unique(s[[i]]$cw)))
  36. well <- c(); file <- c();
  37. file <- rep(strsplit(basename(s[[i]]$file), ".RData")[[1]][1],
  38. length(s[[i]]$cw))
  39. well <- s[[i]]$cw
  40. # channel data frame
  41. df2 <- cbind(file, well, as.data.frame(s[[i]]$bs[1:length(s[[i]]$bs)]))
  42. # write a title
  43. write.table("Burst Analysis Averaged Over Each Well",
  44. csvfile, sep = ",", append = FALSE, row.names = FALSE, col.names = FALSE)
  45. write.table(paste("file= ", strsplit(basename(s[[i]]$file),
  46. ".RData")[[1]][1], sep = ""),
  47. csvfile, sep = ",", append = TRUE, row.names = FALSE, col.names = FALSE)
  48. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  49. col.names = FALSE)
  50. # recording time
  51. write.table(paste("recording time (s): [", paste(s[[i]]$rec_time[1],
  52. round(s[[i]]$rec_time[2]), sep = " ,"),
  53. "]", sep = ""), csvfile, sep = ",", append = TRUE, row.names = FALSE,
  54. col.names = FALSE)
  55. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  56. col.names = FALSE)
  57. # summary write data, add back genotype (column 1)
  58. if (dim(df)[1] == 1) {
  59. suppressWarnings(write.table(t(df[, - c(2:3)]),
  60. csvfile, sep = ",", append = TRUE, row.names = FALSE,
  61. col.names = TRUE))
  62. if (i == 1) {
  63. suppressWarnings(write.table(cbind(div, t(df[, - c(2:3)])),
  64. csvwell, sep = ",", append = TRUE, row.names = FALSE,
  65. col.names = TRUE))
  66. } else {
  67. suppressWarnings(write.table(cbind(div, t(df[, - c(2:3)])),
  68. csvwell, sep = ",", append = TRUE, row.names = FALSE,
  69. col.names = FALSE))
  70. }
  71. } else {
  72. suppressWarnings(write.table(df[, - c(2:3)],
  73. csvfile, sep = ",", append = TRUE, row.names = FALSE,
  74. col.names = TRUE))
  75. if (i == 1) {
  76. suppressWarnings(write.table(cbind(div, df[, - c(2:3)]),
  77. csvwell, sep = ",", append = TRUE, row.names = FALSE,
  78. col.names = TRUE))
  79. } else {
  80. suppressWarnings(write.table(cbind(div, df[, - c(2:3)]),
  81. csvwell, sep = ",", append = TRUE, row.names = FALSE,
  82. col.names = FALSE))
  83. }
  84. }
  85. # new lines
  86. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  87. col.names = FALSE)
  88. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  89. col.names = FALSE)
  90. # title
  91. write.table("Channel Burst Summary", csvfile, sep = ",", append = TRUE,
  92. row.names = FALSE, col.names = FALSE)
  93. write.table(paste("file= ", strsplit(basename(s[[i]]$file),
  94. ".RData")[[1]][1], sep = ""),
  95. csvfile, sep = ",", append = TRUE, row.names = FALSE, col.names = FALSE)
  96. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  97. col.names = FALSE)
  98. # channel data
  99. suppressWarnings(write.table(df2,
  100. csvfile, sep = ",", append = TRUE, row.names = FALSE, col.names = TRUE))
  101. # new lines
  102. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  103. col.names = FALSE)
  104. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  105. col.names = FALSE)
  106. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  107. col.names = FALSE)
  108. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  109. col.names = FALSE)
  110. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  111. col.names = FALSE)
  112. write.table(" ", csvfile, sep = ",", append = TRUE, row.names = FALSE,
  113. col.names = FALSE)
  114. } # end of loop through writting tables
  115. }
  116. .calc_all_isi <- function(s, allb) {
  117. ## Compute ISI within bursts for all spike trains.
  118. calc_isi <- function(spikes, b) {
  119. ## for one spike train, get all isis within bursts in that train.
  120. if (.num_bursts(b) == 0) {
  121. return(NA)
  122. }
  123. ## as.vector is needed below in case each burst is of the same
  124. ## length (in which case an array is returned by apply). In
  125. ## normal cases, bursts are of different lengths, so "apply"
  126. ## returns a list.
  127. isis <- as.vector(
  128. unlist(apply(b, 1,
  129. function(x) {
  130. diff(spikes[x[1]:x[2]])
  131. })))
  132. }
  133. nchannels <- s$NCells
  134. isis <- list()
  135. for (i in 1:nchannels) {
  136. isis[[i]] <- calc_isi(s$spikes[[i]], allb[[i]])
  137. }
  138. isis
  139. }
  140. .calc_ibi <- function(spikes, b) {
  141. ## Compute the interburst intervals (IBI) for one spike train.
  142. ## Only valid if more than one burst.
  143. nburst <- .num_bursts(b)
  144. if (nburst == 0) {
  145. res <- NA # no bursts
  146. } else {
  147. if (nburst == 1) {
  148. res <- NA # cannot compute IBI w/only 1 burst.
  149. } else {
  150. ## find end spike in each burst.
  151. end <- b[, "beg"] + b[, "len"] - 1
  152. ## for n bursts, there will be n bursts minus 1 IBIs.
  153. start_spikes <- b[2:nburst, "beg"]
  154. end_spikes <- end[1:(nburst - 1)]
  155. ## NEX uses a strange definition of IBI: it counts the time between
  156. ## the first spike of n burst and the first spike of n burst
  157. ## plus one as the IBI.
  158. ## If we want to use that definition, use the following line:
  159. ## end.spikes equal b where 1 to nburst minus 1
  160. res <- spikes[start_spikes] - spikes[end_spikes]
  161. }
  162. }
  163. res
  164. }
  165. .num_bursts <- function(b) {
  166. ## Return the number of bursts found for a spike train.
  167. if (is.na(b[1]))
  168. 0
  169. else
  170. nrow(b)
  171. }
  172. .calc_all_ibi <- function(s, allb) {
  173. ## Compute IBI for all spike trains.
  174. nchannels <- s$NCells
  175. ibis <- list()
  176. for (i in 1:nchannels) {
  177. ibis[[i]] <- .calc_ibi(s$spikes[[i]], allb[[i]])
  178. }
  179. ibis
  180. }
  181. .get_mean_burst_info_per_well_mod <- function(s) {
  182. master_sum <- list() # summary over all files
  183. for (i in 1:length(s)) {
  184. sum <- list() # summary for each timepoint
  185. # calculate bursting variables for current data File
  186. nbursts <- sapply(s[[i]]$allb, nrow)
  187. allb <- s[[i]]$allb
  188. tempsum <- calc_burst_summary(s[[i]])
  189. ###### NEW PART 1/3 ######
  190. for (t in 1:nrow(tempsum)) {
  191. if (tempsum[t,'nbursts'] == 0) {
  192. tempsum[t,'bursts_per_sec'] <- NA
  193. tempsum[t,'bursts_per_min'] <- NA
  194. tempsum[t,'mean_dur'] <- NA
  195. tempsum[t,'mean_spikes'] <- NA
  196. }
  197. }
  198. ###### NEW PART 1/3 ENDS ######
  199. # isis: gets the ISI for each channel of s[[i]]
  200. isis <- .calc_all_isi(s[[i]], allb)
  201. # IBIs get IBI's across all inter burst intervals across all data
  202. temp_ibis <- .calc_all_ibi(s[[i]], allb)
  203. # loop through goodwells
  204. for (j in 1:length(s[[i]]$goodwells)) {
  205. # indicator of current well
  206. icurrentwell <- (s[[i]]$goodwells[j] == s[[i]]$cw)
  207. # index of current well
  208. incurrentwell <- which(s[[i]]$goodwells[j] == s[[i]]$cw)
  209. if (sum(icurrentwell) != 0){
  210. ##### variables that need summing and averaging
  211. # total spikes across all AE in current well
  212. sum$nspikes[j] <- sum(tempsum$spikes[icurrentwell], na.rm = TRUE)
  213. sum$nAB[j] <- length(which(nbursts[incurrentwell] > 0))
  214. # Total recorded time on current well= recording time * nae
  215. sum$duration[j] <-
  216. length(incurrentwell) * (s[[i]]$rec_time[2] - s[[i]]$rec_time[1])
  217. # mean duration
  218. sum$mean_dur[j] <- mean(tempsum$mean_dur[incurrentwell], na.rm = TRUE)
  219. # mean spikes per second
  220. sum$mean_freq[j] <- mean(tempsum$mean_freq[incurrentwell], na.rm = TRUE)
  221. # total number of bursts
  222. sum$nbursts[j] <- sum(tempsum$nbursts[icurrentwell], na.rm = TRUE)
  223. # mean burst per second
  224. sum$bursts_per_sec[j] <- mean(tempsum$bursts_per_sec[incurrentwell], na.rm = TRUE)
  225. # mean burst per minute
  226. sum$bursts_per_min[j] <- sum$bursts_per_sec[j] * 60
  227. # finds the mean of duration for a particular well (across all channels)
  228. # get_burst_info(allb[icurrentwell],"durn")
  229. # takes out the column "durn" of all
  230. # matricies allb among the indicator set icurrentwell
  231. # get duration data across all channels of current well
  232. #sum$mean_dur[j] <-
  233. # mean(unlist(get_burst_info(allb[icurrentwell], "durn")), na.rm = TRUE)
  234. ######## NEW PART 2/3 #########
  235. my.dur <- unlist(get_burst_info(allb[icurrentwell], "durn"))
  236. my.len <- unlist(get_burst_info(allb[incurrentwell], "len"))
  237. for (m in 1:length(my.dur)) {
  238. if (my.dur[m] == 0) {
  239. my.dur[m] <- NA
  240. }
  241. }
  242. for (n in 1:length(my.len)) {
  243. if (my.len[n] == 0) {
  244. my.len[n] <- NA
  245. }
  246. }
  247. # get duration data across all channels of current well
  248. sum$mean_dur[j] <-
  249. mean(my.dur, na.rm = TRUE)
  250. # sd of current well burst durations
  251. sum$sd_dur[j] <- sd(my.dur, na.rm = TRUE)
  252. # mean frequency within a burst
  253. sum$mean_freq_in_burst[j] <-
  254. mean(my.len /
  255. my.dur, na.rm = TRUE)
  256. # sd frequency within a burst
  257. sum$sd_freq_in_burst[j] <-
  258. sd(my.len /
  259. my.dur, na.rm = TRUE)
  260. ######## NEW PART 2/3 ENDS ########
  261. # sd of current well burst durations
  262. #sum$sd_dur[j] <- sd(unlist(get_burst_info(allb[icurrentwell], "durn")))
  263. # mean frequency within a burst
  264. #sum$mean_freq_in_burst[j] <-
  265. # mean(unlist(get_burst_info(allb[incurrentwell], "len")) /
  266. # unlist(get_burst_info(allb[incurrentwell], "durn")), na.rm = TRUE)
  267. # sd frequency within a burst
  268. #sum$sd_freq_in_burst[j] <-
  269. # sd(unlist(get_burst_info(allb[incurrentwell], "len")) /
  270. # unlist(get_burst_info(allb[incurrentwell], "durn")), na.rm = TRUE)
  271. # mean of ISI across all channels in current well
  272. sum$mean_isis[j] <- mean(unlist(isis[incurrentwell]), na.rm = TRUE)
  273. # finds sd of ISI across all channels in current well
  274. sum$sd_isis[j] <- sd(unlist(isis[incurrentwell]), na.rm = TRUE)
  275. ######## NEW PART 3/3 ########
  276. # mean spikes in burst
  277. sum$mean_spikes_in_burst[j] <- round(mean(my.len, na.rm = TRUE), 3)
  278. # sd of spikes in burst
  279. sum$sd_spikes_in_burst[j] <- round(sd(my.len, na.rm = TRUE), 3)
  280. # total number of spikes arcross all bursts
  281. sum$total_spikes_in_burst[j] <- sum(unlist(get_burst_info(allb[incurrentwell], "len")), na.rm = TRUE)
  282. ######## NEW PART 3/3 ENDS ########
  283. # len=#spikes in burst (length of burst in bursts)
  284. # mean_spikes_in_burst
  285. #ns <- unlist(get_burst_info(allb[icurrentwell], "len"))
  286. #sum$mean_spikes_in_burst[j] <- round(mean(ns, na.rm = TRUE), 3)
  287. # sd of spikes in burst
  288. #sum$sd_spikes_in_burst[j] <- round(sd(ns, na.rm = TRUE), 3)
  289. # total number of spikes arcross all bursts
  290. #sum$total_spikes_in_burst[j] <- sum(ns, na.rm = TRUE)
  291. # percent of spikes in bursts
  292. sum$per_spikes_in_burst[j] <-
  293. round(100 * (sum$total_spikes_in_burst[j] / sum$nspikes[j]), 3)
  294. # mean IBI
  295. sum$mean_ibis[j] <-
  296. round(mean(unlist(temp_ibis[incurrentwell]), na.rm = TRUE), 3)
  297. # sd IBI
  298. sum$sd_ibis[j] <-
  299. round(sd(unlist(temp_ibis[incurrentwell]), na.rm = TRUE), 3)
  300. # cv IBI
  301. sum$cv_ibis[j] <- round(sum$mean_ibis[j] / sum$sd_ibis[j], 3)
  302. } else {
  303. sum$nspikes[j] <- NA
  304. sum$nAB[j] <- NA
  305. sum$duration[j] <- NA
  306. sum$mean_dur[j] <- NA
  307. sum$mean_freq[j] <- NA
  308. sum$nbursts[j] <- NA
  309. sum$bursts_per_sec[j] <- NA
  310. sum$bursts_per_min[j] <- NA
  311. sum$mean_dur[j] <- NA
  312. sum$sd_dur[j] <- NA
  313. sum$mean_freq_in_burst[j] <- NA
  314. sum$sd_freq_in_burst[j] <- NA
  315. sum$mean_isis[j] <- NA
  316. sum$sd_isis[j] <- NA
  317. sum$mean_spikes_in_burst[j] <- NA
  318. sum$sd_spikes_in_burst[j] <- NA
  319. sum$total_spikes_in_burst[j] <- NA
  320. sum$per_spikes_in_burst[j] <- NA
  321. sum$mean_ibis[j] <- NA
  322. sum$sd_ibis[j] <- NA
  323. sum$cv_ibis[j] <- NA
  324. }
  325. }
  326. ### Set all names
  327. for (k in 1:length(names(sum))) {
  328. names(sum[[k]]) <- s[[i]]$goodwells
  329. }
  330. # make a master_sum, that is a list of all the summaries
  331. goodwellindex <- which(is.element(s[[i]]$well, s[[i]]$goodwells))
  332. master_sum[[i]] <- sum
  333. master_sum[[i]]$file <- strsplit(basename(s[[i]]$file), ".RData")[[1]][1]
  334. master_sum[[i]]$treatment <- s[[i]]$treatment[goodwellindex]
  335. master_sum[[i]]$size <- s[[i]]$size[goodwellindex]
  336. master_sum[[i]]$dose <- s[[i]]$dose[goodwellindex]
  337. master_sum[[i]]$well <- s[[i]]$well[goodwellindex]
  338. master_sum[[i]]$nae <- s[[i]]$nae[goodwellindex]
  339. master_sum[[i]]$timepoint <-
  340. rep(s[[i]]$timepoint[1], length(s[[i]]$goodwells))
  341. master_sum[[i]]$start_rec_time <-
  342. rep(s[[i]]$rec_time[1], length(s[[i]]$goodwells))
  343. master_sum[[i]]$end_rec_time <-
  344. rep(s[[i]]$rec_time[2], length(s[[i]]$goodwells))
  345. master_sum[[i]]$goodwells <- s[[i]]$goodwells
  346. }
  347. master_sum
  348. }
  349. ##### needed additional functions
  350. .get_div <- function(s) {
  351. div <- NA
  352. if(length(s$div>0)){
  353. div<-s$div
  354. } else {
  355. t1 <- strsplit(s$file, split = "_", fixed = TRUE)
  356. for (i in t1[[1]]) {
  357. i <- toupper(i)
  358. if (nchar(i) > 2 && substr(i, 1, 3) == "DIV") {
  359. if (nchar(i) > 5) {
  360. i <- unlist(strsplit(i, split = ".", fixed = T))[1]
  361. }
  362. div <- as.numeric(substr(i, 4, nchar(i)))
  363. }
  364. }
  365. }
  366. # set default div as 1
  367. if (is.na(div)){ div <- 1}
  368. div
  369. }