-
Notifications
You must be signed in to change notification settings - Fork 0
/
findInteractions.R
164 lines (122 loc) · 5.29 KB
/
findInteractions.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
# Calculate interaction scores of receptors-ligand pairs in database betweeen adjacent spots
# Create function
calculateInteractions <- function(neighboursList,
dat,
database,
filter,
threshold) {
# Create vector containing the barcodes that are in the neighbors list and in the data (i.e. actual tissue spots)
message('Creating vector of barcodes in neighbours list and in data object.')
select <- names(neighboursList)[names(neighboursList) %in% dat@assays$Spatial@counts@Dimnames[[2]]]
# Get the scaled data in a dataframe
message('Extracting scaled data.')
scaledat <- as.data.frame(GetAssayData(object = dat, slot = "data"))
# Filter the scaled data down to all genes in the database
message('Filtering scaled data down to all genes in the database.')
# Create a vector of all the genes in the database
db_elements <- unique(as.vector(unlist(database)))
# Go through each gene and select it from scaledat, if not present insert 0s
scaledat_filt <- scaledat[0,]
for (x in 1:length(db_elements)) {
if (db_elements[x] %in% row.names(scaledat)) {
scaledat_filt[db_elements[x], ] <- scaledat[db_elements[x], ]
} else {
scaledat_filt[db_elements[x], ] <- 0
}
}
# Now calculate the interaction scores ----
message('Processing barcodes...')
# Create dummy dataframe
dummy <- data.frame()
# Iterate through each of the barcodes in the select vector created earlier
# Store the primary barcode and the neighbour barcodes in objects
# Ensure to add barcode1 to neighbors so it checks interaction within itself
# Ensure that the neighbor barcodes are in the select vector!
for (y in 1:length(select)) {
bcode1 <- select[y]
nbours <-
c(neighboursList[[bcode1]]$neighbours[neighboursList[[bcode1]]$neighbours %in% select],
bcode1)
message(paste0(
'Starting barcode ',
y,
' of ',
length(select),
'. Progress: ',
round(((y / length(select)) * 100), digits = 1),
'%'
))
# Iterate through the neighbors - store barcode
for (x in 1:length(nbours)) {
bcode2 <- nbours[x]
# Now for the pair of barcodes selected iterate through the database
# Find the minimum expression value of all the genes in the complex in barcode1
# Find the expression of all the ligands in barcode2
for (v in 1:length(database)) {
spot1_complex <- scaledat_filt[database[[v]]$Complex_Genes, bcode1]
complex_expr <- min(spot1_complex)
if (complex_expr != 0) {
spot2_ligands <- data.frame(gene = database[[v]]$Partner_Genes,
expr = scaledat_filt[database[[v]]$Partner_Genes, bcode2])
# There may be more than 1 ligand for the complex - iterate through ligands
# Store the barcodes, complex name & expression, ligand name & expression in dataframe
# Append the dataframe with the new information, return to start of loop
for (ligands in 1:nrow(spot2_ligands)) {
if (spot2_ligands$expr[ligands] != 0) {
new_entry <- data.frame(
spot1 = bcode1,
spot2 = bcode2,
spot1_complex = names(database)[v],
spot1_complex_expr = complex_expr,
spot2_ligand = spot2_ligands$gene[ligands],
spot2_ligand_expr = spot2_ligands$expr[ligands]
)
dummy <- rbind(dummy, new_entry)
} else {
next
}
}
} else {
next
}
}
}
}
# Calculate interaction score
message('Calculating interaction scores.')
dummy <-
dummy %>%
rowwise() %>%
mutate(interaction_score = mean(c_across(
c(spot1_complex_expr, spot2_ligand_expr)
))) %>%
filter(!is.infinite(interaction_score))
# Find mean and standard deviation of interaction scores
message('Calculating mean and STDEV of interaction scores.')
mean_intscore <- mean(dummy$interaction_score)
sd_intscore <- sd(dummy$interaction_score)
# If filter == TRUE - filter to rows with interactions 'x' STDEVs greater than mean
if (filter == TRUE) {
message('Filtering to interactions with scores 2 STDEVs greater than mean.')
dummy <- dummy[dummy$interaction_score > (mean_intscore+(threshold*sd_intscore)), ]
# Sort by interaction score
results <- dummy %>%
arrange(desc(interaction_score))
} else if (filter == FALSE) {
message('Not filtering interaction scores.')
# Sort by interaction score
results <- dummy %>%
arrange(desc(interaction_score))
}
# Gather and return results
message('Returning results.')
# Count occurrences of different complexes in final results
complex_counts <- results %>%
count(spot1_complex) %>%
arrange(desc(n))
# Create list of results and complex counts
interactionResults <- list(Interactions = results,
Complex_Summary = complex_counts)
# Return interactionResults
return(interactionResults)
}