Help understanding Macro Execute Error

Neurons
Posts: 9
Joined: 2017-06-12
Location: United States

I am trying to write a macro that makes calculations based on X and Y variables. The variables are imported via Neuromatic, but the units are not necessarily the same each time. Therefore, I would like my macro to be able to convert to SI units based on the data read from the String variables.

I tried running the macro and it seems to execute

if ($xLabel = "Time (msec)") 
Variable bin = $SampleInterval*10^-3

just fine, but when it gets to the (nearly identical) next line

elseif ($xLabel = "Time (sec)")

it throws an error that reads "This syntax is not allowed in macros -- use functions"

I would like to follow with a similar if-elseif statement for y units, and I would strongly prefer not to have run a function prior to my macro for each new data set (there are hundreds if not thousands of these, and I am bound to make mistakes if I have to remember to do it manually).

So...what exactly is wrong with my syntax, and what changes should I make so that it will work with my macro?


[ last edited June 14, 2017 - 20:00 ]
ChrLie
Posts: 253
Joined: 2009-01-06
Location: Switzerland

Hello,

it would be good if you could post a complete minimum example of you code, not just fragments. Here, it is not clear how "xLabel" is defined. If it is a string, you probably want to use cmpstr(xLabel, "Time (msec)") instead of what you have now.

...(edit: deleted an incorrect comment regarding the "$" operator)...

Unless you have a very specific reason you should be using functions instead of macros, please check out DisplayHelptopic "Macros" and the topic underneath.

PS: a function tells you on compiling what is wrong. Enter first the following into a procedure window:

macro testMacro()
	if ($xLabel = "Time (msec)")  	
	else
endmacro

Then click "Compile" at the bottom of the window. Nothing happens.
Now add the following and compile again.

function testFunc()
	string xLabel
	if ($xLabel = "Time (msec)") 
 
	else
end


[ last edited June 14, 2017 - 22:15 ]
Neurons
Posts: 9
Joined: 2017-06-12
Location: United States

ChrLie wrote:
Hello,

it would be good if you could post a complete minimum example of you code, not just fragments. Here, it is not clear how "xLabel" is defined. If it is a string, you probably want to use cmpstr(xLabel, "Time (msec)") instead of what you have now.

...(edit: deleted an incorrect comment regarding the "$" operator)...

Unless you have a very specific reason you should be using functions instead of macros, please check out DisplayHelptopic "Macros" and the topic underneath.

PS: a function tells you on compiling what is wrong. Enter first the following into a procedure window:

macro testMacro()
	if ($xLabel = "Time (msec)")  	
	else
endmacro

Then click "Compile" at the bottom of the window. Nothing happens.
Now add the following and compile again.

function testFunc()
	string xLabel
	if ($xLabel = "Time (msec)") 
 
	else
end

Thanks for the feedback. I can't include my entire macro code as it's nearly 300 lines, but the part that I most recently added starts with what I included in my original post. I did not have to encode "xLabel" as that was encoded automatically by Neuromatic when I imported the data. I assume it is a string variable because when I click on xLabel in the Data Browser Igor returns xLabel = "Time (msec)" and there is a "$" icon to the left of "xLabel" in the Data Browser (numeric variables have the "#" icon and waves have those funky squiggly lines). If there is a way to confirm that's the case, I would like to know. I know in R, for example, I would write  storage.mode(xLabel) and that would return something like [1] "character". I'm not sure what the Igor equivalent of that would be.

I don't understand how compstr would be used in this context since there is only one "xLabel" for each data file, so there is not really anything to compare to. I'm sorry if I was not clear earlier in my explanation, but the files will all be imported via Neuromatic and Neuromatic creates many of these variables, including xLabel and SampleInterval.

I tried the DisplayHelpTopic "Macros" and got an error that read "The topic was not found after searching all the Igor help files in the Igor Pro folder and subfolders. Replacing "Macros" with "Macro" helped a little, as Igor brought me to help a topic for Macro that--although quite brief--included a link to Macros but when I click on it I get the same error message as before.

When I tried to compile

 function testFunc()
	string xLabel
	if ($xLabel = "Time (msec)") 
 
	else
end

