;+ 
;NAME: 
;	FILE.PRO 
; 
;LAST CHANGED: ----------------------------------- 26-feb-00 
; 
;PURPOSE: 
;	This set of functions processes text information associated with 
; reading ascii data files. 
; 	ISNUMBER - check if string is numerical 
;	PARSESTRING - splits text string into constituent numbers. 
;	CHKFILEBLOCKS - determines block structure of a text string 
;	TEXT_READ - multi-block file read-in 
;	TEXT_READ1 - simple text file read-in (single block) 
; 
;CATEGORY: 
;	STAND ALONE: utilities 
; 
;CALLING SEQUENCE: 
;	Result = text_READ1(FILNENAME) etc 
; 
;CALLED FROM AXIS: 
;	many procedures 
; 
;ROUTINES 
;	function ISNUMBER, STRING 
;	returns 1 if string is numerical 
; 
;	function PARSESTRING, STRING 
; 	if the input string is a tab or space delimited list of #s, 
; parsestring returns an array of numbers. 
; if no numbers are found, or other error, returns 0 
; you can distinguish the error from "0.0" using the size function, 
; since the error condition is a scalar, not a vector 
; 
;	function CHKFILEBLOCKS, FNAME 
;	looks in FILE (fname), counts the number of "blocks" of data, where 
; a block is a (r x c) block of numbers. If there are no blocks found, 
; returns a scalar 0, else returns a (b, 2)-dim array, where b is the 
; block index, (b,0) is the number of rows, (b,1) is the number of columns 
; and (b,2) is the starting row in the file (counting from 0) 
; 
;	function TEXT_READ, FNAME, block=b, blkInfo=bi 
;	reads the bth block (starting from zero) in the file 
; and returns the contents as a matrix 
; KEYWORDS: 
;	BLOCK - block number to read 
;	BLKINFO - string array for header information for block 
; 
;	function 	TEXT_READ1, FNAME, print=print 
; reads simple text files consisting of 1 block plus a header 
; KEYWORDS 
;	PRINT - if set, then print header information 
; 
;COMMON BLOCKS: none 
; 
;----------------- 
; FILE ROUTINES -- eli's text format 
;----------------- 
;file structure- 
;line 0: number of items 
;line 1: string=name of first item 
;line 2: size(item) 
;line 3: item, space-delimited 
;line 4: string=name of next item 
;    : 
;    : 
; 
;MODIFICATION HISTORY: 
; (25-may-99 aph) activated print option in textread1 to work with ascii read-in 
; (26-feb-00 aph) AXIS standard documentation 
;- 
; ******************************************************************************* 
function isNumber, string 
  ;returns 1 if string is a number else 
  on_Error,2 
  error=0 
  for i=0, strlen(string)-1 do begin 
    ch=strmid(string, i, 1) 
    if ((ch ge '0') and (ch le '9')) or (ch eq 'e') or (ch eq 'E') $ 
       or (ch eq '+') or (ch eq '-') or (ch eq '.') or (ch eq string(13B)) then $ 
         error=error else error=error+1 
  endfor 
  return,(error eq 0) 
end 
 
; ******************************************************************************* 
function parseString, string 
;given string, which is a tab or space delimited list of #s, 
;returns an array of numbers. 
;if no numbers are found, or other error, returns 0 
;you can distinguish the error from "0.0" using the size function, 
;since the error condition is a scalar, not a vector 
  on_Error,2 
  sa=strarr(500) 
  string=strtrim(string, 2) ;removes leading/trailing space 
  string=strcompress(string) ; tabs, multi-space-> space 
 
  ;count the number of items --> sa 
 ; i=0 
 ; cnt=0 
 ; if strlen(string) ne 0 then begin 
 ;   while(i ne -1) do begin 
 ;     j=strpos(string, ' ', i) 
 ;     if(j ne -1) then begin 
 ;       sa(cnt)=strmid(string, i, j-i) 
 ;       cnt=cnt+1 
 ;       i=j+1 
 ;     endif else begin 
 ;       sa(cnt)=strmid(string, i, strlen(string)-i) 
 ;       cnt=cnt+1 
 ;       i=-1 
 ;     endelse 
 ;   endwhile 
 ;   sa=sa(0:cnt-1) 
 ; endif 
 
  sa=str_sep(string, ' ') 
  cnt=n_elements(sa) 
 
  if(cnt gt 0) then begin 
    fa=fltarr(cnt) 
    error=0 
;check that the first column is a number and then assume they all are 
;    if isNumber(sa(0)) then reads,sa,fa else error=1 
;check each item one at a time; if number, then copy to fa 
    flt=0.0 
    error=0 
    for i=0,cnt-1 do begin 
      if isNumber(sa(i)) eq 1 then begin 
        reads,sa(i),flt 
        fa(i)=flt 
      endif else begin 
        error=+1 
      endelse 
    endfor ;i 
