PRO boost, a, b_in, pushdim=pushdim, plus=plus, top=top, lead=lead, _extra=_extra ;+ ; NAME: ; boost ; PURPOSE: ; Combining arrays ; CATEGORY: ; Toolbox ; CALLING SEQUENCE: ; boost, a, b [, pushdim=pushdim, plus=plus, top=top, value=value] ; INPUTS: ; a array; type: any ; array to be added to ; b array; type: same as 'a' ; array to be appended to 'a' ; OPTIONAL INPUT PARAMETERS: ; pushdim=pushdim ; scalar; type: integer ; dimension to be boosted using 'b' or 'plus' ; plus=plus scalar; type: integer; default: 0 ; only used if b_in not set or doesn't exist ; # elements to be added to dimension 'pushdim' ; /lead adds to the front of the array instead of the end ; /top by default, the input array is put at the bottom ; of dimension; if /top is set then it is shifted to ; the top of the dimension (see EXAMPLE) ; ; Additional arguments, except 'type' and 'dim' can be passed to make_array ; through the _extra keyword. Probably the only useful one is: ; ; value=value scalar; type: same as 'a' ; value used to pad the output array 'a' where needed ; OUTPUTS: ; a array; type: same as input ; input array 'a' boosted using 'b' or 'plus' ; (used by make_array as initialization value). ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; InitVar, where_common, rank_array, SyncDims, IsType ; PROCEDURE: ; print, boost( indgen(3,2), plus=5) ; 0 1 2 0 0 0 0 0 ; 3 4 5 0 0 0 0 0 ; print, boost( indgen(3,2), plus=5, /top) ; 0 0 0 0 0 0 1 2 ; 0 0 0 0 0 3 4 5 ; ; IDL> a = [0,1,2] ; IDL> b = [0,1,2,3] ; IDL> boost, a,b ; IDL> print,a ; 0 1 2 0 1 2 3 ; (i.e. concatenats a and b) ; ; IDL> a = [0,1,2] ; IDL> b = [0,1,2,3] ; IDL> boost, a,b, /push ; IDL> print,a ; 0 1 2 ; 0 1 2 ; (i.e. puts 2nd array on new array, truncating or padding as necessary) ; ; IDL> a = indgen(3,4,5) ; IDL> b = indgen(3,5) ; IDL> boost, a,b ; IDL> help,a ; A INT = Array[3, 5, 5] ; ; I.e. array b is merged with a by adding it to the 2nd dimension. ; The dimension to be added to is determined by excluding dimension ; with the same number of elements. The pushdim keyword can be ; used to explicitly select the dimension. ; ; MODIFICATION HISTORY: ; FEB-2002, Paul Hick (UCSD/CASS) ; Extended old version of boost considerably; also merged ; boostdim with boost (using keyword 'plus') ; APR-2002, Paul Hick (UCSD/CASS) ; replaced explicit keyword 'value' by _extra. 'value' was passed ; to make_array explicitly, but this caused problems in IDL 5.3 ; (the variable MUST exist). ; AUG-2002, Paul Hick (UCSD/CASS) ; Added keyword /lead ; MAR-2003, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Made some modifications to make this work with structures. ; The change involves replacing make_array calls with replicate calls. ;- InitVar, top , /key InitVar, lead, /key CASE 1 OF IsType(plus, /defined): BEGIN IF plus GT 0 THEN BEGIN CASE IsType(a, /defined) OF 0: b = make_array(type=IsType(/short_int), dim=plus, _extra=_extra) 1: BEGIN InitVar, pushdim, 0 n = size(a, /dim) n[pushdim] = plus case IsType(a, /struct) of 0: b = make_array(type=IsType(a), dim=n, _extra=_extra) 1: b = replicate(a[0],n) ENDCASE END ENDCASE ENDIF END IsType(b_in, /defined): b = b_in ELSE: ENDCASE IF IsType(b, /undefined) THEN $ ; Nothing to do ('a' may or may not exist) RETURN IF IsType(a, /undefined) THEN BEGIN ; Non-existent 'a'; return 'b' a = b RETURN ENDIF ; Both 'a' and 'b' exist IF n_elements(a) EQ 1 THEN a = [a] ; Scalars are a problem IF n_elements(b) EQ 1 THEN b = [b] IF IsType(pushdim, /defined) THEN $ IF pushdim eq size(a,/n_dim) THEN $ a = reform(a,[size(a,/dim),1],/overwrite) IF IsType(pushdim, /undefined) THEN BEGIN n = where_common(size(a,/dim),size(b,/dim),absent=pushdim) pushdim = pushdim[0] IF pushdim EQ -1 THEN pushdim = 0 ENDIF IF size(b,/n_dim) EQ size(a,/n_dim)-1 THEN BEGIN n = size(b,/dim) n = [-1,n,-1] n = [n[0:pushdim],1,n[pushdim+1:*]] n = n[1:n_elements(n)-2] b = reform(b,n,/overwrite) ENDIF ; a and b should have the same number of dimensions now n = indgen( size(a,/n_dim) ) p = where(n ne pushdim) CASE p[0] OF -1 : ar = n ELSE: ar = [pushdim, n[p]] ENDCASE rearrange = (where(ar NE n))[0] NE -1 IF rearrange THEN BEGIN ; Put the dimension to be added to in first place rank_ar = rank_array(ar) ; IDL tends to loose degenerate dimensions. Make sure to keep them. n = size(a,/dim) a = transpose(a, ar) a = reform(a, n[ar], /overwrite) n = size(b,/dim) b = transpose(b, ar) b = reform(b, n[ar], /overwrite) ENDIF na = size(a, /dim) ; Build size vector for output array nb = size(b, /dim) CASE n_elements(na) OF 1 : nd = nb[0] ELSE: nd = [nb[0], na[1:*]] ENDCASE CASE IsType(a, /structure) OF 0: d = make_array(type=IsType(a), dim=nd, _extra=_extra) 1: d = replicate(a[0],nd) ENDCASE d = reform(d, nd, /overwrite) ; Don't loose degenerate dimensions nb = nb < nd ; Truncate to 'nd' if necessary s = 0*nb *(1-top)+(nd-nb)*top ; Start index in 'd' e = (nb-1)*(1-top)+(nd- 1)*top ; End index in 'd' f = nb-1 CASE size(a, /n_dim) OF 1: d[s[0]:e[0]] = b[0:f[0]] 2: d[*,s[1]:e[1]] = b[*,0:f[1]] 3: d[*,s[1]:e[1],s[2]:e[2]] = b[*,0:f[1],0:f[2]] 4: d[*,s[1]:e[1],s[2]:e[2],s[3]:e[3]] = b[*,0:f[1],0:f[2],0:f[3]] 5: d[*,s[1]:e[1],s[2]:e[2],s[3]:e[3],s[4]:e[4]] = b[*,0:f[1],0:f[2],0:f[3],0:f[4]] 6: d[*,s[1]:e[1],s[2]:e[2],s[3]:e[3],s[4]:e[4],s[5]:e[5]] = b[*,0:f[1],0:f[2],0:f[3],0:f[4],0:f[5]] 7: d[*,s[1]:e[1],s[2]:e[2],s[3]:e[3],s[4]:e[4],s[5]:e[5],s[6]:e[6]] = b[*,0:f[1],0:f[2],0:f[3],0:f[4],0:f[5],0:f[6]] 7: d[*,s[1]:e[1],s[2]:e[2],s[3]:e[3],s[4]:e[4],s[5]:e[5],s[6]:e[6],s[7]:e[7]] = b[*,0:f[1],0:f[2],0:f[3],0:f[4],0:f[5],0:f[6],0:f[7]] ENDCASE CASE lead OF 0: a = [a,d] 1: a = [d,a] ENDCASE na[0] = na[0]+nb[0] ; Update number of elements in first dimension a = reform(a, na, /overwrite) IF rearrange THEN BEGIN ; Undo the rearrange operation n = size(a,/dim) a = transpose(a, rank_ar) a = reform(a, n[rank_ar], /overwrite) ENDIF RETURN & END