Instance-aware calls to Igor from script

This is a two part question / wish (if no functionality exists for either part). Some of what I describe below may be specific to Windows, as I have no experience with Igor on Mac.

Part 1: I would like to know if there is a way to force one instance of Igor to control another instance of Igor with a specified instance (window) name. As far as I know, the only way for two instances of Igor to interact (apart from XOPs, at least) is to use ExecuteScriptText to call either the 32-bit or 64-bit Igor executable.

When Igor is commanded in this way, it appears that there is a special "primary" instance (one for 32-bit and one for 64-bit) that gets all the attention of the associated Igor.exe (when called with ExecuteScriptText, at least). The other instances are untouchable via script. I wonder if there are any work-arounds so that one can get Igor.exe to deal with an Igor instance of choice.

Part 2: Is there a way to tell Igor to open a pxp from script? In Windows cmd.exe, I have tried <IGOR> <Path To Pxp> which causes the Igor that is under cmd.exe control to (open, if not yet opened, and) print "Error 1521 trying to open a file specified in start-up command: <Path to Pxp>" (here, <IGOR> is as described in DisplayHelpTopic "Calling Igor From Scripts")

Reason I am asking: I am trying to make it easy to move from graphs that were generated for presentation/publication (and saved as image files, which I usually embed in illustrator ai files) back to their pxp. My current process is to save a text file of similar name, which holds the name of the experiment that created the image. When Windows wants to open the image, the Windows default is to open it in Igor, which then has a BeforeFileOpenHook set to tell me what experiment they came from.

It would be ideal if this hook also opened the pxp, if it's available on the computer.

It would be even better behavior for it to cause the instance of Igor that already has that pxp open to maximize or blink (or something else obvious), if such an instance already exists.

As far as I can tell, these behaviors would require something like the functions described above.

 

Thanks in advance!

This is not to say that your ideas are not interesting in their own right. To your bigger question though: Have you considered using a meta-data-management app? The idea is to store information about "how was this content created" in its own meta-notebook in a hyperlinked format that references back to the source files. Think of a cork board dedicated to the project where you can post file contents or links to file contents for:

* images
* an Igor Pro experiment that created an image (perhaps as hyper-links on the image itself)
* a journal article written from the images or related to the image
* the raw data

An advantage of using this approach is that it allows you to create timeline snapshots of the project development.

In reply to by johnweeks

johnweeks wrote:
DisplayHelpTopic "Calling Igor from Scripts"

I started there, but as far as I can tell it makes no mention of either issue. Here's a more concrete example: 

Imagine that you open file1.pxp, then start a second instance of Igor (a second window, on Windows) and open file2.pxp in it, then you start a third instance of Igor (a third window) and open file3.pxp in it. I find that you can control at most one of these Windows from script and there is never access to the other two from script (unless perhaps you close the first one, in which case you might get access to one of the other two). It would be great to be able to control whichever one I'd like. 

Additionally, it doesn't seem that there is a way to tell an instance of Igor (either existing or about to launch) to open a pre-existing experiment file (e.g., file1.pxp) in it. I get the error code I mentioned above when I pass a pxp as the parameter for running Igor from script.

@jjweimer: I agree that that sounds great in principle. Do you use a certain program for that? My general approach has been to move as much of the data collection, notekeeping, and analysis into Igor, which has the flexibility to organize things as needed.

As far as linking back to a pxp or it's contents, I'd be curious to know how you propose to do it? An ability to launch and command specific Igor pxp files from script (whether they are opened or need to be opened) seems like a helpful mechanism. The link could launch the pxp, if it's not already open, and then bring the window to top (or recreate it if it no longer exists). That's mainly what I'm looking to do.

Thanks for the feedback!

