@jbrowse/plugin-linear-comparative-view 3.6.5 → 3.7.0

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 (57) hide show
  1. package/dist/LGVSyntenyDisplay/model.d.ts +17 -2
  2. package/dist/LinearComparativeView/components/ColorBySelector.d.ts +5 -0
  3. package/dist/LinearComparativeView/components/ColorBySelector.js +54 -0
  4. package/dist/LinearComparativeView/components/Header.js +7 -2
  5. package/dist/LinearComparativeView/components/MinLengthSlider.d.ts +5 -0
  6. package/dist/LinearComparativeView/components/MinLengthSlider.js +47 -0
  7. package/dist/LinearComparativeView/components/OpacitySlider.d.ts +5 -0
  8. package/dist/LinearComparativeView/components/OpacitySlider.js +46 -0
  9. package/dist/LinearComparativeView/components/RubberbandSpan.js +2 -2
  10. package/dist/LinearComparativeView/components/SliderTooltip.d.ts +2 -0
  11. package/dist/LinearComparativeView/components/SliderTooltip.js +9 -0
  12. package/dist/LinearComparativeView/components/useRangeSelect.js +10 -14
  13. package/dist/LinearComparativeView/model.d.ts +3 -0
  14. package/dist/LinearComparativeView/model.js +4 -0
  15. package/dist/LinearSyntenyDisplay/afterAttach.js +5 -3
  16. package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +10 -5
  17. package/dist/LinearSyntenyDisplay/components/util.d.ts +2 -1
  18. package/dist/LinearSyntenyDisplay/components/util.js +43 -2
  19. package/dist/LinearSyntenyDisplay/drawSynteny.d.ts +3 -2
  20. package/dist/LinearSyntenyDisplay/drawSynteny.js +284 -45
  21. package/dist/LinearSyntenyDisplay/model.d.ts +6 -0
  22. package/dist/LinearSyntenyDisplay/model.js +12 -0
  23. package/dist/LinearSyntenyView/components/DiagonalizationProgressDialog.d.ts +6 -0
  24. package/dist/LinearSyntenyView/components/DiagonalizationProgressDialog.js +87 -0
  25. package/dist/LinearSyntenyView/model.d.ts +42 -11
  26. package/dist/LinearSyntenyView/model.js +70 -18
  27. package/dist/LinearSyntenyView/util/diagonalize.d.ts +27 -0
  28. package/dist/LinearSyntenyView/util/diagonalize.js +91 -0
  29. package/esm/LGVSyntenyDisplay/model.d.ts +17 -2
  30. package/esm/LinearComparativeView/components/ColorBySelector.d.ts +5 -0
  31. package/esm/LinearComparativeView/components/ColorBySelector.js +49 -0
  32. package/esm/LinearComparativeView/components/Header.js +8 -3
  33. package/esm/LinearComparativeView/components/MinLengthSlider.d.ts +5 -0
  34. package/esm/LinearComparativeView/components/MinLengthSlider.js +42 -0
  35. package/esm/LinearComparativeView/components/OpacitySlider.d.ts +5 -0
  36. package/esm/LinearComparativeView/components/OpacitySlider.js +41 -0
  37. package/esm/LinearComparativeView/components/RubberbandSpan.js +2 -2
  38. package/esm/LinearComparativeView/components/SliderTooltip.d.ts +2 -0
  39. package/esm/LinearComparativeView/components/SliderTooltip.js +6 -0
  40. package/esm/LinearComparativeView/components/useRangeSelect.js +11 -15
  41. package/esm/LinearComparativeView/model.d.ts +3 -0
  42. package/esm/LinearComparativeView/model.js +4 -0
  43. package/esm/LinearSyntenyDisplay/afterAttach.js +6 -4
  44. package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +10 -5
  45. package/esm/LinearSyntenyDisplay/components/util.d.ts +2 -1
  46. package/esm/LinearSyntenyDisplay/components/util.js +43 -3
  47. package/esm/LinearSyntenyDisplay/drawSynteny.d.ts +3 -2
  48. package/esm/LinearSyntenyDisplay/drawSynteny.js +283 -45
  49. package/esm/LinearSyntenyDisplay/model.d.ts +6 -0
  50. package/esm/LinearSyntenyDisplay/model.js +12 -0
  51. package/esm/LinearSyntenyView/components/DiagonalizationProgressDialog.d.ts +6 -0
  52. package/esm/LinearSyntenyView/components/DiagonalizationProgressDialog.js +85 -0
  53. package/esm/LinearSyntenyView/model.d.ts +42 -11
  54. package/esm/LinearSyntenyView/model.js +70 -18
  55. package/esm/LinearSyntenyView/util/diagonalize.d.ts +27 -0
  56. package/esm/LinearSyntenyView/util/diagonalize.js +88 -0
  57. package/package.json +5 -5
