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.
Files changed (29) hide show
  1. package/dist/AddHighlightModel/MsaToGenomeHighlight.js +8 -9
  2. package/dist/LaunchMsaViewExtensionPoint/index.js +12 -5
  3. package/dist/MsaViewPanel/afterCreateAutoruns.d.ts +0 -2
  4. package/dist/MsaViewPanel/afterCreateAutoruns.js +8 -81
  5. package/dist/MsaViewPanel/model.d.ts +3 -28
  6. package/dist/MsaViewPanel/model.js +5 -103
  7. package/dist/MsaViewPanel/structureConnection.d.ts +0 -18
  8. package/dist/MsaViewPanel/types.d.ts +1 -4
  9. package/dist/jbrowse-plugin-msaview.umd.production.min.js +26 -26
  10. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
  11. package/dist/version.d.ts +1 -1
  12. package/dist/version.js +1 -1
  13. package/package.json +1 -1
  14. package/src/AddHighlightModel/MsaToGenomeHighlight.tsx +8 -9
  15. package/src/LaunchMsaViewExtensionPoint/index.ts +12 -5
  16. package/src/MsaViewPanel/afterCreateAutoruns.ts +8 -109
  17. package/src/MsaViewPanel/model.ts +4 -135
  18. package/src/MsaViewPanel/structureConnection.ts +0 -17
  19. package/src/MsaViewPanel/types.ts +14 -9
  20. package/src/version.ts +1 -1
  21. package/dist/MsaViewPanel/components/ConnectStructureDialog.d.ts +0 -7
  22. package/dist/MsaViewPanel/components/ConnectStructureDialog.js +0 -60
  23. package/dist/MsaViewPanel/pairwiseAlignment.d.ts +0 -20
  24. package/dist/MsaViewPanel/pairwiseAlignment.js +0 -138
  25. package/dist/MsaViewPanel/pairwiseAlignment.test.d.ts +0 -1
  26. package/dist/MsaViewPanel/pairwiseAlignment.test.js +0 -111
  27. package/src/MsaViewPanel/components/ConnectStructureDialog.tsx +0 -154
  28. package/src/MsaViewPanel/pairwiseAlignment.test.ts +0 -140
  29. package/src/MsaViewPanel/pairwiseAlignment.ts +0 -182
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.6.2";
1
+ export declare const version = "2.6.4";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.6.2';
1
+ export const version = '2.6.4';
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.6.2",
2
+ "version": "2.6.4",
3
3
  "license": "MIT",
4
4
  "name": "jbrowse-plugin-msaview",
