
Security News
Crates.io Users Targeted by Phishing Emails
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.
itp-parser
Advanced tools
A basic ITP/TOP file parser
Install the package using npm.
npm i itp-parser
This package exports two objects: ItpFile
and TopFile
, whose have obvious usages.
Default export is ItpFile
.
// ECMA Modules
import ItpFile, { TopFile } from 'itp-parser';
// or
import { ItpFile, TopFile } from 'itp-parser';
// CommonJS modules
const { ItpFile, TopFile } = require('itp-parser');
ItpFile
and TopFile
instancesItpFile
instancemoleculetype
field per instanceTopFile
instancemolecules
field, associate every described molecule to a ItpFile
instanceThis parser handle only basic parsing:
It does not resolve includes, and it does not consider #define
, #ifdef
or other preprocessor statements.
Lines that contains those preprocessors are stored as plain lines in field definitions.
To have a support of includes and basic support of preprocessors, see AdvancedTopFile
object.
Async instanciation accepts string
(as file path), NodeJS.ReadableStream
and File
/Blob
objects (from browser).
Sync instanciation accepts string
(as file content).
The following sections will talk about the ItpFile
object.
If you know that your ITP file does not contain a molecule (moleculetype
) definition,
or contains only one definition,
use ItpFile.read()
or ItpFile.readFromString()
as constructor.
import { ItpFile } from 'itp-parser';
import fs from 'fs';
// Read asynchrounously
(async () => {
// Single line instanciation
// With file path
const file = await ItpFile.read('/path/to/file');
// With a readable stream
const file = await ItpFile.read(fs.createReadStream('/path/to/file'));
// With a File/Blob (inside a browser)
const file = await ItpFile.read(document.querySelector('input[type="file"]').files[0]);
console.log("This ITP hold moleculetype", file.name);
// {file} is ready !
})();
// Read synchronously
const file = ItpFile.readFromString(fs.readFileSync('/path/to/file.itp', 'utf-8'));
// {file} is ready
If your ITP contain multiple molecule definitions, or if you don't know how many moleculetype
are presents
in the targeted ITP, use ItpFile.readMany()
or ItpFile.readManyFromString()
as constructor.
It both returns a array of ItpFile
, once per moleculetype
definition.
If the ITP does not contain any moleculetype
, an array of one ItpFile
is returned.
import { ItpFile } from 'itp-parser';
// Asynchrounously
(async () => {
const itps = await ItpFile.readMany('/path/to/file');
for (const itp of itps) {
console.log("ITP: moleculetype", itp.name);
}
// All itps are ready !
})();
// Read synchronously
const itps = ItpFile.readManyFromString(fs.readFileSync('/path/to/file.itp', 'utf-8'));
Every field is an array of strings (array of lines).
file.getField('{field_name}'); // => string[] (every line contained in the field. Empty lines are skipped.)
// For example: Access to all atoms
file.getField('atoms');
// Get a field without the lines that are only comments
file.getField('atoms', true);
Some fields have direct accessor:
file.name; // Name/Type. Read from moleculetype
file.name_and_nrexcl; // => [string, number]. parsed version of file.getField('moleculetype')
file.atoms; // string[]. Equivalent to file.getField('atoms')
file.bonds; // string[]. Equivalent to file.getField('bonds')
file.virtual_sites; // string[]. Equivalent to file.getField('virtual_sitesn')
Lines read before encountering a single field declaration are stored in .headlines
.
file.headlines; // => string[]
You can change data of a field with .setField(name, lines)
and create a read stream of this ITP with .asReadStream()
.
import fs from 'fs';
// Change the atom field with modified data
file.setField('atoms', file.atoms.filter(line => line.split(/\s+/).length > 3));
// Write the new ITP
const writestm = fs.createWriteStream('/path/to/output.itp');
new Promise((resolve, reject) => {
const reads = file.asReadStream();
reads.on('close', resolve);
reads.on('error', reject);
writestm.on('error', reject);
reads.pipe(writestm);
}).then(() => {
console.log("Write is over !");
}).catch(e => {
console.log("An error occured.", e);
});
A .toString()
method is also available to return the formatted ITP as a plain string.
const file_as_string = file.toString(); // or String(file)
fs.writeFileSync('/path/to/output.itp', file_as_string);
The following sections will talk about the TopFile
object.
With the TopFile
object, you can read a TOP file and associated ITPs.
In order to link moleculetype
described in molecules
field of TOP with ITP data, you either:
// Asynchronously
const top = await TopFile.read('/path/to/top', ['/path/to/itp1', '/path/to/itp2']);
// Synchronously
const top = TopFile.readFromString(
fs.readFileSync('/path/to/top', 'utf-8'),
[
fs.readFileSync('/path/to/itp1', 'utf-8'),
fs.readFileSync('/path/to/itp2', 'utf-8'),
]
);
// {top} is ready !
for (const molecule of top.molecules) {
console.log("Molecule", molecule.type, ":", molecule.count, "times in the system");
}
When you know which moleculetype
is present in the system, you can load inside the TopFile
instance the ITPs you want.
// Asynchronously
await top.sideloadItp('/path/to/itp');
// Synchronously
top.sideloadItpFromString(fs.readFileSync('/path/to/itp', 'utf-8'));
For example, if your system contain DPPC
:
// If your file contains multiple moleculetype, they're all parsed in async mode
await top.sideloadItp('lipids.itp');
top.molecules.filter(e => e.type === "DPPC")[0].itp; // => ItpFile
A molecule can be described multiple times in a system, for example:
[ molecules ]
molecule_0 2
molecule_1 3
molecule_0 1
is a valid format for GROMACS.
For this reason, a molecule type can be present multiple time in the top.molecules
array.
top.molecules
is an array of MoleculeDefinition
.
interface MoleculeDefinition {
itp: ItpFile,
count: number,
type: string
}
The first string
is the molecule type,
and the MoleculeDefinition
is an object containing two fields:
itp
: Contains the related ItpFile
for this molecule typecount
: Associated count of the molecule type, number on the right in exampleIn order to access ItpFile
instance, you must provide the ITP for the given moleculetype
in the constructor.
const molecules = top.molecules.filter(e => e.type === "DPPC");
if (molecules) {
console.log("Molecule DPPC is present", molecules.reduce((acc, cur) => acc + cur.count, 0), "times in the system");
}
The TopFile
instance inherits from ItpFile
, so all methods presented before are accessible with.
AdvancedTopFile
have a similar API of TopFile
, except some points.
Therefore, unlike the other classes, you must instanciate it with the constructor then using .read(what: ReadEntry, onInclude: Includer)
.
This class accepts files with a ReadEntry
partial object.
interface ReadEntry {
path: string;
stream: NodeJS.ReadableStream;
content: string;
file: Blob;
/** Only valid on return of a `on_include` closure. */
none: true;
}
To specify which file you want to load, fill only one of the properties of the object.
In order to resolve includes, you must specify a callback (async or not) that returns a ReadEntry
as the second parameter of .read
method.
type Includer = (filename: string) => Partial<ReadEntry> | Promise<Partial<ReadEntry>>;
Let's see how it works with an example:
import { AdvancedTopFile } from 'itp-parser';
import fs, { promises as FsPromise } from 'fs';
const top = new AdvancedTopFile(/* enable_preprocessors = */ true);
await top.read(
/* the file to read */ { path: '/path/to/file.top' },
/* when a file is included */
async (name: string) => {
const exists = await FsPromise.access(name, fs.F_OK)
.then(() => true)
.catch(() => false);
if (exists) {
// If file exists, include it as path
return { path: name };
}
// Otherwise, fill the none field (do not include it)
return { none: true };
}
);
// Your whole system described by file.top is ready,
// even included files are resolved !
The following methods/properties are available:
.define(name: string)
: To do before .read()
; Define a macro, like #define NAME
in a ITP fileItpFile
, this object inherits from itTopFile
:
.registred_itps
: A Set
of all molecules as ItpFile
s.molecules
: A MoleculeDefinition
array.name
: Name of the system.getMolecule(name: string)
: A MoleculeDefinition
array containing all occurence of molecule {name}
.includes
: All the #include
lines (they're not inside the fields arrays, so you can find them here).toString()
and .asReadStream()
: a string
/stream.Readable
representation of the system; all included files are emitted in the stream, so the system could be written a a single fileThis module is written in TypeScript. In order to use it, you must have the TypeScript compiler installed.
git clone https://github.com/alkihis/itp-parser.git
cd itp-parser
npm i
tsc
# Compiled JS entrypoint is in dist/index.js
FAQs
A basic ITP/TOP file parser
We found that itp-parser demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The Rust Security Response WG is warning of phishing emails from rustfoundation.dev targeting crates.io users.
Product
Socket now lets you customize pull request alert headers, helping security teams share clear guidance right in PRs to speed reviews and reduce back-and-forth.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.