@@ -13,6 +13,7 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
13
13
  showIntraviewLinks: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
14
14
  linkViews: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
15
15
  interactiveOverlay: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
16
+ showDynamicControls: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
16
17
  levels: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
17
18
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
18
19
  type: import("mobx-state-tree").IType<string | undefined, string, string>;
@@ -285,6 +286,7 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
285
286
  drawCIGAR: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
286
287
  drawCIGARMatchesOnly: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
287
288
  drawCurves: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
289
+ drawLocationMarkers: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
288
290
  }, {
289
291
  width: number;
290
292
  } & {
@@ -308,6 +310,7 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
308
310
  removeView(view: import("@jbrowse/plugin-linear-genome-view").LinearGenomeViewModel): void;
309
311
  setLevelHeight(newHeight: number, level?: number): number;
310
312
  setLinkViews(arg: boolean): void;
313
+ setShowDynamicControls(arg: boolean): void;
311
314
  activateTrackSelector(level: number): import("@jbrowse/core/util").Widget;
312
315
  toggleTrack(trackId: string, level?: number): void;
313
316
  showTrack(trackId: string, level?: number, initialSnapshot?: {}): void;
@@ -333,6 +336,7 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
333
336
  setDrawCurves(arg: boolean): void;
334
337
  setDrawCIGAR(arg: boolean): void;
335
338
  setDrawCIGARMatchesOnly(arg: boolean): void;
339
+ setDrawLocationMarkers(arg: boolean): void;
336
340
  showAllRegions(): void;
337
341
  } & {
338
342
  exportSvg(opts: ExportSvgOptions): Promise<void>;
@@ -344,40 +348,66 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
344
348
  icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
345
349
  muiName: string;
346
350
  };
347
- checked?: undefined;
351
+ helpText: string;
348
352
  type?: undefined;
353
+ checked?: undefined;
354
+ subMenu?: undefined;
349
355
  } | {
350
356
  label: string;
351
- checked: boolean;
352
357
  type: string;
353
- description: string;
358
+ checked: boolean;
354
359
  onClick: () => void;
360
+ helpText: string;
361
+ description?: undefined;
355
362
  icon?: undefined;
363
+ subMenu?: undefined;
356
364
  } | {
357
365
  label: string;
358
- type: string;
359
- checked: boolean;
360
- icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
361
- muiName: string;
362
- };
363
- onClick: () => void;
366
+ subMenu: ({
367
+ label: string;
368
+ checked: boolean;
369
+ type: string;
370
+ description: string;
371
+ onClick: () => void;
372
+ helpText: string;
373
+ icon?: undefined;
374
+ } | {
375
+ label: string;
376
+ type: string;
377
+ checked: boolean;
378
+ icon: typeof Curves;
379
+ onClick: () => void;
380
+ helpText: string;
381
+ description?: undefined;
382
+ })[];
383
+ onClick?: undefined;
364
384
  description?: undefined;
