MTZLIB (CCP4: Library)

NAME

mtzlib - Software Library for Reflection data file handling

CONTENTS

  1. DESCRIPTION
  2. FORTRAN API
  3. ORIENTATION BLOCK DATA FOR MULTI-RECORD FILES
  4. EXAMPLE PROGRAM USING AN MTZ FILE
  5. AUTHORS AND HISTORY

DESCRIPTION

See separate document for a description of the MTZ file format.

From CCP4 5.0, the core reading/writing/modifying of MTZ reflection data files is done by a set of C functions. Separate documentation describes the structures and functions used, and the API for C/C++ programs.

For Fortran programs, the original set of subroutines (held in mtzlib.f) has been replaced by an interface to the C library. From the point of view of an application programmer, this interface should be identical to the original set of subroutines. This document originates from the original Fortran library, but should be applicable to the new library.

The first argument to all the Fortran calls in MTZLIB is MINDX. This mechanism allows more than one pair of MTZ files to be open for read and write at the same time, without the need for separate subroutines. At present a maximum of 8 files can be opened simultaneously (4 for read and 4 for write), but this could be increased easily.

In the interface functions, the MINDX parameter acts as an index to several static arrays, including one that contains pointers to MTZ data structures. This mimics the use of COMMON blocks in the original Fortran library, and means that when an input file has been opened the header information is available for writing to an output file, without being explicitly copied by the calling program. This information may be replaced or new information may be added depending on the requirements of the output file or it may be created if no input file was read.

FORTRAN API

The following Fortran calls are available. Note that this documentation originates from the original Fortran library, and may be out-of-date in some details.

The initialisation routine for the file handling system

MTZINI
This MUST be called first

Subroutines for reading an MTZ file

LROPEN
Open MTZ file for read
LRASSN
Set up the input column assignments
LRBATS
Return the number of batches present and their serial numbers from the MTZ header (for multi-record files)
LRBRES
Reset batch header reading pointer
LRCELL
Deprecated - use specific dataset cell obtained from LRIDX
LRCLAB
Return the Column labels and types from the MTZ header
LRHIST
Returns history information from the MTZ header
LRINFO
Return general info (number of columns etc.) from the MTZ header
LRNCOL
Returns number of columns from the MTZ header
LRRSOL
Return the minimum and maximum resolution from the MTZ header (1/d**2)
LRSORT
Return the sort order from the MTZ header
LRSYMI
Return symmetry information (if available) from the MTZ header
LRSYMM
Return symmetry operations (if available) from the MTZ header
LRTITL
Return the title from the MTZ header
LRREFL
Read a reflection record in file order from the MTZ file
LRREFF
Read a reflection record in Lookup order from the MTZ file
LRNREF
Return the number of the reflection record last read (i.e. the current position in the file)
LRSEEK
Move to a specific reflection record number
LRREWD
Rewind an MTZ file for re-read
LRCLOS
Close an MTZ file which has been opened for read

Subroutines for writing an MTZ file

LWOPEN
Open MTZ file for write
LWASSN
Set up the output column assignments, new columns etc.
LWCELL
Update the Cell dimensions in the MTZ header
LWCLAB
Write Column labels and types to an output MTZ file
LWHIST
Append to the history information in the MTZ header
LWHSTL
Simple way of appending standard history line
LWSORT
Update the Sort order in the MTZ header
LWSYMM
Update the Symmetry operation in the MTZ header
LWTITL
Append to or replace the title in the MTZ header
LWREFL
Write a reflection record to the MTZ file
LWCLOS
Close an MTZ file which has been opened for write

Subroutines for multi-record MTZ files

LRBAT
Return batch information from the header for one batch
LWBAT
Write updated batch header for one batch
LRBSCL
Return selected values from the header for one batch
LRBTIT
Return the batch title from the header for one batch
LWBTIT
Write batch title and dummy orientation block for one batch
LWBSCL
Update selected values in the header for one batch
LBPRT
Print batch information in pretty format - called by LRBAT - calls LBPRTH (does the actual print)

Subroutines for handling Missing Number Flags

EQUAL_MAGIC
Initialises an array so all elements are set to MNF
IS_MAGIC
Routine that checks any datum to see if datum=MNF
RESET_MAGIC
Alters the MNF per reflection in the data itself
SET_MAGIC
Either returns the value of MNF in the MTZ header or overwrites it.
LRREFM
Returns a logical array identifying which data of a reflection=MNF

Subroutines for handling Dataset Information

LRIDX
Subroutine to return information for all datasets from the MTZ file header, including crystal names.
LRIDC
Deprecated - use LRIDX.
LRID
Deprecated - use LRIDX.
LWIDX
Subroutine to add dataset information to the output MTZ file header, including crystal names.
LWIDC
Deprecated - use LWIDX.
LWID
Deprecated - use LWIDX.
LRCLID
Subroutine to return the ID of the related dataset for each column of the input MTZ file, as obtained from the header.
LWIDASX
Subroutine to associate dataset entry with each column for the output MTZ file.
LWIDAS
Deprecated - use LWIDASX.
LRBSETID
Subroutine to read dataset ID for batch BATNO from batch headers for multi-record file open on index MINDX.
LWBSETIDX
Subroutine to write dataset ID for batch BATNO to batch headers for multi-record file open on index MINDX.
LWBSETID
Deprecated - use LWBSETIDX.

Utility subroutines

LKYIN
Used to parse any label assignments (input and output) made by the user
LKYSET
Similar to LKYIN except the lookup array is passed back to the program
LKYOUT
parse any label assignments (input and output) made by the user
LKYASN
Jiffy to call LKYIN and LRASSN, no need for parser in main program
LHPRT
Subroutine to output data from an MTZ header
LPHIST
Prints history information from the MTZ header

Internal routines

There are 13 more subroutines which are internal to the package and are included here for completeness, but should not be called by the user program:
RBATHD
read the actual header from the file and return the data items packed into a REAL and a CHAR array - called by LROPEN
WBATHD
write the batch headers to the MTZ file open for write the batch headers are written at the end of the file - called by LWCLOS
LRHDRL
read one line from the header on the file (calls qread)
LBPRTH
does the actual printing for LBPRT
LABPRT
Subroutine used to output character strings (e.g. column labels) nicely across 80 character page
SORTUP
INTEGER version of indexed Singleton sort - copied from STILLS program.
ADDLIN
Subroutine to add a new line to a character array
NEXTLN
Function to find the next empty line in a character array
LSTRSL
Routine to calculate coefficients for (sin(theta)/lambda)**2 from h,k,l for general axes
LSTLSQ
Function to calculate (sin(theta)/lambda)**2 from h,k,l coefficients set by call to LSTRSL, for the file open on index MINDX

Subroutine MTZINI

This Subroutine initialises the MTZ file handling system.

This subroutine must be called before any other mtzlib subroutine. Failure to do so may result in unpredictable behaviour.

Subroutine LROPEN(MINDX,FILNAM,IPRINT,IFAIL)

Subroutine to open an MTZ file for read. This should be the first MTZ subroutine called in a set of operations on a pair of files (i.e. one input and one output). The subroutine zeros all the Header COMMON block entries, opens the specified file and loads the header into the COMMONs, and positions the file ready to read the first data record.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
FILNAM (I) CHARACTER*(*)
name of file to be opened
IPRINT (I) INTEGER
print indicator:
=0
No MTZ info printed at all
=1
Brief header info printed (default)
=2
as above plus history info
=3
Full header dump; symmetry
any other value; nothing happens
IFAIL (O) INTEGER
error indicator: meaning: on output
=0
OK
=-1
no such file
all other errors cause stop
LROPEN calls the following which are external to MTZLIB:

External Functions: INTEGER LENSTR
External Subroutines: BLANK,GTPINT,GTPREA,LERROR,PARSER,PUTLIN,QOPEN,
QSEEK,QMODE,QREAD,SYMFR3

Function:

Subroutine LROPEN checks that nothing is already open for required index
If it is continue, but print warning
If already open for read, then probably forgot to call LRCLOS from a previous file
If already open for write, then programmer hasn't read manual - ie has called LWOPEN on this index before LROPEN
If already open for read and write then the program stops
Then opens the file and record the stream
CALL QOPEN(IUNIN,FILNAM,'READONLY')
CALL QMODE(IUNIN,2,NITEM)
Then Zero the header arrays etc.
Read the 1st record of the file, check it's an MTZ file, and go to the start of the header records - first record of file contains the offset in the file of the start of the header records. Put this offset into a call to QSEEK ( CALL QSEEK(RLUN(INDEX),1,HDRST(INDEX),1)) to position file at start of headers.
Then reads and parses the header, and load COMMON blocks
Passing header line to MRC parser:
CALL PARSER(KEY,LINE,IBEG,IEND,ITYP,FVALUE,CVALUE,
+ IDEC,NTOK,LEND,.FALSE.)
and loops over possible keywords

 
 
VERS - version of routines which wrote the file 
       could test versions here in the future 
TITL - read file title 
NCOL - no. of cols and refls in file and batches in file 
       if no. of batches=0 then this is a standard file 
CELL - read in the Cell parameters 
SORT - read in sort order 
SYMI - various symmetry stuff 
SYMM - read in the symmetry cards and convert to matrices 
       If present then calls SYMFR3 
RESO - resolution limits for the file (1/d-squared) 
COLU - column labels, types and ranges 
BATC - batch serial numbers - hopefully only if nbatch >0 
END    of header card 
 

