@gmod/cram 2.0.0 → 2.0.2

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 (143) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/craiIndex.d.ts +2 -2
  3. package/dist/craiIndex.js +5 -9
  4. package/dist/craiIndex.js.map +1 -1
  5. package/dist/cram-bundle.js +1 -1
  6. package/dist/cramFile/codecs/_base.d.ts +6 -6
  7. package/dist/cramFile/codecs/beta.js.map +1 -1
  8. package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
  9. package/dist/cramFile/codecs/byteArrayStop.js.map +1 -1
  10. package/dist/cramFile/codecs/external.js +1 -0
  11. package/dist/cramFile/codecs/external.js.map +1 -1
  12. package/dist/cramFile/codecs/gamma.js.map +1 -1
  13. package/dist/cramFile/codecs/getBits.js.map +1 -1
  14. package/dist/cramFile/codecs/huffman.d.ts +0 -1
  15. package/dist/cramFile/codecs/huffman.js +1 -3
  16. package/dist/cramFile/codecs/huffman.js.map +1 -1
  17. package/dist/cramFile/codecs/index.js.map +1 -1
  18. package/dist/cramFile/codecs/subexp.js.map +1 -1
  19. package/dist/cramFile/container/compressionScheme.js +1 -1
  20. package/dist/cramFile/container/compressionScheme.js.map +1 -1
  21. package/dist/cramFile/container/index.js.map +1 -1
  22. package/dist/cramFile/encoding.d.ts +20 -20
  23. package/dist/cramFile/file.d.ts +14 -7
  24. package/dist/cramFile/file.js.map +1 -1
  25. package/dist/cramFile/filehandle.d.ts +1 -2
  26. package/dist/cramFile/index.d.ts +1 -2
  27. package/dist/cramFile/index.js +3 -3
  28. package/dist/cramFile/index.js.map +1 -1
  29. package/dist/cramFile/record.d.ts +6 -6
  30. package/dist/cramFile/record.js +7 -4
  31. package/dist/cramFile/record.js.map +1 -1
  32. package/dist/cramFile/sectionParsers.d.ts +9 -8
  33. package/dist/cramFile/sectionParsers.js +10 -11
  34. package/dist/cramFile/sectionParsers.js.map +1 -1
  35. package/dist/cramFile/slice/decodeRecord.js +7 -11
  36. package/dist/cramFile/slice/decodeRecord.js.map +1 -1
  37. package/dist/cramFile/slice/index.js +24 -22
  38. package/dist/cramFile/slice/index.js.map +1 -1
  39. package/dist/cramFile/util.d.ts +1 -0
  40. package/dist/cramFile/util.js +1 -1
  41. package/dist/cramFile/util.js.map +1 -1
  42. package/dist/index.d.ts +3 -4
  43. package/dist/index.js +7 -30
  44. package/dist/index.js.map +1 -1
  45. package/dist/indexedCramFile.d.ts +6 -6
  46. package/dist/indexedCramFile.js +13 -18
  47. package/dist/indexedCramFile.js.map +1 -1
  48. package/dist/io/index.d.ts +2 -1
  49. package/dist/io/index.js +4 -3
  50. package/dist/io/index.js.map +1 -1
  51. package/dist/rans/d04.js.map +1 -1
  52. package/dist/rans/d14.js.map +1 -1
  53. package/dist/rans/decoding.js.map +1 -1
  54. package/dist/rans/frequencies.js.map +1 -1
  55. package/dist/rans/index.js.map +1 -1
  56. package/dist/sam.d.ts +5 -6
  57. package/dist/sam.js +20 -7
  58. package/dist/sam.js.map +1 -1
  59. package/dist/typescript.js.map +1 -1
  60. package/dist/unzip.d.ts +2 -2
  61. package/dist/unzip.js +1 -1
  62. package/dist/unzip.js.map +1 -1
  63. package/esm/craiIndex.d.ts +2 -2
  64. package/esm/craiIndex.js +5 -9
  65. package/esm/craiIndex.js.map +1 -1
  66. package/esm/cramFile/codecs/_base.d.ts +6 -6
  67. package/esm/cramFile/codecs/beta.js.map +1 -1
  68. package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
  69. package/esm/cramFile/codecs/byteArrayStop.js.map +1 -1
  70. package/esm/cramFile/codecs/external.js +1 -0
  71. package/esm/cramFile/codecs/external.js.map +1 -1
  72. package/esm/cramFile/codecs/gamma.js.map +1 -1
  73. package/esm/cramFile/codecs/getBits.js.map +1 -1
  74. package/esm/cramFile/codecs/huffman.d.ts +0 -1
  75. package/esm/cramFile/codecs/huffman.js +1 -3
  76. package/esm/cramFile/codecs/huffman.js.map +1 -1
  77. package/esm/cramFile/codecs/index.js.map +1 -1
  78. package/esm/cramFile/codecs/subexp.js.map +1 -1
  79. package/esm/cramFile/container/compressionScheme.js +1 -1
  80. package/esm/cramFile/container/compressionScheme.js.map +1 -1
  81. package/esm/cramFile/container/index.js.map +1 -1
  82. package/esm/cramFile/encoding.d.ts +20 -20
  83. package/esm/cramFile/file.d.ts +14 -7
  84. package/esm/cramFile/file.js.map +1 -1
  85. package/esm/cramFile/filehandle.d.ts +1 -2
  86. package/esm/cramFile/index.d.ts +1 -2
  87. package/esm/cramFile/index.js +1 -2
  88. package/esm/cramFile/index.js.map +1 -1
  89. package/esm/cramFile/record.d.ts +6 -6
  90. package/esm/cramFile/record.js +7 -4
  91. package/esm/cramFile/record.js.map +1 -1
  92. package/esm/cramFile/sectionParsers.d.ts +9 -8
  93. package/esm/cramFile/sectionParsers.js +10 -11
  94. package/esm/cramFile/sectionParsers.js.map +1 -1
  95. package/esm/cramFile/slice/decodeRecord.js +7 -11
  96. package/esm/cramFile/slice/decodeRecord.js.map +1 -1
  97. package/esm/cramFile/slice/index.js +24 -22
  98. package/esm/cramFile/slice/index.js.map +1 -1
  99. package/esm/cramFile/util.d.ts +1 -0
  100. package/esm/cramFile/util.js +1 -1
  101. package/esm/cramFile/util.js.map +1 -1
  102. package/esm/index.d.ts +3 -4
  103. package/esm/index.js +3 -4
  104. package/esm/index.js.map +1 -1
  105. package/esm/indexedCramFile.d.ts +6 -6
  106. package/esm/indexedCramFile.js +13 -18
  107. package/esm/indexedCramFile.js.map +1 -1
  108. package/esm/io/index.d.ts +2 -1
  109. package/esm/io/index.js +2 -1
  110. package/esm/io/index.js.map +1 -1
  111. package/esm/rans/d04.js.map +1 -1
  112. package/esm/rans/d14.js.map +1 -1
  113. package/esm/rans/decoding.js.map +1 -1
  114. package/esm/rans/frequencies.js.map +1 -1
  115. package/esm/rans/index.js.map +1 -1
  116. package/esm/sam.d.ts +5 -6
  117. package/esm/sam.js +20 -7
  118. package/esm/sam.js.map +1 -1
  119. package/esm/typescript.js.map +1 -1
  120. package/esm/unzip.d.ts +2 -2
  121. package/esm/unzip.js +1 -2
  122. package/esm/unzip.js.map +1 -1
  123. package/package.json +11 -11
  124. package/src/craiIndex.ts +8 -13
  125. package/src/cramFile/codecs/_base.ts +3 -3
  126. package/src/cramFile/codecs/external.ts +1 -0
  127. package/src/cramFile/codecs/huffman.ts +7 -8
  128. package/src/cramFile/container/compressionScheme.ts +1 -1
  129. package/src/cramFile/encoding.ts +10 -10
  130. package/src/cramFile/file.ts +5 -5
  131. package/src/cramFile/filehandle.ts +1 -3
  132. package/src/cramFile/index.ts +1 -2
  133. package/src/cramFile/record.ts +13 -10
  134. package/src/cramFile/sectionParsers.ts +8 -9
  135. package/src/cramFile/slice/decodeRecord.ts +15 -17
  136. package/src/cramFile/slice/index.ts +26 -23
  137. package/src/cramFile/util.ts +1 -1
  138. package/src/index.ts +3 -5
  139. package/src/indexedCramFile.ts +19 -23
  140. package/src/io/index.ts +3 -1
  141. package/src/sam.ts +28 -14
  142. package/src/typings/binary-parser.d.ts +1 -1
  143. package/src/unzip.ts +1 -2
