@jbrowse/plugin-hic 2.15.4 → 2.16.1

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.
@@ -1,28 +1,23 @@
1
1
  import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
2
- import { Region, FileLocation } from '@jbrowse/core/util/types';
3
- import type { GenericFilehandle } from 'generic-filehandle';
2
+ import { Region } from '@jbrowse/core/util/types';
4
3
  import PluginManager from '@jbrowse/core/PluginManager';
5
4
  import { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
6
5
  import { AnyConfigurationModel } from '@jbrowse/core/configuration';
7
6
  interface HicOptions extends BaseOptions {
8
7
  resolution?: number;
9
8
  bpPerPx?: number;
9
+ normalization?: string;
10
10
  }
11
- declare class GenericFilehandleWrapper {
12
- private filehandle;
13
- constructor(filehandle: GenericFilehandle);
14
- read(position: number, length: number): Promise<ArrayBuffer>;
15
- }
16
- export declare function openFilehandleWrapper(location: FileLocation, pluginManager?: PluginManager): GenericFilehandleWrapper;
17
11
  export default class HicAdapter extends BaseFeatureDataAdapter {
18
12
  private hic;
19
13
  constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
20
14
  private setup;
21
15
  getHeader(opts?: BaseOptions): Promise<{
16
+ norms: any;
22
17
  resolutions: number[];
23
18
  }>;
24
19
  getRefNames(opts?: BaseOptions): Promise<string[]>;
25
- getResolution(bpPerPx: number, opts?: BaseOptions): Promise<number>;
20
+ getResolution(res: number, opts?: BaseOptions): Promise<number>;
26
21
  getFeatures(region: Region, opts?: HicOptions): any;
27
22
  getMultiRegionFeatureDensityStats(_regions: Region[]): Promise<{
28
23
  featureDensity: number;
@@ -3,57 +3,40 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.openFilehandleWrapper = openFilehandleWrapper;
7
6
  const BaseAdapter_1 = require("@jbrowse/core/data_adapters/BaseAdapter");
8
7
  const rxjs_1 = require("@jbrowse/core/util/rxjs");
9
- const io_1 = require("@jbrowse/core/util/io");
10
8
  const hic_straw_1 = __importDefault(require("hic-straw"));
11
- const buffer_1 = require("buffer");
12
- // wraps generic-filehandle so the read function only takes a position and
13
- // length in some ways, generic-filehandle wishes it was just this but it has
14
- // to adapt to the node.js fs promises API
15
- class GenericFilehandleWrapper {
16
- constructor(filehandle) {
17
- this.filehandle = filehandle;
18
- }
19
- async read(position, length) {
20
- const { buffer } = await this.filehandle.read(buffer_1.Buffer.alloc(length), 0, length, position);
21
- return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
22
- }
23
- }
24
- function openFilehandleWrapper(location, pluginManager) {
25
- return new GenericFilehandleWrapper((0, io_1.openLocation)(location, pluginManager));
26
- }
9
+ const util_1 = require("@jbrowse/core/util");
10
+ // locals
11
+ const HicFilehandle_1 = require("./HicFilehandle");
27
12
  class HicAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
28
13
  constructor(config, getSubAdapter, pluginManager) {
29
14
  super(config, getSubAdapter, pluginManager);
30
- const hicLocation = this.getConf('hicLocation');
31
15
  this.hic = new hic_straw_1.default({
32
- file: openFilehandleWrapper(hicLocation, this.pluginManager),
16
+ file: (0, HicFilehandle_1.openHicFilehandle)(this.getConf('hicLocation'), this.pluginManager),
33
17
  });
34
18
  }
35
19
  async setup(opts) {
36
20
  const { statusCallback = () => { } } = opts || {};
37
- statusCallback('Downloading .hic header');
38
- const result = await this.hic.getMetaData();
39
- statusCallback('');
40
- return result;
21
+ return (0, util_1.updateStatus)('Downloading .hic header', statusCallback, () => this.hic.getMetaData());
41
22
  }
42
23
  async getHeader(opts) {
43
- const ret = await this.setup(opts);
44
- const { chromosomes, ...rest } = ret;
45
- return rest;
24
+ const { chromosomes, ...rest } = await this.setup(opts);
25
+ // @ts-expect-error
26
+ const norms = await this.hic.getNormalizationOptions();
27
+ return { ...rest, norms };
46
28
  }
47
29
  async getRefNames(opts) {
48
30
  const metadata = await this.setup(opts);
49
31
  return metadata.chromosomes.map(chr => chr.name);
50
32
  }
51
- async getResolution(bpPerPx, opts) {
33
+ async getResolution(res, opts) {
52
34
  const { resolutions } = await this.setup(opts);
35
+ const resolutionMultiplier = this.getConf('resolutionMultiplier');
53
36
  let chosenResolution = resolutions.at(-1);
54
37
  for (let i = resolutions.length - 1; i >= 0; i -= 1) {
55
38
  const r = resolutions[i];
56
- if (r <= 2 * bpPerPx) {
39
+ if (r <= 2 * res * resolutionMultiplier) {
57
40
  chosenResolution = r;
58
41
  }
59
42
  }
@@ -62,20 +45,22 @@ class HicAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
62
45
  getFeatures(region, opts = {}) {
63
46
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
64
47
  const { refName: chr, start, end } = region;
65
- const { resolution, bpPerPx = 1, statusCallback = () => { } } = opts;
48
+ const { resolution, normalization = 'KR', bpPerPx = 1, statusCallback = () => { }, } = opts;
66
49
  const res = await this.getResolution(bpPerPx / (resolution || 1000), opts);
67
- statusCallback('Downloading .hic data');
68
- const records = await this.hic.getContactRecords('KR', { start, chr, end }, { start, chr, end }, 'BP', res);
69
- for (const record of records) {
70
- observer.next(record);
71
- }
72
- statusCallback('');
50
+ await (0, util_1.updateStatus)('Downloading .hic data', statusCallback, async () => {
51
+ const records = await this.hic.getContactRecords(normalization, { start, chr, end }, { start, chr, end }, 'BP', res);
52
+ for (const record of records) {
53
+ observer.next(record);
54
+ }
55
+ });
73
56
  observer.complete();
74
57
  }, opts.signal);
75
58
  }
76
59
  // don't do feature stats estimation, similar to bigwigadapter
77
60
  async getMultiRegionFeatureDensityStats(_regions) {
78
- return { featureDensity: 0 };
61
+ return {
62
+ featureDensity: 0,
63
+ };
79
64
  }
80
65
  freeResources( /* { region } */) { }
81
66
  }
@@ -0,0 +1,10 @@
1
+ import { FileLocation } from '@jbrowse/core/util';
2
+ import type { GenericFilehandle } from 'generic-filehandle';
3
+ import PluginManager from '@jbrowse/core/PluginManager';
4
+ declare class HicFilehandle {
5
+ private filehandle;
6
+ constructor(filehandle: GenericFilehandle);
7
+ read(position: number, length: number): Promise<ArrayBuffer>;
8
+ }
9
+ export declare function openHicFilehandle(location: FileLocation, pluginManager?: PluginManager): HicFilehandle;
10
+ export {};
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openHicFilehandle = openHicFilehandle;
4
+ const io_1 = require("@jbrowse/core/util/io");
5
+ const buffer_1 = require("buffer");
6
+ // wraps generic-filehandle so the read function only takes a position and
7
+ // length
8
+ //
9
+ // in some ways, generic-filehandle wishes it was just this but it has
10
+ // to adapt to the node.js fs promises API
11
+ class HicFilehandle {
12
+ constructor(filehandle) {
13
+ this.filehandle = filehandle;
14
+ }
15
+ async read(position, length) {
16
+ const { buffer } = await this.filehandle.read(buffer_1.Buffer.alloc(length), 0, length, position);
17
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
18
+ }
19
+ }
20
+ function openHicFilehandle(location, pluginManager) {
21
+ return new HicFilehandle((0, io_1.openLocation)(location, pluginManager));
22
+ }
@@ -9,5 +9,13 @@ declare const HicAdapter: import("@jbrowse/core/configuration/configurationSchem
9
9
  locationType: string;
10
10
  };
11
11
  };
12
+ /**
13
+ * #slot
14
+ */
15
+ resolutionMultiplier: {
16
+ type: string;
17
+ defaultValue: number;
18
+ description: string;
19
+ };
12
20
  }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
13
21
  export default HicAdapter;
@@ -17,5 +17,13 @@ const HicAdapter = (0, configuration_1.ConfigurationSchema)('HicAdapter', {
17
17
  locationType: 'UriLocation',
18
18
  },
19
19
  },
20
+ /**
21
+ * #slot
22
+ */
23
+ resolutionMultiplier: {
24
+ type: 'number',
25
+ defaultValue: 1,
26
+ description: 'Initial resolution multiplier',
27
+ },
20
28
  }, { explicitlyTyped: true });