Ignores unrecognised lines.
If end of header reached, but no END card, print warning
Check no. of column cards input equals NCOLS from 1st line
Check correct number of symmetry cards
If NBATCH>0 prepare to read the batch headers
Loop over the rest of the header lines looking for MTZHIST or MTZBATS as keyword, and proceed accordingly.
Finally, hopefully hit the MTZENDOFHEADERS line.
Output information with CALL LHPRT(INDEX,IPRINT,IFAIL) (if IPRINT>0)
Finally positions the file ready to read reflection records with
CALL QSEEK(RLUN(INDEX),1,SIZE1+1,1),
where SIZE1 is the size of the first record in the file (which contained the offset).

Subroutine LRASSN(MINDX,LSPRGI,NLPRGI,LOOKUP,CTPRGI)

Subroutine to apply the input column label assignments to the MTZ file which is open for read and setup the Lookup pointer array

If the program is going to allow user input column assignments, then you MUST call subroutine LKYIN to parse these input label assignments, before LRASSN is called, as LKYIN sets up arrays which are then used by LRASSN.

Note that user input labels and file labels are case sensitive - the input label must match the file label exactly.

Also note that having an unassigned program label is a fatal error, but this subroutine uses LERROR to report this as a warning, so that all the program label assignments can be checked before stopping.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
LSPRGI (I) CHARACTER*30
array of dimension at least NLPRGI containing the program label strings
NLPRGI (I) INTEGER
number of input program labels
LOOKUP (I/O) INTEGER
array of dimension at least NLPRGI containing index from program labels to file labels. On input these should be set to -1 for compulsory labels, 1 for soft compulsory labels and 0 for optional labels, and on exit labels which are not present in the file have their lookup entry set to 0. Both types of compulsory label will be assigned automatically if the LSPRGI=MTZfile_label, so this status should be used carefully. If they are assigned explicitly (typically in the LABIN keyword) this overrides the above assignment. For compulsory labels (lookup=-1) it is an error if the labels are not assigned in the calling program. For soft compulsory and optional labels no error is given if they are not assigned to a column in the MTZ file.
CTPRGI (I) CHARACTER*1
array of dimension at least NLPRGI containing the program label types
LRASSN calls the following which are external to MTZLIB:

External Functions: INTEGER LENSTR
External Subroutines: BLANK,LERROR,PUTLIN

Function:

This subroutine references the internal COMMON Blocks /MTZLBC/ and /MTZLAB/ which are set up by LKYIN.
Rpoint is the same as lookup, but held in the MTZWRK COMMON work with this and copy to LOOKUP at the end, so set to 0.
Also store the number of program labels in MTZWRK, and the program labels in MTZWRC
First loop over user input labels (if any) and assign them to file labels.
Now loop over program labels for those not yet assigned
Copy RPOINT to LOOKUP
If we had some errors then return or stop now
Print out program labels, column labels and lookup
Check the column types if any given

Subroutine LRBATS(MINDX,NBATX,BATCHX)

Return the number of batches and their batch serial numbers from the header of a multi-record MTZ file

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
NBATX (I/O) INTEGER
On input, dimension of BATCHX; on exit number of batches in the file.
BATCHX (O) INTEGER
array of dimension at least NBATX containing the serial numbers of the batches in the file
LRBATS calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LRBRES (MINDX,BATNO)

Reset the batch header info pointer to the batch BATNO, for re-read by subroutine LRBAT, for an MTZ file which has been opened for read on index MINDX.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (I) INTEGER
batch number to reset pointer to If BATNO = 0, reset to beginning of batch headers.
LRBRES calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LRCELL(MINDX,CELLP)

Return Cell Parameters from header of MTZ file open for read on index MINDX

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
CELLP (O) REAL(6)
array of dimension (6) containing cell parameters from header on exit
LRCELL calls the following which are external to MTZLIB:
External Subroutines: LERROR

Subroutine LRCLAB(MINDX,CLABS,CTYPS,NCOL)

Return the column labels, column types and number of columns from the header of an MTZ file.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
CLABS (O) CHARACTER*30
array of dimension at least NCOL containing the column labels on exit
CTYPS (O) CHARACTER*1
array of dimension at least NCOL containing the column types on exit
NCOL (I/O) INTEGER
On entry the dimension of CLABS and CTYPS; on exit the number of columns in the MTZ file
LRCLAB calls the following which are external to MTZLIB:

External Functions : INTEGER LENSTR
External Subroutines: LERROR

Subroutine LRHIST(MINDX,HSTRNG,NLINES)

Return the history information from the MTZ file header.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
HSTRNG (O) CHARACTER*(*)
array of (NLINES) with the history lines
NLINES (I/O) INTEGER
On entry the dimension of HSTRNG; on exit the number of history lines being returned
LRHIST calls the following which are external to MTZLIB:

External Functions: INTEGER LENSTR
External Subroutines: LERROR

Subroutine LRINFO(MINDX,VERSNX,NCOLX,NREFLX,RANGES)

Return information about the MTZ file open for read on index MINDX.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
VERSNX (O) CHARACTER*10
version stamp of MTZ subroutines used to write the file
NCOLX (I/O) INTEGER
On entry, the last dimension of RANGES; on exit the number of columns in the file
NREFLX (O) INTEGER
number of reflection records in the file
RANGES (O) REAL
array(2,NCOLX) containing the minimum and maximum values in each column
LRINFO calls the following which are external to MTZLIB:
External Subroutines: LERROR

Subroutine LRNCOL(MINDX,NCOLX)

Return the number of columns in the MTZ file open for read on index MINDX. A simpler call than LRINFO.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
NCOLX (O) INTEGER
number of columns in MTZ file
LRNCOL calls the following which are external to MTZLIB:
External Subroutines: LERROR

Subroutine LRNREF(MINDX,REFNUM)

Return the current reflection number from an MTZ file opened for read. Files are normally read sequentially. The number returned is the number of the *NEXT* reflection record to be read. If you are going to jump about the file with LRSEEK then use this to record the current position before you start, so that it can be restored afterwards, if required.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file (up to MFILES possible open at once)
REFNUM (O) INTEGER
the reflection record number of the next reflection to be read
LRNREF calls the following which are external to MTZLIB:
External Subroutines: LERROR

Subroutine LRREFF(MINDX,RESOL,ADATA,EOF)

Subroutine to read a reflection record from an MTZ file which has been opened for read. This returns the record in `lookup' order (as set by LRASSN).

The subroutine also returns the resolution (1/d**2). The resolution is calculated from the indices H, K and L, and a set of cell dimensions. If the MTZ file contains columns from several crystals, then there is a choice of cell dimensions. The library uses the first crystal with non-zero cell dimensions. This will typically be the HKL_base crystal, which contains a copy of the cell dimensions of the first real crystal. Clearly if there are several different crystals in the MTZ file, the quoted resolution is somewhat arbitrary.

There is a kluge to handle the absence flags defined by the Groningen BIOMOL system: If the MINDX is larger then 1000, then it is assumed that the subroutine is called by a BIOMOL program or another program that is able to interpret the BIOMOL absence flags (e.g. a value of -1.0E+10 indicates absent data). If MINDX is in the normal range of 1 to 3, then the subroutine will convert values of -1.0E+10 to zero to allow normal processing by the CCP4 programs.

Arguments:

MINDX (I) INTEGER indicates which MTZ file - one index points to both input and output files

RESOL (O) REAL
resolution (4 * sin**theta/lambda**2).
ADATA (O) REAL
array of dimension at least NPLABS(MINDX) containing the reflection record on exit in lookup order
EOF (O) LOGICAL
End-of-File indicator
LRREFF calls the following which are external to MTZLIB:

External Subroutines: LERROR,QREAD

Function:

Check that there is a file open
Everything OK, update the number of records read
If not end of file read a record with
CALL QREAD(RLUN(INDEX),BDATA,NCOLS(INDEX),IERR)
and rearrange it
Check first 3 columns are of type H and if so calculate the resolution. Transfer data to ADATA in LOOKUP order, if LOOKUP(?) is 0 then presume it was an optional column and set ADATA(?) to 0.0

Subroutine LRREFL(MINDX,RESOL,ADATA,EOF)

Read a reflection record from an MTZ file which has been opened for read. This returns the record in `file' order - the physical order of columns in the file rather than the `lookup' order, c.f. LRREFF. Otherwise the same as LRREFF.

The subroutine also returns the resolution (1/d**2). The resolution is calculated from the indices H, K and L, and a set of cell dimensions. If the MTZ file contains columns from several crystals, then there is a choice of cell dimensions. The library uses the first crystal with non-zero cell dimensions. This will typically be the HKL_base crystal, which contains a copy of the cell dimensions of the first real crystal. Clearly if there are several different crystals in the MTZ file, the quoted resolution is somewhat arbitrary.

LRREFL calls the following which are external to MTZLIB:

External Subroutines: LERROR,QREAD

Function:

Check that there is a file open
Everything OK, update the number of records read
Check first 3 columns are of type H and if so calculate the resolution
If not end of file read a record with
CALL QREAD(RLUN(INDEX),ADATA,NCOLS(INDEX),IERR)
NB: End of file is no. of refs read > total no. of refs (from header)

Subroutine LRRSOL(MINDX,MINRES,MAXRES)

