-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmetadataMapperJson.js
More file actions
253 lines (193 loc) · 6.71 KB
/
metadataMapperJson.js
File metadata and controls
253 lines (193 loc) · 6.71 KB
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
const convert = require('sbgnml-to-cytoscape');
const metadataParser = require('./metadataParserJson');
//Map metadata from BioPax to nodes
//Returns a cy cytoscape json
//Requires valid BioPax and sbgn files
module.exports = function (biopax, sbgn) {
//Convert sbgn to json
let cyGraph = convert(sbgn);
//Get mapped node list
let nodes = cyGraph.nodes;
cyGraph.nodes = processBioPax(biopax, nodes);
//Return Enhanced JSON
return cyGraph;
}
//Build a sub tree array for a biopax element
function buildBioPaxSubtree(biopaxElement, biopaxFile, visited, nodeType = 'default') {
let result = [];
if (nodeType !== 'Reference') {
//Get type
let type = biopaxElement['@type']
if (type) { result.push(['Type', type]); }
//Get data source
let dataSource = biopaxElement['dataSource'];
if (dataSource) { result.push(['Data Source', dataSource]); }
//Get display name
let dName = biopaxElement['displayName'];
if (dName) { result.push(['Display Name', dName]); }
//Get Comments
let comment = biopaxElement['comment'];
if (comment) { result.push(['Comment', comment]); }
//Get Names
let name = biopaxElement['name'];
if (name) { result.push(['Names', name]); }
//Get Standard Name
let sName = biopaxElement['standardName'];
if (sName) { result.push(['Standard Name', sName]); }
//Get Chemical Formula
let formula = biopaxElement['chemicalFormula'];
if (formula) { result.push(['Chemical Formula', formula]); }
//Get Cellular Location
let cellLocation = biopaxElement['cellularLocation'];
if (cellLocation && cellLocation.indexOf('http') !== -1) {
cellLocation = getElementFromBioPax(biopaxFile, cellLocation);
cellLocation = cellLocation['term'];
}
if (cellLocation) { result.push(['Cellular Location', cellLocation]); }
}
//Get database id
let db = biopaxElement['db'];
let id = biopaxElement['id'];
if (db && id) { result.push(['Database ID', [db, id]]); }
//Get any cross references
let xref = biopaxElement['xref'];
//Resolve String/Array Issue
if (typeof xref == 'string') { xref = [xref]; }
if (!(xref)) { xref = []; }
//Get entity reference and add it to xref
let eref = biopaxElement['entityReference']
if (eref) xref.push(eref);
//Recurse on each cross reference (Lim it level depth to 4)
if (xref) {
for (let i = 0; i < xref.length; i++) {
let keyName = 'Reference';
if (i == (xref.length - 1) && eref) { keyName = 'EntityReference' };
//Get Referenced Element
let refElement = getElementFromBioPax(biopaxFile, xref[i]);
//Make a copy of visited
let visitCopy = visited.slice();
//Check validity of element
if (!(refElement)) { continue; }
//Recurse on current element
if (visitCopy.indexOf(xref[i]) <= -1 && visitCopy.length <= 2) {
visitCopy.push(xref[i]);
result.push([keyName, buildBioPaxSubtree(refElement, biopaxFile, visitCopy, keyName)]);
}
}
}
//Return subtree
return result;
}
//Build a tree array for a biopax file
function buildBioPaxTree(children, biopaxFile) {
let result = [];
if (!(children)) { return };
//Get the node id
let id = children['pathid']
if (!(id)) { id = children['about']; }
if (!(id)) { return; }
//Build a subtree
let visited = [id];
let subtree = buildBioPaxSubtree(children, biopaxFile, visited);
result.push([id, subtree]);
//Return Biopax Tree
return result;
}
//Remove all characters after nth instance of underscore
//Requires the string to contain at least 1 underscore
function removeAfterUnderscore(word, numberOfElements) {
let splitWord = word.split('_');
let newWord = '';
for (let i = 0; i < numberOfElements; i++) {
if (i != (numberOfElements - 1)) {
newWord += splitWord[i] + '_';
} else {
newWord += splitWord[i];
}
}
return newWord;
}
//Check if ID even exists in the biopax file
//Returns teh matching element or null
function getElementFromBioPax(biopaxFile, id) {
//Append pc2 address, if id is not already an uri
if (id.indexOf('http') !== -1) {
var lastIndex = id.lastIndexOf('/');
id = id.substring(lastIndex + 1);
}
//Get element matching the id
let result = biopaxFile.get(id);
return result;
}
//Get subtree for each node
//Requires tree to be a valid biopax tree
function getBioPaxSubtree(nodeId, biopax) {
//Remove extra identifiers appended by cytoscape.js
let fixedNodeId = removeAfterUnderscore(nodeId, 2);
//Resolve issues if there is no appended identifiers
if (nodeId.indexOf('_') <= -1) {
fixedNodeId = nodeId;
}
//Conduct a basic search
let basicSearch = getElementFromBioPax(biopax, fixedNodeId);
if (basicSearch) { return buildBioPaxTree(basicSearch, biopax); }
//Check if id is an unification reference
fixedNodeId = 'UnificationXref_' + nodeId;
//Conduct a unification ref search
let uniSearch = getElementFromBioPax(biopax, fixedNodeId);
if (uniSearch) { return buildBioPaxTree(uniSearch, biopax); }
//Check if id is an external identifier
fixedNodeId = removeAfterUnderscore(nodeId, 2);
fixedNodeId = 'http://identifiers.org/' + fixedNodeId.replace(/_/g, '/');
//Conduct a external identifier search
let extSearch = getElementFromBioPax(biopax, fixedNodeId);
if (extSearch) { return buildBioPaxTree(extSearch, biopax); }
return null;
}
//Replace all instances of a substring with a given string
//Returns a string
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
//Preprocess biopax file and create a map
//Returns a map of the biopax file
function preProcessBioPax(biopaxFile){
let bioMap = new Map();
//Loop through all biopax entires and add them to the map
for(let i = 0; i < biopaxFile.length; i++){
//Get the biopax id
let biopaxElement = biopaxFile[i];
let id = biopaxElement['pathid'];
var lastIndex = id.lastIndexOf('/');
id = id.substring(lastIndex + 1);
//Add a new map entry
bioMap.set(id, biopaxElement);
}
return bioMap;
}
//Process biopax file
function processBioPax(data, nodes) {
data = replaceAll(data, "@id", 'pathid');
//fs.writeFileSync('test', data);
data = JSON.parse(data);
//Get Graph Elements
let graph = data['@graph'];
//Create a biopax map
graph = preProcessBioPax(graph);
//Loop through all nodes
for (let i = 0; i < nodes.length; i++) {
//Get element values
let id = nodes[i].data.id;
//Get metadata for current node
let metadata = getBioPaxSubtree(id, graph);
//Parse metadata
try {
//Add data to nodes
let parsedMetadata = metadataParser(metadata);
nodes[i].data.parsedMetadata = parsedMetadata;
}
catch (e) { console.log(e); throw e; }
}
//Return nodes
return nodes;
}