; docformat = 'rst' ;+ ; :Description: ; Reads an OBSFLUX-type file generated by cmfgen and parses its content to extract each variable in it. ; ; Also works for obs_fin, even though it has less variables in it. ; ; More precisely, the format assumed is a text file where: ; ; Scalars occupy one line, with their name followed by : followed by their value. ; ; Arrays occupy one line for the name, followed by however many lines with however many numbers in each ; with the numbers in each line separated by blanks (space or tab). ; ; An array ends when a name (of the next variable) or the end of the file is reached. ; ; Blank lines anywhere are ignored. ; ; :Returns: ; The results are packed in a structure, see the end of the function for definition of members. ; ; :Params: ; file : in, optional, default='OBSFLUX' ; String with the name of the file to read. ; ; :Examples: ; To read everything from the file 'OBSFLUX':: ; ; obs=pp_cmfread('OBSFLUX') ; print,obs.nscal ; ; 6 ; for i=0,obs.nscal-1 do print,obs.scal[i] ; ;{ Total Line luminosity 0.0000000} ; ;{ Total Dielectronic and Implicit Recombination Luminosity 0.0000000} ; ;{ Total Mechanical Luminosity 1531.0000} ; ;{ Total Shock Luminosity 0.0000000} ; ;{ X-ray Luminosity (> 0.1 keV) 0.0000000} ; ;{ X-ray Luminosity (> 1 keV) 0.0000000} ; ; :Author: Paulo Penteado (pp.penteado@gmail.com), Aug/2009 ;- function pp_cmfread,file compile_opt idl2 ;Defaults file=(n_elements(file) eq 1) ? file : 'OBSFLUX' ;read the lines into a string array nlines=file_lines(file) if (nlines eq 0) then message,'file is empty' lines=strarr(nlines) openr,unit,file,/get_lun readf,unit,lines free_lun,unit ;find and remove the blank lines lines=lines[where(strlen(strcompress(lines,/remove_all)) ne 0)] nlines=n_elements(lines) ;find the lines with scalars (identified by :) sid=strpos(lines,':') scal_ind=where((sid ne -1),nscalars) arr_ind=where((sid eq -1)) ;extract the scalars scal=0 if (nscalars ne 0) then begin scal=replicate({name:'',value:0d0},nscalars) for i=0,nscalars-1 do begin tmp=strsplit(lines[scal_ind[i]],':',/extract) scal[i].name=strtrim(strcompress(tmp[0]),2) scal[i].value=tmp[1] endfor endif ;remove the lines with scalars lines=lines[arr_ind] nlines=n_elements(lines) narr=0 arr=0 if (nlines ne 0) then begin ;find the lines with the name of each array ; fpexpr='^[-+]?(([0-9]*\.?[0-9]+)|([0-9]+\.?[0-9]*))([eEdD][-+]?[0-9]+)?$' ;the expression above matches every floating point string I could think of ; text=bytarr(nlines) ;1 for lines that do not contain only floating point numbers ; for i=0,nlines-1 do begin ;test if each part of each line is a floating point number ; stmp=strsplit(lines[i],/extract,count=itmp) ; text[i]=(total(stregex(stmp,fpexpr,/bool)) ne itmp) ; endfor fpexpr='^[-+]?(([0-9]*\.?[0-9]+)|([0-9]+\.?[0-9]*))([eEdD][-+]?[0-9]+)?' ;the expression above matches every string starting with floating point string I could think of lines=strtrim(lines,2) text=~stregex(lines,fpexpr,/bool) w=where(text,narr) w=[w,nlines] if (narr ne 0) then begin ;process each array arr=replicate({name:'',values:ptr_new()},narr) for i=0,narr-1 do begin atmp=0d0 for line=w[i]+1,w[i+1]-1 do begin ;start at the first line after the name of the array stmp=strsplit(lines[line],/extract) ;separate the columns of this line atmp=[atmp,stmp] ;convert them to double and append to the temporary array endfor arr[i].name=strtrim(strcompress(lines[w[i]]),2) arr[i].values=ptr_new(atmp[1:*],/no_copy) endfor endif endif ;return structure ret={nscal:nscalars,$ ;number of scalars read scal:scal,$ ;vector of structures, with one (name,value) pair for each scalar read (0 if nscal=0) narr:narr,$ ;number of arrays read arr:arr} ;vector of structures, with one (name,values) pair for each array read (0 if narr=0) return,ret end