21
29
  exports.default = HicAdapter;
@@ -48,4 +48,4 @@ export default class HicRenderer extends ServerSideRendererType {
48
48
  }>;
49
49
  getFeatures(args: RenderArgsDeserialized): Promise<any>;
50
50
  }
51
- export { type RenderArgsSerialized, type RenderResults, } from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType';
51
+ export type { RenderArgsSerialized, RenderResults, } from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType';
@@ -1,12 +1,6 @@
1
1
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
2
2
  export default function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
3
- id: import("mobx-state-tree").IOptionalIType<import(
4
- /**
5
- * #stateModel LinearHicDisplay
6
- * #category display
7
- * extends `BaseLinearDisplay`
8
- */
9
- "mobx-state-tree").ISimpleType<string>, [undefined]>;
3
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
10
4
  type: import("mobx-state-tree").ISimpleType<string>;
11
5
  rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
12
6
  } & {
@@ -18,12 +12,16 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
18
12
  blockState: import("mobx-state-tree").IMapType<import("mobx-state-tree").IModelType<{
19
13
  key: import("mobx-state-tree").ISimpleType<string>;
20
14
  region: import("mobx-state-tree").IModelType<{
21
- refName: import("mobx-state-tree").ISimpleType<string>;
15
+ refName: import("mobx-state-tree" /**
16
+ * #property
17
+ */).ISimpleType<string>;
22
18
  start: import("mobx-state-tree").ISimpleType<number>;
23
19
  end: import("mobx-state-tree").ISimpleType<number>;
24
20
  reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
25
21
  } & {
26
- assemblyName: import("mobx-state-tree").ISimpleType<string>;
22
+ assemblyName: import("mobx-state-tree" /**
23
+ * #property
24
+ */).ISimpleType<string>;
27
25
  }, {
28
26
  setRefName(newRefName: string): void;
29
27
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -33,9 +31,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
33
31
  }, {
34
32
  renderInProgress: AbortController | undefined;
35
33
  filled: boolean;
36
- reactElement: React.ReactElement /**
37
- * #getter
38
- */ | undefined;
34
+ reactElement: React.ReactElement | undefined;
39
35
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
40
36
  layout: any;
41
37
  status: string;
@@ -44,13 +40,17 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
44
40
  maxHeightReached: boolean;
45
41
  ReactComponent: ({ model, }: {
46
42
  model: {
47
- error? /**
48
- * #method
49
- */: unknown;
43
+ error?: unknown;
50
44
  reload: () => void;
51
45
  message: React.ReactNode;
52
46
  filled?: boolean;
53
- status?: string;
47
+ status
48
+ /**
49
+ * #getter
50
+ */
51
+ ? /**
52
+ * #getter
53
+ */: string;
54
54
  reactElement?: React.ReactElement;
55
55
  };
56
56
  }) => import("react").JSX.Element | undefined;
@@ -106,6 +106,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
106
106
  resolution: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
107
107
  useLogScale: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
108
108
  colorScheme: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
109
+ activeNormalization: import("mobx-state-tree").IType<string | undefined, string, string>;
109
110
  }, {
110
111
  rendererTypeName: string;
111
112
  error: unknown;
@@ -120,17 +121,19 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
120
121
  rendererTypeName: string;
121
122
  error: unknown;
122
123
  message: string | undefined;
123
- } & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
124
- id: import("mobx-state-tree" /**
125
- * #getter
126
- */).IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
124
+ } & import("mobx-state-tree" /**
125
+ * #property
126
+ */).IStateTreeNode<import("mobx-state-tree").IModelType<{
127
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
127
128
  type: import("mobx-state-tree").ISimpleType<string>;
128
129
  rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
129
130
  }, {
130
131
  rendererTypeName: string;
131
132
  error: unknown;
132
133
  message: string | undefined;
133
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
134
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree" /**
135
+ * #method
136
+ */)._NotCustomized>>;
134
137
  onHorizontalScroll?: () => void;
135
138
  blockState?: Record<string, any>;
136
139
  }>;
