@gmod/bed
Version:
A BED file format parser with autoSql support
100 lines • 4.21 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const autoSql_ts_1 = __importDefault(require("./autoSql.js"));
const defaultTypes_ts_1 = __importDefault(require("./defaultTypes.js"));
const util_ts_1 = require("./util.js");
const strandMap = { '.': 0, '-': -1, '+': 1 };
// heuristic that a BED file is BED12 like...the number in col 10 is
// blockCount-like
function isBed12Like(fields) {
return (fields.length >= 12 &&
!Number.isNaN(Number.parseInt(fields[9], 10)) &&
fields[10]?.split(',').filter(f => !!f).length ===
Number.parseInt(fields[9], 10));
}
class BED {
constructor(arguments_ = {}) {
if (arguments_.autoSql) {
this.autoSql = (0, util_ts_1.detectTypes)(
// @ts-expect-error
autoSql_ts_1.default.parse(arguments_.autoSql));
}
else if (arguments_.type) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!defaultTypes_ts_1.default[arguments_.type]) {
throw new Error('Type not found');
}
this.autoSql = (0, util_ts_1.detectTypes)(defaultTypes_ts_1.default[arguments_.type]);
}
else {
this.autoSql = (0, util_ts_1.detectTypes)(defaultTypes_ts_1.default.defaultBedSchema);
this.attemptDefaultBed = true;
}
}
/*
* parses a line of text as a BED line with the loaded autoSql schema
*
* @param line - a BED line as tab delimited text or array
* @param opts - supply opts.uniqueId
* @return a object representing a feature
*/
parseLine(line, options = {}) {
const { autoSql } = this;
const { uniqueId } = options;
const fields = Array.isArray(line) ? line : line.split('\t');
let feature = {};
if (!this.attemptDefaultBed ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
(this.attemptDefaultBed && isBed12Like(fields))) {
for (let index = 0; index < autoSql.fields.length; index++) {
const autoField = autoSql.fields[index];
let columnValue = fields[index];
const { isNumeric, isArray, arrayIsNumeric, name } = autoField;
if (columnValue === null || columnValue === undefined) {
break;
}
if (columnValue !== '.') {
if (isNumeric) {
const number_ = Number(columnValue);
columnValue = Number.isNaN(number_) ? columnValue : number_;
}
else if (isArray) {
columnValue = columnValue.split(',');
if (columnValue.at(-1) === '') {
columnValue.pop();
}
if (arrayIsNumeric) {
columnValue = columnValue.map(Number);
}
}
feature[name] = columnValue;
}
}
}
else {
const fieldNames = ['chrom', 'chromStart', 'chromEnd', 'name'];
feature = Object.fromEntries(fields.map((f, index) => [fieldNames[index] || 'field' + index, f]));
feature.chromStart = +feature.chromStart;
feature.chromEnd = +feature.chromEnd;
if (!Number.isNaN(Number.parseFloat(feature.field4))) {
feature.score = +feature.field4;
delete feature.field4;
}
if (feature.field5 === '+' || feature.field5 === '-') {
feature.strand = feature.field5;
delete feature.field5;
}
}
if (uniqueId) {
feature.uniqueId = uniqueId;
}
feature.strand = strandMap[feature.strand] || 0;
feature.chrom = decodeURIComponent(feature.chrom);
return feature;
}
}
exports.default = BED;
//# sourceMappingURL=parser.js.map