Return the resolution range for the reflections in the MTZ file open for read on index MINDX (resolution is 1/d-squared). For a given list of reflection indices, there will be different resolution limits for columns belonging to crystals with different cell dimensions. The subroutine returns the most extreme MINRES and MAXRES. The resolution limits are calculated when the file is written - no `S' column is required in MTZ files. (See also subroutines LRREFF, LRREFL).

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
MINRES (O) REAL
minimum resolution for reflections in file (smallest number)
MAXRES (O) REAL
maximum resolution for reflections in file (largest number)
LRRSOL calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LRSORT(MINDX,SORTX)

Return sort order from header of MTZ file

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
SORTX (O) INTEGER
array of dimension (5) containing sort order of 1st 5 columns in MTZ file, negative numbers for descending order, 0 for not sorted
LRSORT calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LRSYMI(MINDX,NSYMPX,LTYPEX,NSPGRX,SPGRNX,PGNAMX)

Return available symmetry information (other than symmetry operations, for which see LRSYMM) from the MTZ header

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
NSYMPX (O) INTEGER
number of primitive symmetry operations
LTYPEX (O) CHARACTER*1
single character denoting the lattice type (possible values are P,A,B,C,I,F,R). Blank if not present in header.
NSPGRX (O) INTEGER
space group number, 0 if not present
SPGRNX (O) CHARACTER*10
space group name, blank if not present
PGNAMX (O) CHARACTER*10
point group name, blank if not present
LRSYMI calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LRSYMM(MINDX,NSYMX,RSYMX)

Return symmetry operations (if available) from the MTZ header

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
NSYMX (I/O) INTEGER
On entry, the last dimension of RSYMX; on exit the total number of symmetry operations or 0 if no symmetry information is present
RSYMX (O) REAL
array of dimensions (4,4,NSYM) of symmetry operations on exit (max. NSYM is 192)
LRSYMM calls the following which are external to MTZLIB:

External Subroutines : LERROR

Subroutine LRTITL(MINDX,FTITLE,LEN)

Return the title and it's length from the header of an MTZ file.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
FTITLE (O) CHARACTER*(*)
character string containing the title on output - maximum possible length 70
LEN (O) INTEGER
length of the title string - i.e. number of characters from start to last non-blank character
LRTITL calls the following which are external to MTZLIB:

External Subroutines: LERROR
External Functions : INTEGER LENSTR

Subroutine LRSEEK(MINDX,REFNUM)

Move to a specific reflection record in an MTZ file opened for read. Files are normally read sequentially, so this should be viewed as a special case. The file read pointer is positioned so that the next record read with a call to LRREFF or LRREFL will be the one requested.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file (up to MFILES possible open at once)
REFNUM (I) INTEGER
the reflection record number to which to move in the file
LRSEEK calls the following which are external to MTZLIB:

External Subroutines: LERROR, QSEEK

Subroutine LRREWD(MINDX)

Rewind an MTZ file for re-reading of reflections. The file must already have been opened for read with LROPEN. The file is positioned at the start of the reflection records.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
LRREWD calls the following which are external to MTZLIB:

External Subroutines: LERROR, QSEEK

Subroutine LRCLOS(MINDX)

Close an MTZ file which has been opened for read

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
LRCLOS calls the following which are external to MTZLIB:

External Subroutines: LERROR,QCLOSE

Function:

Close the file with CALL QCLOSE(RLUN(INDEX))

Mark this index as unoccupied for read

Subroutine LWOPEN(MINDX,FILNAM)

Open MTZ file for write. This subroutine should be called after the corresponding input file has been opened (i.e. after LROPEN has been called).

NB: Every time LROPEN is called it zeros all the header info for that MINDX, and then loads up the header storage with data from the file. Therefore if LWOPEN is called first, and if (e.g.) a title of a history line is added with LWTITL or LWHIST, this info will be lost if it is followed by a call to LROPEN (on the same MINDX). While this is unlikely to occur in most programs, care should be taken with programs which open a large number of input files in sequence and write one output file (and therefore have a sequence of calls like - LROPEN, LWOPEN, LRREFL, LWREFL, LRCLOS, LROPEN, LRREFL, LWREFL, LRCLOS ... LWCLOS) not to update items in the header until the last input file has been opened. Alternatively, if you want to retain the data from the first input header in the output header, you should open the first input file on index 1, and the output file on 1 also, and all subsequent input files on index 2.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
FILNAM (I) CHARACTER*(*)
name of file to be opened
LWOPEN calls the following which are external to MTZLIB:

External Subroutines: LERROR,QOPEN,QMODE,QWRITE

Function:

Explicitly pull in the initialise block data here (EXTERNAL MTZINI) Check for other open files on this index - first read files If no read file open, then LROPEN has not been called - initialise all the MTZ header common blocks here - some of these not nec. if no read file, but do it for consistency
Then the write files - pretty serious if already open, so stop.
Everything OK, open the file and zero a few variables
CALL QOPEN(IUNIN,FILNAM,'NEW')
CALL QMODE(IUNIN,2,NITEM)
Write a dummy first record to the file (the one which will contain the header offset and the machine stamp and mtz stamp)

Subroutine LWASSN(MINDX,LSPRGO,NLPRGO,CTPRGO,IAPPND)

Setup the column labels and column types for the output MTZ file. This allows for the user to have specified output column assignments.

Note that this subroutine changes the values in the header common block, so all information about the input file's labels and types should already have been extracted.

If the program is going to allow user output labels, then the subroutine LKYOUT *MUST* be called to parse the output label assignments from the input control data, before LWASSN is called.

Also note that the case of the user and/or program output labels is preserved.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
LSPRGO (I) CHARACTER*30
array of dimension at least NLPRGO containing the program output labels
NLPRGO (I) INTEGER
number of output program labels
CTPRGO (I) CHARACTER*1
array of dimension at least NLPRGO containing the output column types
IAPPND (I) INTEGER
=0
replace all existing labels and types
=1
append to the existing labels and types

LWASSN calls the following which are external to MTZLIB:

External Functions : INTEGER LENSTR
External Subroutines: BLANK,LABPRT,LERROR,PUTLIN

Function:

Work out starting column
Work out total number of columns to be written to output file. Loop over the new labels, and check the user assignments - if an output program label is the same as an input one, and there is no user output assignment then check the input assignments and keep the original user label for that column.
Print out the output program labels and output column label, and an output lookup. Then check the column types are valid.

Subroutine LWCELL(MINDX,CELLP)

Write Cell Parameters into the header common block (to be written to the output MTZ file). When this is called the calculation for the resolution is re-initialised for the new cell parameters, therefore this should be called before any reflections are written to the output file (ie before any calls to LWREFL).

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
CELLP (I) REAL
array of dimension (6) containing cell parameters to write to header

LWCELL calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LWCLAB(MINDX,LSPRGO,NLPRGO,CTPRGO,IAPPND)

Write the column labels and column types to the header of an output MTZ file. This is simpler than LWASSN as it doesn't look for column assignments and doesn't check back to the input file at all - so the output column labels are exactly what come into this subroutine in CLABS, and the case of the labels is preserved.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
LSPRGO (I) CHARACTER*30
array of dimension at least NLPRGO containing the column labels on entry
NLPRGO (I) INTEGER
number of columns input
CTPRGO (I) CHARACTER*1
array of dimension at least NLPRGO containing the column types on entry
IAPPND (I) INTEGER
=0
replace all existing labels and types
=1
append to the existing labels and types
LWCLAB calls the following which are external to MTZLIB:
External Functions : INTEGER LENSTR
External Subroutines: LERROR

Subroutine LWHIST(MINDX,HSTRNG,NLINES)

Write new history lines to history header. History headers have a maximum of NHISTL lines. We write the new NLINES of history to the header and then fill up any free lines with the older lines.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
HSTRNG (I) CHARACTER
array of (NLINES) with the history lines
NLINES (I) INTEGER
number of history lines to be written

Subroutine LWHSTL(MINDX,EXTRA)

Write a single line of history information to an MTZ file with index MINDX indicating that it was output from the program whose name was previously set with CCPVRS (/CCPRCS) at the current date and time. EXTRA is more information to append to the record (or blank). An example of the information produced might be:
    From FREERFLAG, 21/ 6/94 18:38:48 with fraction 0.050
         ^^^^^^^^^                    ^^^^^^^^^^^^^^^^^^^
         CCPVRS arg                           EXTRA
This is just a simplified interface to LWHIST. The history line will be truncated to 80 characters.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
EXTRA (I) CHARACTER*(*)
Extra information to print
LWHIST calls the following which are external to MTZLIB:
External Subroutines: LERROR

Function:

Check not too many lines input - if so take first NHISTL lines
Copy existing history lines to scratch array
Copy input lines to the history array in the header common blocks
Fill up any space left with lines already in history header

Subroutine LWSORT(MINDX,SORTX)

Write the sort order of the output file to the MTZ header.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
SORTX (I) INTEGER
array of dimension (5) containing sort order of 1st 5 columns in MTZ file negative numbers for descending order 0 for not sorted
LWSORT calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LWSYMM(MINDX,NSYMX,NSYMPX,RSYMX,LTYPEX,NSPGRX,SPGRNX,PGNAMX)

Update the symmetry operations and information in the MTZ header.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
NSYMX (I) INTEGER
total number of symmetry operations. If this is 0 then the symmetry operation values are not changed
NSYMPX (I) INTEGER
number of primitive operations
RSYMX (I) REAL
array of dimensions (4,4,192) of symmetry operations on entry
LTYPEX (I) CHARACTER*1
single character denoting the lattice type (possible values are P,A,B,C,I,F,R) if blank then current value not changed
NSPGRX (I) INTEGER
space group number, if 0 not changed
SPGRNX (I) CHARACTER*10
space group name, if blank not changed
PGNAMX (I) CHARACTER*10
point group name, if blank not changed
LWSYMM calls the following which are external to MTZLIB:

External Subroutines: LERROR,PUTLIN

Function:

First deal with symmetry operations - if NSYMX .gt. 0 ie there is already symmetry info there, print warning with
CALL SYMTR3(NSYM(INDEX),RSYM(1,1,1,INDEX),SYMCHS,IPRINT) and
CALL SYMTR3(NSYMX,RSYMX(1,1,1),SYMCHS,IPRINT)
but copy the new ones into the header blocks anyway. Then deal with the other arguments.

Subroutine LWTITL(MINDX,NTITLE,FLAG)

Update the title of an MTZ file in the header common block.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
NTITLE (I) CHARACTER*(*)
character string containing the title - maximum possible length 70
FLAG (I) INTEGER
=0
replace old title with new one
=1
append new one to old, with one space

LWTITL calls the following which are external to MTZLIB:

External Functions : INTEGER LENSTR
External Subroutines: LERROR

Subroutine LWREFL(MINDX,ADATA)

Write a reflection record to an MTZ file which has been opened for write. Also output column labels etc. should already have been setup using LWASSN.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
ADATA (I) REAL
array of dimension at least NCOLW(MINDX) containing the reflection record
LWREFL calls the following which are external to MTZLIB:

External Subroutines: LERROR,QWRITE
External Functions : REAL LSTLSQ

Function:

Check that there is a file open. If everything OK, increment no. of reflection records written.
Update the column ranges
Update the resolution limits
Write the reflection record to file with
CALL QWRITE(WLUN(INDEX),ADATA,NCOLW(INDEX))

Subroutine LWCLOS(MINDX,IPRINT)

Close an MTZ file which has been opened for write. The new header information should already have been supplied by calls to other LW* routines. This subroutine writes the MTZ header and its associated history header to the output file, writes a pointer to the headers in the first record of the file, and a machine stamp and closes the file. The headers are actually written at the end of the file.

This is one of the most important subroutines in the library. If you do not call this subroutine your output file will be corrupted; it will have no header information and the file will be unreadable.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file (up to MFILES possible open at once)
IPRINT (I) INTEGER
print indicator: meaning:
=0
No MTZ info printed at all
=1
Brief header info printed (normal)
=2
Brief header plus history
=3
Full header dump

LWCLOS calls the following which are external to MTZLIB:

External Functions : INTEGER LENSTR
External Subroutines: BLANK,LERROR,PUTLIN,QCLOSE,QSEEK,QWRITE,QMODE,QTYPE

Function:

Calculate position of start of header records, and move to it -
=no.refls*no.cols+size of 1st record + 1
Loop over the header lines and write them out (see LROPEN for a list of the possible header lines) If it is a multi-record file, and if we found that when we were writing the batches out to the file, the batches were out of order (ie serial numbers not in ascending order), then do an indexed sort of the array containing the batch serial numbers, so that they, and the batch information (title and orientation data), can be output serially. (NB the batch header info is never read at the same time as the corresponding reflection records, as it was in the LCF files - all batch headers are read as soon as the file is opened)
Then write the history lines and then the batch info if a multi-record file.
Write MTZENDOFHEADERS record (which is also end of file).
Go back to the beginning and fill up the first record with an identification stamp and the offset of the headers. (ie the offset of the headers is the second long-word in the file)
If IPRINT is gt 0 then call LHPRT to output header information.
Close the file - CALL QCLOSE(WLUN(INDEX)) and mark the index available for write by setting WLUN(INDEX) to 0.

Subroutine LRBAT(MINDX,BATNO,RBATCH,CBATCH,IPRINT)

Return the header info for the next batch from the multi-record MTZ file (or pair of files) open on index MINDX, and the information in the two arrays RBATCH (for numbers) and CBATCH (for characters).

This will also optionally print out all this information in a pretty format.

Note that the maximum numbers of batches currently allowed is 1000.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (O) INTEGER
serial number of this batch, returned as -1 if all batch headers have been read
RBATCH (O) REAL(*)
array into which integer and real batch information is stored by subroutine rbathd this should be equivalenced onto the appropriate COMMON block in the calling program. The first item is Nwords, i.e. how many items in the array: Nwords = 0 if no orientation data are present in the batch header
CBATCH (O) CHARACTER(*)*1
as RBATCH, but for character items - no nwords however
IPRINT (I) INTEGER
print indicator
=0
no print
=1
print batch title only
=2
print orientation block as well
>30
print orientation block as well BUT to IPRINT unit number

LRBAT calls the following which are external to MTZLIB:

External Subroutines: LERROR

Subroutine LWBAT(MINDX,BATNO,RBATCH,CBATCH)

Write the header for batch with serial number BATNO to the MTZ file open for write on index MINDX, batch info stored in the two arrays RBATCH (for numbers) and CBATCH (for characters).

If this routine is called at all then it must be called for every batch which is to be output - these batch serial numbers are stored and used in LWCLOS.

If it is called with BATNO = 0 this is a flag to say that the output MTZ file will be a standard file, and not a multi-record one, i.e. no batches. After this call no batch information is available to the calling program, so don't call it too soon !

Note that the maximum numbers of batches currently allowed is 1000.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (I) INTEGER
serial number of this batch if 0 wipe away all batch info for file
RBATCH (I) REAL(*)
array from which integer and real batch info is decoded by subroutine WBATHD this should be equivalenced onto the appropriate COMMON block in the calling program. The first item is NWORDS, i.e. how many items in the array. If NWORDS is 0 then only the title is written to header
CBATCH (I) CHARACTER(*)*1
as RBATCH, but for character items - no nwords however; title is 1st 70 chars of CBATCH.
LWBAT calls the following which are external to MTZLIB:

External Subroutines: LERROR

Function:

This subroutine will check whether the number of the current batch which is being written is (1) already present in the output file (ie LWBAT has already been called with this batch number) and (2) less than the serial number of the last batch written (ie the serial numbers are out of order). If 2 batches are the same the program will stop, and if the serial numbers are out of order a flag is set so that they will be sorted by LWCLOS before being written out to the file.

Subroutine LRBSCL (MINDX,BATNO,BATSCL,NBATSC)

Read batch scale, Bfactor and batch title for batch BATNO from batch headers from multi-record file open on index MINDX
MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (I) INTEGER
batch number
NBATSC (I) INTEGER
maximum number of batch scales expected
BATSCL (O) REAL
array of dimension at least NBATSC containing batch scale, relative Bfactor, SD(Bscale), SD(Bfactor) if NBATSC = 4 else NBATSC/2 scales or B-factors + Sd's on output
NBATSC (I/O) INTEGER
On entry the dimension of BATSCL; on exit the number of batch scales found
LRBSCL calls the following which are external to MTZLIB:
External Subroutines: LERROR

Subroutine LRBTIT (MINDX,BATNO,TBATCH,IPRINT)

Read batch title for batch BATNO from batch headers from multi-record mtz file open on index MINDX

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (I) INTEGER
batch number
TBATCH (O) CHARACTER
batch title
IPRINT (I) INTEGER
print flag
=0
no print
=1
print title
=2
print title and orientation block

Subroutine LWBTIT (MINDX,BATNO,TBATCH)

Write batch title and dummy orientation block for batch BATNO to multi-record file open on index MINDX

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (I) INTEGER
batch number
TBATCH (I) CHARACTER
batch title

Subroutine LWBSCL(MINDX,BATNO,BATSCL,NBATSC)

Write batch scale and Bfactor for batch BATNO to batch headers for multi-record file open on index MINDX

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - one index points to both input and output files
BATNO (I) INTEGER
batch number
BATSCL (I) REAL
batch scale, relative Bfactor, SD(Bscale), SD(Bfactor) if NBATSC = 4 else NBATSC/2 scales or B-factors + Sd's
NBATSC (I) INTEGER
number of batch scales (=0 to clear)

Subroutine LBPRT(IBATCH,IPRINT,RBATCH,CBATCH)

Internal MTZ subroutine which copies the batch header information as it is stored in raw form on the files, into the common blocks MBTHDR and CBTHDR, and then calls LBPRTH to make some sense of these numbers.

Arguments:

IBATCH (I) INTEGER
batch number
IPRINT (I) INTEGER
print indicator: meaning:
=0
no print
=1
print batch title only
=2
also print orientation block
>30
also print orientation block BUT to IPRINT unit number
RBATCH (I) REAL(*)
array from which integer and real batch info is decoded by subroutine WBATHD. This should be equivalenced onto the appropriate COMMON block in the calling program. The first item is NWORDS, i.e. how many items in the array. If NWORDS is 0 then only the title is written to header.
CBATCH (I) CHARACTER(*)*1
as RBATCH, but for character items - no nwords however; title is 1st 70 chars of CBATCH.

LBPRT is called by LRBAT, and it calls LBPRTH to do the actual printing.

SUBROUTINE EQUAL_MAGIC(MINDX,ADATA,NCOL)

Sets an array of NCOL to VAL_MISS(2,MINDX), the appropriate value for the output file.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
ADATA (I) REAL
array of dimension at least NCOL containing the reflection record with "missing" values set to VAL_MAGICA
NCOL (I) INTEGER
Array size of ADATA

SUBROUTINE IS_MAGIC (VAL_MAGIC,VALTST,LVALMS)

Function to test whether a number is "magic". Returns LVALMS TRUE if it is - otherwise LVALMS FALSE.

Arguments :

VAL_MAGIC (I) REAL
Missing value flag as "magic" for this mtz file.
VALTST (I) REAL
Number to test to see if it is defined as "magic" for this mtz file.
LVALMS (O) LOGICAL
Returns LVALMS TRUE if VALTST is "magic", FALSE if it is not, or if there is no "missing" number set.

SUBROUTINE RESET_MAGIC(MINDX,ADATA,BDATA,NCOL,VAL_MAGICA,VAL_MAGICB)

Resets an array containing Missing value flags VAL_MAGICA to one containing Missing value flags VAL_MAGICB If MINDX > 0 then VAL_MAGICA is taken to be the value of the MNF stored in the MTZ header, for MTZ file MINDX. Else the passed value is taken. The MNF pertaining to the data need not necessarily be the same as that stored in the header. This allows you to list arrays containing Nan entries.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
ADATA (I) REAL
array of dimension at least NCOL containing the reflection record with "missing" values set to VAL_MAGICA
BDATA (O) REAL
Array of dimension at least NCOL containing the reflection record with "missing" values reset to VAL_MAGIC
NCOL (I) INTEGER
Array size of ADATA
VAL_MAGICA (I) REAL
If MINDX = 0 then this value will be treated as the MNF pertaining to the data. Otherwise
VAL_MAGICB (I) REAL
"Missing value" flag to reset in BDATA to allow record to be printed.

SUBROUTINE SET_MAGIC(MINDX,VAL_MAGIC,SETVAL)

Subroutine to pass the "magic" value for this mtz file either into the file or back to the calling program

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
VAL_MAGIC (I) REAL
variable giving value assigned to "missing data"; it may be passed to an MTZ file, or return a preset value.
SETVAL (I) LOGICAL
if TRUE on entry, the mtz missing flag is set to VAL_MAGIC - ie the value in the mtz file is OVERWRITTEN! if FALSE on entry and there is a "missing value" set in the input MTZ file that will be returned as VAL_MAGIC, and SETVAL will be returned TRUE. if FALSE on entry and there is NO "missing value" set in the input MTZ file VAL_MAGIC will be set to the default for both input and output SETVAL returned TRUE

SUBROUTINE LRREFM(MINDX,LOGMSS)

Returns Logical array which flags missing data entries Array DATMSS set in LRREFF and LRREFL

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
LOGMSS (O) LOGICAL
Array of dimension at least NPLABS(MINDX) if LRREFF is being used, or NCOLS(MINDX) if LRREFL is being used. In practice, dimension MCOLS is safest. Contains the logical array LOGMSS on exit in order of LRREFF or LRREFL, whichever was most recently called. IF LOGMSS(..) is TRUE the entry is "missing". Maps onto DATMSS.

SUBROUTINE LRIDX(MINDX,PNAME,XNAME,DNAME,ISETS,DATCELL, DATWAVE,NDATASETS)

Subroutine to return information for all datasets from the MTZ file header, including crystal names. Datasets are identified by the XNAME / DNAME pair. There is also an integer ID in ISETS which is more useful for programming. Note that i'th dataset does not necessarily have ID=i.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
PNAME (O) CHARACTER
array of dimension at least NDATASETS containing the project names on exit
XNAME (O) CHARACTER
array of dimension at least NDATASETS containing the crystal names on exit
DNAME (O) CHARACTER
array of dimension at least NDATASETS containing the dataset names on exit
ISETS (O) INTEGER
array of dimension at least NDATASETS containing the dataset IDs on exit
DATCELL (O) REAL
a 2-dimensional array of dimension at least (6,NDATASETS) containing the cell dimensions for all datasets on exit
DATWAVE (O) REAL
array of dimension at least NDATASETS containing the dataset wavelengths
NDATASETS (I/O) INTEGER
On entry, it should be set to the dimension of the arrays used (PNAME, etc.). This should be large enough to hold the maximum number of expected datasets. On exit, NDATASETS contains the actual number of datasets in the MTZ header

SUBROUTINE LRIDC(MINDX,PNAME,DNAME,ISETS,DATCELL, DATWAVE,NDATASETS)

Subroutine to return information for all datasets from the MTZ file header.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
PNAME (O) CHARACTER
array of dimension at least NDATASETS containing the protein name on exit
DNAME (O) CHARACTER
array of dimension at least NDATASETS containing the dataset name on exit
ISETS (O) INTEGER
array of dimension at least NDATASETS containing the dataset IDs on exit
DATCELL (O) REAL
a 2-dimensional array of dimension at least (6,NDATASETS) containing the cell dimensions for all datasets on exit
DATWAVE (O) REAL
array of dimension at least NDATASETS containing the dataset wavelengths (returns zero if not set).
NDATASETS (O) INTEGER
number of datasets in MTZ header

SUBROUTINE LRID(MINDX,PNAME,DNAME,ISETS,NDATASETS)

As LRIDC, but without cell and wavelength information (for backwards compatibility).

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
PNAME (O) CHARACTER
array of dimension at least NDATASETS containing the protein name on exit
DNAME (O) CHARACTER
array of dimension at least NDATASETS containing the dataset name on exit
ISETS (O) INTEGER
array of dimension at least NDATASETS containing the dataset IDs on exit
NDATASETS (O) INTEGER
number of datasets in MTZ header

SUBROUTINE LWIDX(MINDX,PROJECT_NAME,CRYSTAL_NAME,DATASET_NAME, DATCELL,DATWAVE)

Subroutine to add dataset information to the output MTZ file header, including crystal names. Datasets identified by the PROJECT_NAME/DATASET_NAME pair are appended to the MTZ header one at a time. Checks to see if the PROJECT_NAME/DATASET_NAME pair is already included; if so, the dataset is updated with the cell and wavelength information. Redundant datasets are removed in LWCLOS.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
PROJECT_NAME (I) CHARACTER
project name of dataset to be added (strings longer than 64 will be truncated)
CRYSTAL_NAME (I) CHARACTER
crystal name of dataset to be added (strings longer than 64 will be truncated)
DATASET_NAME (I) CHARACTER
dataset name of dataset to be added (strings longer than 64 will be truncated)
DATCELL (I) REAL
cell dimensions of dataset to be added
DATWAVE (I) REAL
wavelength of dataset to be added

SUBROUTINE LWIDC(MINDX,PROTEIN_NAME,DATASET_NAME, DATCELL,DATWAVE)

Subroutine to add dataset information to the output MTZ file header. Datasets identified by the PROJECT_NAME/DATASET_NAME pair are appended to the MTZ header one at a time. Checks to see if the PROJECT_NAME/DATASET_NAME pair is already included; if so, the dataset is updated with the cell and wavelength information. Redundant datasets are removed in LWCLOS.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
PROTEIN_NAME (I) CHARACTER
protein name of dataset to be added (strings longer than 64 will be truncated)
DATASET_NAME (I) CHARACTER
dataset name of dataset to be added (strings longer than 64 will be truncated)
DATCELL (I) REAL
cell dimensions of dataset to be added (if zero passed, no cell information is added, but when the output header is written by LWCLOS, DATCELL defaults to overall cell).
DATWAVE (I) REAL
wavelength of dataset to be added (if zero passed, no wavelength information is added).

SUBROUTINE LWID(MINDX,PROTEIN_NAME,DATASET_NAME)

As LWIDC, but without cell and wavelength information (for backwards compatibility).

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
PROTEIN_NAME (I) CHARACTER
protein name of dataset to be added (strings longer than 64 will be truncated)
DATASET_NAME (I) CHARACTER
dataset name of dataset to be added (strings longer than 64 will be truncated)

SUBROUTINE LRCLID(MINDX,CSETID,NCOL)

Subroutine to return the ID of the related dataset for each column of the input MTZ file, as obtained from the header. Thus CSETID(4)=2 means that the 4th column belongs to the dataset with ID "2" (which is not necessarily the 2nd dataset). The dataset IDs are returned by subroutine LRIDX .

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
CSETID (O) INTEGER
array of dimension at least NCOL containing the dataset IDs on exit
NCOL (O) INTEGER
number of columns in the MTZ file

SUBROUTINE LWIDASX(MINDX,NLPRGO,XNAME,DNAME,IAPPND)

Subroutine to associate dataset entry with each column for the output MTZ file.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
NLPRGO (I) INTEGER
number of output program labels
XNAME (I) CHARACTER
array of dimension at least NLPRGO containing the output crystal name
DNAME (I) CHARACTER
array of dimension at least NLPRGO containing the output dataset name
IAPPND (I) INTEGER
=0 replace all existing column info
=1 append to the existing column info

SUBROUTINE LWIDAS(MINDX,NLPRGO,PNAME,DNAME,IAPPND)

Subroutine to associate dataset entry with each column for the output MTZ file.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
NLPRGO (I) INTEGER
number of output program labels
PNAME (I) CHARACTER
array of dimension at least NLPRGO containing the output project name
DNAME (I) CHARACTER
array of dimension at least NLPRGO containing the output dataset name
IAPPND (I) INTEGER
=0 replace all existing column info
=1 append to the existing column info

SUBROUTINE LRBSETID (MINDX,BATNO,BSETID)

Subroutine to read dataset ID for batch BATNO from batch headers for multi-record file open on index MINDX. If LWBAT has been used, the batch headers in RBATW are used, else those in RBATR are used.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
BATNO (I) INTEGER
batch number
BSETID (O) INTEGER
dataset ID for batch

SUBROUTINE LWBSETIDX (MINDX,BATNO,XNAME,DNAME)

Subroutine to write dataset ID for batch BATNO to batch headers for multi-record file open on index MINDX. If LWBAT has been used, the batch headers in RBATW are used, else those in RBATR are used.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
BATNO (I) INTEGER
batch number
XNAME (I) CHARACTER
crystal name of dataset
DNAME (I) CHARACTER
dataset name of dataset

SUBROUTINE LWBSETID (MINDX,BATNO,PNAME,DNAME)

Subroutine to write dataset ID for batch BATNO to batch headers for multi-record file open on index MINDX. If LWBAT has been used, the batch headers in RBATW are used, else those in RBATR are used.

Arguments :

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
BATNO (I) INTEGER
batch number
PNAME (I) CHARACTER
project name of dataset
DNAME (I) CHARACTER
dataset name of dataset

Subroutine LKYIN(MINDX,LSPRGI,NLPRGI,NTOK,LINE,IBEG,IEND)

Read standard input lines of the form
LABIN <program label>=<file label> ...
Use this to read the inputs, and then LRASSN to setup the program label to file label assignments.

LKYIN also checks that each assignment set actually contains an input program label on one side of the = sign. This comparison is not case sensitive.

If there is no ambiguity, the order in which program and file labels are given may be swapped.

Arguments:

LSPRGI (I) CHARACTER*30
program label strings (array); L(abel) S(tring) PRG(rammme) I(nput)
NLPRGI (I) INTEGER
number of program input labels: N(umber of) L(abels) PRG(ramme) I(nput)
NTOK (I) INTEGER
from Parser, number of tokens on line
LINE (I) CHARACTER*(*)
the input line
IBEG,IEND (I) INTEGER
arrays from the parser, delimiters for each token
LKYIN calls the following which are external to MTZLIB:

External Subroutines: CCPUPC, PUTLIN
External Functions : INTEGER LENSTR

Subroutine LKYSET(LSPRGI,NLPRGI,LSUSRJ,KPOINT,ITOK,NTOK,LINE,IBEG,IEND)

Parses standard input lines of the form
[LABIN] item1=name1 item2=name2 ...

This subroutine returns the user input labels to the calling program (LKYIN does not) and the array KPOINT which indicates which of the program labels were assigned user input file labels

Note that although this Subroutine looks similar to LKYIN it cannot be called in its place, it simply adds extra functionality. There is no MINDX argument to this call - it is not tied to any particular file(s) and the header common blocks are not affected by this subroutine.

See the notes above (LKYIN) about the order of the assignment statements.

Arguments:

LSPRGI (I) CHARACTER*30
program label strings (array): L(abel) S(tring) PRG(rammme) I(nput)
NLPRGI (I) INTEGER
number of program input labels: N(umber of) L(abels) PRG(ramme) I(nput)
LSPRGJ (O) CHARACTER*30
user supplied label strings (array): L(abel) S(tring) USR(rammme) I(nput). Copy of user input labels to return to the calling program
KPOINT (O) INTEGER
Indicator whether each program label is set: -1 if set, 0 if not
ITOK (I) INTEGER
First token to search on line - allows you to skip the LABIN token
NTOK (I) INTEGER
from Parser, number of tokens on line
LINE (I) CHARACTER*(*)
the input line
IBEG,IEND (I) INTEGER
arrays from the parser, delimiters for each token
LKSET calls the following which are external to MTZLIB:

External Subroutines: CCPUPC, PUTLIN
External Functions : INTEGER LENSTR

Subroutine LKYOUT(MINDX,LSPRGO,NLPRGO,NTOK,LINE,IBEG,IEND)

Read standard input lines of the form
LABOUT LabelFC=userFC LabelPHCAL=userPHCAL ...
Use this to read the inputs, and then LWASSN to setup the program label to (new) file label assignments.

LKYOUT also checks that each assignment set actually contains an output program label on one side of the = sign. This comparison is not case sensitive.

If there is no ambiguity, the order in which program and file labels are given may be swapped.

Note that the case of the user output labels is preserved.

Arguments:

LSPRGO (I) CHARACTER*30
program label strings (array): L(abel) S(tring) PRG(rammme) O(utput)
NLPRGO (I) INTEGER
number of program output labels: N(umber of) L(abels) PRG(ramme) O(utput)
NTOK (I) INTEGER
from Parser, number of tokens on line
LINE (I) CHARACTER*(*)
the input line
IBEG,IEND (I) INTEGER
arrays from the parser, delimiters for each token
LKYOUT calls the following which are external to MTZLIB:

External Subroutines: CCPUPC, PUTLIN
External Functions : INTEGER LENSTR

Subroutine LKYASN(MINDX,NLPRGI,LSPRGI,CTPRGI,LOOKUP)

Do column assignments, bypassing the need for keyworded input. This is useful in writing little mtz programs, without using Parser in the main program.

Read column assignments and make them, for input MTZ file open for read on index MINDX

It expects to read from stream 5 a line of the form
LABIN program_label=file_label program_label=file_label . . .
This routine is useful for simple jiffy programs that don't want full keyworded input

See the LKYIN section above for the notes on case, and order of input assignments.

Arguments:

MINDX (I) INTEGER
file index number for opened MTZ input file
NLPRGI (I) INTEGER
number of input program labels
LSPRGI (I) CHARACTER*30
array of dimension at least NLPRGI containing the program label strings
CTPRGI (I) CHARACTER*1
array of column types for each column: these will be checked to see that they match the actual column types in the file. If you don't want to check column types, provide blank types here (dimension at least NLPRGI)
LOOKUP (O) INTEGER
array of dimension at least NLPRGI containing column numbers for each assigned label
LKYASN calls the following which are external to MTZLIB:

External Subroutines: PARSER, LERROR

Subroutine LHPRT(MINDX,IPRINT)

Print out the header information from the MTZ COMMON blocks for the MTZ file open on index MINDX.

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
IPRINT (I) INTEGER
print indicator: meaning:
=1
Brief header info printed (default)
=2
As above plus history info
=3
Full header dump, symmetry, alles!
=4
As 1 plus full symmetry
any other value, nothing happens

LHPRT calls the following which are external to MTZLIB:

External Functions : INTEGER LENSTR
External Subroutines: BLANK,LERROR,PUTLIN,SYMTR3

Subroutine LPHIST(MINDX)

Output the history information from the MTZ file header. This text can be anything the programmer chooses, (but probably program stamps at least).

Arguments:

MINDX (I) INTEGER
indicates which MTZ file - 1 index points to both input and output files
LPHIST calls the following which are external to MTZLIB:
External Functions : INTEGER LENSTR
External Subroutines: BLANK,LERROR,PUTLIN

Subroutine RBATHD(ILUN,BATCH,RBATCH,CBATCH)

MTZLIB internal subroutine to read next batch header from multi-record MTZ file open on unit ILUN, and return it's batch number, plus real and character arrays.
 
 
Arguments: 
 
ILUN    (I)  INTEGER         LUN on which the file is open 
 
BATCH   (O)  INTEGER         serial number of this batch 
 
RBATCH  (O)  REAL(*)         array into which integer and real batch 
                             info is decoded by subroutine 
                             this should be equivalenced onto the 
                             appropriate COMMON block in the calling 
                             program. The first item is nwords, ie how 
                             many items in the array, if nword is 0 
                             then only the title is present 
 
CBATCH  (O)  CHARACTER(*)*1  as RBATCH, but for character items - no 
                             nwords however; title is 1st 70 chars of 
                             CBATCH. 
 

RBATHD is call by LROPEN.

RBATHD calls the following which are external to MTZLIB:

External Subroutines: LERROR,QMODE,QREAD

Subroutine WBATHD(ILUN,BATCH,RBATCH,CBATCH)

MTZLIB internal subroutine to write batch header to Multi-record MTZ file open for write on ILUN, with batch number BATCH, and data in RBATCH and CBATCH
 
 
Arguments: 
 
ILUN    (I)  INTEGER         LUN on which the file is open 
 
BATCH   (I)  INTEGER         serial number of this batch 
 
RBATCH  (I)  REAL(*)         array from which integer and real batch 
                             info is encoded by subroutine 
                             this should be equivalenced onto the 
                             appropriate COMMON block in the calling 
                             program. The first item is nwords, ie how 
                             many items in the array, if nword is 0 
                             then only the title is written 
 
CBATCH  (I)  CHARACTER(*)*1  as RBATCH, but for character items - no 
                             nwords however; title is 1st 70 chars of 
                             CBATCH. 
 

WBATHD is called by LWCLOS.

WBATHD calls the following which are external to MTZLIB:

External Subroutines: QMODE,QWRITE

Subroutine LRHDRL(ILUN,LINE)

MTZLIB internal subroutine to read one header record from an MTZ file open for read on unit ILUN, and place the result in the character string LINE. All the header lines are 80 characters long and written to the file in 20A4 format, so have to decode from integers to chars QMODE = 0 for the header record (ie bytes)
 
 
Arguments: 
 
ILUN    (I)  INTEGER         LUN on which the file is open,  
                             for each MTZ file open this is stored  
                             in the RLUN array in MTZWRK  
 
LINE    (O)  CHARACTER*(*)   character string containing one header 
                             record from the MTZ file 
                              

LRHDRL calls the following which are external to MTZLIB:
External Subroutines: QREAD,LERROR

Subroutine LBPRTH(IBATCH,IPRINT)

Internal subroutine to print out the batch header information from the MTZ COMMON blocks /MBTHDR/ and /CBTHDR/ (info already there)
 
 
Arguments: 
 
IBATCH  (I)  INTEGER    batch number 
 
IPRINT  (I)  INTEGER    print indicator: meaning: 
                        =0 no print 
                        =1 print batch title only 
                        =2 also print orientation block 
                        .GT. 30 also print orientation block 
                        TO UNIT NUMBER IPRINT 
 

LBPRTH is called by LBPRT.

LBPRTH calls the following which are external to MTZLIB:

External Subroutines: BLANK,PUTLIN

Subroutine LABPRT(LABELS,NLABS)

Internal subroutine for MTZ routines to output an array of character strings across the page nicely eg labels or types.
Uses subroutine PUTLIN to output to window CURWIN.
 
 
Arguments: 
 
LABELS  (I)  CHARACTER*(*)   array of dimension (NLABS) containing 
                             the character strings to be output 
 
NLABS   (I)  INTEGER         number of labels to be output 
 
 

LABPRT calls the following which are external to MTZLIB:

External Functions : INTEGER LENSTR
External Subroutines: PUTLIN

Subroutine SORTUP(N,A,IN)

Internal subroutine to return order of A in IN - Index Sort, for integer array. Lifted from STILLS program (MOSCO suite).
Ref: Comm. ACM VOL.12 #3 MARCH 1969, R.C.SINGLETON
 
 
Arguments: 
 
N       (I)  INTEGER    dimension of arrays A and IN 
 
A   (I)  INTEGER    array to be sorted 
 
IN  (O)  INTEGER    index array for A 
 

Subroutine ADDLIN(NEWLIN,LINES,MAXLIN)

Internal subroutine to add new lines from NEWLIN to array LINES
 
 
Arguments: 
 
NEWLIN(MAXLIN)  (I/O)   character array 
   this is cleared on output 
 
LINES(MAXLIN)  (O)   character array 
 

INTEGER Function NEXTLN(LINES,MAXLIN)

Internal integer function to find the next empty line in a character array
 
 
Arguments: 
 
LINES(MAXLIN) (I)   character array 
 
NEXTLN        (O)   INTEGER number of next blank line (= -1 if full) 
     
 

Subroutine LSTRSL(MINDX,A,B,C,ALPHA,BETA,GAMMA)

Internal subroutine to calculate coefficients for (sin(theta)/lambda)**2 from h,k,l for general axes.

First calculate the components of input axes in an orthonormal basis, then calculate components of reciprocal axes in same basis

Input angles are in degrees

This is exactly the same as the subroutine SETRSL in SYMLIB, except that it stores its variables in the internal MTZ COMMON blocks, and will work if more than one file is open at once.

 
 
MINDX  (I)  INTEGER      indicates which MTZ file - one index 
                         points to both input and output files 
 
A,B,C,ALPHA,BETA,GAMMA 
       (I)  REAL         cell parameters 
 

REAL FUNCTION LSTLSQ(MINDX,IH,IK,IL)

Internal real function to calculate (sin(theta)/lambda)**2 from h,k,l; coef's set by call to LSTRSL, for the file open on index MINDX

This is exactly the same as the function STHLSQ in SYMLIB, except that it stores it's variables in the internal MTZ COMMON blocks, and will work if more than one file is open at once.

 
 
MINDX     (I)  INTEGER    indicates which MTZ file - one index 
                          points to both input and output files 
 
IH,IK,IL  (I)  INTEGER    Miller indices for the reflection 
 

ORIENTATION BLOCK DATA FOR MULTI-RECORD FILES

This contains slots for all information that seems to be essential at present. Each group of parameters is padded at the end for future expansion.

Data in the orientation block are referred to the Cambridge laboratory axis frame: x along the (idealized) X-ray beam, z along usual rotation axis E1 (omega on 3-axis system). The matrix Q converts a vector in the Madnes frame to the Cambridge frame. Note that the laboratory frame is essentially defined by the vectors e1,e2,e3 and source. It doesn't really seem necessary to carry through a whole lot of crystal and beam tensors, particularly as we have integrated intensities at this stage, but maybe someone will want to, using the allocated padding
The general orientation equation is

 
 
x  =   R M U B h 
 
where x    position in laboratory frame 
R    goniostat matrix 
M    missetting angle matrix (if relevant, see MISFLG) 
            PhiZ PhiY PhiX (PHIXYZ) 
U    crystal orientation matrix UMAT 
B    cell orthogonalization matrix, derived from cell dimensions 
h    reflection indices 
 
 
Note that the description below is NOT is the same order as in the 
common block, in which all the integers come before all the reals 
(flagged as I or R in the description below) 
 
I    NWORDS       number of words in orientation block 
I    NINTGR       number of integers (first part of block includes 
                  these counts) 
I    NREALS       number of reals 
I    IORTYP       type of orientation block (for possible future 
                  use, now = 0) 
I    INTPAD(8)    padding for future use (integers) 
 
--- Information for this crystal 
 
R    CELL(6)      cell dimensions  (A and degrees) 
I    LBCELL(6)    refinement flags for cell dimensions 
R    UMAT(3,3)    orientation matrix U. If MISFLG .gt. 0, U is the 
                   standard setting when PhiXYZ ==0 
I    MISFLG       status of missetting angles PHIXYZ 
                   = 0  PHIXYZ not used, all orientation in UMAT 
                   = 1  1 set of missetting angles (PHIXYZ(I,1)) 
                   = 2  2 sets PHIXYZ(I,J), J=1,2 
R    PHIXYZ(3,2)  missetting angles at beginning and end of rotation 
I    JUMPAX       reciprocal axis closest to principle goniostat axis E1 
                       (only used for printing) 
I    NCRYST       crystal number: a crystal may contain several batches 
I    LBSETID      dataset number (this indexes a list of datasets in the
                  file header)
I    LCRFLG       type of crystal mosaicity information 
                  (=0 for isotropic, =1 anisotropic) 
     *** CRYDAT(12) equivalenced to following *** 
R    ETAD         reflection width (full width) (degrees) (if LCRFLG=0) 
      or 
R    ETADH,ETADV  horizontal and vertical reflection width  (if LCRFLG=1) 
R    rest of CRYDAT: padding for crystal information 
                     (eg more complicated mosaicity model) 
 
--- Information for this batch 
 
I    LDTYPE       type of data 
                   = 1    oscillation data   (2D spots) 
                   = 2    area detector data (3D spots) 
                   = 3    Laue data 
R    DATUM(3)     datum values of goniostat axes, from which 
                  Phi is measured (degrees) 
R    PHISTT,PHIEND start and stop values of Phi (degrees) 
                   relative to datum 
R    PHIRANGE     range of Phi values: typically this will be PHIEND-PHISTT,
                    but storing this explicitly allows a distinction 
                    eg between a rotation of +160 degrees from a rotation
                    of -200 degrees
I    JSCAXS       goniostat scan axis number (=1,2,3, or =0 
                  for multiple axis scan 
R    SCANAX(3)    rotation axis in laboratory frame 
                  (not yet implemented: only relevant if JSCAXS=0) 
R    TIME1, TIME2 start and stop times in minutes 
I    NBSCAL       number of batch scales and Bfactors plus SD's 
                   (4 at present, BSCALE, BBFAC and sd's) 
                  set = 0 if batch scales unset 
R    BSCALE       batch scale 
R    BBFAC        batch temperature factor. 
                   corresponding scale is 
                   exp(-2 B (sin theta/lambda)**2) 
R    SDBSCL       sd (Bscale) 
R    SDBFAC       sd (BBfac) 
R    BATPAD(11)   padding for batch information 
 
--- Crystal goniostat information 
 
I    NGONAX       number of goniostat axes (normally 1 or 3) 
I    E1(3),E2(3),E3(3) vectors (in Cambridge laboratory frame, 
                        see below) defining the NGONAX goniostat axes 
C    GONLAB(3)  names of the three goniostat axes 
R    GONPAD(12) padding for goniostat information 
 
 
--- Beam information 
 
R    SOURCE(3)    Idealized (ie excluding tilts) source vector 
                   (antiparallel to beam), in Cambridge 
                   laboratory frame 
R    S0(3)        Source vector (antiparallel ! to beam), in 
                   Cambridge laboratory frame, including tilts 
I    LBMFLG       flag for type of beam information following 
                   = 0 for ALAMBD, DELAMB only (laboratory source) 
                   = 1     ALAMBD,DELAMB,DELCOR,DIVHD,DIVVD 
                           (synchrotron) 
                           (other options could include white beam) 
*** BEMDAT(25) equivalenced to following *** 
R    ALAMBD       Wavelength in Angstroms 
R    DELAMB       dispersion Deltalambda / lambda. 
R    DELCOR       Correlated component of wavelength dispersion. 
R    DIVHD        Horizontal beam divergence in degrees. 
R    DIVVD        Vertical beam divergence (may be 0.0 for 
                   isotropic beam divergence. 
R    rest of BEMDAT: padding for beam information 
 
--- Detector information 
 
I    NDET         number of detectors (current maximum 2) 
     -- for each detector 
R    DXn          crystal to detector distance (mm) 
R    THETAn       detector tilt angle (=Madnes:tau2) (degrees) 
R    DETLMn(2,2)  minimum and maximum values of detector 
                  coordinates (pixels) 
                     (i,j): i = 1 minimum, = 2 maximum 
                            j = 1 Ydet,    = 2 Zdet 
R    DETPAD(34)     padding for detector information 
 
 
If you want to see an example of this, look at the subroutines 
LBPRT and LBPRTH. 
 

EXAMPLE PROGRAM USING AN MTZ FILE

(See also the program templates available on the CCP4 developer's pages.)

      PROGRAM example_MTZ
C     ===================
C
C---- An example of a program reading and writing MTZ files.C
C
C     .. Parameters ..
      INTEGER MCOLS, NPAR, NLOC
      PARAMETER (MCOLS=500, NPAR=200, NLOC=50)
C     ..
C     .. Scalars for Parser ..
      INTEGER NTOK
      LOGICAL LEND
      CHARACTER KEY*4,LINE*400
C     ..
C     .. Arrays for Parser ..
      REAL FVALUE(NPAR)
      INTEGER IBEG(NPAR),IDEC(NPAR),IEND(NPAR),ITYP(NPAR)
      CHARACTER CVALUE(NPAR)*4
C     ..
C     .. Local Scalars ..
      REAL EPS,F1,F2,FLAGIP,FLAGOP,RSOL
      INTEGER ALLSYM,I,IC,ICALL,ICEN,IERR,IFIL,II,ILEN,IPRINT,ISYSAB,
     +        JDO10,JDO30,JDO40,JQ,NCEN,NCHK,NCOL,NEPS,NLPRGI,NLPRGO,
     +        NREF,NSYM,NSYSAB,NLUSRI,NLURSO
      CHARACTER DUMMY*10,TITNEW*70
      LOGICAL EOF
C     ..
C     .. Local Arrays ..
      REAL ADATA(MCOLS),DUM(2,MCOLS),RSYM(4,4,192)
      INTEGER IH(3),JPOINT(NLOC),LOOKUP(NLOC)
      CHARACTER OUTTYP(NLOC)*1,LSPRGI(NLOC)*30,LSPRGO(NLOC)*30,
     +          HISNEW(20)*80,CTPRGI(NLOC)*1
C     ..
C     .. External Subroutines ..
      EXTERNAL CCPUPC,CENTR,EPSLON,LRASSN,LRINFO,LROPEN,LRREFF,
     +         LRSYMM,LRTITL,LWASSN,LWCLOS,LWHIST,LWOPEN,LWREFL,LWTITL,
     +         PARSER,SYMTRN,LKYIN,LKYOUT
C     ..
C     .. Data statements ..
C---- NLPRGI  =  number of input labels
      DATA NLPRGI,LSPRGI/7,'H','K','L','F1','SIG1','DELF1',
     +     'SIGDELF1',43*' '/
C---- NLPRGO  =  number of output labels
      DATA NLPRGO,LSPRGO/9,'H','K','L','FP','F1','SIG1','SIGFP',
     +     'FN','SIGFN',41*' '/
C---- This code signs which input columns are essential (LOOKUP)
      DATA CTPRGI/'H','H','H','F','Q','F','Q',43*' '/
      DATA OUTTYP/'H','H','H','F','Q','F','Q','F','Q',41*' '/
      DATA LOOKUP/-1,-1,-1,-1,-1,-1,0,43*0/
C---- Clear character arrays  TITNEW, HISNEW, JPOINT
      DATA HISNEW/20*' '/, JPOINT/50*0/
C     ..
      CALL CCPFYP
      CALL MTZINI
      NTOK = NPAR
      IFIL = 1
      IPRINT = 3
C---- Open input file for Read
      CALL LROPEN(IFIL,'HKLIN',IPRINT,IERR)
C---- Open output file
      CALL LWOPEN(IFIL,'HKLOUT')
C---- Default is to copy input title to output
C---- Do you want to change title??
      TITNEW = 'A test case for reading and writing MTZ files'
      CALL LWTITL(IFIL,TITNEW,0)
C---- Some history to append to output file
C      Only last 30 lines will be kept
      HISNEW(1) = ' Calculating F(+) F(-) - MTZRW_NEW'
      HISNEW(2) = ' Some more info...'
      CALL LWHIST(IFIL,HISNEW,2)
C---- Find out how many columns and reflections in input file
      CALL LRINFO(IFIL,DUMMY,NCOL,NREF,DUM)
C---- We want to set up centric and epsilon tests
      ALLSYM = 0
      CALL LRSYMM(IFIL,NSYM,RSYM)
      CALL SYMTRN(NSYM,RSYM)
      CALL CENTRIC(NSYM,ISYM,0)
C---- Read Program labels here if you like or
C     use those assigned in data stt above...
C
C    Eg as in FFT  F1 SIG1 F2 SIG2 PHI ....
C
C    LKYIN will read string F1=FNAT89 PHI=Acalc  ...
C    LRASSN  will set LOOKUP(i) (i=1-nlabs) equal
C                column number in input file.
C    LOOKUP(i)=0 if label not matched...
      NLUSRI = 0
      NLUSRO = 0
   20 CONTINUE
      LINE = ' '
      KEY = ' '
      NTOK = NPAR
      CALL PARSER(KEY,LINE,IBEG,IEND,ITYP,FVALUE,CVALUE,IDEC,NTOK,LEND,
     +            .FALSE.)
      IF (.NOT.LEND) THEN
        IF (KEY.EQ.'LABI') THEN
          CALL LKYIN (IFIL,LSPRGI,NLPRGI,NTOK,LINE,IBEG,IEND)
          CALL LRASSN(IFIL,LSPRGI,NLPRGI,LOOKUP,CTPRGI)
        ELSE IF (KEY.EQ.'LABO') THEN
          CALL LKYOUT(IFIL,LSPRGO,NLPRGO,NTOK,LINE,IBEG,IEND)
          CALL LWASSN(IFIL,LSPRGO,NLPRGO,OUTTYP,0)
        END IF
        GO TO 20
      END IF
C---- Now read data (`lookup' order)
      WRITE (6,FMT=*) '  NREF= ',NREF
      DO 40 JDO40 = 1,NREF
        CALL LRREFF(IFIL,RSOL,ADATA,EOF)
        IH(1) = ADATA(1)
        IH(2) = ADATA(2)
        IH(3) = ADATA(3)
