Parsing ErrorBar wave information

I tried hard to parse out the name of the error-bar wave and displayed range, but so far I haven't found a general solution. I am banging my head against this wall for quite a while now. Anybody has an idea how to parse a string which might look like this (Which is part of TraceInfo()):

"ErrorBars 'Peak[30],results'#1 XY,pct=0.01,wave=('Peak[30],error'[12,20;2][%loc_err],'Peak[30],error 2'[13,17][15])"

The range might be complicated or easy or not present at all. What I want to get out is:

Peak[30],error
12,20;2   // may not be present
%loc_err  // may not be present

This problem may get considerably easier if there was a way to obtain the name of the error wave from somewhere else.

OK, I might have found a solution (that is some serious rubber duck debugging today). It is ugly but it seems to work (don't ask me about the regex details too much). If anybody has a simpler solution I am all ears:

string tmpStr, errWInfo, errName, eRow_label, eCol_label, eLay_label, eChk_label, regex
SplitString/E=("(.*);RECREATION") TraceInfo(graphName,traceName,0), tmpStr
SplitString/E=("(?:.*)(?:wave=\()([^\)]*)") tmpStr, errWInfo    // get wave info in brackets
if (strlen(errWInfo))
    if (StringMatch(errWInfo,"*[*"))    // contains range
        if (!CmpStr(errWInfo[0],"'"))   // liberal name
            regex = "'([^'?]*?)(?:')(?:\[(.*?)\])?(?:\[(.*?)\])?(?:\[(.*?)\])?(?:\[(.*?)\])?,?(?:.*)"
        else
            regex = "(.*?)\[([^]]*?)](?:\[(.*?)\])?(?:\[(.*?)\])?(?:\[(.*?)\])?,?(?:.*)"
        endif
        SplitString/E=(regex) errWInfo, errName, eRow_label, eCol_label, eLay_label, eChk_label
    else
        SplitString/E=("^(.*?)(\[|,)") errWInfo, errName
    endif
endif

 

Lots of REGEX. Pulling off the ERRORBARS string from TraceInfo using StringByKey might eliminate the first REGEX. You have one of these (with options for additional [] for the q indices)

wave=('liberal name X'#N[...],'liberal name Y'#N[...])
wave=('liberal name X'[...],'liberal name Y'[...])
wave=(nameX#N[...],nameY#N[...])
wave=(nameX[...],nameY[...])
...

Rather than separating between liberal and standard names, zap the ' characters and replace spaces by double __ using ReplaceString. This removes the need for two different REGEX expressions. You now get this ...

wave=(liberal__name__X#N[...][...],liberal__name__Y#N[...][...])

The REGEX to capture the ranges (if they exist) should now become an easier expression. It may even be possible to avoid REGEX using ListMatch(list,"[*]").

Capture the wave names (standardized) and convert back to liberal as needed by replacing double __ with space.

Caveat: Fear for those who use double __ in their file names at the outset.
 

 

JJ, thanks for your input! I will look into your idea of replacing the ' with another special symbol, but I am not seeing how this helps me handle exotic liberal names better. Here are a few issues which complicate these things further:

  • You cannot use StringByKey, StringFromList or the like to even get the wave=() bracket, because the list separator string ";" can easily part of your input (in fact, this already happens when the wave range contains an increment, e.g., [10,50;2]). Interestingly, the XRANGE and YRANGE keywords are protected from this (ranges are given as [10,50:2]). Maybe an oversight by the WM team with error waves?
  • Something like ListMatch(in, "[*","]") could be an option if one manages to extract the range boxes without the wave name in the first place. However, the asterisk character is very likely part of the string ("[*]" indicates 'full range').
  • Commas, square brackets and other abominations can easily be part of a wave name, making this a huge head scratcher.

I think there is surely a more elegant regex, which would shorten this considerably. My regex-fu is very weak, and I couldn't even figure out how to parse something like "[STUFF]" repeated 1-4 times with a repeating pattern into different groups, hence the unwieldy optional matching thing going on there.

I was able to reduce this to two paths for the regex at least, one for liberal names and one for strict names (EDIT: I also could get rid of one of the SplitString lines):

string tmpStr, errWInfo, errName, eRow_label, eCol_label, eLay_label, eChk_label, regex
SplitString/E=("(?:.*)(?:wave=\()([^\)]*)\)\;RECREATION") TraceInfo(graphName,traceName,0), errWInfo
if (strlen(errWInfo))    // wave info in brackets
    if (!CmpStr(errWInfo[0],"'"))    // is liberal
        regex = "'?([^']*)'"
    else
        regex = "([^\[|,]*)"
    endif
    regex += ReplicateString("(?:\[(.*?)\])?", 4) + ",?(?:.*)"  // captures 4 range boxes
    SplitString/E=(regex) errWInfo, errName, eRow_label, eCol_label, eLay_label, eChk_label
endif

 

It has been certainly a good learning experience, for sure.

With this I hope to finally offer the full feature set (and more) of the official Quick Fit in my Super Quick Fit package.