start adding triumf mud-file-format support. For a few days musrfit will be a bit frail.
This commit is contained in:
581
src/external/mud/readme
vendored
Normal file
581
src/external/mud/readme
vendored
Normal file
@@ -0,0 +1,581 @@
|
||||
|
||||
MUD Data Format
|
||||
|
||||
Overview:
|
||||
|
||||
The muon data (MUD) format used at TRIUMF is an efficent framework
|
||||
for storing and retrieving muSR data. Its existing structure is
|
||||
optimized for muSR data, but the basic framework is universal and
|
||||
the definition is extensible, so it can grow to meet new demands.
|
||||
|
||||
The MUD 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
|
||||
number specifying the instance of the type (instanceID).
|
||||
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. Type identifiers can be assigned to new Section types
|
||||
used for applications local to a lab, but the ideal is to have
|
||||
shared data type specifications, with generally-accepted ID codes.
|
||||
To this end, ranges of secID numbers are reserved for individual
|
||||
laboratories, to prevent conflicts of local definitions.
|
||||
Additionally, there is a range for generic secIDs whose
|
||||
definitions can be collected (at TRIUMF) and distributed with
|
||||
the MUD program libraries.
|
||||
|
||||
File Contents:
|
||||
|
||||
A MUD data format file consists of sequential contiguous Sections
|
||||
in a stream file. Common to all types of MUD Section is a small
|
||||
Core structure giving Section type and instance, size, and a
|
||||
pointer to the next Section. This design, with the relative file
|
||||
position of the next Section encoded into the Core part of each
|
||||
Section, allows for traversal of the file and for the modification
|
||||
of the contents of a Section type while maintaining backwards
|
||||
compatibility with MUD file readers.
|
||||
|
||||
Sections of any combination of types may be organized into Groups.
|
||||
The Group is simply a class of MUD Section which indicates that a
|
||||
number of following Sections are to be grouped together. The Group
|
||||
provides an index of (relative file position) pointers to those
|
||||
ensuing Sections, which may be thought of as being contained within
|
||||
the Group Section. The whole MUD file is a particular case
|
||||
of a MUD group.
|
||||
|
||||
The most important MUD Sections are those that hold data, and
|
||||
the secID implies how to read that data. Not only the content
|
||||
and the organization, but also the encoding are specified by the
|
||||
definition of the Section type. Encoding includes byte order
|
||||
and floating-point format (although floating-point should be
|
||||
avoided). The MUD library includes standard routines to read
|
||||
the file's encoding into the computer's native format.
|
||||
|
||||
Copying MUD files:
|
||||
|
||||
MUD files are pure binary streams, without any record format.
|
||||
This is attractive for moving files between operating systems,
|
||||
some of which have no concept of file records. On VMS systems,
|
||||
with a rich repertoire of record types, MUD files are typically
|
||||
called "stream LF" because that is what C programs automatically
|
||||
produce, even though the correct type should be "stream". FTP
|
||||
transfer between VMS and Unix systems does not work well, because
|
||||
it usually assumes a particular record format (fixed 512 byte
|
||||
records) on the VMS end. To use FTP one should first "zip" the
|
||||
files, and transfer the zip archive. NFS works well.
|
||||
|
||||
Software Library/Applications:
|
||||
|
||||
It is intended that the data be accessed via the set of supplied
|
||||
routines for reading and writing the MUD format. There are both
|
||||
high-level (API) routines for accessing particular components of
|
||||
existing MUD Sections, and low-level routines used to implement
|
||||
the API or to read and write MUD files directly. If such
|
||||
low-level access is desired, inspection of the (C language) source
|
||||
code (which is not extensive) should reveal the necessary
|
||||
information.
|
||||
|
||||
Defining New Types:
|
||||
|
||||
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 Example 1)
|
||||
|
||||
2. Writing one C subroutine that handles the specifics of
|
||||
the I/O, etc., in a brief and well-defined manner
|
||||
(Example 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.
|
||||
|
||||
and optionally,
|
||||
|
||||
5. Adding the corresponding "friendly" API functions.
|
||||
|
||||
The Section definition and its ID should be contributed to the
|
||||
centralized library (maintained at TRIUMF), allowing all MUD-aware
|
||||
applications to understand them.
|
||||
|
||||
Applications may be written in C or Fortran and linked to the MUD
|
||||
library, although the natural language is C for low-level access.
|
||||
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 Example 3). Alternatively, the
|
||||
I/O of each Section may be done separately, also in both languages
|
||||
(see Example 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.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Example 1. Sample MUD format structure (in C; from mud.h)
|
||||
|
||||
typedef struct {
|
||||
MUD_CORE core;
|
||||
|
||||
UINT32 ID;
|
||||
UINT32 prevReplyID;
|
||||
UINT32 nextReplyID;
|
||||
TIME time;
|
||||
char* author;
|
||||
char* title;
|
||||
char* comment;
|
||||
} MUD_SEC_CMT;
|
||||
|
||||
|
||||
The same structure for (VAX) Fortran (from mud.finc)
|
||||
|
||||
structure /MUD_SEC_CMT/
|
||||
record /MUD_CORE/ core
|
||||
|
||||
integer*4 ID
|
||||
integer*4 prevReplyID
|
||||
integer*4 nextReplyID
|
||||
integer*4 time
|
||||
integer*4 pcsAuthor
|
||||
integer*4 pcsTitle
|
||||
integer*4 pcsComment
|
||||
end structure
|
||||
|
||||
The same structure for Fortran 90/95 (from mud.f90)
|
||||
|
||||
type MUD_SEC_CMT
|
||||
sequence
|
||||
type(MUD_CORE) core
|
||||
|
||||
integer*4 ID
|
||||
integer*4 prevReplyID
|
||||
integer*4 nextReplyID
|
||||
integer*4 time
|
||||
integer*4 pcsAuthor
|
||||
integer*4 pcsTitle
|
||||
integer*4 pcsComment
|
||||
end type
|
||||
|
||||
Note that the Fortran structures are identical to the C structure,
|
||||
including the use of pointers to strings. Subroutines are provided
|
||||
for conversion between these pointers and ordinary Fortran character
|
||||
variables (see Example 4, fMUD_ctofString).
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Example 2. Subroutine to handle the type in Example 1:
|
||||
|
||||
|
||||
int
|
||||
MUD_SEC_CMT_proc( op, pBuf, pMUD )
|
||||
MUD_OPT op;
|
||||
BUF* pBuf;
|
||||
MUD_SEC_CMT* pMUD;
|
||||
{
|
||||
int size;
|
||||
char tempStr1[32];
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case MUD_FREE:
|
||||
_free( pMUD->author );
|
||||
_free( pMUD->title );
|
||||
_free( pMUD->comment );
|
||||
break;
|
||||
case MUD_DECODE:
|
||||
decode_4( pBuf, &pMUD->ID );
|
||||
decode_4( pBuf, &pMUD->prevReplyID );
|
||||
decode_4( pBuf, &pMUD->nextReplyID );
|
||||
decode_4( pBuf, &pMUD->time );
|
||||
decode_str( pBuf, &pMUD->author );
|
||||
decode_str( pBuf, &pMUD->title );
|
||||
decode_str( pBuf, &pMUD->comment );
|
||||
break;
|
||||
case MUD_ENCODE:
|
||||
encode_4( pBuf, &pMUD->ID );
|
||||
encode_4( pBuf, &pMUD->prevReplyID );
|
||||
encode_4( pBuf, &pMUD->nextReplyID );
|
||||
encode_4( pBuf, &pMUD->time );
|
||||
encode_str( pBuf, &pMUD->author );
|
||||
encode_str( pBuf, &pMUD->title );
|
||||
encode_str( pBuf, &pMUD->comment );
|
||||
break;
|
||||
case MUD_GET_SIZE:
|
||||
size = 3*sizeof( UINT32 );
|
||||
size += 1*sizeof( TIME );
|
||||
size += sizeof( MUD_STR_LEN_TYPE ) + _strlen( pMUD->author );
|
||||
size += sizeof( MUD_STR_LEN_TYPE ) + _strlen( pMUD->title );
|
||||
size += sizeof( MUD_STR_LEN_TYPE ) + _strlen( pMUD->comment );
|
||||
return( size );
|
||||
case MUD_SHOW:
|
||||
printf( " MUD_SEC_CMT: \n" );
|
||||
printf( " number:[%ld], prevReply:[%ld], nextReply:[%ld]\n",
|
||||
pMUD->ID, pMUD->prevReplyID, pMUD->nextReplyID );
|
||||
strcpy( tempStr1, ctime( (time_t*)&pMUD->time ) );
|
||||
tempStr1[strlen(tempStr1)-1] = '\0';
|
||||
printf( " time:[%s]\n", tempStr1 );
|
||||
if( pMUD->author ) printf( " author:\"%s\"\n", pMUD->author );
|
||||
if( pMUD->title ) printf( " title:\"%s\"\n", pMUD->title );
|
||||
if( pMUD->comment ) printf( " comment:\"%s\"\n", pMUD->comment );
|
||||
break;
|
||||
case MUD_HEADS:
|
||||
printf( "Comment number %ld. ", pMUD->ID );
|
||||
if( pMUD->prevReplyID > 0 )
|
||||
printf(" Re: #%ld. ", pMUD->prevReplyID );
|
||||
if( pMUD->nextReplyID > 0 )
|
||||
printf(" Next: #%ld.", pMUD->nextReplyID );
|
||||
printf( "\n" );
|
||||
strcpy( tempStr1, ctime( (time_t*)&pMUD->time ) );
|
||||
tempStr1[strlen(tempStr1)-1] = '\0';
|
||||
if( pMUD->author ) printf( " author: %s, time: %s\n", pMUD->author, tempStr1 );
|
||||
if( pMUD->title ) printf( " title: %s\n", pMUD->title );
|
||||
if( pMUD->comment ) printf( "%s\n", pMUD->comment );
|
||||
break;
|
||||
}
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Example 3. Sample C application:
|
||||
|
||||
/*
|
||||
* mud_test.c
|
||||
*/
|
||||
|
||||
#include 'mud.h'
|
||||
|
||||
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 (header for) the third histogram in the TD histogram group
|
||||
*/
|
||||
pMUD_hist = MUD_search( pMUD_head, MUD_SEC_GROUP_ID, MUD_GRP_TRI_TD_HIST_ID,
|
||||
MUD_SEC_GEN_HIST_HDR_ID, 3,
|
||||
0 );
|
||||
printf( "Number of bins: %d\n", pMUD_hist->nBins )
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Example 4. Sample Fortran applications:
|
||||
|
||||
Modern Fortran:
|
||||
~~~~~~~~~~~~~~~
|
||||
program mud_test_fortran
|
||||
implicit none
|
||||
|
||||
include 'mud.f90'
|
||||
|
||||
integer, parameter :: i4 = selected_int_kind(9) ! integer*4
|
||||
|
||||
integer(kind=i4) status
|
||||
integer(kind=i4) i
|
||||
character(len=32) filename
|
||||
integer(kind=i4) fileHandle
|
||||
character(len=20) title
|
||||
|
||||
type(MUD_SEC_GEN_HIST_HDR) MUD_hist_hdr(8)
|
||||
|
||||
|
||||
!
|
||||
! Open an MUD format file
|
||||
!
|
||||
filename = '001234.msr'
|
||||
|
||||
fileHandle = fMUD_openInput( filename )
|
||||
if (fileHandle .eq. 0) then
|
||||
write (*,*) 'Could not open file ',filename,
|
||||
+ ' (',fileHandle,')'
|
||||
stop
|
||||
endif
|
||||
write (*,*) 'Opened file ', filename
|
||||
|
||||
!
|
||||
! Position the file before the first histogram of the
|
||||
! TD histogram group
|
||||
!
|
||||
status = fMUD_fseek( fileHandle,
|
||||
+ MUD_SEC_GRP_ID, MUD_GRP_TRI_TD_HIST_ID,
|
||||
+ 0, 0 )
|
||||
if( status .eq. -1 ) then
|
||||
write (*,*) 'Failed to find histogram group! status=',status
|
||||
goto 999
|
||||
endif
|
||||
!
|
||||
! Read the histogram headers
|
||||
!
|
||||
|
||||
do i=1,8 ! we dimensioned MUD_hist_hdr(8)
|
||||
|
||||
status = fMUD_fseek( fileHandle,
|
||||
+ MUD_SEC_GEN_HIST_HDR_ID, i,
|
||||
+ 0)
|
||||
!
|
||||
! If no more histograms, then we are finished:
|
||||
!
|
||||
if (status .eq. -1 ) exit
|
||||
|
||||
status = fMUD_read( fileHandle, MUD_hist_hdr(i) )
|
||||
|
||||
!
|
||||
! Access the histogram title
|
||||
!
|
||||
if (status.eq.1) then
|
||||
call fMUD_ctofString( title, MUD_hist_hdr(i)%pcsTitle )
|
||||
write (*,*) 'histogram ',i,' title = "',trim(title),'"'
|
||||
else
|
||||
write (*,*) 'Failed to read header for histogram',i
|
||||
endif
|
||||
|
||||
end do
|
||||
|
||||
999 continue
|
||||
|
||||
call fMUD_close( fileHandle )
|
||||
|
||||
end program mud_test_fortran
|
||||
|
||||
|
||||
|
||||
Sample for VAX Fortran:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
program mud_test_fortran
|
||||
implicit none
|
||||
|
||||
include 'mud.finc'
|
||||
|
||||
integer*4 status
|
||||
integer*4 i
|
||||
character*32 filename
|
||||
integer*4 fileHandle
|
||||
character*20 title
|
||||
|
||||
record /MUD_SEC_GEN_HIST_HDR/ MUD_hist_hdr(8)
|
||||
|
||||
|
||||
!
|
||||
! Open an MUD format file
|
||||
!
|
||||
filename = '001234.msr'
|
||||
|
||||
fileHandle = fMUD_openInput( filename )
|
||||
if (fileHandle .eq. 0) then
|
||||
write (*,*) 'Could not open file ',filename,
|
||||
> ' (',fileHandle,')'
|
||||
stop
|
||||
endif
|
||||
write (*,*) 'Opened file ', filename
|
||||
|
||||
!
|
||||
! Position the file before the first histogram of the
|
||||
! TD histogram group
|
||||
!
|
||||
status = fMUD_fseek( fileHandle,
|
||||
+ MUD_SEC_GRP_ID, MUD_GRP_TRI_TD_HIST_ID,
|
||||
+ 0, 0 )
|
||||
if( status .eq. -1 ) then
|
||||
write (*,*) 'Failed to find histogram group! status=',status
|
||||
goto 999
|
||||
endif
|
||||
!
|
||||
! Read the histogram headers
|
||||
!
|
||||
|
||||
do i=1,8 ! we dimensioned MUD_hist_hdr(8)
|
||||
|
||||
status = fMUD_fseek( fileHandle,
|
||||
+ MUD_SEC_GEN_HIST_HDR_ID, i,
|
||||
+ 0)
|
||||
!
|
||||
! If no more histograms, then we are finished:
|
||||
!
|
||||
if (status .eq. -1 ) goto 999
|
||||
|
||||
status = fMUD_read( fileHandle, MUD_hist_hdr(i) )
|
||||
|
||||
!
|
||||
! Access the histogram title
|
||||
!
|
||||
if (status.eq.1) then
|
||||
call fMUD_ctofString( title, MUD_hist_hdr(i).pcsTitle )
|
||||
write (*,*) 'histogram ',i,' title = "',title,'"'
|
||||
else
|
||||
write (*,*) 'Failed to read header for histogram',i
|
||||
endif
|
||||
|
||||
end do
|
||||
|
||||
999 continue
|
||||
|
||||
call fMUD_close( fileHandle )
|
||||
|
||||
end ! program mud_test_fortran
|
||||
|
||||
|
||||
Sample for old (but extended) Fortran77 (g77):
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
program mud_test_fortran
|
||||
|
||||
include 'mud.f77'
|
||||
|
||||
integer*4 status
|
||||
integer*4 i
|
||||
character*32 filename
|
||||
integer*4 fileHandle
|
||||
character*20 title
|
||||
|
||||
integer*4 MUD_hist_hdr
|
||||
|
||||
* Hist header structure, implemented as a common block.
|
||||
* All hist header elements are named hh_... The core elements
|
||||
* are named hh_c_...
|
||||
|
||||
integer*4 hh_c_pNext !* pointer to next section *
|
||||
integer*4 hh_c_size
|
||||
integer*4 hh_c_secID !* Ident of section type *
|
||||
integer*4 hh_c_instanceID
|
||||
integer*4 hh_c_sizeof
|
||||
integer*4 hh_c_proc
|
||||
!
|
||||
integer*4 hh_histType
|
||||
integer*4 hh_nBytes
|
||||
integer*4 hh_nBins
|
||||
integer*4 hh_bytesPerBin
|
||||
integer*4 hh_fsPerBin
|
||||
integer*4 hh_t0_ps
|
||||
integer*4 hh_t0_bin
|
||||
integer*4 hh_goodBin1
|
||||
integer*4 hh_goodBin2
|
||||
integer*4 hh_bkgd1
|
||||
integer*4 hh_bkgd2
|
||||
integer*4 hh_nEvents
|
||||
integer*4 hh_pcsTitle
|
||||
|
||||
|
||||
common /cmn_hdr/
|
||||
+ hh_c_pNext, hh_c_size, hh_c_secID, hh_c_instanceID,
|
||||
+ hh_c_sizeof, hh_c_proc,
|
||||
+ hh_histType, hh_nBytes, hh_nBins, hh_bytesPerBin,
|
||||
+ hh_fsPerBin, hh_t0_ps, hh_t0_bin, hh_goodBin1, hh_goodBin2,
|
||||
+ hh_bkgd1, hh_bkgd2, hh_nEvents, hh_pcsTitle
|
||||
|
||||
equivalence(hh_c_pNext,MUD_hist_hdr)
|
||||
|
||||
!
|
||||
! Open an MUD format file
|
||||
!
|
||||
filename = '001234.msr'
|
||||
|
||||
fileHandle = fMUD_openInput( filename )
|
||||
if (fileHandle .eq. 0) then
|
||||
write (*,*) 'Could not open file ',filename,
|
||||
> ' (',fileHandle,')'
|
||||
stop
|
||||
endif
|
||||
write (*,*) 'Opened file ', filename
|
||||
|
||||
!
|
||||
! Position the file before the first histogram of the
|
||||
! TD histogram group
|
||||
!
|
||||
status = fMUD_fseek( fileHandle,
|
||||
+ MUD_SEC_GRP_ID, MUD_GRP_TRI_TD_HIST_ID,
|
||||
+ 0 )
|
||||
if( status .eq. -1 ) then
|
||||
write (*,*) 'Failed to find histogram group! status=',status
|
||||
goto 999
|
||||
endif
|
||||
!
|
||||
! Read the histogram headers
|
||||
!
|
||||
do i=1,16
|
||||
|
||||
status = fMUD_fseek( fileHandle,
|
||||
+ MUD_SEC_GEN_HIST_HDR_ID, i,
|
||||
+ 0 )
|
||||
|
||||
if (status .eq. -1 ) goto 999
|
||||
|
||||
status = fMUD_read( fileHandle, MUD_hist_hdr )
|
||||
|
||||
!
|
||||
! Access the histogram title
|
||||
!
|
||||
if (status.eq.1) then
|
||||
call fMUD_ctofString( title, hh_pcsTitle )
|
||||
write (*,*) ' histogram title = <', title, '>'
|
||||
else
|
||||
write (*,*) ' Failed to read header for histogram',i
|
||||
endif
|
||||
|
||||
end do
|
||||
|
||||
999 continue
|
||||
call fMUD_close( fileHandle )
|
||||
stop
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user