@teselagen/bio-parsers 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +330 -0
- package/fastaToJson.d.ts +1 -1
- package/index.js +133 -116
- package/index.mjs +133 -116
- package/index.umd.js +132 -115
- package/package.json +1 -2
- package/src/ab1ToJson.js +13 -18
- package/src/anyToJson.js +7 -7
- package/src/fastaToJson.js +12 -7
- package/src/genbankToJson.js +21 -20
- package/src/geneiousXmlToJson.js +3 -6
- package/src/gffToJson.js +5 -5
- package/src/jbeiXmlToJson.js +10 -13
- package/src/jsonToBed.js +4 -3
- package/src/jsonToFasta.js +4 -2
- package/src/jsonToGenbank.js +13 -12
- package/src/jsonToJsonString.js +1 -1
- package/src/sbolXmlToJson.js +9 -9
- package/src/snapgeneToJson.js +14 -12
- package/src/utils/NameUtils.js +1 -1
- package/src/utils/ParserUtil.js +81 -83
- package/src/utils/cleanUpTeselagenJsonForExport.js +8 -9
- package/src/utils/constants.js +22 -22
- package/src/utils/convertOldSequenceDataToNewDataType.js +5 -6
- package/src/utils/createInitialSequence.js +13 -11
- package/src/utils/extractFileExtension.js +11 -13
- package/src/utils/flattenSequenceArray.js +14 -14
- package/src/utils/getArrayBufferFromFile.js +5 -5
- package/src/utils/isBrowser.js +2 -1
- package/src/utils/parseUracilFeatures.js +2 -2
- package/src/utils/pragmasAndTypes.js +3 -2
- package/src/utils/searchWholeObjByName.js +3 -3
- package/src/utils/splitStringIntoLines.js +13 -12
- package/src/utils/validateSequence.js +15 -10
- package/src/utils/validateSequenceArray.js +17 -17
- package/utils/getArrayBufferFromFile.d.ts +1 -1
package/src/ab1ToJson.js
CHANGED
|
@@ -10,7 +10,7 @@ async function ab1ToJson(fileObj, options = {}) {
|
|
|
10
10
|
returnVal.parsedSequence = {
|
|
11
11
|
...returnVal.parsedSequence,
|
|
12
12
|
sequence: chromatogramData.baseCalls.join(""),
|
|
13
|
-
chromatogramData
|
|
13
|
+
chromatogramData
|
|
14
14
|
};
|
|
15
15
|
return [returnVal];
|
|
16
16
|
}
|
|
@@ -22,7 +22,6 @@ function abConverter(inputArrayBuffer) {
|
|
|
22
22
|
const numElements = inputArrayBuffer.getInt32(18);
|
|
23
23
|
const lastEntry = dirLocation + numElements * 28;
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
this.getNumber = (inOffset, numEntries) => {
|
|
27
26
|
const retArray = [];
|
|
28
27
|
for (let counter = 0; counter < numEntries; counter += 1) {
|
|
@@ -49,8 +48,7 @@ function abConverter(inputArrayBuffer) {
|
|
|
49
48
|
return retArray;
|
|
50
49
|
};
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
this.getTagName = (inOffset) => {
|
|
51
|
+
this.getTagName = inOffset => {
|
|
54
52
|
let name = "";
|
|
55
53
|
for (let loopOffset = inOffset; loopOffset < inOffset + 4; loopOffset++) {
|
|
56
54
|
name += String.fromCharCode(inputArrayBuffer.getInt8(loopOffset));
|
|
@@ -58,7 +56,7 @@ function abConverter(inputArrayBuffer) {
|
|
|
58
56
|
return name;
|
|
59
57
|
};
|
|
60
58
|
|
|
61
|
-
this.getDataTag = function(inTag) {
|
|
59
|
+
this.getDataTag = function (inTag) {
|
|
62
60
|
let output;
|
|
63
61
|
let curElem = dirLocation;
|
|
64
62
|
do {
|
|
@@ -75,7 +73,7 @@ function abConverter(inputArrayBuffer) {
|
|
|
75
73
|
return output;
|
|
76
74
|
};
|
|
77
75
|
|
|
78
|
-
this.getTraceData = function() {
|
|
76
|
+
this.getTraceData = function () {
|
|
79
77
|
const traceData = {};
|
|
80
78
|
traceData.aTrace = this.getDataTag(tagDict.colorDataA);
|
|
81
79
|
traceData.tTrace = this.getDataTag(tagDict.colorDataT);
|
|
@@ -84,10 +82,10 @@ function abConverter(inputArrayBuffer) {
|
|
|
84
82
|
traceData.basePos = this.getDataTag(tagDict.peakLocations);
|
|
85
83
|
traceData.baseCalls = this.getDataTag(tagDict.baseCalls2);
|
|
86
84
|
traceData.qualNums = this.getDataTag(tagDict.qualNums);
|
|
87
|
-
if (traceData.qualNums
|
|
85
|
+
if (traceData.qualNums) {
|
|
88
86
|
//tnr if we're only getting 1's and 0's as qualNums, that means that there weren't actual qual nums attached to the file
|
|
89
|
-
if (!traceData.qualNums.filter(q =>
|
|
90
|
-
delete traceData.qualNums
|
|
87
|
+
if (!traceData.qualNums.filter(q => q !== 1 && q !== 0).length) {
|
|
88
|
+
delete traceData.qualNums;
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
91
|
return convertBasePosTraceToPerBpTrace(traceData);
|
|
@@ -116,11 +114,10 @@ const tagDict = {
|
|
|
116
114
|
colorDataA: { tagName: "DATA", tagNum: 10, typeToReturn: "getShort" },
|
|
117
115
|
colorDataT: { tagName: "DATA", tagNum: 11, typeToReturn: "getShort" },
|
|
118
116
|
colorDataG: { tagName: "DATA", tagNum: 9, typeToReturn: "getShort" },
|
|
119
|
-
colorDataC: { tagName: "DATA", tagNum: 12, typeToReturn: "getShort" }
|
|
117
|
+
colorDataC: { tagName: "DATA", tagNum: 12, typeToReturn: "getShort" }
|
|
120
118
|
};
|
|
121
119
|
|
|
122
|
-
|
|
123
|
-
const correctionAmount = 3
|
|
120
|
+
const correctionAmount = 3;
|
|
124
121
|
// tnr: this function takes in chromData which has 4 traces and a basePos (which describes where in the trace the base call lands)
|
|
125
122
|
// It "normalizes" that data into a baseTraces array so that each base has its own set of that data (having a per-base trace makes insertion/deletion/copy/paste actions all easier)
|
|
126
123
|
function convertBasePosTraceToPerBpTrace(chromData) {
|
|
@@ -152,15 +149,15 @@ function convertBasePosTraceToPerBpTrace(chromData) {
|
|
|
152
149
|
"gTrace",
|
|
153
150
|
"cTrace"
|
|
154
151
|
// eslint-disable-next-line no-loop-func
|
|
155
|
-
].forEach(
|
|
152
|
+
].forEach(type => {
|
|
156
153
|
const traceForType = tracesForType[type];
|
|
157
154
|
const traceData = chromData[type];
|
|
158
155
|
for (let j = startPos; j < endPos + correctionAmount; j++) {
|
|
159
156
|
traceForType.push(traceData[j] || 0);
|
|
160
157
|
}
|
|
161
158
|
});
|
|
162
|
-
if (i !== basePos.length-1) {
|
|
163
|
-
startPos = endPos+correctionAmount;
|
|
159
|
+
if (i !== basePos.length - 1) {
|
|
160
|
+
startPos = endPos + correctionAmount;
|
|
164
161
|
nextBasePos = basePos[i + 2];
|
|
165
162
|
setEndPos();
|
|
166
163
|
}
|
|
@@ -172,6 +169,4 @@ function convertBasePosTraceToPerBpTrace(chromData) {
|
|
|
172
169
|
};
|
|
173
170
|
}
|
|
174
171
|
|
|
175
|
-
export {
|
|
176
|
-
convertBasePosTraceToPerBpTrace
|
|
177
|
-
}
|
|
172
|
+
export { convertBasePosTraceToPerBpTrace };
|
package/src/anyToJson.js
CHANGED
|
@@ -71,7 +71,7 @@ async function anyToJson(fileContentStringOrFileObj, options) {
|
|
|
71
71
|
}
|
|
72
72
|
// console.log(`fileContentString.includes("seq:seq"):`,fileContentString.includes("seq:seq"))
|
|
73
73
|
// console.log(`fileContentString.includes("jbei")):`,fileContentString.includes("jbei"))
|
|
74
|
-
if (/^(fasta|fas|fa|fna|ffn)$/.test(ext)) {
|
|
74
|
+
if (/^(fasta|fas|fa|fna|ffn|faa)$/.test(ext)) {
|
|
75
75
|
// FASTA
|
|
76
76
|
return fastaToJson(fileContentString, options);
|
|
77
77
|
} else if (/^(gb|gbk)$/.test(ext)) {
|
|
@@ -132,12 +132,12 @@ async function anyToJson(fileContentStringOrFileObj, options) {
|
|
|
132
132
|
|
|
133
133
|
//try to guess the file type based on the first non-whitespace char in the filestring
|
|
134
134
|
if (firstChar === ">") {
|
|
135
|
-
parsersToTry = parsersToTry.sort(
|
|
135
|
+
parsersToTry = parsersToTry.sort(a => {
|
|
136
136
|
if (a.name === "Fasta Parser") return -1;
|
|
137
137
|
return 1;
|
|
138
138
|
});
|
|
139
139
|
} else if (firstChar === "L") {
|
|
140
|
-
parsersToTry = parsersToTry.sort(
|
|
140
|
+
parsersToTry = parsersToTry.sort(a => {
|
|
141
141
|
if (a.name === "Genbank Parser") return -1;
|
|
142
142
|
return 1;
|
|
143
143
|
});
|
|
@@ -188,10 +188,10 @@ function getUtf8StringFromFile(file, { emulateBrowser } = {}) {
|
|
|
188
188
|
const reader = new window.FileReader();
|
|
189
189
|
reader.readAsText(file, "UTF-8");
|
|
190
190
|
return new Promise((resolve, reject) => {
|
|
191
|
-
reader.onload =
|
|
191
|
+
reader.onload = evt => {
|
|
192
192
|
resolve(evt.target.result);
|
|
193
193
|
};
|
|
194
|
-
reader.onerror =
|
|
194
|
+
reader.onerror = err => {
|
|
195
195
|
console.error("err:", err);
|
|
196
196
|
reject(err);
|
|
197
197
|
};
|
|
@@ -212,12 +212,12 @@ function getUint8ArrayFromFile(file, { emulateBrowser } = {}) {
|
|
|
212
212
|
reader.readAsArrayBuffer(file);
|
|
213
213
|
|
|
214
214
|
return new Promise((resolve, reject) => {
|
|
215
|
-
reader.onload =
|
|
215
|
+
reader.onload = evt => {
|
|
216
216
|
const arrayBuffer = evt.target.result;
|
|
217
217
|
const bytes = new Uint8Array(arrayBuffer);
|
|
218
218
|
resolve(bytes);
|
|
219
219
|
};
|
|
220
|
-
reader.onerror =
|
|
220
|
+
reader.onerror = err => {
|
|
221
221
|
console.error("err:", err);
|
|
222
222
|
reject(err);
|
|
223
223
|
};
|
package/src/fastaToJson.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import createInitialSequence from "./utils/createInitialSequence";
|
|
2
|
+
import extractFileExtension from "./utils/extractFileExtension";
|
|
2
3
|
import splitStringIntoLines from "./utils/splitStringIntoLines.js";
|
|
3
4
|
import validateSequenceArray from "./utils/validateSequenceArray";
|
|
4
5
|
|
|
@@ -9,7 +10,12 @@ import validateSequenceArray from "./utils/validateSequenceArray";
|
|
|
9
10
|
* @author Joshua P Nixon
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
function fastaToJson(fileString, options) {
|
|
13
|
+
function fastaToJson(fileString, options = {}) {
|
|
14
|
+
const ext = extractFileExtension(options.fileName);
|
|
15
|
+
if (/^(faa)$/.test(ext)) {
|
|
16
|
+
options.isProtein = true;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
let resultArray = [];
|
|
14
20
|
let result = null;
|
|
15
21
|
try {
|
|
@@ -28,8 +34,8 @@ function fastaToJson(fileString, options) {
|
|
|
28
34
|
resultArray = [
|
|
29
35
|
{
|
|
30
36
|
success: false,
|
|
31
|
-
messages: ["Import Error: Invalid File"]
|
|
32
|
-
}
|
|
37
|
+
messages: ["Import Error: Invalid File"]
|
|
38
|
+
}
|
|
33
39
|
];
|
|
34
40
|
}
|
|
35
41
|
return validateSequenceArray(resultArray, options);
|
|
@@ -71,10 +77,9 @@ function fastaToJson(fileString, options) {
|
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
function parseTitle(line) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return
|
|
80
|
+
if (options && "parseName" in options && !options.parseName) {
|
|
81
|
+
result.parsedSequence.name = line.slice(1);
|
|
82
|
+
return;
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
const pipeIndex = line.indexOf("|");
|
package/src/genbankToJson.js
CHANGED
|
@@ -66,18 +66,20 @@ function genbankToJson(string, options = {}) {
|
|
|
66
66
|
const isKey = isKeyword(line);
|
|
67
67
|
|
|
68
68
|
//only set a new LINETYPE in the case that we've encountered a key that warrants it.
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
if (!isKeyRunon) {
|
|
70
|
+
if (key === "LOCUS") {
|
|
71
|
+
LINETYPE = key;
|
|
72
|
+
} else if (key === "REFERENCE") {
|
|
73
|
+
LINETYPE = key;
|
|
74
|
+
} else if (key === "FEATURES") {
|
|
75
|
+
LINETYPE = key;
|
|
76
|
+
} else if (key === "ORIGIN") {
|
|
77
|
+
LINETYPE = key;
|
|
78
|
+
} else if (key === "//") {
|
|
79
|
+
LINETYPE = key;
|
|
80
|
+
} else if (isKey === true) {
|
|
81
|
+
LINETYPE = key;
|
|
82
|
+
}
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
// IGNORE LINES: DO NOT EVEN PROCESS
|
|
@@ -237,10 +239,10 @@ function genbankToJson(string, options = {}) {
|
|
|
237
239
|
// default sequence json has primers at the top level separate from features, e.g. parsedSequence: { primers: [ {}, {} ], features: [ {}, {} ] }
|
|
238
240
|
// if options.primersAsFeatures is set to true, primers are included in features with type set to primer
|
|
239
241
|
|
|
240
|
-
results.forEach(
|
|
242
|
+
results.forEach(result => {
|
|
241
243
|
if (result.success) {
|
|
242
244
|
const sequence = result.parsedSequence;
|
|
243
|
-
sequence.features.forEach(
|
|
245
|
+
sequence.features.forEach(feat => {
|
|
244
246
|
if (feat.type === "primer") {
|
|
245
247
|
feat.type = "primer_bind";
|
|
246
248
|
}
|
|
@@ -248,10 +250,10 @@ function genbankToJson(string, options = {}) {
|
|
|
248
250
|
|
|
249
251
|
if (!options.primersAsFeatures) {
|
|
250
252
|
sequence.primers = sequence.features.filter(
|
|
251
|
-
|
|
253
|
+
feat => feat.type === "primer_bind"
|
|
252
254
|
);
|
|
253
255
|
sequence.features = sequence.features.filter(
|
|
254
|
-
|
|
256
|
+
feat => feat.type !== "primer_bind"
|
|
255
257
|
);
|
|
256
258
|
}
|
|
257
259
|
}
|
|
@@ -298,7 +300,6 @@ function genbankToJson(string, options = {}) {
|
|
|
298
300
|
|
|
299
301
|
function parseLocus(line) {
|
|
300
302
|
result = createInitialSequence(options);
|
|
301
|
-
let locusName;
|
|
302
303
|
let circular;
|
|
303
304
|
|
|
304
305
|
let gbDivision;
|
|
@@ -312,7 +313,7 @@ function genbankToJson(string, options = {}) {
|
|
|
312
313
|
// TODO
|
|
313
314
|
addMessage("Import Warning: Locus line contains no values: " + line);
|
|
314
315
|
}
|
|
315
|
-
locusName = lineArr[1];
|
|
316
|
+
const locusName = lineArr[1];
|
|
316
317
|
|
|
317
318
|
// Linear vs Circular?
|
|
318
319
|
for (let i = 1; i < lineArr.length; i++) {
|
|
@@ -525,13 +526,13 @@ function genbankToJson(string, options = {}) {
|
|
|
525
526
|
}
|
|
526
527
|
|
|
527
528
|
function parseFeatureNote(line) {
|
|
528
|
-
let newLine
|
|
529
|
+
let newLine;
|
|
529
530
|
|
|
530
531
|
// only trim file formatting spaces (i.e. the left ones)
|
|
531
532
|
// spaces on the right are necessary (e.g. spacing between words, etc.)
|
|
532
533
|
newLine = line.trimLeft();
|
|
533
534
|
newLine = newLine.replace(/^\/|"$/g, "");
|
|
534
|
-
lineArr = newLine.split(/="|=/);
|
|
535
|
+
const lineArr = newLine.split(/="|=/);
|
|
535
536
|
|
|
536
537
|
let val = lineArr.slice(1).join("=");
|
|
537
538
|
|
package/src/geneiousXmlToJson.js
CHANGED
|
@@ -40,7 +40,7 @@ async function geneiousXmlToJson(string, options) {
|
|
|
40
40
|
messages: ["Error: XML is not valid geneious format"]
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
forEach(geneiousJsonMatches,
|
|
43
|
+
forEach(geneiousJsonMatches, geneiousJson => {
|
|
44
44
|
const response = {
|
|
45
45
|
parsedSequence: null,
|
|
46
46
|
messages: [],
|
|
@@ -58,10 +58,7 @@ async function geneiousXmlToJson(string, options) {
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
|
-
const toRet = filter(
|
|
62
|
-
resultArray,
|
|
63
|
-
(r) => r?.parsedSequence?.sequence?.length
|
|
64
|
-
);
|
|
61
|
+
const toRet = filter(resultArray, r => r?.parsedSequence?.sequence?.length);
|
|
65
62
|
if (toRet.length) return toRet;
|
|
66
63
|
return onFileParsed(resultArray);
|
|
67
64
|
} catch (e) {
|
|
@@ -105,7 +102,7 @@ function parseGeneiousJson(geneiousJson) {
|
|
|
105
102
|
searchWholeObjByNameSimple("maximumIndex", lastInterval) - 1;
|
|
106
103
|
let locations;
|
|
107
104
|
if (intervals.length > 1) {
|
|
108
|
-
locations = intervals.map(
|
|
105
|
+
locations = intervals.map(i => {
|
|
109
106
|
const start = searchWholeObjByNameSimple("minimumIndex", i) - 1;
|
|
110
107
|
const end = searchWholeObjByNameSimple("maximumIndex", i) - 1;
|
|
111
108
|
return {
|
package/src/gffToJson.js
CHANGED
|
@@ -6,7 +6,7 @@ function gffToJson(string) {
|
|
|
6
6
|
const results = [];
|
|
7
7
|
const sequences = [];
|
|
8
8
|
const features = {};
|
|
9
|
-
arrayOfThings.forEach(
|
|
9
|
+
arrayOfThings.forEach(featureOrSeq => {
|
|
10
10
|
if (featureOrSeq.sequence) {
|
|
11
11
|
sequences.push(featureOrSeq);
|
|
12
12
|
} else {
|
|
@@ -19,11 +19,11 @@ function gffToJson(string) {
|
|
|
19
19
|
start: feature.start,
|
|
20
20
|
end: feature.end,
|
|
21
21
|
strand: feature.strand === "+" ? 1 : -1,
|
|
22
|
-
type: feature.type
|
|
22
|
+
type: feature.type
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
|
-
sequences.forEach(
|
|
26
|
+
sequences.forEach(sequence => {
|
|
27
27
|
const sequenceId = sequence.id;
|
|
28
28
|
const result = {
|
|
29
29
|
messages: [],
|
|
@@ -32,8 +32,8 @@ function gffToJson(string) {
|
|
|
32
32
|
name: sequenceId,
|
|
33
33
|
sequence: sequence.sequence,
|
|
34
34
|
circular: false,
|
|
35
|
-
features: features[sequence.id]
|
|
36
|
-
}
|
|
35
|
+
features: features[sequence.id]
|
|
36
|
+
}
|
|
37
37
|
};
|
|
38
38
|
results.push(result);
|
|
39
39
|
});
|
package/src/jbeiXmlToJson.js
CHANGED
|
@@ -25,14 +25,14 @@ async function jbeiXmlToJson(string, options) {
|
|
|
25
25
|
if (!jbeiSeq) {
|
|
26
26
|
return onFileParsed({
|
|
27
27
|
success: false,
|
|
28
|
-
messages: ["Error: XML is not valid jbei format"]
|
|
28
|
+
messages: ["Error: XML is not valid jbei format"]
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const response = {
|
|
33
33
|
parsedSequence: null,
|
|
34
34
|
messages: [],
|
|
35
|
-
success: true
|
|
35
|
+
success: true
|
|
36
36
|
};
|
|
37
37
|
try {
|
|
38
38
|
response.parsedSequence = parseJbeiXml(jbeiSeq, options);
|
|
@@ -42,21 +42,18 @@ async function jbeiXmlToJson(string, options) {
|
|
|
42
42
|
console.error("error.stack: ", e.stack);
|
|
43
43
|
resultArray.push({
|
|
44
44
|
success: false,
|
|
45
|
-
messages: ["Error while parsing JBEI format"]
|
|
45
|
+
messages: ["Error while parsing JBEI format"]
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const toRet = filter(
|
|
50
|
-
resultArray,
|
|
51
|
-
(r) => r?.parsedSequence?.sequence?.length
|
|
52
|
-
);
|
|
49
|
+
const toRet = filter(resultArray, r => r?.parsedSequence?.sequence?.length);
|
|
53
50
|
if (toRet.length) return toRet;
|
|
54
51
|
return onFileParsed(resultArray);
|
|
55
52
|
} catch (e) {
|
|
56
53
|
console.error(`e:`, e);
|
|
57
54
|
return onFileParsed({
|
|
58
55
|
success: false,
|
|
59
|
-
messages: ["Error parsing jbei to JSON"]
|
|
56
|
+
messages: ["Error parsing jbei to JSON"]
|
|
60
57
|
});
|
|
61
58
|
}
|
|
62
59
|
}
|
|
@@ -65,7 +62,7 @@ function parseJbeiXml(jbeiJson) {
|
|
|
65
62
|
"seq:sequence": sequence,
|
|
66
63
|
"seq:name": name,
|
|
67
64
|
"seq:circular": circular,
|
|
68
|
-
"seq:features": { "seq:feature": features }
|
|
65
|
+
"seq:features": { "seq:feature": features }
|
|
69
66
|
} = jbeiJson;
|
|
70
67
|
return {
|
|
71
68
|
sequence,
|
|
@@ -76,7 +73,7 @@ function parseJbeiXml(jbeiJson) {
|
|
|
76
73
|
"seq:complement": complement,
|
|
77
74
|
"seq:label": label,
|
|
78
75
|
"seq:type": type,
|
|
79
|
-
"seq:location": jbeiLocations
|
|
76
|
+
"seq:location": jbeiLocations
|
|
80
77
|
}) => {
|
|
81
78
|
let start, end;
|
|
82
79
|
const locs = Array.isArray(jbeiLocations)
|
|
@@ -88,7 +85,7 @@ function parseJbeiXml(jbeiJson) {
|
|
|
88
85
|
if (i === locs.length - 1) end = normEnd - 1;
|
|
89
86
|
return {
|
|
90
87
|
start: gbStart - 1,
|
|
91
|
-
end: normEnd - 1
|
|
88
|
+
end: normEnd - 1
|
|
92
89
|
};
|
|
93
90
|
}
|
|
94
91
|
);
|
|
@@ -99,10 +96,10 @@ function parseJbeiXml(jbeiJson) {
|
|
|
99
96
|
locations: locations.length > 1 ? locations : undefined,
|
|
100
97
|
name: label,
|
|
101
98
|
type,
|
|
102
|
-
strand: complement ? -1 : 1
|
|
99
|
+
strand: complement ? -1 : 1
|
|
103
100
|
};
|
|
104
101
|
}
|
|
105
|
-
)
|
|
102
|
+
)
|
|
106
103
|
};
|
|
107
104
|
}
|
|
108
105
|
|
package/src/jsonToBed.js
CHANGED
|
@@ -15,7 +15,7 @@ function jsonToBed(jsonSequence, options = {}) {
|
|
|
15
15
|
let outString = "";
|
|
16
16
|
outString += `track name="${sequenceNameToUse}" description="${name} Annotations" itemRgb="On"\n`;
|
|
17
17
|
|
|
18
|
-
features.forEach(function(feat) {
|
|
18
|
+
features.forEach(function (feat) {
|
|
19
19
|
const { start, end, name, type, forward, strand } = feat;
|
|
20
20
|
const label = name ? name : type;
|
|
21
21
|
let orientation;
|
|
@@ -30,8 +30,9 @@ function jsonToBed(jsonSequence, options = {}) {
|
|
|
30
30
|
const color = type === "CDS" ? "230,88,0" : "";
|
|
31
31
|
// chromStart is 0-based, chromEnd of the BED file format is not included in the feature
|
|
32
32
|
// when there is no thick part, thickStart and thickEnd are usually set to the chromStart position
|
|
33
|
-
outString += `${sequenceNameToUse}\t${start}\t${
|
|
34
|
-
1
|
|
33
|
+
outString += `${sequenceNameToUse}\t${start}\t${
|
|
34
|
+
end + 1
|
|
35
|
+
}\t${label}\t\t${orientation}\t\t\t${color}\n`;
|
|
35
36
|
});
|
|
36
37
|
return outString;
|
|
37
38
|
}
|
package/src/jsonToFasta.js
CHANGED
|
@@ -11,7 +11,7 @@ export default function jsonToFasta(jsonSequence, options) {
|
|
|
11
11
|
sequence,
|
|
12
12
|
isProtein,
|
|
13
13
|
proteinSize,
|
|
14
|
-
proteinSequence
|
|
14
|
+
proteinSequence
|
|
15
15
|
} = cleanedData;
|
|
16
16
|
|
|
17
17
|
options = options || {};
|
|
@@ -25,7 +25,9 @@ export default function jsonToFasta(jsonSequence, options) {
|
|
|
25
25
|
let fastaString = "";
|
|
26
26
|
fastaString += `>${name || "Untitled Sequence"}|`;
|
|
27
27
|
fastaString += "|" + sizeToUse;
|
|
28
|
-
fastaString += description
|
|
28
|
+
fastaString += description
|
|
29
|
+
? "|" + mangleOrStripUrls(description, options)
|
|
30
|
+
: "";
|
|
29
31
|
fastaString += "|" + (circular ? "circular" : "linear");
|
|
30
32
|
fastaString += "\n";
|
|
31
33
|
fastaString += (seqToUse.match(/.{1,80}/g) || []).join("\n");
|
package/src/jsonToGenbank.js
CHANGED
|
@@ -49,7 +49,7 @@ const StringUtil = {
|
|
|
49
49
|
let str = line;
|
|
50
50
|
while (str.length < length) str = str + padString;
|
|
51
51
|
return str;
|
|
52
|
-
}
|
|
52
|
+
}
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
const DIGEST_PART_EXPORT_FIELD_MAP = {
|
|
@@ -64,7 +64,7 @@ const DIGEST_PART_EXPORT_FIELD_MAP = {
|
|
|
64
64
|
"re3Prime.recognitionRegex": "re3PrimePattern",
|
|
65
65
|
re3PrimeOverhang: "re3PrimeOverhang",
|
|
66
66
|
re3PrimeOverhangStrand: "re3PrimeOverhangStrand",
|
|
67
|
-
re3PrimeRecognitionTypeCode: "re3PrimeRecognitionTypeCode"
|
|
67
|
+
re3PrimeRecognitionTypeCode: "re3PrimeRecognitionTypeCode"
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
function cutUpArray(val, start, end) {
|
|
@@ -129,7 +129,7 @@ export default function (_serSeq, options) {
|
|
|
129
129
|
|
|
130
130
|
serSeq.features = map(serSeq.features).concat(
|
|
131
131
|
flatMap(pragmasAndTypes, ({ pragma, type }) => {
|
|
132
|
-
return flatMap(serSeq[type],
|
|
132
|
+
return flatMap(serSeq[type], ann => {
|
|
133
133
|
if (!isObject(ann)) {
|
|
134
134
|
return [];
|
|
135
135
|
}
|
|
@@ -142,7 +142,7 @@ export default function (_serSeq, options) {
|
|
|
142
142
|
ann.notes = pragma
|
|
143
143
|
? {
|
|
144
144
|
...ann.notes,
|
|
145
|
-
pragma: [pragma]
|
|
145
|
+
pragma: [pragma]
|
|
146
146
|
}
|
|
147
147
|
: ann.notes;
|
|
148
148
|
return ann;
|
|
@@ -164,7 +164,7 @@ export default function (_serSeq, options) {
|
|
|
164
164
|
lines.push(
|
|
165
165
|
featureToGenbankString(feat, {
|
|
166
166
|
...options,
|
|
167
|
-
featurePadLength: longestFeatureTypeLength + 1
|
|
167
|
+
featurePadLength: longestFeatureTypeLength + 1
|
|
168
168
|
})
|
|
169
169
|
);
|
|
170
170
|
});
|
|
@@ -200,22 +200,23 @@ function createGenbankLocus(serSeq, options) {
|
|
|
200
200
|
serSeq.sequence = serSeq.sequence.symbols.split("");
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
let tmp;
|
|
204
203
|
let dnaType;
|
|
205
204
|
if (serSeq.isProtein) {
|
|
206
205
|
dnaType = "";
|
|
207
206
|
} else if (serSeq.type === "RNA") {
|
|
208
|
-
dnaType = serSeq?.doubleStranded
|
|
207
|
+
dnaType = serSeq?.doubleStranded
|
|
208
|
+
? "RNA"
|
|
209
|
+
: serSeq?.sequenceTypeFromLocus ?? "ss-RNA";
|
|
209
210
|
} else {
|
|
210
|
-
dnaType = serSeq?.doubleStranded
|
|
211
|
+
dnaType = serSeq?.doubleStranded
|
|
212
|
+
? "DNA"
|
|
213
|
+
: serSeq?.sequenceTypeFromLocus ?? "DNA";
|
|
211
214
|
}
|
|
212
215
|
const date = getCurrentDateString();
|
|
213
216
|
|
|
214
217
|
let line = StringUtil.rpad("LOCUS", " ", 12);
|
|
215
218
|
let nameToUse = serSeq.name || "Untitled_Sequence";
|
|
216
|
-
nameToUse = options.reformatSeqName
|
|
217
|
-
? reformatName(nameToUse)
|
|
218
|
-
: nameToUse;
|
|
219
|
+
nameToUse = options.reformatSeqName ? reformatName(nameToUse) : nameToUse;
|
|
219
220
|
line += StringUtil.rpad(nameToUse, " ", 16);
|
|
220
221
|
line += " "; // T.H line 2778 of GenbankFormat.as col 29 space
|
|
221
222
|
line += StringUtil.lpad(String(serSeq.sequence.length), " ", 11);
|
|
@@ -223,7 +224,7 @@ function createGenbankLocus(serSeq, options) {
|
|
|
223
224
|
// if (strandType !== "") {
|
|
224
225
|
// tmp = strandType + "-";
|
|
225
226
|
// } else {
|
|
226
|
-
tmp = "";
|
|
227
|
+
const tmp = "";
|
|
227
228
|
// }
|
|
228
229
|
line += StringUtil.lpad(tmp, " ", 3);
|
|
229
230
|
line += StringUtil.rpad(dnaType, " ", 6);
|
package/src/jsonToJsonString.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { omit } from "lodash";
|
|
2
2
|
|
|
3
|
-
import cleanUpTeselagenJsonForExport from "./utils/cleanUpTeselagenJsonForExport"
|
|
3
|
+
import cleanUpTeselagenJsonForExport from "./utils/cleanUpTeselagenJsonForExport";
|
|
4
4
|
import { tidyUpSequenceData } from "@teselagen/sequence-utils";
|
|
5
5
|
|
|
6
6
|
/**
|
package/src/sbolXmlToJson.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import validateSequenceArray from "./utils/validateSequenceArray";
|
|
3
3
|
import searchWholeObjByName, {
|
|
4
4
|
searchWholeObjByNameSimple,
|
|
5
|
-
searchWholeObjByNameSimpleArray
|
|
5
|
+
searchWholeObjByNameSimpleArray
|
|
6
6
|
} from "./utils/searchWholeObjByName";
|
|
7
7
|
|
|
8
8
|
import { XMLParser } from "fast-xml-parser";
|
|
@@ -23,12 +23,12 @@ async function sbolXmlToJson(string, options) {
|
|
|
23
23
|
let response = {
|
|
24
24
|
parsedSequence: null,
|
|
25
25
|
messages: [],
|
|
26
|
-
success: true
|
|
26
|
+
success: true
|
|
27
27
|
};
|
|
28
28
|
try {
|
|
29
29
|
const result = new XMLParser({
|
|
30
30
|
isArray: () => true,
|
|
31
|
-
ignoreAttributes: false
|
|
31
|
+
ignoreAttributes: false
|
|
32
32
|
}).parse(string);
|
|
33
33
|
const sbolJsonMatches = searchWholeObjByName("DnaComponent", result);
|
|
34
34
|
if (sbolJsonMatches[0]) {
|
|
@@ -38,7 +38,7 @@ async function sbolXmlToJson(string, options) {
|
|
|
38
38
|
response = {
|
|
39
39
|
parsedSequence: null,
|
|
40
40
|
messages: [],
|
|
41
|
-
success: true
|
|
41
|
+
success: true
|
|
42
42
|
};
|
|
43
43
|
response.parsedSequence = parseSbolJson(
|
|
44
44
|
sbolJsonMatches[0].value[i],
|
|
@@ -49,7 +49,7 @@ async function sbolXmlToJson(string, options) {
|
|
|
49
49
|
console.error("error.stack: ", e.stack);
|
|
50
50
|
resultArray.push({
|
|
51
51
|
success: false,
|
|
52
|
-
messages: ["Error while parsing Sbol format"]
|
|
52
|
+
messages: ["Error while parsing Sbol format"]
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
if (response.parsedSequence.features.length > 0) {
|
|
@@ -63,13 +63,13 @@ async function sbolXmlToJson(string, options) {
|
|
|
63
63
|
} else {
|
|
64
64
|
return onFileParsed({
|
|
65
65
|
success: false,
|
|
66
|
-
messages: ["Error: XML is not valid Jbei or Sbol format"]
|
|
66
|
+
messages: ["Error: XML is not valid Jbei or Sbol format"]
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
} catch (e) {
|
|
70
70
|
return onFileParsed({
|
|
71
71
|
success: false,
|
|
72
|
-
messages: ["Error parsing XML to JSON"]
|
|
72
|
+
messages: ["Error parsing XML to JSON"]
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -124,11 +124,11 @@ function parseSbolJson(sbolJson, options) {
|
|
|
124
124
|
end: parseInt(
|
|
125
125
|
get(feature, "bioEnd[0]") - (options.inclusive1BasedEnd ? 0 : 1)
|
|
126
126
|
),
|
|
127
|
-
strand: get(feature, "strand[0]")
|
|
127
|
+
strand: get(feature, "strand[0]") //+ or -
|
|
128
128
|
// notes: feature['seq:label'],
|
|
129
129
|
};
|
|
130
130
|
}
|
|
131
|
-
})
|
|
131
|
+
})
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
|