Best way to have multiple versions of a toolbox peacefully coexist?

Folks,

I have a question about how to package up some code I wrote in such a way that it's easy to switch between different versions of the code. I've read about modules and independent modules, but I'm not sure that they're an ideal solution to my problem. Any suggestions would be appreciated.

I'm working on a set of procedure files for doing data acquisition, which are collectively called "DataPro". These procedure files all work together to display windows, acquire data, etc. At this point, there have been several versions of the DataPro package.

In the past, a user would install DataPro by putting a DataPro folder containing all the .ipf files in their User Procedures directory, and then create a shortcut to the main DataPro.ipf file (which #includes all the others) in their Igor Procedures folder. Then they would do an experiment (in the non-Igor-Pro sense) using this package, which would result in an unpacked experiment (in the Igor Pro sense) containing the acquired data in various waves.

The problem arises when the user upgrades to a new version of DataPro, which (currently) means deleting the the old DataPro folder in User Procedures, deleting the old shortcut in Igor Procedures, and installing new ones in their place. The user can now do new experiments using the new package, but when they go back to look at an old experiment file, all the windows in it were created with the old version of the software, so all the callbacks point at procedures in the old version, which may or may not be present in the new software, and so chaos ensues if they try to use any of the controls in the windows.

So my question is: How can I make it so that the user can have several versions of the package installed at the same time, and have them peacefully co-exist?

The best solution I can think of involves using modules, but seems non-ideal. I could put all my code in a module, and have different module names for different versions of the package. Also, the name of the DataPro.ipf procedure file could carry a version specifier, e.g. DataPro704.ipf. Then the user could modify the procedure file of their old experiments to #include the appropriate DataPro.ipf file. For their future experiments, they could make a template whose procedure file #include's the latest version. Then, when a new version is released, they could just change that one line in their template. But then (if I understand right) I would have to add the module name to all the callback specifiers in all my controls, because callbacks are searched for in GlobalProc. That sounds like a royal pain...

Is there a better solution that I'm overlooking?

Thanks in advance for any help you can lend...

Adam

This is difficult.

I came up with a solution for another user and created a very simple demo of it. My solution is attached. An explanation of how it works can be found in the comments in the "Demo Loader.ipf" file.

The solution involves a file structure like this:
Igor Pro User Files
  Demo  // Your package folder
    V1
      Procedures
        DemoProc.ipf
    V2
      Procedures
        DemoProc.ipf
    V3
      Procedures
        DemoProc.ipf


It relies on the fact that a #include statement can take a partial path (starting with a colon) which is interpreted as relative to the "Igor Pro User Files" folder.

This may not solve your problem but it may give you some ideas.

The use of partial paths to reference the various versions of the procedure file prevents the use of shortcuts (a.k.a, aliases) to activate the Demo folder. This is because Igor does not resolve shortcuts when interpreting the individual elements of a partial path in a #include statement. This in turn means that the Demo folder must reside in the Igor Pro User Files folder so that its contents can be referenced using partial paths. This is generally not a problem but if for some reason you want it to reside elsewhere then a different approach would be needed and it would require that the version be encoded in the name of each procedure file. So you would have DemoProcV1.ipf, DemoProcV2.ipf, DemoProcV3.ipf. You would then put a shortcut to the Demo folder in User Procedures and use a simple file name rather than a partial path in the #include statement. The #include statement with a simple name causes Igor to search User Procedures and subfolders, including subfolders referenced by shortcuts. By virtue of the shortcut to Demo in User Procedures, Igor would find the referenced procedure file.
Demo.zip
Just out of curiosity: Why are the data acquisition procedures included in the experiment results at all? Wouldn't it be better to just get the raw data and no extra clutter in form of open windows, outdated variables, leftover data, etc., which even causes these kind of problems? I would suggest a separation of steps: Acquire raw data just as waves / packed experiments without any extras (ok, maybe runtime documentation, if you like), then create specific collections for a data series, and then analyze the data in a separate step. If you keep your procedures somewhat backward compatible, you can exchange for new versions all you like.