different colors for different waves
reserbat
I've got a very simple problem, but I don't find how to solve it, neither my office mates (!)
I've got N waves (corresponding to N experimental curves, taken at different times) that I want to display on a single graph.
This is easy, but I would like also to make my wave 1 = red --> wave N = yellow with incremental changes from 1 to N in color.
Every ideas are welcome...
Antoine
Copy the following code in the procedure window. Make sure that your graph containing the traces is the frontmost and then execute setcolor() from the command window.
string trl=tracenamelist("",";",1), item
variable items=itemsinlist(trl), i
variable ink=103/(items-1)
colortab2wave yellowHot256
wave/i/u M_colors
for(i=0;i<items;i+=1)
item=stringfromlist(i,trl)
ModifyGraph rgb($item)=(M_colors[140+i*ink][0],M_colors[140+i*ink][1],M_colors[140+i*ink][2])
endfor
killwaves/z M_colors
end
Andreas
May 28, 2010 at 04:30 am - Permalink
Ciao
Antoine
May 28, 2010 at 05:25 am - Permalink
#include <KBColorizeTraces>
.May 28, 2010 at 07:25 am - Permalink
From Igor's Graph menu, choose Packages->Make Traces Different.
Generally useful tip: Check out the various Packages submenus when looking for something you have a feeling must be somewhere.
The other place to look is in Windows->Help Windows->WM Procedures Index.
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
May 29, 2010 at 10:51 pm - Permalink
We did something similar to this many years ago and called it "Rainbow()", but I'm re-inventing it using a routine in KBColorizeTraces.ipf.
I have a simple FUNCTION to colorize traces (below), and a question, because I'd like to change it to a MACRO, but I can't get that to work.
When I make it a Macro, I get an "Expected local variable name" error for "red" in the KBRGBToHS call.
Why?
I know that I can 'cheat' and make a MACRO called "Rainbow_" that simply calls the FUNCTION caled "Rainbow", but is there a way to make a direct call instead of this transfer?
A bit of explanation first:
1) Because HUE wraps around, I stopped the range in the "violet" part of the spectrum (47500) instead of going all the way to 65535.
2) Saturation is max (65535), and lightness is mid-range (32767)
3) Do-While is used in this example because For-endFor is not allowed in a MACRO (both work equally well in a FUNCTION)
string names=tracenamelist("",";",1),name
variable count=itemsinlist(names)
variable i,hue,red,green,blue
variable step = (47500) / (count-1)
i=0
do
name=stringfromlist(i,names)
hue = i * step
KBRGBToHSL(hue, 65535, 32767, red, green, blue)
ModifyGraph rgb($name)=(red,green,blue)
i+=1
while (i < count)
end
Thank you!
Sean
p.s. Is there a way to get TAB or SPACE characters in the code snippet "manually", i.e. w/o using the igor and /igor tags
June 11, 2010 at 07:59 am - Permalink
You can put space and tab characters in your post, but browsers collapse whitespace in HTML, so they won't be visible. In addition, if you don't surround your code with the igor tags, special characters like the < and > symbols will often be mistaken as HTML tags that are not allowed, and will not be displayed. This is done to prevent people from posting malicious HTML or javascript code on the site.
You can also use <code></code> tags around your code, but you won't get the benefit of Igor syntax highlighting that way.
June 11, 2010 at 11:13 am - Permalink
Also often I want a given quantity to be the same color in every graph. For example, if my data consists of displacement, velocity and acceleration, I want displacement to be red in all graphs, velocity to be green in all graphs and acceleration to be blue in all graphs.
My solution, which is far from ideal, is to create a function that returns an RGB color given an index number. The colors are manually chosen to be as distinct as I can make them for a given n.
See the function below for an example.
I use a separate function to map between index numbers and quantity names (e.g., displacement, velocity, acceleration).
It would be great to have a function that would return maximally distinct colors for any n but that's way beyond my capabilities.
Variable colorIndex
Variable &red, &green, &blue // Outputs
colorIndex = mod(colorIndex, kNumVanBlariganWaves) // Wrap around if necessary
switch(colorIndex)
case 0: // Time wave
red = 0; green = 0; blue = 0; // Black
break
case 1:
red = 65535; green = 16385; blue = 16385; // Red
break
case 2:
red = 2; green = 39321; blue = 1; // Green
break
case 3:
red = 0; green = 0; blue = 65535; // Blue
break
case 4:
red = 39321; green = 1; blue = 31457; // Purple
break
case 5:
red = 39321; green = 39321; blue = 39321; // Gray
break
case 6:
red = 65535; green = 32768; blue = 32768; // Salmon
break
case 7:
red = 0; green = 65535; blue = 0; // Lime
break
case 8:
red = 16385; green = 65535; blue = 65535; // Turquoise
break
case 9:
red = 65535; green = 32768; blue = 58981; // Light purple
break
case 10:
red = 39321; green = 26208; blue = 1; // Brown
break
case 11:
red = 52428; green = 34958; blue = 1; // Light brown
break
case 12:
red = 65535; green = 32764; blue = 16385; // Orange
break
case 13:
red = 1; green = 52428; blue = 26586; // Teal
break
case 14:
red = 1; green = 3; blue = 39321; // Dark blue
break
case 15:
red = 65535; green = 49151; blue = 55704; // Pink
break
endswitch
End
June 11, 2010 at 11:35 am - Permalink
Why would you want to do that?
It's because the last three parameters are call-by-reference- they are outputs. You can't call that function from a macro. Again, why do you want to make it a macro?
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
June 11, 2010 at 01:05 pm - Permalink
Is there a (historical?) programming explanation why the different code structures (do-while, for-endfor, ...) are allowed in functions, but not macros, or procedures, or vice versa?
It seems like 20 years after the introduction of these 'limitations', that someone could make each type of routine "equivalent", but I'm not a C++/?? guru to know that there would be any deep-seated programming reason why this is not possible.
Thank you,
Sean
p.s. nobody mentioned which HTML tag could be used for a TAB or SPACE character. There must be one, but I am not HTML-savvy.
June 14, 2010 at 04:34 am - Permalink
This will equate the menu "Rainbowize" to the FUNCTION Rainbowize ...
"Rainbowize Graph"/Q,Rainbowize()
end
I don't know either. AFAIK however, macros run somewhat as BASIC code in a "line-by-line" mode while functions run as pre-compiled units.
http://webdesign.about.com/od/localization/l/blhtmlcodes-punc.htm?rd=1
http://www.web-source.net/symbols.htm
The "non-breaking space" code - $nbsp; - is fairly common.
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
June 14, 2010 at 06:54 am - Permalink
In an earlier post, I also mentioned using a macro to call a function/procedure, but that just seems "wasteful", and I was wondering if there was a programming reason why the loop styles are not interchangeable, and similarly why Macros, Functions, and Procedures are all handled differently.
Sean
June 14, 2010 at 07:29 am - Permalink
That depends on what you figure is "wasted". For me, adding the extra Menu call at the top of the procedure is always a cleaner way to track where I am making the entry point in my code. I also think (though I could be wrong), using Menu calls to enter functions runs faster than using Macros to generate menu calls due to compiled versus run-time issues -- though even if I am correct, you would likely not notice the difference anyway.
My guess for the first is because writing pre-compiled code segments to map to do-while is a harder task than to map for-endfor.
My guess for the second is ... that is just showing the historical development of Igor coding from a run-time macro language to a compiled level function language.
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
June 14, 2010 at 08:26 am - Permalink
You can use a regular space character or a regular tab character. Note that in most browsers, hitting the tab key will move the selected form element, not insert the tab into a text box, so you have to copy and paste it in. But just because you have entered a tab character or multiple space characters doesn't mean that the browser will actually render them. That's why you need to enclose your code in code or igor tags, because doing so tells the browser that you want it to render the text as you have typed it. You can use multiple characters as a substitute for a tab character, because the browser will not collapse them into just one space, however this works just as well as using multiple spaces does to left align text...that is, not very well unless you're using a monospaced font. To use a monospaced font, you need to use code or igor tags, and if you use the tags you don't have to worry about putting in your own characters.
If you ever look at a .html page created by MS Word from a few versions ago, you'll see that they attempt to keep the layout the same by filling the document with characters all over the place, yet it still doesn't look very good.
When Igor was very young, it didn't support user defined functions. At some point, they were added. Because they are better in every (or almost every) way, new programming features were added to functions but weren't added to macros, because outside of window recreation macros people really should be writing functions.
So sayeth Programming.ihf
I'll also add that you can use Igor's debugger with functions, but can't do so with macros. [edit: actually, you can]
There are a few very old operations that cannot be called directly from within user defined functions. Some XOPs have similar limitations in external operations they provide. In those cases you can use the Execute operation to execute those operations.
June 14, 2010 at 09:14 am - Permalink
I also learned recently that you can execute a function by just typing it, without the need to actually do anything with the RETURNed value. i.e. just type foo() instead of print foo().
Slowly but surely I'll get back into the swing of things and I'll start thinking along the lines of making everything into FUNCTIONs.
Cheers!
Sean
June 14, 2010 at 10:29 am - Permalink
Well, that's actually not true: the debugger works just fine with Macros and Procs.
I know, because I wrote the debugger.
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
June 14, 2010 at 08:53 pm - Permalink
I found the package in the Graph menu. Can I also do this automatically with a command in a procedure? How would I do that?
(Sorry if the answer should already be clear from the previous post, but I'm new to Igor)
June 30, 2010 at 08:26 am - Permalink
Take a look at the content of the KBColorizeTraces.ipf procedure window that's loaded into your experiment when you select the package, and call the desired function(s).
For example to use the "Commonly-used Colors" feature from your own function, call:
CommonColorsButtonProc("")
End
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
June 30, 2010 at 11:47 am - Permalink
This example works fine, but I can't figure out, how I would use the function to color the graph in e.g. Rainbow colors. I found this function "static Function KBColorTablePopMenuProc(ctrlName,popNum,popStr) : PopupMenuControl" which looks to me like the option I have in the graphical interface. But what are the arguments I would have to use?
Could you maybe give me a really small (but complete) example of how I can color a graph in rainbow colors? Being a beginner in Igor, I couldn't figure it out myself so far.
July 1, 2010 at 02:24 am - Permalink
KBColorizeTraces#KBColorTablePopMenuProc("",0,"Rainbow")
July 4, 2010 at 10:45 pm - Permalink
KBColorizeTraces#KBColorTablePopMenuProc("",0,"Rainbow")
worked out fine so far. But now all on a sudden I get the error "attempt to use a null string variable".
It must come from the colorize traces. If I comment it out, the error is gone. I changed a few things in the procedure, but the error even persists if I open a new experiment and load the last working procedure I saved. Where might this error come from?
August 6, 2010 at 12:38 am - Permalink
Turn on "Enable Debugger", "Debug on Error", and "Wave, NVAR and SVAR Checking" in the Procedure menu. To do this you must first activate a procedure window. Then when an error occurs, Igor will drop into the debugger and you can see where the error is coming from.
For details execute this:
August 7, 2010 at 04:20 pm - Permalink
#include <KBColorizeTraces>
Macro test_load()
LoadWave/J/D/W/K=0 "J:TFT-Tatjana:evaporation:sample1:2010-06-11-gate-or-source-drain-scans:ivg_30050.txt"
•Display Isd_A_ vs Vg_V_
•KBColorizeTraces#KBColorTablePopMenuProc("",0,"Rainbow")
end
This is a small code, where the error still occurs. I just have now idea. Does the colorizeTraces use a string I don't know about? I seems that I have changes something in the program itself as it occurs now always (restarting Igor doesn't help, neither does a starting a new experiment).
I tried with the debugger. It stops at
SetDataFolder savedDataFolder
in StoreKBColorizeSettings (functionstatic Function StoreKBColorizeSettings()
)which is called by KBColorTablePopMenuProc in functionstatic Function KBColorTablePopMenuProc(ctrlName,popNum,popStr) : PopupMenuControl
I also get the information "savedDataFolder ¦ "root" "
It would be great if somebody could help in order to solve this problem. I think I don't know yet enough about Igor to understand such problems.
August 10, 2010 at 08:36 am - Permalink
String/G gColorTableName= S_value
It assumes that the KBColorizePanel control panel exists, but that is not the case.
You are calling this:
This is a popup menu action procedure that is designed to be called when the user clicks a popup menu in a control panel.
In other words, you're trying to use a function designed to work with a control panel but you don't have the control panel.
As it stands, it appears that KBColorizeTraces is not appropriate for programmatic use.
I would not use KBColorizeTraces for programmatic use but instead would create a custom function. See my post from June 11th above.
August 10, 2010 at 10:55 am - Permalink
But why did it work before without showing me an error?
And it still gives the desired result but shows me the error in the end.
August 11, 2010 at 01:33 am - Permalink
Because you had opened the panel which created variables that the function expects to exist.
August 11, 2010 at 10:02 am - Permalink
This is a nice feature of Igor's programming environment: Igor allows the code to execute anyway even though the error occurred immediately at the beginning - the error message is simply "delayed" as you said. The executed function
StoreKBColorizeSettings()
in which the error occurred certainly fails in some way, but this does not stop the calling functionKBColorTablePopMenuProc
to execute successfully.You seem earnest in learning more about Igor programming and I fear you are "being led" to a part of the learning curve that is particularly steep: You have been tempted to call a function deep in a procedure file not written by yourself, and you have even been enticed to use the debugger. If you want to compound this, here is "some more rope to hang yourself with" (as WM are prone to say): You can modify the KPColorizeTraces.ipf (after having saved it under a new name).
A "quick hack" would be to put the following code:
if( V_Flag == 0 ) // KBColorizePanel does not exist
return -1
endif
immediately below the line saying
This checks whether the panel actually exists and bypasses the rest of the code if it doesn't. It allows you to use your function call
without throwing the error, and without the need to actually open the panel even once ...
On the other hand, it is probably healthier to follow Howard Rodstein's advice and rather write a single, shiny new function as the one he put in his June-11th post. This avoids carrying a lot of functions around that are also part of the
KBColorizeTraces
package but "do nothing" for you, and reduces the future risk of entanglements in KBColorizeTrace's inner workings.If you use my tip above, you should also change the module name (second line in your newly saved .ipf file) to something other than
so that you can still use the original package if the need arises. If you do this, remember to change your call accordingly, i.e., type the same module name befor the "#" sign in the line
Greetings,
Wolfgang
August 11, 2010 at 10:52 am - Permalink