#pragma rtGlobals=1 // Use modern global access method. // Prepared 6/22/2004 by Ed Dunlea // Lots of stuff here is just Ed's take on how to do things. // For the most part, you can blame Scott Herndon for the way I think in Igor. // The audience that I am shooting for at the moment is one that has a familiarity with Igor, but has not // yet gotten into programming yet. // ######################### // Functions vs Macros?? // Functions. // Oh, but you can do macros if you want something to appear in the pull down menus up top. // (there's other real reasons for using macros, but they are not that important, just use functions) // ######################### // How to put together a function function iAmDoingSomething( ) // note the "function" the " ( ) " and the "end" print "watch me go" // these are all musts for a proper function end // type iAmDoingSomething() // ######################### // How to input variables into a function function iCanInputAvariable( str, num ) // whatever you type is passed into the function, note separation by comma string str // variables must be declared on the first line(s) variable num // after the "function" statement // note that strings must be typed in with quotes print "Igor says " + str print num / 2 end // type iCanInputAvariable( "hi there", 6 ) // ######################### // compiling means making sure code is all in right format // does not mean your function will do what you want it to // ######################### // stop and show example of how something doesn't compile // comment out something and try to have it compile // ######################### // back to the show... // ######################### function returnAnumberPlusOne( num ) // your function always returns a value, you can define what it is variable num return num + 1 end // type print returnAnumberPlusOne( 2 ) function/T returnAstr( str ) // your function always returns a value, /T makes it a text string string str str += " and this is for the horse you came in on" return str end // type print returnAstr( "this is for you" ) // ######################### // call a function from within another function function whatever( ) variable temp = 9 print temp temp = returnAnumberPlusOne( 55 ) print temp end // type whatever() // ######################### // if - then statements function showAnIfThen( num ) variable num if ( num > 3 ) print "big" endif end // type showAnIfThen( 6 ) // type showAnIfThen( 2 ) function showAnIfThenElse( num ) variable num if ( num > 3 ) print "big" elseif ( num == 4 ) print "4" else print "small" endif end // type showAnIfThenElse( 6 ) // type showAnIfThenElse( 4 ) // type showAnIfThenElse( 0.8 ) // ######################### // do - while loops function doWhileLoop( num ) variable num variable idex = 0, count = num // good habit to define your variables outright when declaring them do print " wolly bully " idex += 1 while ( idex < count ) end // type doWhileLoop( 5 ) // ######################### function forWhileLoop( ) variable idex = 0 for ( idex=2; idex<9; idex+=1 ) // for ( ; ; ) print num2str( 100 - idex ) + " bottles of beer on the wall" endfor variable var = str2num( "99") // this also illustrates the num2str and str2num print "you started with " + num2str( var ) end // type forWhileLoop() // ######################### // let's try a quick example of something pseudo real function realityBites( wvName ) string wvName make/N=9 wavesName // creates a wave -- the /O flag is overwrite, the /N flag is number of points wave wv = $wvName // in order to interact with a wave, need to declare it, just like a string or a variable edit $wvName // makes a table doupdate // does just what it sounds like, updates everything at this moment wv[7] = 999 // the [7] notation interacts with point # 7, you will use with something like wv[var] all the time variable idex = 0, count = numpnts( $wvName ) wave wv = $wvName // note that I had to declare the wave in order to use it in a do // conditional statement, also applies when assigning if ( wv[idex] == 999 ) // values into a wave, e.g., wv[idex] = otherWv[idex+1] print " got one on number " + num2str ( idex ) endif idex += 1 while ( idex < count ) end // type realityBites( "junk" ) // ######################### function theSprintfStatement( str ) // sprintf is a formatted print into a string string str // printf is a formatted print into the cmd line printf "do you know how many times Ferris has been absent %s\r", str // equivalent to print "do you know how many times Ferris has been absent" + str // difference is that printf can handle more complicated stuff in a more compact manner variable var = 9 string aNewStr sprintf aNewStr, "%g times", var // sprintf is very useful, also check out fprintf for printing into a file aNewStr = num2str( var ) + " times" // this shows equivalent way of doing this with print print aNewStr end // type theSprintfStatement( "this term" ) // ######################### function howToUseLists() string someList = "jack;jill;hill;", newStr sprintf newStr, "%s and %s", stringFromList( 0, someList ), stringFromList( 1, someList ) sprintf newStr, "%s went up the %s", newStr, stringFromList( 2, someList ) // note that you can sprintf a variable into itself print newStr end // type howToUseLists() function moreLists() make/N=8/O my8sWave // note that using semicolon in middle of line makes it a new line make/N=9/O my9sWave // also note that because I just made the waves in the function my8sWave = 8; my9sWave = 9 // I didn't have to declare the waves -- this is sloppy, I should declared them string wvNameList = waveList( "m*", ";", "" ) print wvNameList printf "there are %g waves in this folder\r", itemsInList( wvNameList ) end // type moreLists() // ######################### function redimensionAwave( ) wave/Z wv = my8swave variable count = numpnts( wv ) // note that for multidimensional waves, use dimsize redimension/N=(count+1) wv end // type moreLists(); redimensionAwave( ) function properRedimensionAwave( wvName ) string wvName if ( waveexists( $wvName ) != 1 ) // ******** this is a really good habit ************* print "no such wave Killer, check your typing" return -999 endif variable count = numpnts( $wvName ) redimension/N=(count+1) $wvName end // type killwaves my8swave; properRedimensionAwave( "my8sWave" ) // type print properRedimensionAwave( "my8sWave" ) // type moreLists(); properRedimensionAwave( "my8sWave" ) // ######################### function duplicatingAwave() make/O/N=8 aCoolWave = 7 duplicate/O aCoolWave, aNotSoCoolWave // straightforward idea - making a duplicate copy of a wave aNotSoCoolWave = 8 end // type duplicatingAwave() // ######################### function howToDoWaveStats() duplicatingAwave() if (waveexists( aCoolWave ) == 1 ) wavestats aCoolWave // note that you can use wavestats/Q to suppress the infomation in the history window print V_max endif end // type howToDoWaveStats() // ######################### function concatenate2wvs() // this only works for Igor 5 duplicatingAwave() // for Igor 4 users - use functions from Scott's Concatenate Waves.ipf if (waveexists( aCoolWave ) != 1) // ConcatenateWaves( w1, w2 ), or ConcatenateWavesInList (dest, wl) print "something wrong" return -999 endif make/O/N=0 theCoolestWave string coolWvNames = waveList( "*coolWave*", ";", "") concatenate coolWvNames, theCoolestWave end // type concatenate2wvs() // ######################### function aWordAboutFlags() print "some useful flags to remember are:" print " /O == overwrite" print " /N=n == number of points" print " /Z == ignore errors" print " /Q == quiet" end // type aWordAboutFlags() // ############################################################### // good programming habits // 1) have all functions that you need in current ipf or in GlobalUtilities.ipf // that way you can take your ipf anywhere // I use a prefix for all functions in same ipf, like "SP_doMyStormPeakFunction()" // 2) the waveExists test // 3) always use idex, count -- some kind of consistent system // 4) waves are called something like "someWv" // strings for wave names are called something like "someWvName" // 5) I like to title my windows the same name that they are actually called // 6) how to make the same figure again and again // DoWindow/K myFig // kill, kill, kill // Display/W=(50,50,650,350) // this sets the size of the window // DoWindow/C/T myFig, "myFig" // make it fresh with the right name and title // then do your appendToGraph magic here // 7) all times in dateTime format // 8) print statements for errors that are informative yet funny // print "settle down Beavis, there is no wave by that name in this data folder" // 9) use the debugging tool (show example of the little red dot) // 10) try to make functions generally useful if possible, always harder, but very often very useful // 11) do messy test programming in the local procedure window (which is local to only whatever experiment you have // open at the moment, and then promote your fully functioning procedure to a permanent, saved ipf file // 11) if possible, always have Led Zeppelin IV playing // ############################################################### // // ############################################################### // general Igor tips: // Use the Data Browser (from data pull down menu) // organize your data into data folders; yes, it can make things a pain in the butt because you can only access // data in the current data folder, but it can really keep you organized when you've got lots of data // // Use Scott's GlobalUtilities.ipf // handygraphbuttons() // appendVal( theWave, theVal ) // primarycolors( "" ) // stackallaxes( "", 0, 0 ) // // Right click on any command word or name of a function to get to the help section on it. // // While programming, if you click out of programming windows (except when clicking on help windows), Igor will automatically attempt to compile your procedures. // // Ctrl + Y == rename a window // // Ctrl + J == call up the command window from wherever you are // // Ctrl + M == call up the local procedure window for fast little programs // // formatted notebooks are the bomb, can insert figures in them and then save them separately, // they are smaller than a whole experiment and you can illustrate your points in them nicely // // modifying graph stuff -- should insert some commands here that are cool // some cool lines to remember: // modifygraph lsize = 2 // modifygraph fsize = 16 // // ############################################################### // // ############################################################### // other topics I did not have time to cover, but you should look up on your own because they are extremely cool: // sscanf -- this is the bomb-diggety if you ever get to needing something like it // loadWave -- loading up waves -- types of files to load from : itx's, text files, delimited text, excel // I can provide examples if you are interested // how to make a dateTime wave (which I always use for my date and time format -- looks like 6/22/2004 14:20:55 // and is really a number of seconds from midnight on January 1, 1904) // setscale/P y, 0,0,"dat", $newTimeWvName // can use dateTime, date2secs (and several more) are useful for interacting with the dateTime format // data wave and time wave ( the x y pairing of waves ) // duplicate/O Series1 Series2_Regrid // Series2_Regrid = Series2[BinarySearchInterp(t_Series2, t_Series1[p])] // all waves have an x dimension that can be utilitzed (referred to as scaled waves) // setscale/P x, date2secs(2003,4,2.5), 60, "dat" doas1_no2_sc // must be a uniform step size between points // use the interp function to insert data from time and signal waves into a scaled wave // xcsr(a), xcsr(b), x2pnt, pnt2x -- all useful for interacting with the cursors // numType is useful in order to test for NaNs, etc // ###############################################################