@@ -233,6 +236,11 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
233
236
  } & {
234
237
  renderSvg(opts: import("@jbrowse/plugin-linear-genome-view").ExportSvgDisplayOptions): Promise<import("react").JSX.Element>;
235
238
  afterAttach(): void;
239
+ } & {
240
+ /**
241
+ * #volatile
242
+ */
243
+ availableNormalizations: string[] | undefined;
236
244
  } & {
237
245
  /**
238
246
  * #getter
@@ -259,6 +267,14 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
259
267
  * #action
260
268
  */
261
269
  setColorScheme(f?: string): void;
270
+ /**
271
+ * #action
272
+ */
273
+ setActiveNormalization(f: string): void;
274
+ /**
275
+ * #action
276
+ */
277
+ setAvailableNormalizations(f: string[]): void;
262
278
  } & {
263
279
  /**
264
280
  * #getter
@@ -278,7 +294,20 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
278
294
  }[];
279
295
  checked?: undefined;
280
296
  onClick?: undefined;
297
+ } | {
298
+ label: string;
299
+ subMenu: {
300
+ label: string;
301
+ type: string;
302
+ checked: boolean;
303
+ onClick: () => void;
304
+ }[];
305
+ type?: undefined;
306
+ checked?: undefined;
307
+ onClick?: undefined;
281
308
  })[];
309
+ } & {
310
+ afterAttach(): void;
282
311
  }, {
283
312
  type: string;
284
313
  } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
@@ -309,9 +338,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
309
338
  }, {
310
339
  renderInProgress: AbortController | undefined;
311
340
  filled: boolean;
312
- reactElement: React.ReactElement /**
313
- * #getter
314
- */ | undefined;
341
+ reactElement: React.ReactElement | undefined;
315
342
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
316
343
  layout: any;
317
344
  status: string;
@@ -320,13 +347,17 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
320
347
  maxHeightReached: boolean;
321
348
  ReactComponent: ({ model, }: {
322
349
  model: {
323
- error? /**
324
- * #method
325
- */: unknown;
350
+ error?: unknown;
326
351
  reload: () => void;
327
352
  message: React.ReactNode;
328
353
  filled?: boolean;
329
- status?: string;
354
+ status
355
+ /**
356
+ * #getter
357
+ */
358
+ ? /**
359
+ * #getter
360
+ */: string;
330
361
  reactElement?: React.ReactElement;
331
362
  };
332
363
  }) => import("react").JSX.Element | undefined;
@@ -4,6 +4,8 @@ exports.default = stateModelFactory;
4
4
  const configuration_1 = require("@jbrowse/core/configuration");
5
5
  const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view");
6
6
  const mobx_state_tree_1 = require("mobx-state-tree");
7
+ const mobx_1 = require("mobx");
8
+ const util_1 = require("@jbrowse/core/util");
7
9
  /**
8
10
  * #stateModel LinearHicDisplay
9
11
  * #category display
@@ -33,6 +35,16 @@ function stateModelFactory(configSchema) {
33
35
  * #property
34
36
  */
35
37
  colorScheme: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.string),
