Pro dummy_var, inp e = 3.0 ;any statement will do here return End ;+ ;NAME: ; string_parser ;PURPOSE: ; Parse strings into components ;CALLING SEQUENCE: ; string_parser, inpx, parse_by, out, output_count ;INPUT: ; inpx strings to parse ; parse_by character to parse by ;OUTPUT: ; out array of substrings ; output_count number of substrings ;HISTORY: ; Updated 22-April-1993 by Terry Slocum ; Fixed output_count bug, 28-mar-94, JMM ; Gave the ability to use a parse_by string of more than one ; character, jmm 13-jun-2007 ;- pro string_parser, inpx, parse_by, out, output_count npb = strlen(parse_by) IF(N_ELEMENTS(inpx) GE 1) THEN BEGIN out = '' input_count = N_ELEMENTS(inpx) FOR yy = 0, input_count-1 DO BEGIN line = inpx(yy) length = STRLEN(line) i = 0 WHILE (length GT 0) DO BEGIN first_p = STRPOS(line, parse_by, i) IF (first_p EQ -1) THEN BEGIN out = [out, line] line = '' ENDIF ELSE IF (first_p EQ 0) THEN BEGIN i = 0 line = STRMID(line, npb, length) ENDIF ELSE BEGIN xx = STRMID(line, i, first_p - i) out = [out, xx] line = STRMID(line, first_p + npb, length) i = 0 ENDELSE length = STRLEN(line) ENDWHILE ENDFOR IF (N_ELEMENTS(out) GT 1) THEN BEGIN out = out(1:*) output_count = n_elements(out) ENDIF ENDIF END ;+ ;NAME: ; code_fragment ;PURPOSE: ; takes a string, where input variables are defined as array_elements ; 'qq' and creates a set of tplot commands using those data ;CALLING SEQUENCE: ; code_fragment, inp_string, otp_string ;HISTORY: ; 13-jun-2007, jmm, jimm@ssl.berkeley.edu ;- Pro code_fragment, inp_string, otp_string ;inp_string has "qq" otp_string = '' bqq = strpos(inp_string, 'qq') If(bqq[0] Eq -1) Then Return inpx = strlowcase(strcompress(inp_string, /remove_all)) linp = strlen(inpx) t1 = strmid(inpx, 0, 2) If(t1 Eq 'qq') Then qq_at_start = 1b Else qq_at_start = 0b t1 = strmid(inpx, linp-2, linp) If(t1 Eq 'qq') Then qq_at_end = 1b Else qq_at_end = 0b string_parser, inpx, 'qq', code_fragments nqq = n_elements(code_fragments) cfnew = code_fragments For j = 0, nqq -1 Do Begin ;Is there an array element there? testj = strmid(code_fragments[j], 0, 1) If(testj[0] Eq '[') Then Begin ;find the closing ']' pj = strsplit(code_fragments[j], ']', /extract) npj = n_elements(pj) If(npj Eq 2) Then Begin cfnew[j] = pj[0]+'].y'+pj[1] Endif Else If(npj Eq 1) Then Begin cfnew[j] = pj[0]+'].y' Endif Else message, 'bad values for pj' If(j Eq 0) Then Begin If(qq_at_start) Then cfnew[j] = 'qq'+cfnew[j] Endif Else cfnew[j] = 'qq'+cfnew[j] Endif Else Begin If(j Eq 0) Then Begin If(qq_at_start) Then cfnew[j] = 'qq.y'+cfnew[j] Endif Else cfnew[j] = 'qq.y'+cfnew[j] Endelse otp_string = otp_string+cfnew[j] Endfor If(qq_at_end) Then otp_string = otp_string+'qq.y' Return End ;+ ;NAME: ; tuserdef ;PURPOSE: ; Inputs a string expression that operates on a tplot variable, or an ; array of tplot variables, and returns the result. Note that this is ; a very experimental program. ;CALLING SEQUENCE: ; otp_var = tuserdef(inp_var, input_string) ;INPUT: ; inp_var = a tplot variable, or an array of tplot variable ; names. Note that the time arrays of the variables need not ; be the same, the program will handle that. But the Y ; arrays of the variables must be the same, unless one is a ; 1d vector. ; input_string = an input string, where 'qq' represents the tplot ; variable data to be operated on, 'qq' can look like ; an array, each element of 'qq' is a separate tplot ; variable. E.g., '2.0*qq[0]/qq[1]' will divide the ; data for qq[0] by that for qq[1], and multiply by ; 2.0. ;OUTPUT: ; otp_var = an output tplot variable name, will be the null string if ; the process fails ;KEYWORDS: ; otp_string = the string used for the 'execute' command ; success = the success value from the execute command, 1 good, 0 not ; out_varname = a name for the output variable, the default is ; tuserdef_output ;EXAMPLES: ; For the absolute value of a variable: ; newvar = tuserdef(oldvar, 'abs(qq)') ; To divide a variable be the square root of another: ; newvar = tuserdef([oldvar1, oldvar2], 'qq[0]/sqrt(qq[1])' ; To compare THEMIS moment data: ; moment_ratio = tuserdef(['tha_peim_ptens', 'tha_peir_ptens'], 'qq[1]/qq[0]') ;HISTORY: ; 19-feb-2008, jmm, jimm@ssl.berkeley.edu ; 24-feb-2008, jmm, Allow replication of 1d y variables to n ; dimensions when multiple dimensions are passed in. ;+ Function tuserdef, inp_var, input_string, $ otp_string = otp_string, success = yyy, $ out_varname = out_varname, _extra = _extra otp_var = '' ;init ;first, get the code needed code_fragment, input_string, otp_string ;now get the data, note that the data structures will need to be ;consistent, since there are different time arrays, the time array of ;the first element in the array will be used. n = n_elements(inp_var) get_data, inp_var[0], data = qq, dlimits = dl If(is_struct(qq) Eq 0) Then Begin dprint, 'No data for: '+inp_var[0],dlevel=2 ;message, 'No data for: '+inp_var[0],/info Return, otp_var Endif If(n Gt 1) Then Begin t = qq.x yp = qq.y & yp[*] = 0.0 ;temporary variable for type issues syp = size(yp) typ_p = size(yp, /type) If(tag_exist(qq, 'v')) Then Begin vp = qq.v yes_v = 1b Endif Else yes_v = 0b ;for each sub_array, use "data_cut" to get a new data structure, if ;necessary -- note that Y arrays aren't checked and incompatible y's ; will bomb, unless Y is a 1d vector, then we replicate For j = 1, n-1 Do Begin get_data, inp_var[j], data = d1 If(is_struct(d1) Eq 0) Then Begin dprint, 'No data for: '+inp_var[j],dlevel=2 ;message,/info,'No data for: '+inp_var[j] Return, otp_var Endif t1 = d1.x If(size(d1.y, /n_dim) Gt 1) Then Begin If(n_elements(d1.y[0, *, *, *]) Ne $ n_elements(qq[0].y[0, *, *, *])) Then Begin dprint, 'Incompatible Y sizes: '+inp_var[j]+' and '+inp_var[0],dlevel=2 ;message,/info, 'Incompatible Y sizes: '+inp_var[j]+' and '+inp_var[0] Return, otp_var Endif ;change type if necessary If(size(d1.y, /type) Ne typ_p) Then Begin ytmp = make_array(dimen = size(d1.y, /dimen), type = typ_p) ytmp[*] = d1.y dummy_var, temporary(d1) d1 = {x:t1, y:ytmp} Endif Endif Else Begin ;replicate the y variable if necessary If(syp[0] Eq 1) Then Begin ytmp = d1.y Endif Else If(syp[0] Eq 2) Then Begin ytmp = rebin(d1.y, syp[1], syp[2]) Endif Else If(syp[0] Eq 3) Then Begin ytmp = rebin(d1.y, syp[1], syp[2], syp[3]) Endif Else If(syp[0] Eq 4) Then Begin ytmp = rebin(d1.y, syp[1], syp[2], syp[3], syp[4]) Endif Else Begin dprint, 'Unsupported Array size',dlevel=2 ; message, 'Unsupported Array size',/info Return, otp_var Endelse If(size(ytmp, /type) Ne typ_p) Then Begin ;change the type ytmp1 = make_array(dimen = size(ytmp, /dimen), type = typ_p) ytmp1[*] = temporary(ytmp) ytmp = temporary(ytmp1) Endif dummy_var, temporary(d1) d1 = {x:t1, y:ytmp} Endelse If(n_elements(t1) Ne n_elements(t) Or $ max(abs(t1-t)) Gt 0.0) Then Begin d1 = data_cut(temporary(d1), t) If(is_struct(d1) Eq 0) Then Begin yp[*] = d1[*] Endif Else yp[*] = d1.y[*] If(yes_v) Then d1 = {x:t, y:yp, v:vp} $ Else d1 = {x:t, y:yp} Endif Else Begin If(yes_v) Then str_element, d1, 'v', qq[0].v, /add_replace Endelse qq = [temporary(qq), temporary(d1)] Endfor Endif Else t = qq.x otp_string = 'y = '+otp_string yyy = execute(otp_string) If(yyy Gt 0) Then Begin ;put this into a tplot variable If(keyword_set(out_varname)) Then otp_var = out_varname $ Else otp_var = 'tuserdef_output' store_data, otp_var, data = {x:t, y:y}, dlimits = dl Endif Else otp_var = '' Return, otp_var End