Passing variables between macros

macro
Tags: #<Tag:0x00007fd54041f1c8>

#1

Dear Forum,

I have a bit of a problem passing variables between macros.
I wrote a litte measuring macro wich works great and saves much time.
At the beginning of the measuring I created a dialog wich asks for the initials of the operator and the measuring time

macro "Measure OCT gapsignal lenght [n]" {operator = "TM";
// some code
operator = "TM";
Dialog.create("Fill");
Dialog.addString("Initials:", operator);
Dialog.addNumber("Measure time:", 1);
Dialog.show();
operator = Dialog.getString();
measuretime = Dialog.getNumber();
//some code for obtaining values

This is working as well.

The variables “operator” and “measuretime” are needed later when I want to save the results table as a csv file.
Now it gets tricky to explain for me :slight_smile:

Saving the files is done with user defined shortcuts

macro "Dentin [d]" { 
save ();

By pressing “d” on the keyboard, the macro Dentin is called and executed.
save is a user defined function wich contains the code for the destination, name and saving the file.
In the save function I’d like to get the value which the user entered at the begining of the macro (initials and measuretime).
But ImageJ is not happy when i use the

operator = Dialog.getString();
measuretime = Dialog.getNumber();

function.
Is there a way to store these values in an overall accesable place?
I found some String Functions in the Built-in Macro Functions, but therfore I need to work with endswith and starts with, and this is a bit confusing for me, hence the example macro isnt much help for me …

I hope you will understand my problem and can maybe help me!?

Best

Tobias

p.s. Using shortcuts like mentioned above is very comfortable for me because I have 8 shortcuts defined for various parameters, which are all saved in a different csv tables in different locations.


#2

Dear @TMC,

you should be able to solve your issue using global variables:

var operator = "TM";

macro "1" {
// set operator
}

macro "2" {
// read operator

Best,
Stefan


#3

Thank you Stefan,

setting a global variable seems to be the way.

But maybe I’m doing it wrong. In my case the the readout is within a user def. function.

var operator = "TM";
var measuretime = 1;

macro "1" {
// set operator (dialogbox)
operator = Dialog.getString();
measuretime = Dialog.getNumber();
}

function save {
// read operator

Is this working only with macros?

( found this in the nabble archives :http://imagej.1557.x6.nabble.com/User-input-for-a-global-variable-in-a-macro-td3694344.html)

Wich is about the same what you suggested…

Best

Tobias


#4

Dear Tobias (@TMC) ,

the following script opens a Dialog and stores the first field (Blubb) to the global operator variable. Executing the second macro (which calls save), prints the content of the first field of the dialog. That is the behavior that I expect, which might not be what you are trying to achieve?

var operator = "TM";
var measuretime = 1;

macro "1" {
	// set operator (dialogbox)
	Dialog.create("Title");
	Dialog.addString("Bla", "Foo");
	Dialog.addNumber("Blubb", 0);
	Dialog.show();
	
	operator = Dialog.getString();
	measuretime = Dialog.getNumber();
}

macro "2" {
	save();
}

function save() {
	// read operator
	print(operator)
}

Best,
Stefan


#5

Thank you Stefen, I think we get there.
This is what I want. Nearly.
In the time between my post and yours I wrote this little example code (which is nearly the code you just wrote.

var operator = "TM";
var measuretime = 1;
macro "test" {
	Dialog.create("Titel");
	Dialog.addString("Bla",  operator);
	Dialog.addNumber("Blubb", 1);
	Dialog.show();
	operator = Dialog.getString();
	measuretime = Dialog.getNumber();
// to use the shortcut for the second macro you need to isntall it, save this code in plugnins/Test/_test.ijm
	dir3 = getDirectory("imagej");		// grabs parent directory of imagej
	dir4=dir3+"plugins\\Test\\";		// defines path of the macro
	dir5=dir4+"_test.ijm]";			// macro name
	path1="["+dir5;
	path=replace(path1, "\\", "/");					
	run("Install...", "install="+path);	
		
}
macro "test_2 [q]" {            // make the imagej mainwindow active and hit "q" to run the second macro
	test();
	print("Test",0);
	}
function test() {
	print(operator);
	print(measuretime);
}

With this code, which is nearly the same as yours, it wont take the new stored variable.
It just prints TM and 1 into the log. I don’t no why :confused:

Do you have any Idea why? I’m shurely missing somthing? (maybe in the installing part?)

Best Tobias


#6

Okay…
My prior guess was right.
The installation of the macro during running the macro seems to be the problem. But I need to install it because of my many custom shortcuts.
One other way to install the macro is to put it into the toolbar under “>>” [Fiji.app\macros\toolsets]. But the it wouldn’t start automacily (yet, maybe I find a way) if i click on it. …

Best Tobias


#7

I have installed my macro set via Plugins > Macros > Install. This way it works properly in my up-to-date Fiji installation.

Looking at your code I can’t shake the feeling that I don’t get what exactly you are trying to achieve with the installation during the macro run. Could you please provide some more information, @TMC?


#8

Aha! Now that I have had a coffee :grin:

I am not entirely sure that this is the ideal way, but it works for me.

  1. Create a plugins/Scripts/Plugins/AutoRun folder in your Fiji installation (this macro will be executed automatically on startup)
  2. Create an install_macro.ijm with your pathfinding logic in there (see below)
// install_macro.ijm
run("Install...", "install=/opt/Fiji.app/plugins/Macros/tmc_.txt");

This will install the macros that are contained in /opt/Fiji.app/plugins/Macros/tmc_.txt with the respective shortcuts in Fiji, which is what you wanted to achieve I guess.


#9

Sorry I’m a bit clumsy in explaning, since my mother language is german ^^ .

Well, yes. If I install your macro code manually, it is working for me as well. (Installing my macro manually would do as well)
But that is not what I want to achieve. I want that the macro (and therefore the shortcuts aswell) are installed when the user starts the macro. The macro is inside the plugins folder. But if I implement the following code FiJi forgets the global varialbe changed in (example) macro 1

// to use the shortcut for the second macro you need to install it, save this code in plugnins/Test/_test.ijm
	dir3 = getDirectory("imagej");		// grabs parent directory of imagej
	dir4=dir3+"plugins\\Test\\";		// defines path of the macro
	dir5=dir4+"_test.ijm]";			// macro name
	path1="["+dir5;
	path=replace(path1, "\\", "/");					
	run("Install...", "install="+path);	`

The macro is desinged for manual analysis of images. So, basicly its opening an image stack. The user had to use the freehand or polyline to measure strucktures within the image. After drawing (measuring) the user wants to store the values in an csv file. For each struckture (there are about 14 structures to analyse). Each structure is to save in a different file in a different location. For simplicity I defined for each struckture an macro with an shortcut (Thats why I have to install the macro at the first place). So the user had only to press the shortcut and the value is saved.
I hope this will get you on track :slight_smile:

Now I want to implement another feauture to this code. I want that the user enters his/her initials.
Because for statistical reasons more than one user had to analyse the same image stack. So now it is necesary that each user has its own folder (distinct through the initials).

Right now I’m trying to get rid of the automatic installing part, maybe paste the macro into the startup macros txt. But I dont want the shortcuts allways accesable …
Maybe I can solve it by putting the “install” part in an other macro. (Can I call and activate an macro in an macro?)
Like a separat ijm file stored somewhere wich contains the install part?

Best

Tobias


#10

Please see the reply that I had posted in the meantime :slight_smile:


#11

Thanky for staying with me :slight_smile:

Am I right, that this way the shortcuts are always acitive?
This would do the trick, but its not elegant. Because we do more stuff with Fiji where we use the “normal” shortcuts.
But thanks anyways :smiley:

TM


#12

Okay I may found a more suitable solution.
Since the problem is installing the macro automaticly, and then change the global variables, i wrote this example:

var operator = "TM";
var measuretime = 1;

macro "install" {
     //installs the macro (installing all shortcuts
     waitForUser(short description);
}
macro "Dialog [i]" {
    // asks for initials
}
macro "Load Dataset [n]" {
    // loads images and does other stuff
}
macro "Measurement [1]" {
    // creating custom resultstable
}
macro "Saving Results Structure One [s]" {
    // saves resultstable in a folder (there are 14 macros like this on in the ijm file for the other structures)
    // contains function for saving

This way the initials ara passed correctly.
Is there a way that the macro automaticly goes to the “Dialog [i]” macro and if the user clicks on okay its going to the "load Dataset [n] macro? (without having the user to use the shortcuts [i] and [n]).

Best Tobias


#13

If you put the Dialog [i] macro first, this is what will be executed when pressing Run. To automatically load the dataset, you should factor out the loading in a function and then call that function from both the Dialog and the Load Dataset macro:

macro "Dialog [i]" {
    // asks for initials

    // hand off to loadDataset function
    loadDataset();
}

macro "Load Dataset [n]" {
    // hand off to loadDataset function
    loadDataset();
}

function loadDataset() {
    // loads images and does other stuff
}

Is that what you mean?


#14

Hey Jan,

thats not what I want to achieve. The first thing to do is to install the shortcuts, then open the dialogbox for the initials and then load the dataset.

Somehow imagej gets confused with the global variables if I doit that way:

var operator = "TM";

macro "install" {
	dir3 = getDirectory("imagej");		// grabs parent directory of imagej
	dir4=dir3+"plugins\\Test\\";		// defines path of the macro
	dir5=dir4+"_example.ijm]";		// macro name
	path1="["+dir5;
	path=replace(path1, "\\", "/");					
	run("Install...", "install="+path);	// installs the shortcuts
	dialog();
	loadData ();
}

macro "LoadDataset [n]"{
	loadData ();
}
function dialog () {
	Dialog.create("Fill");
	Dialog.addString("Initialien:",  operator);
	Dialog.show();
	operator = Dialog.getString();
}
function loadData () {
	print("Loading Complete:", 1);
	print("Operator:", operator);
}

If I run this script, in the beginning it prints the initial I typed in (e.g. DF).
But if I press [n] to do a nother analysis, it just prints TM. I need it to print “DF”

I hove no clue why.

I guess its about the order of execution. It seems fiji is “forgetting” that I previously told him that the variable operator is “DF”

Have you any clues?

Best Tobias


#15

This is because you are running two instances of the same code: in the scope of the script that you start from the script editor, you set operator to “DF”; but the code that gets installed as a macro has not been called yet, it would only get initialized once you run the dialog() function of the installed version of your code.

In general, I agree with @stelfrich that the process you’re trying to achieve is rather convoluted. You should separate installation and execution of your code as he suggests. For example, you could have a short macro file Install_and_run_my_analysis.ijm that you copy into your ./Fiji.app/plugins/Scripts/menu-of-your-choice and that does the following:

run("Install...", "install="+path);
run("Dialog [i]");
run("Load Dataset [n]");

Another - maybe better - option is to put your script into ./Fiji.app/macros/tools and use the >> menu to start it, as you mentioned yourself already.


#16

Dear @imagejan and @stelfrich,

thank you both for your help. I was on a short trip and had no time to answer.
I guess the way I want to do it is not feasible with imagej. But nevertheless, I found a way wich is working for me.
The user has now to press one more shortcut in the beginning and then it’s the working perfectly.
I separated the installation part and the dialogbox part, maybe in the future when I’m more experienced in writing code I’ll find a more elegant solution. :slight_smile:

Best

Tobias


#17

Sorry for digging out this old topic. I have a little different problem, which is, however, related to the problem above.
I understand that I have to define variables outside of the a macro to make it global. But how about paths of a directory.

macro_inDir = getDirectory("Where is the macro?");
macro_name = getString("How is the macro called on your system?","test.ijm");
run("Install...", "install="+macro_inDir+macro_name);
dir=getDirectory("Choose a working directory"); 
test_folder= dir + "\\test\\";
File.makeDirectory(test_folder); 

macro "Macro s [s] "{
    print("Some text to explain the macro");
}

macro "Macro 1 [1] "{
    open("C:\\Users\\User\\Desktop\\test\\Image21.tiff");
    title=getTitle();
    saveAs("Tiff", test_folder+title);
    run("Close All");
}

When I run this script it first installs the macro and creates a folder in my “working directory”. But when I later call Macro 1 it forgets what test_folder is (in saveAs("Tiff", test_folder+title);). Even when I include print(test_folder);, it does not know what it is. I tried to store the path as a variable, but this does not work either.

Any ideas?

Thanks a lot.


#18

Welcome to the forum, @Smu21101.

Adding var in front of the variable declaration should help (see the macro language documentation):

var test_folder= dir + "\\test\\";

(Please always link if you cross-post on stackoverflow.com)


#19

Thanks for the reply. I will try the var and cross-link the next time. Thanks