38
+ /**
39
+ * #property
40
+ */
41
+ activeNormalization: 'KR',
42
+ }))
43
+ .volatile(() => ({
44
+ /**
45
+ * #volatile
46
+ */
47
+ availableNormalizations: undefined,
36
48
  }))
37
49
  .views(self => {
38
50
  const { renderProps: superRenderProps } = self;
@@ -63,6 +75,7 @@ function stateModelFactory(configSchema) {
63
75
  return {
64
76
  ...superRenderProps(),
65
77
  config,
78
+ normalization: self.activeNormalization,
66
79
  rpcDriverName: self.rpcDriverName,
67
80
  displayModel: self,
68
81
  resolution: self.resolution,
@@ -91,6 +104,18 @@ function stateModelFactory(configSchema) {
91
104
  setColorScheme(f) {
92
105
  self.colorScheme = f;
93
106
  },
107
+ /**
108
+ * #action
109
+ */
110
+ setActiveNormalization(f) {
111
+ self.activeNormalization = f;
112
+ },
113
+ /**
114
+ * #action
115
+ */
116
+ setAvailableNormalizations(f) {
117
+ self.availableNormalizations = f;
118
+ },
94
119
  }))
95
120
  .views(self => {
96
121
  const { trackMenuItems: superTrackMenuItems } = self;
@@ -156,8 +181,44 @@ function stateModelFactory(configSchema) {
156
181
  },
157
182
  ],
158
183
  },
184
+ ...(self.availableNormalizations
185
+ ? [
186
+ {
187
+ label: 'Normalization scheme',
188
+ subMenu: self.availableNormalizations.map(norm => ({
189
+ label: norm,
190
+ type: 'checkbox',
191
+ checked: norm === self.activeNormalization,
192
+ onClick: () => {
193
+ self.setActiveNormalization(norm);
194
+ },
195
+ })),
196
+ },
197
+ ]
198
+ : []),
159
199
  ];
160
200
  },
161
201
  };
162
- });
202
+ })
203
+ .actions(self => ({
204
+ afterAttach() {
205
+ (0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(async () => {
206
+ try {
207
+ const { rpcManager } = (0, util_1.getSession)(self);
208
+ const track = (0, util_1.getContainingTrack)(self);
209
+ const adapterConfig = (0, configuration_1.getConf)(track, 'adapter');
210
+ const { norms } = (await rpcManager.call((0, configuration_1.getConf)(track, 'trackId'), 'CoreGetInfo', {
211
+ adapterConfig,
212
+ }));
213
+ if (norms) {
214
+ self.setAvailableNormalizations(norms);
215
+ }
216
+ }
217
+ catch (e) {
218
+ console.error(e);
219
+ (0, util_1.getSession)(self).notifyError(`${e}`, e);
220
+ }
221
+ }));
222
+ },
223
+ }));
163
224
  }
@@ -1,28 +1,23 @@
1
1
  import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
