@datagrok/sequence-translator 1.3.2 → 1.3.4
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/CHANGELOG.md +12 -0
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +1 -1
- package/src/apps/pattern/view/svg-utils/strands-block.ts +98 -7
- package/src/apps/pattern/view/svg-utils/svg-block-base.ts +4 -12
- package/src/package.ts +2 -1
- package/src/polytool/pt-conversion.ts +11 -7
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {NUCLEOTIDES} from '../../../common/model/const';
|
|
2
|
-
import {STRAND, STRANDS, TERMINUS} from '../../model/const';
|
|
2
|
+
import {STRAND, STRANDS, TERMINI, TERMINUS} from '../../model/const';
|
|
3
3
|
import {PatternConfiguration} from '../../model/types';
|
|
4
4
|
import {isOverhangNucleotide} from '../../model/utils';
|
|
5
5
|
import {SVG_CIRCLE_SIZES, SVG_ELEMENT_COLORS, SVG_TEXT_FONT_SIZES} from './const';
|
|
@@ -19,6 +19,7 @@ const RIGHT_LABEL_WIDTH = 20;
|
|
|
19
19
|
export class StrandsBlock extends SVGBlockBase {
|
|
20
20
|
private strands: SVGBlockBase[];
|
|
21
21
|
private labels: SVGBlockBase[];
|
|
22
|
+
private terminalModifications: SVGBlockBase[];
|
|
22
23
|
constructor(
|
|
23
24
|
svgElementFactory: SVGElementFactory,
|
|
24
25
|
config: PatternConfiguration,
|
|
@@ -30,16 +31,22 @@ export class StrandsBlock extends SVGBlockBase {
|
|
|
30
31
|
this.strands = strandTypes
|
|
31
32
|
.map((strand) => new SingleStrandBlock(this.svgElementFactory, config, yShift, strand));
|
|
32
33
|
|
|
34
|
+
|
|
35
|
+
this.terminalModifications = strandTypes.map(
|
|
36
|
+
(strandType, idx) =>
|
|
37
|
+
new TerminalModificationLabels(this.svgElementFactory, config, yShift, strandType, this.strands[idx] as SingleStrandBlock)
|
|
38
|
+
);
|
|
33
39
|
this.labels = strandTypes.map(
|
|
34
40
|
(strandType, idx) =>
|
|
35
|
-
new StrandLabel(this.svgElementFactory, config, yShift, strandType, this.
|
|
41
|
+
new StrandLabel(this.svgElementFactory, config, yShift, strandType, this.terminalModifications[idx] as TerminalModificationLabels)
|
|
36
42
|
);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
get svgElements(): SVGElement[] {
|
|
40
46
|
const elements = [
|
|
41
47
|
...this.strands,
|
|
42
|
-
...this.
|
|
48
|
+
...this.terminalModifications,
|
|
49
|
+
...this.labels,
|
|
43
50
|
].map((block) => block.svgElements).flat();
|
|
44
51
|
return elements;
|
|
45
52
|
}
|
|
@@ -255,11 +262,10 @@ class StrandLabel extends SVGBlockBase {
|
|
|
255
262
|
protected config: PatternConfiguration,
|
|
256
263
|
protected yShift: number,
|
|
257
264
|
private strand: STRAND,
|
|
258
|
-
private
|
|
265
|
+
private terminalModifications: TerminalModificationLabels
|
|
259
266
|
) {
|
|
260
267
|
super(svgElementFactory, config, yShift);
|
|
261
268
|
this._svgElements = this.createSVGElements();
|
|
262
|
-
// this.strandSvgWrapper.shiftElements({x: this.getLeftLabelWidth(), y: 0});
|
|
263
269
|
}
|
|
264
270
|
|
|
265
271
|
private createSVGElements(): SVGElement[] {
|
|
@@ -300,7 +306,7 @@ class StrandLabel extends SVGBlockBase {
|
|
|
300
306
|
const text = ` ${terminus}`;
|
|
301
307
|
const textDimensions = TextDimensionsCalculator.getTextDimensions(text, SVG_TEXT_FONT_SIZES.NUCLEOBASE);
|
|
302
308
|
const position = {
|
|
303
|
-
x: SENSE_STRAND_HORIZONTAL_SHIFT + this.
|
|
309
|
+
x: SENSE_STRAND_HORIZONTAL_SHIFT + this.terminalModifications.getContentWidth() + 5,
|
|
304
310
|
y: getStrandCircleYShift(this.strand, this.yShift) + textDimensions.height / 3
|
|
305
311
|
};
|
|
306
312
|
|
|
@@ -317,7 +323,92 @@ class StrandLabel extends SVGBlockBase {
|
|
|
317
323
|
}
|
|
318
324
|
|
|
319
325
|
getContentWidth(): number {
|
|
320
|
-
return this.
|
|
326
|
+
return this.terminalModifications.getContentWidth() + this.getLeftLabelWidth() +
|
|
327
|
+
this.getRightLabelWidth() + SENSE_STRAND_PADDING;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
getContentHeight(): number {
|
|
331
|
+
return this.terminalModifications.getContentHeight();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
class TerminalModificationLabels extends SVGBlockBase {
|
|
336
|
+
private _svgElements: SVGElement[];
|
|
337
|
+
constructor(
|
|
338
|
+
protected svgElementFactory: SVGElementFactory,
|
|
339
|
+
protected config: PatternConfiguration,
|
|
340
|
+
protected yShift: number,
|
|
341
|
+
private strand: STRAND,
|
|
342
|
+
private strandSvgWrapper: SingleStrandBlock
|
|
343
|
+
) {
|
|
344
|
+
super(svgElementFactory, config, yShift);
|
|
345
|
+
this._svgElements = this.createSVGElements();
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private createSVGElements(): SVGElement[] {
|
|
349
|
+
const elements = this.createTerminalModifications();
|
|
350
|
+
return elements;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private getTerminalModification(terminus: TERMINUS): string {
|
|
354
|
+
const terminalModification = this.config.strandTerminusModifications[this.strand][terminus];
|
|
355
|
+
return terminalModification;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
private getTerminalModificationTextDimensions(terminus: TERMINUS): {width: number, height: number} {
|
|
359
|
+
const terminalModification = this.getTerminalModification(terminus);
|
|
360
|
+
const textDimensions = TextDimensionsCalculator
|
|
361
|
+
.getTextDimensions(terminalModification, SVG_TEXT_FONT_SIZES.NUCLEOBASE);
|
|
362
|
+
return textDimensions;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private getLeftTerminus(): TERMINUS {
|
|
366
|
+
return this.strand === STRAND.SENSE ? TERMINUS.FIVE_PRIME : TERMINUS.THREE_PRIME;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private createTerminalModification(terminus: TERMINUS): SVGTextElement {
|
|
370
|
+
const terminalModification = this.getTerminalModification(terminus);
|
|
371
|
+
const dimensions = this.getTerminalModificationTextDimensions(terminus);
|
|
372
|
+
|
|
373
|
+
const isLeft = terminus === this.getLeftTerminus();
|
|
374
|
+
const xShift = isLeft ? SENSE_STRAND_HORIZONTAL_SHIFT :
|
|
375
|
+
SENSE_STRAND_HORIZONTAL_SHIFT +
|
|
376
|
+
this.getTerminalModificationTextDimensions(this.getLeftTerminus()).width +
|
|
377
|
+
this.strandSvgWrapper.getContentWidth();
|
|
378
|
+
const position = {
|
|
379
|
+
x: xShift,
|
|
380
|
+
y: getStrandCircleYShift(this.strand, this.yShift) + dimensions.height / 3
|
|
381
|
+
};
|
|
382
|
+
if (isLeft) {
|
|
383
|
+
this.strandSvgWrapper.shiftElements({
|
|
384
|
+
x: dimensions.width,
|
|
385
|
+
y: 0
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return this.svgElementFactory.createTextElement(
|
|
390
|
+
terminalModification,
|
|
391
|
+
position,
|
|
392
|
+
SVG_TEXT_FONT_SIZES.NUCLEOBASE,
|
|
393
|
+
SVG_ELEMENT_COLORS.MODIFICATION_TEXT
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private createTerminalModifications(): SVGTextElement[] {
|
|
398
|
+
const termini = (this.strand === STRAND.ANTISENSE) ? TERMINI : Array.from(TERMINI).reverse();
|
|
399
|
+
const textElements = termini.map((terminus) => this.createTerminalModification(terminus));
|
|
400
|
+
return textElements;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
get svgElements(): SVGElement[] {
|
|
404
|
+
return this._svgElements;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
getContentWidth(): number {
|
|
408
|
+
return this.strandSvgWrapper.getContentWidth() +
|
|
409
|
+
TERMINI
|
|
410
|
+
.map((terminus) => this.getTerminalModificationTextDimensions(terminus).width)
|
|
411
|
+
.reduce((acc, curr) => acc += curr, 0);
|
|
321
412
|
}
|
|
322
413
|
|
|
323
414
|
getContentHeight(): number {
|
|
@@ -17,21 +17,13 @@ export abstract class SVGBlockBase {
|
|
|
17
17
|
shiftElements(shift: {x: number, y: number}): void {
|
|
18
18
|
this.svgElements.forEach((element) => {
|
|
19
19
|
const transform = element.getAttribute('transform') || '';
|
|
20
|
-
const match = transform.match(/translate\(([^,]+),([^,]+)\)/);
|
|
21
|
-
const x = match ? parseFloat(match[1]) : 0;
|
|
22
|
-
const y = match ? parseFloat(match[2]) : 0;
|
|
23
|
-
const newTransform = `translate(${
|
|
20
|
+
// const match = transform.match(/translate\(([^,]+),([^,]+)\)/);
|
|
21
|
+
// const x = match ? parseFloat(match[1]) : 0;
|
|
22
|
+
// const y = match ? parseFloat(match[2]) : 0;
|
|
23
|
+
const newTransform = `translate(${shift.x},${shift.y})`;
|
|
24
24
|
element.setAttribute('transform', `${transform} ${newTransform}`);
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
adjustContentWithinGlobalContainer(globalWidth: number): void {
|
|
29
|
-
const contentWidth = this.getContentWidth();
|
|
30
|
-
if (contentWidth < globalWidth) {
|
|
31
|
-
const shift = (globalWidth - contentWidth) / 2;
|
|
32
|
-
this.shiftElements({x: shift, y: 0});
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
28
|
abstract getContentWidth(): number;
|
|
37
29
|
}
|
package/src/package.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import DG from 'datagrok-api/dg';
|
|
2
1
|
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
4
|
|
|
4
5
|
import {MonomerLibWrapper} from './apps/common/model/monomer-lib/lib-wrapper';
|
|
5
6
|
import {OligoToolkitPackage} from './apps/common/model/oligo-toolkit-package';
|
|
@@ -268,8 +268,12 @@ export class Chain {
|
|
|
268
268
|
function getHelms(sequences: string[], rules: Rules): string[] {
|
|
269
269
|
const helms = new Array<string>(sequences.length);
|
|
270
270
|
for (let i = 0; i < sequences.length; i++) {
|
|
271
|
-
|
|
272
|
-
|
|
271
|
+
if (sequences[i] === undefined)
|
|
272
|
+
helms[i] = '';
|
|
273
|
+
else {
|
|
274
|
+
const chain = Chain.fromNotation(sequences[i], rules);
|
|
275
|
+
helms[i] = chain.getHelm();
|
|
276
|
+
}
|
|
273
277
|
}
|
|
274
278
|
|
|
275
279
|
return helms;
|
|
@@ -288,20 +292,20 @@ export async function addTransformedColumn(
|
|
|
288
292
|
addCommonTags(targetHelmCol);
|
|
289
293
|
targetHelmCol.setTag('units', NOTATION.HELM);
|
|
290
294
|
|
|
295
|
+
if (addHelm) {
|
|
296
|
+
targetHelmCol.setTag('cell.renderer', 'helm');
|
|
297
|
+
df.columns.add(targetHelmCol);
|
|
298
|
+
}
|
|
299
|
+
|
|
291
300
|
const molCol = await grok.functions.call('Bio:getMolFromHelm', {
|
|
292
301
|
'df': df,
|
|
293
302
|
'helmCol': targetHelmCol,
|
|
294
303
|
'chiralityEngine': chiralityEngine
|
|
295
304
|
});
|
|
296
305
|
|
|
297
|
-
|
|
298
306
|
molCol.name = df.columns.getUnusedName('molfile(' + sequencesCol.name + ')');
|
|
299
307
|
molCol.semType = DG.SEMTYPE.MOLECULE;
|
|
300
308
|
|
|
301
|
-
if (addHelm) {
|
|
302
|
-
targetHelmCol.setTag('cell.renderer', 'helm');
|
|
303
|
-
df.columns.add(targetHelmCol);
|
|
304
|
-
}
|
|
305
309
|
df.columns.add(molCol, true);
|
|
306
310
|
await grok.data.detectSemanticTypes(df);
|
|
307
311
|
}
|