@datagrok/sequence-translator 1.3.9 → 1.3.11
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 +16 -0
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +1 -1
- package/src/apps/pattern/model/const.ts +8 -5
- package/src/apps/pattern/model/data-manager.ts +40 -15
- package/src/apps/pattern/model/event-bus.ts +2 -0
- package/src/apps/pattern/model/types.ts +8 -6
- package/src/apps/pattern/view/components/load-block-controls.ts +9 -6
- package/src/apps/pattern/view/components/right-section.ts +50 -1
- package/src/apps/pattern/view/ui.ts +1 -1
- package/src/package.ts +42 -30
- package/src/polytool/pt-dialog.ts +25 -6
- package/src/polytool/pt-enumeration-chem.ts +35 -21
- package/src/utils/context-menu.ts +1 -1
- package/src/polytool/pt-ui.ts +0 -25
package/package.json
CHANGED
|
@@ -57,6 +57,12 @@ export namespace LEGEND_SETTINGS_KEYS {
|
|
|
57
57
|
export namespace PATTERN_RECORD_KEYS {
|
|
58
58
|
export const PATTERN_CONFIG = 'patternConfig';
|
|
59
59
|
export const AUTHOR_ID = 'authorID';
|
|
60
|
+
export const DATE = 'date';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export namespace DATE_KEYS {
|
|
64
|
+
export const CREATE = 'create';
|
|
65
|
+
export const MODIFY = 'modify';
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
export const GRAPH_SETTINGS_KEY_LIST = [
|
|
@@ -72,11 +78,6 @@ export const LEGEND_SETTINGS_KEY_LIST = [
|
|
|
72
78
|
LEGEND_SETTINGS_KEYS.NUCLEOTIDES_WITH_NUMERIC_LABELS
|
|
73
79
|
];
|
|
74
80
|
|
|
75
|
-
export const PATTERN_RECORD_KEY_LIST = [
|
|
76
|
-
PATTERN_RECORD_KEYS.PATTERN_CONFIG,
|
|
77
|
-
PATTERN_RECORD_KEYS.AUTHOR_ID
|
|
78
|
-
];
|
|
79
|
-
|
|
80
81
|
export const EXAMPLE_PATTERN_CONFIG =
|
|
81
82
|
{
|
|
82
83
|
'patternConfig': {
|
|
@@ -119,3 +120,5 @@ export const EXAMPLE_PATTERN_CONFIG =
|
|
|
119
120
|
},
|
|
120
121
|
'authorID': ''
|
|
121
122
|
};
|
|
123
|
+
|
|
124
|
+
export const DEFAULT_DATE = '2024-01-01T18:00:00.000Z';
|
|
@@ -3,7 +3,8 @@ import * as grok from 'datagrok-api/grok';
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
EXAMPLE_PATTERN_CONFIG,
|
|
6
|
-
GRAPH_SETTINGS_KEY_LIST as GKL, LEGEND_SETTINGS_KEYS as L,
|
|
6
|
+
GRAPH_SETTINGS_KEY_LIST as GKL, LEGEND_SETTINGS_KEYS as L,
|
|
7
|
+
OTHER_USERS, PATTERN_RECORD_KEYS as R, STORAGE_NAME, DATE_KEYS as D
|
|
7
8
|
} from './const';
|
|
8
9
|
import {
|
|
9
10
|
PatternConfigRecord, PatternConfiguration, PatternExistsError, PatternNameExistsError, RawPatternRecords
|
|
@@ -76,7 +77,7 @@ export class DataManager {
|
|
|
76
77
|
return patternHash;
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
async
|
|
80
|
+
async getPatternRecordByHash(hash: string): Promise<PatternConfigRecord | null> {
|
|
80
81
|
if (hash === null || hash === '')
|
|
81
82
|
return null;
|
|
82
83
|
try {
|
|
@@ -91,7 +92,7 @@ export class DataManager {
|
|
|
91
92
|
async getPatternConfig(hash: string | null): Promise<PatternConfiguration | null> {
|
|
92
93
|
if (hash === '' || hash === null)
|
|
93
94
|
return null;
|
|
94
|
-
const record = await this.
|
|
95
|
+
const record = await this.getPatternRecordByHash(hash);
|
|
95
96
|
const config = record === null ? null : record[R.PATTERN_CONFIG] as PatternConfiguration;
|
|
96
97
|
return config;
|
|
97
98
|
}
|
|
@@ -144,13 +145,13 @@ export class DataManager {
|
|
|
144
145
|
return hash;
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
private async getRecordFromPattern(
|
|
148
|
-
|
|
148
|
+
private async getRecordFromPattern(
|
|
149
|
+
patternConfig: PatternConfiguration
|
|
150
|
+
): Promise<PatternConfigRecord> {
|
|
151
|
+
return {
|
|
149
152
|
[R.PATTERN_CONFIG]: patternConfig,
|
|
150
153
|
[R.AUTHOR_ID]: await grok.dapi.users.current().then((u) => u.id),
|
|
151
154
|
};
|
|
152
|
-
const stringifiedRecord = JSON.stringify(record);
|
|
153
|
-
return stringifiedRecord;
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
private getHash(patternConfig: PatternConfiguration): string {
|
|
@@ -173,13 +174,21 @@ export class DataManager {
|
|
|
173
174
|
const patternName = patternConfig[L.PATTERN_NAME];
|
|
174
175
|
this.validatePatternNameUniqueness(patternName);
|
|
175
176
|
|
|
176
|
-
const
|
|
177
|
+
const recordObj = await this.getRecordFromPattern(patternConfig);
|
|
178
|
+
const timestamp = new Date().toISOString();
|
|
179
|
+
recordObj[R.DATE] = {
|
|
180
|
+
[D.CREATE]: timestamp,
|
|
181
|
+
[D.MODIFY]: timestamp,
|
|
182
|
+
};
|
|
183
|
+
const record = JSON.stringify(recordObj);
|
|
177
184
|
await grok.dapi.userDataStorage.postValue(STORAGE_NAME, hash, record, false);
|
|
178
185
|
this.currentUserPatternNameToHash.set(patternName, hash);
|
|
179
186
|
|
|
180
187
|
eventBus.selectAuthor(this.getCurrentUserAuthorshipCategory());
|
|
181
188
|
|
|
182
189
|
eventBus.updatePatternList();
|
|
190
|
+
eventBus.requestPatternLoad(hash);
|
|
191
|
+
eventBus.updateUrlState(hash);
|
|
183
192
|
} catch (e) {
|
|
184
193
|
if (e instanceof PatternNameExistsError || e instanceof PatternExistsError)
|
|
185
194
|
throw e;
|
|
@@ -188,17 +197,33 @@ export class DataManager {
|
|
|
188
197
|
}
|
|
189
198
|
}
|
|
190
199
|
|
|
191
|
-
async
|
|
200
|
+
async overwriteExistingPatternInUserStorage(
|
|
192
201
|
eventBus: EventBus
|
|
193
202
|
): Promise<void> {
|
|
194
203
|
const patternConfig = eventBus.getPatternConfig();
|
|
195
|
-
const hash = this.getHash(patternConfig);
|
|
196
204
|
const patternName = patternConfig[L.PATTERN_NAME];
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
205
|
+
const oldHash = this.currentUserPatternNameToHash.get(patternName);
|
|
206
|
+
|
|
207
|
+
if (oldHash === undefined)
|
|
208
|
+
throw new Error(`Old hash is undefined`);
|
|
209
|
+
const newHash = this.getHash(patternConfig);
|
|
210
|
+
const newRecordObj = await this.getRecordFromPattern(patternConfig);
|
|
211
|
+
const timestamp = new Date().toISOString();
|
|
212
|
+
newRecordObj[R.DATE] = {
|
|
213
|
+
[D.MODIFY]: timestamp,
|
|
214
|
+
};
|
|
215
|
+
const oldPattern = await grok.dapi.userDataStorage.getValue(STORAGE_NAME, oldHash, false);
|
|
216
|
+
const oldPatternsRecord = JSON.parse(oldPattern) as PatternConfigRecord;
|
|
217
|
+
if (oldPatternsRecord[R.DATE] !== undefined && oldPatternsRecord[R.DATE][D.CREATE] != undefined)
|
|
218
|
+
newRecordObj[R.DATE][D.CREATE] = oldPatternsRecord[R.DATE][D.CREATE];
|
|
219
|
+
|
|
220
|
+
const newRecord = JSON.stringify(newRecordObj);
|
|
221
|
+
await grok.dapi.userDataStorage.postValue(STORAGE_NAME, newHash, newRecord, false);
|
|
222
|
+
await grok.dapi.userDataStorage.remove(STORAGE_NAME, oldHash, false);
|
|
223
|
+
|
|
224
|
+
this.currentUserPatternNameToHash.set(patternName, newHash);
|
|
225
|
+
eventBus.requestPatternLoad(newHash);
|
|
226
|
+
eventBus.updateUrlState(newHash);
|
|
202
227
|
}
|
|
203
228
|
|
|
204
229
|
async deletePattern(
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
/* Do not change these import lines to match external modules in webpack configuration */
|
|
2
|
-
import * as grok from 'datagrok-api/grok';
|
|
3
|
-
import * as ui from 'datagrok-api/ui';
|
|
4
|
-
import * as DG from 'datagrok-api/dg';
|
|
5
|
-
|
|
6
1
|
import {
|
|
7
2
|
TERMINI, STRANDS,
|
|
8
|
-
GRAPH_SETTINGS_KEYS as G, LEGEND_SETTINGS_KEYS as L, PATTERN_RECORD_KEYS as R
|
|
3
|
+
GRAPH_SETTINGS_KEYS as G, LEGEND_SETTINGS_KEYS as L, PATTERN_RECORD_KEYS as R,
|
|
4
|
+
DATE_KEYS as D
|
|
9
5
|
} from './const';
|
|
10
6
|
|
|
11
7
|
export type StrandType = typeof STRANDS[number];
|
|
@@ -30,9 +26,15 @@ export type PatternLegendSettings = {
|
|
|
30
26
|
|
|
31
27
|
export type PatternConfiguration = PatternGraphSettings & PatternLegendSettings;
|
|
32
28
|
|
|
29
|
+
type DateRecord = {
|
|
30
|
+
[D.CREATE]?: string,
|
|
31
|
+
[D.MODIFY]: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
33
34
|
export type PatternConfigRecord = {
|
|
34
35
|
[R.PATTERN_CONFIG]: PatternConfiguration,
|
|
35
36
|
[R.AUTHOR_ID]: string,
|
|
37
|
+
[R.DATE]?: DateRecord
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export class PatternNameExistsError extends Error {
|
|
@@ -94,12 +94,15 @@ export class PatternLoadControlsManager {
|
|
|
94
94
|
possibleValues.push(this.dataManager.getOtherUsersAuthorshipCategory());
|
|
95
95
|
|
|
96
96
|
const authorChoiceInput = ui.input.choice(
|
|
97
|
-
'Author', {value: this.eventBus.getSelectedAuthor(), items: possibleValues
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
'Author', {value: this.eventBus.getSelectedAuthor(), items: possibleValues});
|
|
98
|
+
|
|
99
|
+
authorChoiceInput.onInput(() => {
|
|
100
|
+
this.authorSelectedByUser = true;
|
|
101
|
+
if (authorChoiceInput.value === null)
|
|
102
|
+
throw new Error('author choice must be non-null');
|
|
103
|
+
this.eventBus.selectAuthor(authorChoiceInput.value);
|
|
104
|
+
});
|
|
105
|
+
|
|
103
106
|
this.setAuthorChoiceInputStyle(authorChoiceInput);
|
|
104
107
|
authorChoiceInput.setTooltip('Select pattern author');
|
|
105
108
|
|
|
@@ -7,6 +7,7 @@ import {PatternExistsError, PatternNameExistsError} from '../../model/types';
|
|
|
7
7
|
import {SvgDisplayManager} from '../svg-utils/svg-display-manager';
|
|
8
8
|
import {NumericLabelVisibilityControls} from './numeric-label-visibility-controls';
|
|
9
9
|
import {TranslationExamplesBlock} from './translation-examples-block';
|
|
10
|
+
import {DEFAULT_DATE, PATTERN_RECORD_KEYS as P, DATE_KEYS as D, LEGEND_SETTINGS_KEYS as L} from '../../model/const';
|
|
10
11
|
|
|
11
12
|
export class PatternAppRightSection {
|
|
12
13
|
private svgDisplay: HTMLDivElement;
|
|
@@ -44,6 +45,7 @@ export class PatternAppRightSection {
|
|
|
44
45
|
this.createSavePatternButton(),
|
|
45
46
|
this.createDownloadPngButton(),
|
|
46
47
|
this.createShareLinkButton(),
|
|
48
|
+
this.createInfoButton(),
|
|
47
49
|
], {style: {gap: '12px', marginTop: '12px'}});
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -55,6 +57,53 @@ export class PatternAppRightSection {
|
|
|
55
57
|
return svgDownloadButton;
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
private createInfoButton(): HTMLButtonElement {
|
|
61
|
+
const shareLinkButton = ui.button(
|
|
62
|
+
ui.iconFA('info-circle'),
|
|
63
|
+
() => this.openInfoDialog()
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
this.eventBus.patternHasUnsavedChanges$.subscribe((hasUnsavedChanges: boolean) => {
|
|
67
|
+
shareLinkButton.disabled = hasUnsavedChanges;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
ui.tooltip.bind(shareLinkButton, 'View pattern metadata');
|
|
71
|
+
return shareLinkButton;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private async openInfoDialog() {
|
|
75
|
+
let author = this.dataManager.getCurrentUserName();
|
|
76
|
+
let patternName = this.dataManager.getDefaultPatternName();
|
|
77
|
+
let createDate = DEFAULT_DATE;
|
|
78
|
+
let modifyDate = DEFAULT_DATE;
|
|
79
|
+
const hash = new URLSearchParams(window.location.search).get('pattern');
|
|
80
|
+
if (hash !== null) {
|
|
81
|
+
const record = await this.dataManager.getPatternRecordByHash(hash);
|
|
82
|
+
if (record !== null) {
|
|
83
|
+
const authorID = record[P.AUTHOR_ID];
|
|
84
|
+
const userFriendlyName = (await grok.dapi.users.find(authorID)).friendlyName;
|
|
85
|
+
author = userFriendlyName;
|
|
86
|
+
patternName = record[P.PATTERN_CONFIG][L.PATTERN_NAME];
|
|
87
|
+
if (record[P.DATE] !== undefined) {
|
|
88
|
+
const create = record[P.DATE][D.CREATE];
|
|
89
|
+
if (create !== undefined)
|
|
90
|
+
createDate = create;
|
|
91
|
+
const modify = record[P.DATE][D.MODIFY];
|
|
92
|
+
if (modify !== undefined)
|
|
93
|
+
modifyDate = modify;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const message = ui.divV([
|
|
99
|
+
ui.divText(`Author: ${author}`),
|
|
100
|
+
ui.divText(`Pattern Name: ${patternName}`),
|
|
101
|
+
ui.divText(`Created: ${new Date(createDate).toLocaleString()}`),
|
|
102
|
+
ui.divText(`Modified: ${new Date(modifyDate).toLocaleString()}`),
|
|
103
|
+
]);
|
|
104
|
+
grok.shell.info(message);
|
|
105
|
+
}
|
|
106
|
+
|
|
58
107
|
private createShareLinkButton(): HTMLButtonElement {
|
|
59
108
|
const shareLinkButton = ui.button(
|
|
60
109
|
ui.iconFA('link'),
|
|
@@ -135,7 +184,7 @@ class OverwritePatternDialog {
|
|
|
135
184
|
|
|
136
185
|
private processOverwriteNamesakePattern(): void {
|
|
137
186
|
const patternName = this.eventBus.getPatternName();
|
|
138
|
-
this.dataManager.
|
|
187
|
+
this.dataManager.overwriteExistingPatternInUserStorage(this.eventBus)
|
|
139
188
|
.then(() => {
|
|
140
189
|
grok.shell.info(`Pattern ${patternName} overwritten`);
|
|
141
190
|
})
|
|
@@ -55,7 +55,7 @@ async function getInitialPatternRecord(
|
|
|
55
55
|
return dataManager.getDefaultPatternRecord();
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
let initialPatternRecord = await dataManager.
|
|
58
|
+
let initialPatternRecord = await dataManager.getPatternRecordByHash(patternHash);
|
|
59
59
|
if (!initialPatternRecord) {
|
|
60
60
|
urlRouter.clearPatternURL();
|
|
61
61
|
initialPatternRecord = dataManager.getDefaultPatternRecord();
|
package/src/package.ts
CHANGED
|
@@ -16,12 +16,12 @@ import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from '.
|
|
|
16
16
|
import {getExternalAppViewFactories} from './plugins/mermade';
|
|
17
17
|
|
|
18
18
|
//polytool specific
|
|
19
|
-
import {getPolyToolConversionDialog} from './polytool/pt-dialog';
|
|
19
|
+
import {getPolyToolConversionDialog, polyToolEnumerateHelmUI, polyToolEnumerateChemUI} from './polytool/pt-dialog';
|
|
20
20
|
import {_setPeptideColumn} from './polytool/utils';
|
|
21
21
|
import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
|
|
22
22
|
import {ITranslationHelper} from './types';
|
|
23
|
-
import {polyToolEnumerateHelmUI, polyToolEnumerateChemUI} from './polytool/pt-ui';
|
|
24
23
|
import {addContextMenuUI} from './utils/context-menu';
|
|
24
|
+
import { NOTATION } from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
25
25
|
|
|
26
26
|
export const _package: OligoToolkitPackage = new OligoToolkitPackage();
|
|
27
27
|
|
|
@@ -172,12 +172,12 @@ export async function polyToolEnumerateHelm(): Promise<void> {
|
|
|
172
172
|
polyToolEnumerateHelmUI();
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
//top-menu: Bio | Convert | PolyTool-Enumerate Chem
|
|
176
|
+
//name: polyToolEnumerateChem
|
|
177
|
+
//description: Perform cyclization of polymers
|
|
178
|
+
export async function polyToolEnumerateChem(): Promise<void> {
|
|
179
|
+
polyToolEnumerateChemUI();
|
|
180
|
+
}
|
|
181
181
|
|
|
182
182
|
//name: polyToolColumnChoice
|
|
183
183
|
//input: dataframe df [Input data table]
|
|
@@ -210,28 +210,40 @@ export function addContextMenu(event: DG.EventData): void {
|
|
|
210
210
|
// //meta.icon: img/icons/structure.png
|
|
211
211
|
// //meta.browsePath: PolyTool
|
|
212
212
|
// //tags: app
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
// const
|
|
216
|
-
//
|
|
213
|
+
// export async function ptConverterApp(): Promise<void> {
|
|
214
|
+
// const view = grok.shell.v as DG.TableView;
|
|
215
|
+
// const table = view.dataFrame;
|
|
216
|
+
// const colNames = table.columns.names();
|
|
217
|
+
// let covertableName = '';
|
|
218
|
+
|
|
219
|
+
// for (let i = 0; i < colNames.length; i++) {
|
|
220
|
+
// const col = table.columns.byName(colNames[i]);
|
|
221
|
+
// if (col.semType === DG.SEMTYPE.MACROMOLECULE && col.meta.units === NOTATION.SEPARATOR) {
|
|
222
|
+
// covertableName = colNames[i];
|
|
223
|
+
// break;
|
|
224
|
+
// }
|
|
225
|
+
// }
|
|
226
|
+
|
|
227
|
+
// if (covertableName === '')
|
|
228
|
+
// grok.shell.error('To run the app open a view with convertable separator notation for macromolecules');
|
|
229
|
+
// else {
|
|
230
|
+
// const dialog = await getPolyToolConversionDialog();
|
|
231
|
+
// dialog.show();
|
|
232
|
+
// }
|
|
217
233
|
// }
|
|
218
234
|
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// return view;
|
|
227
|
-
// }
|
|
235
|
+
//name: PolyTool Enumerator Helm
|
|
236
|
+
//meta.icon: img/icons/structure.png
|
|
237
|
+
//meta.browsePath: PolyTool
|
|
238
|
+
//tags: app
|
|
239
|
+
export async function ptEnumeratorHelmApp(): Promise<void> {
|
|
240
|
+
polyToolEnumerateHelmUI();
|
|
241
|
+
}
|
|
228
242
|
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
// return view;
|
|
237
|
-
// }
|
|
243
|
+
//name: PolyTool Enumerator Chem
|
|
244
|
+
//meta.icon: img/icons/structure.png
|
|
245
|
+
//meta.browsePath: PolyTool
|
|
246
|
+
//tags: app
|
|
247
|
+
export async function ptEnumeratorChemApp(): Promise<void> {
|
|
248
|
+
polyToolEnumerateChemUI();
|
|
249
|
+
}
|
|
@@ -28,7 +28,27 @@ const PT_UI_DIALOG_CONVERSION = 'Poly Tool Conversion';
|
|
|
28
28
|
const PT_UI_DIALOG_ENUMERATION = 'Poly Tool Enumeration';
|
|
29
29
|
const PT_UI_RULES_USED = 'Rules used';
|
|
30
30
|
|
|
31
|
-
export
|
|
31
|
+
export function polyToolEnumerateHelmUI(cell?: DG.Cell): void {
|
|
32
|
+
getPolyToolEnumerationHelmDialog(cell)
|
|
33
|
+
.then((dialog) => {
|
|
34
|
+
dialog.show({resizable: true});
|
|
35
|
+
})
|
|
36
|
+
.catch((_err: any) => {
|
|
37
|
+
grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function polyToolEnumerateChemUI(cell?: DG.Cell): void {
|
|
42
|
+
getPolyToolEnumerationChemDialog(cell)
|
|
43
|
+
.then((dialog) => {
|
|
44
|
+
dialog.show({resizable: true});
|
|
45
|
+
})
|
|
46
|
+
.catch((_err: any) => {
|
|
47
|
+
grok.shell.warning('To run PolyTool Enumeration, sketch the molecule and specify the R group to vary');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function getPolyToolConversionDialog(targetCol?: DG.Column): Promise<DG.Dialog> {
|
|
32
52
|
const targetColumns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
|
|
33
53
|
if (!targetColumns)
|
|
34
54
|
throw new Error(PT_ERROR_DATAFRAME);
|
|
@@ -38,6 +58,8 @@ export async function getPolyToolConversionDialog(): Promise<DG.Dialog> {
|
|
|
38
58
|
filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE
|
|
39
59
|
});
|
|
40
60
|
|
|
61
|
+
targetColumnInput.value = targetCol ? targetCol : targetColumnInput.value;
|
|
62
|
+
|
|
41
63
|
const generateHelmChoiceInput = ui.input.bool(PT_UI_GET_HELM, {value: true});
|
|
42
64
|
ui.tooltip.bind(generateHelmChoiceInput.root, PT_UI_ADD_HELM);
|
|
43
65
|
|
|
@@ -82,7 +104,7 @@ export async function getPolyToolConversionDialog(): Promise<DG.Dialog> {
|
|
|
82
104
|
return dialog;
|
|
83
105
|
}
|
|
84
106
|
|
|
85
|
-
|
|
107
|
+
async function getPolyToolEnumerationHelmDialog(cell?: DG.Cell): Promise<DG.Dialog> {
|
|
86
108
|
const [libList, helmHelper] = await Promise.all([
|
|
87
109
|
getLibrariesList(), getHelmHelper()]);
|
|
88
110
|
|
|
@@ -137,7 +159,7 @@ export async function getPolyToolEnumerationHelmDialog(cell?: DG.Cell): Promise<
|
|
|
137
159
|
return dialog;
|
|
138
160
|
}
|
|
139
161
|
|
|
140
|
-
|
|
162
|
+
async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dialog> {
|
|
141
163
|
const [libList, helmHelper] = await Promise.all([
|
|
142
164
|
getLibrariesList(), getHelmHelper()]);
|
|
143
165
|
|
|
@@ -147,9 +169,6 @@ export async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<
|
|
|
147
169
|
// sketcher.setMolFile(col.tags[ALIGN_BY_SCAFFOLD_TAG]);
|
|
148
170
|
molInput.onChanged.subscribe((_: any) => {
|
|
149
171
|
molValue = molInput.getMolFile();
|
|
150
|
-
// col.tags[ALIGN_BY_SCAFFOLD_TAG] = molFile;
|
|
151
|
-
// col.temp[ALIGN_BY_SCAFFOLD_TAG] = molFile;
|
|
152
|
-
// col.dataFrame?.fireValuesChanged();
|
|
153
172
|
});
|
|
154
173
|
molInput.root.classList.add('ui-input-editor');
|
|
155
174
|
molInput.root.style.marginTop = '3px';
|
|
@@ -29,7 +29,7 @@ export const PT_CHEM_EXAMPLE = `
|
|
|
29
29
|
2.4544 0.4877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
30
30
|
-1.8175 -1.9896 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
31
31
|
-3.2453 0.4877 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
32
|
-
3.1670 1.7285 0.0000
|
|
32
|
+
3.1670 1.7285 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
33
33
|
1.7149 2.5513 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0
|
|
34
34
|
2 1 2 0 0 0 0
|
|
35
35
|
3 1 1 0 0 0 0
|
|
@@ -55,18 +55,15 @@ export const PT_CHEM_EXAMPLE = `
|
|
|
55
55
|
14 10 1 0 0 0 0
|
|
56
56
|
15 21 1 0 0 0 0
|
|
57
57
|
12 22 1 0 0 0 0
|
|
58
|
-
M RGP
|
|
58
|
+
M RGP 1 22 1
|
|
59
59
|
M END`;
|
|
60
60
|
|
|
61
61
|
export async function getEnumerationChem(molString: string, screenLibrary: string):
|
|
62
62
|
Promise<string[]> {
|
|
63
|
+
|
|
63
64
|
const variableMonomers = await getAvailableMonomers(screenLibrary);
|
|
64
65
|
const variableMols = await getAvailableMonomerMols(screenLibrary);
|
|
65
|
-
|
|
66
|
-
const idx = molString.indexOf('M RGP');
|
|
67
|
-
const rCount = parseInt(molString.slice(idx + 6, idx + 9)); //extracting from molfile positions
|
|
68
|
-
const size = 1 * variableMonomers.length;
|
|
69
|
-
const enumerations = new Array<string>(size);
|
|
66
|
+
const enumerations = new Array<string>(variableMonomers.length);
|
|
70
67
|
|
|
71
68
|
const rdkitModule: RDModule = await grok.functions.call('Chem:getRdKitModule');
|
|
72
69
|
const molScaffold: RDMol = rdkitModule.get_mol(molString);
|
|
@@ -84,22 +81,39 @@ export async function getEnumerationChem(molString: string, screenLibrary: strin
|
|
|
84
81
|
molSubst.delete();
|
|
85
82
|
}
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
for (let i = 0; i < variableMonomers.length; i++) {
|
|
85
|
+
let molRes: RDMol | null = null;
|
|
86
|
+
try {
|
|
87
|
+
//TODO: use RDKit linking function when exposed
|
|
88
|
+
const smiResRaw = `${smiScaffold}.${smilesSubsts[i]}`.replaceAll('[1*]C', 'C([1*])').replaceAll('[1*]c', 'c([1*])').replaceAll('[1*]O', 'O([1*])').replaceAll('[1*]N', 'N([1*])');
|
|
89
|
+
const smiRes = `${smiResRaw}`.replaceAll('([1*])', '9').replaceAll('[1*]', '9');
|
|
90
|
+
molRes = rdkitModule.get_mol(smiRes);
|
|
91
|
+
let molV3 = molRes.get_v3Kmolblock();
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
//TODO: use RDKit when MASS problem is solved
|
|
95
|
+
while(molV3.includes('MASS')) {
|
|
96
|
+
|
|
97
|
+
//MASS=2 VAL=1
|
|
98
|
+
//RGROUPS=(1 2)
|
|
99
|
+
const idx = molV3.indexOf('MASS');
|
|
100
|
+
const rNum = parseInt(molV3.slice(idx + 5, idx + 6));
|
|
101
|
+
const replace = `RGROUPS=(1 ${rNum})`;
|
|
102
|
+
molV3 = molV3.substring(0, idx) + replace + molV3.substring(idx + 12);
|
|
100
103
|
}
|
|
101
|
-
|
|
104
|
+
|
|
105
|
+
molV3 = molV3.replaceAll('R ', 'R# ')
|
|
106
|
+
|
|
107
|
+
enumerations[i] = molV3;
|
|
108
|
+
}
|
|
109
|
+
catch(err:any) {
|
|
110
|
+
enumerations[i] = '';
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
molRes?.delete();
|
|
114
|
+
}
|
|
102
115
|
}
|
|
116
|
+
|
|
103
117
|
|
|
104
118
|
return enumerations;
|
|
105
119
|
}
|
|
@@ -6,7 +6,7 @@ import {defaultErrorHandler} from './err-info';
|
|
|
6
6
|
import {_package, addContextMenu} from '../package';
|
|
7
7
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
8
8
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
|
-
import {polyToolEnumerateHelmUI} from '../polytool/pt-
|
|
9
|
+
import {polyToolEnumerateHelmUI} from '../polytool/pt-dialog';
|
|
10
10
|
|
|
11
11
|
export type SequenceTranslatorWindowType = Window & {
|
|
12
12
|
$sequenceTranslator?: {
|
package/src/polytool/pt-ui.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
|
-
import * as DG from 'datagrok-api/dg';
|
|
3
|
-
import * as ui from 'datagrok-api/ui';
|
|
4
|
-
|
|
5
|
-
import {getPolyToolEnumerationHelmDialog, getPolyToolEnumerationChemDialog} from './pt-dialog';
|
|
6
|
-
|
|
7
|
-
export function polyToolEnumerateHelmUI(cell?: DG.Cell): void {
|
|
8
|
-
getPolyToolEnumerationHelmDialog(cell)
|
|
9
|
-
.then((dialog) => {
|
|
10
|
-
dialog.show({resizable: true});
|
|
11
|
-
})
|
|
12
|
-
.catch((_err: any) => {
|
|
13
|
-
grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function polyToolEnumerateChemUI(cell?: DG.Cell): void {
|
|
18
|
-
getPolyToolEnumerationChemDialog(cell)
|
|
19
|
-
.then((dialog) => {
|
|
20
|
-
dialog.show({resizable: true});
|
|
21
|
-
})
|
|
22
|
-
.catch((_err: any) => {
|
|
23
|
-
grok.shell.warning('To run PolyTool Enumeration, sketch the molecule and specify the R group to vary');
|
|
24
|
-
});
|
|
25
|
-
}
|