-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStep2_UA_tracker_processing CSV updated.R
214 lines (176 loc) · 7.49 KB
/
Step2_UA_tracker_processing CSV updated.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
rm(list=ls())
library(svDialogs)
library(ggplot2)
library(plyr)
library(stringr)
library(xlsx)
############################################################
#######################START CODE HERE######################
############################################################
setwd(choose.dir(default = "S:/LAB-titus004/AnnikaSchroder/Analysis/no cells touching/Ax2/", caption = "Select folder"))
#make raw and normalized folders
dir.create("Output")
#set frame rate
framerate <- 15 # dlg_input("Enter frame interval (seconds): ", Sys.info()[""])$res
# manually set experiment number/ID and frame rate
concentration <- dlg_input("Enter concentration of chemoattractant loaded in middle well: ", Sys.info()[""])$res
G120
celltype <- dlg_input("Enter type of cells/genotype: ", Sys.info()[""])$res
# LOAD DATA
file <- list.files(pattern="Tracker_Results*",recursive=FALSE)
df <- read.csv(file, header=T) # open data
#######################
####assign cell IDs####
#######################
#split data to isolate first frame only, and assign cell IDs to each cell
totalframes <- max(df$Slice)
n.slice1 <- count(df$Slice==1)[2,2]
df$ID <- ""
df$distance <- ""
for (i in 1:n.slice1) { # assign cell IDs to cells in first slice
df[i,"ID"] <- paste("cell",i)
}
listcellIDs <- unique(df$ID)[1:n.slice1]
dfcells <- ""
for (k in 1:totalframes) { # totalframe is the same as slice
if (k == 1) {
prev <- subset(df, Slice == 1)
} else {
prev <- subset(dfcells, Slice == (k-1))
}
current <- subset(df, Slice == k)
# IF YOU EXPORTED CENTROID:
current$X <- as.numeric(current$X)
current$Y <- as.numeric(current$Y)
prev$X <- as.numeric(prev$X)
prev$Y <- as.numeric(prev$Y)
# IF YOU EXPORTED CENTER OF MASS
# current$XM <- as.numeric(current$XM)
# current$YM <- as.numeric(current$YM)
# prev$XM <- as.numeric(prev$XM)
# prev$YM <- as.numeric(prev$YM)
#now loop through current slice and find nearest neighbor of the previous slice to assign cell ID
for(i in 1:nrow(current)) {
#make new distance column
prev$distance <- NA
#find distance between first point and all cells from previous slice
for (j in 1:nrow(prev)) {
# IF YOU EXPORTED CENTROID:
prev[j,"distance"] <- sqrt((current[i,"X"] - prev[j,"X"])^2 + (current[i,"Y"] - prev[j,"Y"])^2)
# IF YOU EXPORTED CENTER OF MASS:
# prev[j,"distance"] <- sqrt((current[i,"XM"] - prev[j,"XM"])^2 + (current[i,"YM"] - prev[j,"YM"])^2)
}
#select smallest distance for each point
cell <- which.min(prev[,"distance"]) #finds row number for smallest value
if (prev[cell,"distance"] < 41.7) { #if nearest neighbor is less than 15um assign cell ID
#if (prev[cell,"distance"] < 15) { #if exported as um
current[i,"ID"] <- prev[cell,"ID"]
current[i,"distance"] <- prev[cell,"distance"]
} else { # if nearest neighbor is more than 5um assign new cell name
lastcell <- unlist(strsplit(tail(listcellIDs,1),split = " "))[2] #identify last cell in the list
newcell <- as.numeric(lastcell) + 1
newcellID <- paste("cell",newcell)
listcellIDs <- c(listcellIDs,newcellID)
current[i,"ID"] <- newcellID
# current[i,"ID"] <- "cell x"
}
}
dfcells <- rbind(dfcells,current)
}
rm(current,prev,i,j,k)
dfcells <- dfcells[2:nrow(dfcells),] #remove the first row which is empty
#make sure all numeric columns are numeric so we can make nice plots
dfcells$`Time (min)` <- (as.numeric(dfcells$Slice) - 1)* as.numeric(framerate) / 60 # in minutes
# dfcells$XM <- as.numeric(as.character(dfcells$XM))
# dfcells$YM <- as.numeric(as.character(dfcells$YM))
dfcells$X <- as.numeric(as.character(dfcells$X))
dfcells$Y <- as.numeric(as.character(dfcells$Y))
#plot the change in xy distance for each cell
ggplot(dfcells, aes(x=X, y=Y, color = ID)) + geom_point()
ggsave(paste0("Output/",concentration,"_",celltype,"_raw_cell_xyscatter.png"))
####verify that the number of each cell is not more than the number of frames
n_cells <- aggregate(data.frame(count = dfcells), list(value = dfcells$ID), length)
n_cells <- n_cells[c("value","count.ID")]
n_cells$FLAG <- ""
for (i in 1:nrow(n_cells)) {
if (n_cells[i,2] <= totalframes) {
n_cells[i,3] = "false"
} else {
n_cells[i,3] = "TRUE"
}
}
n_cells #check for any "true" flags
# exclude all cells that have fewer than 8 time points (2min)
keepcells <- subset(n_cells,n_cells$count.ID > 7)
list.keepcells <- unlist(keepcells[1])
dfcellstrimmed <- dfcells[dfcells$ID %in% list.keepcells,]
#############################################
######Calculate chemotaxis parameters########
#############################################
# first adjust xy to origin for spider plots
data <- ""
for (j in 1:length(list.keepcells)) { # subset data to loop thru all tracks
current <- subset(dfcellstrimmed, ID == list.keepcells[j])
X.ori <- current[1,3]
Y.ori <- current[1,4]
current$X.origin <- current$X - X.ori # calculate x and y adjusted to origin
current$Y.origin <- current$Y - Y.ori
data <- rbind(data,current) # bind all cell tracks together
}
rm(current,X.ori,Y.ori,j)
data <- data[!apply(data == "", 1, all),] # remove the first row which is empty
colkeep <- c("ID","Time (min)","X.origin","Y.origin", "Circ.")
data <- data[,colkeep]
data$X.origin <- as.numeric(as.character(data$X.origin))
data$Y.origin <- as.numeric(as.character(data$Y.origin))
#plot the change in xy distance for each cell
ggplot(data, aes(x=X.origin, y=Y.origin, color = ID)) + geom_point()
ggsave(paste0("Output/",concentration,"_",celltype,"_trimmed_cell_xyscatter.png"))
# add columns for other metrics we want
data$`[cAMP] (nM)` <- concentration
data$Cells <- celltype
data$`Net Displacement (um)` <- ""
data$`Speed (um/min)` <- ""
data$Directionality <- ""
data$`Chemotactic Index` <- ""
data$`MSD (um^2)` <- ""
data2 <- ""
# calculate distance and speed per cell by subsetting and binding
for (cell in list.keepcells) {
temp <- subset(data, ID == cell)
# set first time point as zeroes
temp[1,8:12] <- 0
temp[,2:4] <- as.numeric(unlist(temp[,2:4]))
# reset timer to 0 for all cells
temp[1,2] <- 0
for (i in 2:nrow(temp)) {
temp[i,2] <- temp[i-1,2] + 0.25
rm(i)
}
# now loop through all other time points + calculate
for (i in 2:nrow(temp)) {
# distance
# current x prev x current y prev y
temp[i,8] <- sqrt((temp[i,3] - temp[i-1,3])^2 + (temp[i,4] - temp[i-1,4])^2)
# speed
# net displacement change in time from prev step
temp[i,9] <- as.numeric(temp[i,8]) / (temp[i,2] - temp[i-1,2])
}
for (i in 2:nrow(temp)) {
# directionality
totaldistance <- sum(as.numeric(temp[2:i,8]))
# final euclidean distance traveled / sum of path length
temp[i,10] <- sqrt(temp[i,3]^2 + temp[i,4]^2) / totaldistance
# chemotactic index
#net movement in x / euclidean distance
#sqrt(temp[i,3]^2 + temp[i,4]^2)
temp[i,11] <- temp[i,3] / sqrt(temp[i,3]^2 + temp[i,4]^2)
# instantenous mean square displacement
temp[i,12] <- totaldistance / sqrt(i-1)
}
data2 <- rbind(data2,temp) # bind all cell tracks together
}
rm(temp,cell,i)
data2 <- data2[2:nrow(data2),] #remove the first row which is empty
#save final data frame
write.csv(data2,paste0("./Output/",concentration,"_",celltype,"_processing_results.csv"))