@jbrowse/core 2.1.7 → 2.2.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 (55) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail.d.ts +2 -2
  2. package/BaseFeatureWidget/SequenceFeatureDetails.js +2 -1
  3. package/PluginManager.d.ts +3 -3
  4. package/ReExports/modules.d.ts +3 -3
  5. package/assemblyManager/assembly.d.ts +20 -14
  6. package/assemblyManager/assembly.js +74 -75
  7. package/assemblyManager/assemblyConfigSchema.d.ts +6 -2
  8. package/assemblyManager/assemblyConfigSchema.js +39 -2
  9. package/assemblyManager/assemblyManager.d.ts +76 -214
  10. package/assemblyManager/assemblyManager.js +17 -39
  11. package/data_adapters/CytobandAdapter.js +7 -0
  12. package/package.json +2 -2
  13. package/pluggableElementTypes/models/BaseDisplayModel.d.ts +60 -1
  14. package/pluggableElementTypes/models/BaseDisplayModel.js +138 -92
  15. package/pluggableElementTypes/models/baseConnectionConfig.js +17 -1
  16. package/pluggableElementTypes/models/baseInternetAccountConfig.js +27 -1
  17. package/pluggableElementTypes/models/baseTrackConfig.d.ts +3 -0
  18. package/pluggableElementTypes/models/baseTrackConfig.js +43 -1
  19. package/pluggableElementTypes/renderers/BoxRendererType.d.ts +1 -1
  20. package/pluggableElementTypes/renderers/BoxRendererType.js +2 -0
  21. package/rpc/MainThreadRpcDriver.d.ts +1 -1
  22. package/rpc/MainThreadRpcDriver.js +2 -2
  23. package/rpc/WebWorkerRpcDriver.d.ts +5 -4
  24. package/rpc/WebWorkerRpcDriver.js +2 -2
  25. package/rpc/baseRpcConfig.d.ts +2 -0
  26. package/rpc/baseRpcConfig.js +18 -0
  27. package/rpc/configSchema.js +16 -10
  28. package/rpc/coreRpcMethods.d.ts +14 -14
  29. package/rpc/coreRpcMethods.js +60 -63
  30. package/rpc/mainThreadRpcConfig.d.ts +2 -0
  31. package/rpc/mainThreadRpcConfig.js +19 -0
  32. package/rpc/webWorkerRpcConfig.d.ts +2 -0
  33. package/rpc/webWorkerRpcConfig.js +19 -0
  34. package/tsconfig.build.tsbuildinfo +1 -1
  35. package/ui/AboutDialog.js +2 -1
  36. package/ui/App.js +8 -5
  37. package/ui/AssemblySelector.js +1 -1
  38. package/ui/DrawerWidget.js +2 -1
  39. package/ui/LoadingEllipses.d.ts +7 -0
  40. package/ui/LoadingEllipses.js +38 -0
  41. package/ui/index.d.ts +1 -0
  42. package/ui/index.js +3 -1
  43. package/util/Base1DUtils.js +9 -3
  44. package/util/calculateDynamicBlocks.js +1 -1
  45. package/util/calculateStaticBlocks.js +1 -1
  46. package/util/index.d.ts +1 -0
  47. package/util/index.js +13 -9
  48. package/util/io/RemoteFileWithRangeCache.d.ts +1 -2
  49. package/util/layouts/GranularRectLayout.d.ts +7 -2
  50. package/util/layouts/GranularRectLayout.js +29 -45
  51. package/util/layouts/MultiLayout.d.ts +2 -2
  52. package/util/layouts/MultiLayout.js +4 -6
  53. package/util/simpleFeature.d.ts +3 -0
  54. package/util/stats.d.ts +26 -0
  55. package/util/stats.js +9 -9
package/ui/AboutDialog.js CHANGED
@@ -33,6 +33,7 @@ const material_1 = require("@mui/material");
33
33
  const Close_1 = __importDefault(require("@mui/icons-material/Close"));
34
34
  const mui_1 = require("tss-react/mui");
35
35
  const configuration_1 = require("../configuration");
36
+ const LoadingEllipses_1 = __importDefault(require("./LoadingEllipses"));
36
37
  const util_1 = require("../util");
37
38
  const tracks_1 = require("../util/tracks");
38
39
  const BaseFeatureDetail_1 = require("../BaseFeatureWidget/BaseFeatureDetail");
