;+ ; NAME: ; flt_format ; PURPOSE: ; Simplifies a format specication as produced by flt_string ; CATEGORY: ; gen/idl/util ; CALLING SEQUENCE: FUNCTION flt_format, InStr ; INPUTS: ; InStr scalar; type: string ; any comma-separated list of format specifiers ; (the outer enclosing brackets are optional, but ; there should be no internal brackets) ; OUTPUTS: ; Result scalar; type: string ; more compact list of format specifiers ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; flt_format, where_common ; RESTRICTIONS: ; The algorithm used tries to find recurring groups of format ; elements, but is somewhat heuristic. ; PROCEDURE: ; The format spec set up by flt_string only takes into account ; immediately neighbouring format specifies, i.e. instead ; of I4,I4,I4 the format will say 3I4. This function looks for ; more complicated repetitions in the flt_string format, e.g ; str = 'I4,I2,F6.2,I2,F6.2,I3,I4,I2,F6.2,I2,F6.2,I3,I6,I1,I1' ; print, flt_format(str) ; 2(I4,2(I2,F6.2),I3),I6,2I1 ; MODIFICATION HISTORY: ; SEP-2004, Paul Hick (UCSD/CASS) ; JUL-2012, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Explicitly remove all whitespace from input string. ; (input is still not modified) ;- Str = strcompress(InStr,/rem) ; Remove all whitespace spart = Str brackets = strmid(spart,0,1) EQ '(' IF brackets THEN spart = strmid(spart,1,strlen(spart)-2) spart = strtok(spart,',',/extract) CASE brackets OF 0: spart = strtok(Str,',',/extract) 1: spart = strtok(strmid(Str,1,strlen(Str)-2),',',/extract) ENDCASE npart = n_elements(spart) i = 0 WHILE i LT npart-1 DO BEGIN ; Occurrences of spart[i] after pos i. ; Note that posn[0] is always zero. posn = where(spart[i:*] EQ spart[i], cntn) ; We start with one group with npart-i elements starting at i. ; If this is the best we can do then the format remains unchanged. pos = posn[0] cnt = 1 len = npart-i ; Look for two or more groups. Try the big groups first. ; Two groups could have a maximum of cntn/2 elements (but could ; be less). So we start looking for groups of cntn/2 elements, and ; work our way down from there. FOR j=cntn/2,1,-1 DO BEGIN cnta = 1+(cntn-1)/j posa = posn[j*indgen(cnta)] lena = posa[1] ; Number of elements in first section posa = [posa, (posa[cnta-1]+lena) < (npart-i)] tmp = (where((posa mod lena) ne 0))[0] IF tmp NE -1 THEN cnta = tmp-1 ; 'cnta' now is the number of consecutive groups of ; 'lena' elements starting with spart[i] cntamax = cnta cnta = 1 WHILE cnta LT cntamax DO BEGIN IF (where(spart[i:i+lena-1] NE spart[i+cnta*lena:i+lena-1+cnta*lena]))[0] NE -1 THEN break cnta += 1 ENDWHILE ; Remember the starting positions of cnta groups of lena elements. ; pos, cnt, len describe the best available group found previously. ; We except this group as 'better' if it has more elements per group ; as the previous one, and if all entries from the previous group are ; also present in the new group. posa = posa[0:cnta-1] IF cnta GT cnt THEN BEGIN tmp = where_common(pos,posa,count=n) IF n EQ cnt THEN BEGIN pos = posa cnt = cnta len = lena ENDIF ENDIF ENDFOR ; 'cnt' now is the number of consecutive groups with identical elements ; The groups have 'len' elements and start at positions 'pos'. IF cnt GT 1 THEN BEGIN ; If the group consists of more than one element.we call flt_string ; recursively, in an attempt the group internally. ; Murphy's law says that this trick is going to cause infinite recursion ; sometime. CASE len NE 1 OF 0: spart[i] = strcompress(cnt,/rem)+spart[i] 1: spart[i] = strcompress(cnt,/rem)+'('+flt_format( strjoin(spart[i:i+len-1],',') )+')' ENDCASE pos = i+pos[cnt-1]+len CASE pos EQ npart OF 0: spart = [spart[0:i],spart[pos:*]] 1: spart = spart[0:i] ENDCASE npart = n_elements(spart) ENDIF i += 1 ENDWHILE spart = strjoin(spart,',') IF brackets THEN spart = '('+spart+')' RETURN, spart & END