I got an error message that read "Can't use $ in this way in a function." I have been using a tutorial (http://payam.minoofar.com/wp-content/uploads/2007/07/introduction_to_igo...) to learn Igor programming and from what I've read there it seems like that is exactly how $ should be used in a function. What am I missing?


Posts: 1780
Joined: 2007-06-29
Location: United States

Try this:

function testFunc()
	string xLabel
	if (CmpStr(xLabel, "Time (msec)") == 0)
 
	elseif ...
end

The $ operator turns the contents of a string expression into a name. Since you actually want the string expression contents (a single string variable can be an "expression") then you don't need the $ operator.

Using "=" you get an assignment. Your line if ($xLabel = ...) is trying to get the name of a global string variable from the contents of xLabel, then *assigning* the quoted string to that global string variable. In programming, the "=" character is not an assertion of equality, it is an assignment of value.

Strings (unfortunately) cannot be compared using == (the actual assertion of equality). You must use CmpStr() to do it.

After posting, it occurred to me that you probably really did mean to use the $ operator. Here's another version:

function testFunc()
     ... do something to put a value into local string xLabel ...
	SVAR xlbl = $xLabel
	if (CmpStr(xlbl, "Time (msec)") == 0)
 
	elseif ...
end

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com


[ last edited June 15, 2017 - 11:25 ]
Neurons
Posts: 9
Joined: 2017-06-12
Location: United States

johnweeks wrote:
Try this:
function testFunc()
	string xLabel
	if (CmpStr(xLabel, "Time (msec)") == 0)
 
	elseif ...
end

The $ operator turns the contents of a string expression into a name. Since you actually want the string expression contents (a single string variable can be an "expression") then you don't need the $ operator.

Using "=" you get an assignment. Your line if ($xLabel = ...) is trying to get the name of a global string variable from the contents of xLabel, then *assigning* the quoted string to that global string variable. In programming, the "=" character is not an assertion of equality, it is an assignment of value.

Strings (unfortunately) cannot be compared using == (the actual assertion of equality). You must use CmpStr() to do it.

After posting, it occurred to me that you probably really did mean to use the $ operator. Here's another version:

function testFunc()
     ... do something to put a value into local string xLabel ...
	SVAR xlbl = $xLabel
	if (CmpStr(xlbl, "Time (msec)") == 0)
 
	elseif ...
end

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com

Thanks! Although SVAR throws an error message that reads "Must use WAVE, NVAR, and SVAR to access global waves, variables and strings with #pragma rtGlobals = 1." I've read a little on these numeric assignments for rtGlobals, and it sounds possibly risky to not use 3, although I don't know all the details and when I try to click on "The rtGlobals Pragma" hyperlink under rtGlobals to see the full details I receive a message that reads "The topic was not found after searching all the Igor help files in the Igor Pro folder and subfolders." Incidentally, I receive that message when I try to click on the hyperlink "Accessing Global Variables and Waves" under "see also" for SVAR/NVAR.

Is SVAR the only option for accessing global variables from a macro or function, or is there a way I can avoid having to switch the rtGlobals assignment? If not, what potential pitfalls should I be on the lookout for with rtGlobals = 1?


Posts: 1780
Joined: 2007-06-29
Location: United States

rtGlobals=3 adds more stringent error checking to the compiler, which is actually a Good Thing, even though it is sometimes annoying. It's optional partly because a couple of the new errors cause code that works (but may be silently buggy) to fail to compile. So to help those people out, you can use rtGlobals=1.

Quote:
Although SVAR throws an error message that reads "Must use WAVE, NVAR, and SVAR to access global waves, variables and strings with #pragma rtGlobals = 1."

That shouldn't happen, unless your code has some syntax error in it. I can't really tell you what might be wrong without seeing the code that gives that error. Try creating a small function that just does the look-up, and doesn't actually try to do any processing. If you still have the error, post the small function here. Post the whole function.

SVAR is only available in functions.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com


Neurons
Posts: 9
Joined: 2017-06-12
Location: United States

Here is the code. The error comes from line 3, beginning with SVAR...

 #pragma rtGlobals=3		// Use modern global access method and strict wave access.
function testFunc()
	SVAR xlbl = $xLabel
	NVAR bin = SampleInterval
	if (CmpStr(xlbl, "Time (msec)") == 0) 
	Variable bin = bin*10^-3
	elseif (CmpStr(xlbl, "Time (sec)") == 0)
	Variable bin = bin
	[else 
		print "Error: x units are not in msec or sec. Edit Macro under '//Get the x units right' to include an elseif with this data's xLabel with proper multiplier."]
end

I do not have the code that encoded xLabel or SampleInterval as both were encoded automatically by Neuromatic when I loaded the data file, but they are in the right folder with the red arrow pointing to it so I assume Igor should be able to find them.


Posts: 1780
Joined: 2007-06-29
Location: United States

If the global string variable you are trying to connect to is called xLabel, then the $ operator is not needed. You can use a shortcut version of SVAR in that case:

function testFunc()
	SVAR xLabel
	NVAR SampleInterval
	if (CmpStr(xLabel, "Time (msec)") == 0) 
		SampleInterval = SampleInterval*10^-3
	elseif (CmpStr(xLabel, "Time (sec)") == 0)
		//SampleInterval = SampleInterval		// this doesn't do anything...
	else 
		print "Error: x units are not in msec or sec. Edit Macro under '//Get the x units right' to include an elseif with this data's xLabel with proper multiplier."
	endif
end

Please read carefully starting at DisplayHelpTopic "Accessing Global Variables And Waves". It is tough going...

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com


Posts: 1596
Joined: 2007-06-21
Location: United States

Quote:
I tried the DisplayHelpTopic "Macros" and got an error that read "The topic was not found after searching all the Igor help files in the Igor Pro folder and subfolders.

This sounds like there is something wrong with your installation. The help topic "Macros" is in the Programming.ihf help file in Igor6 and in the Macros.ihf help file in Igor7. In either case, the help file should be automatically opened by Igor when you launch it. Igor opens all files in the "Igor Help Files" folder of the Igor Pro installation folder at launch time. You should see that help file in the Windows->Help Windows submenu in Igor6 or in the Help->Help Windows submenu in Igor7.

For further help with this, I would need to know what version of Igor you are running and what OS.

You should also do the Igor Pro tutorial by choosing Help->Getting Started. This includes a section entitled "Using Igor Documentation" that walks you through using the online help.


Back to top