import { BaseFeatureDataAdapter , BaseOptions , } from '@jbrowse/core/data_adapters/BaseAdapter' ; import { Region , FileLocation } from '@jbrowse/core/util/types' ; import { ObservableCreate } from '@jbrowse/core/util/rxjs' ; import { openLocation } from '@jbrowse/core/util/io' ; import { Instance } from 'mobx-state-tree' ; import { readConfObject } from '@jbrowse/core/configuration' ; import type { GenericFilehandle } from 'generic-filehandle' ; import HicStraw from 'hic-straw' ; import MyConfigSchema from './configSchema' ; import PluginManager from '@jbrowse/core/PluginManager' ; import { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache' ; interface ContactRecord { bin1 : number ; bin2 : number ; counts : number ; } interface HicMetadata { chromosomes : { name : string ; length : number ; id : number ; } [ ] ; resolutions : number [ ] ; } interface Ref { chr : string ; start : number ; end : number ; } interface HicOptions extends BaseOptions { resolution ? : number ; bpPerPx ? : number ; } class GenericFilehandleWrapper { constructor ( private filehandle ) { } async read ( position , length ) { const { buffer : b , bytesRead } = await this . filehandle . read ( Buffer . allocUnsafe ( length ) , 0 , length , position ) ; return b . buffer . slice ( b . byteOffset , b . byteOffset + bytesRead ) ; } } export function openFilehandleWrapper ( location ) { return new GenericFilehandleWrapper ( openLocation ( location ) ) ; } export default class HicAdapter extends BaseFeatureDataAdapter { private hic : { getContactRecords : ( normalize : string , ref : Ref , ref2 : Ref , units : string , binsize : number ) => Promise < ContactRecord [ ] > ; getMetaData : ( ) => Promise < HicMetadata > ; } ; public constructor ( config , getSubAdapter ? , pluginManager ? ) { super ( config , getSubAdapter , pluginManager ) ; const hicLocation = readConfObject ( config , 'hicLocation' ) ; this . hic = new HicStraw ( { file : openFilehandleWrapper ( hicLocation ) , } ) ; } private async setup ( opts ? ) { const { statusCallback = ( ) => { } } = opts || { } ; statusCallback ( 'Downloading .hic header' ) ; const result = await this . hic . getMetaData ( ) ; statusCallback ( '' ) ; return result ; } public async getHeader ( opts ? ) { const ret = await this . setup ( opts ) ; const { chromosomes , ... rest } = ret ; return rest ; } async getRefNames ( opts ? ) { const metadata = await this . setup ( opts ) ; return metadata . chromosomes . map ( chr => chr . name ) ; } async getResolution ( bpPerPx , opts ? ) { const metadata = await this . setup ( opts ) ; const { resolutions } = metadata ; let chosenResolution = resolutions [ resolutions . length - 1 ] ; for ( let i = resolutions . length - 1 ; i >= 0 ; i -= 1 ) { const r = resolutions [ i ] ; if ( r <= 2 * bpPerPx ) { chosenResolution = r ; } } return chosenResolution ; } getFeatures ( region , opts = { } ) { return ObservableCreate < ContactRecord > ( async ( observer ) => { const { refName : chr , start , end } = region ; const { resolution , bpPerPx = 1 , statusCallback = ( ) => { } } = opts ; const res = await this . getResolution ( bpPerPx / ( resolution || 1000 ) , opts ) ; statusCallback ( 'Downloading .hic data' ) ; const records = await this . hic . getContactRecords ( 'KR' , { start , chr , end } , { start , chr , end } , 'BP' , res ) ; records . forEach ( record => { observer . next ( record ) ; } ) ; statusCallback ( '' ) ; observer . complete ( ) ; } , opts . signal ) as any ; } freeResources ( ) { } }