@@ -86,7 +87,7 @@ function FileInfo({ config }) {
86
87
  .replace(/>/g, '&gt;')}</pre>`,
87
88
  }
88
89
  : info || {};
89
- return info !== null ? (react_1.default.createElement(BaseFeatureDetail_1.BaseCard, { title: "File info" }, error ? (react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`)) : info === undefined ? ('Loading file data...') : (react_1.default.createElement(BaseFeatureDetail_1.Attributes, { attributes: details })))) : null;
90
+ return info !== null ? (react_1.default.createElement(BaseFeatureDetail_1.BaseCard, { title: "File info" }, error ? (react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`)) : info === undefined ? (react_1.default.createElement(LoadingEllipses_1.default, { message: "Loading file data" })) : (react_1.default.createElement(BaseFeatureDetail_1.Attributes, { attributes: details })))) : null;
90
91
  }
91
92
  exports.FileInfo = FileInfo;
92
93
  function AboutContents({ config }) {
package/ui/App.js CHANGED
@@ -38,6 +38,7 @@ const configuration_1 = require("../configuration");
38
38
  const DrawerWidget_1 = __importDefault(require("./DrawerWidget"));
39
39
  const DropDownMenu_1 = __importDefault(require("./DropDownMenu"));
40
40
  const ErrorMessage_1 = __importDefault(require("./ErrorMessage"));
41
+ const LoadingEllipses_1 = __importDefault(require("./LoadingEllipses"));
41
42
  const EditableTypography_1 = __importDefault(require("./EditableTypography"));
42
43
  const Logo_1 = require("./Logo");
43
44
  const Snackbar_1 = __importDefault(require("./Snackbar"));
@@ -139,10 +140,12 @@ const ViewLauncher = (0, mobx_react_1.observer)(({ session }) => {
139
140
  const [value, setValue] = (0, react_1.useState)((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
140
141
  return (react_1.default.createElement(material_1.Paper, { className: classes.selectPaper },
141
142
  react_1.default.createElement(material_1.Typography, null, "Select a view to launch"),
142
- react_1.default.createElement(material_1.Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, name)))),
143
- react_1.default.createElement(material_1.Button, { onClick: () => {
144
- session.addView(value, {});
145
- }, variant: "contained", color: "primary" }, "Launch view")));
143
+ react_1.default.createElement(material_1.FormControl, { style: { margin: 2 } },
144
+ react_1.default.createElement(material_1.Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, name))))),
145
+ react_1.default.createElement(material_1.FormControl, { style: { margin: 2 } },
146
+ react_1.default.createElement(material_1.Button, { onClick: () => {
147
+ session.addView(value, {});
148
+ }, variant: "contained", color: "primary" }, "Launch view"))));
146
149
  });
147
150
  const ViewPanel = (0, mobx_react_1.observer)(({ view, session }) => {
148
151
  const { pluginManager } = (0, mobx_state_tree_1.getEnv)(session);
@@ -152,7 +155,7 @@ const ViewPanel = (0, mobx_react_1.observer)(({ view, session }) => {
152
155
  }
153
156
  const { ReactComponent } = viewType;
154
157
  return (react_1.default.createElement(ViewContainer_1.default, { view: view, onClose: () => session.removeView(view) },
155
- react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
158
+ react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(LoadingEllipses_1.default, null) },
156
159
  react_1.default.createElement(ReactComponent, { model: view, session: session, getTrackType: pluginManager.getTrackType }))));
157
160
  });
158
161
  const App = (0, mobx_react_1.observer)((props) => {
@@ -55,7 +55,7 @@ const AssemblySelector = (0, mobx_react_1.observer)(({ session, onChange, select
55
55
  }
56
56
  }, [selection, onChange, selected]);
57
57
  const error = assemblyNames.length ? '' : 'No configured assemblies';
58
- return (react_1.default.createElement(material_1.TextField, { select: true, label: "Assembly", variant: "outlined", helperText: error || 'Select assembly to view', value: error ? '' : selection, inputProps: { 'data-testid': 'assembly-selector' }, onChange: event => setLastSelected(event.target.value), error: !!error, InputProps: InputProps, disabled: !!error, className: classes.importFormEntry }, assemblyNames.map(name => {
58
+ return (react_1.default.createElement(material_1.TextField, { select: true, label: "Assembly", variant: "outlined", helperText: error || 'Select assembly to view', value: selection, inputProps: { 'data-testid': 'assembly-selector' }, onChange: event => setLastSelected(event.target.value), error: !!error, InputProps: InputProps, disabled: !!error, className: classes.importFormEntry }, assemblyNames.map(name => {
59
59
  const assembly = assemblyManager.get(name);
60
60
  const displayName = assembly ? (0, configuration_1.getConf)(assembly, 'displayName') : '';
61
61
  return (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, displayName || name));
@@ -32,6 +32,7 @@ const material_1 = require("@mui/material");
32
32
  const mui_1 = require("tss-react/mui");
33
33
  const mobx_react_1 = require("mobx-react");
34
34
  const util_1 = require("../util");
35
+ const LoadingEllipses_1 = __importDefault(require("./LoadingEllipses"));
35
36
  // icons
36
37
  const Delete_1 = __importDefault(require("@mui/icons-material/Delete"));
37
38
  const Close_1 = __importDefault(require("@mui/icons-material/Close"));
@@ -123,7 +124,7 @@ const DrawerWidget = (0, mobx_react_1.observer)(({ session }) => {
123
124
  const [toolbarHeight, setToolbarHeight] = (0, react_1.useState)(0);
124
125
  return (react_1.default.createElement(Drawer_1.default, { session: session },
125
126
  react_1.default.createElement(DrawerHeader, { session: session, setToolbarHeight: setToolbarHeight }),
126
- react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
127
+ react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(LoadingEllipses_1.default, null) },
127
128
  react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: ({ error }) => react_1.default.createElement(ErrorMessage_1.default, { error: error }) }, DrawerComponent ? (react_1.default.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight })) : null))));
128
129
  });
129
130
  exports.default = DrawerWidget;
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { TypographyProps } from '@mui/material';
3
+ interface Props extends TypographyProps {
4
+ message?: string;
5
+ }
6
+ export default function LoadingEllipses({ message, variant, ...rest }: Props): JSX.Element;
7
+ export {};
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const material_1 = require("@mui/material");
8
+ const mui_1 = require("tss-react/mui");
9
+ const tss_react_1 = require("tss-react");
10
+ const useStyles = (0, mui_1.makeStyles)()({
11
+ dots: {
12
+ '&::after': {
13
+ display: 'inline-block',
14
+ content: '""',
15
+ width: '1em',
16
+ textAlign: 'left',
17
+ animation: `${(0, tss_react_1.keyframes) `
18
+ 0% {
19
+ content: '';
20
+ }
21
+ 25% {
22
+ content: '.';
23
+ }
24
+ 50% {
25
+ content: '..';
26
+ }
27
+ 75% {
28
+ content: '...';
29
+ }
30
+ `} 1.4s infinite ease-in-out`,
31
+ },
32
+ },
33
+ });
34
+ function LoadingEllipses({ message = 'Loading', variant = 'body2', ...rest }) {
35
+ const { classes } = useStyles();
36
+ return (react_1.default.createElement(material_1.Typography, { className: classes.dots, ...rest, variant: variant }, `${message || 'Loading'}`));
37
+ }
38
+ exports.default = LoadingEllipses;
package/ui/index.d.ts CHANGED
@@ -14,4 +14,5 @@ export { default as FatalErrorDialog } from './FatalErrorDialog';
14
14
  export { default as Menu } from './Menu';
15
15
  export { default as CascadingMenu } from './CascadingMenu';
16
16
  export { default as SanitizedHTML } from './SanitizedHTML';
17
+ export { default as LoadingEllipses } from './LoadingEllipses';
17
18
  export * from './Menu';
package/ui/index.js CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.SanitizedHTML = exports.CascadingMenu = exports.Menu = exports.FatalErrorDialog = exports.Tooltip = exports.FactoryResetDialog = exports.EditableTypography = exports.ResizeHandle = exports.PrerenderedCanvas = exports.FileSelector = exports.AssemblySelector = exports.ErrorMessage = exports.ReturnToImportFormDialog = exports.App = exports.Logomark = exports.LogoFull = void 0;
20
+ exports.LoadingEllipses = exports.SanitizedHTML = exports.CascadingMenu = exports.Menu = exports.FatalErrorDialog = exports.Tooltip = exports.FactoryResetDialog = exports.EditableTypography = exports.ResizeHandle = exports.PrerenderedCanvas = exports.FileSelector = exports.AssemblySelector = exports.ErrorMessage = exports.ReturnToImportFormDialog = exports.App = exports.Logomark = exports.LogoFull = void 0;
21
21
  __exportStar(require("./theme"), exports);
22
22
  var Logo_1 = require("./Logo");
23
23
  Object.defineProperty(exports, "LogoFull", { enumerable: true, get: function () { return Logo_1.LogoFull; } });
@@ -50,4 +50,6 @@ var CascadingMenu_1 = require("./CascadingMenu");
50
50
  Object.defineProperty(exports, "CascadingMenu", { enumerable: true, get: function () { return __importDefault(CascadingMenu_1).default; } });
51
51
  var SanitizedHTML_1 = require("./SanitizedHTML");
52
52
  Object.defineProperty(exports, "SanitizedHTML", { enumerable: true, get: function () { return __importDefault(SanitizedHTML_1).default; } });
53
+ var LoadingEllipses_1 = require("./LoadingEllipses");
54
+ Object.defineProperty(exports, "LoadingEllipses", { enumerable: true, get: function () { return __importDefault(LoadingEllipses_1).default; } });
53
55
  __exportStar(require("./Menu"), exports);
@@ -26,10 +26,16 @@ function moveTo(self, start, end) {
26
26
  if (!start || !end) {
27
27
  return;
28
28
  }
29
- const { width, interRegionPaddingWidth } = self;
29
+ const { width, interRegionPaddingWidth, displayedRegions, bpPerPx, minimumBlockWidth, } = self;
30
30
  const len = lengthBetween(self, start, end);
31
- const numBlocks = end.index - start.index;
32
- const targetBpPerPx = len / (width - interRegionPaddingWidth * numBlocks);
31
+ let numBlocksWideEnough = 0;
32
+ for (let i = start.index; i < end.index; i++) {
33
+ const r = displayedRegions[i];
34
+ if ((r.end - r.start) / bpPerPx > minimumBlockWidth) {
35
+ numBlocksWideEnough++;
36
+ }
37
+ }
38
+ const targetBpPerPx = len / (width - interRegionPaddingWidth * numBlocksWideEnough);
33
39
  const newBpPerPx = self.zoomTo(targetBpPerPx);
34
40
  // If our target bpPerPx was smaller than the allowed minBpPerPx, adjust
35
41
  // the scroll so the requested range is in the middle of the screen
@@ -75,7 +75,7 @@ function calculateDynamicBlocks(model, padding = true, elision = true) {
75
75
  isRightEndOfDisplayedRegion,
76
76
  key: '',
77
77
  };
78
- blockData.key = `${(0, _1.assembleLocString)(blockData)}-${regionNumber}${reversed ? '-reversed' : ''}`;
78
+ blockData.key = `${(0, _1.assembleLocStringFast)(blockData)}-${regionNumber}${reversed ? '-reversed' : ''}`;
79
79
  if (padding && blocks.length === 0 && isLeftEndOfDisplayedRegion) {
80
80
  blocks.push(new blockTypes_1.InterRegionPaddingBlock({
81
81
  key: `${blockData.key}-beforeFirstRegion`,
@@ -59,7 +59,7 @@ function calculateStaticBlocks(model, padding = true, elision = true, extra = 0,
59
59
  isRightEndOfDisplayedRegion,
60
60
  key: '',
61
61
  };
62
- blockData.key = `${(0, _1.assembleLocString)(blockData)}-${regionNumber}${reversed ? '-reversed' : ''}`;
62
+ blockData.key = `${(0, _1.assembleLocStringFast)(blockData)}-${regionNumber}${reversed ? '-reversed' : ''}`;
63
63
  if (padding && regionNumber === 0 && blockNum === 0) {
64
64
  blocks.push(new blockTypes_1.InterRegionPaddingBlock({
65
65
  key: `${blockData.key}-beforeFirstRegion`,
package/util/index.d.ts CHANGED
@@ -63,6 +63,7 @@ export declare function getContainingDisplay(node: IAnyStateTreeNode): import(".
63
63
  * ```
64
64
  */
65
65
  export declare function assembleLocString(region: ParsedLocString): string;
66
+ export declare function assembleLocStringFast(region: ParsedLocString, cb?: (n: number) => string | number): string;
66
67
  export interface ParsedLocString {
67
68
  assemblyName?: string;
68
69
  refName: string;
package/util/index.js CHANGED
@@ -29,8 +29,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
29
29
  return (mod && mod.__esModule) ? mod : { "default": mod };
30
30
  };
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.getBpDisplayStr = exports.supportedIndexingAdapters = exports.bytesForRegions = exports.objectHash = exports.hashCode = exports.updateStatus = exports.generateCodonTable = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.measureText = exports.rIC = exports.blobToDataURL = exports.complement = exports.reverse = exports.revcom = exports.isElectron = exports.stringify = exports.minmax = exports.renameRegionsIfNeeded = exports.renameRegionIfNeeded = exports.makeAbortableReaction = exports.findLastIndex = exports.iterMap = exports.bpSpanPx = exports.featureSpanPx = exports.cartesianToPolar = exports.polarToCartesian = exports.degToRad = exports.radToDeg = exports.bpToPx = exports.clamp = exports.compareLocStrings = exports.compareLocs = exports.parseLocString = exports.parseLocStringOneBased = exports.assembleLocString = exports.getContainingDisplay = exports.getContainingTrack = exports.getContainingView = exports.getSession = exports.findParentThatIs = exports.springAnimate = exports.findParentThat = exports.useDebouncedCallback = exports.useDebounce = exports.inProduction = exports.inDevelopment = exports.isFeature = exports.SimpleFeature = void 0;
33
- exports.getEnv = exports.measureGridWidth = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = exports.toLocale = void 0;
32
+ exports.supportedIndexingAdapters = exports.bytesForRegions = exports.objectHash = exports.hashCode = exports.updateStatus = exports.generateCodonTable = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.measureText = exports.rIC = exports.blobToDataURL = exports.complement = exports.reverse = exports.revcom = exports.isElectron = exports.stringify = exports.minmax = exports.renameRegionsIfNeeded = exports.renameRegionIfNeeded = exports.makeAbortableReaction = exports.findLastIndex = exports.iterMap = exports.bpSpanPx = exports.featureSpanPx = exports.cartesianToPolar = exports.polarToCartesian = exports.degToRad = exports.radToDeg = exports.bpToPx = exports.clamp = exports.compareLocStrings = exports.compareLocs = exports.parseLocString = exports.parseLocStringOneBased = exports.assembleLocStringFast = exports.assembleLocString = exports.getContainingDisplay = exports.getContainingTrack = exports.getContainingView = exports.getSession = exports.findParentThatIs = exports.springAnimate = exports.findParentThat = exports.useDebouncedCallback = exports.useDebounce = exports.inProduction = exports.inDevelopment = exports.isFeature = exports.SimpleFeature = void 0;
33
+ exports.getEnv = exports.measureGridWidth = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = exports.toLocale = exports.getBpDisplayStr = void 0;
34
34
  /* eslint-disable @typescript-eslint/no-explicit-any */
35
35
  const react_1 = require("react");
36
36
  const is_object_1 = __importDefault(require("is-object"));
@@ -237,11 +237,18 @@ exports.getContainingDisplay = getContainingDisplay;
237
237
  * ```
238
238
  */
239
239
  function assembleLocString(region) {
240
+ return assembleLocStringFast(region, toLocale);
241
+ }
242
+ exports.assembleLocString = assembleLocString;
243
+ // same as assembleLocString above, but does not perform toLocaleString which
244
+ // can slow down the speed of block calculations which use assembleLocString
245
+ // for block.key
246
+ function assembleLocStringFast(region, cb = (n) => n) {
240
247
  const { assemblyName, refName, start, end, reversed } = region;
241
248
  const assemblyNameString = assemblyName ? `{${assemblyName}}` : '';
242
249
  let startString;
243
250
  if (start !== undefined) {
244
- startString = `:${(start + 1).toLocaleString('en-US')}`;
251
+ startString = `:${cb(start + 1)}`;
245
252
  }
246
253
  else if (end !== undefined) {
247
254
  startString = ':1';
@@ -251,10 +258,7 @@ function assembleLocString(region) {
251
258
  }
252
259
  let endString;
253
260
  if (end !== undefined) {
254
- endString =
255
- start !== undefined && start + 1 === end
256
- ? ''
257
- : `..${end.toLocaleString('en-US')}`;
261
+ endString = start !== undefined && start + 1 === end ? '' : `..${cb(end)}`;
258
262
  }
259
263
  else {
260
264
  endString = start !== undefined ? '..' : '';
@@ -265,7 +269,7 @@ function assembleLocString(region) {
265
269
  }
266
270
  return `${assemblyNameString}${refName}${startString}${endString}${rev}`;
267
271
  }
268
- exports.assembleLocString = assembleLocString;
272
+ exports.assembleLocStringFast = assembleLocStringFast;
269
273
  function parseLocStringOneBased(locString, isValidRefName) {
270
274
  if (!locString) {
271
275
  throw new Error('no location string provided, could not parse');
@@ -649,7 +653,7 @@ function minmax(a, b) {
649
653
  exports.minmax = minmax;
650
654
  function stringify({ refName, coord, oob, }) {
651
655
  return refName
652
- ? `${refName}:${coord.toLocaleString('en-US')}${oob ? ' (out of bounds)' : ''}`
656
+ ? `${refName}:${toLocale(coord)}${oob ? ' (out of bounds)' : ''}`
653
657
  : '';
654
658
  }
655
659
  exports.stringify = stringify;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { RemoteFile, PolyfilledResponse } from 'generic-filehandle';
3
- interface BinaryRangeResponse {
3
+ export interface BinaryRangeResponse {
4
4
  headers: Record<string, string>;
5
5
  requestDate: Date;
6
6
  responseDate: Date;
@@ -14,4 +14,3 @@ export declare class RemoteFileWithRangeCache extends RemoteFile {
14
14
  signal?: AbortSignal;
15
15
  }): Promise<BinaryRangeResponse>;
16
16
  }
17
- export {};
@@ -9,6 +9,11 @@ export default class GranularRectLayout<T> implements BaseLayout<T> {
9
9
  private maxHeight;
10
10
  private displayMode;
11
11
  private pTotalHeight;
12
+ /**
13
+ * pitchX - layout grid pitch in the X direction
14
+ * pitchY - layout grid pitch in the Y direction
15
+ * maxHeight - maximum layout height, default Infinity (no max)
16
+ */
12
17
  constructor({ pitchX, pitchY, maxHeight, hardRowLimit, displayMode, }?: {
13
18
  pitchX?: number;
14
19
  pitchY?: number;
@@ -33,9 +38,9 @@ export default class GranularRectLayout<T> implements BaseLayout<T> {
33
38
  */
34
39
  discardRange(left: number, right: number): void;
35
40
  hasSeen(id: string): boolean;
36
- getByCoord(x: number, y: number): Record<string, T> | string | undefined;
41
+ getByCoord(x: number, y: number): string | Record<string, T> | undefined;
37
42
  getByID(id: string): RectTuple | undefined;
38
- getDataByID(id: string): unknown;
43
+ getDataByID(id: string): T | undefined;
39
44
  cleanup(): void;
40
45
  getTotalHeight(): number;
41
46
  get totalHeight(): number;
@@ -18,66 +18,47 @@ class LayoutRow {
18
18
  constructor() {
19
19
  this.padding = 1;
20
20
  this.widthLimit = 1000000;
21
- // this.rowState.offset is the offset of the bits array relative to the genomic coordinates
22
- // (modified by pitchX, but we don't know that in this class)
23
- // this.rowState.bits is the array of items in the layout row, indexed by (x - this.offset)
24
- // this.rowState.min is the leftmost edge of all the rectangles we have in the layout
25
- // this.rowState.max is the rightmost edge of all the rectangles we have in the layout
26
21
  }
27
- // log(msg: string): void {
28
- // // if (this.rowNumber === 0)
29
- // // eslint-disable-next-line no-console
30
- // console.log(`r${this.rowNumber}: ${msg}`)
31
- // }
22
+ // this.rowState.bits is the array of items in the layout row, indexed by (x - this.offset)
23
+ // this.rowState.min is the leftmost edge of all the rectangles we have in the layout
24
+ // this.rowState.max is the rightmost edge of all the rectangles we have in the layout
25
+ // this.rowState.offset is the offset of the bits array relative to the genomic coordinates
26
+ // (modified by pitchX, but we don't know that in this class)
32
27
  setAllFilled(data) {
33
28
  this.allFilled = data;
34
29
  }
35
30
  getItemAt(x) {
31
+ var _a;
36
32
  if (this.allFilled) {
37
33
  return this.allFilled;
38
34
  }
39
- if (!this.rowState) {
40
- return undefined;
41
- }
42
- if (this.rowState.min === undefined) {
35
+ if (((_a = this.rowState) === null || _a === void 0 ? void 0 : _a.min) === undefined ||
36
+ x < this.rowState.min ||
37
+ x >= this.rowState.max) {
43
38
  return undefined;
44
39
  }
45
- if (x < this.rowState.min) {
46
- return undefined;
47
- }
48
- if (x >= this.rowState.max) {
49
- return undefined;
50
- }
51
- const offset = x - this.rowState.offset;
52
- // if (offset < 0)
53
- // debugger
54
- // if (offset >= this.rowState.bits.length)
55
- // debugger
56
- return this.rowState.bits[offset];
40
+ return this.rowState.bits[x - this.rowState.offset];
57
41
  }
58
42
  isRangeClear(left, right) {
59
43
  if (this.allFilled) {
60
44
  return false;
61
45
  }
62
- if (!this.rowState) {
63
- return true;
64
- }
65
- const { min, max } = this.rowState;
66
- if (right <= min || left >= max) {
46
+ if (this.rowState === undefined ||
47
+ right <= this.rowState.min ||
48
+ left >= this.rowState.max) {
67
49
  return true;
68
50
  }
69
- // TODO: check right and middle before looping
70
- const maxX = Math.min(max, right);
71
- let x = Math.max(min, left);
72
- for (; x < right && x < maxX; x += 1) {
73
- if (this.getItemAt(x)) {
74
- return false;
75
- }
51
+ const { min, max, offset, bits } = this.rowState;
52
+ const maxX = Math.min(max, right) - offset;
53
+ let flag = true;
54
+ for (let x = Math.max(min, left) - offset; x < maxX && flag; x++) {
55
+ flag = bits[x] === undefined;
76
56
  }
77
- return true;
57
+ return flag;
78
58
  }
59
+ // NOTE: this.rowState.min, this.rowState.max, and this.rowState.offset are
60
+ // interbase coordinates
79
61
  initialize(left, right) {
80
- // NOTE: this.rowState.min, this.rowState.max, and this.rowState.offset are interbase coordinates
81
62
  const rectWidth = right - left;
82
63
  return {
83
64
  offset: left - rectWidth,
@@ -85,7 +66,6 @@ class LayoutRow {
85
66
  max: right,
86
67
  bits: new Array(3 * rectWidth),
87
68
  };
88
- // this.log(`initialize ${this.rowState.min} - ${this.rowState.max} (${this.rowState.bits.length})`)
89
69
  }
90
70
  addRect(rect, data) {
91
71
  const left = rect.l;
@@ -220,8 +200,7 @@ class LayoutRow {
220
200
  }
221
201
  }
222
202
  class GranularRectLayout {
223
- /*
224
- *
203
+ /**
225
204
  * pitchX - layout grid pitch in the X direction
226
205
  * pitchY - layout grid pitch in the Y direction
227
206
  * maxHeight - maximum layout height, default Infinity (no max)
@@ -296,7 +275,7 @@ class GranularRectLayout {
296
275
  const maxY = top + rect.h;
297
276
  for (let y = top; y < maxY; y += 1) {
298
277
  const row = bitmap[y];
299
- if (row && !row.isRangeClear(rect.l, rect.r)) {
278
+ if (row !== undefined && !row.isRangeClear(rect.l, rect.r)) {
300
279
  return true;
301
280
  }
302
281
  }
@@ -370,7 +349,12 @@ class GranularRectLayout {
370
349
  const r = this.rectangles.get(id);
371
350
  if (r) {
372
351
  const t = r.top * this.pitchY;
373
- return [r.l * this.pitchX, t, r.r * this.pitchX, t + r.originalHeight];
352
+ return [
353
+ r.l * this.pitchX,
354
+ t,
355
+ r.r * this.pitchX,
356
+ t + r.originalHeight,
357
+ ];
374
358
  }
375
359
  return undefined;
376
360
  }
@@ -1,14 +1,14 @@
1
1
  import { BaseLayout, SerializedLayout } from './BaseLayout';
2
2
  export default class MultiLayout<SUB_LAYOUT_CLASS extends BaseLayout<T>, T> {
3
3
  SubLayoutClass: new (...args: any[]) => SUB_LAYOUT_CLASS;
4
- subLayouts: Map<string, SUB_LAYOUT_CLASS>;
5
4
  subLayoutConstructorArgs: Record<string, any>;
5
+ subLayouts: Map<string, SUB_LAYOUT_CLASS>;
6
6
  /**
7
7
  * layout class that just keeps a number of named sub-layouts.
8
8
  * basically just a fancier
9
9
  * `{ layout1: new GranularRectLayout(), layout2: new GranularRectLayout() ...}`
10
10
  */
11
- constructor(SubLayoutClass: new (...args: any[]) => SUB_LAYOUT_CLASS, layoutArgs?: Record<string, any>);
11
+ constructor(SubLayoutClass: new (...args: any[]) => SUB_LAYOUT_CLASS, subLayoutConstructorArgs?: Record<string, any>);
12
12
  getDataByID(id: string): unknown;
13
13
  getSublayout(layoutName: string): SUB_LAYOUT_CLASS;
14
14
  addRect(layoutName: string, id: string, left: number, right: number, height: number, data?: Record<string, T>): number | null;
@@ -6,12 +6,10 @@ class MultiLayout {
6
6
  * basically just a fancier
7
7
  * `{ layout1: new GranularRectLayout(), layout2: new GranularRectLayout() ...}`
8
8
  */
9
- constructor(SubLayoutClass, layoutArgs = {}) {
9
+ constructor(SubLayoutClass, subLayoutConstructorArgs = {}) {
10
10
  this.SubLayoutClass = SubLayoutClass;
11
+ this.subLayoutConstructorArgs = subLayoutConstructorArgs;
11
12
  this.subLayouts = new Map();
12
- this.subLayoutConstructorArgs = {};
13
- this.subLayouts = new Map();
14
- this.subLayoutConstructorArgs = layoutArgs;
15
13
  }
16
14
  getDataByID(id) {
17
15
  for (const layout of this.subLayouts.values()) {
@@ -36,8 +34,8 @@ class MultiLayout {
36
34
  return this.getSublayout(layoutName).addRect(id, left, right, height, data);
37
35
  }
38
36
  discardRange(layoutName, left, right) {
39
- const layout = this.subLayouts.get(layoutName);
40
- return layout && layout.discardRange(left, right);
37
+ var _a;
38
+ return (_a = this.subLayouts.get(layoutName)) === null || _a === void 0 ? void 0 : _a.discardRange(left, right);
41
39
  }
42
40
  toJSON() {
43
41
  const data = {};
@@ -31,6 +31,9 @@ export interface Feature {
31
31
  * Get an array of child features, or undefined if none.
32
32
  */
33
33
  children(): Feature[] | undefined;
34
+ /**
35
+ * Convert to JSON
36
+ */
34
37
  toJSON(): SimpleFeatureSerialized;
35
38
  }
36
39
  export declare function isFeature(thing: unknown): thing is Feature;
package/util/stats.d.ts CHANGED
@@ -14,8 +14,34 @@ export interface FeatureStats extends UnrectifiedFeatureStats {
14
14
  scoreMean: number;
15
15
  scoreStdDev: number;
16
16
  }
17
+ /**
18
+ * calculate standard deviation using the 'shortcut method' that accepts
19
+ * the sum and the sum squares of the elements
20
+ *
21
+ * @param sum - sum(i, 1..n)
22
+ * @param sumSquares - sum(i^2, 1..n)
23
+ * @param n - number of elements
24
+ * @param population - boolean: use population instead of sample correction
25
+ * @returns - the estimated std deviation
26
+ */
17
27
  export declare function calcStdFromSums(sum: number, sumSquares: number, n: number, population?: boolean): number;
28
+ /**
29
+ * @param stats - a summary stats object with scoreSum, featureCount, scoreSumSquares, and basesCovered
30
+ * @returns - a summary stats object with scoreMean, scoreStdDev, and featureDensity added
31
+ */
18
32
  export declare function rectifyStats(s: UnrectifiedFeatureStats): FeatureStats;
33
+ /**
34
+ * calculates per-base scores for variable width features over a region
35
+ * @param region - object contains start, end
36
+ * @param features - list of features with start, end, score
37
+ * @returns array of numeric scores
38
+ */
19
39
  export declare function calcPerBaseStats(region: NoAssemblyRegion, features: Feature[]): number[];
40
+ /**
41
+ * transform a list of scores to summary statistics
42
+ * @param region - object with start, end
43
+ * @param features - array of features which are possibly summary features
44
+ * @returns - object with scoreMax, scoreMin, scoreSum, scoreSumSquares, etc
45
+ */
20
46
  export declare function scoresToStats(region: NoAssemblyRegion, features: Observable<Feature>): Promise<FeatureStats>;
21
47
  export declare function blankStats(): FeatureStats;
package/util/stats.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.blankStats = exports.scoresToStats = exports.calcPerBaseStats = exports.rectifyStats = exports.calcStdFromSums = void 0;
4
4
  const operators_1 = require("rxjs/operators");
5
- /*
5
+ /**
6
6
  * calculate standard deviation using the 'shortcut method' that accepts
7
7
  * the sum and the sum squares of the elements
8
8
  *
@@ -10,7 +10,7 @@ const operators_1 = require("rxjs/operators");
10
10
  * @param sumSquares - sum(i^2, 1..n)
11
11
  * @param n - number of elements
12
12
  * @param population - boolean: use population instead of sample correction
13
- * @return the estimated std deviation
13
+ * @returns - the estimated std deviation
14
14
  */
15
15
  function calcStdFromSums(sum, sumSquares, n, population = false) {
16
16
  if (n === 0) {
@@ -30,9 +30,9 @@ function calcStdFromSums(sum, sumSquares, n, population = false) {
30
30
  return variance < 0 ? 0 : Math.sqrt(variance);
31
31
  }
32
32
  exports.calcStdFromSums = calcStdFromSums;
33
- /*
33
+ /**
34
34
  * @param stats - a summary stats object with scoreSum, featureCount, scoreSumSquares, and basesCovered
35
- * @return - a summary stats object with scoreMean, scoreStdDev, and featureDensity added
35
+ * @returns - a summary stats object with scoreMean, scoreStdDev, and featureDensity added
36
36
  */
37
37
  function rectifyStats(s) {
38
38
  return {
@@ -43,11 +43,11 @@ function rectifyStats(s) {
43
43
  };
44
44
  }
45
45
  exports.rectifyStats = rectifyStats;
46
- /*
46
+ /**
47
47
  * calculates per-base scores for variable width features over a region
48
48
  * @param region - object contains start, end
49
49
  * @param features - list of features with start, end, score
50
- * @return array of numeric scores
50
+ * @returns array of numeric scores
51
51
  */
52
52
  function calcPerBaseStats(region, features) {
53
53
  const { start, end } = region;
@@ -76,11 +76,11 @@ function calcPerBaseStats(region, features) {
76
76
  return scores;
77
77
  }
78
78
  exports.calcPerBaseStats = calcPerBaseStats;
79
- /*
79
+ /**
80
80
  * transform a list of scores to summary statistics
81
81
  * @param region - object with start, end
82
- * @param feats - array of features which are possibly summary features
83
- * @return - object with scoreMax, scoreMin, scoreSum, scoreSumSquares, etc
82
+ * @param features - array of features which are possibly summary features
83
+ * @returns - object with scoreMax, scoreMin, scoreSum, scoreSumSquares, etc
84
84
  */
85
85
  async function scoresToStats(region, features) {
86
86
  const { start, end } = region;