Merging graphs

I would like to request the addition of a function that merges the desired graphs, maintaining (optionally) all the formatting of the original graphs or adopting the formatting of one of the selected graphs. This should include the axes, xwaves, ywaves, X&Y error bars, line/marker styles, sparse markers, etc., essentially containing all the information generated with the graph recreation macros for all the desired graphs.

At the moment I find myself with graphs that contain a large number of waves, each having a separate xwaves and different waves for their error bars. Combining these can be time-consuming so I have written some very basic functions to merge them, but it relies on foreknowledge of the error-bar wave names (not provided by TraceInfo, or at least this is not documented yet) and it does not capture the trace settings which should be available from TraceInfo. In other words, this is still far from a general solution.

I envision a simple interface (similar to the Graph Browser) to allow users to select which graphs are to be merged and a preview pane showing the result of the merger prior to generating a stand-alone graph window.

Best,
Andrew
Ok, well it may be possible to write a pretty general function that provides this capability then using user-accessible functions such as TraceInfo, but I don't think this would be the most efficient way to achieve the goal of merging graphs.

Is there any way to access the code Igor uses to Duplicate graphs or to generate a recreation macro? Those functions already contain all of the required logic required to fully reproduce a graph. By combining the information extracted from multiple passes of these commands on different graphs, we should be able to produce a graph that merges multiple graphs.
Are you aware of the WinRecreation function?

Also- I don't really understand what you want. Could you show pictures of two graphs that you want merged, and the result you want?

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
johnweeks wrote:
Are you aware of the WinRecreation function?

Also- I don't really understand what you want. Could you show pictures of two graphs that you want merged, and the result you want?


Yes I am aware of the WinRecreation function. It produces valid code to reproduce an individual graph regardless of complexity, but if you naively generate a recreation macro for graph0 and one for graph1 and then merge the code together, you will not get a new graph that combines all the elements of graph0 and graph1.

I've attached a simple example demonstrating what I mean. Graph0 and Graph1 each have one trace with x, y, xErr, and yErr waves. Graph2 is the merger of these two keeping the markers, colors, and errorbars of both initial graphs. This is simple for the case of few traces, but can become a very big problem when trying to add lots of traces that each have separate x-waves and x/y error waves.

I wrote some simple code that merges graphs using the output of the WinRecreation function (see attached ipf file). This is an improvement over my attempts to use the TraceInfo output, but still seems somewhat inefficient. At the moment the style is lost in the merger, but the data is preserved. I believe this scales to arbitrary complex graphs, but have not tested in thoroughly. You can use it by calling the function mergeWindows("Graph0;Graph1;")
I think I'm beginning to get it...

It seems like it would be possible to come up with something that worked about 75 percent. It seems like there are lots of issues:

If the two graphs display the same data, do you create a merged graph with two traces or one? If one, which graph do you get the trace styles from? I suppose for the first question you could come up with a heuristic like, "If the traces use the same-named axes for both X and Y, then they are the same trace and there should be just one trace in the final graph".

What do you do if two axes are in the same spot but have different names? Are they one axis or two?

No doubt the best way to handle all this is to simply accept everything from each graph- if the same data are displayed in both graphs, you wind up with two traces. But in that case, you have to make sure to patch up the trace styles to reference the second trace (mode(ydata#1)=1, for instance).

At any rate, it seems like a good idea, but is far from trivial. Perhaps a good first step would be to figure out how to clone a trace into another graph. Perhaps that would cover what you really want. You may find
#include <Graph Utility Procs>

to be useful- it includes CopyTraceSettings() and CopyAxisSettings().

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Here is an approach I've used that you might be able to include in such a function. This procedure takes the specified trace and creates a new graph of it, which I often use to extract a trace as it is currently displayed. It has a few wonky workarounds to some limitations I had to contend with, but it works well for taking any trace from a graph and getting its properties to apply to a new graph. I figure you can use a similar approach to extract all trace information from a particular graph and apply it to another one.

Function DisplayTracename()
    GetLastUserMenuInfo
    //get recreation string
    string tracerec=StringByKey("RECREATION", replacestring(";",traceinfo("",S_traceName,0),"?",0,8),":","?")
    string winrec=WinRecreation("",0)
    Display TraceNameToWaveRef("",S_traceName)
    //apply recreation
    string exstr
    variable i
   
    for(i=0;i<itemsinlist(winrec,"\r");i+=1)
        exstr=stringfromlist(i,winrec,"\r")
        if(strsearch(exstr,"ErrorBars",0)>=0)
            if (strsearch(exstr, S_traceName+" ", 0) >= 0) // space prevents finding trace "wave0x" when you ask for "wave0"
                Execute exstr
            endif
        endif
    endfor
   
    for(i=0;i<itemsinlist(tracerec);i+=1)
        exstr=replacestring("(x)",stringfromlist(i,tracerec),"("+S_traceName+")")
        //do not include offset values
        if(!grepstring(exstr,"offset"))
            Execute "ModifyGraph "+exstr
        endif
    endfor
end

Menu "TracePopup", dynamic //"AllTracesPopup"
    getlastusermenuinfo
    "Display "+S_traceName+" as-is", /Q , DisplayTracename()
End


Several folks here helped me get this function going.
Thanks for the feedback.

I adapted my code (attached if anyone is interested) to now make an attempt to copy styles from the original graphs using the recreation string from TraceInfo. It works most of the time, but still can't deal with multiple instances of the same wave and finding the correct style for the appropriate instance (I made no effort to solve this). It also doesn't know what to do if there are text boxes or other objects with the same name in multiple graphs*. For my needs this is a workable solution, but it is not as general use-case as it could be.

I believe this would have been simpler to accomplish if there were a few additional options for the WinRecreation function.

For instance, it would be helpful if WinRecreation could take an option to return ModifyGraph commands including trace names (ie: verbose commands instead of shortform). It would also help if it could separate the trace-specific ModifyGraph commands (such as those in the Modify Trace Appearance panel) from the window-specific ModifyGraph commands (such as those in the Modify Axis and Modify Graph panels) perhaps by organizing these and using a comment line to act as a separator.

Best,
Andrew


*It should be possible to address this by finding duplicate object names in the command string and replacing these names with unique names.
MergeGraphs.ipf