C       centricity check
        CALL CENTR(IH,ICEN)
        IF (ICEN.EQ.1) THEN
          NCEN = NCEN + 1
          IF (NCEN.LT.21) WRITE (6,FMT='(A,3I4,F8.2)') ' CENTRIC ',IH
        END IF
C---- EPS = multiplicity of reflection. ISYSAB = 1 - systematic absence
        CALL EPSLON(IH,EPS,ISYSAB)
        IF (EPS.GT.1.0) THEN
          NEPS = NEPS + 1
          WRITE (6,FMT='(/,A,3I4,F8.2)') '  EPS GT 1 ',IH,EPS
          IF (ISYSAB.EQ.1) THEN
            NSYSAB = NSYSAB + 1
            WRITE (6,FMT='(/,A,3I4,F8.2)') ' SYS ABS  ',IH
          END IF
        END IF
        NCHK = MOD(JDO40,500)
        IF (NCHK.EQ.1) THEN
          IH(1) = ADATA(1)
          IH(2) = ADATA(2)
          IH(3) = ADATA(3)
          WRITE (6,FMT=6004) JDO40,IERR,IH, (ADATA(II),II=4,NCOL)
        END IF
C---- Do something .....
        F1 = (ADATA(4)+ADATA(6))/2
        F2 = (ADATA(4)-ADATA(6))/2
        ADATA(6) = F1
        ADATA(7) = ADATA(5)
        ADATA(8) = F2
        ADATA(9) = ADATA(5)
