Identifying the source (matrix) wave from a contour trace name

I didn't find how to achieve the following: Suppose you have a contour trace name (a string from TraceNameList(myGraph,";",2)) and want to get a reference to the source matrix wave. Since the source wave's name may (or may not anymore) be part of the contour trace name, I was under the impression this could be somehow achieved by using ContourNameList(). But the name gets truncated to 17 characters anyway. So it is impossible to distinguish MyLongNamesSourceWaveA and MyLongNamesSourceWaveB should they be both plotted in the same graph. So I guess I have to give up and just grab the best match from ContourNameList() hoping that the wave's name is not identical in the first 17 characters and that the contour trace has not been renamed in the meantime?

How about ContourInfo? The output includes keywords for each of the three waves that might or might not be present on your graph.

Also, can you expand on "But the name gets truncated to 17 characters anyway." What is truncating to 17 characters? Surely not Igor- there has never been a time when a name would be truncated to 17 characters.

Hi Chozo,

I think you are a bit confused between wavename and tracename (including trace, image, and contour). Very often, with a relatively short wave name, this tracename string happens to be the same as wavename.

In order to figure out the underlying wave of an object in a graph (again either trace, image, and/or contour), you first use the corresponding XXNameList function (TraceNameList, ImageNameList, ContourNameList). From this list, get the tracename of the object you want using StringFromList function. Using this name, call the corresponding XXNameToWaveRef function (TraceNameToWaveRef, ImageNameToWaveRef, ContourNameToWaveRef) to get the wave reference to that underlying wave. Finally, call GetWavesDataFolder function to get the full name or partial name of the underlying wave, depending on the parameter fed to the function.

string contourList = ContourNameList("","")//Get a list of names of the contours on your topgraph
string contourName = StringFromList(0, contourList) //Get the name of the first counter in the contourList
string wavefullname = GetWavesDataFolder(ContourNameToWaveRef(GraphName, tracename), 2)//Get the full wave name and path of the underlying wave of that first contour.

 

John, thanks for your message. But here is the thing: ContourInfo() requests the source wave name as input and then ... tells me the source wave name (via the ZWAVE key). So this is kind of moot. Also, you will see this for TRACESFORMAT: "%.17s=%g", so truncation to 17 characters (but I assume this depends on the string length of the levels indicators). As far as I can see, there is no function or operation which does 'contour trace/wave name' => 'source wave name', which was very surprising to me. I can maybe do 'source wave name' => 'contour trace/wave name' using the stuff ContourInfo() gives me, but not the other way around.

@BuntCake: No, I am not confused. It is likely that you have not realized that contour traces are constructed a bit differently. Namely, contour traces are constructed from special waves which are hidden to the user, and do not directly reference back to the source wave (at least not in an accessible way to us). I don't want access to these internal waves for each contour trace. Instead I want to refer back to the source given a single contour trace name. Yes, I know the trace name is in some way constructed from the source wave name, but this is the reason I wrote about long wave names, since the contour trace name has its limits.

When you append the contour traces to your plot, you can specify the format using the /F flag, e.g.

AppendMatrixContour/F="%s=%g"

which should guarantee unique contour trace names, but that won't help if that flag wasn't used when making the graph. 

If you append MyLongNamesSourceWaveA and then MyLongNamesSourceWaveB, the contour trace names would be 'MyLongNamesSource=100' and 'MyLongNamesSource=100'#1, so maybe you could hack it by getting the list of contours and then using the trace instance to determine which contour the trace goes with?  The code below seems to work, but I'm not sure it's 100% reliable.  If the user does something crazy like reordering the contour traces then all bets are off.  

