@datagrok/bio 2.16.5 → 2.16.7

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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Aleksandr Tanas",
6
6
  "email": "atanas@datagrok.ai"
7
7
  },
8
- "version": "2.16.5",
8
+ "version": "2.16.7",
9
9
  "description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
10
10
  "repository": {
11
11
  "type": "git",
@@ -37,7 +37,7 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@biowasm/aioli": "^3.1.0",
40
- "@datagrok-libraries/bio": "^5.45.3",
40
+ "@datagrok-libraries/bio": "^5.45.5",
41
41
  "@datagrok-libraries/chem-meta": "^1.2.7",
42
42
  "@datagrok-libraries/math": "^1.2.2",
43
43
  "@datagrok-libraries/ml": "^6.7.4",
package/src/package.ts CHANGED
@@ -27,6 +27,7 @@ import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
27
27
  import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
28
28
  import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
29
29
  import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
30
+ import {MmcrTemps} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
30
31
 
31
32
  import {getMacromoleculeColumns} from './utils/ui-utils';
32
33
  import {MacromoleculeDifferenceCellRenderer, MacromoleculeSequenceCellRenderer,} from './utils/cell-renderer';
@@ -630,7 +631,7 @@ export async function toAtomicLevel(
630
631
  const pi = DG.TaskBarProgressIndicator.create('Converting to atomic level ...');
631
632
  try {
632
633
  await initBioPromise;
633
- const monomerLib = _package.monomerLib;
634
+ const monomerLib = seqCol.temp[MmcrTemps.overriddenLibrary] ?? _package.monomerLib;
634
635
  const seqHelper = _package.seqHelper;
635
636
  const rdKitModule = _package.rdKitModule;
636
637
  await sequenceToMolfile(table, seqCol, nonlinear, highlight, monomerLib, seqHelper, rdKitModule);
@@ -1138,7 +1139,6 @@ export async function sdfToJsonLib(table: DG.DataFrame) {
1138
1139
  //input: string seq { semType: Macromolecule }
1139
1140
  //input: bool nonlinear
1140
1141
  //output: string molfile { semType: Molecule }
1141
- //meta.role: converter
1142
1142
  export async function seq2atomic(seq: string, nonlinear: boolean): Promise<string | undefined> {
1143
1143
  if (!(seq.trim())) return '';
1144
1144
  try {
@@ -85,6 +85,7 @@ category('monomerLibraries', () => {
85
85
 
86
86
  const overriddenMonomerLib = monomerLib.override({[overMon.polymerType]: {[overMon.symbol]: overMon}}, 'test');
87
87
  const resOverMon = overriddenMonomerLib.getMonomer(overMon.polymerType, overMon.symbol);
88
+ if (resOverMon) resOverMon.lib = undefined; // cleanup to prevent infinite recursive comparison
88
89
  expectObject(resOverMon as any, overMon);
89
90
  });
90
91
  });
@@ -81,8 +81,8 @@ category('SeqHandler: getHelm', () => {
81
81
  await grok.data.detectSemanticTypes(df);
82
82
 
83
83
  const sh = seqHelper.getSeqHandler(seqCol);
84
- const resSemValue = await sh.getHelm(0);
85
- const resHelm = resSemValue.value;
84
+ const resMValue = await sh.getValue(0);
85
+ const resHelm = resMValue.helm;
86
86
  expect(resHelm, tgtHelm);
87
87
  }
88
88
  });
@@ -114,7 +114,8 @@ rut2-rty-her2---wert-rut12-rty-her2---wert
114
114
  PEPTIDE1{meI.hHis.Aca.N.T.dE.Thr_PO3H2.Aca.D-Tyr_Et.Thr_PO3H2.Aca.D-Tyr_Et}$$$$
115
115
  PEPTIDE1{meI.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.Aca.dK.Thr_PO3H2.Aca}$$$$
116
116
  PEPTIDE1{Lys_Boc.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.Aca.dK.Thr_PO3H2.Aca}$$$$
117
- PEPTIDE1{meI.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.T.dK.Thr_PO3H2}$$$$`
117
+ PEPTIDE1{meI.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.T.dK.Thr_PO3H2}$$$$,
118
+ PEPTIDE1{meI.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.T.dK}|PEPTIDE2{Thr_PO3H2}$$$$`,
118
119
  },
119
120
  tgt: {
120
121
  notation: NOTATION.HELM,
@@ -123,6 +124,7 @@ PEPTIDE1{meI.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.T.dK.Thr_PO3H2}$$$$`
123
124
  ['meI', 'hHis', 'Aca', 'Cys_SEt', 'T', 'dK', 'Thr_PO3H2', 'Aca', 'dK', 'Thr_PO3H2', 'Aca'],
124
125
  ['Lys_Boc', 'hHis', 'Aca', 'Cys_SEt', 'T', 'dK', 'Thr_PO3H2', 'Aca', 'dK', 'Thr_PO3H2', 'Aca'],
125
126
  ['meI', 'hHis', 'Aca', 'Cys_SEt', 'T', 'dK', 'Thr_PO3H2', 'T', 'dK', 'Thr_PO3H2'],
127
+ ['meI', 'hHis', 'Aca', 'Cys_SEt', 'T', 'dK', 'Thr_PO3H2', 'T', 'dK', 'Thr_PO3H2'],
126
128
  ]
127
129
  }
128
130
  }
@@ -94,53 +94,33 @@ export class HelmToMolfileConverter {
94
94
  }
95
95
 
96
96
 
97
- public convertToMolfileV3KColumn(
98
- helmCol: DG.Column<string>
99
- ): DG.Column<string> {
97
+ public convertToMolfileV3KColumn(helmCol: DG.Column<string>): DG.Column<string> {
100
98
  const df = helmCol.dataFrame;
101
- const polymerGraphColumn: DG.Column<string> = this.getPolymerGraphColumn(helmCol);
102
- const molfileList = polymerGraphColumn.toList().map(
103
- (pseudoMolfile: string, idx: number) => {
104
- const helm = helmCol.get(idx);
105
- if (!helm) return '';
106
-
107
- let resMolfileWithMap: MolfileWithMap;
108
- try {
109
- resMolfileWithMap = this.getPolymerMolfile(helm, pseudoMolfile);
110
- } catch (err: any) {
111
- const [errMsg, errStack] = errInfo(err);
112
- _package.logger.error(errMsg, undefined, errStack);
113
- resMolfileWithMap = MolfileWithMap.createEmpty();
114
- }
115
- return resMolfileWithMap.molfile;
116
- });
99
+ const molfileList = this.convertToMolfileV3K(helmCol.toList()).map((mwm) => mwm.molfile);
117
100
  const molColName = getUnusedColName(df, `molfileV2K(${helmCol.name})`);
118
101
  const molfileColumn = DG.Column.fromList('string', molColName, molfileList);
119
102
  return molfileColumn;
120
103
  }
121
104
 
122
105
  /** Gets list of monomer molfiles */
123
- public convertToMolfileV3K(helmCol: DG.Column<string>, rdKitModule: RDModule, monomerLib: IMonomerLibBase): MolfileWithMap[] {
124
- const polymerGraphColumn: DG.Column<string> = this.getPolymerGraphColumn(helmCol);
125
- const rowCount = helmCol.length;
126
- const resList: MolfileWithMap[] = new Array<MolfileWithMap>(rowCount);
127
- for (let rowIdx = 0; rowIdx < rowCount; ++rowIdx) {
128
- const helm = helmCol.get(rowIdx);
106
+ public convertToMolfileV3K(helmList: string[]): MolfileWithMap[] {
107
+ const resList: MolfileWithMap[] = new Array<MolfileWithMap>(helmList.length);
108
+ for (let i = 0; i < helmList.length; ++i) {
109
+ const helm = helmList[i];
129
110
  if (!helm) {
130
- resList[rowIdx] = MolfileWithMap.createEmpty();
111
+ resList[i] = MolfileWithMap.createEmpty();
131
112
  continue;
132
113
  }
133
114
 
134
- const pseudoMolfile = polymerGraphColumn.get(rowIdx)!;
135
115
  let resMolfile: MolfileWithMap;
136
116
  try {
137
- resMolfile = this.getPolymerMolfile(helm, pseudoMolfile);
117
+ resMolfile = this.getPolymerMolfile(helm);
138
118
  } catch (err: any) {
139
119
  const [errMsg, errStack] = errInfo(err);
140
120
  _package.logger.error(errMsg, undefined, errStack);
141
121
  resMolfile = MolfileWithMap.createEmpty();
142
122
  }
143
- resList[rowIdx] = resMolfile;
123
+ resList[i] = resMolfile;
144
124
  }
145
125
  return resList;
146
126
  }
@@ -152,16 +132,15 @@ export class HelmToMolfileConverter {
152
132
  return molfileCol;
153
133
  }
154
134
 
155
- private getPolymerMolfile(
156
- helm: string, polymerGraph: string
157
- ): MolfileWithMap {
135
+ private getPolymerMolfile(helm: string): MolfileWithMap {
158
136
  const woGapsRes = this.helmHelper.removeGaps(helm);
159
137
  const woGapsHelm = woGapsRes.resHelm;
160
138
  const woGapsReverseMap = new Map<number, number>();
161
139
  for (const [orgPosIdx, woGapsPosIdx] of (woGapsRes.monomerMap?.entries() ?? [])) {
162
140
  woGapsReverseMap.set(woGapsPosIdx, orgPosIdx);
163
141
  }
164
- const globalPositionHandler = new GlobalMonomerPositionHandler(polymerGraph);
142
+ const pseudoMolfile = this.helmHelper.getMolfiles([woGapsHelm])[0];
143
+ const globalPositionHandler = new GlobalMonomerPositionHandler(pseudoMolfile);
165
144
  const woGapsPolymer = new Polymer(woGapsHelm, this.rdKitModule, this.monomerLib);
166
145
  globalPositionHandler.monomerSymbols.forEach((monomerSymbol: string, monomerIdx: number) => {
167
146
  const shift = globalPositionHandler.getMonomerShifts(monomerIdx);
@@ -1,4 +1,6 @@
1
1
  import {HELM_MONOMER_TYPE, HELM_POLYMER_TYPE} from '@datagrok-libraries/bio/src/utils/const';
2
+ import {cleanupHelmSymbol} from '@datagrok-libraries/bio/src/helm/utils';
3
+
2
4
  import {Bond} from './types';
3
5
 
4
6
  /** Wrapper over simple polymer substring of HELM, like RNA1{d(A)p} */
@@ -41,7 +43,7 @@ export class SimplePolymer {
41
43
  return id;
42
44
  }
43
45
 
44
- private getMonomerSymbolsAndTypes(): {monomers: string[], monomerTypes: HELM_MONOMER_TYPE[]} {
46
+ private getMonomerSymbolsAndTypes(): { monomers: string[], monomerTypes: HELM_MONOMER_TYPE[] } {
45
47
  const helmWrapperRegex = new RegExp(`${this.polymerType}${this.idx}{|}`, 'g');
46
48
  const monomerGroups = this.simplePolymer.replace(helmWrapperRegex, '').split('.');
47
49
  const monomerList: string[] = [];
@@ -51,7 +53,7 @@ export class SimplePolymer {
51
53
  // monomerList.push(...splitted);
52
54
  // WARNING: only the groups of the form r(A)p, as in RNA, are supported
53
55
 
54
- monomerList.push(monomerGroup);
56
+ monomerList.push(cleanupHelmSymbol(monomerGroup));
55
57
  // const monomerTypes = splitted.map(
56
58
  // (_, idx) => (idx % 2 === 0) ? HELM_MONOMER_TYPE.BACKBONE : HELM_MONOMER_TYPE.BRANCH
57
59
  // );
@@ -132,7 +132,7 @@ class LibraryControlsManager {
132
132
 
133
133
  private _createControlsForm(): HTMLElement {
134
134
  const libraryControls = this.createLibraryControls();
135
- const inputsForm = ui.form(libraryControls);
135
+ const inputsForm = ui.form(libraryControls, undefined, false);
136
136
  $(inputsForm).addClass('monomer-lib-controls-form');
137
137
 
138
138
  return inputsForm;
@@ -46,6 +46,10 @@ export class MonomerLibBase implements IMonomerLibBase {
46
46
  ) {
47
47
  this._isEmpty = !this._monomers || Object.keys(this._monomers).length === 0 ||
48
48
  Object.entries(this._monomers).every(([_, ptMonomers]) => Object.keys(ptMonomers).length === 0);
49
+ for (const [_monomerType, monomersOfType] of Object.entries(this._monomers)) {
50
+ for (const [_monomerSymbol, monomer] of Object.entries(monomersOfType))
51
+ monomer.lib = this;
52
+ }
49
53
  }
50
54
 
51
55
  getMonomerSymbolsByType(polymerType: PolymerType): string[] {
@@ -43,10 +43,6 @@ export class MonomerLib extends MonomerLibBase implements IMonomerLib {
43
43
  public readonly error: string | undefined = undefined,
44
44
  ) {
45
45
  super(monomers, source);
46
- for (const [_monomerType, monomersOfType] of Object.entries(this._monomers)) {
47
- for (const [_monomerSymbol, monomer] of Object.entries(monomersOfType))
48
- monomer.lib = this;
49
- }
50
46
  }
51
47
 
52
48
  toJSON(): Monomer[] {
@@ -237,8 +233,10 @@ export class MonomerLib extends MonomerLibBase implements IMonomerLib {
237
233
  return resStr;
238
234
  }
239
235
 
236
+ static overrideCounter: number = 0;
237
+
240
238
  override(data: MonomerLibData, source: string): IMonomerLibBase {
241
- return new OverriddenMonomerLib(data, source, this);
239
+ return new OverriddenMonomerLib(data, `override: ${++MonomerLib.overrideCounter}, ${source}`, this);
242
240
  }
243
241
  }
244
242
 
@@ -868,6 +868,7 @@ class MonomerForm implements INewMonomerForm {
868
868
  await grok.dapi.files.writeAsText(LIB_PATH + libName, JSON.stringify(libJSON));
869
869
  await (await MonomerLibManager.getInstance()).loadLibraries(true);
870
870
  await this.refreshTable(monomer.symbol);
871
+ this._molChanged = false; // reset the flag
871
872
  grok.shell.info(`Monomer ${monomer.symbol} was successfully saved in library ${libName}`);
872
873
  } catch (e) {
873
874
  grok.shell.error('Error saving monomer');
@@ -14,7 +14,7 @@ import {GAP_SYMBOL, GapOriginals} from '@datagrok-libraries/bio/src/utils/macrom
14
14
  import {CellRendererBackBase, GridCellRendererTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
15
15
  import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
16
16
  import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
17
- import {ISeqHandler, ConvertFunc, JoinerFunc, SeqTemps} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
17
+ import {ISeqHandler, ConvertFunc, JoinerFunc, SeqTemps, MacromoleculeValueBase} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
18
18
 
19
19
  import {SeqHelper} from './seq-helper';
20
20
 
@@ -241,18 +241,16 @@ export class SeqHandler implements ISeqHandler {
241
241
  }
242
242
 
243
243
  /** Any Macromolecule can be represented on Helm format. The reverse is not always possible. */
244
- public async getHelm(rowIdx: number, options?: any): Promise<DG.SemanticValue<string>> {
244
+ public async getValue(rowIdx: number, options?: any): Promise<MacromoleculeValueBase> {
245
245
  const seq: string = this.column.get(rowIdx);
246
- let resHelmSV: DG.SemanticValue<string>;
246
+ let resHelm: string;
247
247
  if (this.notationProvider)
248
- resHelmSV = await this.notationProvider.getHelm(seq, options);
248
+ resHelm = await this.notationProvider.getHelm(seq, options);
249
249
  else {
250
- const resHelm = this.convertToHelm(seq);
251
- resHelmSV = DG.SemanticValue.fromValueType(resHelm, DG.SEMTYPE.MACROMOLECULE, NOTATION.HELM);
252
- // TODO: set tags from column
250
+ resHelm = this.convertToHelm(seq);
253
251
  }
254
-
255
- return resHelmSV;
252
+ const resMValue = new MacromoleculeValueBase(resHelm, this, rowIdx);
253
+ return resMValue;
256
254
  }
257
255
 
258
256
  private _stats: SeqColStats | null = null;
@@ -56,7 +56,7 @@ export class SeqHelper implements ISeqHelper {
56
56
 
57
57
  //#region From HelmToMolfileConverter.convertToRdKitBeautifiedMolfileColumn
58
58
 
59
- const molfilesV3K = converter.convertToMolfileV3K(helmCol, this.rdKitModule, monomerLib);
59
+ const molfilesV3K = converter.convertToMolfileV3K(helmCol.toList());
60
60
 
61
61
  const beautifiedMolList: (RDMol | null)[] = molfilesV3K.map((item) => {
62
62
  const molfile = item.molfile;