@teselagen/ove 0.8.18 → 0.8.20

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/index.umd.js CHANGED
@@ -35432,6 +35432,15 @@ ${latestSubscriptionCallbackError.current.stack}
35432
35432
  return value < other;
35433
35433
  }
35434
35434
  __name(baseLt, "baseLt");
35435
+ function mapValues$1(object2, iteratee) {
35436
+ var result = {};
35437
+ iteratee = baseIteratee(iteratee);
35438
+ baseForOwn(object2, function(value, key, object3) {
35439
+ baseAssignValue(result, key, iteratee(value, key, object3));
35440
+ });
35441
+ return result;
35442
+ }
35443
+ __name(mapValues$1, "mapValues$1");
35435
35444
  function baseExtremum(array, iteratee, comparator) {
35436
35445
  var index2 = -1, length = array.length;
35437
35446
  while (++index2 < length) {
@@ -40254,12 +40263,12 @@ ${latestSubscriptionCallbackError.current.stack}
40254
40263
  if (typeof window !== "undefined") {
40255
40264
  getComputedStyleX = window.getComputedStyle ? _getComputedStyle : _getComputedStyleIE;
40256
40265
  }
40257
- function each$2(arr, fn2) {
40266
+ function each(arr, fn2) {
40258
40267
  for (var i2 = 0; i2 < arr.length; i2++) {
40259
40268
  fn2(arr[i2]);
40260
40269
  }
40261
40270
  }
40262
- __name(each$2, "each$2");
40271
+ __name(each, "each");
40263
40272
  function isBorderBoxFn(elem) {
40264
40273
  return getComputedStyleX(elem, "boxSizing") === "border-box";
40265
40274
  }
@@ -40314,7 +40323,7 @@ ${latestSubscriptionCallbackError.current.stack}
40314
40323
  }
40315
40324
  __name(isWindow, "isWindow");
40316
40325
  var domUtils = {};
40317
- each$2(["Width", "Height"], function(name2) {
40326
+ each(["Width", "Height"], function(name2) {
40318
40327
  domUtils["doc".concat(name2)] = function(refWin) {
40319
40328
  var d2 = refWin.document;
40320
40329
  return Math.max(
@@ -40410,7 +40419,7 @@ ${latestSubscriptionCallbackError.current.stack}
40410
40419
  return getComputedStyleX(el, name2);
40411
40420
  }
40412
40421
  __name(css, "css");
40413
- each$2(["width", "height"], function(name2) {
40422
+ each(["width", "height"], function(name2) {
40414
40423
  var first = name2.charAt(0).toUpperCase() + name2.slice(1);
40415
40424
  domUtils["outer".concat(first)] = function(el, includeMargin) {
40416
40425
  return el && getWHIgnoreDisplay(el, name2, includeMargin ? MARGIN_INDEX : BORDER_INDEX);
@@ -40461,7 +40470,7 @@ ${latestSubscriptionCallbackError.current.stack}
40461
40470
  }
40462
40471
  }, "offset"),
40463
40472
  isWindow,
40464
- each: each$2,
40473
+ each,
40465
40474
  css,
40466
40475
  clone: /* @__PURE__ */ __name(function clone2(obj) {
40467
40476
  var ret = {};
@@ -104112,17 +104121,25 @@ ${latestSubscriptionCallbackError.current.stack}
104112
104121
  });
104113
104122
  if (!noTranslationData) {
104114
104123
  seqData.translations = flatMap(seqData.translations, (translation) => {
104124
+ var _a2, _b2;
104115
104125
  if (noCdsTranslations && translation.translationType === "CDS Feature") {
104116
104126
  return [];
104117
104127
  }
104118
- if (!translation.aminoAcids && !seqData.noSequence) {
104119
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
104128
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
104129
+ const expandedRange = expandOrContractRangeByLength(
104130
+ translation,
104131
+ -codonStart,
104132
+ true,
104133
+ seqData.sequence.length
104134
+ );
104135
+ if (!expandedRange.aminoAcids && !seqData.noSequence) {
104136
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
104120
104137
  seqData.sequence,
104121
- translation.forward,
104122
- translation
104138
+ expandedRange.forward,
104139
+ expandedRange
104123
104140
  );
104124
104141
  }
104125
- return translation;
104142
+ return expandedRange;
104126
104143
  });
104127
104144
  }
104128
104145
  if (annotationsAsObjects) {
@@ -113235,6 +113252,160 @@ ${latestSubscriptionCallbackError.current.stack}
113235
113252
  }
113236
113253
  }
113237
113254
  __name(calculateNebTm, "calculateNebTm");
113255
+ const PRIMER3_PARAMS = {
113256
+ saltMonovalent: 50,
113257
+ // mM
113258
+ saltDivalent: 1.5,
113259
+ // mM
113260
+ dntpConc: 0.6,
113261
+ // mM
113262
+ dnaConc: 50,
113263
+ // nM
113264
+ R: 1.987
113265
+ // Gas constant (cal/K·mol)
113266
+ };
113267
+ const SANTA_LUCIA_NN = {
113268
+ AA: { dH: -7.9, dS: -22.2 },
113269
+ TT: { dH: -7.9, dS: -22.2 },
113270
+ AT: { dH: -7.2, dS: -20.4 },
113271
+ TA: { dH: -7.2, dS: -21.3 },
113272
+ CA: { dH: -8.5, dS: -22.7 },
113273
+ TG: { dH: -8.5, dS: -22.7 },
113274
+ GT: { dH: -8.4, dS: -22.4 },
113275
+ AC: { dH: -8.4, dS: -22.4 },
113276
+ CT: { dH: -7.8, dS: -21 },
113277
+ AG: { dH: -7.8, dS: -21 },
113278
+ GA: { dH: -8.2, dS: -22.2 },
113279
+ TC: { dH: -8.2, dS: -22.2 },
113280
+ CG: { dH: -10.6, dS: -27.2 },
113281
+ GC: { dH: -9.8, dS: -24.4 },
113282
+ GG: { dH: -8, dS: -19.9 },
113283
+ CC: { dH: -8, dS: -19.9 }
113284
+ };
113285
+ const SANTA_LUCIA_INIT = {
113286
+ GC: { dH: 0.1, dS: -2.8 },
113287
+ // initiation with terminal GC
113288
+ AT: { dH: 2.3, dS: 4.1 }
113289
+ // initiation with terminal AT
113290
+ };
113291
+ function getEffectiveMonovalentConc() {
113292
+ let effectiveMono = PRIMER3_PARAMS.saltMonovalent;
113293
+ {
113294
+ const freeMg = Math.max(
113295
+ 0,
113296
+ PRIMER3_PARAMS.saltDivalent - PRIMER3_PARAMS.dntpConc
113297
+ );
113298
+ effectiveMono += 120 * Math.sqrt(freeMg);
113299
+ }
113300
+ return effectiveMono;
113301
+ }
113302
+ __name(getEffectiveMonovalentConc, "getEffectiveMonovalentConc");
113303
+ function applySaltCorrection(deltaS, nnPairs) {
113304
+ const effectiveMono = getEffectiveMonovalentConc();
113305
+ return deltaS + 0.368 * nnPairs * Math.log(effectiveMono / 1e3);
113306
+ }
113307
+ __name(applySaltCorrection, "applySaltCorrection");
113308
+ function isValidSequence(sequence2) {
113309
+ return /^[ATGCN]+$/.test(sequence2);
113310
+ }
113311
+ __name(isValidSequence, "isValidSequence");
113312
+ function calculateSantaLuciaTm(sequence2) {
113313
+ try {
113314
+ sequence2 = sequence2 == null ? void 0 : sequence2.toUpperCase().trim();
113315
+ if (!isValidSequence(sequence2)) {
113316
+ throw new Error("Invalid sequence: contains non-DNA characters");
113317
+ }
113318
+ if (sequence2.length < 2) {
113319
+ throw new Error("Sequence too short: minimum length is 2 bases");
113320
+ }
113321
+ let deltaH = 0;
113322
+ let deltaS = 0;
113323
+ for (let i2 = 0; i2 < sequence2.length - 1; i2++) {
113324
+ const dinucleotide = sequence2.substring(i2, i2 + 2);
113325
+ if (dinucleotide.includes("N")) {
113326
+ continue;
113327
+ }
113328
+ const params = SANTA_LUCIA_NN[dinucleotide];
113329
+ if (params) {
113330
+ deltaH += params.dH;
113331
+ deltaS += params.dS;
113332
+ }
113333
+ }
113334
+ const firstBase = sequence2[0];
113335
+ const lastBase = sequence2[sequence2.length - 1];
113336
+ if (firstBase === "G" || firstBase === "C") {
113337
+ deltaH += SANTA_LUCIA_INIT.GC.dH;
113338
+ deltaS += SANTA_LUCIA_INIT.GC.dS;
113339
+ } else {
113340
+ deltaH += SANTA_LUCIA_INIT.AT.dH;
113341
+ deltaS += SANTA_LUCIA_INIT.AT.dS;
113342
+ }
113343
+ if (lastBase === "G" || lastBase === "C") {
113344
+ deltaH += SANTA_LUCIA_INIT.GC.dH;
113345
+ deltaS += SANTA_LUCIA_INIT.GC.dS;
113346
+ } else {
113347
+ deltaH += SANTA_LUCIA_INIT.AT.dH;
113348
+ deltaS += SANTA_LUCIA_INIT.AT.dS;
113349
+ }
113350
+ const nnPairs = sequence2.length - 1;
113351
+ deltaS = applySaltCorrection(deltaS, nnPairs);
113352
+ const C = PRIMER3_PARAMS.dnaConc * 1e-9;
113353
+ const Tm = deltaH * 1e3 / (deltaS + PRIMER3_PARAMS.R * Math.log(C / 4));
113354
+ return Tm - 273.15;
113355
+ } catch (e2) {
113356
+ return `Error calculating Tm for sequence ${sequence2}. ${e2}`;
113357
+ }
113358
+ }
113359
+ __name(calculateSantaLuciaTm, "calculateSantaLuciaTm");
113360
+ function calculateEndStability(sequence2) {
113361
+ try {
113362
+ sequence2 = sequence2 == null ? void 0 : sequence2.toUpperCase().trim();
113363
+ if (!isValidSequence(sequence2)) {
113364
+ throw new Error("Invalid sequence: contains non-DNA characters");
113365
+ }
113366
+ if (sequence2.length < 5) {
113367
+ throw new Error(
113368
+ "Sequence too short: minimum length is 5 bases for end stability calculation"
113369
+ );
113370
+ }
113371
+ const last5Bases = sequence2.substring(sequence2.length - 5);
113372
+ let deltaH = 0;
113373
+ let deltaS = 0;
113374
+ for (let i2 = 0; i2 < 4; i2++) {
113375
+ const dinucleotide = last5Bases.substring(i2, i2 + 2);
113376
+ if (dinucleotide.includes("N")) {
113377
+ continue;
113378
+ }
113379
+ const params = SANTA_LUCIA_NN[dinucleotide];
113380
+ if (params) {
113381
+ deltaH += params.dH;
113382
+ deltaS += params.dS;
113383
+ }
113384
+ }
113385
+ const firstBase = last5Bases[0];
113386
+ const lastBase = last5Bases[last5Bases.length - 1];
113387
+ if (firstBase === "G" || firstBase === "C") {
113388
+ deltaH += SANTA_LUCIA_INIT.GC.dH;
113389
+ deltaS += SANTA_LUCIA_INIT.GC.dS;
113390
+ } else {
113391
+ deltaH += SANTA_LUCIA_INIT.AT.dH;
113392
+ deltaS += SANTA_LUCIA_INIT.AT.dS;
113393
+ }
113394
+ if (lastBase === "G" || lastBase === "C") {
113395
+ deltaH += SANTA_LUCIA_INIT.GC.dH;
113396
+ deltaS += SANTA_LUCIA_INIT.GC.dS;
113397
+ } else {
113398
+ deltaH += SANTA_LUCIA_INIT.AT.dH;
113399
+ deltaS += SANTA_LUCIA_INIT.AT.dS;
113400
+ }
113401
+ const T2 = 310.15;
113402
+ const deltaG = deltaH - T2 * deltaS / 1e3;
113403
+ return Math.round(Math.abs(deltaG) * 100) / 100;
113404
+ } catch (e2) {
113405
+ return `Error calculating end stability for sequence ${sequence2}. ${e2}`;
113406
+ }
113407
+ }
113408
+ __name(calculateEndStability, "calculateEndStability");
113238
113409
  function convertAACaretPositionOrRangeToDna(rangeOrCaret) {
113239
113410
  if (typeof rangeOrCaret === "object" && rangeOrCaret !== null) {
113240
113411
  return convertAARangeToDnaRange(__spreadProps(__spreadValues({}, rangeOrCaret), {
@@ -125958,32 +126129,6 @@ ${seq.sequence}
125958
126129
  (state2) => state2.useAdditionalOrfStartCodons,
125959
126130
  findOrfsInPlasmid
125960
126131
  );
125961
- var forEach_1;
125962
- var hasRequiredForEach;
125963
- function requireForEach() {
125964
- if (hasRequiredForEach) return forEach_1;
125965
- hasRequiredForEach = 1;
125966
- var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
125967
- function forEach2(collection, iteratee) {
125968
- var func = isArray2(collection) ? arrayEach2 : baseEach2;
125969
- return func(collection, castFunction2(iteratee));
125970
- }
125971
- __name(forEach2, "forEach");
125972
- forEach_1 = forEach2;
125973
- return forEach_1;
125974
- }
125975
- __name(requireForEach, "requireForEach");
125976
- var each$1;
125977
- var hasRequiredEach;
125978
- function requireEach() {
125979
- if (hasRequiredEach) return each$1;
125980
- hasRequiredEach = 1;
125981
- each$1 = requireForEach();
125982
- return each$1;
125983
- }
125984
- __name(requireEach, "requireEach");
125985
- var eachExports = requireEach();
125986
- const each = /* @__PURE__ */ getDefaultExportFromCjs(eachExports);
125987
126132
  function translationsRawSelector(sequenceData2) {
125988
126133
  return sequenceData2.translations;
125989
126134
  }
@@ -126150,14 +126295,22 @@ ${seq.sequence}
126150
126295
  },
126151
126296
  {}
126152
126297
  ));
126153
- each(translationsToPass, function(translation) {
126154
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
126298
+ return mapValues$1(translationsToPass, (translation) => {
126299
+ var _a2, _b2;
126300
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
126301
+ const expandedRange = expandOrContractRangeByLength(
126302
+ translation,
126303
+ -codonStart,
126304
+ true,
126305
+ sequence2.length
126306
+ );
126307
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
126155
126308
  sequence2,
126156
- translation.forward,
126157
- translation
126309
+ expandedRange.forward,
126310
+ expandedRange
126158
126311
  );
126312
+ return expandedRange;
126159
126313
  });
126160
- return translationsToPass;
126161
126314
  }
126162
126315
  __name(translationsSelector, "translationsSelector");
126163
126316
  const translationsSelector$1 = createSelector(
@@ -138033,6 +138186,21 @@ ${seq.sequence}
138033
138186
  );
138034
138187
  }
138035
138188
  __name(Orf, "Orf");
138189
+ var forEach_1;
138190
+ var hasRequiredForEach;
138191
+ function requireForEach() {
138192
+ if (hasRequiredForEach) return forEach_1;
138193
+ hasRequiredForEach = 1;
138194
+ var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
138195
+ function forEach2(collection, iteratee) {
138196
+ var func = isArray2(collection) ? arrayEach2 : baseEach2;
138197
+ return func(collection, castFunction2(iteratee));
138198
+ }
138199
+ __name(forEach2, "forEach");
138200
+ forEach_1 = forEach2;
138201
+ return forEach_1;
138202
+ }
138203
+ __name(requireForEach, "requireForEach");
138036
138204
  var forEachExports = requireForEach();
138037
138205
  const forEach = /* @__PURE__ */ getDefaultExportFromCjs(forEachExports);
138038
138206
  var lib = {};
@@ -144738,7 +144906,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
144738
144906
  input.click();
144739
144907
  }
144740
144908
  __name(showFileDialog, "showFileDialog");
144741
- const version = "0.8.17";
144909
+ const version = "0.8.19";
144742
144910
  const packageJson = {
144743
144911
  version
144744
144912
  };
@@ -150788,6 +150956,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
150788
150956
  RowItem$1,
150789
150957
  __spreadProps(__spreadValues({}, __spreadValues(__spreadProps(__spreadValues({}, rest), {
150790
150958
  editorName,
150959
+ showAminoAcidUnitAsCodon,
150791
150960
  onScroll: /* @__PURE__ */ __name(() => {
150792
150961
  this.easyStore.viewportWidth = width;
150793
150962
  const row = this.linearView.querySelector(".veRowItemWrapper");
@@ -163835,7 +164004,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
163835
164004
  /* , setMonovalentCationConc */
163836
164005
  ] = React.useState(0.05);
163837
164006
  const [tmType, setTmType] = useTmType();
163838
- let tm = (tmType === "neb_tm" ? calculateNebTm : calculateTm)(sequence2, {
164007
+ let tm = (tmType === "neb_tm" ? calculateNebTm : tmType === "default" ? calculateSantaLuciaTm : calculateTm)(sequence2, {
163839
164008
  monovalentCationConc,
163840
164009
  primerConc
163841
164010
  });
@@ -163860,8 +164029,9 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
163860
164029
  {
163861
164030
  label: "Choose Tm Type:",
163862
164031
  options: [
163863
- { value: "default", label: "Default Tm (Breslauer)" },
163864
- { value: "neb_tm", label: "NEB Tm (SantaLucia)" }
164032
+ { value: "default", label: "Santa Lucia (Default)" },
164033
+ { value: "breslauer", label: "Breslauer" },
164034
+ { value: "neb_tm", label: "NEB Tm" }
163865
164035
  ],
163866
164036
  onChange: /* @__PURE__ */ __name((e2) => setTmType(e2.target.value), "onChange"),
163867
164037
  selectedValue: tmType
@@ -163875,7 +164045,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
163875
164045
  }
163876
164046
  ), hasWarning, /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("br", null), "Try using the Default Tm"))
163877
164047
  },
163878
- /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InnerWrapper, null, "Melting Temp: ", Number(tm) || 0, " "), hasWarning && /* @__PURE__ */ React.createElement(
164048
+ /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InnerWrapper, null, "Melting Temp: ", Number(tm) || 0, "°C"), hasWarning && /* @__PURE__ */ React.createElement(
163879
164049
  Icon,
163880
164050
  {
163881
164051
  style: { marginLeft: 5, marginRight: 5 },
@@ -164139,12 +164309,24 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
164139
164309
  )), /* @__PURE__ */ React.createElement(
164140
164310
  MeltingTemp,
164141
164311
  {
164142
- InnerWrapper: InnerWrapperMeltingTemp,
164312
+ InnerWrapper: TextInnerWrapper,
164143
164313
  sequence: bases
164144
164314
  }
164145
- ))
164315
+ ), /* @__PURE__ */ React.createElement(TextInnerWrapper, null, "GC content: ", bases && calculatePercentGC(bases).toFixed(1), "%"), /* @__PURE__ */ React.createElement(TextInnerWrapper, null, "3' Stability: ", bases && calculateEndStability(bases), " kcal/mol"))
164146
164316
  );
164147
164317
  }, "RenderBases");
164318
+ const TextInnerWrapper = /* @__PURE__ */ __name((p2) => /* @__PURE__ */ React.createElement(
164319
+ "div",
164320
+ {
164321
+ className: "bp3-text-muted bp3-text-small",
164322
+ style: {
164323
+ marginBottom: 15,
164324
+ marginTop: -5,
164325
+ fontStyle: "italic"
164326
+ }
164327
+ },
164328
+ p2.children
164329
+ ), "TextInnerWrapper");
164148
164330
  const AddOrEditPrimerDialog = AddOrEditAnnotationDialog$1({
164149
164331
  formName: "AddOrEditPrimerDialog",
164150
164332
  getProps: /* @__PURE__ */ __name((props) => ({
@@ -164153,14 +164335,6 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
164153
164335
  RenderBases
164154
164336
  }), "getProps")
164155
164337
  });
164156
- const InnerWrapperMeltingTemp = /* @__PURE__ */ __name((p2) => /* @__PURE__ */ React.createElement(
164157
- "div",
164158
- {
164159
- className: "bp3-text-muted bp3-text-small",
164160
- style: { marginBottom: 15, marginTop: -5, fontStyle: "italic" }
164161
- },
164162
- p2.children
164163
- ), "InnerWrapperMeltingTemp");
164164
164338
  const Dialogs = {
164165
164339
  RenameSequenceDialog,
164166
164340
  PrintDialog: PrintDialog$1,
@@ -164592,7 +164766,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
164592
164766
  item: selection && selection.start > -1 ? /* @__PURE__ */ React.createElement("span", null, selection.start + 1, " - ", selection.end + 1) : /* @__PURE__ */ React.createElement("span", null, "1 - ", isProtein2 ? proteinSize : size2),
164593
164767
  title: "Region"
164594
164768
  }
164595
- )), /* @__PURE__ */ React.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Amino Acid"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
164769
+ )), /* @__PURE__ */ React.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, isProtein2 ? "Amino Acid" : "Base"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
164596
164770
  return /* @__PURE__ */ React.createElement("div", { className: `sidebar-row property-amino-acid-${idx}` }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, aa, " ", isProtein2 ? `(${aminoAcidShortNames[aa]})` : ""), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.count), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.percentage.toFixed(1), "%"));
