@teselagen/sequence-utils 0.3.35 → 0.3.37
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/calculateEndStability.d.ts +16 -0
- package/calculateEndStability.test.d.ts +1 -0
- package/calculateSantaLuciaTm.d.ts +127 -0
- package/calculateSantaLuciaTm.test.d.ts +1 -0
- package/index.cjs +170 -6
- package/index.d.ts +2 -0
- package/index.js +170 -6
- package/index.umd.cjs +170 -6
- package/package.json +1 -1
- package/src/calculateEndStability.js +86 -0
- package/src/calculateEndStability.test.js +21 -0
- package/src/calculateSantaLuciaTm.js +177 -0
- package/src/calculateSantaLuciaTm.test.js +39 -0
- package/src/featureTypesAndColors.js +1 -1
- package/src/index.js +2 -0
- package/src/tidyUpSequenceData.js +13 -5
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate End Stability (3' end stability) of a primer
|
|
3
|
+
*
|
|
4
|
+
* The maximum stability for the last five 3' bases of a left or right primer.
|
|
5
|
+
* Bigger numbers mean more stable 3' ends. The value is the maximum delta G
|
|
6
|
+
* (kcal/mol) for duplex disruption for the five 3' bases.
|
|
7
|
+
*
|
|
8
|
+
* According to Primer3 documentation:
|
|
9
|
+
* - Most stable 5mer duplex: GCGCG = 6.86 kcal/mol (SantaLucia 1998)
|
|
10
|
+
* - Most labile 5mer duplex: TATAT = 0.86 kcal/mol (SantaLucia 1998)
|
|
11
|
+
*
|
|
12
|
+
* @param {string} sequence - DNA sequence (5' to 3')
|
|
13
|
+
* @returns {number} - Delta G (kcal/mol) for the last 5 bases at 3' end
|
|
14
|
+
* @throws {Error} Invalid sequence or too short.
|
|
15
|
+
*/
|
|
16
|
+
export default function calculateEndStability(sequence: string): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate DNA sequence
|
|
3
|
+
*
|
|
4
|
+
* @param {string} sequence - DNA sequence
|
|
5
|
+
* @returns {boolean} - True if valid
|
|
6
|
+
*/
|
|
7
|
+
export function isValidSequence(sequence: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Calculate melting temperature using SantaLucia (1998) method
|
|
10
|
+
*
|
|
11
|
+
* @param {string} sequence - DNA sequence (5' to 3')
|
|
12
|
+
* @returns {number} - Melting temperature in Celsius
|
|
13
|
+
* @throws {Error} Invalid sequence or too short.
|
|
14
|
+
*/
|
|
15
|
+
export default function calculateSantaLuciaTm(sequence: string): number;
|
|
16
|
+
export namespace SANTA_LUCIA_NN {
|
|
17
|
+
namespace AA {
|
|
18
|
+
let dH: number;
|
|
19
|
+
let dS: number;
|
|
20
|
+
}
|
|
21
|
+
namespace TT {
|
|
22
|
+
let dH_1: number;
|
|
23
|
+
export { dH_1 as dH };
|
|
24
|
+
let dS_1: number;
|
|
25
|
+
export { dS_1 as dS };
|
|
26
|
+
}
|
|
27
|
+
namespace AT {
|
|
28
|
+
let dH_2: number;
|
|
29
|
+
export { dH_2 as dH };
|
|
30
|
+
let dS_2: number;
|
|
31
|
+
export { dS_2 as dS };
|
|
32
|
+
}
|
|
33
|
+
namespace TA {
|
|
34
|
+
let dH_3: number;
|
|
35
|
+
export { dH_3 as dH };
|
|
36
|
+
let dS_3: number;
|
|
37
|
+
export { dS_3 as dS };
|
|
38
|
+
}
|
|
39
|
+
namespace CA {
|
|
40
|
+
let dH_4: number;
|
|
41
|
+
export { dH_4 as dH };
|
|
42
|
+
let dS_4: number;
|
|
43
|
+
export { dS_4 as dS };
|
|
44
|
+
}
|
|
45
|
+
namespace TG {
|
|
46
|
+
let dH_5: number;
|
|
47
|
+
export { dH_5 as dH };
|
|
48
|
+
let dS_5: number;
|
|
49
|
+
export { dS_5 as dS };
|
|
50
|
+
}
|
|
51
|
+
namespace GT {
|
|
52
|
+
let dH_6: number;
|
|
53
|
+
export { dH_6 as dH };
|
|
54
|
+
let dS_6: number;
|
|
55
|
+
export { dS_6 as dS };
|
|
56
|
+
}
|
|
57
|
+
namespace AC {
|
|
58
|
+
let dH_7: number;
|
|
59
|
+
export { dH_7 as dH };
|
|
60
|
+
let dS_7: number;
|
|
61
|
+
export { dS_7 as dS };
|
|
62
|
+
}
|
|
63
|
+
namespace CT {
|
|
64
|
+
let dH_8: number;
|
|
65
|
+
export { dH_8 as dH };
|
|
66
|
+
let dS_8: number;
|
|
67
|
+
export { dS_8 as dS };
|
|
68
|
+
}
|
|
69
|
+
namespace AG {
|
|
70
|
+
let dH_9: number;
|
|
71
|
+
export { dH_9 as dH };
|
|
72
|
+
let dS_9: number;
|
|
73
|
+
export { dS_9 as dS };
|
|
74
|
+
}
|
|
75
|
+
namespace GA {
|
|
76
|
+
let dH_10: number;
|
|
77
|
+
export { dH_10 as dH };
|
|
78
|
+
let dS_10: number;
|
|
79
|
+
export { dS_10 as dS };
|
|
80
|
+
}
|
|
81
|
+
namespace TC {
|
|
82
|
+
let dH_11: number;
|
|
83
|
+
export { dH_11 as dH };
|
|
84
|
+
let dS_11: number;
|
|
85
|
+
export { dS_11 as dS };
|
|
86
|
+
}
|
|
87
|
+
namespace CG {
|
|
88
|
+
let dH_12: number;
|
|
89
|
+
export { dH_12 as dH };
|
|
90
|
+
let dS_12: number;
|
|
91
|
+
export { dS_12 as dS };
|
|
92
|
+
}
|
|
93
|
+
namespace GC {
|
|
94
|
+
let dH_13: number;
|
|
95
|
+
export { dH_13 as dH };
|
|
96
|
+
let dS_13: number;
|
|
97
|
+
export { dS_13 as dS };
|
|
98
|
+
}
|
|
99
|
+
namespace GG {
|
|
100
|
+
let dH_14: number;
|
|
101
|
+
export { dH_14 as dH };
|
|
102
|
+
let dS_14: number;
|
|
103
|
+
export { dS_14 as dS };
|
|
104
|
+
}
|
|
105
|
+
namespace CC {
|
|
106
|
+
let dH_15: number;
|
|
107
|
+
export { dH_15 as dH };
|
|
108
|
+
let dS_15: number;
|
|
109
|
+
export { dS_15 as dS };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export namespace SANTA_LUCIA_INIT {
|
|
113
|
+
export namespace GC_1 {
|
|
114
|
+
let dH_16: number;
|
|
115
|
+
export { dH_16 as dH };
|
|
116
|
+
let dS_16: number;
|
|
117
|
+
export { dS_16 as dS };
|
|
118
|
+
}
|
|
119
|
+
export { GC_1 as GC };
|
|
120
|
+
export namespace AT_1 {
|
|
121
|
+
let dH_17: number;
|
|
122
|
+
export { dH_17 as dH };
|
|
123
|
+
let dS_17: number;
|
|
124
|
+
export { dS_17 as dS };
|
|
125
|
+
}
|
|
126
|
+
export { AT_1 as AT };
|
|
127
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/index.cjs
CHANGED
|
@@ -3563,7 +3563,7 @@ const genbankFeatureTypes = [
|
|
|
3563
3563
|
{ name: "regulatory", color: "#3F6C51" },
|
|
3564
3564
|
{ name: "SecStr", color: "#7B4B94" },
|
|
3565
3565
|
{ name: "Site", color: "#7D82B8" },
|
|
3566
|
-
{ name: "telomere", color: "DE9151" },
|
|
3566
|
+
{ name: "telomere", color: "#DE9151" },
|
|
3567
3567
|
{ name: "tmRNA", color: "#B7E3CC" },
|
|
3568
3568
|
{ name: "unsure", color: "#C4FFB2" },
|
|
3569
3569
|
{ name: "V_segment", color: "#D6F7A3" },
|
|
@@ -6532,17 +6532,25 @@ function tidyUpSequenceData(pSeqData, options = {}) {
|
|
|
6532
6532
|
});
|
|
6533
6533
|
if (!noTranslationData) {
|
|
6534
6534
|
seqData.translations = flatMap(seqData.translations, (translation) => {
|
|
6535
|
+
var _a, _b;
|
|
6535
6536
|
if (noCdsTranslations && translation.translationType === "CDS Feature") {
|
|
6536
6537
|
return [];
|
|
6537
6538
|
}
|
|
6538
|
-
|
|
6539
|
-
|
|
6539
|
+
const codonStart = ((_b = (_a = translation == null ? void 0 : translation.notes) == null ? void 0 : _a.codon_start) == null ? void 0 : _b[0]) - 1 || 0;
|
|
6540
|
+
const expandedRange = expandOrContractRangeByLength(
|
|
6541
|
+
translation,
|
|
6542
|
+
-codonStart,
|
|
6543
|
+
true,
|
|
6544
|
+
seqData.sequence.length
|
|
6545
|
+
);
|
|
6546
|
+
if (!expandedRange.aminoAcids && !seqData.noSequence) {
|
|
6547
|
+
expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
|
|
6540
6548
|
seqData.sequence,
|
|
6541
|
-
|
|
6542
|
-
|
|
6549
|
+
expandedRange.forward,
|
|
6550
|
+
expandedRange
|
|
6543
6551
|
);
|
|
6544
6552
|
}
|
|
6545
|
-
return
|
|
6553
|
+
return expandedRange;
|
|
6546
6554
|
});
|
|
6547
6555
|
}
|
|
6548
6556
|
if (annotationsAsObjects) {
|
|
@@ -16513,6 +16521,160 @@ function calculateNebTa(sequences, primerConc, { monovalentCationConc, polymeras
|
|
|
16513
16521
|
}
|
|
16514
16522
|
}
|
|
16515
16523
|
__name(calculateNebTa, "calculateNebTa");
|
|
16524
|
+
const PRIMER3_PARAMS = {
|
|
16525
|
+
saltMonovalent: 50,
|
|
16526
|
+
// mM
|
|
16527
|
+
saltDivalent: 1.5,
|
|
16528
|
+
// mM
|
|
16529
|
+
dntpConc: 0.6,
|
|
16530
|
+
// mM
|
|
16531
|
+
dnaConc: 50,
|
|
16532
|
+
// nM
|
|
16533
|
+
R: 1.987
|
|
16534
|
+
// Gas constant (cal/K·mol)
|
|
16535
|
+
};
|
|
16536
|
+
const SANTA_LUCIA_NN = {
|
|
16537
|
+
AA: { dH: -7.9, dS: -22.2 },
|
|
16538
|
+
TT: { dH: -7.9, dS: -22.2 },
|
|
16539
|
+
AT: { dH: -7.2, dS: -20.4 },
|
|
16540
|
+
TA: { dH: -7.2, dS: -21.3 },
|
|
16541
|
+
CA: { dH: -8.5, dS: -22.7 },
|
|
16542
|
+
TG: { dH: -8.5, dS: -22.7 },
|
|
16543
|
+
GT: { dH: -8.4, dS: -22.4 },
|
|
16544
|
+
AC: { dH: -8.4, dS: -22.4 },
|
|
16545
|
+
CT: { dH: -7.8, dS: -21 },
|
|
16546
|
+
AG: { dH: -7.8, dS: -21 },
|
|
16547
|
+
GA: { dH: -8.2, dS: -22.2 },
|
|
16548
|
+
TC: { dH: -8.2, dS: -22.2 },
|
|
16549
|
+
CG: { dH: -10.6, dS: -27.2 },
|
|
16550
|
+
GC: { dH: -9.8, dS: -24.4 },
|
|
16551
|
+
GG: { dH: -8, dS: -19.9 },
|
|
16552
|
+
CC: { dH: -8, dS: -19.9 }
|
|
16553
|
+
};
|
|
16554
|
+
const SANTA_LUCIA_INIT = {
|
|
16555
|
+
GC: { dH: 0.1, dS: -2.8 },
|
|
16556
|
+
// initiation with terminal GC
|
|
16557
|
+
AT: { dH: 2.3, dS: 4.1 }
|
|
16558
|
+
// initiation with terminal AT
|
|
16559
|
+
};
|
|
16560
|
+
function getEffectiveMonovalentConc() {
|
|
16561
|
+
let effectiveMono = PRIMER3_PARAMS.saltMonovalent;
|
|
16562
|
+
{
|
|
16563
|
+
const freeMg = Math.max(
|
|
16564
|
+
0,
|
|
16565
|
+
PRIMER3_PARAMS.saltDivalent - PRIMER3_PARAMS.dntpConc
|
|
16566
|
+
);
|
|
16567
|
+
effectiveMono += 120 * Math.sqrt(freeMg);
|
|
16568
|
+
}
|
|
16569
|
+
return effectiveMono;
|
|
16570
|
+
}
|
|
16571
|
+
__name(getEffectiveMonovalentConc, "getEffectiveMonovalentConc");
|
|
16572
|
+
function applySaltCorrection(deltaS, nnPairs) {
|
|
16573
|
+
const effectiveMono = getEffectiveMonovalentConc();
|
|
16574
|
+
return deltaS + 0.368 * nnPairs * Math.log(effectiveMono / 1e3);
|
|
16575
|
+
}
|
|
16576
|
+
__name(applySaltCorrection, "applySaltCorrection");
|
|
16577
|
+
function isValidSequence(sequence) {
|
|
16578
|
+
return /^[ATGCN]+$/.test(sequence);
|
|
16579
|
+
}
|
|
16580
|
+
__name(isValidSequence, "isValidSequence");
|
|
16581
|
+
function calculateSantaLuciaTm(sequence) {
|
|
16582
|
+
try {
|
|
16583
|
+
sequence = sequence == null ? void 0 : sequence.toUpperCase().trim();
|
|
16584
|
+
if (!isValidSequence(sequence)) {
|
|
16585
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
16586
|
+
}
|
|
16587
|
+
if (sequence.length < 2) {
|
|
16588
|
+
throw new Error("Sequence too short: minimum length is 2 bases");
|
|
16589
|
+
}
|
|
16590
|
+
let deltaH = 0;
|
|
16591
|
+
let deltaS = 0;
|
|
16592
|
+
for (let i = 0; i < sequence.length - 1; i++) {
|
|
16593
|
+
const dinucleotide = sequence.substring(i, i + 2);
|
|
16594
|
+
if (dinucleotide.includes("N")) {
|
|
16595
|
+
continue;
|
|
16596
|
+
}
|
|
16597
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
16598
|
+
if (params) {
|
|
16599
|
+
deltaH += params.dH;
|
|
16600
|
+
deltaS += params.dS;
|
|
16601
|
+
}
|
|
16602
|
+
}
|
|
16603
|
+
const firstBase = sequence[0];
|
|
16604
|
+
const lastBase = sequence[sequence.length - 1];
|
|
16605
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
16606
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16607
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16608
|
+
} else {
|
|
16609
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16610
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16611
|
+
}
|
|
16612
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
16613
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16614
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16615
|
+
} else {
|
|
16616
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16617
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16618
|
+
}
|
|
16619
|
+
const nnPairs = sequence.length - 1;
|
|
16620
|
+
deltaS = applySaltCorrection(deltaS, nnPairs);
|
|
16621
|
+
const C = PRIMER3_PARAMS.dnaConc * 1e-9;
|
|
16622
|
+
const Tm = deltaH * 1e3 / (deltaS + PRIMER3_PARAMS.R * Math.log(C / 4));
|
|
16623
|
+
return Tm - 273.15;
|
|
16624
|
+
} catch (e) {
|
|
16625
|
+
return `Error calculating Tm for sequence ${sequence}. ${e}`;
|
|
16626
|
+
}
|
|
16627
|
+
}
|
|
16628
|
+
__name(calculateSantaLuciaTm, "calculateSantaLuciaTm");
|
|
16629
|
+
function calculateEndStability(sequence) {
|
|
16630
|
+
try {
|
|
16631
|
+
sequence = sequence == null ? void 0 : sequence.toUpperCase().trim();
|
|
16632
|
+
if (!isValidSequence(sequence)) {
|
|
16633
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
16634
|
+
}
|
|
16635
|
+
if (sequence.length < 5) {
|
|
16636
|
+
throw new Error(
|
|
16637
|
+
"Sequence too short: minimum length is 5 bases for end stability calculation"
|
|
16638
|
+
);
|
|
16639
|
+
}
|
|
16640
|
+
const last5Bases = sequence.substring(sequence.length - 5);
|
|
16641
|
+
let deltaH = 0;
|
|
16642
|
+
let deltaS = 0;
|
|
16643
|
+
for (let i = 0; i < 4; i++) {
|
|
16644
|
+
const dinucleotide = last5Bases.substring(i, i + 2);
|
|
16645
|
+
if (dinucleotide.includes("N")) {
|
|
16646
|
+
continue;
|
|
16647
|
+
}
|
|
16648
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
16649
|
+
if (params) {
|
|
16650
|
+
deltaH += params.dH;
|
|
16651
|
+
deltaS += params.dS;
|
|
16652
|
+
}
|
|
16653
|
+
}
|
|
16654
|
+
const firstBase = last5Bases[0];
|
|
16655
|
+
const lastBase = last5Bases[last5Bases.length - 1];
|
|
16656
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
16657
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16658
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16659
|
+
} else {
|
|
16660
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16661
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16662
|
+
}
|
|
16663
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
16664
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16665
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16666
|
+
} else {
|
|
16667
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16668
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16669
|
+
}
|
|
16670
|
+
const T = 310.15;
|
|
16671
|
+
const deltaG = deltaH - T * deltaS / 1e3;
|
|
16672
|
+
return Math.round(Math.abs(deltaG) * 100) / 100;
|
|
16673
|
+
} catch (e) {
|
|
16674
|
+
return `Error calculating end stability for sequence ${sequence}. ${e}`;
|
|
16675
|
+
}
|
|
16676
|
+
}
|
|
16677
|
+
__name(calculateEndStability, "calculateEndStability");
|
|
16516
16678
|
function getDigestFragmentsForCutsites(sequenceLength, circular, cutsites, opts = {}) {
|
|
16517
16679
|
const fragments = [];
|
|
16518
16680
|
const pairs = [];
|
|
@@ -16674,9 +16836,11 @@ exports.annotateSingleSeq = annotateSingleSeq;
|
|
|
16674
16836
|
exports.annotationTypes = annotationTypes;
|
|
16675
16837
|
exports.autoAnnotate = autoAnnotate;
|
|
16676
16838
|
exports.bioData = bioData;
|
|
16839
|
+
exports.calculateEndStability = calculateEndStability;
|
|
16677
16840
|
exports.calculateNebTa = calculateNebTa;
|
|
16678
16841
|
exports.calculateNebTm = calculateNebTm;
|
|
16679
16842
|
exports.calculatePercentGC = calculatePercentGC;
|
|
16843
|
+
exports.calculateSantaLuciaTm = calculateSantaLuciaTm;
|
|
16680
16844
|
exports.calculateTm = calculateTm;
|
|
16681
16845
|
exports.computeDigestFragments = computeDigestFragments;
|
|
16682
16846
|
exports.condensePairwiseAlignmentDifferences = condensePairwiseAlignmentDifferences;
|
package/index.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export { default as condensePairwiseAlignmentDifferences } from './condensePairw
|
|
|
63
63
|
export { default as addGapsToSeqReads } from './addGapsToSeqReads';
|
|
64
64
|
export { default as calculateNebTm } from './calculateNebTm';
|
|
65
65
|
export { default as calculateNebTa } from './calculateNebTa';
|
|
66
|
+
export { default as calculateSantaLuciaTm } from './calculateSantaLuciaTm';
|
|
67
|
+
export { default as calculateEndStability } from './calculateEndStability';
|
|
66
68
|
export { default as getDigestFragmentsForCutsites } from './getDigestFragmentsForCutsites';
|
|
67
69
|
export { default as getDigestFragmentsForRestrictionEnzymes } from './getDigestFragmentsForRestrictionEnzymes';
|
|
68
70
|
export { default as convertDnaCaretPositionOrRangeToAA } from './convertDnaCaretPositionOrRangeToAA';
|
package/index.js
CHANGED
|
@@ -3561,7 +3561,7 @@ const genbankFeatureTypes = [
|
|
|
3561
3561
|
{ name: "regulatory", color: "#3F6C51" },
|
|
3562
3562
|
{ name: "SecStr", color: "#7B4B94" },
|
|
3563
3563
|
{ name: "Site", color: "#7D82B8" },
|
|
3564
|
-
{ name: "telomere", color: "DE9151" },
|
|
3564
|
+
{ name: "telomere", color: "#DE9151" },
|
|
3565
3565
|
{ name: "tmRNA", color: "#B7E3CC" },
|
|
3566
3566
|
{ name: "unsure", color: "#C4FFB2" },
|
|
3567
3567
|
{ name: "V_segment", color: "#D6F7A3" },
|
|
@@ -6530,17 +6530,25 @@ function tidyUpSequenceData(pSeqData, options = {}) {
|
|
|
6530
6530
|
});
|
|
6531
6531
|
if (!noTranslationData) {
|
|
6532
6532
|
seqData.translations = flatMap(seqData.translations, (translation) => {
|
|
6533
|
+
var _a, _b;
|
|
6533
6534
|
if (noCdsTranslations && translation.translationType === "CDS Feature") {
|
|
6534
6535
|
return [];
|
|
6535
6536
|
}
|
|
6536
|
-
|
|
6537
|
-
|
|
6537
|
+
const codonStart = ((_b = (_a = translation == null ? void 0 : translation.notes) == null ? void 0 : _a.codon_start) == null ? void 0 : _b[0]) - 1 || 0;
|
|
6538
|
+
const expandedRange = expandOrContractRangeByLength(
|
|
6539
|
+
translation,
|
|
6540
|
+
-codonStart,
|
|
6541
|
+
true,
|
|
6542
|
+
seqData.sequence.length
|
|
6543
|
+
);
|
|
6544
|
+
if (!expandedRange.aminoAcids && !seqData.noSequence) {
|
|
6545
|
+
expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
|
|
6538
6546
|
seqData.sequence,
|
|
6539
|
-
|
|
6540
|
-
|
|
6547
|
+
expandedRange.forward,
|
|
6548
|
+
expandedRange
|
|
6541
6549
|
);
|
|
6542
6550
|
}
|
|
6543
|
-
return
|
|
6551
|
+
return expandedRange;
|
|
6544
6552
|
});
|
|
6545
6553
|
}
|
|
6546
6554
|
if (annotationsAsObjects) {
|
|
@@ -16511,6 +16519,160 @@ function calculateNebTa(sequences, primerConc, { monovalentCationConc, polymeras
|
|
|
16511
16519
|
}
|
|
16512
16520
|
}
|
|
16513
16521
|
__name(calculateNebTa, "calculateNebTa");
|
|
16522
|
+
const PRIMER3_PARAMS = {
|
|
16523
|
+
saltMonovalent: 50,
|
|
16524
|
+
// mM
|
|
16525
|
+
saltDivalent: 1.5,
|
|
16526
|
+
// mM
|
|
16527
|
+
dntpConc: 0.6,
|
|
16528
|
+
// mM
|
|
16529
|
+
dnaConc: 50,
|
|
16530
|
+
// nM
|
|
16531
|
+
R: 1.987
|
|
16532
|
+
// Gas constant (cal/K·mol)
|
|
16533
|
+
};
|
|
16534
|
+
const SANTA_LUCIA_NN = {
|
|
16535
|
+
AA: { dH: -7.9, dS: -22.2 },
|
|
16536
|
+
TT: { dH: -7.9, dS: -22.2 },
|
|
16537
|
+
AT: { dH: -7.2, dS: -20.4 },
|
|
16538
|
+
TA: { dH: -7.2, dS: -21.3 },
|
|
16539
|
+
CA: { dH: -8.5, dS: -22.7 },
|
|
16540
|
+
TG: { dH: -8.5, dS: -22.7 },
|
|
16541
|
+
GT: { dH: -8.4, dS: -22.4 },
|
|
16542
|
+
AC: { dH: -8.4, dS: -22.4 },
|
|
16543
|
+
CT: { dH: -7.8, dS: -21 },
|
|
16544
|
+
AG: { dH: -7.8, dS: -21 },
|
|
16545
|
+
GA: { dH: -8.2, dS: -22.2 },
|
|
16546
|
+
TC: { dH: -8.2, dS: -22.2 },
|
|
16547
|
+
CG: { dH: -10.6, dS: -27.2 },
|
|
16548
|
+
GC: { dH: -9.8, dS: -24.4 },
|
|
16549
|
+
GG: { dH: -8, dS: -19.9 },
|
|
16550
|
+
CC: { dH: -8, dS: -19.9 }
|
|
16551
|
+
};
|
|
16552
|
+
const SANTA_LUCIA_INIT = {
|
|
16553
|
+
GC: { dH: 0.1, dS: -2.8 },
|
|
16554
|
+
// initiation with terminal GC
|
|
16555
|
+
AT: { dH: 2.3, dS: 4.1 }
|
|
16556
|
+
// initiation with terminal AT
|
|
16557
|
+
};
|
|
16558
|
+
function getEffectiveMonovalentConc() {
|
|
16559
|
+
let effectiveMono = PRIMER3_PARAMS.saltMonovalent;
|
|
16560
|
+
{
|
|
16561
|
+
const freeMg = Math.max(
|
|
16562
|
+
0,
|
|
16563
|
+
PRIMER3_PARAMS.saltDivalent - PRIMER3_PARAMS.dntpConc
|
|
16564
|
+
);
|
|
16565
|
+
effectiveMono += 120 * Math.sqrt(freeMg);
|
|
16566
|
+
}
|
|
16567
|
+
return effectiveMono;
|
|
16568
|
+
}
|
|
16569
|
+
__name(getEffectiveMonovalentConc, "getEffectiveMonovalentConc");
|
|
16570
|
+
function applySaltCorrection(deltaS, nnPairs) {
|
|
16571
|
+
const effectiveMono = getEffectiveMonovalentConc();
|
|
16572
|
+
return deltaS + 0.368 * nnPairs * Math.log(effectiveMono / 1e3);
|
|
16573
|
+
}
|
|
16574
|
+
__name(applySaltCorrection, "applySaltCorrection");
|
|
16575
|
+
function isValidSequence(sequence) {
|
|
16576
|
+
return /^[ATGCN]+$/.test(sequence);
|
|
16577
|
+
}
|
|
16578
|
+
__name(isValidSequence, "isValidSequence");
|
|
16579
|
+
function calculateSantaLuciaTm(sequence) {
|
|
16580
|
+
try {
|
|
16581
|
+
sequence = sequence == null ? void 0 : sequence.toUpperCase().trim();
|
|
16582
|
+
if (!isValidSequence(sequence)) {
|
|
16583
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
16584
|
+
}
|
|
16585
|
+
if (sequence.length < 2) {
|
|
16586
|
+
throw new Error("Sequence too short: minimum length is 2 bases");
|
|
16587
|
+
}
|
|
16588
|
+
let deltaH = 0;
|
|
16589
|
+
let deltaS = 0;
|
|
16590
|
+
for (let i = 0; i < sequence.length - 1; i++) {
|
|
16591
|
+
const dinucleotide = sequence.substring(i, i + 2);
|
|
16592
|
+
if (dinucleotide.includes("N")) {
|
|
16593
|
+
continue;
|
|
16594
|
+
}
|
|
16595
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
16596
|
+
if (params) {
|
|
16597
|
+
deltaH += params.dH;
|
|
16598
|
+
deltaS += params.dS;
|
|
16599
|
+
}
|
|
16600
|
+
}
|
|
16601
|
+
const firstBase = sequence[0];
|
|
16602
|
+
const lastBase = sequence[sequence.length - 1];
|
|
16603
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
16604
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16605
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16606
|
+
} else {
|
|
16607
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16608
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16609
|
+
}
|
|
16610
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
16611
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16612
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16613
|
+
} else {
|
|
16614
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16615
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16616
|
+
}
|
|
16617
|
+
const nnPairs = sequence.length - 1;
|
|
16618
|
+
deltaS = applySaltCorrection(deltaS, nnPairs);
|
|
16619
|
+
const C = PRIMER3_PARAMS.dnaConc * 1e-9;
|
|
16620
|
+
const Tm = deltaH * 1e3 / (deltaS + PRIMER3_PARAMS.R * Math.log(C / 4));
|
|
16621
|
+
return Tm - 273.15;
|
|
16622
|
+
} catch (e) {
|
|
16623
|
+
return `Error calculating Tm for sequence ${sequence}. ${e}`;
|
|
16624
|
+
}
|
|
16625
|
+
}
|
|
16626
|
+
__name(calculateSantaLuciaTm, "calculateSantaLuciaTm");
|
|
16627
|
+
function calculateEndStability(sequence) {
|
|
16628
|
+
try {
|
|
16629
|
+
sequence = sequence == null ? void 0 : sequence.toUpperCase().trim();
|
|
16630
|
+
if (!isValidSequence(sequence)) {
|
|
16631
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
16632
|
+
}
|
|
16633
|
+
if (sequence.length < 5) {
|
|
16634
|
+
throw new Error(
|
|
16635
|
+
"Sequence too short: minimum length is 5 bases for end stability calculation"
|
|
16636
|
+
);
|
|
16637
|
+
}
|
|
16638
|
+
const last5Bases = sequence.substring(sequence.length - 5);
|
|
16639
|
+
let deltaH = 0;
|
|
16640
|
+
let deltaS = 0;
|
|
16641
|
+
for (let i = 0; i < 4; i++) {
|
|
16642
|
+
const dinucleotide = last5Bases.substring(i, i + 2);
|
|
16643
|
+
if (dinucleotide.includes("N")) {
|
|
16644
|
+
continue;
|
|
16645
|
+
}
|
|
16646
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
16647
|
+
if (params) {
|
|
16648
|
+
deltaH += params.dH;
|
|
16649
|
+
deltaS += params.dS;
|
|
16650
|
+
}
|
|
16651
|
+
}
|
|
16652
|
+
const firstBase = last5Bases[0];
|
|
16653
|
+
const lastBase = last5Bases[last5Bases.length - 1];
|
|
16654
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
16655
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16656
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16657
|
+
} else {
|
|
16658
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16659
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16660
|
+
}
|
|
16661
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
16662
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16663
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16664
|
+
} else {
|
|
16665
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16666
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16667
|
+
}
|
|
16668
|
+
const T = 310.15;
|
|
16669
|
+
const deltaG = deltaH - T * deltaS / 1e3;
|
|
16670
|
+
return Math.round(Math.abs(deltaG) * 100) / 100;
|
|
16671
|
+
} catch (e) {
|
|
16672
|
+
return `Error calculating end stability for sequence ${sequence}. ${e}`;
|
|
16673
|
+
}
|
|
16674
|
+
}
|
|
16675
|
+
__name(calculateEndStability, "calculateEndStability");
|
|
16514
16676
|
function getDigestFragmentsForCutsites(sequenceLength, circular, cutsites, opts = {}) {
|
|
16515
16677
|
const fragments = [];
|
|
16516
16678
|
const pairs = [];
|
|
@@ -16673,9 +16835,11 @@ export {
|
|
|
16673
16835
|
annotationTypes,
|
|
16674
16836
|
autoAnnotate,
|
|
16675
16837
|
bioData,
|
|
16838
|
+
calculateEndStability,
|
|
16676
16839
|
calculateNebTa,
|
|
16677
16840
|
calculateNebTm,
|
|
16678
16841
|
calculatePercentGC,
|
|
16842
|
+
calculateSantaLuciaTm,
|
|
16679
16843
|
calculateTm,
|
|
16680
16844
|
computeDigestFragments,
|
|
16681
16845
|
condensePairwiseAlignmentDifferences,
|
package/index.umd.cjs
CHANGED
|
@@ -3565,7 +3565,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
3565
3565
|
{ name: "regulatory", color: "#3F6C51" },
|
|
3566
3566
|
{ name: "SecStr", color: "#7B4B94" },
|
|
3567
3567
|
{ name: "Site", color: "#7D82B8" },
|
|
3568
|
-
{ name: "telomere", color: "DE9151" },
|
|
3568
|
+
{ name: "telomere", color: "#DE9151" },
|
|
3569
3569
|
{ name: "tmRNA", color: "#B7E3CC" },
|
|
3570
3570
|
{ name: "unsure", color: "#C4FFB2" },
|
|
3571
3571
|
{ name: "V_segment", color: "#D6F7A3" },
|
|
@@ -6534,17 +6534,25 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
6534
6534
|
});
|
|
6535
6535
|
if (!noTranslationData) {
|
|
6536
6536
|
seqData.translations = flatMap(seqData.translations, (translation) => {
|
|
6537
|
+
var _a, _b;
|
|
6537
6538
|
if (noCdsTranslations && translation.translationType === "CDS Feature") {
|
|
6538
6539
|
return [];
|
|
6539
6540
|
}
|
|
6540
|
-
|
|
6541
|
-
|
|
6541
|
+
const codonStart = ((_b = (_a = translation == null ? void 0 : translation.notes) == null ? void 0 : _a.codon_start) == null ? void 0 : _b[0]) - 1 || 0;
|
|
6542
|
+
const expandedRange = expandOrContractRangeByLength(
|
|
6543
|
+
translation,
|
|
6544
|
+
-codonStart,
|
|
6545
|
+
true,
|
|
6546
|
+
seqData.sequence.length
|
|
6547
|
+
);
|
|
6548
|
+
if (!expandedRange.aminoAcids && !seqData.noSequence) {
|
|
6549
|
+
expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
|
|
6542
6550
|
seqData.sequence,
|
|
6543
|
-
|
|
6544
|
-
|
|
6551
|
+
expandedRange.forward,
|
|
6552
|
+
expandedRange
|
|
6545
6553
|
);
|
|
6546
6554
|
}
|
|
6547
|
-
return
|
|
6555
|
+
return expandedRange;
|
|
6548
6556
|
});
|
|
6549
6557
|
}
|
|
6550
6558
|
if (annotationsAsObjects) {
|
|
@@ -16515,6 +16523,160 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
16515
16523
|
}
|
|
16516
16524
|
}
|
|
16517
16525
|
__name(calculateNebTa, "calculateNebTa");
|
|
16526
|
+
const PRIMER3_PARAMS = {
|
|
16527
|
+
saltMonovalent: 50,
|
|
16528
|
+
// mM
|
|
16529
|
+
saltDivalent: 1.5,
|
|
16530
|
+
// mM
|
|
16531
|
+
dntpConc: 0.6,
|
|
16532
|
+
// mM
|
|
16533
|
+
dnaConc: 50,
|
|
16534
|
+
// nM
|
|
16535
|
+
R: 1.987
|
|
16536
|
+
// Gas constant (cal/K·mol)
|
|
16537
|
+
};
|
|
16538
|
+
const SANTA_LUCIA_NN = {
|
|
16539
|
+
AA: { dH: -7.9, dS: -22.2 },
|
|
16540
|
+
TT: { dH: -7.9, dS: -22.2 },
|
|
16541
|
+
AT: { dH: -7.2, dS: -20.4 },
|
|
16542
|
+
TA: { dH: -7.2, dS: -21.3 },
|
|
16543
|
+
CA: { dH: -8.5, dS: -22.7 },
|
|
16544
|
+
TG: { dH: -8.5, dS: -22.7 },
|
|
16545
|
+
GT: { dH: -8.4, dS: -22.4 },
|
|
16546
|
+
AC: { dH: -8.4, dS: -22.4 },
|
|
16547
|
+
CT: { dH: -7.8, dS: -21 },
|
|
16548
|
+
AG: { dH: -7.8, dS: -21 },
|
|
16549
|
+
GA: { dH: -8.2, dS: -22.2 },
|
|
16550
|
+
TC: { dH: -8.2, dS: -22.2 },
|
|
16551
|
+
CG: { dH: -10.6, dS: -27.2 },
|
|
16552
|
+
GC: { dH: -9.8, dS: -24.4 },
|
|
16553
|
+
GG: { dH: -8, dS: -19.9 },
|
|
16554
|
+
CC: { dH: -8, dS: -19.9 }
|
|
16555
|
+
};
|
|
16556
|
+
const SANTA_LUCIA_INIT = {
|
|
16557
|
+
GC: { dH: 0.1, dS: -2.8 },
|
|
16558
|
+
// initiation with terminal GC
|
|
16559
|
+
AT: { dH: 2.3, dS: 4.1 }
|
|
16560
|
+
// initiation with terminal AT
|
|
16561
|
+
};
|
|
16562
|
+
function getEffectiveMonovalentConc() {
|
|
16563
|
+
let effectiveMono = PRIMER3_PARAMS.saltMonovalent;
|
|
16564
|
+
{
|
|
16565
|
+
const freeMg = Math.max(
|
|
16566
|
+
0,
|
|
16567
|
+
PRIMER3_PARAMS.saltDivalent - PRIMER3_PARAMS.dntpConc
|
|
16568
|
+
);
|
|
16569
|
+
effectiveMono += 120 * Math.sqrt(freeMg);
|
|
16570
|
+
}
|
|
16571
|
+
return effectiveMono;
|
|
16572
|
+
}
|
|
16573
|
+
__name(getEffectiveMonovalentConc, "getEffectiveMonovalentConc");
|
|
16574
|
+
function applySaltCorrection(deltaS, nnPairs) {
|
|
16575
|
+
const effectiveMono = getEffectiveMonovalentConc();
|
|
16576
|
+
return deltaS + 0.368 * nnPairs * Math.log(effectiveMono / 1e3);
|
|
16577
|
+
}
|
|
16578
|
+
__name(applySaltCorrection, "applySaltCorrection");
|
|
16579
|
+
function isValidSequence(sequence) {
|
|
16580
|
+
return /^[ATGCN]+$/.test(sequence);
|
|
16581
|
+
}
|
|
16582
|
+
__name(isValidSequence, "isValidSequence");
|
|
16583
|
+
function calculateSantaLuciaTm(sequence) {
|
|
16584
|
+
try {
|
|
16585
|
+
sequence = sequence == null ? void 0 : sequence.toUpperCase().trim();
|
|
16586
|
+
if (!isValidSequence(sequence)) {
|
|
16587
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
16588
|
+
}
|
|
16589
|
+
if (sequence.length < 2) {
|
|
16590
|
+
throw new Error("Sequence too short: minimum length is 2 bases");
|
|
16591
|
+
}
|
|
16592
|
+
let deltaH = 0;
|
|
16593
|
+
let deltaS = 0;
|
|
16594
|
+
for (let i = 0; i < sequence.length - 1; i++) {
|
|
16595
|
+
const dinucleotide = sequence.substring(i, i + 2);
|
|
16596
|
+
if (dinucleotide.includes("N")) {
|
|
16597
|
+
continue;
|
|
16598
|
+
}
|
|
16599
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
16600
|
+
if (params) {
|
|
16601
|
+
deltaH += params.dH;
|
|
16602
|
+
deltaS += params.dS;
|
|
16603
|
+
}
|
|
16604
|
+
}
|
|
16605
|
+
const firstBase = sequence[0];
|
|
16606
|
+
const lastBase = sequence[sequence.length - 1];
|
|
16607
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
16608
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16609
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16610
|
+
} else {
|
|
16611
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16612
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16613
|
+
}
|
|
16614
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
16615
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16616
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16617
|
+
} else {
|
|
16618
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16619
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16620
|
+
}
|
|
16621
|
+
const nnPairs = sequence.length - 1;
|
|
16622
|
+
deltaS = applySaltCorrection(deltaS, nnPairs);
|
|
16623
|
+
const C = PRIMER3_PARAMS.dnaConc * 1e-9;
|
|
16624
|
+
const Tm = deltaH * 1e3 / (deltaS + PRIMER3_PARAMS.R * Math.log(C / 4));
|
|
16625
|
+
return Tm - 273.15;
|
|
16626
|
+
} catch (e) {
|
|
16627
|
+
return `Error calculating Tm for sequence ${sequence}. ${e}`;
|
|
16628
|
+
}
|
|
16629
|
+
}
|
|
16630
|
+
__name(calculateSantaLuciaTm, "calculateSantaLuciaTm");
|
|
16631
|
+
function calculateEndStability(sequence) {
|
|
16632
|
+
try {
|
|
16633
|
+
sequence = sequence == null ? void 0 : sequence.toUpperCase().trim();
|
|
16634
|
+
if (!isValidSequence(sequence)) {
|
|
16635
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
16636
|
+
}
|
|
16637
|
+
if (sequence.length < 5) {
|
|
16638
|
+
throw new Error(
|
|
16639
|
+
"Sequence too short: minimum length is 5 bases for end stability calculation"
|
|
16640
|
+
);
|
|
16641
|
+
}
|
|
16642
|
+
const last5Bases = sequence.substring(sequence.length - 5);
|
|
16643
|
+
let deltaH = 0;
|
|
16644
|
+
let deltaS = 0;
|
|
16645
|
+
for (let i = 0; i < 4; i++) {
|
|
16646
|
+
const dinucleotide = last5Bases.substring(i, i + 2);
|
|
16647
|
+
if (dinucleotide.includes("N")) {
|
|
16648
|
+
continue;
|
|
16649
|
+
}
|
|
16650
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
16651
|
+
if (params) {
|
|
16652
|
+
deltaH += params.dH;
|
|
16653
|
+
deltaS += params.dS;
|
|
16654
|
+
}
|
|
16655
|
+
}
|
|
16656
|
+
const firstBase = last5Bases[0];
|
|
16657
|
+
const lastBase = last5Bases[last5Bases.length - 1];
|
|
16658
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
16659
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16660
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16661
|
+
} else {
|
|
16662
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16663
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16664
|
+
}
|
|
16665
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
16666
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
16667
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
16668
|
+
} else {
|
|
16669
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
16670
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
16671
|
+
}
|
|
16672
|
+
const T = 310.15;
|
|
16673
|
+
const deltaG = deltaH - T * deltaS / 1e3;
|
|
16674
|
+
return Math.round(Math.abs(deltaG) * 100) / 100;
|
|
16675
|
+
} catch (e) {
|
|
16676
|
+
return `Error calculating end stability for sequence ${sequence}. ${e}`;
|
|
16677
|
+
}
|
|
16678
|
+
}
|
|
16679
|
+
__name(calculateEndStability, "calculateEndStability");
|
|
16518
16680
|
function getDigestFragmentsForCutsites(sequenceLength, circular, cutsites, opts = {}) {
|
|
16519
16681
|
const fragments = [];
|
|
16520
16682
|
const pairs = [];
|
|
@@ -16676,9 +16838,11 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
16676
16838
|
exports2.annotationTypes = annotationTypes;
|
|
16677
16839
|
exports2.autoAnnotate = autoAnnotate;
|
|
16678
16840
|
exports2.bioData = bioData;
|
|
16841
|
+
exports2.calculateEndStability = calculateEndStability;
|
|
16679
16842
|
exports2.calculateNebTa = calculateNebTa;
|
|
16680
16843
|
exports2.calculateNebTm = calculateNebTm;
|
|
16681
16844
|
exports2.calculatePercentGC = calculatePercentGC;
|
|
16845
|
+
exports2.calculateSantaLuciaTm = calculateSantaLuciaTm;
|
|
16682
16846
|
exports2.calculateTm = calculateTm;
|
|
16683
16847
|
exports2.computeDigestFragments = computeDigestFragments;
|
|
16684
16848
|
exports2.condensePairwiseAlignmentDifferences = condensePairwiseAlignmentDifferences;
|
package/package.json
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isValidSequence,
|
|
3
|
+
SANTA_LUCIA_NN,
|
|
4
|
+
SANTA_LUCIA_INIT
|
|
5
|
+
} from "./calculateSantaLuciaTm.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Calculate End Stability (3' end stability) of a primer
|
|
9
|
+
*
|
|
10
|
+
* The maximum stability for the last five 3' bases of a left or right primer.
|
|
11
|
+
* Bigger numbers mean more stable 3' ends. The value is the maximum delta G
|
|
12
|
+
* (kcal/mol) for duplex disruption for the five 3' bases.
|
|
13
|
+
*
|
|
14
|
+
* According to Primer3 documentation:
|
|
15
|
+
* - Most stable 5mer duplex: GCGCG = 6.86 kcal/mol (SantaLucia 1998)
|
|
16
|
+
* - Most labile 5mer duplex: TATAT = 0.86 kcal/mol (SantaLucia 1998)
|
|
17
|
+
*
|
|
18
|
+
* @param {string} sequence - DNA sequence (5' to 3')
|
|
19
|
+
* @returns {number} - Delta G (kcal/mol) for the last 5 bases at 3' end
|
|
20
|
+
* @throws {Error} Invalid sequence or too short.
|
|
21
|
+
*/
|
|
22
|
+
export default function calculateEndStability(sequence) {
|
|
23
|
+
try {
|
|
24
|
+
sequence = sequence?.toUpperCase().trim();
|
|
25
|
+
|
|
26
|
+
if (!isValidSequence(sequence)) {
|
|
27
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (sequence.length < 5) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
"Sequence too short: minimum length is 5 bases for end stability calculation"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const last5Bases = sequence.substring(sequence.length - 5);
|
|
37
|
+
|
|
38
|
+
let deltaH = 0; // kcal/mol
|
|
39
|
+
let deltaS = 0; // cal/K·mol
|
|
40
|
+
|
|
41
|
+
// Calculate nearest-neighbor contributions for the 4 dinucleotides
|
|
42
|
+
for (let i = 0; i < 4; i++) {
|
|
43
|
+
const dinucleotide = last5Bases.substring(i, i + 2);
|
|
44
|
+
|
|
45
|
+
if (dinucleotide.includes("N")) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
50
|
+
if (params) {
|
|
51
|
+
deltaH += params.dH;
|
|
52
|
+
deltaS += params.dS;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Add initiation parameters for terminal base pairs
|
|
57
|
+
const firstBase = last5Bases[0];
|
|
58
|
+
const lastBase = last5Bases[last5Bases.length - 1];
|
|
59
|
+
|
|
60
|
+
// Terminal GC or AT initiation
|
|
61
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
62
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
63
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
64
|
+
} else {
|
|
65
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
66
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
70
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
71
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
72
|
+
} else {
|
|
73
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
74
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Calculate deltaG at 37°C (310.15 K)
|
|
78
|
+
// deltaG = deltaH - T * deltaS
|
|
79
|
+
const T = 310.15; // 37°C in Kelvin
|
|
80
|
+
const deltaG = deltaH - (T * deltaS) / 1000; // Result in kcal/mol
|
|
81
|
+
|
|
82
|
+
return Math.round(Math.abs(deltaG) * 100) / 100;
|
|
83
|
+
} catch (e) {
|
|
84
|
+
return `Error calculating end stability for sequence ${sequence}. ${e}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import calculateEndStability from "./calculateEndStability";
|
|
3
|
+
|
|
4
|
+
describe("Calculate the stability of the primer ends.", () => {
|
|
5
|
+
it("should return the end stability score of a given primer sequence", () => {
|
|
6
|
+
assert.equal(calculateEndStability("AGCGGATAACAATTTCACACAGGA"), 3.89);
|
|
7
|
+
assert.equal(calculateEndStability("AGCGGATAACAATTTCAC"), 3.24);
|
|
8
|
+
assert.equal(calculateEndStability("AGCGGATAACAATTTcac"), 3.24);
|
|
9
|
+
assert.equal(calculateEndStability("ataataccgcgccacatagc"), 2.99);
|
|
10
|
+
assert.equal(calculateEndStability("AGCGGATAACAATACNNN"), 0.6);
|
|
11
|
+
assert.equal(calculateEndStability("AGCGGATAACAATACnnn"), 0.6);
|
|
12
|
+
assert.equal(
|
|
13
|
+
calculateEndStability("AGCGGATAACAYZAKLPATAC"),
|
|
14
|
+
"Error calculating end stability for sequence AGCGGATAACAYZAKLPATAC. Error: Invalid sequence: contains non-DNA characters"
|
|
15
|
+
);
|
|
16
|
+
assert.equal(
|
|
17
|
+
calculateEndStability("AGCG"),
|
|
18
|
+
"Error calculating end stability for sequence AGCG. Error: Sequence too short: minimum length is 5 bases for end stability calculation"
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primer3 Melting Temperature Calculator
|
|
3
|
+
*
|
|
4
|
+
* Implements the melting temperature calculation algorithm from Primer3
|
|
5
|
+
* based on the documentation at https://primer3.ut.ee/primer3web_help.htm
|
|
6
|
+
*
|
|
7
|
+
* Uses SantaLucia (1998) nearest-neighbor thermodynamics method with
|
|
8
|
+
* fixed Primer3 custom parameters:
|
|
9
|
+
* - Formula: SantaLucia (1998)
|
|
10
|
+
* - Salt correction: SantaLucia (1998)
|
|
11
|
+
* - Monovalent salt: 50.0 mM
|
|
12
|
+
* - Divalent salt: 1.5 mM
|
|
13
|
+
* - dNTP concentration: 0.6 mM
|
|
14
|
+
* - DNA concentration: 50.0 nM
|
|
15
|
+
*
|
|
16
|
+
* References:
|
|
17
|
+
* - SantaLucia JR (1998) "A unified view of polymer, dumbbell and
|
|
18
|
+
* oligonucleotide DNA nearest-neighbor thermodynamics",
|
|
19
|
+
* Proc Natl Acad Sci 95:1460-65
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Primer3 custom parameters (fixed)
|
|
23
|
+
const PRIMER3_PARAMS = {
|
|
24
|
+
saltMonovalent: 50.0, // mM
|
|
25
|
+
saltDivalent: 1.5, // mM
|
|
26
|
+
dntpConc: 0.6, // mM
|
|
27
|
+
dnaConc: 50.0, // nM
|
|
28
|
+
R: 1.987 // Gas constant (cal/K·mol)
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// SantaLucia (1998) nearest-neighbor parameters
|
|
32
|
+
// dH in kcal/mol, dS in cal/K·mol
|
|
33
|
+
export const SANTA_LUCIA_NN = {
|
|
34
|
+
AA: { dH: -7.9, dS: -22.2 },
|
|
35
|
+
TT: { dH: -7.9, dS: -22.2 },
|
|
36
|
+
AT: { dH: -7.2, dS: -20.4 },
|
|
37
|
+
TA: { dH: -7.2, dS: -21.3 },
|
|
38
|
+
CA: { dH: -8.5, dS: -22.7 },
|
|
39
|
+
TG: { dH: -8.5, dS: -22.7 },
|
|
40
|
+
GT: { dH: -8.4, dS: -22.4 },
|
|
41
|
+
AC: { dH: -8.4, dS: -22.4 },
|
|
42
|
+
CT: { dH: -7.8, dS: -21.0 },
|
|
43
|
+
AG: { dH: -7.8, dS: -21.0 },
|
|
44
|
+
GA: { dH: -8.2, dS: -22.2 },
|
|
45
|
+
TC: { dH: -8.2, dS: -22.2 },
|
|
46
|
+
CG: { dH: -10.6, dS: -27.2 },
|
|
47
|
+
GC: { dH: -9.8, dS: -24.4 },
|
|
48
|
+
GG: { dH: -8.0, dS: -19.9 },
|
|
49
|
+
CC: { dH: -8.0, dS: -19.9 }
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Initiation parameters (SantaLucia 1998)
|
|
53
|
+
export const SANTA_LUCIA_INIT = {
|
|
54
|
+
GC: { dH: 0.1, dS: -2.8 }, // initiation with terminal GC
|
|
55
|
+
AT: { dH: 2.3, dS: 4.1 } // initiation with terminal AT
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Calculate effective monovalent cation concentration
|
|
60
|
+
* Accounts for divalent cations (Mg2+) binding to dNTPs
|
|
61
|
+
* Formula from von Ahsen et al. (2001)
|
|
62
|
+
*
|
|
63
|
+
* @returns {number} - Effective monovalent concentration in mM
|
|
64
|
+
*/
|
|
65
|
+
function getEffectiveMonovalentConc() {
|
|
66
|
+
let effectiveMono = PRIMER3_PARAMS.saltMonovalent;
|
|
67
|
+
|
|
68
|
+
// Adjust for divalent cations
|
|
69
|
+
if (PRIMER3_PARAMS.saltDivalent > 0) {
|
|
70
|
+
const freeMg = Math.max(
|
|
71
|
+
0,
|
|
72
|
+
PRIMER3_PARAMS.saltDivalent - PRIMER3_PARAMS.dntpConc
|
|
73
|
+
);
|
|
74
|
+
effectiveMono += 120 * Math.sqrt(freeMg);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return effectiveMono;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Apply SantaLucia (1998) salt correction to entropy
|
|
82
|
+
*
|
|
83
|
+
* @param {number} deltaS - Entropy in cal/K·mol
|
|
84
|
+
* @param {number} nnPairs - Number of nearest-neighbor pairs
|
|
85
|
+
* @returns {number} - Corrected entropy in cal/K·mol
|
|
86
|
+
*/
|
|
87
|
+
function applySaltCorrection(deltaS, nnPairs) {
|
|
88
|
+
const effectiveMono = getEffectiveMonovalentConc();
|
|
89
|
+
// SantaLucia (1998) salt correction
|
|
90
|
+
return deltaS + 0.368 * nnPairs * Math.log(effectiveMono / 1000);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Validate DNA sequence
|
|
95
|
+
*
|
|
96
|
+
* @param {string} sequence - DNA sequence
|
|
97
|
+
* @returns {boolean} - True if valid
|
|
98
|
+
*/
|
|
99
|
+
export function isValidSequence(sequence) {
|
|
100
|
+
return /^[ATGCN]+$/.test(sequence);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Calculate melting temperature using SantaLucia (1998) method
|
|
105
|
+
*
|
|
106
|
+
* @param {string} sequence - DNA sequence (5' to 3')
|
|
107
|
+
* @returns {number} - Melting temperature in Celsius
|
|
108
|
+
* @throws {Error} Invalid sequence or too short.
|
|
109
|
+
*/
|
|
110
|
+
export default function calculateSantaLuciaTm(sequence) {
|
|
111
|
+
// Convert to uppercase and validate
|
|
112
|
+
try {
|
|
113
|
+
sequence = sequence?.toUpperCase().trim();
|
|
114
|
+
|
|
115
|
+
if (!isValidSequence(sequence)) {
|
|
116
|
+
throw new Error("Invalid sequence: contains non-DNA characters");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (sequence.length < 2) {
|
|
120
|
+
throw new Error("Sequence too short: minimum length is 2 bases");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let deltaH = 0; // kcal/mol
|
|
124
|
+
let deltaS = 0; // cal/K·mol
|
|
125
|
+
|
|
126
|
+
// Calculate nearest-neighbor contributions
|
|
127
|
+
for (let i = 0; i < sequence.length - 1; i++) {
|
|
128
|
+
const dinucleotide = sequence.substring(i, i + 2);
|
|
129
|
+
|
|
130
|
+
// Skip if contains N
|
|
131
|
+
if (dinucleotide.includes("N")) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const params = SANTA_LUCIA_NN[dinucleotide];
|
|
136
|
+
if (params) {
|
|
137
|
+
deltaH += params.dH;
|
|
138
|
+
deltaS += params.dS;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Add initiation parameters
|
|
143
|
+
const firstBase = sequence[0];
|
|
144
|
+
const lastBase = sequence[sequence.length - 1];
|
|
145
|
+
|
|
146
|
+
// Terminal GC or AT initiation
|
|
147
|
+
if (firstBase === "G" || firstBase === "C") {
|
|
148
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
149
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
150
|
+
} else {
|
|
151
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
152
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (lastBase === "G" || lastBase === "C") {
|
|
156
|
+
deltaH += SANTA_LUCIA_INIT.GC.dH;
|
|
157
|
+
deltaS += SANTA_LUCIA_INIT.GC.dS;
|
|
158
|
+
} else {
|
|
159
|
+
deltaH += SANTA_LUCIA_INIT.AT.dH;
|
|
160
|
+
deltaS += SANTA_LUCIA_INIT.AT.dS;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Apply salt correction
|
|
164
|
+
const nnPairs = sequence.length - 1;
|
|
165
|
+
deltaS = applySaltCorrection(deltaS, nnPairs);
|
|
166
|
+
|
|
167
|
+
// Calculate Tm using: Tm = deltaH / (deltaS + R * ln(C/4))
|
|
168
|
+
// where C is DNA concentration in M (convert from nM)
|
|
169
|
+
const C = PRIMER3_PARAMS.dnaConc * 1e-9; // Convert nM to M
|
|
170
|
+
const Tm = (deltaH * 1000) / (deltaS + PRIMER3_PARAMS.R * Math.log(C / 4));
|
|
171
|
+
|
|
172
|
+
// Convert from Kelvin to Celsius
|
|
173
|
+
return Tm - 273.15;
|
|
174
|
+
} catch (e) {
|
|
175
|
+
return `Error calculating Tm for sequence ${sequence}. ${e}`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import calculateSantaLuciaTm from "./calculateSantaLuciaTm";
|
|
3
|
+
|
|
4
|
+
describe("calculate Tm based on SantaLucia 1998", () => {
|
|
5
|
+
it("should return the melting temperature of a given sequence, if no degenerate bases are present", () => {
|
|
6
|
+
assert.equal(
|
|
7
|
+
calculateSantaLuciaTm("AGCGGATAACAATTTCACACAGGA"),
|
|
8
|
+
60.805947394707346
|
|
9
|
+
);
|
|
10
|
+
assert.equal(
|
|
11
|
+
calculateSantaLuciaTm("AGCGGATAACAATTTCAC"),
|
|
12
|
+
50.301642635069356
|
|
13
|
+
);
|
|
14
|
+
assert.equal(
|
|
15
|
+
calculateSantaLuciaTm("AGCGGATAACAATTTcac"),
|
|
16
|
+
50.301642635069356
|
|
17
|
+
);
|
|
18
|
+
assert.equal(
|
|
19
|
+
calculateSantaLuciaTm("ataataccgcgccacatagc"),
|
|
20
|
+
58.27798862992364
|
|
21
|
+
);
|
|
22
|
+
assert.equal(
|
|
23
|
+
calculateSantaLuciaTm("AGCGGATAACAATACNNN"),
|
|
24
|
+
40.92944342497407
|
|
25
|
+
);
|
|
26
|
+
assert.equal(
|
|
27
|
+
calculateSantaLuciaTm("AGCGGATAACAATACnnn"),
|
|
28
|
+
40.92944342497407
|
|
29
|
+
);
|
|
30
|
+
assert.equal(
|
|
31
|
+
calculateSantaLuciaTm("AGCGGATAACAYZAKLPATAC"),
|
|
32
|
+
"Error calculating Tm for sequence AGCGGATAACAYZAKLPATAC. Error: Invalid sequence: contains non-DNA characters"
|
|
33
|
+
);
|
|
34
|
+
assert.equal(
|
|
35
|
+
calculateSantaLuciaTm("A"),
|
|
36
|
+
"Error calculating Tm for sequence A. Error: Sequence too short: minimum length is 2 bases"
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -17,7 +17,7 @@ const genbankFeatureTypes = [
|
|
|
17
17
|
{ name: "regulatory", color: "#3F6C51" },
|
|
18
18
|
{ name: "SecStr", color: "#7B4B94" },
|
|
19
19
|
{ name: "Site", color: "#7D82B8" },
|
|
20
|
-
{ name: "telomere", color: "DE9151" },
|
|
20
|
+
{ name: "telomere", color: "#DE9151" },
|
|
21
21
|
{ name: "tmRNA", color: "#B7E3CC" },
|
|
22
22
|
{ name: "unsure", color: "#C4FFB2" },
|
|
23
23
|
{ name: "V_segment", color: "#D6F7A3" },
|
package/src/index.js
CHANGED
|
@@ -96,6 +96,8 @@ export { default as condensePairwiseAlignmentDifferences } from "./condensePairw
|
|
|
96
96
|
export { default as addGapsToSeqReads } from "./addGapsToSeqReads";
|
|
97
97
|
export { default as calculateNebTm } from "./calculateNebTm";
|
|
98
98
|
export { default as calculateNebTa } from "./calculateNebTa";
|
|
99
|
+
export { default as calculateSantaLuciaTm } from "./calculateSantaLuciaTm";
|
|
100
|
+
export { default as calculateEndStability } from "./calculateEndStability";
|
|
99
101
|
export { default as getDigestFragmentsForCutsites } from "./getDigestFragmentsForCutsites";
|
|
100
102
|
export { default as getDigestFragmentsForRestrictionEnzymes } from "./getDigestFragmentsForRestrictionEnzymes";
|
|
101
103
|
export { default as convertDnaCaretPositionOrRangeToAA } from "./convertDnaCaretPositionOrRangeToAA";
|
|
@@ -9,6 +9,7 @@ import tidyUpAnnotation from "./tidyUpAnnotation";
|
|
|
9
9
|
import getDegenerateDnaStringFromAaString from "./getDegenerateDnaStringFromAAString";
|
|
10
10
|
import { getFeatureTypes } from "./featureTypesAndColors";
|
|
11
11
|
import getAminoAcidStringFromSequenceString from "./getAminoAcidStringFromSequenceString";
|
|
12
|
+
import { expandOrContractRangeByLength } from "@teselagen/range-utils";
|
|
12
13
|
|
|
13
14
|
export default function tidyUpSequenceData(pSeqData, options = {}) {
|
|
14
15
|
const {
|
|
@@ -137,14 +138,21 @@ export default function tidyUpSequenceData(pSeqData, options = {}) {
|
|
|
137
138
|
//filter off cds translations
|
|
138
139
|
return [];
|
|
139
140
|
}
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
const codonStart = translation?.notes?.codon_start?.[0] - 1 || 0;
|
|
142
|
+
const expandedRange = expandOrContractRangeByLength(
|
|
143
|
+
translation,
|
|
144
|
+
-codonStart,
|
|
145
|
+
true,
|
|
146
|
+
seqData.sequence.length
|
|
147
|
+
);
|
|
148
|
+
if (!expandedRange.aminoAcids && !seqData.noSequence) {
|
|
149
|
+
expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
|
|
142
150
|
seqData.sequence,
|
|
143
|
-
|
|
144
|
-
|
|
151
|
+
expandedRange.forward,
|
|
152
|
+
expandedRange
|
|
145
153
|
);
|
|
146
154
|
}
|
|
147
|
-
return
|
|
155
|
+
return expandedRange;
|
|
148
156
|
});
|
|
149
157
|
}
|
|
150
158
|
|