FUNCTION Make_2D()

    Make/O/D/N=(30,30) Long_Name_Dummy_Matrix=(p+1)*(q+1)
    Make/O/D/N=(30,30) Long_Name_Dummy_Matrix_2=(p+3)*(q+3)
   
    Display/K=1;DelayUpdate
    AppendMatrixContour Long_Name_Dummy_Matrix
    AppendMatrixContour Long_Name_Dummy_Matrix_2
   
    ModifyGraph hideTrace('Long_Name_Dummy_M=boundary')=1,hideTrace('Long_Name_Dummy_M=boundary'#1)=1
    ModifyGraph mirror=0
    Cursor/P A 'Long_Name_Dummy_M=100' 26
    Cursor/P B 'Long_Name_Dummy_M=100'#1 31
    ShowInfo

END


FUNCTION Get_Contour(STRING strCursor_Name)

    String strContour_Trace_Name=CsrWave($strCursor_Name, "", 1)
    Variable vEquals_Sign=strsearch(strContour_Trace_Name, "=", 0, 2)
    String strTruncated_Contour_Name=strContour_Trace_Name[1,vEquals_Sign-1]
    Variable vInstance_Start=strsearch(strContour_Trace_Name, "#", 0, 2)
   
    Variable vInstance=0
    IF(vInstance_Start>=0)
        vInstance=str2num(strContour_Trace_Name[vInstance_Start+1, strlen(strContour_Trace_Name)-1])
    ENDIF
       
    String strContour_List=ContourNameList("", ";")
   
    String strContour_From_Trace
   
    Variable iContourDex
    FOR(iContourDex=0;iContourDex<ItemsInList(strContour_List);iContourDex+=1)
        String strContour_Name=StringFromList(iContourDex, strContour_List)
       
        String strTrace_Format_Full=StringByKey("TRACESFORMAT", ContourInfo("", strContour_Name, 0))
        vEquals_Sign=strsearch(strTrace_Format_Full, "=", 0, 2)
        String strTrace_Format=strTrace_Format_Full[0,vEquals_Sign-1]
       
        String strContour_Name_Formatted
        sprintf strContour_Name_Formatted, strTrace_Format, strContour_Name
       
        IF(cmpstr(strContour_Name_Formatted, strTruncated_Contour_Name)==0 && vInstance==iContourDex)
            strContour_From_Trace=strContour_Name
        ENDIF

    ENDFOR
   
    Print strContour_From_Trace
END

 

Adding a function to do this, or maybe easier, adding a field to TraceInfo if the trace type is 1, seems like a useful addition.  With longer names now allowed, it would also be nice if the default trace name format was longer than %0.17s.  

Thanks! Yes, this is probably the best idea in lack of a direct (official) conversion method. The instance should indeed indicate the order in which the source wave appears in CountourNameList(). Here is what I have in my code now (I really like to use regex lately):

string traceBase, traceInst
SplitString/E="([^\=]*)(?:[^#]*)#?([0-9]*)?" traceName, traceBase, traceInst  // split at = and possibly #
int instance = strlen(traceInst) ? str2num(traceInst) : 0
contourName = StringFromList(instance, GrepList(ContourNameList(myGraph,";"),"^"+traceBase))

 

@chozo, that's really nice code, and way more elegant than what I came up with!  I'm glad my suggestion was helpful.  When I tested your code, tracebase still had a leading single quote that needs to be removed.  Maybe this would work:

SplitString/E="([^*'][^\=]*)(?:[^#]*)#?([0-9]*)?" traceName, traceBase, traceInst  // split at = and possibly #

 

Yes, I think my issue is solved thanks to your idea. Note that ContourNameList() reports the names including single quotes, so parsing this is actually intended. Your SplitString command is of course good for other things like constructing custom wave names out of the input contour trace.

@chozo I misunderstood your original posting, clearly. Now that we have a solution, can you let us know what you are trying to accomplish? Altering the appearance of contour traces can be a frustrating experience- the contour itself tends to wipe out customizations.

John, thank you for offering your help. You were not the only one who misunderstood my post. But I couldn't think of a way to explain myself better. Anyway, my reasons are very simple: I want to offer all and everything Quick Fit can do in my Super Quick Fit package, so that there is no reason not to use it. :) For this I need a way to construct the fit call when someone clicks on a contour trace. Even if nobody uses this in the end, it has been certainly a learning experience.

Ah- apparently another way around this would be if we had a way to tell you which contour plot you clicked on. But I have a funny feeling that TraceInfo() might have the info you need in Igor 10.

Aha! Would be really great if your funny feeling turns out to be right. (Still, I will likely be supporting the old way of doing things for a while until this mysterious Igor 10 I keep hearing about will materialize for the masses, i.e., my users. ;-)