@@ -199,7 +199,7 @@ export default class CramSlice {
199
199
  containerHeader._endPosition + this.containerPosition,
200
200
  )
201
201
  if (header === undefined) {
202
- throw new Error()
202
+ throw new Error('block header undefined')
203
203
  }
204
204
  if (header.contentType === 'MAPPED_SLICE_HEADER') {
205
205
  const content = parseItem(
@@ -233,7 +233,7 @@ export default class CramSlice {
233
233
  for (let i = 0; i < blocks.length; i += 1) {
234
234
  const block = await this.file.readBlock(blockPosition)
235
235
  if (block === undefined) {
236
- throw new Error()
236
+ throw new Error('block undefined')
237
237
  }
238
238
  blocks[i] = block
239
239
  blockPosition = blocks[i]._endPosition
@@ -270,7 +270,7 @@ export default class CramSlice {
270
270
  // read the slice header
271
271
  const sliceHeader = (await this.getHeader()).parsedContent
272
272
  if (!isMappedSliceHeader(sliceHeader)) {
273
- throw new Error()
273
+ throw new Error('slice header not mapped')
274
274
  }
275
275
 
276
276
  if (sliceHeader.refSeqId < 0) {
@@ -279,11 +279,9 @@ export default class CramSlice {
279
279
 
280
280
  const compressionScheme = await this.container.getCompressionScheme()
281
281
  if (compressionScheme === undefined) {
282
- throw new Error()
282
+ throw new Error('compression scheme undefined')
283
283
  }
284
284
 
285
- // console.log(JSON.stringify(sliceHeader, null, ' '))
286
-
287
285
  if (sliceHeader.refBaseBlockId >= 0) {
288
286
  const refBlock = await this.getBlockByContentId(
289
287
  sliceHeader.refBaseBlockId,
@@ -349,12 +347,12 @@ export default class CramSlice {
349
347
 
350
348
  const compressionScheme = await this.container.getCompressionScheme()
351
349
  if (compressionScheme === undefined) {
352
- throw new Error()
350
+ throw new Error('compression scheme undefined')
353
351
  }
354
352
 
355
353
  const sliceHeader = await this.getHeader()
356
354
  if (sliceHeader === undefined) {
357
- throw new Error()
355
+ throw new Error('slice header undefined')
358
356
  }
359
357
 
360
358
  const blocksByContentId = await this._getBlocksContentIdIndex()
@@ -503,22 +501,23 @@ export default class CramSlice {
503
501
  : undefined
504
502
  const compressionScheme = await this.container.getCompressionScheme()
505
503
  if (compressionScheme === undefined) {
506
- throw new Error()
504
+ throw new Error('compression scheme undefined')
507
505
  }
508
506
  const refRegions: Record<
509
507
  string,
510
508
  { id: number; start: number; end: number; seq: string | null }
511
- > = {} // seqId => { start, end, seq }
509
+ > = {}
512
510
 
513
- // iterate over the records to find the spans of the reference sequences we need to fetch
514
- for (let i = 0; i < records.length; i += 1) {
511
+ // iterate over the records to find the spans of the reference
512
+ // sequences we need to fetch
513
+ for (const record of records) {
515
514
  const seqId =
516
- singleRefId !== undefined ? singleRefId : records[i].sequenceId
515
+ singleRefId !== undefined ? singleRefId : record.sequenceId
517
516
  let refRegion = refRegions[seqId]
518
517
  if (!refRegion) {
519
518
  refRegion = {
520
519
  id: seqId,
521
- start: records[i].alignmentStart,
520
+ start: record.alignmentStart,
522
521
  end: -Infinity,
523
522
  seq: null,
524
523
  }
@@ -526,21 +525,25 @@ export default class CramSlice {
526
525
  }
527
526
 
528
527
  const end =
529
- records[i].alignmentStart +
530
- (records[i].lengthOnRef || records[i].readLength) -
528
+ record.alignmentStart +
529
+ (record.lengthOnRef || record.readLength) -
531
530
  1
532
531
  if (end > refRegion.end) {
533
532
  refRegion.end = end
534
533
  }
535
- if (records[i].alignmentStart < refRegion.start) {
536
- refRegion.start = records[i].alignmentStart
534
+ if (record.alignmentStart < refRegion.start) {
535
+ refRegion.start = record.alignmentStart
537
536
  }
538
537
  }
539
538
 
540
539
  // fetch the `seq` for all of the ref regions
541
540
  await Promise.all(
542
541
  Object.values(refRegions).map(async refRegion => {
543
- if (refRegion.id !== -1 && refRegion.start <= refRegion.end) {
542
+ if (
543
+ refRegion.id !== -1 &&
544
+ refRegion.start <= refRegion.end &&
545
+ this.file.fetchReferenceSequenceCallback
546
+ ) {
544
547
  refRegion.seq = await this.file.fetchReferenceSequenceCallback(
545
548
  refRegion.id,
546
549
  refRegion.start,
@@ -551,13 +554,13 @@ export default class CramSlice {
551
554
  )
552
555
 
553
556
  // now decorate all the records with them
554
- for (let i = 0; i < records.length; i += 1) {
557
+ for (const record of records) {
555
558
  const seqId =
556
- singleRefId !== undefined ? singleRefId : records[i].sequenceId
559
+ singleRefId !== undefined ? singleRefId : record.sequenceId
557
560
  const refRegion = refRegions[seqId]
558
- if (refRegion && refRegion.seq) {
561
+ if (refRegion?.seq) {
559
562
  const seq = refRegion.seq
560
- records[i].addReferenceSequence(
563
+ record.addReferenceSequence(
561
564
  { ...refRegion, seq },
562
565
  compressionScheme,
563
566
  )
@@ -176,5 +176,5 @@ export function tinyMemoize(_class: any, methodName: any) {
176
176
  }
177
177
 
178
178
  export function sequenceMD5(seq: string) {
179
- return md5(seq.toUpperCase().replace(/[^\x21-\x7e]/g, ''))
179
+ return md5(seq.toUpperCase().replaceAll(/[^\u0021-\u007e]/g, ''))
180
180
  }
package/src/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- import CramFile, { CramRecord } from './cramFile'
2
- import IndexedCramFile from './indexedCramFile'
3
- import CraiIndex from './craiIndex'
4
-
5
- export { CramFile, IndexedCramFile, CraiIndex, CramRecord }
1
+ export { default as CramFile, CramRecord } from './cramFile'
2
+ export { default as CraiIndex } from './craiIndex'
3
+ export { default as IndexedCramFile } from './indexedCramFile'
@@ -6,13 +6,13 @@ import { SeqFetch } from './cramFile/file'
6
6
  import { Filehandle } from './cramFile/filehandle'
7
7
  import { Slice } from './craiIndex'
8
8
 
9
- export type CramFileSource = {
9
+ export interface CramFileSource {
10
10
  cramFilehandle?: Filehandle
11
11
  cramUrl?: string
12
12
  cramPath?: string
13
13
  }
14
14
 
15
- export type CramIndexLike = {
15
+ export interface CramIndexLike {
16
16
  getEntriesForRange: (
17
17
  seqId: number,
18
18
  start: number,
@@ -44,17 +44,16 @@ export default class IndexedCramFile {
44
44
  | { cram: CramFile }
45
45
  | ({
46
46
  cram?: undefined
47
- seqFetch: SeqFetch
48
- checkSequenceMD5: boolean
47
+ seqFetch?: SeqFetch
48
+ checkSequenceMD5?: boolean
49
49
  cacheSize?: number
50
50
  } & CramFileSource)
51
51
  ),
52
52
  ) {
53
53
  // { cram, index, seqFetch /* fasta, fastaIndex */ }) {
54
- if (args.cram) {
55
- this.cram = args.cram
56
- } else {
57
- this.cram = new CramFile({
54
+ this.cram =
55
+ args.cram ??
56
+ new CramFile({
58
57
  url: args.cramUrl,
59
58
  path: args.cramPath,
60
59
  filehandle: args.cramFilehandle,
@@ -62,7 +61,6 @@ export default class IndexedCramFile {
62
61
  checkSequenceMD5: args.checkSequenceMD5,
63
62
  cacheSize: args.cacheSize,
64
63
  })
65
- }
66
64
 
67
65
  if (!(this.cram instanceof CramFile)) {
68
66
  throw new Error('invalid arguments: no cramfile')
@@ -128,12 +126,12 @@ export default class IndexedCramFile {
128
126
  if (opts.viewAsPairs) {
129
127
  const readNames: Record<string, number> = {}
130
128
  const readIds: Record<string, number> = {}
131
- for (let i = 0; i < ret.length; i += 1) {
132
- const name = ret[i].readName
129
+ for (const read of ret) {
130
+ const name = read.readName
133
131
  if (name === undefined) {
134
- throw new Error()
132
+ throw new Error('readName undefined')
135
133
  }
136
- const id = ret[i].uniqueId
134
+ const id = read.uniqueId
137
135
  if (!readNames[name]) {
138
136
  readNames[name] = 0
139
137
  }
@@ -147,11 +145,10 @@ export default class IndexedCramFile {
147
145
  }
148
146
  })
149
147
  const matePromises = []
150
- for (let i = 0; i < ret.length; i += 1) {
151
- const cramRecord = ret[i]
148
+ for (const cramRecord of ret) {
152
149
  const name = cramRecord.readName
153
150
  if (name === undefined) {
154
- throw new Error()
151
+ throw new Error('readName undefined')
155
152
  }
156
153
  if (
157
154
  unmatedPairs[name] &&
@@ -169,9 +166,9 @@ export default class IndexedCramFile {
169
166
  }
170
167
  }
171
168
  const mateBlocks = await Promise.all(matePromises)
172
- let mateChunks = []
173
- for (let i = 0; i < mateBlocks.length; i += 1) {
174
- mateChunks.push(...mateBlocks[i])
169
+ let mateChunks = [] as Slice[]
170
+ for (const block of mateBlocks) {
171
+ mateChunks.push(...block)
175
172
  }
176
173
  // filter out duplicates
177
174
  mateChunks = mateChunks
@@ -182,7 +179,7 @@ export default class IndexedCramFile {
182
179
  )
183
180
 
184
181
  const mateRecordPromises = []
185
- const mateFeatPromises: Array<Promise<CramRecord[]>> = []
182
+ const mateFeatPromises: Promise<CramRecord[]>[] = []
186
183
 
187
184
  const mateTotalSize = mateChunks
188
185
  .map(s => s.sliceBytes)
@@ -202,10 +199,9 @@ export default class IndexedCramFile {
202
199
  mateRecordPromises.push(recordPromise)
203
200
  const featPromise = recordPromise.then(feats => {
204
201
  const mateRecs = []
205
- for (let i = 0; i < feats.length; i += 1) {
206
- const feature = feats[i]
202
+ for (const feature of feats) {
207
203
  if (feature.readName === undefined) {
208
- throw new Error()
204
+ throw new Error('readName undefined')
209
205
  }
210
206
  if (unmatedPairs[feature.readName] && !readIds[feature.uniqueId]) {
211
207
  mateRecs.push(feature)
package/src/io/index.ts CHANGED
@@ -28,4 +28,6 @@ function open(
28
28
  throw new Error('no url, path, or filehandle provided, cannot open')
29
29
  }
30
30
 
31
- export { LocalFile, RemoteFile, fromUrl, open }
31
+ export { fromUrl, open }
32
+
33
+ export { LocalFile, RemoteFile } from 'generic-filehandle'
package/src/sam.ts CHANGED
@@ -1,20 +1,34 @@
1
- export type HeaderDataItem = {
2
- tag: string
3
- data: Array<{ tag: string; value: string }>
4
- }
5
-
6
- export function parseHeaderText(text: string): HeaderDataItem[] {
1
+ export function parseHeaderText(text: string) {
7
2
  const lines = text.split(/\r?\n/)
8
- const data: HeaderDataItem[] = []
9
- lines.forEach(line => {
3
+ const data: {
4
+ tag: string
5
+ data: {
6
+ tag: string
7
+ value: string | undefined
8
+ }[]
9
+ }[] = []
10
+ for (const line of lines) {
10
11
  const [tag, ...fields] = line.split(/\t/)
11
- const parsedFields = fields.map(f => {
12
- const [fieldTag, value] = f.split(':', 2)
13
- return { tag: fieldTag, value }
14
- })
15
12
  if (tag) {
16
- data.push({ tag: tag.substr(1), data: parsedFields })
13
+ data.push({
14
+ tag: tag.slice(1),
15
+ data: fields.map(f => {
16
+ const r = f.indexOf(':')
17
+ return r !== -1
18
+ ? {
19
+ tag: f.slice(0, r),
20
+ value: f.slice(r + 1),
21
+ }
22
+ : // @CO lines are not comma separated.
23
+ // See "samtools view -H c2\#pad.3.0.cram"
24
+ // so, just store value tag itself
25
+ {
26
+ tag: f,
27
+ value: undefined,
28
+ }
29
+ }),
30
+ })
17
31
  }
18
- })
32
+ }
19
33
  return data
20
34
  }
@@ -1,5 +1,5 @@
1
1
  declare module '@gmod/binary-parser' {
2
- export type Options = {
2
+ export interface Options {
3
3
  stripNull?: boolean
4
4
  formatter?: (item: any) => any
5
5
  length?: number | string | ((this: { $parent: unknown }) => void)
package/src/unzip.ts CHANGED
@@ -1,2 +1 @@
1
- import { gunzipSync } from 'zlib'
2
- export { gunzipSync as unzip }
1
+ export { gunzipSync as unzip } from 'zlib'