@jbrowse/cli 3.5.1 → 3.6.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.
- package/README.md +291 -607
- package/bin/run +1 -6
- package/bundle/index.js +4459 -0
- package/dist/base.js +5 -0
- package/dist/bin.js +3 -0
- package/dist/commands/add-assembly.js +143 -0
- package/dist/commands/add-connection.js +177 -0
- package/dist/commands/add-track-json.js +81 -0
- package/dist/commands/add-track-utils/adapter-utils.js +304 -0
- package/dist/commands/add-track-utils/file-operations.js +36 -0
- package/dist/commands/add-track-utils/track-config.js +63 -0
- package/dist/commands/add-track-utils/validators.js +74 -0
- package/dist/commands/add-track.js +193 -0
- package/dist/commands/admin-server-utils.js +238 -0
- package/dist/commands/admin-server.js +51 -0
- package/dist/commands/assembly-utils.js +410 -0
- package/dist/commands/create.js +121 -0
- package/dist/commands/make-pif-utils/cigar-utils.js +29 -0
- package/dist/commands/make-pif-utils/file-utils.js +38 -0
- package/dist/commands/make-pif-utils/pif-generator.js +64 -0
- package/dist/commands/make-pif-utils/validators.js +22 -0
- package/dist/commands/make-pif.js +58 -0
- package/dist/commands/remove-track.js +58 -0
- package/dist/commands/set-default-session.js +104 -0
- package/dist/commands/sort-bed-utils/constants.js +12 -0
- package/dist/commands/sort-bed-utils/process-utils.js +23 -0
- package/dist/commands/sort-bed-utils/sort-utils.js +24 -0
- package/dist/commands/sort-bed-utils/validators.js +22 -0
- package/dist/commands/sort-bed.js +49 -0
- package/dist/commands/sort-gff-utils/constants.js +13 -0
- package/dist/commands/sort-gff-utils/process-utils.js +23 -0
- package/dist/commands/sort-gff-utils/sort-utils.js +55 -0
- package/dist/commands/sort-gff-utils/validators.js +21 -0
- package/dist/commands/sort-gff.js +49 -0
- package/dist/commands/text-index-utils/adapter-utils.js +63 -0
- package/dist/commands/text-index-utils/aggregate.js +87 -0
- package/dist/commands/text-index-utils/config-utils.js +59 -0
- package/dist/commands/text-index-utils/file-list.js +31 -0
- package/dist/commands/text-index-utils/index.js +9 -0
- package/dist/commands/text-index-utils/indexing-utils.js +84 -0
- package/dist/commands/text-index-utils/per-track.js +65 -0
- package/dist/commands/text-index-utils/validators.js +20 -0
- package/dist/commands/text-index.js +113 -0
- package/dist/commands/track-utils.js +85 -0
- package/dist/commands/upgrade.js +122 -0
- package/dist/index.js +119 -0
- package/dist/utils.js +154 -0
- package/package.json +13 -38
- package/bin/dev +0 -17
- package/bin/dev.cmd +0 -3
- package/bin/run.cmd +0 -3
- package/lib/base.js +0 -157
- package/lib/commands/add-assembly.js +0 -491
- package/lib/commands/add-connection.js +0 -170
- package/lib/commands/add-track-json.js +0 -67
- package/lib/commands/add-track.js +0 -564
- package/lib/commands/admin-server.js +0 -153
- package/lib/commands/create.js +0 -111
- package/lib/commands/make-pif.js +0 -116
- package/lib/commands/remove-track.js +0 -37
- package/lib/commands/set-default-session.js +0 -98
- package/lib/commands/sort-bed.js +0 -45
- package/lib/commands/sort-gff.js +0 -45
- package/lib/commands/text-index.js +0 -380
- package/lib/commands/upgrade.js +0 -109
- package/lib/index.js +0 -6
- package/oclif.manifest.json +0 -1169
- /package/{lib → dist}/fetchWithProxy.js +0 -0
- /package/{lib → dist}/types/common.js +0 -0
- /package/{lib → dist}/types/gff3Adapter.js +0 -0
- /package/{lib → dist}/types/vcfAdapter.js +0 -0
- /package/{lib → dist}/util.js +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
exports.getMinimalEnvironment = getMinimalEnvironment;
|
|
7
|
+
exports.createSortCommandForStdin = createSortCommandForStdin;
|
|
8
|
+
exports.createSortCommandForFile = createSortCommandForFile;
|
|
9
|
+
exports.spawnSortProcessFromFile = spawnSortProcessFromFile;
|
|
10
|
+
exports.spawnSortProcessFromStdin = spawnSortProcessFromStdin;
|
|
11
|
+
exports.spawnSortProcess = spawnSortProcess;
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const tmp_1 = __importDefault(require("tmp"));
|
|
14
|
+
function getMinimalEnvironment() {
|
|
15
|
+
return {
|
|
16
|
+
...process.env,
|
|
17
|
+
LC_ALL: 'C',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function createSortCommandForStdin() {
|
|
21
|
+
// Create a temporary file to store stdin content, then process it
|
|
22
|
+
// This allows us to read the data twice - once for headers, once for sorting
|
|
23
|
+
const tmpFile = tmp_1.default.fileSync({
|
|
24
|
+
prefix: 'jbrowse-sort-gff',
|
|
25
|
+
}).name;
|
|
26
|
+
const sortCmd = `sort -t"\`printf '\\t'\`" -k1,1 -k4,4n`;
|
|
27
|
+
// Save stdin to temp file, extract headers, sort non-headers, then cleanup
|
|
28
|
+
return `cat > ${tmpFile} && (grep "^#" ${tmpFile}; grep -v "^#" ${tmpFile} | ${sortCmd}) && rm -f ${tmpFile}`;
|
|
29
|
+
}
|
|
30
|
+
function createSortCommandForFile(file) {
|
|
31
|
+
// When reading from a file, we can read it multiple times directly
|
|
32
|
+
// Need to wrap in parentheses to ensure both grep outputs are combined
|
|
33
|
+
return `(grep "^#" "${file}"; grep -v "^#" "${file}" | sort -t"\`printf '\\t'\`" -k1,1 -k4,4n)`;
|
|
34
|
+
}
|
|
35
|
+
function spawnSortProcessFromFile(file) {
|
|
36
|
+
const command = createSortCommandForFile(file);
|
|
37
|
+
const env = getMinimalEnvironment();
|
|
38
|
+
return (0, child_process_1.spawn)('sh', ['-c', command], {
|
|
39
|
+
env,
|
|
40
|
+
stdio: 'inherit',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function spawnSortProcessFromStdin() {
|
|
44
|
+
const command = createSortCommandForStdin();
|
|
45
|
+
const env = getMinimalEnvironment();
|
|
46
|
+
return (0, child_process_1.spawn)('sh', ['-c', command], {
|
|
47
|
+
env,
|
|
48
|
+
stdio: 'inherit',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function spawnSortProcess(options) {
|
|
52
|
+
return options.file
|
|
53
|
+
? spawnSortProcessFromFile(options.file)
|
|
54
|
+
: spawnSortProcessFromStdin();
|
|
55
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateFileArgument = validateFileArgument;
|
|
4
|
+
exports.validateRequiredCommands = validateRequiredCommands;
|
|
5
|
+
const command_exists_1 = require("command-exists");
|
|
6
|
+
function validateFileArgument(file) {
|
|
7
|
+
// Allow no file argument for stdin input
|
|
8
|
+
if (!file && process.stdin.isTTY) {
|
|
9
|
+
console.error('Error: Missing required argument: file');
|
|
10
|
+
console.error('Usage: jbrowse sort-gff <file>');
|
|
11
|
+
console.error(' OR pipe data via stdin: cat file.gff | jbrowse sort-gff');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function validateRequiredCommands() {
|
|
16
|
+
const requiredCommands = ['sh', 'sort', 'grep'];
|
|
17
|
+
const missingCommands = requiredCommands.filter(cmd => !(0, command_exists_1.sync)(cmd));
|
|
18
|
+
if (missingCommands.length > 0) {
|
|
19
|
+
throw new Error('Error: Unable to sort, requires unix type environment with sort, grep');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.run = run;
|
|
4
|
+
const util_1 = require("util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const constants_1 = require("./sort-gff-utils/constants");
|
|
7
|
+
const process_utils_1 = require("./sort-gff-utils/process-utils");
|
|
8
|
+
const sort_utils_1 = require("./sort-gff-utils/sort-utils");
|
|
9
|
+
const validators_1 = require("./sort-gff-utils/validators");
|
|
10
|
+
async function run(args) {
|
|
11
|
+
const options = {
|
|
12
|
+
help: {
|
|
13
|
+
type: 'boolean',
|
|
14
|
+
short: 'h',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
const { values: flags, positionals } = (0, util_1.parseArgs)({
|
|
18
|
+
args,
|
|
19
|
+
options,
|
|
20
|
+
allowPositionals: true,
|
|
21
|
+
});
|
|
22
|
+
const description = constants_1.SORT_GFF_DESCRIPTION;
|
|
23
|
+
const examples = constants_1.SORT_GFF_EXAMPLES;
|
|
24
|
+
if (flags.help) {
|
|
25
|
+
(0, utils_1.printHelp)({
|
|
26
|
+
description,
|
|
27
|
+
examples,
|
|
28
|
+
usage: 'jbrowse sort-gff [file] [options]',
|
|
29
|
+
options,
|
|
30
|
+
});
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const file = positionals[0];
|
|
34
|
+
if (file) {
|
|
35
|
+
(0, validators_1.validateFileArgument)(file);
|
|
36
|
+
}
|
|
37
|
+
(0, validators_1.validateRequiredCommands)();
|
|
38
|
+
try {
|
|
39
|
+
const child = (0, sort_utils_1.spawnSortProcess)({ file: file || '-' });
|
|
40
|
+
const exitCode = await (0, process_utils_1.waitForProcessClose)(child);
|
|
41
|
+
if (exitCode !== 0) {
|
|
42
|
+
console.error(`Sort process exited with code ${exitCode}`);
|
|
43
|
+
process.exit(exitCode || 1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
(0, process_utils_1.handleProcessError)(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLoc = getLoc;
|
|
4
|
+
exports.createTrixAdapter = createTrixAdapter;
|
|
5
|
+
exports.createPerTrackTrixAdapter = createPerTrackTrixAdapter;
|
|
6
|
+
exports.getAdapterLocation = getAdapterLocation;
|
|
7
|
+
function getLoc(elt) {
|
|
8
|
+
return elt.locationType === 'LocalPathLocation' ? elt.localPath : elt.uri;
|
|
9
|
+
}
|
|
10
|
+
function createTrixAdapter(id, asm, assemblyNames) {
|
|
11
|
+
return {
|
|
12
|
+
type: 'TrixTextSearchAdapter',
|
|
13
|
+
textSearchAdapterId: id,
|
|
14
|
+
ixFilePath: {
|
|
15
|
+
uri: `trix/${asm}.ix`,
|
|
16
|
+
locationType: 'UriLocation',
|
|
17
|
+
},
|
|
18
|
+
ixxFilePath: {
|
|
19
|
+
uri: `trix/${asm}.ixx`,
|
|
20
|
+
locationType: 'UriLocation',
|
|
21
|
+
},
|
|
22
|
+
metaFilePath: {
|
|
23
|
+
uri: `trix/${asm}_meta.json`,
|
|
24
|
+
locationType: 'UriLocation',
|
|
25
|
+
},
|
|
26
|
+
assemblyNames: assemblyNames || [asm],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function createPerTrackTrixAdapter(trackId, assemblyNames) {
|
|
30
|
+
return {
|
|
31
|
+
type: 'TrixTextSearchAdapter',
|
|
32
|
+
textSearchAdapterId: `${trackId}-index`,
|
|
33
|
+
ixFilePath: {
|
|
34
|
+
uri: `trix/${trackId}.ix`,
|
|
35
|
+
locationType: 'UriLocation',
|
|
36
|
+
},
|
|
37
|
+
ixxFilePath: {
|
|
38
|
+
uri: `trix/${trackId}.ixx`,
|
|
39
|
+
locationType: 'UriLocation',
|
|
40
|
+
},
|
|
41
|
+
metaFilePath: {
|
|
42
|
+
uri: `trix/${trackId}_meta.json`,
|
|
43
|
+
locationType: 'UriLocation',
|
|
44
|
+
},
|
|
45
|
+
assemblyNames: assemblyNames,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function getAdapterLocation(adapter) {
|
|
49
|
+
const { type } = adapter || {};
|
|
50
|
+
if (type === 'Gff3TabixAdapter') {
|
|
51
|
+
return adapter.gffGzLocation || adapter;
|
|
52
|
+
}
|
|
53
|
+
else if (type === 'Gff3Adapter') {
|
|
54
|
+
return adapter.gffLocation || adapter;
|
|
55
|
+
}
|
|
56
|
+
else if (type === 'VcfAdapter') {
|
|
57
|
+
return adapter.vcfLocation || adapter;
|
|
58
|
+
}
|
|
59
|
+
else if (type === 'VcfTabixAdapter') {
|
|
60
|
+
return adapter.vcfGzLocation || adapter;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
exports.aggregateIndex = aggregateIndex;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const config_utils_1 = require("./config-utils");
|
|
10
|
+
const indexing_utils_1 = require("./indexing-utils");
|
|
11
|
+
async function aggregateIndex(flags) {
|
|
12
|
+
const { out, target, tracks, assemblies, attributes, quiet, force, exclude, dryrun, prefixSize, } = flags;
|
|
13
|
+
const outFlag = target || out || '.';
|
|
14
|
+
const isDir = fs_1.default.lstatSync(outFlag).isDirectory();
|
|
15
|
+
const confPath = isDir ? path_1.default.join(outFlag, 'config.json') : outFlag;
|
|
16
|
+
const outLocation = path_1.default.dirname(confPath);
|
|
17
|
+
const config = (0, config_utils_1.readConf)(confPath);
|
|
18
|
+
const trixDir = path_1.default.join(outLocation, 'trix');
|
|
19
|
+
if (!fs_1.default.existsSync(trixDir)) {
|
|
20
|
+
fs_1.default.mkdirSync(trixDir);
|
|
21
|
+
}
|
|
22
|
+
const aggregateTextSearchAdapters = config.aggregateTextSearchAdapters || [];
|
|
23
|
+
const asms = assemblies?.split(',') ||
|
|
24
|
+
config.assemblies?.map(a => a.name) ||
|
|
25
|
+
(config.assembly ? [config.assembly.name] : []);
|
|
26
|
+
if (!asms.length) {
|
|
27
|
+
throw new Error('No assemblies found');
|
|
28
|
+
}
|
|
29
|
+
for (const asm of asms) {
|
|
30
|
+
const trackConfigs = (0, config_utils_1.getTrackConfigs)(confPath, tracks?.split(','), asm);
|
|
31
|
+
if (!trackConfigs.length) {
|
|
32
|
+
console.log(`Indexing assembly ${asm}...(no tracks found)...`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
console.log(`Indexing assembly ${asm}...`);
|
|
36
|
+
if (dryrun) {
|
|
37
|
+
console.log(trackConfigs.map(e => `${e.trackId} ${e.adapter?.type}`).join('\n'));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const id = `${asm}-index`;
|
|
41
|
+
const idx = aggregateTextSearchAdapters.findIndex(x => x.textSearchAdapterId === id);
|
|
42
|
+
if (idx !== -1 && !force) {
|
|
43
|
+
console.log(`Note: ${asm} has already been indexed with this configuration, use --force to overwrite this assembly. Skipping for now`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
await (0, indexing_utils_1.indexDriver)({
|
|
47
|
+
trackConfigs,
|
|
48
|
+
outLocation,
|
|
49
|
+
quiet,
|
|
50
|
+
name: asm,
|
|
51
|
+
attributes: attributes.split(','),
|
|
52
|
+
typesToExclude: exclude.split(','),
|
|
53
|
+
assemblyNames: [asm],
|
|
54
|
+
prefixSize,
|
|
55
|
+
});
|
|
56
|
+
const trixConf = {
|
|
57
|
+
type: 'TrixTextSearchAdapter',
|
|
58
|
+
textSearchAdapterId: id,
|
|
59
|
+
ixFilePath: {
|
|
60
|
+
uri: `trix/${asm}.ix`,
|
|
61
|
+
locationType: 'UriLocation',
|
|
62
|
+
},
|
|
63
|
+
ixxFilePath: {
|
|
64
|
+
uri: `trix/${asm}.ixx`,
|
|
65
|
+
locationType: 'UriLocation',
|
|
66
|
+
},
|
|
67
|
+
metaFilePath: {
|
|
68
|
+
uri: `trix/${asm}_meta.json`,
|
|
69
|
+
locationType: 'UriLocation',
|
|
70
|
+
},
|
|
71
|
+
assemblyNames: [asm],
|
|
72
|
+
};
|
|
73
|
+
if (idx === -1) {
|
|
74
|
+
aggregateTextSearchAdapters.push(trixConf);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
aggregateTextSearchAdapters[idx] = trixConf;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!dryrun) {
|
|
82
|
+
(0, config_utils_1.writeConf)({
|
|
83
|
+
...config,
|
|
84
|
+
aggregateTextSearchAdapters,
|
|
85
|
+
}, confPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
exports.readConf = readConf;
|
|
7
|
+
exports.writeConf = writeConf;
|
|
8
|
+
exports.getConfigPath = getConfigPath;
|
|
9
|
+
exports.ensureTrixDir = ensureTrixDir;
|
|
10
|
+
exports.getAssemblyNames = getAssemblyNames;
|
|
11
|
+
exports.getTrackConfigs = getTrackConfigs;
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const common_1 = require("../../types/common");
|
|
15
|
+
function readConf(configPath) {
|
|
16
|
+
return JSON.parse(fs_1.default.readFileSync(configPath, 'utf8'));
|
|
17
|
+
}
|
|
18
|
+
function writeConf(obj, configPath) {
|
|
19
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(obj, null, 2));
|
|
20
|
+
}
|
|
21
|
+
function getConfigPath(outFlag) {
|
|
22
|
+
const isDir = fs_1.default.lstatSync(outFlag).isDirectory();
|
|
23
|
+
const configPath = isDir ? path_1.default.join(outFlag, 'config.json') : outFlag;
|
|
24
|
+
const outLocation = path_1.default.dirname(configPath);
|
|
25
|
+
return { configPath, outLocation };
|
|
26
|
+
}
|
|
27
|
+
function ensureTrixDir(outLocation) {
|
|
28
|
+
const trixDir = path_1.default.join(outLocation, 'trix');
|
|
29
|
+
if (!fs_1.default.existsSync(trixDir)) {
|
|
30
|
+
fs_1.default.mkdirSync(trixDir);
|
|
31
|
+
}
|
|
32
|
+
return trixDir;
|
|
33
|
+
}
|
|
34
|
+
function getAssemblyNames(config, assemblies) {
|
|
35
|
+
const asms = assemblies?.split(',') ||
|
|
36
|
+
config.assemblies?.map(a => a.name) ||
|
|
37
|
+
(config.assembly ? [config.assembly.name] : []);
|
|
38
|
+
if (!asms.length) {
|
|
39
|
+
throw new Error('No assemblies found');
|
|
40
|
+
}
|
|
41
|
+
return asms;
|
|
42
|
+
}
|
|
43
|
+
function getTrackConfigs(configPath, trackIds, assemblyName) {
|
|
44
|
+
const { tracks } = readConf(configPath);
|
|
45
|
+
if (!tracks) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const trackIdsToIndex = trackIds || tracks.map(track => track.trackId);
|
|
49
|
+
return trackIdsToIndex
|
|
50
|
+
.map(trackId => {
|
|
51
|
+
const currentTrack = tracks.find(t => trackId === t.trackId);
|
|
52
|
+
if (!currentTrack) {
|
|
53
|
+
throw new Error(`Track not found in config.json for trackId ${trackId}, please add track configuration before indexing.`);
|
|
54
|
+
}
|
|
55
|
+
return currentTrack;
|
|
56
|
+
})
|
|
57
|
+
.filter(track => (0, common_1.supported)(track.adapter?.type))
|
|
58
|
+
.filter(track => assemblyName ? track.assemblyNames.includes(assemblyName) : true);
|
|
59
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
exports.indexFileList = indexFileList;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const indexing_utils_1 = require("./indexing-utils");
|
|
10
|
+
const validators_1 = require("./validators");
|
|
11
|
+
async function indexFileList(flags) {
|
|
12
|
+
const { out, target, fileId, file, attributes, quiet, exclude, prefixSize } = flags;
|
|
13
|
+
(0, validators_1.validateFileInput)(file);
|
|
14
|
+
const outFlag = target || out || '.';
|
|
15
|
+
const trixDir = path_1.default.join(outFlag, 'trix');
|
|
16
|
+
if (!fs_1.default.existsSync(trixDir)) {
|
|
17
|
+
fs_1.default.mkdirSync(trixDir);
|
|
18
|
+
}
|
|
19
|
+
const trackConfigs = (0, indexing_utils_1.prepareFileTrackConfigs)(file, fileId);
|
|
20
|
+
await (0, indexing_utils_1.indexDriver)({
|
|
21
|
+
trackConfigs,
|
|
22
|
+
outLocation: outFlag,
|
|
23
|
+
name: trackConfigs.length > 1 ? 'aggregate' : path_1.default.basename(file[0]),
|
|
24
|
+
quiet,
|
|
25
|
+
attributes: attributes.split(','),
|
|
26
|
+
typesToExclude: exclude.split(','),
|
|
27
|
+
assemblyNames: [],
|
|
28
|
+
prefixSize,
|
|
29
|
+
});
|
|
30
|
+
console.log('Successfully created index for these files. See https://jbrowse.org/storybook/lgv/main/?path=/story/text-searching--page for info about usage');
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.indexFileList = exports.perTrackIndex = exports.aggregateIndex = void 0;
|
|
4
|
+
var aggregate_1 = require("./aggregate");
|
|
5
|
+
Object.defineProperty(exports, "aggregateIndex", { enumerable: true, get: function () { return aggregate_1.aggregateIndex; } });
|
|
6
|
+
var per_track_1 = require("./per-track");
|
|
7
|
+
Object.defineProperty(exports, "perTrackIndex", { enumerable: true, get: function () { return per_track_1.perTrackIndex; } });
|
|
8
|
+
var file_list_1 = require("./file-list");
|
|
9
|
+
Object.defineProperty(exports, "indexFileList", { enumerable: true, get: function () { return file_list_1.indexFileList; } });
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
exports.runIxIxx = runIxIxx;
|
|
7
|
+
exports.indexFiles = indexFiles;
|
|
8
|
+
exports.indexDriver = indexDriver;
|
|
9
|
+
exports.prepareFileTrackConfigs = prepareFileTrackConfigs;
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const stream_1 = require("stream");
|
|
12
|
+
const ixixx_1 = require("ixixx");
|
|
13
|
+
const adapter_utils_1 = require("./adapter-utils");
|
|
14
|
+
const common_1 = require("../../types/common");
|
|
15
|
+
const gff3Adapter_1 = require("../../types/gff3Adapter");
|
|
16
|
+
const vcfAdapter_1 = require("../../types/vcfAdapter");
|
|
17
|
+
async function runIxIxx({ readStream, outLocation, name, prefixSize, }) {
|
|
18
|
+
await (0, ixixx_1.ixIxxStream)(readStream, path_1.default.join(outLocation, 'trix', `${name}.ix`), path_1.default.join(outLocation, 'trix', `${name}.ixx`), prefixSize);
|
|
19
|
+
}
|
|
20
|
+
async function* indexFiles({ trackConfigs, attributes, outLocation, quiet, typesToExclude, }) {
|
|
21
|
+
for (const config of trackConfigs) {
|
|
22
|
+
const { adapter, textSearching } = config;
|
|
23
|
+
const { type } = adapter || {};
|
|
24
|
+
const { indexingFeatureTypesToExclude = typesToExclude, indexingAttributes = attributes, } = textSearching || {};
|
|
25
|
+
const loc = (0, adapter_utils_1.getAdapterLocation)(adapter);
|
|
26
|
+
if (!loc) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (type === 'Gff3TabixAdapter' || type === 'Gff3Adapter') {
|
|
30
|
+
yield* (0, gff3Adapter_1.indexGff3)({
|
|
31
|
+
config,
|
|
32
|
+
attributesToIndex: indexingAttributes,
|
|
33
|
+
inLocation: (0, adapter_utils_1.getLoc)(loc),
|
|
34
|
+
outLocation,
|
|
35
|
+
typesToExclude: indexingFeatureTypesToExclude,
|
|
36
|
+
quiet,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else if (type === 'VcfTabixAdapter' || type === 'VcfAdapter') {
|
|
40
|
+
yield* (0, vcfAdapter_1.indexVcf)({
|
|
41
|
+
config,
|
|
42
|
+
attributesToIndex: indexingAttributes,
|
|
43
|
+
inLocation: (0, adapter_utils_1.getLoc)(loc),
|
|
44
|
+
outLocation,
|
|
45
|
+
typesToExclude: indexingFeatureTypesToExclude,
|
|
46
|
+
quiet,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function indexDriver({ trackConfigs, attributes, outLocation, name, quiet, typesToExclude, assemblyNames, prefixSize, }) {
|
|
52
|
+
const readStream = stream_1.Readable.from(indexFiles({
|
|
53
|
+
trackConfigs,
|
|
54
|
+
attributes,
|
|
55
|
+
outLocation,
|
|
56
|
+
quiet,
|
|
57
|
+
typesToExclude,
|
|
58
|
+
}));
|
|
59
|
+
await runIxIxx({
|
|
60
|
+
readStream,
|
|
61
|
+
outLocation,
|
|
62
|
+
name,
|
|
63
|
+
prefixSize: typeof prefixSize === 'string' ? parseInt(prefixSize) : prefixSize,
|
|
64
|
+
});
|
|
65
|
+
await (0, common_1.generateMeta)({
|
|
66
|
+
trackConfigs,
|
|
67
|
+
attributes,
|
|
68
|
+
outLocation,
|
|
69
|
+
name,
|
|
70
|
+
typesToExclude,
|
|
71
|
+
assemblyNames,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function prepareFileTrackConfigs(files, fileIds) {
|
|
75
|
+
const trackConfigs = files
|
|
76
|
+
.map(file => (0, common_1.guessAdapterFromFileName)(file))
|
|
77
|
+
.filter(fileConfig => (0, common_1.supported)(fileConfig.adapter?.type));
|
|
78
|
+
if (fileIds?.length) {
|
|
79
|
+
for (const [i, element] of fileIds.entries()) {
|
|
80
|
+
trackConfigs[i].trackId = element;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return trackConfigs;
|
|
84
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
exports.perTrackIndex = perTrackIndex;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const adapter_utils_1 = require("./adapter-utils");
|
|
10
|
+
const config_utils_1 = require("./config-utils");
|
|
11
|
+
const indexing_utils_1 = require("./indexing-utils");
|
|
12
|
+
const validators_1 = require("./validators");
|
|
13
|
+
async function perTrackIndex(flags) {
|
|
14
|
+
const { out, target, tracks, assemblies, attributes, quiet, force, exclude, prefixSize, } = flags;
|
|
15
|
+
const outFlag = target || out || '.';
|
|
16
|
+
const isDir = fs_1.default.lstatSync(outFlag).isDirectory();
|
|
17
|
+
const confFilePath = isDir ? path_1.default.join(outFlag, 'config.json') : outFlag;
|
|
18
|
+
const outLocation = path_1.default.dirname(confFilePath);
|
|
19
|
+
const config = (0, config_utils_1.readConf)(confFilePath);
|
|
20
|
+
const configTracks = config.tracks || [];
|
|
21
|
+
const trixDir = path_1.default.join(outLocation, 'trix');
|
|
22
|
+
if (!fs_1.default.existsSync(trixDir)) {
|
|
23
|
+
fs_1.default.mkdirSync(trixDir);
|
|
24
|
+
}
|
|
25
|
+
(0, validators_1.validateAssembliesForPerTrack)(assemblies);
|
|
26
|
+
const confs = (0, config_utils_1.getTrackConfigs)(confFilePath, tracks?.split(','));
|
|
27
|
+
if (!confs.length) {
|
|
28
|
+
throw new Error('Tracks not found in config.json, please add track configurations before indexing.');
|
|
29
|
+
}
|
|
30
|
+
for (const trackConfig of confs) {
|
|
31
|
+
const { textSearching, trackId, assemblyNames } = trackConfig;
|
|
32
|
+
if (textSearching?.textSearchAdapter && !force) {
|
|
33
|
+
console.log(`Note: ${trackId} has already been indexed with this configuration, use --force to overwrite this track. Skipping for now`);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
console.log(`Indexing track ${trackId}...`);
|
|
37
|
+
await (0, indexing_utils_1.indexDriver)({
|
|
38
|
+
trackConfigs: [trackConfig],
|
|
39
|
+
attributes: attributes.split(','),
|
|
40
|
+
outLocation,
|
|
41
|
+
quiet,
|
|
42
|
+
name: trackId,
|
|
43
|
+
typesToExclude: exclude.split(','),
|
|
44
|
+
assemblyNames,
|
|
45
|
+
prefixSize,
|
|
46
|
+
});
|
|
47
|
+
if (!textSearching?.textSearchAdapter) {
|
|
48
|
+
// modifies track with new text search adapter
|
|
49
|
+
const index = configTracks.findIndex(track => trackId === track.trackId);
|
|
50
|
+
if (index !== -1) {
|
|
51
|
+
configTracks[index] = {
|
|
52
|
+
...trackConfig,
|
|
53
|
+
textSearching: {
|
|
54
|
+
...textSearching,
|
|
55
|
+
textSearchAdapter: (0, adapter_utils_1.createPerTrackTrixAdapter)(trackId, assemblyNames),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.log("Error: can't find trackId");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
(0, config_utils_1.writeConf)({ ...config, tracks: configTracks }, confFilePath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateTrackConfigs = validateTrackConfigs;
|
|
4
|
+
exports.validateFileInput = validateFileInput;
|
|
5
|
+
exports.validateAssembliesForPerTrack = validateAssembliesForPerTrack;
|
|
6
|
+
function validateTrackConfigs(tracks) {
|
|
7
|
+
if (!tracks.length) {
|
|
8
|
+
throw new Error('Tracks not found in config.json, please add track configurations before indexing.');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function validateFileInput(file) {
|
|
12
|
+
if (!file) {
|
|
13
|
+
throw new Error('Cannot index file list without files');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function validateAssembliesForPerTrack(assemblies) {
|
|
17
|
+
if (assemblies) {
|
|
18
|
+
throw new Error(`Can't specify assemblies when indexing per track, remove assemblies flag to continue.`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.run = run;
|
|
4
|
+
const util_1 = require("util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const index_1 = require("./text-index-utils/index");
|
|
7
|
+
async function run(args) {
|
|
8
|
+
const options = {
|
|
9
|
+
help: {
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
short: 'h',
|
|
12
|
+
description: 'Show CLI help',
|
|
13
|
+
},
|
|
14
|
+
tracks: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Specific tracks to index, formatted as comma separated trackIds. If unspecified, indexes all available tracks',
|
|
17
|
+
},
|
|
18
|
+
target: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Path to config file in JB2 installation directory to read from.',
|
|
21
|
+
},
|
|
22
|
+
out: { type: 'string', description: 'Synonym for target' },
|
|
23
|
+
attributes: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'Comma separated list of attributes to index',
|
|
26
|
+
default: 'Name,ID',
|
|
27
|
+
},
|
|
28
|
+
assemblies: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
short: 'a',
|
|
31
|
+
description: 'Specify the assembl(ies) to create an index for. If unspecified, creates an index for each assembly in the config',
|
|
32
|
+
},
|
|
33
|
+
force: {
|
|
34
|
+
type: 'boolean',
|
|
35
|
+
default: false,
|
|
36
|
+
description: 'Overwrite previously existing indexes',
|
|
37
|
+
},
|
|
38
|
+
quiet: {
|
|
39
|
+
type: 'boolean',
|
|
40
|
+
short: 'q',
|
|
41
|
+
default: false,
|
|
42
|
+
description: 'Hide the progress bars',
|
|
43
|
+
},
|
|
44
|
+
perTrack: {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
default: false,
|
|
47
|
+
description: 'If set, creates an index per track',
|
|
48
|
+
},
|
|
49
|
+
exclude: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Adds gene type to list of excluded types',
|
|
52
|
+
default: 'CDS,exon',
|
|
53
|
+
},
|
|
54
|
+
prefixSize: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'Specify the prefix size for the ixx index. We attempt to automatically calculate this, but you can manually specify this too. If many genes have similar gene IDs e.g. Z000000001, Z000000002 the prefix size should be larger so that they get split into different bins',
|
|
57
|
+
},
|
|
58
|
+
file: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
multiple: true,
|
|
61
|
+
description: 'File or files to index (can be used to create trix indexes for embedded component use cases not using a config.json for example)',
|
|
62
|
+
},
|
|
63
|
+
fileId: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
multiple: true,
|
|
66
|
+
description: 'Set the trackId used for the indexes generated with the --file argument',
|
|
67
|
+
},
|
|
68
|
+
dryrun: {
|
|
69
|
+
type: 'boolean',
|
|
70
|
+
description: 'Just print out tracks that will be indexed by the process, without doing any indexing',
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
const { values: flags } = (0, util_1.parseArgs)({
|
|
74
|
+
args,
|
|
75
|
+
options,
|
|
76
|
+
});
|
|
77
|
+
const description = 'Make a text-indexing file for any given track(s).';
|
|
78
|
+
const examples = [
|
|
79
|
+
"# indexes all tracks that it can find in the current directory's config.json",
|
|
80
|
+
'$ jbrowse text-index',
|
|
81
|
+
'',
|
|
82
|
+
"# indexes specific trackIds that it can find in the current directory's config.json",
|
|
83
|
+
'$ jbrowse text-index --tracks=track1,track2,track3',
|
|
84
|
+
'',
|
|
85
|
+
"# indexes all tracks in a directory's config.json or in a specific config file",
|
|
86
|
+
'$ jbrowse text-index --out /path/to/jb2/',
|
|
87
|
+
'',
|
|
88
|
+
'# indexes only a specific assembly, and overwrite what was previously there using force (which is needed if a previous index already existed)',
|
|
89
|
+
'$ jbrowse text-index -a hg19 --force',
|
|
90
|
+
'',
|
|
91
|
+
'# create index for some files for use in @jbrowse/react-linear-genome-view2 or similar',
|
|
92
|
+
'$ jbrowse text-index --file myfile.gff3.gz --file myfile.vcfgz --out indexes',
|
|
93
|
+
];
|
|
94
|
+
if (flags.help) {
|
|
95
|
+
(0, utils_1.printHelp)({
|
|
96
|
+
description,
|
|
97
|
+
examples,
|
|
98
|
+
usage: 'jbrowse text-index [options]',
|
|
99
|
+
options,
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const { perTrack, file } = flags;
|
|
104
|
+
if (file) {
|
|
105
|
+
await (0, index_1.indexFileList)(flags);
|
|
106
|
+
}
|
|
107
|
+
else if (perTrack) {
|
|
108
|
+
await (0, index_1.perTrackIndex)(flags);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
await (0, index_1.aggregateIndex)(flags);
|
|
112
|
+
}
|
|
113
|
+
}
|