#pragma rtGlobals=1 // Use modern global access method. //---------------------------------------------------------------------------------------------------------- // LaTeXinIGOR v2.1 //---------------------------------------------------------------------------------------------------------- // (Written by Jesús Martínez Blanco) // Special thanks to Victor Joco for his advice and computer support. // April 2007 // LaTeXinIGOR is an IGOR PRO procedure for those Igor 6 users // in Windows who want to embed a LaTeX expression in their // graphs, panels, layouts or notebooks. The expression is loaded as an // Igor picture from an Enhanced Meta File image (EMF) generated // by the program pstoedit, that converts the postscript output of // the program LaTeX into a vectorial graph, or alternatively, from an // Encapsulated PostScript (EPS) with a TIFF preview added by the program // epstool (new in version 2.0). // This procedure is freeware in the hope that it will be useful, // but without any warranty. I would be thankful for any suggestion, // comment or bug fixing that could improve this code. // email address: jm.blanco@uam.es // ************************************************************************************* // ***************** version 2.1 (May 21st, 2007) **************** // ************************************************************************************* // 1.-Bug fixed in the function ShowSelectedExpression that caused a wrong // behaviour in marking the expression with the green frame because some // lines in the window recreation macro where deleted instead of replaced by // a dummy DrawRect command. // 2.-Function ListBoxPicList was revisited to avoid a non-fatal error. I removed // the lines which called the functions StandardOrGeneral and EditLaTeXfile // and instead, ListBoxPicList does everything in itself. // ************************************************************************************* // ***************** New features in version 2.0 (May 4th, 2007) **************** // ************************************************************************************* // 1.-It is possible now to import pictures in EPS format. In Igor you will only // see the preview generated by the external free program EPSTOOL that // must be downloaded. // 2.-EMF pictures generated by PSTOEDIT can have now true type fonts // instead of converting them to polygons. The result is almost the same // but sometimes you get some improvement. For this option you must // download the latex equivalent ttf fonts and install them in windows. // 3.-The latex source code of every expression is saved in a text wave and you // can re-edit it by selecting the corresponding picture embedded by // LaTeXinIGOR in a window. In this way, it is possible to recompile and // modify an existing expression. // 4.-Latex.exe is executed now with the option -quiet, in such way that the // DOS console window appears for a shorter time when you compile an // expression. In case of spelling errors in your input, latex.exe will not // interrupt, but LaTeXinIGOR will tell you whether the compilation gave // any output or not. You can anyway see the .log file generated by latex. // 5.-The main working panel is now labelled with the title "LaTeX to PICTURE" // instead of "LaTeX to EMF". If you kill this panel, its position is remembered // so it will appear in the same place when you invoke it again from the menu // Macros->LaTeX to PICTURE // 6.-In the panel, besides the new popup menu where you can choose the picture // format, the title of the button that you have to press to compile an expression // is changing according to the action that is about to be done. Small red // triangles also will indicate you which controls of the panel you can modify // to affect the resulting picture. // 7.-The Igor datafolder used by the procedure to store waves and global variables // is also called now root:LaTeXtoPICTURE istead of root:LaTeXtoEMF. The // name of the pictures changed to latexpic_#, where # is an increasing number. // 8.-PSTOEDIT is executed with the option -pta and DVIPS is executed with the // options -E -G1. // Look in http://www.uam.es/fmc/especifica/igor/LaTeXinIGOR.htm // for a detailed explanation of the usage of LaTeXinIGOR //------------------------------------------------------------------------------------------------------------------------------------ menu "Macros" "-" "LaTeX to PICTURE" end //------------------------------------------------------------------------------------------------------------------------------------ Macro LaTeXtoPICTURE() // Initializes global variables and strings // and shows the working panel. Silent 1;pauseupdate DoWindow PanelLaTeXtoPICT if (V_Flag==0) if (exists("root:LaTeXtoPICTURE:formula")!=2) String savedDF= GetDataFolder(1) newdatafolder/O/S root:LaTeXtoPICTURE string/G formula="Insert here a LaTeX expression like $\\rho$." variable/G standorgen=0 variable/G anglerot=0 variable/G scalefac=100 string/G selectedcolor="(0,0,0)" variable/G selectedformat=1 //This item correspond with "EMF polygons" variable/G lastselected=-1 make/n=0/T CodeStorage string/G panelpos="(29,80,414,220)" SetDataFolder savedDF endif PanelLaTeXtoPICT() StandardOrGeneral("reinvoke",root:LaTeXtoPICTURE:standorgen) Execute/Q/Z "popupmenu selectcolorPIC popColor="+root:LaTeXtoPICTURE:selectedcolor Execute/Q/Z "popupmenu picformat mode="+num2str(root:LaTeXtoPICTURE:selectedformat) Dowindow/T LaTeXeditor,"LaTeX code" // It is important to remove any picture name from the title, because it could be recompiled otherwise. else Dowindow/F PanelLaTeXtoPICT endif end //------------------------------------------------------------------------------------------------------------------------------------ Window PanelLaTeXtoPICT() : Panel PauseUpdate; Silent 1 // building window... Execute/Q/Z "NewPanel /K=1 /W="+root:LaTeXtoPICTURE:panelpos+" as \"LaTeX to PICTURE\"" SetDrawLayer ProgBack SetDrawEnv fillfgc= (65280,0,0) DrawPoly 233,58,1,1,{0,0,5,5,0,10,0,0} SetDrawEnv fillfgc= (65280,0,0) DrawPoly 233,77,1,1,{0,0,5,5,0,10,0,0} SetDrawEnv fillfgc= (65280,0,0) DrawPoly 233,96,1,1,{0,0,5,5,0,10,0,0} SetDrawEnv fillfgc= (65280,0,0) DrawPoly 114,93,1,1,{0,0,5,5,0,10,0,0} SetDrawLayer UserBack SetVariable texformula,pos={10,25},size={365,20},title=" ",font="Courier New" SetVariable texformula,fSize=14,fStyle=0,value= root:LaTeXtoPICTURE:formula Button generate,pos={114,53},size={115,35},proc=GeneratePICTURE,title="\\f01\\K(65280,0,0)COMPILE & paste\rsimple expression" Button generate,fColor=(60928,60928,60928) TitleBox titleexpression,pos={10,6},size={192,17},title="LaTeX simple expression:" TitleBox titleexpression,font="Courier New",fSize=14,frame=0 PopupMenu selectcolorPIC,pos={240,54},size={79,21},proc=PopMenuValues,title="Color" PopupMenu selectcolorPIC,mode=1,popColor= (0,0,0),value= #"\"*COLORPOP*\"" SetVariable anglePIC,pos={240,76},size={129,16},title="Rot. Angle (deg)" SetVariable anglePIC,limits={0,360,5},value= root:LaTeXtoPICTURE:anglerot SetVariable scalePIC,pos={240,94},size={129,16},title="Scale Factor (%)" SetVariable scalePIC,limits={5,inf,10},value= root:LaTeXtoPICTURE:scalefac CheckBox stndgen,pos={10,51},size={95,14},proc=StandardOrGeneral,title="Compile General" CheckBox stndgen,variable= root:LaTeXtoPICTURE:standorgen Button editlatex,pos={10,72},size={96,37},disable=2,proc=EditLaTeXFile,title="\\Z14EDIT new\rLaTeX code" GroupBox Frame,pos={10,25},size={364,20},frame=0 Button colortoclipboard,pos={317,54},size={52,19},proc=ColorToClipBoard,title="\\JL\\W649Clip" PopupMenu picformat,pos={113,88},size={117,21},proc=PopMenuValues,title=" " PopupMenu picformat,mode=1,bodyWidth= 109,popvalue="EMF polygons",value= #"\"EMF polygons;EMF fonts;EPS\"" Button PopUpPanelListPicts,pos={331,117},size={20,17},proc=PopUpListPicts,title="\\W623" TitleBox title0,pos={26,117},size={302,16},title="\\Z14Select here a picture from target to recompile code:" TitleBox title0,frame=0 GroupBox groupInput,pos={110,49},size={264,65} SetWindow kwTopWin,hook=RememberPosMainPanel EndMacro //------------------------------------------------------------------------------------------------------------------------------------ Function RememberPosMainPanel(infoStr) // This is a hook function to store the position of the working panel when you kill it. // In case you update the window macro called PanelLaTeXtoPICT via Dowindow/R, // you must replace the line with the command NewPanel with the line: // Execute/Q/Z "NewPanel /K=1 /W="+root:LaTeXtoPICTURE:panelpos+" as \"LaTeX to PICTURE\"" String infoStr String event= StringByKey("EVENT",infoStr) SVAR panelpos=root:LaTeXtoPICTURE:panelpos if (cmpstr(event,"kill")==0) panelpos=stringbykey("/W",WinRecreation("PanelLaTeXtoPICT",0 ),"="," ") endif End //------------------------------------------------------------------------------------------------------------------------------------ Function GeneratePICTURE(ctrlName) : ButtonControl // From a LaTeX code, generates the EMF or EPS file and // paste it as an Igor picture in the target window. String ctrlName variable filenum SVAR formula=root:LaTeXtoPICTURE:formula NVAR scalefac=root:LaTeXtoPICTURE:scalefac NVAR anglerot=root:LaTeXtoPICTURE:anglerot NVAR standorgen=root:LaTeXtoPICTURE:standorgen WAVE/T CodeStorage=root:LaTeXtoPICTURE:CodeStorage //----Obtain the chosen picture format: 1.EMF polygons, 2.EMF fonts, 3.EPS ControlInfo picformat variable fmt=V_value //----Check whether the executables latex.exe, dvips.exe and pstoedit.exe are available string notfound=SetPathsforExec(fmt) if (strlen(notfound)!=0) DoAlert 0,"The following program/s can not be found:\r "+notfound+"\rThe execution will be aborted." abort endif //----Create latex source file "formula.tex" in LaTeXInIGOR path, either from the LaTeX editor (notebook) or from the input box in the panel PathInfo Igor NewPath/C/O/Q LaTeXInIGOR , S_Path+"LaTeXInIGOR:" if (standorgen) SaveNotebook/O/S=3/P=LaTeXInIGOR LaTeXeditor as "formula.tex" else controlinfo selectcolorPIC open/P=LaTeXInIGOR filenum as "formula.tex" fprintf filenum, "\\documentclass[12pt]{article}\r" fprintf filenum, "\\usepackage{amsmath}\r" fprintf filenum, "\\usepackage{amssymb}\r" fprintf filenum, "\\usepackage{color}\r" fprintf filenum, "\\begin{document}\r" fprintf filenum, "\\pagestyle{empty}\r" fprintf filenum, "\\color[rgb]{"+RGBforLaTeX(s_value)+"}\r" fprintf filenum, formula+"\r" fprintf filenum, "\end{document}\r" close filenum endif //----Create auxiliary LaTeX source "ROTformula.tex" in LaTeXInIGOR path, needed to rotate EPS if (fmt==3 && anglerot!=0) open/P=LaTeXInIGOR filenum as "ROTformula.tex" fprintf filenum, "\\documentclass{article}\r" fprintf filenum, "\\usepackage{epsfig}\r" fprintf filenum, "\\begin{document}\r" fprintf filenum, "\\pagestyle{empty}\r" fprintf filenum, "\\epsfig{file=formula.ps,angle="+num2str(anglerot)+"}\r" fprintf filenum, "\end{document}\r" close filenum endif //----Create the BATCH file to be executed to generate the EMF or EPS file in LaTeXInIGOR path PathInfo LaTeXInIGOR string pathLaTeXInIGOR=ParseFilePath(5, S_Path,"*",0,0) PathInfo latexdvips string latexPATH=ParseFilePath(5, S_Path,"*",0,0) PathInfo pstoedit string pstoeditPATH=ParseFilePath(5, S_Path,"*",0,0) PathInfo epstool string epstoolPATH=ParseFilePath(5, S_Path,"*",0,0) open/P=LaTeXInIGOR filenum as "formula.bat" fprintf filenum,pathLaTeXInIGOR[0,1]+"\n" fprintf filenum,"cd "+pathLaTeXInIGOR+"\n" fprintf filenum,"set path="+latexPATH+"\n" fprintf filenum,"latex -quiet formula.tex"+"\n" fprintf filenum,"dvips -E -G1 -q formula.dvi"+"\n" switch(fmt) case 1: fprintf filenum,"set path="+pstoeditPATH+"\n" fprintf filenum, "pstoedit -f emf -pta -dt -flat 0.0001 -rotate "+num2str(anglerot)+" formula.ps formula.emf"+"\n" break case 2: fprintf filenum,"set path="+pstoeditPATH+"\n" fprintf filenum, "pstoedit -f emf -pta -rotate "+num2str(anglerot)+" formula.ps formula.emf"+"\n" break case 3: if (anglerot!=0) // If expression is rotated, latex.exe is invoked again to generate a rotated postscript fprintf filenum,"latex -quiet ROTformula.tex"+"\n" fprintf filenum,"dvips -E -G1 -q ROTformula.dvi"+"\n" fprintf filenum,"set path="+epstoolPATH+"\n" fprintf filenum, "epstool --quiet --bbox --dpi 200 -t6p ROTformula.ps formula.eps"+"\n" else fprintf filenum,"set path="+epstoolPATH+"\n" fprintf filenum, "epstool --quiet --bbox --dpi 200 -t6p formula.ps formula.eps"+"\n" endif break endswitch close filenum //----Execute the BATCH file ExecuteScriptText "\""+pathLaTeXInIGOR+"formula.bat\"" //----Check latex output. In case there was a problem (probable wrong spelling) the picture was not generated. Abort Dowindow/K latexLOG opennotebook/A/K=1/V=0/N=latexLOG/P=LaTeXInIGOR/R "formula.log" DoWindow /T latexLOG, "formula.log" notebook latexLOG,selection={startOfPrevParagraph,endOfPrevParagraph} GetSelection notebook,latexLOG,2 if (cmpstr(S_Selection,"No pages of output.\r")==0) DoAlert 1, "No output file from latex.exe.\rMost probably there is a spelling problem in your expression.\rDo you want to see the LOG file?" if (V_flag==1) Dowindow/F latexLOG else Dowindow/K latexLOG endif abort endif Dowindow/K latexLOG //----Load the EMF or EPS file as an Igor picture string listpics=PICTList("latexpic_*",";","") variable numpics=ItemsInList(listpics) variable lastpic,numformerexp=NaN if (numpics != 0) controlinfo/W=PanelLaTeXtoPICT generate numformerexp=NumberByKey("latexpic",s_recreation, "_"," ")// The button title will tell us if the user wants to recompile an existing expression or a new one if (numformerexp!=numformerexp) // LaTeXeditor contains the code of a new expression lastpic=str2num(ReplaceString("latexpic_", stringfromlist(numpics-1,listpics),"")) else // LaTeXeditor contains the code of a former expression lastpic=numformerexp-1 endif else lastpic=-1 endif string expression="latexpic_"+num2str(lastpic+1) if (fmt!=3) LoadPICT/Q/O/P=LaTeXInIGOR "formula.emf", $expression else LoadPICT/Q/O/P=LaTeXInIGOR "formula.eps", $expression endif string targetwindow=SuitableWindow() // A graph, layout, panel or formatted notebook. //----Store the latex code in the text wave CodeStorage string expressioncode open/R/Z/P=LaTeXInIGOR filenum as "formula.tex" FReadLine/T="" filenum, expressioncode expressioncode=ReplaceString("\n", expressioncode, "") if (numformerexp!=numformerexp) // LaTeX file contains the code of a new expression InsertPoints numpnts(CodeStorage), 1, CodeStorage CodeStorage[numpnts(CodeStorage)-1]=expressioncode else // LaTeX file contains the code of a former expression CodeStorage[numformerexp]=expressioncode endif close filenum //----Define coordinates to paste the picture. In Layouts, the margins are taken into account. variable posX,posY string papercoords if (WinType(targetwindow)==3) papercoords=StringByKey("PAGE",layoutinfo(targetwindow,"Layout")) posX=str2num(stringfromlist(0,papercoords,",")) posY=str2num(stringfromlist(1,papercoords,",")) else posX=0 posY=0 endif if (fmt!=3) //----In case of EMF format, paste in a dummy window and save back as emf again. The image is reloaded to use in Igor //----This is a non-elegant way to avoid cropping of some images. The cause of this cropping is unknown to me. variable wpic=str2num(stringbykey("PHYSWIDTH",PictInfo(expression),":")) variable hpic=str2num(stringbykey("PHYSHEIGHT",PictInfo(expression),":")) variable bor=0.5 //margin points to avoid cropping. display/N=dumpic/HIDE=1 ModifyGraph/W=dumpic width=wpic+2*bor,height=hpic+2*bor SetDrawLayer/W=dumpic UserFront SetDrawEnv xcoord=abs,ycoord=abs DrawPICT/W=dumpic bor,bor,1,1,$expression SavePICT/O/WIN=dumpic/P=LaTeXInIGOR/E=-2 as "formula.emf" dowindow/K dumpic LoadPICT/Q/O/P=LaTeXInIGOR "formula.emf", $expression endif //----Paste the picture in the target suitable window if any, or don't do anything if you are recompiling former expression.. if (numformerexp!=numformerexp) if (strlen(targetwindow)==0) DoAlert 0,"The LaTeX expression was loaded (see menu Misc->Pictures)\rbut It could not be pasted in any of the existing windows." else dowindow/F $targetwindow if (WinType(targetwindow)==5) notebook $targetwindow,scaling={scalefac,scalefac},picture={$expression,-2,1} else SetDrawLayer/W=$targetwindow UserFront DrawPICT/W=$targetwindow posX,posY,scalefac/100,scalefac/100,$expression endif endif endif End //------------------------------------------------------------------------------------------------------------------------------------ Function/S SuitableWindow() // Returns the name of the first graph, layout, panel or formatted notebook // contained in WinList("*", ";", "WIN:85") excluding the working panel. // The plain notebooks are also excluded since it is not possible to paste // a picture on them. string prelist=WinList("*", ";", "WIN:85") //list of graphs, layouts, panels and notebooks (formatted or plain). string availablewin="",wname variable w variable i //i=0 is the working panel. for (i=1;i1.5 seems to be the extra frame height per cell ListPictsOnTargetSELECTOR=0 ListPictsOnTargetSELECTOR[selected]=1 string clickout=StringByKey("EVENT",infoStr) GetWindow PanelListPicts,title // I use the title of the popupmenu panel to know the suitable window string swindow=S_Value if (cmpstr(clickout,"deactivate")==0 || cmpstr(clickout,"kill")==0) DoWindow/K PanelListPicts SetDrawLayer/W=$swindow/K ProgBack SetDrawLayer/W=$swindow UserFront lastselected=-1 DoUpdate //needed for layouts else if (selected!=lastselected) //The mouse has just changed to another item ShowSelectedExpression(swindow,ListPictsOnTarget[selected]) lastselected=selected DoUpdate //needed for layouts endif endif End //------------------------------------------------------------------------------------------------------------------------------------ Function ListBoxPicList(ctrlName,row,col,event) : ListboxControl // This function displays the notebook LaTeXeditor to edit the corresponding LaTeX code // every time an item is selected in the list of pictures (panel with popupmenu style). String ctrlName Variable row Variable col Variable event if (event==2) WAVE/T ListPictsOnTarget=root:LaTeXtoPICTURE:ListPictsOnTarget String PicName=ListPictsOnTarget[row] WAVE/T CodeStorage=root:LaTeXtoPICTURE:CodeStorage string ind=StringByKey("latexpic",PicName, "_") Button generate win=PanelLaTeXtoPICT,title="\\f01\\K(65280,0,0)RECOMPILE\r latexpic_"+ind SetDrawLayer/W=PanelLaTeXtoPICT/K ProgBack SetDrawEnv/W=PanelLaTeXtoPICT fillfgc= (65280,0,0) DrawPoly/W=PanelLaTeXtoPICT 233,77,1,1,{0,0,5,5,0,10,0,0} SetDrawEnv/W=PanelLaTeXtoPICT fillfgc= (65280,0,0) DrawPoly/W=PanelLaTeXtoPICT 114,93,1,1,{0,0,5,5,0,10,0,0} SetDrawLayer/W=PanelLaTeXtoPICT UserBack CheckBox stndgen win=PanelLaTeXtoPICT,value=1 Button editlatex win=PanelLaTeXtoPICT,disable=0 SetVariable texformula win=PanelLaTeXtoPICT,disable=2 SetVariable texformula win=PanelLaTeXtoPICT,frame=0 SetVariable texformula win=PanelLaTeXtoPICT,fstyle=2 DoWindow LaTeXeditor if (V_Flag==0) NewNotebook/K=3/F=0/N=LaTeXeditor as "LaTeX code latexpic_"+ind notebook LaTeXeditor selection={startOfFile,endoffile}, text= CodeStorage[str2num(ind)] else Dowindow/F LaTeXeditor Dowindow/T LaTeXeditor,"LaTeX code latexpic_"+ind notebook LaTeXeditor selection={startOfFile,endOfFile}, text= CodeStorage[str2num(ind)] endif endif End //------------------------------------------------------------------------------------------------------------------------------------ Function CreateMarkerFrame() // This function generates (if it does not exist) a png image in the LaTeXInIGOR path and // loads it as a picture called MarkerFrame. This picture is used to mark a mathematical expression // embedded in a panel or in a graph. variable MFexists=strlen(PictLIST("MarkerFrame","","")) if (MFexists==0) Display/N=MarkerFrameWin/HIDE=1 ModifyGraph width=100,height=100 SetDrawLayer UserFront SetDrawEnv xcoord= rel,ycoord= rel,fillfgc= (32768,65280,0) DrawRect 0,0,.99,.99 SavePICT/O/WIN=MarkerFrameWin/E=-5/B=72/P=LaTeXInIGOR as "MarkerFrame.png" dowindow/K MarkerFrameWin LoadPICT/Q/O/P=LaTeXInIGOR "MarkerFrame.png", MarkerFrame endif end //------------------------------------------------------------------------------------------------------------------------------------ Function ShowSelectedExpression(swindow,latexpic) // This function marks with a frame the mathematical expression/s embedded in swindow // whose name is in the mouse coordinates within the panel PanelListPicts. string swindow,latexpic variable i,Wpict,Hpict,Wmarker,Hmarker,scaleX,scaleY,typePic string piccoor,picName,info string line,comm,newSX,newSY //----Take the size of the picture MarkerFrame info=PICTInfo("MarkerFrame") Wmarker=NumberByKey("WIDTH",info) Hmarker=NumberByKey("HEIGHT",info) //----Delete the ProgBack layer and take the window recreation macro SetDrawLayer/W=$swindow/K ProgBack string wrecreation = WinRecreation(swindow, 0) //----Look for a DrawPict command in the recreation macro of swindow // and draw the picture MarkerFrame in the ProgBack layer with the same // drawing enviroment. i=0 do line=StringFromList(i, wrecreation,"\r") comm=StringFromList(0,line," ") comm=ReplaceString("\t",comm,"") //Extract those command lines with SetDrawEnv or DrawPict. Delete the rest. strswitch (comm) case "SetDrawEnv": line=AddListItem("/W="+swindow,line," ",1)//The command line will apply on swindow wrecreation=ReplaceItemInList(i,wrecreation,line,"\r") break case "DrawPict": piccoor=stringbykey("DrawPICT",line," ","\t") picName=StringFromList(4,piccoor,",") if (cmpstr(picName,latexpic)==0) scaleX=Str2Num(StringFromList(2,piccoor,",")) scaleY=Str2Num(StringFromList(3,piccoor,",")) info=PICTInfo(picName) Wpict=NumberByKey("WIDTH",info) Hpict=NumberByKey("HEIGHT",info) typePic=stringmatch(stringbykey("TYPE",info), "Encapsulated PostScript") newSX=num2str((1+typePic*0.1)*scaleX*Wpict/Wmarker)//EPS previews are opaque, so make the size of MarkerFrame 10% bigger in order to see it. newSY=num2str((1+typePic*0.1)*scaleY*Hpict/Hmarker) line=ReplaceItemInList(2,line,newSX,",") line=ReplaceItemInList(3,line,newSY,",") line=ReplaceItemInList(4,line,"MarkerFrame",",") line=AddListItem("/W="+swindow,line," ",1)//The command line will apply on swindow wrecreation=ReplaceItemInList(i,wrecreation,line,"\r") else line=AddListItem("/W="+swindow,line," ",1)//The command line will apply on swindow wrecreation=ReplaceItemInList(i,wrecreation,line,"\r") endif break default: if (cmpstr(comm[0,3],"Draw")!=0) wrecreation=RemoveListItem(i, wrecreation,"\r") i-=1 else // instead of removing the line, I will replace it with a command to draw a dummy rectangle to preserve the enviroment (17May2007) wrecreation=ReplaceItemInList(i,wrecreation,"\tDrawRect /W="+swindow+" 0,0,0,0","\r") endif endswitch i+=1 while (i