[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![license](https://img.shields.io/npm/l/@kkitahara/cif-tools.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![pipeline status](https://gitlab.com/kkitahara/cif-tools/badges/v2.1.0/pipeline.svg)](https://gitlab.com/kkitahara/cif-tools/commits/v2.1.0)
[![coverage report](https://gitlab.com/kkitahara/cif-tools/badges/v2.1.0/coverage.svg)](https://gitlab.com/kkitahara/cif-tools/commits/v2.1.0)
[![version](https://img.shields.io/npm/v/@kkitahara/cif-tools/latest.svg)](https://www.npmjs.com/package/@kkitahara/cif-tools)
[![bundle size](https://img.shields.io/bundlephobia/min/@kkitahara/cif-tools.svg)](https://www.npmjs.com/package/@kkitahara/cif-tools)
[![downloads per week](https://img.shields.io/npm/dw/@kkitahara/cif-tools.svg)](https://www.npmjs.com/package/@kkitahara/cif-tools)
[![downloads per month](https://img.shields.io/npm/dm/@kkitahara/cif-tools.svg)](https://www.npmjs.com/package/@kkitahara/cif-tools)
[![downloads per year](https://img.shields.io/npm/dy/@kkitahara/cif-tools.svg)](https://www.npmjs.com/package/@kkitahara/cif-tools)
[![downloads total](https://img.shields.io/npm/dt/@kkitahara/cif-tools.svg)](https://www.npmjs.com/package/@kkitahara/cif-tools)

# CIFTools

ECMAScript modules for manipulating Crystallographic Information File (CIF).

Currently, following functionalities are implemented:
- reading (from a CIF 1.1 or CIF2.0 string to a CIF object)
- translation of a data value by using DDL1 dictionaries

New functionalities, for example,
- writing (from a CIF object to a CIF string)
- validation
- support for DDL2, DDLm and dREL

may be added on (author's) demand in future.

## Instllation
```
npm install @kkitahara/cif-tools
```

## Examples
```javascript
import { CIF, Dict } from '@kkitahara/cif-tools'
```

Construct a CIF object from a string
```javascript
let cif = CIF.fromCIFString(`#\\#CIF_2.0
    data_my_awesome_crystal
      _cell_length_a 1.00(1)
      _cell_length_b 2.00(2)
      _cell_length_c 3.00(3)

    data_My_Ordinary_Crystal
      _cell_length_a 1.0(1)
      _cell_length_b 2.0(2)
      _cell_length_c 3.0(3)

    data_MY_AWFUL_CRYSTAL
      _CELL_LENGTH_A 1.0(10)
      _CELL_LENGTH_B 2.0(20)
      _CELL_LENGTH_C 3.0(30)
`)
cif instanceof CIF // true
```

Extract block codes from a CIF object
```javascript
let blockCodes = CIF.getBlockCodes(cif)

blockCodes[0] // 'my_awesome_crystal'
blockCodes[1] // 'my_ordinary_crystal'
blockCodes[2] // 'my_awful_crystal'
```
:memo: block codes are case folded

Extract a data block from a CIF object
```javascript
let block = CIF.getBlock(cif, 'my_awful_crystal')
```

Extract a raw data value from a block
```javascript
let val = CIF.getDataValue(block, '_cell_length_a')

// A raw data value is contained in an array
val.length // 1
val[0] // '1.0(10)'
```
:memo: tag (data name) is case-insensitive

Get dictionaries to which blocks in a given cif corform
```javascript
let dicts = Dict.getConformDicts(cif)

// A dictionary for a block
let dict = dicts['my_awful_crystal']
```

Translate a data value by using a dictionary
```javascript
let translated = Dict.translate(dict, '_cell_length_a', val[0])
translated.value // 1
translated.su // 1
```

The data structure of CIF objects conforms to [JSON representation of CIF information (DRAFT)](http://comcifs.github.io/cif-json.html)
```javascript
cif['CIF-JSON']['my_awesome_crystal']['_cell_length_a'][0] // '1.00(1)'
```

JSON.stringify
```javascript
let str = JSON.stringify(cif)
```

JSON.parse
```javascript
cif = JSON.parse(str, CIF.reviver)
cif instanceof CIF // true
```

### ESDoc documents
For more examples, see ESDoc documents:
```
cd node_modules/@kkitahara/cif-tools
npm install --only=dev
npm run doc
```
and open `doc/index.html` in your browser.

## Deviations from specs
- CIF 1.1 ([specification](https://www.iucr.org/resources/cif/spec/version1.1))
  - A \<WhiteSpace\> is inserted before the first \<value\> of \<LoopBody\>,
    otherwise the first \<value\> cannot be distinguished from the last \<Tag\>
    in loops by the lexer.
- CIF 2.0 ([specification](https://doi.org/10.1107/S1600576715021871))
  - Sequences [wspace], [comment] appear in the productions CIF2-file
    and wspace-data-value are replaced by [wspace [comment]],
    otherwise comments can follow the preceding token without any white spaces.
  - The specification does not mention the uniqueness of table keys.
    As for the CIF-JSON object, the keys must be unique.
    Therefore, the uniqueness (case sensitive manner) of the keys
    is required in this software.

## LICENSE
&copy; 2019 Koichi Kitahara  
[Apache 2.0](LICENSE)