; 
    if error then ans=0 else ans=fa 
  endif else ans=0 
  return,ans 
end 
 
; ******************************************************************************* 
function chkFileBlocks,fname 
  ;looks in fname, counts the number of "blocks" of data, where 
  ;a block is a (r x c) block of numbers. If there are no blocks found, 
  ;returns a scalar 0, else returns a (b, 2)-dim array, where b is the 
  ;block index, (b,0) is the number of rows, (b,1) is the number of columns 
  ;and (b,2) is the starting row in the file (counting from 0) 
  on_error,2 
  bcnt=-1 
  col=-1 
  row=0 
  barr=intarr(100,3) 
  s='' 
  lcnt=-1 
  openr, unit, fname, /GET_LUN 
  while(not eof(unit)) do begin 
;print,lcnt 
    ;get a line from the file 
    lcnt=lcnt+1 
    readf,unit,s 
    fa=parseString(s) & sfa=size(fa) 
    if sfa(0) gt 0 then begin 
      ;line contains numbers 
      if sfa(1) ne col then begin 
        ;new block size found 
	;setup next block 
        row=1 
        col=sfa(1) 
        bcnt=bcnt+1 
	barr(bcnt,0)=row 
	barr(bcnt,1)=col 
        barr(bcnt,2)=lcnt 
      endif else begin 
	;continuation of previous block 
	row=row+1 
        barr(bcnt,0)=row 
      endelse 
    endif else begin 
      ;non-numerical line found, indicates end of block and maybe new one 
      if(col gt 0) then begin 
 	;end of previous block 
        barr(bcnt,0)=row 
        barr(bcnt,1)=col 
      endif 
      col=-1 
      row=0 
    endelse 
  endwhile 
  if (bcnt ge 0) then ans=barr(0:bcnt,*) else ans=0 
  FREE_LUN, unit 
  return,ans 
end 
 
; ******************************************************************************* 
function text_read, fname, block=b, blkInfo=bi 
; reads the bth block (starting from zero) in the file and returns as a matrix 
 
  on_error,2 
  if keyword_set(bi) eq 0 then a=chkfileblocks(fname) else a=bi 
  if keyword_set(b) ne 0 then begin 
    start=a(b,2) 
    nrow=a(b,0) 
    ncol=a(b,1) 
  endif else begin 
    start=a(0,2) 
    nrow=a(0,0) 
    ncol=a(0,1) 
  endelse 
  openr, unit, fname, /get_lun 
  if start gt 0 then begin 
    s=strarr(start) 
    readf,unit,s 
  endif 
  ans=fltarr(ncol, nrow) 
  readf,unit,ans 
  as=size(ans) 
  if (as(0) eq 1) and (as(1) eq 1) then ans=ans(0,0) ;single #,convert to scalar 
  if (as(0) eq 2) and (as(1) eq 1) then begin 
    ;single column, convert to 1-dim array 
    b=fltarr(as(2)) 
    for i=0,as(2)-1 do b(i)=ans(0,i) 
    ans=b 
  endif 
  close, unit 
  free_lun,unit 
  return,ans 
end 
 
; ******************************************************************************* 
function text_read1,fname, PRINT=print 
   ;reads simple files which only consist of header info and one block 
   on_error,2 
   s='' 
   openr,unit,fname,/get_lun 
   while not eof(unit) do begin 
      readf,unit,s 
      fa=parsestring(s) & sfa=size(fa) 
      if keyword_set(print) and sfa(0) EQ 0 then print, s 
      if sfa(0) gt 0 then begin 
        ;line contains numbers 
	nrows=6000 
        ans=fltarr(sfa(1), nrows) 
        ans(*,0)=fa 
        j=long(1) 
        while not eof(unit) do begin 
           ;if j/100 eq j/100. then print,j 
           readf,unit,fa 
           ans(*,j)=fa 
           j=j+1 
        endwhile 
      endif 
   endwhile 
   close,unit 
   free_lun,unit 
   return,ans(*,0:j-1) 
end 
;----------------- 
; FILE ROUTINES -- eli's text format 
;----------------- 
;file structure- 
;line 0: number of items 
;line 1: string=name of first item 
;line 2: size(item) 
;line 3: item, space-delimited 
;line 4: string=name of next item 
;    : 
;    : 
;pro save,savearr 
;  openw, unit, fname, /get_lun 
;  ne=n_elements(savearr) 
;  printf,unit,ne 
;  for i=0, ne-1 
;    printf,unit,savearr(0) 
;    printf,unit 
;  endfor 
;end 
 