2
- import { Region, FileLocation } from '@jbrowse/core/util/types';
3
- import type { GenericFilehandle } from 'generic-filehandle';
2
+ import { Region } from '@jbrowse/core/util/types';
4
3
  import PluginManager from '@jbrowse/core/PluginManager';
5
4
  import { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
6
5
  import { AnyConfigurationModel } from '@jbrowse/core/configuration';
7
6
  interface HicOptions extends BaseOptions {
8
7
  resolution?: number;
9
8
  bpPerPx?: number;
9
+ normalization?: string;
10
10
  }
11
- declare class GenericFilehandleWrapper {
12
- private filehandle;
13
- constructor(filehandle: GenericFilehandle);
14
- read(position: number, length: number): Promise<ArrayBuffer>;
15
- }
16
- export declare function openFilehandleWrapper(location: FileLocation, pluginManager?: PluginManager): GenericFilehandleWrapper;
17
11
  export default class HicAdapter extends BaseFeatureDataAdapter {
18
12
  private hic;
19
13
  constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
20
14
  private setup;
21
15
  getHeader(opts?: BaseOptions): Promise<{
16
+ norms: any;
22
17
  resolutions: number[];
23
18
  }>;
24
19
  getRefNames(opts?: BaseOptions): Promise<string[]>;
25
- getResolution(bpPerPx: number, opts?: BaseOptions): Promise<number>;
20
+ getResolution(res: number, opts?: BaseOptions): Promise<number>;
26
21
  getFeatures(region: Region, opts?: HicOptions): any;
27
22
  getMultiRegionFeatureDensityStats(_regions: Region[]): Promise<{
28
23
  featureDensity: number;
@@ -1,53 +1,37 @@
1
1
  import { BaseFeatureDataAdapter, } from '@jbrowse/core/data_adapters/BaseAdapter';
2
2
  import { ObservableCreate } from '@jbrowse/core/util/rxjs';
3
- import { openLocation } from '@jbrowse/core/util/io';
4
3
  import HicStraw from 'hic-straw';
5
- import { Buffer } from 'buffer';
6
- // wraps generic-filehandle so the read function only takes a position and
7
- // length in some ways, generic-filehandle wishes it was just this but it has
8
- // to adapt to the node.js fs promises API
9
- class GenericFilehandleWrapper {
10
- constructor(filehandle) {
11
- this.filehandle = filehandle;
12
- }
13
- async read(position, length) {
14
- const { buffer } = await this.filehandle.read(Buffer.alloc(length), 0, length, position);
15
- return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
16
- }
17
- }
18
- export function openFilehandleWrapper(location, pluginManager) {
19
- return new GenericFilehandleWrapper(openLocation(location, pluginManager));
20
- }
4
+ import { updateStatus } from '@jbrowse/core/util';
5
+ // locals
6
+ import { openHicFilehandle } from './HicFilehandle';
21
7
  export default class HicAdapter extends BaseFeatureDataAdapter {
22
8
  constructor(config, getSubAdapter, pluginManager) {
23
9
  super(config, getSubAdapter, pluginManager);
24
- const hicLocation = this.getConf('hicLocation');
25
10
  this.hic = new HicStraw({
26
- file: openFilehandleWrapper(hicLocation, this.pluginManager),
11
+ file: openHicFilehandle(this.getConf('hicLocation'), this.pluginManager),
27
12
  });
28
13
  }
29
14
  async setup(opts) {
30
15
  const { statusCallback = () => { } } = opts || {};
31
- statusCallback('Downloading .hic header');
32
- const result = await this.hic.getMetaData();
33
- statusCallback('');
34
- return result;
16
+ return updateStatus('Downloading .hic header', statusCallback, () => this.hic.getMetaData());
35
17
  }
36
18
  async getHeader(opts) {
37
- const ret = await this.setup(opts);
38
- const { chromosomes, ...rest } = ret;
39
- return rest;
19
+ const { chromosomes, ...rest } = await this.setup(opts);
20
+ // @ts-expect-error
21
+ const norms = await this.hic.getNormalizationOptions();
22
+ return { ...rest, norms };
40
23
  }
41
24
  async getRefNames(opts) {
42
25
  const metadata = await this.setup(opts);
43
26
  return metadata.chromosomes.map(chr => chr.name);
44
27
  }
45
- async getResolution(bpPerPx, opts) {
28
+ async getResolution(res, opts) {
46
29
  const { resolutions } = await this.setup(opts);
30
+ const resolutionMultiplier = this.getConf('resolutionMultiplier');
47
31
  let chosenResolution = resolutions.at(-1);
48
32
  for (let i = resolutions.length - 1; i >= 0; i -= 1) {
49
33
  const r = resolutions[i];
50
- if (r <= 2 * bpPerPx) {
34
+ if (r <= 2 * res * resolutionMultiplier) {
51
35
  chosenResolution = r;
52
36
  }
53
37
  }
@@ -56,20 +40,22 @@ export default class HicAdapter extends BaseFeatureDataAdapter {
56
40
  getFeatures(region, opts = {}) {
57
41
  return ObservableCreate(async (observer) => {
58
42
  const { refName: chr, start, end } = region;
59
- const { resolution, bpPerPx = 1, statusCallback = () => { } } = opts;
43
+ const { resolution, normalization = 'KR', bpPerPx = 1, statusCallback = () => { }, } = opts;
60
44
  const res = await this.getResolution(bpPerPx / (resolution || 1000), opts);
61
- statusCallback('Downloading .hic data');
62
- const records = await this.hic.getContactRecords('KR', { start, chr, end }, { start, chr, end }, 'BP', res);
63
- for (const record of records) {
64
- observer.next(record);
65
- }
66
- statusCallback('');
45
+ await updateStatus('Downloading .hic data', statusCallback, async () => {
46
+ const records = await this.hic.getContactRecords(normalization, { start, chr, end }, { start, chr, end }, 'BP', res);
47
+ for (const record of records) {
48
+ observer.next(record);
49
+ }
50
+ });
67
51
  observer.complete();
68
52
  }, opts.signal);
69
53
  }
70
54
  // don't do feature stats estimation, similar to bigwigadapter
71
55
  async getMultiRegionFeatureDensityStats(_regions) {
72
- return { featureDensity: 0 };
56
+ return {
57
+ featureDensity: 0,
58
+ };
73
59
  }
74
60
  freeResources( /* { region } */) { }
75
61
  }
@@ -0,0 +1,10 @@
1
+ import { FileLocation } from '@jbrowse/core/util';
2
+ import type { GenericFilehandle } from 'generic-filehandle';
3
+ import PluginManager from '@jbrowse/core/PluginManager';
4
+ declare class HicFilehandle {
5
+ private filehandle;
6
+ constructor(filehandle: GenericFilehandle);
7
+ read(position: number, length: number): Promise<ArrayBuffer>;
8
+ }
9
+ export declare function openHicFilehandle(location: FileLocation, pluginManager?: PluginManager): HicFilehandle;
10
+ export {};
@@ -0,0 +1,19 @@
1
+ import { openLocation } from '@jbrowse/core/util/io';
2
+ import { Buffer } from 'buffer';
3
+ // wraps generic-filehandle so the read function only takes a position and
4
+ // length
5
+ //
6
+ // in some ways, generic-filehandle wishes it was just this but it has
7
+ // to adapt to the node.js fs promises API
8
+ class HicFilehandle {
9
+ constructor(filehandle) {
10
+ this.filehandle = filehandle;
11
+ }
12
+ async read(position, length) {
13
+ const { buffer } = await this.filehandle.read(Buffer.alloc(length), 0, length, position);
14
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
15
+ }
16
+ }
17
+ export function openHicFilehandle(location, pluginManager) {
18
+ return new HicFilehandle(openLocation(location, pluginManager));
19
+ }
@@ -9,5 +9,13 @@ declare const HicAdapter: import("@jbrowse/core/configuration/configurationSchem
9
9
  locationType: string;
10
10
  };
11
11
  };
12
+ /**
13
+ * #slot
14
+ */
15
+ resolutionMultiplier: {
16
+ type: string;
17
+ defaultValue: number;
18
+ description: string;
19
+ };
12
20
  }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
13
21
  export default HicAdapter;
@@ -15,5 +15,13 @@ const HicAdapter = ConfigurationSchema('HicAdapter', {
15
15
  locationType: 'UriLocation',
16
16
  },
17
17
  },
18
+ /**
19
+ * #slot
20
+ */
21
+ resolutionMultiplier: {
22
+ type: 'number',
23
+ defaultValue: 1,
24
+ description: 'Initial resolution multiplier',
25
+ },
18
26
  }, { explicitlyTyped: true });
19
27
  export default HicAdapter;
@@ -48,4 +48,4 @@ export default class HicRenderer extends ServerSideRendererType {
48
48
  }>;
49
49
  getFeatures(args: RenderArgsDeserialized): Promise<any>;
50
50
  }
51
- export { type RenderArgsSerialized, type RenderResults, } from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType';
51
+ export type { RenderArgsSerialized, RenderResults, } from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType';
@@ -1,12 +1,6 @@
1
1
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
2
2
  export default function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
3
- id: import("mobx-state-tree").IOptionalIType<import(
4
- /**
5
- * #stateModel LinearHicDisplay
6
- * #category display
7
- * extends `BaseLinearDisplay`
8
- */
9
- "mobx-state-tree").ISimpleType<string>, [undefined]>;
3
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
10
4
  type: import("mobx-state-tree").ISimpleType<string>;
11
5
  rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
12
6
  } & {
@@ -18,12 +12,16 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
18
12
  blockState: import("mobx-state-tree").IMapType<import("mobx-state-tree").IModelType<{
19
13
  key: import("mobx-state-tree").ISimpleType<string>;
20
14
  region: import("mobx-state-tree").IModelType<{
21
- refName: import("mobx-state-tree").ISimpleType<string>;
15
+ refName: import("mobx-state-tree" /**
16
+ * #property
17
+ */).ISimpleType<string>;
22
18
  start: import("mobx-state-tree").ISimpleType<number>;
23
19
  end: import("mobx-state-tree").ISimpleType<number>;
24
20
  reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
25
21
  } & {
26
- assemblyName: import("mobx-state-tree").ISimpleType<string>;
22
+ assemblyName: import("mobx-state-tree" /**
23
+ * #property
24
+ */).ISimpleType<string>;
27
25
  }, {
28
26
  setRefName(newRefName: string): void;
29
27
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -33,9 +31,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
33
31
  }, {
34
32
  renderInProgress: AbortController | undefined;
35
33
  filled: boolean;
36
- reactElement: React.ReactElement /**
37
- * #getter
38
- */ | undefined;
34
+ reactElement: React.ReactElement | undefined;
39
35
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
40
36
  layout: any;
41
37
  status: string;
@@ -44,13 +40,17 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
44
40
  maxHeightReached: boolean;
45
41
  ReactComponent: ({ model, }: {
46
42
  model: {
47
- error? /**
48
- * #method
49
- */: unknown;
43
+ error?: unknown;
50
44
  reload: () => void;
51
45
  message: React.ReactNode;
52
46
  filled?: boolean;
53
- status?: string;
47
+ status
48
+ /**
49
+ * #getter
50
+ */
51
+ ? /**
52
+ * #getter
53
+ */: string;
54
54
  reactElement?: React.ReactElement;
55
55
  };
56
56
  }) => import("react").JSX.Element | undefined;
@@ -106,6 +106,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
106
106
  resolution: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
107
107
  useLogScale: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
108
108
  colorScheme: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
109
+ activeNormalization: import("mobx-state-tree").IType<string | undefined, string, string>;
109
110
  }, {
110
111
  rendererTypeName: string;
111
112
  error: unknown;
@@ -120,17 +121,19 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
120
121
  rendererTypeName: string;
121
122
  error: unknown;
122
123
  message: string | undefined;
123
- } & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
124
- id: import("mobx-state-tree" /**
125
- * #getter
126
- */).IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
124
+ } & import("mobx-state-tree" /**
125
+ * #property
126
+ */).IStateTreeNode<import("mobx-state-tree").IModelType<{
127
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
127
128
  type: import("mobx-state-tree").ISimpleType<string>;
128
129
  rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
129
130
  }, {
130
131
  rendererTypeName: string;
131
132
  error: unknown;
132
133
  message: string | undefined;
133
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
134
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree" /**
135
+ * #method
136
+ */)._NotCustomized>>;
134
137
  onHorizontalScroll?: () => void;
135
138
  blockState?: Record<string, any>;
136
139
  }>;
@@ -233,6 +236,11 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
233
236
  } & {
234
237
  renderSvg(opts: import("@jbrowse/plugin-linear-genome-view").ExportSvgDisplayOptions): Promise<import("react").JSX.Element>;
235
238
  afterAttach(): void;
239
+ } & {
240
+ /**
241
+ * #volatile
242
+ */
243
+ availableNormalizations: string[] | undefined;
236
244
  } & {
237
245
  /**
238
246
  * #getter
@@ -259,6 +267,14 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
259
267
  * #action
260
268
  */
261
269
  setColorScheme(f?: string): void;
270
+ /**
271
+ * #action
272
+ */
273
+ setActiveNormalization(f: string): void;
274
+ /**
275
+ * #action
276
+ */
277
+ setAvailableNormalizations(f: string[]): void;
262
278
  } & {
263
279
  /**
264
280
  * #getter
@@ -278,7 +294,20 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
278
294
  }[];
279
295
  checked?: undefined;
280
296
  onClick?: undefined;
297
+ } | {
298
+ label: string;
299
+ subMenu: {
300
+ label: string;
301
+ type: string;
302
+ checked: boolean;
303
+ onClick: () => void;
304
+ }[];
305
+ type?: undefined;
306
+ checked?: undefined;
307
+ onClick?: undefined;
281
308
  })[];
309
+ } & {
310
+ afterAttach(): void;
282
311
  }, {
283
312
  type: string;
284
313
  } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
@@ -309,9 +338,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
309
338
  }, {
310
339
  renderInProgress: AbortController | undefined;
311
340
  filled: boolean;
312
- reactElement: React.ReactElement /**
313
- * #getter
314
- */ | undefined;
341
+ reactElement: React.ReactElement | undefined;
315
342
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
316
343
  layout: any;
317
344
  status: string;
@@ -320,13 +347,17 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
320
347
  maxHeightReached: boolean;
321
348
  ReactComponent: ({ model, }: {
322
349
  model: {
323
- error? /**
324
- * #method
325
- */: unknown;
350
+ error?: unknown;
326
351
  reload: () => void;
327
352
  message: React.ReactNode;
328
353
  filled?: boolean;
329
- status?: string;
354
+ status
355
+ /**
356
+ * #getter
357
+ */
358
+ ? /**
359
+ * #getter
360
+ */: string;
330
361
  reactElement?: React.ReactElement;
331
362
  };
332
363
  }) => import("react").JSX.Element | undefined;
@@ -1,6 +1,8 @@
1
1
  import { ConfigurationReference, getConf } from '@jbrowse/core/configuration';
2
2
  import { BaseLinearDisplay } from '@jbrowse/plugin-linear-genome-view';
3
- import { types, getEnv } from 'mobx-state-tree';
3
+ import { types, getEnv, addDisposer } from 'mobx-state-tree';
4
+ import { autorun } from 'mobx';
5
+ import { getContainingTrack, getSession } from '@jbrowse/core/util';
4
6
  /**
5
7
  * #stateModel LinearHicDisplay
6
8
  * #category display
@@ -30,6 +32,16 @@ export default function stateModelFactory(configSchema) {
30
32
  * #property
31
33
  */
32
34
  colorScheme: types.maybe(types.string),
35
+ /**
36
+ * #property
37
+ */
38
+ activeNormalization: 'KR',
39
+ }))
40
+ .volatile(() => ({
41
+ /**
42
+ * #volatile
43
+ */
44
+ availableNormalizations: undefined,
33
45
  }))