5
5
  "repository": {
@@ -5,7 +5,6 @@ import { observer } from 'mobx-react'
5
5
 
6
6
  import { hasHoverPosition, useStyles } from './util'
7
7
  import { isMsaView } from '../MsaViewPanel/model'
8
- import { getCanonicalRefName } from '../MsaViewPanel/util'
9
8
 
10
9
  import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
11
10
 
@@ -38,19 +37,19 @@ const MsaToGenomeHighlightRenderer = observer(function ({
38
37
  highlights: { refName: string; start: number; end: number }[]
39
38
  }) {
40
39
  const { classes } = useStyles()
41
- const { assemblyManager } = getSession(model)
42
40
  const { offsetPx } = model
43
41
 
44
42
  return (
45
43
  <>
46
44
  {highlights.map((r, idx) => {
47
- const refName = getCanonicalRefName({
48
- assemblyManager,
49
- assemblyNames: model.assemblyNames,
50
- refName: r.refName,
51
- })
52
- const s = model.bpToPx({ refName, coord: r.start })
53
- const e = model.bpToPx({ refName, coord: r.end })
45
+ // Use the highlight's own refName, which is already in the connected
46
+ // view's coordinate space (it comes from the connectedFeature the
47
+ // launcher set on this LGV). Do NOT canonicalize: bpToPx matches
48
+ // displayed regions by exact refName with no alias resolution, so
49
+ // rewriting e.g. "chr17" to the assembly-canonical "17" misses a view
50
+ // whose regions are "chr17". (GenomeMouseoverHighlight does the same.)
51
+ const s = model.bpToPx({ refName: r.refName, coord: r.start })
52
+ const e = model.bpToPx({ refName: r.refName, coord: r.end })
54
53
  if (s && e) {
55
54
  const width = Math.max(Math.abs(e.offsetPx - s.offsetPx), 4)
56
55
  const left = Math.min(s.offsetPx, e.offsetPx) - offsetPx
@@ -46,18 +46,25 @@ export default function LaunchMsaViewExtensionPointF(
46
46
  )
47
47
  }
48
48
 
49
- // all data sources flow through `init` so processInit is the single place
50
- // that resolves them (AlphaFold detection, native filehandle loading, etc.)
49
+ // inline data and the tree URL are native react-msaview snapshot props, set
50
+ // directly. Only sources needing launch-time resolution go through `init`:
51
+ // msaUrl (AlphaFold sniff) and the name-indexed bgzip block (no native loader).
51
52
  session.addView('MsaView', {
52
53
  type: 'MsaView',
53
54
  ...rest,
55
+ data,
56
+ ...(treeFileLocation
57
+ ? {
58
+ treeFilehandle: {
59
+ ...treeFileLocation,
60
+ locationType: 'UriLocation',
61
+ },
62
+ }
63
+ : {}),
54
64
  init: {
55
- msaData: data?.msa,
56
- treeData: data?.tree,
57
65
  msaUrl: msaFileLocation?.uri,
58
66
  msaIndexedLocation,
59
67
  msaName,
60
- treeUrl: treeFileLocation?.uri,
61
68
  querySeqName,
62
69
  },
63
70
  })
@@ -10,10 +10,7 @@ import {
10
10
  retrieveMsaData,
11
11
  storeMsaData,
12
12
  } from './msaDataStore'
13
- import {
14
- gappedToUngappedPosition,
15
- getProteinViews,
16
- } from './structureConnection'
13
+ import { getProteinViews } from './structureConnection'
17
14
  import { getUniprotIdFromAlphaFoldUrl } from './util'
18
15
 
19
16
  import type { JBrowsePluginMsaViewModel } from './model'
@@ -128,22 +125,15 @@ export function autoLoadProteinDomains(self: JBrowsePluginMsaViewModel) {
128
125
  }
129
126
  }
130
127
 
131
- // Resolve the declarative `init` launch contract once. Inline strings go straight
132
- // to the data model; URLs are handed to react-msaview's native filehandle loaders
133
- // (openLocation + progress + abort + CORS-proxy) rather than a hand-rolled fetch;
134
- // the bgzip name-indexed block is the one source with no native loader.
128
+ // Resolve the declarative `init` launch contract once, then clear it. msaUrl is
129
+ // handed to react-msaview's native filehandle loader (openLocation + progress +
130
+ // abort + CORS-proxy) and sniffed for an AlphaFold uniprotId; the bgzip
131
+ // name-indexed block is the one source with no native loader, so it's fetched
132
+ // here. Inline data and tree URLs arrive as native snapshot props, not via init.
135
133
  export function processInit(self: JBrowsePluginMsaViewModel) {
136
134
  const { init } = self
137
135
  if (init) {
138
- const {
139
- msaData,
140
- msaUrl,
141
- msaIndexedLocation,
142
- msaName,
143
- treeData,
144
- treeUrl,
145
- querySeqName,
146
- } = init
136
+ const { msaUrl, msaIndexedLocation, msaName, querySeqName } = init
147
137
  void (async () => {
148
138
  try {
149
139
  self.setError(undefined)
@@ -159,9 +149,7 @@ export function processInit(self: JBrowsePluginMsaViewModel) {
159
149
  self.setQuerySeqName(querySeqName)
160
150
  }
161
151
 
162
- if (msaData) {
163
- self.setMSA(msaData)
164
- } else if (msaUrl) {
152
+ if (msaUrl) {
165
153
  self.setMSAFilehandle({ uri: msaUrl, locationType: 'UriLocation' })
166
154
  } else if (msaIndexedLocation && msaName) {
167
155
  const fasta = await fetchIndexedMsa({
@@ -177,12 +165,6 @@ export function processInit(self: JBrowsePluginMsaViewModel) {
177
165
  }
178
166
  }
179
167
 
180
- if (treeData) {
181
- self.setTree(treeData)
182
- } else if (treeUrl) {
183
- self.setTreeFilehandle({ uri: treeUrl, locationType: 'UriLocation' })
184
- }
185
-
186
168
  self.setInit(undefined)
187
169
  } catch (e) {
188
170
  self.setError(e)
@@ -213,89 +195,6 @@ export function syncGenomeHoverToMsaColumn(self: JBrowsePluginMsaViewModel) {
213
195
  }
214
196
  }
215
197
 
216
- export function highlightConnectedStructures(self: JBrowsePluginMsaViewModel) {
217
- const { mouseCol, connectedProteinViews } = self
218
- if (connectedProteinViews.length === 0) {
219
- return
220
- }
221
-
222
- for (const conn of connectedProteinViews) {
223
- const structure = conn.proteinView.structures[conn.structureIdx]
224
- if (!structure) {
225
- continue
226
- }
227
-
228
- if (mouseCol === undefined) {
229
- structure.clearHighlightFromExternal?.()
230
- continue
231
- }
232
-
233
- const seq = self.getSequenceByRowName(conn.msaRowName)
234
- if (!seq) {
235
- continue
236
- }
237
-
238
- const msaUngapped = gappedToUngappedPosition(seq, mouseCol)
239
- if (msaUngapped === undefined) {
240
- structure.clearHighlightFromExternal?.()
241
- continue
242
- }
243
-
244
- const structurePos = conn.msaToStructure[msaUngapped]
245
- if (structurePos === undefined) {
246
- structure.clearHighlightFromExternal?.()
247
- } else {
248
- structure.highlightFromExternal?.(structurePos)
249
- }
250
- }
251
- }
252
-
253
- export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
254
- const { connectedViewId, uniprotId, rows, connectedStructures } = self
255
-
256
- if (!uniprotId || rows.length === 0) {
257
- return
258
- }
259
-
260
- for (const view of getProteinViews(getSession(self).views)) {
261
- for (
262
- let structureIdx = 0;
263
- structureIdx < view.structures.length;
264
- structureIdx++
265
- ) {
266
- const structure = view.structures[structureIdx]
267
- if (!structure) {
268
- continue
269
- }
270
-
271
- if (structure.connectedViewId !== connectedViewId) {
272
- continue
273
- }
274
-
275
- if (structure.uniprotId !== uniprotId) {
276
- continue
277
- }
278
-
279
- const alreadyConnected = connectedStructures.some(
280
- c => c.proteinViewId === view.id && c.structureIdx === structureIdx,
281
- )
282
- if (alreadyConnected) {
283
- continue
284
- }
285
-
286
- if (!structure.structureSequences?.[0]) {
287
- continue
288
- }
289
-
290
- try {
291
- self.connectToStructure(view.id, structureIdx)
292
- } catch (e) {
293
- console.error('Failed to auto-connect to ProteinView:', e)
294
- }
295
- }
296
- }
297
- }
298
-
299
198
  /**
300
199
  * Mirror a connected 3D protein view's hovered residue onto the MSA's
301
200
  * highlighted columns. Returns the autorun body and keeps a flag tracking
@@ -1,5 +1,3 @@
1
- import { lazy } from 'react'
2
-
3
1
  import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes'
4
2
  import { getSession } from '@jbrowse/core/util'
5
3
  import { addDisposer, types } from '@jbrowse/mobx-state-tree'
@@ -12,9 +10,7 @@ import { MSAModelF } from 'react-msaview'
12
10
  export type { MSAFormat } from 'msa-parsers'
13
11
 
14
12
  import {
15
- autoConnectStructures,
16
13
  autoLoadProteinDomains,
17
- highlightConnectedStructures,
18
14
  launchBlastIfNeeded,
19
15
  loadStoredData,
20
16
  observeProteinHighlights,
@@ -24,11 +20,7 @@ import {
24
20
  syncGenomeHoverToMsaColumn,
25
21
  } from './afterCreateAutoruns'
26
22
  import { msaCoordToGenomeCoord } from './msaCoordToGenomeCoord'
27
- import { buildAlignmentMaps, runPairwiseAlignment } from './pairwiseAlignment'
28
- import { getProteinViews } from './structureConnection'
29
- import { getCanonicalRefName } from './util'
30
23
 
31
- import type { ProteinView, StructureConnection } from './structureConnection'
32
24
  import type { MafRegion, MsaViewInitState } from './types'
33
25
  import type {
34
26
  BlastDatabase,
@@ -39,10 +31,6 @@ import type { Feature } from '@jbrowse/core/util'
39
31
  import type { Instance } from '@jbrowse/mobx-state-tree'
40
32
  import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
41
33
 
42
- const ConnectStructureDialog = lazy(
43
- () => import('./components/ConnectStructureDialog'),
44
- )
45
-
46
34
  type LGV = LinearGenomeViewModel
47
35
 
48
36
  type MaybeLGV = LGV | undefined
@@ -106,11 +94,6 @@ export default function stateModelFactory() {
106
94
  */
107
95
  init: types.frozen<MsaViewInitState | undefined>(),
108
96
 
109
- /**
110
- * #property
111
- */
112
- connectedStructures: types.array(types.frozen<StructureConnection>()),
113
-
114
97
  /**
115
98
  * #property
116
99
  */
@@ -194,24 +177,6 @@ export default function stateModelFactory() {
194
177
  const { views } = getSession(self)
195
178
  return views.find(f => f.id === self.connectedViewId) as MaybeLGV
196
179
  },
197
-
198
- /**
199
- * #getter
200
- */
201
- get connectedProteinViews() {
202
- const proteinViews = getProteinViews(getSession(self).views)
203
- const result: (StructureConnection & { proteinView: ProteinView })[] =
204
- []
205
- for (const conn of self.connectedStructures) {
206
- const proteinView = proteinViews.find(
207
- v => v.id === conn.proteinViewId,
208
- )
209
- if (proteinView) {
210
- result.push({ ...conn, proteinView })
211
- }
212
- }
213
- return result
214
- },
215
180
  }))
216
181
 
217
182
  .views(self => ({
@@ -315,94 +280,22 @@ export default function stateModelFactory() {
315
280
  */
316
281
  handleMsaClick(coord: number) {
317
282
  const { connectedView, zoomToBaseLevel } = self
318
- const { assemblyManager } = getSession(self)
319
283
  const r2 = msaCoordToGenomeCoord({ model: self, coord })
320
284
 
321
285
  if (!r2 || !connectedView) {
322
286
  return
323
287
  }
324
288
 
289
+ // Use the genome coord's own refName for both nav paths — it matches the
290
+ // connected view's displayed regions. Canonicalizing (e.g. "chr17"->"17")
291
+ // can miss a view whose regions are an alias (same as the bpToPx path).
325
292
  if (zoomToBaseLevel) {
326
293
  connectedView.navTo(r2)
327
294
  } else {
328
- const r = getCanonicalRefName({
329
- assemblyManager,
330
- assemblyNames: connectedView.assemblyNames,
331
- refName: r2.refName,
332
- })
333
- connectedView.centerAt(r2.start, r)
295
+ connectedView.centerAt(r2.start, r2.refName)
334
296
  }
335
297
  },
336
298
 
337
- /**
338
- * #action
339
- */
340
- connectToStructure(
341
- proteinViewId: string,
342
- structureIdx: number,
343
- msaRowName?: string,
344
- ) {
345
- const rowName = msaRowName ?? self.querySeqName
346
- const msaSequence = self.getSequenceByRowName(rowName)
347
- if (!msaSequence) {
348
- throw new Error(`MSA row "${rowName}" not found`)
349
- }
350
-
351
- const ungappedMsaSequence = msaSequence.replaceAll('-', '')
352
-
353
- const proteinView = getProteinViews(getSession(self).views).find(
354
- v => v.id === proteinViewId,
355
- )
356
- if (!proteinView) {
357
- throw new Error(`ProteinView "${proteinViewId}" not found`)
358
- }
359
-
360
- const structure = proteinView.structures[structureIdx]
361
- if (!structure) {
362
- throw new Error(`Structure at index ${structureIdx} not found`)
363
- }
364
-
365
- const structureSequence = structure.structureSequences?.[0]
366
- if (!structureSequence) {
367
- throw new Error('Structure sequence not available')
368
- }
369
-
370
- const alignment = runPairwiseAlignment(
371
- ungappedMsaSequence,
372
- structureSequence,
373
- )
374
- const { seq1ToSeq2 } = buildAlignmentMaps(alignment)
375
-
376
- const connection: StructureConnection = {
377
- proteinViewId,
378
- structureIdx,
379
- msaRowName: rowName,
380
- msaToStructure: Object.fromEntries(seq1ToSeq2),
381
- }
382
-
383
- self.connectedStructures.push(connection)
384
- },
385
-
386
- /**
387
- * #action
388
- */
389
- disconnectFromStructure(proteinViewId: string, structureIdx: number) {
390
- const idx = self.connectedStructures.findIndex(
391
- c =>
392
- c.proteinViewId === proteinViewId &&
393
- c.structureIdx === structureIdx,
394
- )
395
- if (idx !== -1) {
396
- self.connectedStructures.splice(idx, 1)
397
- }
398
- },
399
-
400
- /**
401
- * #action
402
- */
403
- disconnectAllStructures() {
404
- self.connectedStructures.clear()
405
- },
406
299
  }))
407
300
  .actions(self => {
408
301
  const superSetMouseClickPos = self.setMouseClickPos.bind(self)
@@ -434,28 +327,6 @@ export default function stateModelFactory() {
434
327
  self.setZoomToBaseLevel(!self.zoomToBaseLevel)
435
328
  },
436
329
  },
437
- {
438
- label: 'Connect to protein structure...',
439
- onClick: () => {
440
- getSession(self).queueDialog(handleClose => [
441
- ConnectStructureDialog,
442
- {
443
- model: self,
444
- handleClose,
445
- },
446
- ])
447
- },
448
- },
449
- ...(self.connectedStructures.length > 0
450
- ? [
451
- {
452
- label: 'Disconnect from protein structures',
453
- onClick: () => {
454
- self.disconnectAllStructures()
455
- },
456
- },
457
- ]
458
- : []),
459
330
  ]
460
331
  },
461
332
  }))
@@ -468,8 +339,6 @@ export default function stateModelFactory() {
468
339
  storeDataToIndexedDB,
469
340
  launchBlastIfNeeded,
470
341
  processInit,
471
- highlightConnectedStructures,
472
- autoConnectStructures,
473
342
  autoLoadProteinDomains,
474
343
  ]) {
475
344
  addDisposer(
@@ -4,9 +4,6 @@ export interface ProteinViewStructure {
4
4
  uniprotId?: string
5
5
  structureSequences?: string[]
6
6
  hoverGenomeHighlights?: { start: number; end: number }[]
7
- hoverPosition?: { structureSeqPos?: number }
8
- clearHighlightFromExternal?: () => void
9
- highlightFromExternal?: (pos: number) => void
10
7
  }
11
8
 
12
9
  export interface ProteinView {
@@ -28,20 +25,6 @@ export function getProteinViews(views: { type: string }[]): ProteinView[] {
28
25
  return (views as unknown[]).filter(isProteinView)
29
26
  }
30
27
 
31
- /**
32
- * Represents a connection between the MSA view and a protein structure
33
- */
34
- export interface StructureConnection {
35
- /** ID of the ProteinView containing the structure */
36
- proteinViewId: string
37
- /** Index of the structure within the ProteinView's structures array */
38
- structureIdx: number
39
- /** Name of the MSA row that corresponds to this structure */
40
- msaRowName: string
41
- /** Map from MSA ungapped position to structure sequence position */
42
- msaToStructure: Record<number, number>
43
- }
44
-
45
28
  /**
46
29
  * Helper to convert gapped MSA column to ungapped position for a specific row
47
30
  */
@@ -1,19 +1,24 @@
1
- // Declarative launch contract, resolved once by processInit. This is also a
2
- // cross-repo contract: jbrowse-plugin-protein3d builds an MsaView snapshot
3
- // directly with `init: { msaUrl }`, so these keys must stay stable.
1
+ // Declarative launch contract, resolved once by processInit, then cleared. Only
2
+ // sources that need launch-time resolution belong here. Inline data and tree URLs
3
+ // do NOT: they are native react-msaview snapshot props (`data`, `treeFilehandle`)
4
+ // applied directly from the addView snapshot, no resolution required.
5
+ //
6
+ // Cross-repo contract: jbrowse-plugin-protein3d builds an MsaView snapshot directly
7
+ // with `init: { msaUrl }`, so these keys must stay stable.
4
8
  export interface MsaViewInitState {
5
- msaData?: string
9
+ // resolved here (not as a native msaFilehandle) so the AlphaFold-URL → uniprotId
10
+ // sniff runs once at launch; querySeqName is coupled to it (AlphaFold files name
11
+ // the query row 'query'), which is why it rides along in init rather than being a
12
+ // plain top-level prop.
6
13
  msaUrl?: string
14
+ querySeqName?: string
7
15
  // a single bgzip `.fa.gz` of per-transcript FASTA blocks; its `.gzi` and name
8
16
  // index `.idx` (name<TAB>offset<TAB>length) are found by suffix. `msaName`
9
17
  // selects one transcript's block by name (a random read), so one genome-scale
10
- // alignment serves any gene without per-gene files or coordinates. See
11
- // react-msaview's gene-explorer.
18
+ // alignment serves any gene without per-gene files or coordinates. This is the
19
+ // one alignment source with no native loader. See react-msaview's gene-explorer.
12
20
  msaIndexedLocation?: { uri: string }
13
21
  msaName?: string
14
- treeData?: string
15
- treeUrl?: string
16
- querySeqName?: string
17
22
  }
18
23
 
19
24
  export interface MafRegion {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '2.6.2'
1
+ export const version = '2.6.4'
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- import type { JBrowsePluginMsaViewModel } from '../model';
3
- declare const ConnectStructureDialog: ({ model, handleClose, }: {
4
- model: JBrowsePluginMsaViewModel;
5
- handleClose: () => void;
6
- }) => React.JSX.Element;
7
- export default ConnectStructureDialog;
@@ -1,60 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { Dialog, ErrorMessage } from '@jbrowse/core/ui';
3
- import { getSession } from '@jbrowse/core/util';
4
- import { Button, DialogActions, DialogContent, FormControl, InputLabel, MenuItem, Select, Typography, } from '@mui/material';
5
- import { observer } from 'mobx-react';
6
- import { makeStyles } from 'tss-react/mui';
7
- import { getProteinViews } from '../structureConnection';
8
- const useStyles = makeStyles()(theme => ({
9
- formControl: {
10
- marginBottom: theme.spacing(2),
11
- },
12
- }));
13
- const ConnectStructureDialog = observer(function ConnectStructureDialog({ model, handleClose, }) {
14
- const { classes } = useStyles();
15
- const session = getSession(model);
16
- const [selectedViewId, setSelectedViewId] = useState('');
17
- const [selectedStructureIdx, setSelectedStructureIdx] = useState(0);
18
- const [selectedMsaRow, setSelectedMsaRow] = useState(model.querySeqName);
19
- const [error, setError] = useState();
20
- const proteinViews = getProteinViews(session.views);
21
- const selectedView = proteinViews.find(v => v.id === selectedViewId);
22
- const structures = selectedView?.structures ?? [];
23
- const msaRowNames = model.rows.map(r => r[0]);
24
- const handleConnect = () => {
25
- if (!selectedViewId) {
26
- setError('Please select a protein view');
27
- return;
28
- }
29
- try {
30
- model.connectToStructure(selectedViewId, selectedStructureIdx, selectedMsaRow);
31
- handleClose();
32
- }
33
- catch (e) {
34
- setError(e instanceof Error ? e.message : String(e));
35
- }
36
- };
37
- return (React.createElement(Dialog, { maxWidth: "sm", title: "Connect to Protein Structure", open: true, onClose: handleClose },
38
- React.createElement(DialogContent, null, proteinViews.length === 0 ? (React.createElement(Typography, { color: "textSecondary" }, "No protein views are currently open. Please open a protein structure view first.")) : (React.createElement(React.Fragment, null,
39
- React.createElement(FormControl, { fullWidth: true, className: classes.formControl },
40
- React.createElement(InputLabel, null, "Protein View"),
41
- React.createElement(Select, { value: selectedViewId, label: "Protein View", onChange: e => {
42
- setSelectedViewId(e.target.value);
43
- setSelectedStructureIdx(0);
44
- } }, proteinViews.map(view => (React.createElement(MenuItem, { key: view.id, value: view.id }, view.displayName ?? `ProteinView ${view.id}`))))),
45
- structures.length > 1 ? (React.createElement(FormControl, { fullWidth: true, className: classes.formControl },
46
- React.createElement(InputLabel, null, "Structure"),
47
- React.createElement(Select, { value: selectedStructureIdx, label: "Structure", onChange: e => {
48
- setSelectedStructureIdx(e.target.value);
49
- } }, structures.map((structure, idx) => (React.createElement(MenuItem, { key: idx, value: idx }, structure.url ?? `Structure ${idx + 1}`)))))) : null,
50
- React.createElement(FormControl, { fullWidth: true, className: classes.formControl },
51
- React.createElement(InputLabel, null, "MSA Row"),
52
- React.createElement(Select, { value: selectedMsaRow, label: "MSA Row", onChange: e => {
53
- setSelectedMsaRow(e.target.value);
54
- } }, msaRowNames.map(name => (React.createElement(MenuItem, { key: name, value: name }, name))))),
55
- error ? React.createElement(ErrorMessage, { error: error }) : null))),
56
- React.createElement(DialogActions, null,
57
- React.createElement(Button, { onClick: handleClose }, "Cancel"),
58
- React.createElement(Button, { onClick: handleConnect, variant: "contained", disabled: proteinViews.length === 0 || !selectedViewId }, "Connect"))));
59
- });
60
- export default ConnectStructureDialog;
@@ -1,20 +0,0 @@
1
- interface AlignmentResult {
2
- alignedSeq1: string;
3
- alignedSeq2: string;
4
- score: number;
5
- }
6
- export interface AlignmentRow {
7
- id: string;
8
- seq: string;
9
- }
10
- export interface PairwiseAlignment {
11
- consensus: string;
12
- alns: readonly [AlignmentRow, AlignmentRow];
13
- }
14
- export declare function needlemanWunsch(seq1: string, seq2: string, gapOpen?: number, gapExtend?: number): AlignmentResult;
15
- export declare function runPairwiseAlignment(seq1: string, seq2: string): PairwiseAlignment;
16
- export declare function buildAlignmentMaps(pairwiseAlignment: PairwiseAlignment): {
17
- seq1ToSeq2: Map<number, number>;
18
- seq2ToSeq1: Map<number, number>;
19
- };
20
- export {};