molstar
Version:
A comprehensive macromolecular library.
113 lines (112 loc) • 4.72 kB
JavaScript
"use strict";
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Sebastian Bittrich <sebastian.bittrich@rcsb.org>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.convert = convert;
const tslib_1 = require("tslib");
const cif_1 = require("../../mol-io/reader/cif");
const cif_2 = require("../../mol-io/writer/cif");
const util = tslib_1.__importStar(require("util"));
const fs = tslib_1.__importStar(require("fs"));
const zlib = tslib_1.__importStar(require("zlib"));
const mol_task_1 = require("../../mol-task");
const binary_cif_1 = require("../../mol-io/common/binary-cif");
const encoder_1 = require("../../mol-io/writer/cif/encoder");
const utf8_1 = require("../../mol-io/common/utf8");
function showProgress(p) {
process.stdout.write(`\r${new Array(80).join(' ')}`);
process.stdout.write(`\r${mol_task_1.Progress.format(p)}`);
}
const readFileAsync = util.promisify(fs.readFile);
const unzipAsync = util.promisify(zlib.unzip);
async function readFile(ctx, filename) {
const isGz = /\.gz$/i.test(filename);
if (filename.match(/\.bcif/)) {
let input = await readFileAsync(filename);
if (isGz)
input = await unzipAsync(input);
return await cif_1.CIF.parseBinary(new Uint8Array(input)).runInContext(ctx);
}
else {
const data = isGz ? await unzipAsync(await readFileAsync(filename)) : await readFileAsync(filename);
const str = (0, utf8_1.utf8ReadLong)(data);
const cif = await cif_1.CIF.parseText(str).runInContext(ctx);
return cif;
}
}
async function getCIF(ctx, filename) {
const parsed = await readFile(ctx, filename);
if (parsed.isError) {
throw new Error(parsed.toString());
}
return parsed.result;
}
function getCategoryInstanceProvider(cat, fields) {
return {
name: cat.name,
instance: () => cif_2.CifWriter.categoryInstance(fields, { data: cat, rowCount: cat.rowCount })
};
}
function classify(name, field) {
const type = (0, cif_1.getCifFieldType)(field);
if (type['@type'] === 'str') {
return { name, type: cif_2.CifWriter.Field.Type.Str, value: field.str, valueKind: field.valueKind };
}
else if (type['@type'] === 'float') {
const encoder = (0, binary_cif_1.classifyFloatArray)(field.toFloatArray({ array: Float64Array }));
return cif_2.CifWriter.Field.float(name, field.float, { valueKind: field.valueKind, encoder, typedArray: Float64Array });
}
else {
const encoder = (0, binary_cif_1.classifyIntArray)(field.toIntArray({ array: Int32Array }));
return cif_2.CifWriter.Field.int(name, field.int, { valueKind: field.valueKind, encoder, typedArray: Int32Array });
}
}
function convert(path, asText = false, hints, filter) {
return mol_task_1.Task.create('Convert CIF', async (ctx) => {
const encodingProvider = hints
? cif_2.CifWriter.createEncodingProviderFromJsonConfig(hints)
: { get: (c, f) => void 0 };
const cif = await getCIF(ctx, path);
const encoder = cif_2.CifWriter.createEncoder({
binary: !asText,
encoderName: 'mol*/ciftools cif2bcif',
binaryAutoClassifyEncoding: true,
binaryEncodingPovider: encodingProvider
});
if (filter) {
encoder.setFilter(encoder_1.Category.filterOf(filter));
}
let maxProgress = 0;
for (const b of cif.blocks) {
maxProgress += b.categoryNames.length;
for (const c of b.categoryNames)
maxProgress += b.categories[c].fieldNames.length;
}
let current = 0;
for (const b of cif.blocks) {
encoder.startDataBlock(b.header);
for (const c of b.categoryNames) {
const cat = b.categories[c];
const fields = [];
for (const f of cat.fieldNames) {
fields.push(classify(f, cat.getField(f)));
current++;
if (ctx.shouldUpdate)
await ctx.update({ message: 'Encoding...', current, max: maxProgress });
}
encoder.writeCategory(getCategoryInstanceProvider(b.categories[c], fields));
current++;
if (ctx.shouldUpdate)
await ctx.update({ message: 'Encoding...', current, max: maxProgress });
}
}
await ctx.update('Exporting...');
const ret = encoder.getData();
await ctx.update('Done.\n');
return ret;
}).run(showProgress, 250);
}