jbrowse-plugin-msaview 2.6.2 → 2.6.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/dist/AddHighlightModel/MsaToGenomeHighlight.js +8 -9
- package/dist/LaunchMsaViewExtensionPoint/index.js +12 -5
- package/dist/MsaViewPanel/afterCreateAutoruns.d.ts +0 -2
- package/dist/MsaViewPanel/afterCreateAutoruns.js +8 -81
- package/dist/MsaViewPanel/model.d.ts +3 -28
- package/dist/MsaViewPanel/model.js +5 -103
- package/dist/MsaViewPanel/structureConnection.d.ts +0 -18
- package/dist/MsaViewPanel/types.d.ts +1 -4
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +26 -26
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/AddHighlightModel/MsaToGenomeHighlight.tsx +8 -9
- package/src/LaunchMsaViewExtensionPoint/index.ts +12 -5
- package/src/MsaViewPanel/afterCreateAutoruns.ts +8 -109
- package/src/MsaViewPanel/model.ts +4 -135
- package/src/MsaViewPanel/structureConnection.ts +0 -17
- package/src/MsaViewPanel/types.ts +14 -9
- package/src/version.ts +1 -1
- package/dist/MsaViewPanel/components/ConnectStructureDialog.d.ts +0 -7
- package/dist/MsaViewPanel/components/ConnectStructureDialog.js +0 -60
- package/dist/MsaViewPanel/pairwiseAlignment.d.ts +0 -20
- package/dist/MsaViewPanel/pairwiseAlignment.js +0 -138
- package/dist/MsaViewPanel/pairwiseAlignment.test.d.ts +0 -1
- package/dist/MsaViewPanel/pairwiseAlignment.test.js +0 -111
- package/src/MsaViewPanel/components/ConnectStructureDialog.tsx +0 -154
- package/src/MsaViewPanel/pairwiseAlignment.test.ts +0 -140
- package/src/MsaViewPanel/pairwiseAlignment.ts +0 -182
|
@@ -3,7 +3,6 @@ import { getSession } from '@jbrowse/core/util';
|
|
|
3
3
|
import { observer } from 'mobx-react';
|
|
4
4
|
import { hasHoverPosition, useStyles } from './util';
|
|
5
5
|
import { isMsaView } from '../MsaViewPanel/model';
|
|
6
|
-
import { getCanonicalRefName } from '../MsaViewPanel/util';
|
|
7
6
|
const MsaToGenomeHighlight = observer(function MsaToGenomeHighlight2({ model, }) {
|
|
8
7
|
const { views, hovered } = getSession(model);
|
|
9
8
|
const msaView = views
|
|
@@ -17,16 +16,16 @@ const MsaToGenomeHighlight = observer(function MsaToGenomeHighlight2({ model, })
|
|
|
17
16
|
// Inner component: handles the scroll-dependent rendering
|
|
18
17
|
const MsaToGenomeHighlightRenderer = observer(function ({ model, highlights, }) {
|
|
19
18
|
const { classes } = useStyles();
|
|
20
|
-
const { assemblyManager } = getSession(model);
|
|
21
19
|
const { offsetPx } = model;
|
|
22
20
|
return (React.createElement(React.Fragment, null, highlights.map((r, idx) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
21
|
+
// Use the highlight's own refName, which is already in the connected
|
|
22
|
+
// view's coordinate space (it comes from the connectedFeature the
|
|
23
|
+
// launcher set on this LGV). Do NOT canonicalize: bpToPx matches
|
|
24
|
+
// displayed regions by exact refName with no alias resolution, so
|
|
25
|
+
// rewriting e.g. "chr17" to the assembly-canonical "17" misses a view
|
|
26
|
+
// whose regions are "chr17". (GenomeMouseoverHighlight does the same.)
|
|
27
|
+
const s = model.bpToPx({ refName: r.refName, coord: r.start });
|
|
28
|
+
const e = model.bpToPx({ refName: r.refName, coord: r.end });
|
|
30
29
|
if (s && e) {
|
|
31
30
|
const width = Math.max(Math.abs(e.offsetPx - s.offsetPx), 4);
|
|
32
31
|
const left = Math.min(s.offsetPx, e.offsetPx) - offsetPx;
|
|
@@ -4,18 +4,25 @@ export default function LaunchMsaViewExtensionPointF(pluginManager) {
|
|
|
4
4
|
if (!data && !msaFileLocation && !msaIndexedLocation) {
|
|
5
5
|
throw new Error('No MSA data or file location provided when launching MSA view');
|
|
6
6
|
}
|
|
7
|
-
//
|
|
8
|
-
//
|
|
7
|
+
// inline data and the tree URL are native react-msaview snapshot props, set
|
|
8
|
+
// directly. Only sources needing launch-time resolution go through `init`:
|
|
9
|
+
// msaUrl (AlphaFold sniff) and the name-indexed bgzip block (no native loader).
|
|
9
10
|
session.addView('MsaView', {
|
|
10
11
|
type: 'MsaView',
|
|
11
12
|
...rest,
|
|
13
|
+
data,
|
|
14
|
+
...(treeFileLocation
|
|
15
|
+
? {
|
|
16
|
+
treeFilehandle: {
|
|
17
|
+
...treeFileLocation,
|
|
18
|
+
locationType: 'UriLocation',
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
: {}),
|
|
12
22
|
init: {
|
|
13
|
-
msaData: data?.msa,
|
|
14
|
-
treeData: data?.tree,
|
|
15
23
|
msaUrl: msaFileLocation?.uri,
|
|
16
24
|
msaIndexedLocation,
|
|
17
25
|
msaName,
|
|
18
|
-
treeUrl: treeFileLocation?.uri,
|
|
19
26
|
querySeqName,
|
|
20
27
|
},
|
|
21
28
|
});
|
|
@@ -18,8 +18,6 @@ export declare function processInit(self: JBrowsePluginMsaViewModel): void;
|
|
|
18
18
|
* column the user is hovering directly in the MSA.
|
|
19
19
|
*/
|
|
20
20
|
export declare function syncGenomeHoverToMsaColumn(self: JBrowsePluginMsaViewModel): () => void;
|
|
21
|
-
export declare function highlightConnectedStructures(self: JBrowsePluginMsaViewModel): void;
|
|
22
|
-
export declare function autoConnectStructures(self: JBrowsePluginMsaViewModel): void;
|
|
23
21
|
/**
|
|
24
22
|
* Mirror a connected 3D protein view's hovered residue onto the MSA's
|
|
25
23
|
* highlighted columns. Returns the autorun body and keeps a flag tracking
|
|
@@ -4,7 +4,7 @@ import { fetchIndexedMsa } from './fetchIndexedMsa';
|
|
|
4
4
|
import { genomeToMSA } from './genomeToMSA';
|
|
5
5
|
import { loadProteinDomains } from './loadProteinDomains';
|
|
6
6
|
import { cleanupOldData, generateDataStoreId, retrieveMsaData, storeMsaData, } from './msaDataStore';
|
|
7
|
-
import {
|
|
7
|
+
import { getProteinViews } from './structureConnection';
|
|
8
8
|
import { getUniprotIdFromAlphaFoldUrl } from './util';
|
|
9
9
|
export function loadStoredData(self) {
|
|
10
10
|
const { dataStoreId, rows } = self;
|
|
@@ -116,14 +116,15 @@ export function autoLoadProteinDomains(self) {
|
|
|
116
116
|
})();
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
// Resolve the declarative `init` launch contract once
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
119
|
+
// Resolve the declarative `init` launch contract once, then clear it. msaUrl is
|
|
120
|
+
// handed to react-msaview's native filehandle loader (openLocation + progress +
|
|
121
|
+
// abort + CORS-proxy) and sniffed for an AlphaFold uniprotId; the bgzip
|
|
122
|
+
// name-indexed block is the one source with no native loader, so it's fetched
|
|
123
|
+
// here. Inline data and tree URLs arrive as native snapshot props, not via init.
|
|
123
124
|
export function processInit(self) {
|
|
124
125
|
const { init } = self;
|
|
125
126
|
if (init) {
|
|
126
|
-
const {
|
|
127
|
+
const { msaUrl, msaIndexedLocation, msaName, querySeqName } = init;
|
|
127
128
|
void (async () => {
|
|
128
129
|
try {
|
|
129
130
|
self.setError(undefined);
|
|
@@ -137,10 +138,7 @@ export function processInit(self) {
|
|
|
137
138
|
if (querySeqName) {
|
|
138
139
|
self.setQuerySeqName(querySeqName);
|
|
139
140
|
}
|
|
140
|
-
if (
|
|
141
|
-
self.setMSA(msaData);
|
|
142
|
-
}
|
|
143
|
-
else if (msaUrl) {
|
|
141
|
+
if (msaUrl) {
|
|
144
142
|
self.setMSAFilehandle({ uri: msaUrl, locationType: 'UriLocation' });
|
|
145
143
|
}
|
|
146
144
|
else if (msaIndexedLocation && msaName) {
|
|
@@ -155,12 +153,6 @@ export function processInit(self) {
|
|
|
155
153
|
throw new Error(`No alignment named ${msaName} in ${msaIndexedLocation.uri}`);
|
|
156
154
|
}
|
|
157
155
|
}
|
|
158
|
-
if (treeData) {
|
|
159
|
-
self.setTree(treeData);
|
|
160
|
-
}
|
|
161
|
-
else if (treeUrl) {
|
|
162
|
-
self.setTreeFilehandle({ uri: treeUrl, locationType: 'UriLocation' });
|
|
163
|
-
}
|
|
164
156
|
self.setInit(undefined);
|
|
165
157
|
}
|
|
166
158
|
catch (e) {
|
|
@@ -191,71 +183,6 @@ export function syncGenomeHoverToMsaColumn(self) {
|
|
|
191
183
|
}
|
|
192
184
|
};
|
|
193
185
|
}
|
|
194
|
-
export function highlightConnectedStructures(self) {
|
|
195
|
-
const { mouseCol, connectedProteinViews } = self;
|
|
196
|
-
if (connectedProteinViews.length === 0) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
for (const conn of connectedProteinViews) {
|
|
200
|
-
const structure = conn.proteinView.structures[conn.structureIdx];
|
|
201
|
-
if (!structure) {
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
if (mouseCol === undefined) {
|
|
205
|
-
structure.clearHighlightFromExternal?.();
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
const seq = self.getSequenceByRowName(conn.msaRowName);
|
|
209
|
-
if (!seq) {
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
const msaUngapped = gappedToUngappedPosition(seq, mouseCol);
|
|
213
|
-
if (msaUngapped === undefined) {
|
|
214
|
-
structure.clearHighlightFromExternal?.();
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
const structurePos = conn.msaToStructure[msaUngapped];
|
|
218
|
-
if (structurePos === undefined) {
|
|
219
|
-
structure.clearHighlightFromExternal?.();
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
structure.highlightFromExternal?.(structurePos);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
export function autoConnectStructures(self) {
|
|
227
|
-
const { connectedViewId, uniprotId, rows, connectedStructures } = self;
|
|
228
|
-
if (!uniprotId || rows.length === 0) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
for (const view of getProteinViews(getSession(self).views)) {
|
|
232
|
-
for (let structureIdx = 0; structureIdx < view.structures.length; structureIdx++) {
|
|
233
|
-
const structure = view.structures[structureIdx];
|
|
234
|
-
if (!structure) {
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
if (structure.connectedViewId !== connectedViewId) {
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
if (structure.uniprotId !== uniprotId) {
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
const alreadyConnected = connectedStructures.some(c => c.proteinViewId === view.id && c.structureIdx === structureIdx);
|
|
244
|
-
if (alreadyConnected) {
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
if (!structure.structureSequences?.[0]) {
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
try {
|
|
251
|
-
self.connectToStructure(view.id, structureIdx);
|
|
252
|
-
}
|
|
253
|
-
catch (e) {
|
|
254
|
-
console.error('Failed to auto-connect to ProteinView:', e);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
186
|
/**
|
|
260
187
|
* Mirror a connected 3D protein view's hovered residue onto the MSA's
|
|
261
188
|
* highlighted columns. Returns the autorun body and keeps a flag tracking
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export type { MSAFormat } from 'msa-parsers';
|
|
2
|
-
import type { ProteinView, StructureConnection } from './structureConnection';
|
|
3
2
|
import type { MafRegion, MsaViewInitState } from './types';
|
|
4
3
|
import type { BlastDatabase, BlastProgram, MsaAlgorithm } from '../LaunchMsaView/components/NCBIBlastQuery/consts';
|
|
5
4
|
import type { Feature } from '@jbrowse/core/util';
|
|
@@ -159,7 +158,7 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
|
|
|
159
158
|
featureFilters: import("@jbrowse/mobx-state-tree").IMapType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
160
159
|
relativeTo: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
|
|
161
160
|
highlightColumns: import("@jbrowse/mobx-state-tree").IType<number[] | undefined, number[] | undefined, number[] | undefined>;
|
|
162
|
-
}, "init" | "querySeqName" | "zoomToBaseLevel" | "connectedViewId" | "connectedFeature" | "blastParams" | "uniprotId" | "
|
|
161
|
+
}, "init" | "querySeqName" | "zoomToBaseLevel" | "connectedViewId" | "connectedFeature" | "blastParams" | "uniprotId" | "dataStoreId" | "mafRegion"> & {
|
|
163
162
|
connectedViewId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
|
|
164
163
|
connectedFeature: import("@jbrowse/mobx-state-tree").IType<any, any, any>;
|
|
165
164
|
blastParams: import("@jbrowse/mobx-state-tree").IType<BlastParams | undefined, BlastParams | undefined, BlastParams | undefined>;
|
|
@@ -167,7 +166,6 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
|
|
|
167
166
|
uniprotId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
|
|
168
167
|
zoomToBaseLevel: import("@jbrowse/mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
169
168
|
init: import("@jbrowse/mobx-state-tree").IType<MsaViewInitState | undefined, MsaViewInitState | undefined, MsaViewInitState | undefined>;
|
|
170
|
-
connectedStructures: import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<StructureConnection, StructureConnection, StructureConnection>>;
|
|
171
169
|
dataStoreId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
|
|
172
170
|
mafRegion: import("@jbrowse/mobx-state-tree").IType<MafRegion | undefined, MafRegion | undefined, MafRegion | undefined>;
|
|
173
171
|
}, {
|
|
@@ -478,12 +476,6 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
|
|
|
478
476
|
* #getter
|
|
479
477
|
*/
|
|
480
478
|
readonly connectedView: MaybeLGV;
|
|
481
|
-
/**
|
|
482
|
-
* #getter
|
|
483
|
-
*/
|
|
484
|
-
readonly connectedProteinViews: (StructureConnection & {
|
|
485
|
-
proteinView: ProteinView;
|
|
486
|
-
})[];
|
|
487
479
|
} & {
|
|
488
480
|
/**
|
|
489
481
|
* #getter
|
|
@@ -546,18 +538,6 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
|
|
|
546
538
|
* #action
|
|
547
539
|
*/
|
|
548
540
|
handleMsaClick(coord: number): void;
|
|
549
|
-
/**
|
|
550
|
-
* #action
|
|
551
|
-
*/
|
|
552
|
-
connectToStructure(proteinViewId: string, structureIdx: number, msaRowName?: string): void;
|
|
553
|
-
/**
|
|
554
|
-
* #action
|
|
555
|
-
*/
|
|
556
|
-
disconnectFromStructure(proteinViewId: string, structureIdx: number): void;
|
|
557
|
-
/**
|
|
558
|
-
* #action
|
|
559
|
-
*/
|
|
560
|
-
disconnectAllStructures(): void;
|
|
561
541
|
} & {
|
|
562
542
|
/**
|
|
563
543
|
* #action
|
|
@@ -567,17 +547,12 @@ export default function stateModelFactory(): import("@jbrowse/mobx-state-tree").
|
|
|
567
547
|
/**
|
|
568
548
|
* #method
|
|
569
549
|
*/
|
|
570
|
-
extraViewMenuItems():
|
|
550
|
+
extraViewMenuItems(): {
|
|
571
551
|
label: string;
|
|
572
552
|
checked: boolean;
|
|
573
553
|
type: string;
|
|
574
554
|
onClick: () => void;
|
|
575
|
-
}
|
|
576
|
-
label: string;
|
|
577
|
-
onClick: () => void;
|
|
578
|
-
checked?: undefined;
|
|
579
|
-
type?: undefined;
|
|
580
|
-
})[];
|
|
555
|
+
}[];
|
|
581
556
|
} & {
|
|
582
557
|
afterCreate(): void;
|
|
583
558
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree").ModelSnapshotType<{
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import { lazy } from 'react';
|
|
2
1
|
import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes';
|
|
3
2
|
import { getSession } from '@jbrowse/core/util';
|
|
4
3
|
import { addDisposer, types } from '@jbrowse/mobx-state-tree';
|
|
5
4
|
import { genomeToTranscriptSeqMapping } from 'g2p_mapper';
|
|
6
5
|
import { autorun } from 'mobx';
|
|
7
6
|
import { MSAModelF } from 'react-msaview';
|
|
8
|
-
import {
|
|
7
|
+
import { autoLoadProteinDomains, launchBlastIfNeeded, loadStoredData, observeProteinHighlights, processInit, runCleanup, storeDataToIndexedDB, syncGenomeHoverToMsaColumn, } from './afterCreateAutoruns';
|
|
9
8
|
import { msaCoordToGenomeCoord } from './msaCoordToGenomeCoord';
|
|
10
|
-
import { buildAlignmentMaps, runPairwiseAlignment } from './pairwiseAlignment';
|
|
11
|
-
import { getProteinViews } from './structureConnection';
|
|
12
|
-
import { getCanonicalRefName } from './util';
|
|
13
|
-
const ConnectStructureDialog = lazy(() => import('./components/ConnectStructureDialog'));
|
|
14
9
|
/**
|
|
15
10
|
* #stateModel MsaViewPlugin
|
|
16
11
|
* extends
|
|
@@ -47,10 +42,6 @@ export default function stateModelFactory() {
|
|
|
47
42
|
* #property
|
|
48
43
|
*/
|
|
49
44
|
init: types.frozen(),
|
|
50
|
-
/**
|
|
51
|
-
* #property
|
|
52
|
-
*/
|
|
53
|
-
connectedStructures: types.array(types.frozen()),
|
|
54
45
|
/**
|
|
55
46
|
* #property
|
|
56
47
|
*/
|
|
@@ -118,20 +109,6 @@ export default function stateModelFactory() {
|
|
|
118
109
|
const { views } = getSession(self);
|
|
119
110
|
return views.find(f => f.id === self.connectedViewId);
|
|
120
111
|
},
|
|
121
|
-
/**
|
|
122
|
-
* #getter
|
|
123
|
-
*/
|
|
124
|
-
get connectedProteinViews() {
|
|
125
|
-
const proteinViews = getProteinViews(getSession(self).views);
|
|
126
|
-
const result = [];
|
|
127
|
-
for (const conn of self.connectedStructures) {
|
|
128
|
-
const proteinView = proteinViews.find(v => v.id === conn.proteinViewId);
|
|
129
|
-
if (proteinView) {
|
|
130
|
-
result.push({ ...conn, proteinView });
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return result;
|
|
134
|
-
},
|
|
135
112
|
}))
|
|
136
113
|
.views(self => ({
|
|
137
114
|
/**
|
|
@@ -233,71 +210,20 @@ export default function stateModelFactory() {
|
|
|
233
210
|
*/
|
|
234
211
|
handleMsaClick(coord) {
|
|
235
212
|
const { connectedView, zoomToBaseLevel } = self;
|
|
236
|
-
const { assemblyManager } = getSession(self);
|
|
237
213
|
const r2 = msaCoordToGenomeCoord({ model: self, coord });
|
|
238
214
|
if (!r2 || !connectedView) {
|
|
239
215
|
return;
|
|
240
216
|
}
|
|
217
|
+
// Use the genome coord's own refName for both nav paths — it matches the
|
|
218
|
+
// connected view's displayed regions. Canonicalizing (e.g. "chr17"->"17")
|
|
219
|
+
// can miss a view whose regions are an alias (same as the bpToPx path).
|
|
241
220
|
if (zoomToBaseLevel) {
|
|
242
221
|
connectedView.navTo(r2);
|
|
243
222
|
}
|
|
244
223
|
else {
|
|
245
|
-
|
|
246
|
-
assemblyManager,
|
|
247
|
-
assemblyNames: connectedView.assemblyNames,
|
|
248
|
-
refName: r2.refName,
|
|
249
|
-
});
|
|
250
|
-
connectedView.centerAt(r2.start, r);
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
/**
|
|
254
|
-
* #action
|
|
255
|
-
*/
|
|
256
|
-
connectToStructure(proteinViewId, structureIdx, msaRowName) {
|
|
257
|
-
const rowName = msaRowName ?? self.querySeqName;
|
|
258
|
-
const msaSequence = self.getSequenceByRowName(rowName);
|
|
259
|
-
if (!msaSequence) {
|
|
260
|
-
throw new Error(`MSA row "${rowName}" not found`);
|
|
261
|
-
}
|
|
262
|
-
const ungappedMsaSequence = msaSequence.replaceAll('-', '');
|
|
263
|
-
const proteinView = getProteinViews(getSession(self).views).find(v => v.id === proteinViewId);
|
|
264
|
-
if (!proteinView) {
|
|
265
|
-
throw new Error(`ProteinView "${proteinViewId}" not found`);
|
|
266
|
-
}
|
|
267
|
-
const structure = proteinView.structures[structureIdx];
|
|
268
|
-
if (!structure) {
|
|
269
|
-
throw new Error(`Structure at index ${structureIdx} not found`);
|
|
270
|
-
}
|
|
271
|
-
const structureSequence = structure.structureSequences?.[0];
|
|
272
|
-
if (!structureSequence) {
|
|
273
|
-
throw new Error('Structure sequence not available');
|
|
274
|
-
}
|
|
275
|
-
const alignment = runPairwiseAlignment(ungappedMsaSequence, structureSequence);
|
|
276
|
-
const { seq1ToSeq2 } = buildAlignmentMaps(alignment);
|
|
277
|
-
const connection = {
|
|
278
|
-
proteinViewId,
|
|
279
|
-
structureIdx,
|
|
280
|
-
msaRowName: rowName,
|
|
281
|
-
msaToStructure: Object.fromEntries(seq1ToSeq2),
|
|
282
|
-
};
|
|
283
|
-
self.connectedStructures.push(connection);
|
|
284
|
-
},
|
|
285
|
-
/**
|
|
286
|
-
* #action
|
|
287
|
-
*/
|
|
288
|
-
disconnectFromStructure(proteinViewId, structureIdx) {
|
|
289
|
-
const idx = self.connectedStructures.findIndex(c => c.proteinViewId === proteinViewId &&
|
|
290
|
-
c.structureIdx === structureIdx);
|
|
291
|
-
if (idx !== -1) {
|
|
292
|
-
self.connectedStructures.splice(idx, 1);
|
|
224
|
+
connectedView.centerAt(r2.start, r2.refName);
|
|
293
225
|
}
|
|
294
226
|
},
|
|
295
|
-
/**
|
|
296
|
-
* #action
|
|
297
|
-
*/
|
|
298
|
-
disconnectAllStructures() {
|
|
299
|
-
self.connectedStructures.clear();
|
|
300
|
-
},
|
|
301
227
|
}))
|
|
302
228
|
.actions(self => {
|
|
303
229
|
const superSetMouseClickPos = self.setMouseClickPos.bind(self);
|
|
@@ -327,28 +253,6 @@ export default function stateModelFactory() {
|
|
|
327
253
|
self.setZoomToBaseLevel(!self.zoomToBaseLevel);
|
|
328
254
|
},
|
|
329
255
|
},
|
|
330
|
-
{
|
|
331
|
-
label: 'Connect to protein structure...',
|
|
332
|
-
onClick: () => {
|
|
333
|
-
getSession(self).queueDialog(handleClose => [
|
|
334
|
-
ConnectStructureDialog,
|
|
335
|
-
{
|
|
336
|
-
model: self,
|
|
337
|
-
handleClose,
|
|
338
|
-
},
|
|
339
|
-
]);
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
...(self.connectedStructures.length > 0
|
|
343
|
-
? [
|
|
344
|
-
{
|
|
345
|
-
label: 'Disconnect from protein structures',
|
|
346
|
-
onClick: () => {
|
|
347
|
-
self.disconnectAllStructures();
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
]
|
|
351
|
-
: []),
|
|
352
256
|
];
|
|
353
257
|
},
|
|
354
258
|
}))
|
|
@@ -360,8 +264,6 @@ export default function stateModelFactory() {
|
|
|
360
264
|
storeDataToIndexedDB,
|
|
361
265
|
launchBlastIfNeeded,
|
|
362
266
|
processInit,
|
|
363
|
-
highlightConnectedStructures,
|
|
364
|
-
autoConnectStructures,
|
|
365
267
|
autoLoadProteinDomains,
|
|
366
268
|
]) {
|
|
367
269
|
addDisposer(self, autorun(() => {
|
|
@@ -7,11 +7,6 @@ export interface ProteinViewStructure {
|
|
|
7
7
|
start: number;
|
|
8
8
|
end: number;
|
|
9
9
|
}[];
|
|
10
|
-
hoverPosition?: {
|
|
11
|
-
structureSeqPos?: number;
|
|
12
|
-
};
|
|
13
|
-
clearHighlightFromExternal?: () => void;
|
|
14
|
-
highlightFromExternal?: (pos: number) => void;
|
|
15
10
|
}
|
|
16
11
|
export interface ProteinView {
|
|
17
12
|
type: 'ProteinView';
|
|
@@ -26,19 +21,6 @@ export declare function isProteinView(view: unknown): view is ProteinView;
|
|
|
26
21
|
export declare function getProteinViews(views: {
|
|
27
22
|
type: string;
|
|
28
23
|
}[]): ProteinView[];
|
|
29
|
-
/**
|
|
30
|
-
* Represents a connection between the MSA view and a protein structure
|
|
31
|
-
*/
|
|
32
|
-
export interface StructureConnection {
|
|
33
|
-
/** ID of the ProteinView containing the structure */
|
|
34
|
-
proteinViewId: string;
|
|
35
|
-
/** Index of the structure within the ProteinView's structures array */
|
|
36
|
-
structureIdx: number;
|
|
37
|
-
/** Name of the MSA row that corresponds to this structure */
|
|
38
|
-
msaRowName: string;
|
|
39
|
-
/** Map from MSA ungapped position to structure sequence position */
|
|
40
|
-
msaToStructure: Record<number, number>;
|
|
41
|
-
}
|
|
42
24
|
/**
|
|
43
25
|
* Helper to convert gapped MSA column to ungapped position for a specific row
|
|
44
26
|
*/
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
export interface MsaViewInitState {
|
|
2
|
-
msaData?: string;
|
|
3
2
|
msaUrl?: string;
|
|
3
|
+
querySeqName?: string;
|
|
4
4
|
msaIndexedLocation?: {
|
|
5
5
|
uri: string;
|
|
6
6
|
};
|
|
7
7
|
msaName?: string;
|
|
8
|
-
treeData?: string;
|
|
9
|
-
treeUrl?: string;
|
|
10
|
-
querySeqName?: string;
|
|
11
8
|
}
|
|
12
9
|
export interface MafRegion {
|
|
13
10
|
refName: string;
|