From b12f11af03393bcb15e2e1c6e9a2693c145583d6 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Wed, 13 Sep 2017 21:01:31 -0700 Subject: [PATCH] renamed table to category, added File and Block classes, typed category and column objects --- dist/molio.esm.js | 91 +++++++++++++----- dist/molio.js | 1 - package.json | 13 ++- rollup.config.js | 18 ++-- src/index.d.ts | 3 + src/index.ts | 3 + src/reader/gro.ts | 94 +++++++++---------- src/reader/spec/gro.spec.ts | 6 +- src/relational/block.ts | 24 +++++ src/relational/category.ts | 61 ++++++++++++ src/relational/file.ts | 10 ++ src/relational/table.ts | 36 ------- src/relational/text-block.ts | 39 ++++++++ .../{text-table.ts => text-category.ts} | 13 +-- src/relational/text-column.ts | 4 +- src/relational/text-file.ts | 17 ++++ src/script.ts | 34 ++++--- 17 files changed, 310 insertions(+), 157 deletions(-) create mode 100644 src/relational/block.ts create mode 100644 src/relational/category.ts create mode 100644 src/relational/file.ts delete mode 100644 src/relational/table.ts create mode 100644 src/relational/text-block.ts rename src/relational/{text-table.ts => text-category.ts} (90%) create mode 100644 src/relational/text-file.ts diff --git a/dist/molio.esm.js b/dist/molio.esm.js index 913109a81..cce873658 100644 --- a/dist/molio.esm.js +++ b/dist/molio.esm.js @@ -72,6 +72,12 @@ function parseFloat(str, start, end) { return neg * ret; } +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * from https://github.com/dsehnal/CIFTools.js + * @author David Sehnal <david.sehnal@gmail.com> + */ /** * Eat everything until a newline occurs. */ @@ -150,6 +156,13 @@ function skipWhitespace(state) { return prev; } +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * from https://github.com/dsehnal/CIFTools.js + * @author David Sehnal <david.sehnal@gmail.com> + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ var Tokens; (function (Tokens) { function resize(tokens) { @@ -182,6 +195,12 @@ var Tokens; Tokens.create = create; })(Tokens || (Tokens = {})); +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * from https://github.com/dsehnal/CIFTools.js + * @author David Sehnal <david.sehnal@gmail.com> + */ /** * Represents a column that is not present. */ @@ -219,6 +238,13 @@ var ShortStringPool; ShortStringPool.get = get; })(ShortStringPool || (ShortStringPool = {})); +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * from https://github.com/dsehnal/CIFTools.js + * @author David Sehnal <david.sehnal@gmail.com> + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ /** * Represents a single column. */ @@ -328,10 +354,17 @@ var CifColumn = (function (TextColumn) { return CifColumn; }(TextColumn)); +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * from https://github.com/dsehnal/CIFTools.js + * @author David Sehnal <david.sehnal@gmail.com> + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ /** - * Represents a table backed by a string. + * Represents a category backed by a string. */ -var TextTable = function TextTable(data, name, columns, tokens) { +var TextCategory = function TextCategory(data, name, columns, tokens) { this.name = name; this.indices = tokens.indices; this.data = data; @@ -348,13 +381,13 @@ prototypeAccessors.columnNames.get = function () { /** * Get a column object that makes accessing data easier. */ -TextTable.prototype.getColumn = function getColumn (name) { +TextCategory.prototype.getColumn = function getColumn (name) { var i = this.columnIndices.get(name); if (i !== void 0) { return new TextColumn(this, this.data, name, i); } return UndefinedColumn; }; -TextTable.prototype.initColumns = function initColumns (columns) { +TextCategory.prototype.initColumns = function initColumns (columns) { var this$1 = this; this.columnIndices = new Map(); @@ -365,23 +398,23 @@ TextTable.prototype.initColumns = function initColumns (columns) { } }; -Object.defineProperties( TextTable.prototype, prototypeAccessors ); -var CifTable = (function (TextTable) { - function CifTable () { - TextTable.apply(this, arguments); +Object.defineProperties( TextCategory.prototype, prototypeAccessors ); +var CifCategory = (function (TextCategory) { + function CifCategory () { + TextCategory.apply(this, arguments); } - if ( TextTable ) CifTable.__proto__ = TextTable; - CifTable.prototype = Object.create( TextTable && TextTable.prototype ); - CifTable.prototype.constructor = CifTable; + if ( TextCategory ) CifCategory.__proto__ = TextCategory; + CifCategory.prototype = Object.create( TextCategory && TextCategory.prototype ); + CifCategory.prototype.constructor = CifCategory; - CifTable.prototype.getColumn = function getColumn (name) { + CifCategory.prototype.getColumn = function getColumn (name) { var i = this.columnIndices.get(name); if (i !== void 0) { return new CifColumn(this, this.data, name, i); } return UndefinedColumn; }; - CifTable.prototype.initColumns = function initColumns (columns) { + CifCategory.prototype.initColumns = function initColumns (columns) { var this$1 = this; this.columnIndices = new Map(); @@ -393,8 +426,8 @@ var CifTable = (function (TextTable) { } }; - return CifTable; -}(TextTable)); + return CifCategory; +}(TextCategory)); /* * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. @@ -445,19 +478,19 @@ var GroFile = function GroFile(data) { }; var GroBlock = function GroBlock(data) { this.data = data; - this.tableMap = new Map(); - this.tableList = []; + this.categoryMap = new Map(); + this.categoryList = []; }; -GroBlock.prototype.getTable = function getTable (name) { - return this.tableMap.get(name); +GroBlock.prototype.getCategory = function getCategory (name) { + return this.categoryMap.get(name); }; /** - * Adds a table. + * Adds a category. */ -GroBlock.prototype.addTable = function addTable (table) { - this.tableList[this.tableList.length] = table; - this.tableMap.set(table.name, table); +GroBlock.prototype.addCategory = function addCategory (category) { + this.categoryList[this.categoryList.length] = category; + this.categoryMap.set(category.name, category); }; function createTokenizer(data) { return { @@ -590,7 +623,7 @@ function handleAtoms(state, block) { state.position = valueEnd; eatLine(state); } - block.addTable(new TextTable(state.data, name, columns, tokens)); + block.addCategory(new TextCategory(state.data, name, columns, tokens)); } /** * box vectors (free format, space separated reals), values: @@ -626,8 +659,8 @@ function parseInternal(data) { file.blocks.push(block); var headerColumns = ['title', 'timeInPs', 'numberOfAtoms', 'boxX', 'boxY', 'boxZ']; var headerTokens = Tokens.create(2 * headerColumns.length); - var header = new TextTable(state.data, 'header', headerColumns, headerTokens); - block.addTable(header); + var header = new TextCategory(state.data, 'header', headerColumns, headerTokens); + block.addCategory(header); handleTitleString(state, headerTokens); handleNumberOfAtoms(state, headerTokens); handleAtoms(state, block); @@ -638,5 +671,11 @@ function parse(data) { return parseInternal(data); } +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + export { parse as groReader }; //# sourceMappingURL=molio.esm.js.map diff --git a/dist/molio.js b/dist/molio.js index 847442f65..e69de29bb 100644 --- a/dist/molio.js +++ b/dist/molio.js @@ -1 +0,0 @@ -!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.MOLIO={})}(this,function(t){"use strict";function n(t,n,e){var i=0,r=1;for(45===t.charCodeAt(n)&&(r=-1,n++);n<e;n++){var o=t.charCodeAt(n)-48;if(o>9||o<0)return r*i|0;i=10*i+o|0}return r*i}function e(t,e,i,r){return 43===e.charCodeAt(i)&&i++,t*Math.pow(10,n(e,i,r))}function i(t,n,i){var r=1,o=0,s=0,u=1;for(45===t.charCodeAt(n)&&(r=-1,++n);n<i;){var a=t.charCodeAt(n)-48;if(!(a>=0&&a<10)){if(-2===a){for(++n;n<i;){if(!((a=t.charCodeAt(n)-48)>=0&&a<10))return 53===a||21===a?e(r*(o+s/u),t,n+1,i):r*(o+s/u);s=10*s+a,u*=10,++n}return r*(o+s/u)}if(53===a||21===a)return e(r*o,t,n+1,i);break}o=10*o+a,++n}return r*o}function r(t){for(;t.position<t.length;)switch(t.data.charCodeAt(t.position)){case 10:return t.currentTokenEnd=t.position,++t.position,void++t.currentLineNumber;case 13:return t.currentTokenEnd=t.position,++t.position,++t.currentLineNumber,void(10===t.data.charCodeAt(t.position)&&++t.position);default:++t.position}t.currentTokenEnd=t.position}function o(t){for(;t.position<t.length;)switch(t.data.charCodeAt(t.position)){case 9:case 10:case 13:case 32:return void(t.currentTokenEnd=t.position);default:++t.position}t.currentTokenEnd=t.position}function s(t){for(var n=10;t.position<t.length;){var e=t.data.charCodeAt(t.position);switch(e){case 9:case 32:n=e,++t.position;break;case 10:13!==n&&++t.currentLineNumber,n=e,++t.position;break;case 13:n=e,++t.position,++t.currentLineNumber;break;default:return n}}return n}function u(t){return{data:t,position:0,length:t.length,currentLineNumber:1,currentTokenStart:0,currentTokenEnd:0,numberOfAtoms:0,hasVelocities:!1,numberOfDecimalPlaces:3}}function a(t,n){r(t);for(var e=t.currentTokenStart,i=t.currentTokenEnd,o=t.currentTokenStart,s=e;s<i&&!d(t.data,s);)++s;if(d(t.data,s)){for(var u=s+2;s>e&&c(t.data,s-1);)--s;for(v.add(n,o,s);u<i&&32===t.data.charCodeAt(u);)++u;for(;s>u&&32===t.data.charCodeAt(s-1);)--s;v.add(n,u,i)}else v.add(n,o,s),v.add(n,s,s)}function c(t,n){var e=t.charCodeAt(n);return 32===e||44===e}function d(t,n){var e=t.charCodeAt(n);return(84===e||116===e)&&61===t.charCodeAt(n+1)}function h(t,e){s(t),t.currentTokenStart=t.position,o(t),t.numberOfAtoms=n(t.data,t.currentTokenStart,t.currentTokenEnd),v.add(e,t.currentTokenStart,t.currentTokenEnd),r(t)}function f(t,n){console.log("MOINMOIN");var e=["residueNumber","residueName","atomName","atomNumber","x","y","z"];t.hasVelocities&&e.push("vx","vy","vz");for(var i,o,s,u=[5,5,5,5,8,8,8,8,8,8],a=e.length,c=v.create(2*t.numberOfAtoms*a),d=t.position,h=0;h<t.numberOfAtoms;++h){t.currentTokenStart=t.position,o=t.currentTokenStart;for(var f=0;f<a;++f){for(s=i=o,d=o=i+u[f];s<d&&32===t.data.charCodeAt(s);)++s;for(;d>s&&32===t.data.charCodeAt(d-1);)--d;v.addUnchecked(c,s,d)}t.position=d,r(t)}n.addTable(new k(t.data,"atoms",e,c))}function p(t,n){for(var e=0;e<3;++e)s(t),t.currentTokenStart=t.position,o(t),v.add(n,t.currentTokenStart,t.currentTokenEnd)}function l(t){return w.success(t)}function m(t){var n=u(t),e=new x(t),i=new E(t);e.blocks.push(i);var r=["title","timeInPs","numberOfAtoms","boxX","boxY","boxZ"],o=v.create(2*r.length),s=new k(n.data,"header",r,o);return i.addTable(s),a(n,o),h(n,o),f(n,i),p(n,o),l(e)}var v;!function(t){function n(t){var n=new Int32Array(1.61*t.indices.length|0);n.set(t.indices),t.indices=n,t.indicesLenMinus2=n.length-2|0}t.add=function(t,e,i){t.count>t.indicesLenMinus2&&n(t),t.indices[t.count++]=e,t.indices[t.count++]=i},t.addUnchecked=function(t,n,e){t.indices[t.count++]=n,t.indices[t.count++]=e},t.create=function(t){return{indicesLenMinus2:t-2|0,count:0,indices:new Int32Array(t)}}}(v||(v={}));var g=function(){this.isDefined=!1};g.prototype.getString=function(t){return null},g.prototype.getInteger=function(t){return 0},g.prototype.getFloat=function(t){return 0},g.prototype.getValuePresence=function(t){return 1},g.prototype.areValuesEqual=function(t,n){return!0},g.prototype.stringEquals=function(t,n){return null===n};var b,y=new g;!function(t){t.create=function(){return Object.create(null)},t.get=function(t,n){if(n.length>6)return n;var e=t[n];return void 0!==e?e:(t[n]=n,n)}}(b||(b={}));var C=function(t,n,e,i){this.data=n,this.name=e,this.index=i,this.stringPool=b.create(),this.isDefined=!0,this.indices=t.indices,this.columnCount=t.columnCount};C.prototype.getString=function(t){var n=2*(t*this.columnCount+this.index);return b.get(this.stringPool,this.data.substring(this.indices[n],this.indices[n+1]))},C.prototype.getInteger=function(t){var e=2*(t*this.columnCount+this.index);return n(this.data,this.indices[e],this.indices[e+1])},C.prototype.getFloat=function(t){var n=2*(t*this.columnCount+this.index);return i(this.data,this.indices[n],this.indices[n+1])},C.prototype.stringEquals=function(t,n){var e=this,i=2*(t*this.columnCount+this.index),r=this.indices[i],o=n.length;if(o!==this.indices[i+1]-r)return!1;for(var s=0;s<o;s++)if(e.data.charCodeAt(s+r)!==n.charCodeAt(s))return!1;return!0},C.prototype.areValuesEqual=function(t,n){var e=this,i=2*(t*this.columnCount+this.index),r=2*(n*this.columnCount+this.index),o=this.indices[i],s=this.indices[r],u=this.indices[i+1]-o;if(u!==this.indices[r+1]-s)return!1;for(var a=0;a<u;a++)if(e.data.charCodeAt(a+o)!==e.data.charCodeAt(a+s))return!1;return!0},C.prototype.getValuePresence=function(t){var n=2*(t*this.columnCount+this.index);return this.indices[n]===this.indices[n+1]?1:0};var A=function(t){function n(){t.apply(this,arguments)}return t&&(n.__proto__=t),n.prototype=Object.create(t&&t.prototype),n.prototype.constructor=n,n.prototype.getString=function(n){var e=t.prototype.getString.call(this,n);return"."===e||"?"===e?null:e},n.prototype.getValuePresence=function(t){var n=2*(t*this.columnCount+this.index),e=this.indices[n];if(this.indices[n+1]-e!=1)return 0;var i=this.data.charCodeAt(e);return 46===i?1:63===i?2:0},n}(C),k=function(t,n,e,i){this.name=n,this.indices=i.indices,this.data=t,this.columnCount=e.length,this.rowCount=i.count/2/e.length|0,this.initColumns(e)},T={columnNames:{}};T.columnNames.get=function(){return this.columnNameList},k.prototype.getColumn=function(t){var n=this.columnIndices.get(t);return void 0!==n?new C(this,this.data,t,n):y},k.prototype.initColumns=function(t){var n=this;this.columnIndices=new Map,this.columnNameList=[];for(var e=0;e<t.length;e++)n.columnIndices.set(t[e],e),n.columnNameList.push(t[e])},Object.defineProperties(k.prototype,T);var w;!function(t){function n(){t.apply(this,arguments)}t&&(n.__proto__=t),n.prototype=Object.create(t&&t.prototype),n.prototype.constructor=n,n.prototype.getColumn=function(t){var n=this.columnIndices.get(t);return void 0!==n?new A(this,this.data,t,n):y},n.prototype.initColumns=function(t){var n=this;this.columnIndices=new Map,this.columnNameList=[];for(var e=0;e<t.length;e++){var i=t[e].substr(n.name.length+1);n.columnIndices.set(i,e),n.columnNameList.push(i)}}}(k);!function(t){t.error=function(t,n){return void 0===n&&(n=-1),new L(t,n)},t.success=function(t,n){return void 0===n&&(n=[]),new N(t,n)}}(w||(w={}));var L=function(t,n){this.message=t,this.line=n,this.isError=!0};L.prototype.toString=function(){return this.line>=0?"[Line "+this.line+"] "+this.message:this.message};var N=function(t,n){this.result=t,this.warnings=n,this.isError=!1},x=function(t){this.blocks=[],this.data=t},E=function(t){this.data=t,this.tableMap=new Map,this.tableList=[]};E.prototype.getTable=function(t){return this.tableMap.get(t)},E.prototype.addTable=function(t){this.tableList[this.tableList.length]=t,this.tableMap.set(t.name,t)},t.groReader=function(t){return m(t)},Object.defineProperty(t,"__esModule",{value:!0})}); diff --git a/package.json b/package.json index 639b0d963..c1de25f15 100644 --- a/package.json +++ b/package.json @@ -23,19 +23,18 @@ "license": "MIT", "devDependencies": { "@types/jest": "latest", - "@types/node": "^8.0.25", - "jest": "^20.0.4", - "rollup": "^0.49.2", + "@types/node": "^8.0.28", + "jest": "^21.1.0", + "rollup": "^0.49.3", "rollup-plugin-buble": "^0.15.0", - "rollup-plugin-commonjs": "^8.2.0", + "rollup-plugin-commonjs": "^8.2.1", "rollup-plugin-json": "^2.3.0", "rollup-plugin-node-resolve": "^3.0.0", "rollup-watch": "^4.3.1", - "ts-jest": "^20.0.14", + "ts-jest": "^21.0.0", "tslint": "^5.7.0", "typescript": "^2.5.1", - "uglify-js": "^3.0.28", - "webpack": "^3.5.5" + "uglify-js": "^3.1.0" }, "dependencies": {} } diff --git a/rollup.config.js b/rollup.config.js index 29e505326..577c39346 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,4 +1,4 @@ -import buble from 'rollup-plugin-buble'; +// import buble from 'rollup-plugin-buble'; import json from 'rollup-plugin-json'; import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; @@ -16,21 +16,21 @@ export default { }), commonjs(), json(), - buble() + // buble() ], output: [ { file: "build/js/molio.dev.js", format: 'umd', name: 'MOLIO', - sourcemap: true + sourcemap: false }, - { - file: "build/js/molio.esm.js", - format: 'es', - sourcemap: true - } + // { + // file: "build/js/molio.esm.js", + // format: 'es', + // sourcemap: false + // } ], external: external, - sourcemap: true + sourcemap: false }; \ No newline at end of file diff --git a/src/index.d.ts b/src/index.d.ts index f4e7f3c9a..8e857ee33 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -6,4 +6,7 @@ export { ParserResult, ParserError, ParserSuccess } from './parser' +export { Category } from './relational/category' +export { Column } from './relational/column' + export { parse as groReader } from './reader/gro' diff --git a/src/index.ts b/src/index.ts index cbcdecf1e..3a7b1225e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,4 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ +export { Category } from './relational/category' +export { Column } from './relational/column' + export { parse as groReader } from './reader/gro' diff --git a/src/reader/gro.ts b/src/reader/gro.ts index ede2ac342..d148f3ebc 100644 --- a/src/reader/gro.ts +++ b/src/reader/gro.ts @@ -9,7 +9,9 @@ import { eatLine, eatValue, skipWhitespace } from '../utils/helper' import { Tokens } from '../utils/tokens' import { TokenizerState } from '../utils/tokenizer-state' -import { TextTable } from '../relational/text-table' +import { TextFile } from '../relational/text-file' +import { TextBlock } from '../relational/text-block' +import { TextCategory } from '../relational/text-category' import { ParserResult } from '../parser' @@ -17,53 +19,40 @@ import { ParserResult } from '../parser' * http://manual.gromacs.org/current/online/gro.html */ -export interface GroFile { - data: string; - blocks: GroBlock[]; +export const GroCategories = { + 'header': '', + 'atoms': '' } -export interface GroBlock { - getTable(name: string): TextTable - addTable(table: TextTable): void -} - -export class GroFile implements GroFile { - data: string; - blocks: GroBlock[] = []; +// type GroCategories = keyof typeof GroCategories - constructor(data: string) { - this.data = data; - } +export const GroAtomBasicColumns = { + 'residueNumber': '', + 'residueName': '', + 'atomName': '', + 'atomNumber': '', + 'x': '', + 'y': '', + 'z': '' } - -export class GroBlock implements GroBlock { - private tableMap: Map<string, TextTable>; - private tableList: TextTable[]; - - data: string; - - /** - * Gets a table by its name. - */ - getTable(name: string) { - return this.tableMap.get(name); - } - - /** - * Adds a table. - */ - addTable(table: TextTable) { - this.tableList[this.tableList.length] = table; - this.tableMap.set(table.name, table); - } - - constructor(data: string) { - this.data = data; - - this.tableMap = new Map() - this.tableList = [] - } +export type GroAtomBasicColumns = keyof typeof GroAtomBasicColumns + +export const GroAtomVelocityColumns = Object.assign({ + 'vx': '', + 'vy': '', + 'vz': '' +}, GroAtomBasicColumns) +export type GroAtomVelocityColumns = keyof typeof GroAtomVelocityColumns + +export const GroHeaderColumns = { + 'title': '', + 'timeInPs': '', + 'numberOfAtoms': '', + 'boxX': '', + 'boxY': '', + 'boxZ': '' } +export type GroHeaderColumns = keyof typeof GroHeaderColumns export interface GroState extends TokenizerState { numberOfAtoms: number @@ -181,7 +170,7 @@ function handleNumberOfAtoms (state: GroState, tokens: Tokens) { * position (in nm, x y z in 3 columns, each 8 positions with 3 decimal places) * velocity (in nm/ps (or km/s), x y z in 3 columns, each 8 positions with 4 decimal places) */ -function handleAtoms (state: GroState, block: GroBlock) { +function handleAtoms (state: GroState, block: TextBlock) { console.log('MOINMOIN') const name = 'atoms' @@ -218,7 +207,7 @@ function handleAtoms (state: GroState, block: GroBlock) { eatLine(state) } - block.addTable(new TextTable(state.data, name, columns, tokens)); + block.addCategory(new TextCategory(state.data, name, columns, tokens)); } /** @@ -241,27 +230,28 @@ function handleBoxVectors (state: GroState, tokens: Tokens) { * Creates an error result. */ // function error(line: number, message: string) { -// return ParserResult.error<GroFile>(message, line); +// return ParserResult.error<TextFile>(message, line); // } /** * Creates a data result. */ -function result(data: GroFile) { +function result(data: TextFile) { return ParserResult.success(data); } -function parseInternal(data: string): ParserResult<GroFile> { +function parseInternal(data: string): ParserResult<TextFile> { const state = createTokenizer(data) - const file = new GroFile(data) + const file = new TextFile(data) + file.blocks - let block = new GroBlock(data) + let block = new TextBlock(data) file.blocks.push(block) const headerColumns = ['title', 'timeInPs', 'numberOfAtoms', 'boxX', 'boxY', 'boxZ'] const headerTokens = Tokens.create(2 * headerColumns.length) - let header = new TextTable(state.data, 'header', headerColumns, headerTokens) - block.addTable(header) + let header = new TextCategory(state.data, 'header', headerColumns, headerTokens) + block.addCategory(header) handleTitleString(state, headerTokens) handleNumberOfAtoms(state, headerTokens) diff --git a/src/reader/spec/gro.spec.ts b/src/reader/spec/gro.spec.ts index db611f56f..0071a447c 100644 --- a/src/reader/spec/gro.spec.ts +++ b/src/reader/spec/gro.spec.ts @@ -5,7 +5,7 @@ */ import { parse } from '../gro' -// import { Table } from '../../relational/table' +// import { Category } from '../../relational/category' const groString = `MD of 2 waters, t= 4.2 6 @@ -33,7 +33,7 @@ describe('gro reader', () => { } else { const groFile = parsed.result - const header = groFile.blocks[0].getTable('header') + const header = groFile.blocks[0].getCategory('header') if (header) { expect(header.columnNames).toEqual(['title', 'timeInPs', 'numberOfAtoms', 'boxX', 'boxY', 'boxZ']) @@ -58,7 +58,7 @@ describe('gro reader', () => { } else { const groFile = parsed.result - const header = groFile.blocks[0].getTable('header') + const header = groFile.blocks[0].getCategory('header') if (header) { expect(header.columnNames).toEqual(['title', 'timeInPs', 'numberOfAtoms', 'boxX', 'boxY', 'boxZ']) diff --git a/src/relational/block.ts b/src/relational/block.ts new file mode 100644 index 000000000..d8c212bff --- /dev/null +++ b/src/relational/block.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Category, UndefinedCategory } from './category' + +export abstract class Block<T> { + abstract getCategory(name: string): T|undefined + abstract addCategory(category: T): void + + getCategoriesFromSchema<T extends object> (schema: T) { + return BlockCategories(this, schema) + } +} + +export type BlockCategories<Categories extends string> = { readonly [name in Categories]: Category } +export function BlockCategories<T extends object>(block: Block<any> | undefined, categories: T): BlockCategories<keyof T> { + const ret = Object.create(null); + if (!block) for (const c of Object.keys(categories)) ret[c] = UndefinedCategory; + else for (const c of Object.keys(categories)) ret[c] = block.getCategory(c); + return ret; +} diff --git a/src/relational/category.ts b/src/relational/category.ts new file mode 100644 index 000000000..0d387b49d --- /dev/null +++ b/src/relational/category.ts @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * from https://github.com/dsehnal/CIFTools.js + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Column, UndefinedColumn } from './column' + +/** + * Represents a tabular category with multiple fields represented as columns. + * + * Example: + * _category.field1 + * _category.field2 + * ... + */ +export abstract class Category { + name: string; + rowCount: number; + columnCount: number; + columnNames: string[]; + + /** + * If a field with the given name is not present, returns UndefinedColumn. + * + * Columns are accessed by their field name only, i.e. + * _category.field is accessed by + * category.getColumn('field') + * + * Note that columns are created on demand and there is some computational + * cost when creating a new column. Therefore, if you need to reuse a column, + * it is a good idea to cache it. + */ + abstract getColumn(name: string): Column; + + getColumnsFromSchema<T extends object> (schema: T) { + return CategoryColumns(this, schema) + } +} + +/** + * Represents a category that is not present. + */ +class _UndefinedCategory extends Category { // tslint:disable-line:class-name + name: '' + rowCount = 0 + columnCount = 0 + columnNames = [] + getColumn(name: string) { return UndefinedColumn } +} +export const UndefinedCategory = new _UndefinedCategory() as Category; + + +export type CategoryColumns<Columns extends string> = { readonly [name in Columns]: Column } +export function CategoryColumns<T extends object>(category: Category | undefined, columns: T): CategoryColumns<keyof T> { + const ret = Object.create(null); + if (!category) for (const c of Object.keys(columns)) ret[c] = UndefinedColumn; + else for (const c of Object.keys(columns)) ret[c] = category.getColumn(c); + return ret; +} diff --git a/src/relational/file.ts b/src/relational/file.ts new file mode 100644 index 000000000..80bf53205 --- /dev/null +++ b/src/relational/file.ts @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +export interface File<T> { + blocks: T[]; +} + diff --git a/src/relational/table.ts b/src/relational/table.ts deleted file mode 100644 index ebf6f88f7..000000000 --- a/src/relational/table.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. - * - * from https://github.com/dsehnal/CIFTools.js - * @author David Sehnal <david.sehnal@gmail.com> - */ - -import { Column } from './column' - -/** - * Represents that CIF category with multiple fields represented as columns. - * - * Example: - * _category.field1 - * _category.field2 - * ... - */ -export interface Table { - name: string; - rowCount: number; - columnCount: number; - columnNames: string[]; - - /** - * If a field with the given name is not present, returns UndefinedColumn. - * - * Columns are accessed by their field name only, i.e. - * _category.field is accessed by - * category.getColumn('field') - * - * Note that columns are created on demand and there is some computational - * cost when creating a new column. Therefore, if you need to reuse a column, - * it is a good idea to cache it. - */ - getColumn(name: string): Column; -} diff --git a/src/relational/text-block.ts b/src/relational/text-block.ts new file mode 100644 index 000000000..c4ef35b76 --- /dev/null +++ b/src/relational/text-block.ts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Block } from './block' +import { TextCategory } from './text-category' + +export class TextBlock extends Block<TextCategory> { + private categoryMap: Map<string, TextCategory>; + private categoryList: TextCategory[]; + + data: string; + + /** + * Gets a category by its name. + */ + getCategory(name: string) { + return this.categoryMap.get(name); + } + + /** + * Adds a category. + */ + addCategory(category: TextCategory) { + this.categoryList[this.categoryList.length] = category; + this.categoryMap.set(category.name, category); + } + + constructor(data: string) { + super() + + this.data = data; + + this.categoryMap = new Map() + this.categoryList = [] + } +} \ No newline at end of file diff --git a/src/relational/text-table.ts b/src/relational/text-category.ts similarity index 90% rename from src/relational/text-table.ts rename to src/relational/text-category.ts index c4ca29a8c..f550213df 100644 --- a/src/relational/text-table.ts +++ b/src/relational/text-category.ts @@ -6,16 +6,16 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Table } from './table' +import { Category } from './category' import { UndefinedColumn } from './column' import { TextColumn, CifColumn } from './text-column' import { Tokens } from '../utils/tokens' /** - * Represents a table backed by a string. + * Represents a category backed by a string. */ -export class TextTable implements Table { +export class TextCategory extends Category { protected data: string; protected columnNameList: string[]; protected columnIndices: Map<string, number>; @@ -66,8 +66,9 @@ export class TextTable implements Table { } } - constructor( - data: string, name: string, columns: string[], tokens: Tokens) { + constructor(data: string, name: string, columns: string[], tokens: Tokens) { + super() + this.name = name; this.indices = tokens.indices; this.data = data; @@ -79,7 +80,7 @@ export class TextTable implements Table { } } -export class CifTable extends TextTable { +export class CifCategory extends TextCategory { getColumn(name: string): CifColumn { let i = this.columnIndices.get(name); if (i !== void 0) return new CifColumn(this, this.data, name, i); diff --git a/src/relational/text-column.ts b/src/relational/text-column.ts index d6cb87c79..7c04c09d6 100644 --- a/src/relational/text-column.ts +++ b/src/relational/text-column.ts @@ -8,7 +8,7 @@ import { Column } from './column' import { ValuePresence } from './constants' -import { TextTable } from './text-table' +import { TextCategory } from './text-category' import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../utils/number-parser' import { ShortStringPool } from '../utils/short-string-pool' @@ -89,7 +89,7 @@ export class TextColumn implements Column { return ValuePresence.Present } - constructor(table: TextTable, protected data: string, public name: string, public index: number) { + constructor(table: TextCategory, protected data: string, public name: string, public index: number) { this.indices = table.indices; this.columnCount = table.columnCount; } diff --git a/src/relational/text-file.ts b/src/relational/text-file.ts new file mode 100644 index 000000000..6058531cc --- /dev/null +++ b/src/relational/text-file.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { File } from './file' +import { TextBlock } from './text-block' + +export class TextFile implements File<TextBlock> { + data: string; + blocks: TextBlock[] = []; + + constructor(data: string) { + this.data = data; + } +} diff --git a/src/script.ts b/src/script.ts index d5520faea..013e07921 100644 --- a/src/script.ts +++ b/src/script.ts @@ -7,17 +7,17 @@ // import * as util from 'util' import * as fs from 'fs' -import { parse } from './reader/gro' -import { Table } from './relational/table' +import { parse, GroCategories, GroAtomBasicColumns } from './reader/gro' +import { Category } from './relational/category' const file = '1crn.gro' // const file = 'water.gro' // const file = 'test.gro' // const file = 'md_1u19_trj.gro' -function getFloatArray(table: Table, name: string) { - const column = table.getColumn(name) - const n = table.rowCount +function getFloatArray(category: Category, name: string) { + const column = category.getColumn(name) + const n = category.rowCount const array = new Float32Array(n) for (let i = 0; i < n; ++i) { array[i] = column.getFloat(i) @@ -25,9 +25,9 @@ function getFloatArray(table: Table, name: string) { return array } -function getIntArray(table: Table, name: string) { - const column = table.getColumn(name) - const n = table.rowCount +function getIntArray(category: Category, name: string) { + const column = category.getColumn(name) + const n = category.rowCount const array = new Int32Array(n) for (let i = 0; i < n; ++i) { array[i] = column.getInteger(i) @@ -48,8 +48,10 @@ fs.readFile(`./examples/${file}`, 'utf8', function (err,data) { console.log(parsed) } else { const groFile = parsed.result + const categories = groFile.blocks[0].getCategoriesFromSchema(GroCategories) - const header = groFile.blocks[0].getTable('header') + // const header = groFile.blocks[0].getCategory('header') + const header = categories.header if (header) { console.log(header.columnNames) @@ -63,15 +65,17 @@ fs.readFile(`./examples/${file}`, 'utf8', function (err,data) { console.error('no header') } - const atoms = groFile.blocks[0].getTable('atoms') + const atoms = categories.atoms if (atoms) { console.log(atoms.columnNames) - console.log(`'${atoms.getColumn('residueNumber').getString(1)}'`) - console.log(`'${atoms.getColumn('residueName').getString(1)}'`) - console.log(`'${atoms.getColumn('atomName').getString(1)}'`) - console.log(atoms.getColumn('z').getFloat(1)) - console.log(`'${atoms.getColumn('z').getString(1)}'`) + const columns = atoms.getColumnsFromSchema(GroAtomBasicColumns) + + console.log(`'${columns.residueNumber.getString(1)}'`) + console.log(`'${columns.residueName.getString(1)}'`) + console.log(`'${columns.atomName.getString(1)}'`) + console.log(columns.z.getFloat(1)) + console.log(`'${columns.z.getString(1)}'`) const n = atoms.rowCount console.log('rowCount', n) -- GitLab