164597
164771
  })));
164598
164772
  } else {
@@ -165092,7 +165266,11 @@ ${seqDataToCopy}\r
165092
165266
  }, [alignmentTracks, id2, store2]);
165093
165267
  reactExports.useEffect(() => {
165094
165268
  const handleAlignmentCopy = /* @__PURE__ */ __name((event) => {
165269
+ var _a3, _b2, _c2;
165095
165270
  if (event.key === "c" && !event.shiftKey && (event.metaKey === true || event.ctrlKey === true)) {
165271
+ if (!((_a3 = document.activeElement) == null ? void 0 : _a3.classList.contains("alignmentView"))) {
165272
+ return;
165273
+ }
165096
165274
  const input = document.createElement("textarea");
165097
165275
  document.body.appendChild(input);
165098
165276
  const seqDataToCopy = getAllAlignmentsFastaText();
@@ -165106,6 +165284,8 @@ ${seqDataToCopy}\r
165106
165284
  }
165107
165285
  document.body.removeChild(input);
165108
165286
  event.preventDefault();
165287
+ (_b2 = document.activeElement) == null ? void 0 : _b2.blur();
165288
+ (_c2 = document.querySelector(".alignmentView")) == null ? void 0 : _c2.focus();
165109
165289
  }
165110
165290
  }, "handleAlignmentCopy");
165111
165291
  document.addEventListener("keydown", handleAlignmentCopy);
@@ -166264,6 +166444,7 @@ ${seqDataToCopy}\r
166264
166444
  position: "relative",
166265
166445
  overflowY: "auto"
166266
166446
  }, style2),