385
+ icon?: undefined;
386
+ helpText?: undefined;
387
+ type?: undefined;
388
+ checked?: undefined;
365
389
  } | {
366
390
  label: string;
367
391
  type: string;
368
392
  checked: boolean;
369
- icon: typeof Curves;
393
+ icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
394
+ muiName: string;
395
+ };
370
396
  onClick: () => void;
397
+ helpText: string;
371
398
  description?: undefined;
399
+ subMenu?: undefined;
372
400
  } | {
373
401
  label: string;
374
402
  icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
375
403
  muiName: string;
376
404
  };
377
405
  onClick: () => void;
406
+ helpText: string;
378
407
  description?: undefined;
379
- checked?: undefined;
380
408
  type?: undefined;
409
+ checked?: undefined;
410
+ subMenu?: undefined;
381
411
  })[];
382
412
  menuItems(): (import("@jbrowse/core/ui").MenuDivider | import("@jbrowse/core/ui").MenuSubHeader | import("@jbrowse/core/ui").NormalMenuItem | import("@jbrowse/core/ui").CheckboxMenuItem | import("@jbrowse/core/ui").RadioMenuItem | import("@jbrowse/core/ui").SubMenuItem | {
383
413
  label: string;
@@ -399,6 +429,7 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
399
429
  showIntraviewLinks: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
400
430
  linkViews: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
401
431
  interactiveOverlay: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
432
+ showDynamicControls: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
402
433
  levels: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
403
434
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
404
435
  type: import("mobx-state-tree").IType<string | undefined, string, string>;
@@ -3,6 +3,7 @@ import { getSession } from '@jbrowse/core/util';
3
3
  import CropFreeIcon from '@mui/icons-material/CropFree';
4
4
  import LinkIcon from '@mui/icons-material/Link';
5
5
  import PhotoCameraIcon from '@mui/icons-material/PhotoCamera';
6
+ import ShuffleIcon from '@mui/icons-material/Shuffle';
6
7
  import VisibilityIcon from '@mui/icons-material/Visibility';
7
8
  import { saveAs } from 'file-saver';
8
9
  import { observable, transaction } from 'mobx';
@@ -10,6 +11,7 @@ import { types } from 'mobx-state-tree';
10
11
  import { Curves } from './components/Icons';
11
12
  import baseModel from '../LinearComparativeView/model';
12
13
  const ExportSvgDialog = lazy(() => import('./components/ExportSvgDialog'));
14
+ const DiagonalizationProgressDialog = lazy(() => import('./components/DiagonalizationProgressDialog'));
13
15
  export default function stateModelFactory(pluginManager) {
14
16
  return types
15
17
  .compose('LinearSyntenyView', baseModel(pluginManager), types.model({
@@ -17,6 +19,7 @@ export default function stateModelFactory(pluginManager) {
17
19
  drawCIGAR: true,
18
20
  drawCIGARMatchesOnly: false,
19
21
  drawCurves: false,
22
+ drawLocationMarkers: false,
20
23
  }))
21
24
  .volatile(() => ({
22
25
  importFormSyntenyTrackSelections: observable.array(),
@@ -40,6 +43,9 @@ export default function stateModelFactory(pluginManager) {
40
43
  setDrawCIGARMatchesOnly(arg) {
41
44
  self.drawCIGARMatchesOnly = arg;
42
45
  },
46
+ setDrawLocationMarkers(arg) {
47
+ self.drawLocationMarkers = arg;
48
+ },
43
49
  showAllRegions() {
44
50
  transaction(() => {
45
51
  for (const view of self.views) {
@@ -68,30 +74,83 @@ export default function stateModelFactory(pluginManager) {
68
74
  onClick: self.squareView,
69
75
  description: 'Makes both views use the same zoom level, adjusting to the average of each',
70
76
  icon: CropFreeIcon,
77
+ helpText: 'Square view synchronizes the zoom levels of both genome views by calculating the average zoom level and applying it to both panels. This helps ensure features are displayed at comparable scales, making it easier to compare syntenic regions visually.',
71
78
  },
72
79
  {
73
80
  label: 'Show all regions',
74
81
  onClick: self.showAllRegions,
75
82
  description: 'Show entire genome assemblies',
76
83
  icon: VisibilityIcon,
84
+ helpText: 'This command will zoom out all views to display the entire genome assemblies. This is useful when you want to get a high-level overview of syntenic relationships across whole genomes or when you need to reset the view after zooming into specific regions.',
77
85
  },
78
86
  {
79
- label: 'Draw CIGAR',
80
- checked: self.drawCIGAR,
81
- type: 'checkbox',
82
- description: 'If disabled, only draws the broad scale CIGAR match',
87
+ label: 'Re-order chromosomes',
83
88
  onClick: () => {
84
- self.setDrawCIGAR(!self.drawCIGAR);
89
+ getSession(self).queueDialog(handleClose => [
90
+ DiagonalizationProgressDialog,
91
+ {
92
+ handleClose,
93
+ model: self,
94
+ },
95
+ ]);
85
96
  },
97
+ icon: ShuffleIcon,
98
+ description: "Reorder and reorient query regions to minimize crossing lines, also known as 'diagonalizing'",
99
+ helpText: "This operation 'diagonalizes' the data which algorithmically reorders and reorients chromosomes to minimize crossing synteny lines, creating a more diagonal pattern. This makes it easier to identify large-scale genomic rearrangements, inversions, and translocations. The process may take a few moments for large genomes.",
86
100
  },
87
101
  {
88
- label: 'Draw only CIGAR matches',
89
- checked: self.drawCIGARMatchesOnly,
102
+ label: 'Show dynamic controls',
90
103
  type: 'checkbox',
91
- description: 'If enabled, it hides the insertions and deletions in the CIGAR strings, helps with divergent',
104
+ checked: self.showDynamicControls,
92
105
  onClick: () => {
93
- self.setDrawCIGARMatchesOnly(!self.drawCIGARMatchesOnly);
106
+ self.setShowDynamicControls(!self.showDynamicControls);
94
107
  },
108
+ helpText: 'Toggle visibility of dynamic controls like opacity and minimum length sliders. These controls allow you to adjust synteny visualization parameters in real-time.',
109
+ },
110
+ {
111
+ label: 'Draw',
112
+ subMenu: [
113
+ {
114
+ label: 'Draw CIGAR',
115
+ checked: self.drawCIGAR,
116
+ type: 'checkbox',
117
+ description: 'If disabled, only draws the broad scale CIGAR match',
118
+ onClick: () => {
119
+ self.setDrawCIGAR(!self.drawCIGAR);
120
+ },
121
+ helpText: 'CIGAR strings encode detailed alignment information including matches, insertions, and deletions. When enabled, this option visualizes the fine-scale variations in syntenic alignments. Disable this for a cleaner view that shows only broad syntenic blocks.',
122
+ },
123
+ {
124
+ label: 'Draw only CIGAR matches',
125
+ checked: self.drawCIGARMatchesOnly,
126
+ type: 'checkbox',
127
+ description: 'If enabled, it hides the insertions and deletions in the CIGAR strings, helps with divergent',
128
+ onClick: () => {
129
+ self.setDrawCIGARMatchesOnly(!self.drawCIGARMatchesOnly);
130
+ },
131
+ helpText: 'When comparing divergent genomes, showing all insertions and deletions can clutter the view. This option filters the CIGAR visualization to show only the matching regions, providing a cleaner view of conserved syntenic blocks while hiding small-scale indels.',
132
+ },
133
+ {
134
+ label: 'Draw curved lines',
135
+ type: 'checkbox',
136
+ checked: self.drawCurves,
137
+ icon: Curves,
138
+ onClick: () => {
139
+ self.setDrawCurves(!self.drawCurves);
140
+ },
141
+ helpText: 'Toggle between straight lines and smooth bezier curves for synteny connections. Curved lines can make the visualization more aesthetically pleasing and may help reduce visual clutter when many syntenic regions are displayed. Straight lines provide a more direct representation.',
142
+ },
143
+ {
144
+ label: 'Draw location markers',
145
+ type: 'checkbox',
146
+ checked: self.drawLocationMarkers,
147
+ description: 'Draw periodic markers to show location within large matches',
148
+ onClick: () => {
149
+ self.setDrawLocationMarkers(!self.drawLocationMarkers);
150
+ },
151
+ helpText: 'Location markers add periodic visual indicators along long syntenic blocks, helping you track position and scale within large conserved regions. This is particularly useful when examining very long syntenic matches where it can be difficult to gauge relative position.',
152
+ },
153
+ ],
95
154
  },
96
155
  {
97
156
  label: 'Link views',
@@ -101,15 +160,7 @@ export default function stateModelFactory(pluginManager) {
101
160
  onClick: () => {
102
161
  self.setLinkViews(!self.linkViews);
103
162
  },
104
- },
105
- {
106
- label: 'Use curved lines',
107
- type: 'checkbox',
108
- checked: self.drawCurves,
109
- icon: Curves,
110
- onClick: () => {
111
- self.setDrawCurves(!self.drawCurves);
112
- },
163
+ helpText: 'When linked, panning and zooming in one genome view will automatically adjust the other view to maintain the correspondence shown by synteny lines. This makes it easier to explore syntenic regions interactively. Unlink views to navigate each genome independently.',
113
164
  },
114
165
  {
115
166
  label: 'Export SVG',
@@ -123,6 +174,7 @@ export default function stateModelFactory(pluginManager) {
123
174
  },
124
175
  ]);
125
176
  },
177
+ helpText: 'Export the current synteny view as a scalable vector graphics (SVG) file. SVG format preserves quality at any zoom level and can be edited in vector graphics software like Inkscape or Adobe Illustrator. Perfect for creating publication-quality figures.',
126
178
  },
127
179
  ];
128
180
  },
@@ -0,0 +1,27 @@
1
+ export interface AlignmentData {
2
+ queryRefName: string;
3
+ refRefName: string;
4
+ queryStart: number;
5
+ queryEnd: number;
6
+ refStart: number;
7
+ refEnd: number;
8
+ strand: number;
9
+ }
10
+ export interface Region {
11
+ refName: string;
12
+ start: number;
13
+ end: number;
14
+ reversed?: boolean;
15
+ assemblyName: string;
16
+ }
17
+ export interface DiagonalizationResult {
18
+ newRegions: Region[];
19
+ stats: {
20
+ totalAlignments: number;
21
+ regionsProcessed: number;
22
+ regionsReordered: number;
23
+ regionsReversed: number;
24
+ };
25
+ }
26
+ export type ProgressCallback = (progress: number, message: string) => void | Promise<void>;
27
+ export declare function diagonalizeRegions(alignments: AlignmentData[], currentRegions: Region[], progressCallback?: ProgressCallback): Promise<DiagonalizationResult>;
@@ -0,0 +1,88 @@
1
+ export async function diagonalizeRegions(alignments, currentRegions, progressCallback) {
2
+ const updateProgress = async (progress, message) => {
3
+ if (progressCallback) {
4
+ await progressCallback(progress, message);
5
+ }
6
+ };
7
+ await updateProgress(20, `Grouping ${alignments.length} alignments...`);
8
+ const queryGroups = new Map();
9
+ for (const aln of alignments) {
10
+ const targetRefName = aln.refRefName;
11
+ if (!queryGroups.has(targetRefName)) {
12
+ queryGroups.set(targetRefName, {
13
+ refAlignments: new Map(),
14
+ strandWeightedSum: 0,
15
+ });
16
+ }
17
+ const group = queryGroups.get(targetRefName);
18
+ const alnLength = Math.abs(aln.queryEnd - aln.queryStart);
19
+ if (!group.refAlignments.has(aln.queryRefName)) {
20
+ group.refAlignments.set(aln.queryRefName, {
21
+ bases: 0,
22
+ positions: [],
23
+ });
24
+ }
25
+ const refData = group.refAlignments.get(aln.queryRefName);
26
+ refData.bases += alnLength;
27
+ refData.positions.push((aln.queryStart + aln.queryEnd) / 2);
28
+ const direction = aln.strand >= 0 ? 1 : -1;
29
+ group.strandWeightedSum += direction * alnLength;
30
+ }
31
+ await updateProgress(50, 'Determining optimal ordering and orientation...');
32
+ const queryOrdering = [];
33
+ for (const [targetRefName, group] of queryGroups) {
34
+ let bestRefName = '';
35
+ let maxBases = 0;
36
+ let bestPositions = [];
37
+ for (const [firstViewRefName, data] of group.refAlignments) {
38
+ if (data.bases > maxBases) {
39
+ maxBases = data.bases;
40
+ bestRefName = firstViewRefName;
41
+ bestPositions = data.positions;
42
+ }
43
+ }
44
+ const bestRefPos = bestPositions.reduce((a, b) => a + b, 0) / bestPositions.length;
45
+ const shouldReverse = group.strandWeightedSum < 0;
46
+ queryOrdering.push({
47
+ refName: targetRefName,
48
+ bestRefName,
49
+ bestRefPos,
50
+ shouldReverse,
51
+ });
52
+ }
53
+ await updateProgress(70, `Sorting ${queryOrdering.length} query regions...`);
54
+ queryOrdering.sort((a, b) => {
55
+ if (a.bestRefName !== b.bestRefName) {
56
+ return a.bestRefName.localeCompare(b.bestRefName);
57
+ }
58
+ return a.bestRefPos - b.bestRefPos;
59
+ });
60
+ await updateProgress(85, 'Building new region layout...');
61
+ const newQueryRegions = [];
62
+ let regionsReversed = 0;
63
+ for (const { refName, shouldReverse } of queryOrdering) {
64
+ const region = currentRegions.find(r => r.refName === refName);
65
+ if (region) {
66
+ newQueryRegions.push({
67
+ ...region,
68
+ reversed: shouldReverse,
69
+ });
70
+ if (shouldReverse !== region.reversed) {
71
+ regionsReversed++;
72
+ }
73
+ }
74
+ else {
75
+ console.warn(`Could not find region for refName: ${refName}`);
76
+ }
77
+ }
78
+ await updateProgress(100, 'Diagonalization complete!');
79
+ return {
80
+ newRegions: newQueryRegions,
81
+ stats: {
82
+ totalAlignments: alignments.length,
83
+ regionsProcessed: queryOrdering.length,
84
+ regionsReordered: newQueryRegions.length,
85
+ regionsReversed,
86
+ },
87
+ };
88
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-linear-comparative-view",
3
- "version": "3.6.5",
3
+ "version": "3.7.0",
4
4
  "description": "JBrowse 2 linear comparative view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -36,9 +36,9 @@
36
36
  "clean": "rimraf dist esm *.tsbuildinfo"
37
37
  },
38
38
  "dependencies": {
39
- "@jbrowse/core": "^3.6.5",
40
- "@jbrowse/plugin-alignments": "^3.6.5",
41
- "@jbrowse/plugin-linear-genome-view": "^3.6.5",
39
+ "@jbrowse/core": "^3.7.0",
40
+ "@jbrowse/plugin-alignments": "^3.7.0",
41
+ "@jbrowse/plugin-linear-genome-view": "^3.7.0",
42
42
  "@mui/icons-material": "^7.0.0",
43
43
  "@mui/material": "^7.0.0",
44
44
  "copy-to-clipboard": "^3.3.1",
@@ -59,5 +59,5 @@
59
59
  "publishConfig": {
60
60
  "access": "public"
61
61
  },
62
- "gitHead": "354d0a87b757b4d84f824b47507662f6f3a1693f"
62
+ "gitHead": "85bdd0d58286b7adbfd408146b15847676317635"
63
63
  }