C---- New write routine
        IF (NCHK.EQ.1) WRITE (6,FMT=6006) JDO40,
     +      (ADATA(II),II=1,NLPRGO)
        IERR = -1
        ICALL = ICALL + 1
        CALL LWREFL(IFIL,ADATA)
   40 CONTINUE
      WRITE (6,FMT=6008) NCEN,NEPS,NSYSAB
C---- Close output file  - This call actually writes the header
      CALL LWCLOS(IFIL,2)
      CALL CCPERR(0, 'Normal termination')
C---- Format statements
 6000 FORMAT (' No assignment using default of ',A)
 6002 FORMAT (' index for MLABSO = ',I4,' prog lab ',A,' user label ',A)
 6004 FORMAT (' NREF IEND - IP DATA ',I8,I3,/1X,3I4,10F8.1,
     +       10 (/13X,10F8.1))
 6006 FORMAT (' NREF OP DATA ',I8,/1X,3F6.2,10F8.1,10 (/13X,10F8.1))
 6008 FORMAT (' END OF FILE - NUMBER OF CENTRIC REFLNS',I5,/' NUMBER O',
     +       'F EPS GT 1 ',I5,/' NUMBER OF SYS ABS ',I5)
      END

AUTHORS AND HISTORY

Sandra McLaughlin and Howard Terry (EMBLHH) November 1989
Header handling revised: SMM November 1990
Multi-record routines: SMM Feb 1990
Symmetry handling routines: Eleanor Dodson (York)
First limited release to an unsuspecting public May 1991

Missing Number Flag routines: 1996-ish

Dataset handling: Martyn Winn 1998-2002

Conversion to C functions: Martyn Winn 2001-2003