I use Curio (https://www.zengobi.com) on macOS. I have a Curio project file as an administrative document for most of my big ticket projects that have inputs from multiple types of files.

On Windows, I understand that OneNote may be somewhat equivalent. For an old school approach, a colleague at a lab I visited some time ago used PowerPoint slides in a “presentation” as a repository of notes and links to oversee his projects.

I now realize that a pxp file is a valid parameter for Igor.exe when called from a script (thanks to this post). This allows one to open a pxp of choice in a new instance of Igor pro, or the pre-existing instance that is under control from script. The error message I mentioned previously was caused by my uncertainty about whether the /X flag would be required (and a typo in the path I was using). In the help, it does say "The usual parameter [for Igor.exe called from a script] is a file for Igor to open". Until now, I wasn't sure this included pxp files, though I had hoped it did.

That is helpful, but it is still not possible to command all instances of Igor Pro from script when multiple are open, as far as I can tell.

I have settled on a workaround which is: 1. open the pxp from script if it's not open, 2. activate and flash the window containing the pxp if it is open. I am not aware of a way to do part 2 in Igor alone, but via ExecuteScriptText Igor can easily make calls to NirCmd, which can activate and flash specific application windows in Windows. I've posted the code I've ended up with here.

@jjweimer. Good to know, thanks!

 

Yes, opening an experiment file from a script takes just the file path as the argument, with no flags.

I wonder if you could do what you want using multiple copies of the Igor Pro folder? Then you have unique paths to multiple Igor executables. The call to Igor would use the full path to whatever executable file you wanted to control. Probably a pretty cumbersome way to organize this.

An example of opening an experiment file using a command line in a script would be nice, wouldn't it?

Seems like it should be possible to identify an instance of a running Igor using the PID. I'm not sure if Igor is ready to respond to commands that arrive when it is already running.

One alternative is to send a single command to Igor that invokes an Igor procedure that does everything that needs to be done. You *would* use the /X flag for that!

In reply to by johnweeks

johnweeks wrote:
I wonder if you could do what you want using multiple copies of the Igor Pro folder? Then you have unique paths to multiple Igor executables. The call to Igor would use the full path to whatever executable file you wanted to control. Probably a pretty cumbersome way to organize this.

Hah, that's an interesting way to get around the problem. It seems to work in a quick test, but I agree that actually implementing it would be (very) cumbersome and so I am not particularly eager to go with that approach.

johnweeks wrote:
Seems like it should be possible to identify an instance of a running Igor using the PID. I'm not sure if Igor is ready to respond to commands that arrive when it is already running.

One specific open instance of Igor usually reliably responds to a succession of command line inputs (with the /X flag, no /I flag). However, for a given Igor executable, it seems there is always just one special instance.

A /PID=pid flag for running Igor from script would be an ideal solution, though I am not sure that that is easily implemented -- I imagine it could run into a limitation of scripted commands on Windows.

johnweeks wrote:
One alternative is to send a single command to Igor that invokes an Igor procedure that does everything that needs to be done. You *would* use the /X flag for that!

That's exactly what I want to do, but it seems that there is simply no way to send a script command to any (but one) of the open instances of Igor (barring your multiple Igor.exe idea). (What "needs to be done", ideally, is tell the pxp that generated a graph to activate its window if its already open--I've solved that part already--and run procedures like bringing the original graph to the top--I haven't been able to do the latter because of the instance issue. I might add that some of these pxps are/will be multiple Gb and possibly dozens of windows, so I am trying to avoid reopening any pxp that is already open.)

Thanks again.

I know of customers who have put together quite complex systems that use one master Igor instance that is responsible for starting up subsequent instances based on commands sent to it. My recollection was that this was a method of multithreading batch processing of some sort: each instance of Igor started up by the master instance would process a file and deposit results in a .pxp file.

I'm wondering if you could do something like that- have the first instance of Igor responsible for looking through the images and spawning further instances to open the experiment files.

But I guess I'm just realizing what your real problem is: if an experiment file was already opened, how do you contact that instance of Igor to do something?

A thought without any analysis- I wonder if ActiveX might help with this? A (very) quick look through the Automation Server help file makes me wonder if you could spawn a COM object for each open instance, and keep track of the Igor instances that way. Could be a total blind alley!

In reply to by johnweeks

johnweeks wrote:
But I guess I'm just realizing what your real problem is: if an experiment file was already opened, how do you contact that instance of Igor to do something?

Yes -- at this point that is my problem. At first I was having trouble with launching unopened pxps too but I've figured that part out (as mentioned above).

ActiveX sounds promising. The meaning of the /Automation flag was opaque to me until you mentioned this, which led me to ctrl+F for automation in the help and realize that a description of using Igor as an ActiveX Automation serve was helpfully positioned right above "Calling Igor From Scripts". I'll take a look at some of the examples. I've never worked with ActiveX so if anyone knows of an example of using ActiveX in this way, that would be very helpful.

In reply to by thomas_braun

thomas_braun wrote:
I would not start using ActiveX.

We are successfully using https://github.com/AllenInstitute/ZeroMQ-XOP/ for communication between different igor instances and other programming languages and IP. It works also across the network.

Thank you for the advice. An issue with ZeroMQ-XOP for what I want to do is that there's no built-in way to coordinate calls to ZeroMQ-XOP from Igor (at least if I am reading its documentation correctly and if the documentation is up to date, it says "Direction: Igor -> World: not yet implemented"). I'd like to have one instance of Igor control another (rather than some other program control them). It seems like one would need to add to that XOP or write a new one, so that Igor commands ZeroMQ or something else, which in turn talks to the other instance of Igor through ZeroMQ. At present, the benefit isn't great enough to justify getting into something that elaborate. 

Two instances of IP can talk to each other. The readme might have forgotten to state such an obvious thing. The remark about the direction "Igor Pro-> World" means that there is no messaging mechanism which let's you get notified as World if something in IP happens.

I've posted an example some time ago on the mailing list, see http://info-igor.org/IgorMessages/2018/09/Info-Igor_2018-09_0011.html. That example posts raw data from one instance to the other. You can also call an user defined function via the zeroMQ and get the results back.