#pragma rtGlobals=2 // Use modern global access method. #pragma IgorVersion = 5.05 #pragma version = 2.58 Menu "Graph" "Append Multiple Graphs to a Layout",AppendGraph2LayoutN(NaN,"","") End Menu "Layout" "Append Multiple Graphs to a Layout",AppendGraph2LayoutN(NaN,"","") End // Puts text on the lower right corner showing when the layout was made, and on the lower left showing where it came from Proc Layout_Corner_Labels_Style_() // This is needed to make it show up in the "Layout Macros" menu Add_Corner_Labels_To_Layout() End Proc Add_Corner_Labels_To_Layout() : LayoutStyle PauseUpdate; Silent 1 // modifying window... Textbox/C/N=stamp0/F=0/A=RB/X=0.1/Y=0.1 "\\Z06\\{\"%s %s\",date(), time()}" Textbox/C/N=stamp1/F=0/A=LB/X=0.1/Y=0.1 "\\Z06\\{\"%s\",CornerStamp1_()}"+":"+WinName(0, 1) EndMacro Function/S CornerStamp1_() PathInfo home // creates String s_path return S_path+IgorInfo(1) End // Puts text on the lower right corner showing when the graph was made, and on the lower left showing where it came from Proc Add_Corner_Labels_To_Graph() : GraphStyle AddCornerLabelsToGraph() EndMacro Function AddCornerLabelsToGraph() GetWindow kwTopWin , psize Variable pBottom=V_bottom Variable pheight = V_bottom-V_top GetWindow kwTopWin , gsize Variable gBottom=V_bottom Variable bottom = -floor(100*(gBottom-pBottom)/pheight) Textbox/C/N=stamp0/F=0/A=RB/X=0.2/Y=(bottom)/E=2 "\\Z04\\{\"%s %s\",date(), time()}" Textbox/C/N=stamp1/F=0/A=LB/X=0.2/Y=(bottom)/E=2 "\\Z04\\{\"%s\",CornerStamp1_()}"+":"+WinName(0, 1) End // Put up multigraph layouts. Each time you call this, it adds another graph to the layout Window AppendMultiGraph2LayoutN() : Layout // this is needed to make it appear in the "Layout Macros" menu AppendGraph2LayoutN(NaN,"","") End // Append a graph to a multiple graph layout. This is for making multi-graph layouts Function/S AppendGraph2LayoutN(Nmax,orientation,gName) Variable Nmax // requested maximum number of graphs in the layout, one of Nlist String orientation // this must be "portrait" or "landscape" String gName // name of graph to append, if empty string, DoPrompt String Nlist = "1;2;3;4;6;8;9;12;16;20" // list of allowed values for Nmax if (!stringmatch("portrait",orientation) && !stringmatch("landscape",orientation)) orientation = "" endif if (Nmax<1 || Nmax>99 || numtype(Nmax)) Nmax = -1 // forces a prompt dialog elseif (Nmax>16) Nmax = 20 elseif (Nmax>12) Nmax = 16 elseif (Nmax>9) Nmax = 12 elseif (Nmax>6) Nmax = 9 elseif (Nmax>4) Nmax = 6 elseif (Nmax>3) Nmax = 4 elseif (Nmax>2) Nmax = 3 elseif (Nmax>1) Nmax = 2 endif Variable printIt=0 String lname if (strlen(gName)<1 || Nmax<0) if (Nmax<0) lname = StringFromList(0,WinList("Layout*",";","WIN:4")) // GetWindow $lname ,note // window note in S_Value // Nmax = NumberByKey("Nmax",S_Value,"=") Nmax = NumberByKey("Nmax",GetUserData(lname,"","AppendGraph2Layout"),"=") Nmax = numtype(Nmax) ? -1 : Nmax endif Nmax = Nmax<0 ? 12 : Nmax // 12 is default for absurd inputs Nmax = WhichListItem(num2istr(Nmax),Nlist)+1 Prompt gName, "Graph to add to layout",popup,WinList("*",";","WIN:1") Prompt Nmax,"number of graphs/layout",popup,Nlist DoPrompt "Pick a Graph",gName,Nmax if (V_flag) return "" endif Nmax = str2num(StringFromList(Nmax-1,Nlist)) printIt = 1 endif if (strlen(gName)<1) DoAlert 0, "no graph to add" return "" endif lname = StringFromList(0,WinList("Layout"+num2istr(Nmax)+"_*",";","WIN:4")) // get layout to append to if (strlen(LayoutInfo(lname, gName ))>1) return lname // graph is on layout, all done endif // check if this layout is full Variable i,N,NL = NumberByKey("NUMOBJECTS", LayoutInfo(lname,"Layout")) for (i=0,N=0;i=Nmax) // this layout is full, force creation of a new one lname = "" endif if (strlen(lname)<1) if (strlen(orientation)<1) // orientation was not passed, ask now orientation = SelectString(Nmax==8,"Landscape","Portrait") Prompt orientation, "page orientation",popup,"Portrait;Landscape" DoPrompt "Pick a Graph",orientation if (V_flag) return "" endif printIt = 1 endif lname = UniqueName("Layout"+num2istr(Nmax)+"_",8,0) // need to make a newlayout NewLayout/P=$orientation ModifyLayout mag=0.5, units=0, frame=0 DoWindow/C $lname // SetWindow kwTopWin ,note=ReplaceNumberByKey("Nmax","",Nmax,"=") SetWindow kwTopWin ,userdata(AppendGraph2Layout)=ReplaceNumberByKey("Nmax","",Nmax,"=") endif String page = StringByKey("PAGE", LayoutInfo(lname,"Layout")) // get page size to determing landscape or portrait Variable aspect = (str2num(StringFromList(3,page,","))-str2num(StringFromList(1,page,","))) // aspect = height/width aspect /= (str2num(StringFromList(2,page,","))-str2num(StringFromList(0,page,","))) orientation = SelectString(aspect>1,"landscape","portrait") // String rc = StringByKey(num2istr(Nmax),"1:1,1;2:2,1;3:3,1;4:2,2;6:3,2;9:3,3;12:4,3;16:4,4;20:4,5") String rc = StringByKey(num2istr(Nmax),"1:1,1;2:2,1;3:3,1;4:2,2;6:3,2;8:4,2;9:3,3;12:4,3;16:4,4;20:4,5") Variable rows=str2num(StringFromList(0,rc,",")) Variable columns=str2num(StringFromList(1,rc,",")) if (stringmatch("landscape",orientation)) // swap rows and columns for Landscape orientation Variable swap = rows rows = columns columns = swap endif AppendLayoutObject/F=0/W=$lname graph $gName String cmd sprintf cmd, "Tile /A=(%d,%d)/O=1",rows,columns Execute cmd RemoveLayoutObjects/W=$lname/Z stamp0,stamp1 // make sure that text boxes are written last, so they show Textbox/C/N=stamp0/W=$lname/F=0/A=RB/X=0.1/Y=0.1 "\\Z06\\{\"%s %s\",date(), time()}" Textbox/C/N=stamp1/W=$lname/F=0/A=LB/X=0.1/Y=0.1 "\\Z06\\{\"%s\", CornerStamp1_()}"+":"+WinName(0,1) if (printIt && topOfStack()) printf "\tAppendGraph2LayoutN(%d,\"%s\",\"%s\")\r",Nmax,orientation,gName endif return lname End //Function xxx(Nmax) // a test routine for AppendGraph2LayoutN() // Variable Nmax // Make/N=100/O y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12 // SetScale/I x 0,10,"", y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12 // y0 = 0.2*x -1 // y1 = sin(x/2) ; y2 = sin(x) ; y3 = sin(2*x) ; y4 = sin(3*x) ; y5 = sin(4*x) // y5 = cos(x/2) ; y6 = cos(x) ; y7 = cos(2*x) ; y8 = cos(3*x) ; y9 = cos(4*x) // y10 = exp(x/10)/3 ; y11 = exp(-x/4) ; y12 = 2*exp(-x/2)-1 // Variable i // String win // for (i=0;i<=12;i+=1) // win = "Graph"+num2istr(i) // if (strlen(WinList(win,"","WIN:1"))<1) // Display/K=1 $("y"+num2istr(i)) // DoWindow/C $win // ModifyGraph tick=2, minor=1, standoff=0, mirror=1 // ModifyGraph axOffset(left)=-4.7,axOffset(bottom)=-1.5 // endif // AppendGraph2LayoutN(Nmax,"",win) // endfor //End // ============================================================================ // // ============================== Start of String Ranges ============================== // // This section is for dealing with random or usually non contiguous sequence of integers // i.e. you took data in scans 1-30, but scans 17, and 25 were no good. So the valid range is "1-16,18-24,26-30" // or perhaps you want to combine scans "3,7,9" The following routines handle those situations in a simple fashion. Function NextInRange(range,last) // given a string like "2-5,7,9-12,50" get the next number in this compound range // the range is assumed to be monotonic, it returns NaN if no more values String range // list defining the range Variable last // last number obtained from this range, use -Inf to get start of range, it returns the next // find first item in the list that should use next String item Variable m,i,j Variable first // first value in an item do item = StringFromList(j,range,",") first = str2num(item) // do we need to check for NaN in first? if (numtype(first)) return NaN elseif (last=first, check to see if item is a '2-5' type range m=-1 // remove any leading white space from item do m += 1 while (char2num(item[m])<=32) item = item[m,strlen(item)-1] i = strsearch(item,"-",1) // location of first '-' after the first character if (i<0) // only a single number, not a dash type range, keep looking j += 1 continue endif // check to see if last was in the range of item, but not the last value if (last>=str2num(item) && last0) return NaN End //Function TestNextInRange(range) // String range // range = SelectString(strlen(range) ,"-16,-7--3,-1-2,5,50-54,99",range) // Variable i = -Inf // printf "for range = {%s}, ", range // do // i = NextInRange(range,i) // if (numtype(i)) // break // endif // printf "%d ", i // while (!numtype(i)) // print "" //End Function PointInRange(i,range) // return the ith number in range, first number is i==0 Variable i // index to number in range String range // a string range Variable N=ItemsInRange(range) i = round(i) if (numtype(i) || i<0 || i>=N) // check for valid index return NaN endif Variable j, m=-Inf for (j=0;j<=i;j+=1) // this is not the fastest, but it is simple m = NextInRange(range,m) endfor return m End Function ItemsInRange(range) // given a string like "2-5,7,9-12,50" get the total number of values in the range String range // list defining the range // the range is assumed to be monotonic, it returns NaN on error String item // each of the comma sepated items Variable len=0 // the result, number of values represented Variable m,i,j,N=ItemsInList(range,",") for (j=0;j=0) return Inf endif i = strlen(range)+1 do i -= 1 c = char2num(range[i-1]) while(c>=48 && c<=57 && i>0) // a digit, continue last=str2num(range[i,Inf]) if (c==45) if (i==1) return -last endif c = char2num(range[i-2]) // char preceeding minus sign if (c==45 || c==44) return -last endif endif return last End // Caution expandRange("1-100000",";") will produce a very long string! Use NextInRange() to avoid this problem Function/S expandRange(range,sep) // expand a string like "2-5,7,9-12,50" to "2,3,4,5,7,9,10,11,12,50" String range // series of numberseparated by commas and dashes, white is space igaored String sep // separates final list, usually ";" if (strsearch(range,"Inf",0,2)>=0) // cannot put an infinite number of characters into a string return "" endif if (strlen(sep)<1) // sep defaults to ';' sep = ";" endif Variable i1,i2,i String str,out="" Variable N=ItemsInList(range,",") if (N<1) return "" endif Variable j=0 do str = StringFromList(j, range, ",") Variable m=-1 // remove any leading white space do m += 1 while (char2num(str[m])<=32) str = str[m,strlen(str)-1] // now check str to see if it is a range like "20-23" i1 = str2num(str) i = strsearch(str,"-",strlen(num2str(i1))) // position of "-" after first number if (i>0) i2 = str2num(str[i+1,inf]) i = i1 do out += num2str(i)+sep i += 1 while (i<=i2) else out += num2str(i1)+sep endif j += 1 while (j '%s'\r",range, compressRange(range,";") // range = "1;2;3;4;5;9;10;11" // printf "'%s' ---> '%s'\r",range, compressRange(range,";") // range = "4" // printf "'%s' ---> '%s'\r",range, compressRange(range,";") // range = "4;7" // printf "'%s' ---> '%s'\r",range, compressRange(range,";") // range = "-10;-9;-8;-7;-6;-5;-3;-2;-1;0;1;2;7;9;22" // printf "'%s' ---> '%s'\r",range, compressRange(range,";") //End // =============================== End of String Ranges ============================== // // ============================================================================ // // ============================================================================ // // ========================== Start of some general utility stuff ========================== // // make a function getFiletype that goes to a file and determines it's filetype Function/T getListOfTypesInFile(fname,path) String fname // full path name to file with tagged geometry values String path // name of Igor path Variable refNum Open/M="file containing tagged values"/P=$path/R/Z=2 refNum as fname if (strlen(S_fileName)<1 || !refNum) return "" endif String line FReadLine refNum, line Close refNum if (!stringmatch(line[0],"$")) // if it does not start with a '$' then forget it. return "" endif Variable i i = strlen(line) i -= char2num(line[i-1])<32 ? 1 : 0 i -= char2num(line[i-2])<32 ? 1 : 0 line = line[0,i-1] // trim off any c/r or new lines i = strsearch(line,"//",0) // remove comment if (i>0) line = line[0,i-1] endif line = ReplaceString("\t",line," ") // change all tabs to spaces line += " " // ensure a space terminator if (strsearch(line,"$filetype ",0)!=0) // does not starts with $filetype, pass back the tag i = strsearch(line," ",0) return line[1,i-1] endif line = line[9,Inf] // strip off the $filetype tag // now get the value for (i=0;i=0 && char2num(line[i])<=32;i-=1) endfor line = line[0,i] line = ReplaceString(",",line,";") // change all commas, and spaces to semi-colons line = ReplaceString(" ",line,";") return line End Function keyInList(key,keyWordList,keySepStr,listSepStr) // returns true if key=value pair is in the keyWordList String key // string with key String keyWordList // list of keyword=value pairs String keySepStr // separates key and value, defaults to colon String listSepStr // separates key value pairs, defaults to semicolon keySepStr = SelectString(strlen(keySepStr),":",keySepStr) // default to colon listSepStr = SelectString(strlen(listSepStr),";",listSepStr) // default to semicolon String find=key+keySepStr // find this if (strsearch(keyWordList,find,0)==0) // check if it is at the start return 1 // found key=value is first pair endif if ( strsearch(keyWordList,listSepStr+find,0)>0) // check if key is after first key=value pair return 1 // found key=value is a later pair endif return 0 // no key=value found End // Merges two key=value lists, if priority=0, then list0 has priority, if priority=1 then list1 Function/S MergeKeywordLists(list0,list1,priority,keySepStr,listSepStr) String list0,list1 Variable priority // 0 or 1 String keySepStr // separates key and value, defaults to colon String listSepStr // separates key value pairs, defaults to semicolon keySepStr = SelectString(strlen(keySepStr),":",keySepStr) // default to colon listSepStr = SelectString(strlen(listSepStr),";",listSepStr) // default to semicolon String item, key,value Variable i,N=ItemsInList(list1) for (i=0;ia[i]) return 0 endif i += 1 while (i