APPENDIX D Interchange File Format (IFF) 1.3
The Interchange File Format (IFF) is a binary file with an AmigaOS chunk structure (like IFF-ILBM, AIFF, etc). All chunks are optional (with the exception of the first one) and the structure is totally expandable. Use this powerful format if you want store the maximum number of information when you are using the VEGA OpenGL and VEGA ZZ.
Conventions for numeric formats:
Type |
Size (bit) |
Description |
BYTE |
8 |
Byte integer. |
UBYTE |
8 |
Unsigned byte integer. |
WORD | 16 |
Two byte integer. |
UWORD |
16 |
Two byte unsigned intege. |
LONG |
32 |
Four byte integer. |
ULONG |
32 |
Four byte unsigned integer. |
DLONG | 64 |
Eight byte integer. |
UDLONG | 64 | Eight byte unsigned integer. |
FLOAT |
32 |
Single precision IEEE float (4 bytes). |
DOUBLE |
64 |
Double precision IEEE float (8 bytes). |
The IFF files are in big endian format and so if the hardware doesn’t
support it (e.g. x86 CPUs),
you must invert the byte order when write the numbers.
The RIFF (Resource Interchange File Format) are the same one but they are in
little endian format and they are supported starting from VEGA ZZ 2.0.6 and VEGA
1.5.6.
A chunk is a data block with a 8 byte header.
Chunk {
HEADER (8 bytes)
Data
}
The first 4 bytes are a string that identify the chunk type and the last 4 bytes (an ULONG) are the size of Data block, as shown in the following C structure:
typedef struct {
UBYTE Hdr[4]
ULONG Size
} HEADER;
IFF file structure:
IFF_File {
HEADER {
"FORM",
4 + sizeof(Chunk_1) + sizeof(Chunk_1) +
+ sizeof(Chunk_N)
}
"MOLE"
Chunk_1
Chunk_2
Chunk_N
}
All IFF files are a sequence of chunks with a 8 bytes standard. The
recognition string (Hdr field) is FORM and the Size field contains
the size of all chunks and the size of subformat recognition header (8 bytes). The IFF is
a family of binary files that can store a variety of data like audio, image, video and
molecule. To recognize the subformat you must read the next 8 byte header. This second
header has the sub-recognition string MOLE and the size field with the value of the
size of all data chunks.
If the file is in little endian format, the main chunk starts with the RIFF
string instead of FORM.
ATOM Atom name chunk:
ATOM {
HEADER {
"ATOM",
4 + 2 * TotAtm
}
ULONG TotAtm
UBYTE Element[2][TotAtm]
}
This is the only non-optional chunk. TotAtm is the total number of atoms stored in the file. Element is a two byte matrix that contains the chemical element name for each atom. If the element name has the size of one character (e.g. H, C, O, S, etc), the second byte must be a space. For the chlorine benzene (C6H5Cl, 12 atoms) molecule the ATOM chunk must be:
ATOM {
HEADER {
"ATOM",
24,
}
"C ", "C ", "C ", "C ", "C
",
"H ", "H ", "H ", "H ",
"Cl"
}
XYZ1 Single precision cartesian coordinate chunk:
XYZ1 {
HEADER {
"XYZ1",
TotAtm * 12
}
XYZ[TotAtm] {
FLOAT x
FLOAT y
FLOAT z
}
}
This chunk contains reported the Cartesian coordinates for each atom in single precision floating-point format. This chunk and the XYZ2 could be present more than on time if the IFF file is a MD trajectory. For benzene (C6H6) this chunk can be:
XYZ1 {
HEADER {
"XYZ1",
144
}
XYZ {
{ 0.695, 1.203, 0.000 },
{-0.695, 1.203, -0.002 },
{-1.389, 0.000, -0.006 },
{-0.695, -1.203, -0.007 },
{ 0.695, -1.203, -0.006 },
{ 1.389, 0.000, -0.002 },
{ 1.235, 2.139, 0.003 },
{-1.235, 2.139, -0.001 },
{-2.470, 0.000, -0.007 },
{-1.235, -2.139, -0.010 },
{ 1.235, -2.139, -0.007 },
{ 2.470, 0.000, -0.001 }
}
}
XYZ2 Double precision Cartesian coordinate chunk:
XYZ2 {
HEADER {
"XYZ1",
TotAtm * 24
}
XYZ[TotAtm] {
DOUBLE x
DOUBLE y
DOUBLE z
}
}
This chunk is very similar to XYZ1, but the coordinates are stored in double precision floating point format.
CONX Connectivity chunk:
CONX {
HEADER {
"CONX",
TotBond * 9
}
ULONG TotBond;
CONN[TotBond] {
ULONG Atom1
ULONG Atom2
UBYTE BondOrder
}
}
This chunk is needed to indicate the connectivity between pairs of atoms. TotBond is the number of bonds, Atom1 and Atom2 is the pair of connected atom and BondOrder specifies the bond order that can be 1 (single bond), 2 (double bond), 3 (triple bond) and 4 (partial double bond).
IIUB IUPAC IUB atom name chunk:
IIUB {
HEADER {
"IIUB",
TotAtm * IUB_Len
}
UBYTE IUB_Len
UBYTE Name[IUB_Len][TotAtm]
}
In this chunk you can find the IUPAC IUB atom names. IUB_Len is the length of Name record.
CALC Potential and atomic charges chunk:
CALC {
HEADER {
"CALC",
18 + sizeof(ForceFieldName[ ]) + TotAtm * (4 +
ATPY_Len)
}
UBYTE ForceFieldName[ ]
HEADER {
"CHRG",
TotAtm * 4
}
FLOAT AtmCharge[TotAtm]
HEADER {
"ATYP",
TotAtm * ATPY_Len
}
UBYTE ATPY_Len
UBYTE AtmType[ATPY_Len][TotAtm]
}
This is a complex chunk that contains the atom type and the atomic charge for each atom. In this chunk are present two sub-chunk: CHRG and ATYP. The first includes the atomic charges in single precision format (AtmCharge). The second is the potential (atom type) chunk. ATPY_Len is the size (in bytes) of each potential record. At the present time, the default value is 8.
FIXA Atom constraints chunk:
FIXA {
HEADER {
"FIXA",
TotAtm
}
FLOAT FixValue[TotAtm]
}
This chunk contains the atom constraint values useful for the molecular dynamics simulations. Each value is a positive floating point number usually ranged from 0 (free) to 1 (fix).
RESI Residue name, residue number and chain identification chunk:
RESI
{
HEADER {
"RESI",
TotRes *
13
}
RESDATA[TotRes] {
ULONG Atoms
UBYTE ResName[4]
UBYTE ResNum[4]
UBYTE ChainID
}
}
TotRes is the total number of residues, Atoms is the number of atoms in the residue, ResName is the residue name, ResNum is the residue number and ChainID is the chain indicator. ChainID contains the chain identification character or a null value.
RSNU Residue number chunk (obsolete):
RSNU {
HEADER {
"RSNU",
TotAtm * 4
}
UBYTE ResNum[4][TotAtm]
}
It's the residue number for each atom. The number ResNum is a four character string, because in this way you can include the chain indicator (e.g. "99 A"). It was maintained for backward compatibility only. You should use the new RESI chunk.
RSNA Residue name chunk (obsolete):
RSNA {
HEADER {
"RSNA",
TotRes * 4
}
UWORD TotRes
RESNAME[TotRes] {
UBYTE ResNum[4]
UBYTE ResName[4]
}
}
This chunk is useful to translate the residue number ResNum into residue name ResName. TotRes is the total number of residue in the file. It was maintained for backward compatibility only. You should use the new RESI chunk.
SEGM Segments chunk:
SEGM {
HEADER {
"SEGM",
TotSeg * 4
}
ULONG AtmNum[TotSeg]
}
This chunk is equivalent to the TER record in PDB file format. TotSeg is the total number of segments in the file and AtmNum in an array containing the atom numbers that indicate the end of each segment.
MOLN Name of the molecules chunk:
MOLN {
HEADER {
"MOLN",
sizeof(MOLNAME[ ])
}
UWORD TotMol
MOLNAME[TotMol] {
ULONG AtmStart
ULONG AtmNum
UBYTE MolName[ ]
}
}
The IFF file format can include more than one molecule. TotMol is the total number of molecules, AtmStart is the first atom number of the molecule, AtmNum is the number of atoms in the selected molecule and MolName is a c-string (null terminated) for the molecule name.
COMM Remark chunk:
COMM {
HEADER {
"COMM",
1 + sizeof(Remark[ ])
}
UBYTE Remark[ ]
}
In this chunk, you can include a remark.
SRFA - Surface atom number chunk
SRFA {
HEADER {
"SRFA",
Points * 4
}
ULONG AtmNum[Points]
}
It stores the atom number for each surface point. This chunk requires the SURF chunk before it.
SRC3 - Surface color chunk (24 bit)
SRC3 {
HEADER {
"SRC3",
Points * 3
}
DOTCOLOR[Points] {
UBYTE R
UBYTE G
UBYTE B
}
}
This chunk contains the color for each surface point in RGB format (24 bit), where R is the red component , G is the green component and B is the blue component. All these parameters have got the value range from 0 to 255. This is the chunk written by VEGA ZZ. You can use both version of this chunk (SRC3 and SRFC) preferring the SRC3 if the alpha information isn't required.
SRFC - Surface color chunk (32 bit)
SRF
C {This chunk contains the color for each surface point in ARGB format, where A is the alpha key, R is the red component , G is the green component and B is the blue component. All these parameters have got the value range from 0 to 255.
SRFF - Surface face chunk
SRFF {
HEADER {
"SRFF",
NumVertexID * Size + 1
}
UBYTE Size
UBYTE (or UWORD, or
ULONG) VertexIDArray[NumVertexID]
}
This chunk contains the surface faces as triplets of vertex IDs. The vertex ID is a positive integer number that indicates the surface dot (see SURF chunk) used to define one face (triangle) vertex. The vertex IDs can be stored in the formats defined by the Size byte: UBYTE (Size = 1), UWORD (Size = 2) and ULONG (Size = 3). The three formats are able to store until 256, 65536 and 4294967296 vertex IDs.
SRFV - Surface value chunk
SRFV {
HEADER {
"SRFV",
Points * 4
}
FLOAT Value[Points]
}
It contains the associated value for each surface dot.
SRFI - Surface information chunk
SRFI {
HEADER {
"SRFI",
LenOfSrfName + 16
}
UBYTE LenOfSrfName
UBYTE SrfName[LenOfSrfName]
LONG Flags
UBYTE SrfType
UBYTE Alpha
UBYTE DotSize
ULONG Reserved1
ULONG Reserved2
}
If you want add extra information to the surface file, you can use this chunk in which SrfName is the surface name, LenOfSrfName is the length of the surface name (max. 255 characters), Flags are the special surface flags (click here for more information), SrfType is the surface type (click here for more information), Alpha is the alpha blending value (0 full transparent, 255 full opaque) and DotSize is the dot size used to show the dotted surface. LenOfSrfName can be zero, but in this case SrfName mustn't present in the chunk. Reserved1 and Reserved2 are for future use.
SRFN - Surface normal chunk
SRFN {
HEADER {
"SRFN",
Points * 6
}
XYZ[Points] {
WORD x
WORD y
WORD z
}
}
This optional chunk is the list of normal vectors for each surface point. It's used by VEGA ZZ to store the data for the lighting engine without recalculating all normals of a solid surface. If the surface is dotted, this chunk is ignored. The normals, which values are in the -1.0 to 1.0 range, are stored in low precision integer format. When you want put the normals in the chunk, you must multiply each coordinate by 32767 and thus you must take the integer part. To return in the floating point format, you must divide the coordinates by 32767 and make the casting to float. In this way you can obtain a good precision using half of disk space.
SURF - Generic surface chunk:
SURF {
HEADER {
"SURF",
Points * 12
}
XYZ[Points] {
FLOAT x
FLOAT y
FLOAT z
}
}
This chunk contains the Cartesian coordinates of each surface point. Points is the number of surface points. The IFF format allows more than one surfaces and so one or more SURF chunk can be present in the file. Please remember that this chunk must written before all other surfaces chunk otherwise they will be ignored. All other surface chunk are optional.
VERS - Version chunk:
VERS
{The chunk contains the file version number organized in two 16 bit words: the higher word is the version and the lower word is the revision.
Special VEGA chunks:
VGAB - Active atom chunk:
VGAB {
HEADER {
"VGAB",
(TotAtm / 8) + 1
}
UBYTE Active[(TotAtm / 8) + 1]
}
It defines if the atom is active or not (visible or not). The boolean values are stored in a bitmap in order to reduce the size and so this chunk is eight time smaller then the VGAC. If a bit is true (1), the atom is active, otherwise if it's false (0), the atom is inactive. To encode/decode this chunk, you can use the routines at the end of this document.
VGAC - Active atom chunk (obsolete):
VGAC {
HEADER {
"VGAC",
TotAtm
}
UBYTE Active[TotAtm]
}
It defines if the atom is active or not (visible or not). If an array item is true (1), the atom will be active, otherwise if it's false (0), the atom will be inactive. This chunk is obsolete and it's replaced by VGAB chunk.
VGCL - Color chunk:
VGCL {
HEADER {
"VGCL",
TotAtm
}
UBYTE ColorID[TotAtm]
}
It stores the color of each atom with the VEGA color code. See below for all color codes.
VGDM - Draw mode chunk:
VGDM {
HEADER {
"VGDM",
TotAtm
}
UBYTE DrawMode[TotAtm]
}
It stores the information about the draw mode for each atom. Starting from VEGA ZZ 2.0.0 it's possible to change the display mode to each atom. See below for the draw modes.
VGLB - Label chunk:
VGLB {
HEADER {
"VGLB",
TotAtm
}
UBYTE Label[TotAtm]
}
This chunk stores the label of each atom. See below for label codes.
VGMO - Monitor chunk:
VGLB {
HEADER {
"VGMO",
The size can't be pre-computed
}
MONITOR[TotMon] {
UBYTE MonType
IF (MonType != 0x10) {
ULONG
AtmNum[MonType & 0xf]
} ELSE {
UBYTE
LblLen
BYTE
Label[LblLen]
}
}
}
This chunk contains the information for the monitors. The MonType byte is the monitor type as reported in the following table:
MonType |
Description |
0x02 |
Distance. |
0x03 | Angle. |
0x04 | Torsion. |
0x06 | Angle between two planes. |
0x10 | H-bond label. |
0x12 | H-bond. |
AtmNum is the array of atom numbers defining the monitor and its size can be obtained by MonType AND (logical operator) 0xf (16). If MonType is 0x10, the AtmNum array is replaced by the LblLen unsigned byte and Label byte array containing the H-bond label.
VGAC - Atom activation chunk:
VGAC {
HEADER {
"VGAC",
TotAtm
}
UBYTE Active[TotAtm]
}
For each atom is stored the activation state: if it's 1 (true) the atom is visible, otherwise if it's 0 (false) the atom is invisible.
VGTR - Transformation chunk:
VGAC {
HEADER {
"VGTR",
TotAtm
}
FLOAT PosX
FLOAT PosY
FLOAT PosZ
FLOAT RotStepX
FLOAT RotStepY
FLOAT RotStepZ
FLOAT PosStepX
FLOAT PosStepY
FLOAT PosStepZ
FLOAT Scale
FLOAT RotMat[4][4]
}
This chunk is only for private use and stores the current view settings of VEGA.
C subroutines and definitions:
In order to simplify the C programming, some useful definitions and subroutines are reported:
/**** VEGA atom label definitions ****/
#define VG_ATMLBL_NONE
0
#define VG_ATMLBL_NAME 1
#define VG_ATMLBL_ELEMENT 2
#define VG_ATMLBL_NUMBER 3
#define VG_ATMLBL_TYPE 4
#define VG_ATMLBL_CHARGE 5
#define VG_ATMLBL_FIX 6
#define VG_ATMLBL_RESNAMESEQ 7
#define VG_ATMLBL_RESNAME 8
#define VG_ATMLBL_RESSEQ 9
/**** VEGA color definitions ****/
#define VGCOL_NONE
0
#define VGCOL_BLACK 1
#define VGCOL_WHITE 2
#define VGCOL_RED
3
#define VGCOL_GREEN 4
#define VGCOL_CYAN 5
#define VGCOL_YELLOW 6
#define VGCOL_FIREBIRCK 7
#define VGCOL_MAGENTA 8
#define VGCOL_PINK 9
#define VGCOL_VIOLET 10
#define VGCOL_GRAY 11
#define VGCOL_ORANGE 12
#define VGCOL_DARKGREEN 13
#define VGCOL_BLUE 14
#define VGCOL_DARKYELLOW 15
#define VGCOL_BROWN 16
#define VGCOL_SKYBLUE 17
#define VGCOL_DARKGRAY 18
#define VGCOL_GHOSTPINK 19
#define VGCOL_GHOSTGREEN 20
#define VGCOL_GHOSTBLUE 21
#define VGCOL_GHOSTYELLOW 22
#define VGCOL_GHOSTGRAY 23
#define VGCOL_SAND 24
/**** Draw modes ****/
#define VG_ATMD_WIREFRAME 0 /* Vectors only
*/
#define VG_ATMD_CPK_DOTTED 1 /* CPK/Van der Waals dotted
*/
#define VG_ATMD_CPK_WIRE 2 /* CPK/Van der Waals wireframe */
#define VG_ATMD_CPK_SOLID 3 /* CPK/Van der Waals solid
*/
#define VG_ATMD_BALL_WIRE 4 /* Ball & stick wireframe
*/
#define VG_ATMD_BALL_SOLID 5 /* Ball & stick solid
*/
#define VG_ATMD_SICK_WIRE 7 /* Stick wireframe
*/
#define VG_ATMD_SICK_SOLID 8 /* Stick solid
*/
#define VG_ATMD_TUBE_SOLID 8 /* Tube solid
*/
#define VG_ATMD_TRACE_SOLID 9 /* Trace solid
*/
/**** Surface
Flags (see SRFI chunk) ****/
#define VG_SRFF_NONE 0
/* None
*/
#define VG_SRFF_ACTIVE 1 /* The surface is visible
*/
#define VG_SRFF_ALPHA 2 /* Enable the alpha blending
*/
/**** Surface types ****/
#define VG_SRFT_DOTTED 0 /*
Dotted
surface
*/
#define VG_SRFT_MESH 1 /* Mesh
surface
*/
#define VG_SRFT_SOLID 2 /*
Solid
surface
*/
/**** Types ****/
typedef char
BYTE;
typedef unsigned char UBYTE;
typedef int
LONG;
typedef unsigned int ULONG;
typedef short WORD;
typedef unsigned short UWORD;
typedef float FLOAT;
typedef double DOUBLE;
/*** IFF Chunk header ****/
typedef struct {
char Hdr[4];
ULONG Size;
} IFFHDR;
/**** Prototypes ****/
void SwapW(void *);
void SwapL(void *);
void SwapD(void *);
/**** Change the endian for WORD and UWORD ****/
void SwapW(register void *Val)
{
register UBYTE T;
T = ((UBYTE *)Val)[0];
((UBYTE *)Val)[0] = ((UBYTE *)Val)[1];
((UBYTE *)Val)[1] = T;
}
/**** Change endian for LONG, ULONG and FLOAT ****/
void SwapL(register void *Val)
{
register UBYTE T;
T = ((UBYTE *)Val)[0];
((UBYTE *)Val)[0] = ((UBYTE *)Val)[3];
((UBYTE *)Val)[3] = T;
T = ((UBYTE *)Val)[1];
((UBYTE *)Val)[1] = ((UBYTE *)Val)[2];
((UBYTE *)Val)[2] = T;
}
/**** Change the endian for DOUBLE ****/
void SwapD(void *Val)
{
register UBYTE T;
T = ((UBYTE *)Val)[0];
((UBYTE *)Val)[0] = ((UBYTE *)Val)[7];
((UBYTE *)Val)[7] = T;
T = ((UBYTE *)Val)[1];
((UBYTE *)Val)[1] = ((UBYTE *)Val)[6];
((UBYTE *)Val)[6] = T;
T = ((UBYTE *)Val)[2];
((UBYTE *)Val)[2] = ((UBYTE *)Val)[5];
((UBYTE *)Val)[5] = T;
T = ((UBYTE *)Val)[3];
((UBYTE *)Val)[3] = ((UBYTE *)Val)[4];
((UBYTE *)Val)[4] = T;
}
/**** Encode the active atom into the bitmap ****/
/*
* Active -> An array of unsigned bytes from which the boolean values
* are packed.
* TotAtm -> Number of atom in the IFF file.
*
* The returned value is the pointer of the bitmap that can be saved
* directly in the IFF file.
*/
UBYTE *EncodeActiveAtm(UBYTE *Active, ULONG TotAtm)
{
UBYTE
*PtrMtx;
UBYTE
Bit;
UBYTE
*Bitmap;
ULONG
i;
if ((Bitmap = (BYTE *)calloc(1, (TotAtm >> 3) + 1)) != NULL) {
PtrMtx = Bitmap;
Bit = 1;
for(i = 0; i < TotAtm; ++i) {
if (Active[i])
*PtrMtx |= Bit;
if (Bit == 128) {
Bit = 1;
++PtrMtx;
} else Bit <<= 1;
} /* End of for */
}
return Bitmap;
}
/**** Decode the active atom from the bitmap ****/
/*
* Active -> An array of unsigned bytes in which the boolean values
* are
unpacked.
* Bitmap -> The bitmap pointer.
* TotAtm -> Number of atom in the IFF file.
*/
void PopActiveAtm(UBYTE *Active, UBYTE *Bitmap, ULONG TotAtm)
{
ULONG i;
UBYTE Bit = 1;
for(i = 0; i < TotAtm; ++i) {
Active[i] = ((*Bitmap & Bit) != 0);
if (Bit == 128) {
Bit = 1;
++Bitmap;
} else Bit <<= 1;
} /* End of for */
}