34
46
  .views(self => {
35
47
  const { renderProps: superRenderProps } = self;
@@ -60,6 +72,7 @@ export default function stateModelFactory(configSchema) {
60
72
  return {
61
73
  ...superRenderProps(),
62
74
  config,
75
+ normalization: self.activeNormalization,
63
76
  rpcDriverName: self.rpcDriverName,
64
77
  displayModel: self,
65
78
  resolution: self.resolution,
@@ -88,6 +101,18 @@ export default function stateModelFactory(configSchema) {
88
101
  setColorScheme(f) {
89
102
  self.colorScheme = f;
90
103
  },
104
+ /**
105
+ * #action
106
+ */
107
+ setActiveNormalization(f) {
108
+ self.activeNormalization = f;
109
+ },
110
+ /**
111
+ * #action
112
+ */
113
+ setAvailableNormalizations(f) {
114
+ self.availableNormalizations = f;
115
+ },
91
116
  }))
92
117
  .views(self => {
93
118
  const { trackMenuItems: superTrackMenuItems } = self;
@@ -153,8 +178,44 @@ export default function stateModelFactory(configSchema) {
153
178
  },
154
179
  ],
155
180
  },
181
+ ...(self.availableNormalizations
182
+ ? [
183
+ {
184
+ label: 'Normalization scheme',
185
+ subMenu: self.availableNormalizations.map(norm => ({
186
+ label: norm,
187
+ type: 'checkbox',
188
+ checked: norm === self.activeNormalization,
189
+ onClick: () => {
190
+ self.setActiveNormalization(norm);
191
+ },
192
+ })),
193
+ },
194
+ ]
195
+ : []),
156
196
  ];
157
197
  },
158
198
  };
159
- });
199
+ })
200
+ .actions(self => ({
201
+ afterAttach() {
202
+ addDisposer(self, autorun(async () => {
203
+ try {
204
+ const { rpcManager } = getSession(self);
205
+ const track = getContainingTrack(self);
206
+ const adapterConfig = getConf(track, 'adapter');
207
+ const { norms } = (await rpcManager.call(getConf(track, 'trackId'), 'CoreGetInfo', {
208
+ adapterConfig,
209
+ }));
210
+ if (norms) {
211
+ self.setAvailableNormalizations(norms);
212
+ }
213
+ }
214
+ catch (e) {
215
+ console.error(e);
216
+ getSession(self).notifyError(`${e}`, e);
217
+ }
218
+ }));
219
+ },
220
+ }));
160
221
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-hic",
3
- "version": "2.15.4",
3
+ "version": "2.16.1",
4
4
  "description": "JBrowse 2 hic adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -55,5 +55,5 @@
55
55
  "publishConfig": {
56
56
  "access": "public"
57
57
  },
58
- "gitHead": "686b4ad9016b3586e8230180f7adb44c238ba4fb"
58
+ "gitHead": "c6a658d2344989895543f0456b1cf7dd3b937769"
59
59
  }