Package cif

import "github.com/BurntSushi/cif"
Overview
Index
Examples

Overview ▾

Package cif provides a reader and a writer for the Crystallographic Information File (CIF) format. This package corresponds (almost) exactly to version 1.1 of the CIF specification: http://www.iucr.org/resources/cif/spec/version1.1/cifsyntax

This package should conform to the entirety of the specification, except it does not enforce maximum line length limits while reading or writing CIF files. This behavior may be changed in the future.

type Block

type Block struct {
    // The name of this block.
    Name string

    // Items maps data tags to values. Data tags that are part of a "loop_"
    // declaration are not included here.
    Items map[string]Value

    // Loops maps data tags to tables defined by a "loop_" declaration. Namely,
    // each data tag in a "loop_" maps to precisely the same loop object.
    // For example, if a "loop_" introduces the data tag "_cats" with values
    // "Cauchy" and "Plato", then the following code accesses that list of
    // cats:
    //
    //	loop := someBlock.Loops["cats"]
    //	cats := loop.Get("cats").Strings()
    //
    // Notice that the key "cats" is used twice. The first time it's used to
    // get the loop object, while the second time its used is to get the
    // actual column of data.
    Loops map[string]*Loop
}

Block represents the structure of any block-like section in a CIF file. It corresponds either to a data block or a save frame.

type CIF

type CIF struct {
    // Version, when present in the source file, contains the version of the
    // specification that the file was generated for. e.g., "CIF_1.1".
    Version string

    // Blocks maps data block names to corresponding data blocks.
    // Note that all data block names are stored in lowercase.
    Blocks map[string]*DataBlock
}

CIF represents an entire CIF file.

func Read

func Read(r io.Reader) (*CIF, error)

Read reads CIF formatted input and returns a CIF value if and only if the input conforms to the CIF 1.1 specification.

Example

Code:

data := `#\\#CIF_1.1
data_1CTF
_entry.id  1CTF
loop_
_entity_poly_seq.num 
_entity_poly_seq.mon_id 
1  ALA
2  ALA
3  GLU
4  GLU
5  LYS
`
cif, err := Read(strings.NewReader(data))
if err != nil {
    log.Fatal(err)
}

block := cif.Blocks["1ctf"] // all items are stored in lowercase
fmt.Printf("%s\n", block.Name)

// You can retrieve a loop by using any of the data tags defined in
// the loop.
loop := block.Loops["entity_poly_seq.num"]

// While using the same key twice may seem redundant, this approach
// guarantees that you're selecting values from precisely the same table.
// Also, loop.Get is guaranteed to return a []string, []int or []float64.
seqNums := loop.Get("entity_poly_seq.num").Ints()
residues := loop.Get("entity_poly_seq.mon_id").Strings()

// If the access methods fail, then nil is returned.
if seqNums == nil {
    log.Fatal("Could not read sequence numbers as integers.")
}
if residues == nil {
    log.Fatal("Could not read residues as strings.")
}

// All columns in a table are guaranteed by Read to have the same length.
for i := 0; i < len(seqNums); i++ {
    fmt.Printf("%d %s\n", seqNums[i], residues[i])
}

Output:

1ctf
1 ALA
2 ALA
3 GLU
4 GLU
5 LYS

func (*CIF) Write

func (cif *CIF) Write(w io.Writer) error

Write writes an existing CIF to the writer given. It is appropriate to read a CIF with Read, modify it in place, and then call Write. Note that Write does not currently impose an ordering on the data items written (except for the columns in a table).

type DataBlock

type DataBlock struct {
    // The name and data items are stored in a block.
    Block

    // Frames maps save frame names to corresponding save frames.
    // Note that all save frame names are stored in lowercase.
    Frames map[string]*SaveFrame
}

DataBlock represents a data block in a CIF file.

type Loop

type Loop struct {
    // Columns maps data tag names to their position in the table (starting
    // at 0).
    Columns map[string]int

    // Values corresponds to the columns of data in the table. Namely, each
    // ValueLoop is a single column of data.
    Values []ValueLoop
}

Loop represents a single table of data within a block.

func (*Loop) Get

func (lp *Loop) Get(name string) ValueLoop

Get is a convenience method for retrieving a column of data corresponding to the data tag given in a particular block.

The underlying type of ValueLoop is guaranteed to be []string, []int or []float64. See the documentation for ValueLoop for more details.

Note that all data tags are stored in lowercase.

type SaveFrame

type SaveFrame struct {
    // The name and data items are stored in a block.
    Block
}

SaveFrame represents a save frame in a CIF file.

type Value

type Value interface {
    // String returns this value as a string. If its underlying type is
    // numeric, then 0 is returned.
    String() string

    // Int returns this value as an integer. If its underlying type is
    // a float, then an int conversion is performed (which may fail).
    // If its underlying type is a string, then the empty string is returned.
    Int() int

    // Float returns this value as a float64. If its underlying type is
    // an integer, then it is converted to a float.
    // If its underlying type is a string, then the empty string is returned.
    Float() float64

    // Raw provides the underlying string, int or float64 value. The interface
    // returned may be used in a type switch.
    // (A Value itself is not amenable to type switching, since the types that
    // satisfy it in this package are not exported.)
    Raw() interface{}
}

func AsValue

func AsValue(v interface{}) Value

AsValue returns a value that satisfies the Value interface if v has type string, int or float. If v has any other type, this function will panic.

This function should only be used when constructing values for writing CIF data.

type ValueLoop

type ValueLoop interface {
    // Strings returns this value as a []string. If its underlying type is
    // not []string, then it is converted to a string and returned.
    Strings() []string

    // Ints returns this value as a []int. If its underlying type is
    // not []int, then nil is returned.
    Ints() []int

    // Floats returns this value as a []float64. If its underlying type is
    // []int, then a new slice is returned with the integers converted to
    // floats. If its underlying type is []string, then nil is returned.
    Floats() []float64

    // Raw provides the underlying []string, []int or []float64 value. The
    // interface returned may be used in a type switch.
    // (A ValueLoop itself is not amenable to type switching, since the types
    // that satisfy it in this package are not exported.)
    Raw() interface{}
}

ValueLoop denotes a single column of data in a table. Its underlying type is guaranteed to be []string, []int or []float64.

Note that []int and []float64 are only used when the column can be interpreted as a homogenous array of data (containing all integers, all floats or a mixture of integers and floats where all integers are converted to floats). If any other type of value is found in the column, then all values are represented as strings.

func AsValues

func AsValues(v interface{}) ValueLoop

AsValues returns a value that satisfies the ValueLoop interface if v has type []string, []int or []float. If v has any other type, this function will panic.

This function should only be used when constructing values for writing CIF data.