166447
+ tabIndex: 0,
166267
166448
  className: "alignmentView"
166268
166449
  },
166269
166450
  /* @__PURE__ */ React.createElement(
package/ove.css CHANGED
@@ -11260,6 +11260,12 @@ path.partWithSelectedTag {
11260
11260
  height: 100% !important;
11261
11261
  overflow: hidden;
11262
11262
  }
11263
+ .alignmentView .veAlignmentSelectionLayer.veRowViewSelectionLayer {
11264
+ background: gray;
11265
+ }
11266
+ .alignmentView:focus .veAlignmentSelectionLayer.veRowViewSelectionLayer {
11267
+ background: #0099ff;
11268
+ }
11263
11269
  .alignmentView .veSelectionLayer {
11264
11270
  top: 0;
11265
11271
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teselagen/ove",
3
- "version": "0.8.18",
3
+ "version": "0.8.20",
4
4
  "main": "./src/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,7 +18,7 @@
18
18
  "@teselagen/file-utils": "0.3.20",
19
19
  "@teselagen/range-utils": "0.3.13",
20
20
  "@teselagen/react-list": "0.8.18",
21
- "@teselagen/sequence-utils": "0.3.35",
21
+ "@teselagen/sequence-utils": "0.3.36",
22
22
  "@teselagen/ui": "0.10.9",
23
23
  "@use-gesture/react": "10.3.0",
24
24
  "biomsa": "^0.2.4",
@@ -1,4 +1,6 @@
1
- declare const _default: ((state: any) => any) & import('reselect').OutputSelectorFields<(args_0: any, args_1: unknown, args_2: any, args_3: {
1
+ declare const _default: ((state: any) => {
2
+ [x: string]: any;
3
+ }) & import('reselect').OutputSelectorFields<(args_0: any, args_1: unknown, args_2: any, args_3: {
2
4
  start: number;
3
5
  end: number;
4
6
  length: number;
@@ -8,7 +10,9 @@ declare const _default: ((state: any) => any) & import('reselect').OutputSelecto
8
10
  annotationTypePlural: string;
9
11
  isOrf: boolean;
10
12
  id: any;
11
- }[], args_4: any, args_5: any, args_6: any[], args_7: any, args_8: any, args_9: any, args_10: any, args_11: any, args_12: any) => any, {
13
+ }[], args_4: any, args_5: any, args_6: any[], args_7: any, args_8: any, args_9: any, args_10: any, args_11: any, args_12: any) => {
14
+ [x: string]: any;
15
+ }, {
12
16
  clearCache: () => void;
13
17
  }> & {
14
18
  clearCache: () => void;
@@ -211,6 +211,9 @@ export const AlignmentView = props => {
211
211
  !event.shiftKey &&
212
212
  (event.metaKey === true || event.ctrlKey === true)
213
213
  ) {
214
+ if (!document.activeElement?.classList.contains("alignmentView")) {
215
+ return; //stop early if we're not focused on the alignment view
216
+ }
214
217
  const input = document.createElement("textarea");
215
218
  document.body.appendChild(input);
216
219
  const seqDataToCopy = getAllAlignmentsFastaText();
@@ -224,6 +227,8 @@ export const AlignmentView = props => {
224
227
  }
225
228
  document.body.removeChild(input);
226
229
  event.preventDefault();
230
+ document.activeElement?.blur();
231
+ document.querySelector(".alignmentView")?.focus();
227
232
  }
228
233
  };
229
234
 
@@ -1584,6 +1589,7 @@ export const AlignmentView = props => {
1584
1589
  ...style
1585
1590
  // borderTop: "1px solid black"
1586
1591
  }}
1592
+ tabIndex={0}
1587
1593
  className="alignmentView"
1588
1594
  >
1589
1595
  <DragDropContext
@@ -73,6 +73,12 @@
73
73
  height: 100% !important;
74
74
  overflow: hidden;
75
75
  }
76
+ .alignmentView .veAlignmentSelectionLayer.veRowViewSelectionLayer {
77
+ background: gray;
78
+ }
79
+ .alignmentView:focus .veAlignmentSelectionLayer.veRowViewSelectionLayer {
80
+ background: #0099ff;
81
+ }
76
82
  .alignmentView .veSelectionLayer {
77
83
  top: 0;
78
84
  }
@@ -327,6 +327,7 @@ class _LinearView extends React.Component {
327
327
  {...{
328
328
  ...rest,
329
329
  editorName,
330
+ showAminoAcidUnitAsCodon,
330
331
  onScroll: () => {
331
332
  this.easyStore.viewportWidth = width;
332
333
  const row =
@@ -149,7 +149,9 @@ export default ({ properties, setProperties, style }) => {
149
149
  <h5>{isProtein ? "Amino Acid" : "Base Pair"} Frequencies</h5>
150
150
  <div className="sidebar-table">
151
151
  <div className="sidebar-row">
152
- <div className="sidebar-cell">Amino Acid</div>
152
+ <div className="sidebar-cell">
153
+ {isProtein ? "Amino Acid" : "Base"}
154
+ </div>
153
155
  <div className="sidebar-cell">Count</div>
154
156
  <div className="sidebar-cell">Percentage</div>
155
157
  </div>
@@ -1,7 +1,11 @@
1
1
  import React from "react";
2
2
  import { Button, Icon, Popover, RadioGroup } from "@blueprintjs/core";
3
3
 
4
- import { calculateTm, calculateNebTm } from "@teselagen/sequence-utils";
4
+ import {
5
+ calculateTm,
6
+ calculateNebTm,
7
+ calculateSantaLuciaTm
8
+ } from "@teselagen/sequence-utils";
5
9
 
6
10
  import { isNumber, isString } from "lodash-es";
7
11
  import { popoverOverflowModifiers } from "@teselagen/ui";
@@ -20,7 +24,13 @@ export default function MeltingTemp({
20
24
  const [monovalentCationConc /* , setMonovalentCationConc */] =
21
25
  React.useState(0.05);
22
26
  const [tmType, setTmType] = useTmType();
23
- let tm = (tmType === "neb_tm" ? calculateNebTm : calculateTm)(sequence, {
27
+ let tm = (
28
+ tmType === "neb_tm"
29
+ ? calculateNebTm
30
+ : tmType === "default"
31
+ ? calculateSantaLuciaTm
32
+ : calculateTm
33
+ )(sequence, {
24
34
  monovalentCationConc,
25
35
  primerConc
26
36
  });
@@ -47,8 +57,9 @@ export default function MeltingTemp({
47
57
  <RadioGroup
48
58
  label="Choose Tm Type:"
49
59
  options={[
50
- { value: "default", label: "Default Tm (Breslauer)" },
51
- { value: "neb_tm", label: "NEB Tm (SantaLucia)" }
60
+ { value: "default", label: "Santa Lucia (Default)" },
61
+ { value: "breslauer", label: "Breslauer" },
62
+ { value: "neb_tm", label: "NEB Tm" }
52
63
  ]}
53
64
  onChange={e => setTmType(e.target.value)}
54
65
  selectedValue={tmType}
@@ -70,7 +81,7 @@ export default function MeltingTemp({
70
81
  }
71
82
  >
72
83
  <React.Fragment>
73
- <InnerWrapper>Melting Temp: {Number(tm) || 0} </InnerWrapper>
84
+ <InnerWrapper>Melting Temp: {Number(tm) || 0}°C</InnerWrapper>
74
85
  {hasWarning && (
75
86
  <Icon
76
87
  style={{ marginLeft: 5, marginRight: 5 }}
@@ -8,7 +8,9 @@ import {
8
8
  } from "@teselagen/ui";
9
9
  import {
10
10
  filterSequenceString,
11
- getReverseComplementSequenceString
11
+ getReverseComplementSequenceString,
12
+ calculatePercentGC,
13
+ calculateEndStability
12
14
  } from "@teselagen/sequence-utils";
13
15
 
14
16
  import AddOrEditAnnotationDialog from "../AddOrEditAnnotationDialog";
@@ -294,15 +296,34 @@ const RenderBases = props => {
294
296
  </AdvancedOptions>
295
297
 
296
298
  <MeltingTemp
297
- InnerWrapper={InnerWrapperMeltingTemp}
299
+ InnerWrapper={TextInnerWrapper}
298
300
  sequence={bases}
299
301
  ></MeltingTemp>
302
+ <TextInnerWrapper>
303
+ GC content: {bases && calculatePercentGC(bases).toFixed(1)}%
304
+ </TextInnerWrapper>
305
+ <TextInnerWrapper>
306
+ 3' Stability: {bases && calculateEndStability(bases)} kcal/mol
307
+ </TextInnerWrapper>
300
308
  </div>
301
309
  )}
302
310
  </div>
303
311
  );
304
312
  };
305
313
 
314
+ const TextInnerWrapper = p => (
315
+ <div
316
+ className="bp3-text-muted bp3-text-small"
317
+ style={{
318
+ marginBottom: 15,
319
+ marginTop: -5,
320
+ fontStyle: "italic"
321
+ }}
322
+ >
323
+ {p.children}
324
+ </div>
325
+ );
326
+
306
327
  export default AddOrEditAnnotationDialog({
307
328
  formName: "AddOrEditPrimerDialog",
308
329
  getProps: props => ({
@@ -311,12 +332,3 @@ export default AddOrEditAnnotationDialog({
311
332
  RenderBases
312
333
  })
313
334
  });
314
-
315
- const InnerWrapperMeltingTemp = p => (
316
- <div
317
- className="bp3-text-muted bp3-text-small"
318
- style={{ marginBottom: 15, marginTop: -5, fontStyle: "italic" }}
319
- >
320
- {p.children}
321
- </div>
322
- );