Re: Reading unformatted binary record

From: Dennis Shea <shea_at_nyahnyahspammersnyahnyah>
Date: Thu, 7 Dec 2006 12:16:23 -0700 (MST)

>I need some help in reading unformatted binary sequential access data
>I have a series of file each of which has 12 records. Each of these
>records have a 80 byte header followed by a 180x90 array of floating
>point data
>
>I have been doing the following to read as an example:
>
> data = fbinrecread(filename,0,-1,"byte") ; read the entire first record
>into one single dimension array
>
>head = data(0:79) ; get the header information
>tdata = onedtond(byte2flt(data(80:64879)),(/180,90/)) ;get the rest of
>the data, convert from byte to float and regrid to 180x90
>
>But tdata values seems to be still in Bytes and doesnt show any floating
>point values.
>
>What am i doing wrong?
>
>A program in Fortran for reading such files should have been like:
>
> CHARACTER*80 HEAD
> REAL*4 TDATA(180,90)
>
> OPEN(1,FORM='UNFORMATTED')
> DO 10 M=1,12
> READ(1) HEAD,TDATA
> WRITE(*,*) HEAD
>
>10 CONTINUE
=======================================================
=======================================================
  mlon = 180
  nlat = 90

[1]
An NCL limitation when reading fortran sequential records
is that records must be of the same type. The above
mixed type record is not supported. If the sequential
file had been written via:
       DO M=1,12
          WRITE(1) HEAD ! character
          WRITE(1) TDATA ! real/float
       END DO
then the following could be used:

  do n=0,11
     head = fbinrecread(fNam, 2*n , 80, "character")
     data = fbinrecread(fNam, 2*n+1, (/nlat,mlon/) , "float")
     
     heads= chartostring( head )
  end do

[1a]
**If** the header had been of type integer [say, HEAD(1)=2000,
HEAD(2)=12, HEAD(3)=7, HEAD(4)=12] an written via
     integer HEAD(4)
     WRITE(1)HEAD,TDATA
then the following could be used
     headData = fbinrecread(fNam, n, 4 + nlat*mlon , "float")
     year = floattointeger( headData(0) )
              :
     hour = floattointeger( headData(3) )
     data = onedtond( headData(3:) , (/nlat,mlon/) )

[2]
In your case, the solution is to use a fortran shared object.
This is very easy. See:
http://www.ncl.ucar.edu/Document/Manuals/Ref_Manual/NclExtend.shtml

An untested fortran subroutine "rdHeadData.f".

Just use

    WRAPIT rdHeadData.f
    
Then try the following after inserting the file name [untested]

    ncl rdHeadData.ncl
    
    
good luck

C NCLFORTSTART
      subroutine rdssarker(fname,tdata,head)
      character*(*) head
      character*(*) fname
      real tdata(180,90)
C NCLEND
      data iflag /0/
      save iflag

      if (ientry.eq.0) then
          OPEN(1,file=fname,FORM='UNFORMATTED')
          ientry = 1
      end if

      READ(1) HEAD, TDATA

      RETURN
      END

external RDFORT "./rdHeadData.so"
begin
  nRec = 12
  mlon = 180
  nlat = 90

  fNam = " ... "

  headc = new( 80 , "character")
  head = new(nRec, "string")
  tdata = new( (/nRec,nlat,mlon/), "float")

  do n=0,nRec-1
     RDFORT::rdssarker(fNam, tdata(n,:,:), headc)
     head(n) = chartostring(headc)

     print("n="+n+" "+heads(n))
     print("n="+n+" min="+min(tdata(n,:,:)) \
                 +" max="+max(tdata(n,:,:)) )
  end do

end

_______________________________________________
ncl-talk mailing list
ncl-talk_at_ucar.edu
http://mailman.ucar.edu/mailman/listinfo/ncl-talk
Received on Thu Dec 07 2006 - 12:16:23 MST

This archive was generated by hypermail 2.2.0 : Thu Dec 07 2006 - 16:52:37 MST