mud_fmt.txt
by
admin
—
last modified
Apr 13, 2006 06:24 PM
MUD Data Format
Overview:
The MUD data format is characterized by the organization of data
into Sections. The instance of each Section is defined by two long
integers: the type identification (secID) and a secondary
identification specifying the instance of the type (instanceID).
Sections of any combination of types may be organized into Groups.
The format has been designed to allow for quick implementation of
new section types or modifications of old types, high flexibility
while maintaining a standard, and ease of use for the application
programmer.
File Contents:
An MUD data format file consists of sequential Sections in a stream
file. The contents of each Section are located together
contiguously. The relative file position of the next Section is
encoded into the Core part of each Section to allow for traversal
of the file and for the modification of the contents of a Section
type while maintaining backwards compatibility with MUD file readers.
The Group is a special Section that simply indicates that the
following n Sections are to be grouped. It is intended that the
data be accessed via the set of supplied routines for reading and
writing the MUD format. If low-level access is desired, inspection
of the source code (which is not extensive) should readily reveal
the necessary information.
Software Library/Applications:
A library of routines is provided for the reading and writing of
the data format from well-defined data structures. The
specification of a Section type includes the following four steps:
1. Definition of a structure in C, and optionally a
corresponding structure in FORTRAN (see Figure 1).
2. Writing one C subroutine that handles the specifics of
the I/O, etc., in a brief and well-defined manner (see
Figure 2).
3. Adding an entry to the C subroutine that dynamically
creates instances of each Section.
4. Reserving the unique 32-bit integer identifier(s) for
the new type.
After having added these to the library (maintained centrally at
TRIUMF), applications may be written in C or FORTRAN to perform the
I/O. In C, the Sections may be written from a linked list of
structures. Routines are available for the creation of Sections and
maintaining the list. In both languages, the entire file may be
read into a linked list, and then search routines are used to access
specific Sections of the list (see Figure 3). Alternatively, the
I/O of each Section may be done separately, also in both languages
(see Figure 4). Access to individual Sections in the data file
may be sequential or pseudo-direct. The pseudo-direct access
involves the call to a routine with the request for a Section of a
certain ID; the routine then searches the file from the current
position for the requested Section and positions the file pointer
to the beginning of this Section.
--------------------------------------------------------------------------------
Figure 1. Sample MUD format structure (in C):
/* Generic histogram structure */
typedef struct {
MUD_SEC_CORE core;
u_long histType;
u_long nBytes;
u_long nRec;
u_long nBins;
u_long bytesPerBin;
u_long fsPerBin;
u_long t0_ps;
u_long t0_bin;
u_long goodBin1;
u_long goodBin2;
u_long bkgd1;
u_long bkgd2;
u_long nEvents;
char* title;
caddr_t pData; /* pointer to the histogram data */
} MUD_SEC_GEN_HIST;
The same structure for FORTRAN:
! Generic histogram structure
structure /MUD_SEC_GEN_HIST/
record /MUD_SEC_CORE/ core
integer*4 histType
integer*4 nBytes
integer*4 nRec
integer*4 nBins
integer*4 bytesPerBin
integer*4 fsPerBin
integer*4 t0_ps
integer*4 t0_bin
integer*4 goodBin1
integer*4 goodBin2
integer*4 bkgd1
integer*4 bkgd2
integer*4 nEvents
integer*4 pcsTitle ! pcs = pointer to c string (zero-term)
integer*4 pData !/* pointer to the histogram data */
end structure
--------------------------------------------------------------------------------
Figure 2. Subroutine to handle the type in Figure 1:
u_long
MUD_SEC_GEN_HIST_proc( MUD_OPT op, BUF* pBuf, MUD_SEC_GEN_HIST* pMUD )
{
u_long size;
switch( op )
{
case MUD_FREE:
_free( pMUD->title );
_free( pMUD->pData );
break;
case MUD_DECODE:
_decode_obj( pBuf, &pMUD->histType, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->nBytes, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->nRec, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->nBins, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->bytesPerBin, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->fsPerBin, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->t0_ps, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->t0_bin, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->goodBin1, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->goodBin2, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->bkgd1, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->bkgd2, sizeof(u_long) );
_decode_obj( pBuf, &pMUD->nEvents, sizeof(u_long) );
decode_str( pBuf, &pMUD->title );
_alloc_buf( pMUD->pData, char*, pMUD->nBytes );
_decode_obj( pBuf, pMUD->pData, pMUD->nBytes );
break;
case MUD_ENCODE:
_encode_obj( pBuf, &pMUD->histType, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->nBytes, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->nRec, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->nBins, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->bytesPerBin, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->fsPerBin, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->t0_ps, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->t0_bin, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->goodBin1, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->goodBin2, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->bkgd1, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->bkgd2, sizeof(u_long) );
_encode_obj( pBuf, &pMUD->nEvents, sizeof(u_long) );
encode_str( pBuf, &pMUD->title );
_encode_obj( pBuf, pMUD->pData, pMUD->nBytes );
break;
case MUD_GET_SIZE:
size = 13*sizeof( u_long );
size += sizeof( MUD_STR_LEN_TYPE ) + _strlen( pMUD->title );
size += pMUD->nBytes;
return( size );
case MUD_SHOW:
printf( " MUD_SEC_GEN_HIST: histType:[0x%08X]\n",
pMUD->histType );
printf( " nBytes:[%d], nRec:[%d], nBins:[%d], nEvents:[%d]\n",
pMUD->nBytes, pMUD->nRec, pMUD->nBins, pMUD->nEvents );
printf( " bytesPerBin:[%d], fsPerBin:[%d], t0_ps:[%d], t0_bin:[%d]\n",
pMUD->bytesPerBin, pMUD->fsPerBin, pMUD->t0_ps, pMUD->t0_bin );
printf( " goodBin1:[%d], goodBin2:[%d], bkgd1:[%d], bkgd2:[%d]\n",
pMUD->goodBin1, pMUD->goodBin2, pMUD->bkgd1, pMUD->bkgd2 );
if( pMUD->title ) printf( " title:\"%s\"\n", pMUD->title );
break;
}
}
--------------------------------------------------------------------------------
Figure 3. Sample C application:
/*
* mud_test.c
*/
#include
int
main( void )
{
FILE* fin;
FILE* fout;
MUD_SEC* pMUD_head = NULL;
MUD_SEC_GEN_RUN_DESC* pMUD_desc;
MUD_SEC_GEN_HIST* pMUD_hist;
char* filename = "006663.mud";
/*
* Read an MUD format file into a linked list
*/
fin = MUD_openInput( filename );
if( fin == NULL ) exit( 0 );
MUD_readFile( fin, &pMUD_head );
fclose( fin );
/*
* Access the third histogram in the TD histogram group
*/
pMUD_hist = MUD_search( pMUD_head, MUD_SEC_GROUP_ID, MUD_GRP_TD_HIST_ID,
MUD_SEC_GEN_HIST_ID, 3,
0 );
/*
* Add a run description section (#2) to the list
*/
pMUD_desc = MUD_new( MUD_SEC_GEN_RUN_DESC_ID, 2 );
MUD_add( &pMUD_head, pMUD_desc );
/*
.
.
.
*/
/*
* Write an MUD format file
*/
fout = MUD_openOutput( filename );
if( fout == NULL ) exit( 0 );
MUD_writeFile( fout, pMUD_head, MUD_FMT_ALL_ID );
fclose( fout );
/*
* Free the linked list
*/
MUD_free( pMUD_head );
}
/*
* end mud_test.c
*/
Compile:
$ cc mud_test.c
Link:
$ link mud_test.obj, mud_lib:mud_fmt/lib, mud_lib:link_options/opt
--------------------------------------------------------------------------------
Figure 4. Sample FORTRAN application:
program mud_test_fortran
include 'mud_lib:mud_defs_fortran.finc'
integer*4 status
integer*4 i
character*32 filename
integer*4 fileHandle
character*80 title
record /MUD_SEC_GEN_HIST/ MUD_hist(4)
!
! Open an MUD format file
!
filename = '006663.mud'
fileHandle = fMUD_openInput( filename )
type *, 'Opened file ', filename
!
! Position the file before the first histogram of the
! TD histogram group
!
status = fMUD_fseek( fileHandle,
+ MUD_SEC_GROUP_ID, MUD_GRP_TD_HIST_ID,
+ MUD_SEC_GEN_HIST_ID, 1,
+ 0 )
type *, 'Seek status = <', status, '>'
!
! Read the first four histograms
!
do i = 1, 4
status = fMUD_read( fileHandle, MUD_hist(i) )
type *, 'Read status = <', status, '> for histogram <', i, '>'
!
! Access the histogram title
!
call fMUD_ctofString( title, MUD_hist(i).pcsTitle )
type *, ' histogram title = <', title, '>'
end do
stop
end
c end program mud_test_fortran
Compile:
$ fort mud_test_fortran.for
Link:
$ link mud_test_fortran.obj, mud_lib:mud_fmt/lib
--------------------------------------------------------------------------------