#pragma rtGlobals=3 // Use modern global access method and strict wave access. #pragma IndependentModule = ALP #pragma version 1.0 // ALP // Alternate Line Profile // The Igor 7 image line profile has lost functionality compared to Igor 6. // It is also now more difficult to manually process the results of the function. // ALP attempts to fulfill typical needs, and make it easy to use the results. // Menu "ALP" // ALPsetup() // ALPmakePanel() // ALPWindowHook(s) // ALPupdate() // ALPdraw() // ALPresetParms() // ALPgetGraphInfo() // get info about 2D waves in top graph // ALPhCheckProc(cba) : CheckBoxControl // ALPvCheckProc(cba) : CheckBoxControl // ALPOneGraphCheckProc(cba) : CheckBoxControl // ALPMultiGraphCheckProc(cba) : CheckBoxControl // ALPSetPixelsProc(sva) : SetVariableControl // ALPSetValsProc(sva) : SetVariableControl // ALPpxToVal() // ALPvalToPx() // ALPsaveGraphButtonProc(ba) : ButtonControl // does the save and graph work // ALPstackTracesButtonProc(ba) : ButtonControl // ALPstackTraces() // ALPnormTracesButtonProc(ba) : ButtonControl // ALPnormTraces() // ALPtagsOnOffButtonProc(ba) : ButtonControl // ALPtoggleTags(onoff) // ALPhelpButtonProc(ba) : ButtonControl // ALPshowHelp() // Seems a bit silly, but maybe it is a good idea: // // Copyright (c) 2016, Richard Knochenmuss // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted for private, academic and noncommercial use, // provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //--------------------------------// //Menu "ALP" Menu "Image" "Alt Line Profile...",/Q, ALPsetup() End //--------------------------------// Function ALPsetup() string SaveDataFolder SaveDataFolder=GetDataFolder(1) if (!Datafolderexists("root:Packages")) NewDataFolder root:Packages endif if (!Datafolderexists("root:Packages:ALP")) NewDataFolder/S root:Packages:ALP variable/G ALPtype=0 // 0=H, 1=V, 2=diag variable/G ALPctrPx, ALPctrVal variable/G ALPwidthPx, ALPwidthVal variable/G ALPgraphing=1 // 0=separate, 1=single string/G ALPmessage string/G ALPsourceWindow string/G ALPsourceWave make/N=(2) ALPprofile, ALPx, ALPy endif ALPgetGraphInfo() // get info about 2D waves in top graph DoWindow ALP if (!v_flag) ALPmakePanel() endif ALPresetParms() ALPupdate() SetDataFolder SaveDataFolder end //--------------------------------// Function ALPdraw() // redraw lines showing region string SaveDataFolder, wrec variable nxpts, nypts, ii, jj, kk, fract, X0, Y0, dx, dy, UL, LL, topax SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal,ALPwidthPx, ALPwidthVal, ALPgraphing svar ALPsourceWindow, ALPsourceWave, ALPmessage wave wv2d=ImageNameToWaveRef(ALPsourceWindow, ALPsourceWave) nxpts=dimsize(wv2d,0) nypts=dimsize(wv2d,1) x0=dimoffset(wv2d,0) y0=dimoffset(wv2d,1) dx=dimdelta(wv2d,0) dy=dimdelta(wv2d,1) ALPmessage="Graph: "+ALPsourceWindow+", 2D wave: "+ALPsourceWave // is image plotted vs top or bottom x axis? wrec=winrecreation(ALPsourceWindow,0) ii=strsearch(wrec,"AppendImage/T",0) if (ii>=0) topax=1 else topax=0 endif DrawAction/W=$ALPsourceWindow getgroup=ALP, delete // delete existing lines SetDrawEnv/W=$ALPsourceWindow gstart, gname= ALP // start drawing new LL=ALPctrVal - ALPwidthVal/2 UL=ALPctrVal + ALPwidthVal/2 if (ALPtype==0) // H LL=max(y0-0.5*dy,LL) UL=min(y0+(nypts-0.5)*dy, UL) // lower limit SetDrawEnv/W=$ALPsourceWindow ycoord= left // black on white dash SetDrawEnv/W=$ALPsourceWindow linethick=1 SetDrawEnv/W=$ALPsourceWindow linefgc=(65535,65535,65535) DrawLine/W=$ALPsourceWindow 0,LL,1, LL SetDrawEnv/W=$ALPsourceWindow ycoord= left SetDrawEnv/W=$ALPsourceWindow dash=7 DrawLine/W=$ALPsourceWindow 0,LL,1, LL // upper limit SetDrawEnv/W=$ALPsourceWindow ycoord= left SetDrawEnv/W=$ALPsourceWindow linethick=1 SetDrawEnv/W=$ALPsourceWindow linefgc=(65535,65535,65535) DrawLine/W=$ALPsourceWindow 0,UL,1, UL SetDrawEnv/W=$ALPsourceWindow ycoord= left SetDrawEnv/W=$ALPsourceWindow dash=7 DrawLine/W=$ALPsourceWindow 0,UL,1, UL // center line SetDrawEnv/W=$ALPsourceWindow ycoord= left SetDrawEnv/W=$ALPsourceWindow linethick=1 SetDrawEnv/W=$ALPsourceWindow linefgc=(65535,65535,65535) DrawLine/W=$ALPsourceWindow 0,ALPctrVal,1, ALPctrVal SetDrawEnv/W=$ALPsourceWindow ycoord= left SetDrawEnv/W=$ALPsourceWindow dash=1 DrawLine/W=$ALPsourceWindow 0,ALPctrVal,1, ALPctrVal elseif(ALPtype==1) // V LL=max(x0-0.5*dx,LL) UL=min(x0+(nxpts-0.5)*dx, UL) if (topax) SetDrawEnv/W=$ALPsourceWindow xcoord= top else SetDrawEnv/W=$ALPsourceWindow xcoord= bottom endif SetDrawEnv/W=$ALPsourceWindow linethick=1 SetDrawEnv/W=$ALPsourceWindow linefgc=(65535,65535,65535) DrawLine/W=$ALPsourceWindow LL, 0, LL, 1 if (topax) SetDrawEnv/W=$ALPsourceWindow xcoord= top else SetDrawEnv/W=$ALPsourceWindow xcoord= bottom endif SetDrawEnv/W=$ALPsourceWindow dash=7 DrawLine/W=$ALPsourceWindow LL, 0, LL, 1 if (topax) SetDrawEnv/W=$ALPsourceWindow xcoord= top else SetDrawEnv/W=$ALPsourceWindow xcoord= bottom endif SetDrawEnv/W=$ALPsourceWindow linethick=1 SetDrawEnv/W=$ALPsourceWindow linefgc=(65535,65535,65535) DrawLine/W=$ALPsourceWindow UL, 0, UL, 1 if (topax) SetDrawEnv/W=$ALPsourceWindow xcoord= top else SetDrawEnv/W=$ALPsourceWindow xcoord= bottom endif SetDrawEnv/W=$ALPsourceWindow dash=7 DrawLine/W=$ALPsourceWindow UL, 0, UL, 1 if (topax) SetDrawEnv/W=$ALPsourceWindow xcoord= top else SetDrawEnv/W=$ALPsourceWindow xcoord= bottom endif SetDrawEnv/W=$ALPsourceWindow linethick=1 SetDrawEnv/W=$ALPsourceWindow linefgc=(65535,65535,65535) DrawLine/W=$ALPsourceWindow ALPctrVal, 0, ALPctrVal, 1 if (topax) SetDrawEnv/W=$ALPsourceWindow xcoord= top else SetDrawEnv/W=$ALPsourceWindow xcoord= bottom endif SetDrawEnv/W=$ALPsourceWindow dash=1 DrawLine/W=$ALPsourceWindow ALPctrVal, 0, ALPctrVal, 1 endif SetDrawEnv/W=$ALPsourceWindow gstop SetDataFolder SaveDataFolder end //--------------------------------// Function ALPupdate() string SaveDataFolder variable nxpts, nypts, ii, jj, kk, fract, X0, Y0, dx, dy variable UL, LL, ULint, LLint SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal,ALPwidthPx, ALPwidthVal, ALPgraphing svar ALPsourceWindow, ALPsourceWave, ALPmessage wave ALPprofile, ALPx, ALPy if (strlen(ALPsourceWindow)>0) // was image found in top graph? ALPdraw() // redraw lines showing region RemoveFromGraph/Z/W=ALP#G0 ALPprofile wave wv2d=ImageNameToWaveRef(ALPsourceWindow, ALPsourceWave) nxpts=dimsize(wv2d,0) nypts=dimsize(wv2d,1) x0=dimoffset(wv2d,0) y0=dimoffset(wv2d,1) dx=dimdelta(wv2d,0) dy=dimdelta(wv2d,1) // the nominal FP limits UL=ALPctrPx+ALPwidthPx/2 LL=ALPctrPx-ALPwidthPx/2 // array index limits, pixel boundaries are half-integer ULint= (UL-floor(UL))>0.5 ? floor(UL)+1 : floor(UL) LLint= (LL-floor(LL))>=0.5 ? floor(LL)+1 : floor(LL) if (ALPtype==0) // HORIZONTAL ---------------------- make/O/N=(nxpts) ALPprofile, ALPx, ALPy ALPx=x0 + p*dx ALPy=ALPctrVal // boundary checking UL=min(nypts-0.5, UL) ULint=min(nypts-1, ULint) LL=max(-0.5, LL) LLint=max(0, LLint) //print/d "start",LL, UL, LLint, ULint ALPprofile=0 if (LLint==ULint) // within 1 pixel if (ALPwidthPx==0) // special case width=0 => get full pixel fract=1 else fract=UL-LL endif //print "1 px fract", fract ALPprofile = WV2D[p][LLint]*fract else // spans more than one pixel // add all full width contributions if (ULint-LLint > 1) for (kk=(LLint+1); kk<=(ULint-1); kk+=1) //print "kk",kk ALPprofile=ALPprofile + WV2D[p][kk] endfor endif // lower partial pixel fract=LL-(LLint-0.5) fract=1-fract //print "lower fract", fract ALPprofile=ALPprofile + WV2D[p][LLint]*fract // upper partial pixel fract=UL-(ULint-0.5) //print "upper fract", fract ALPprofile=ALPprofile + WV2D[p][ULint]*fract endif appendtograph/w=ALP#G0 ALPprofile vs ALPx modifygraph/w=ALP#G0 mirror=2 label/w=ALP#G0 bottom "X Value" elseif(ALPtype==1) // VERTICAL ---------------------- make/O/N=(nypts) ALPprofile, ALPx, ALPy ALPx=ALPctrVal ALPy=y0 + p*dy // boundary checking UL=min(nxpts-0.5, UL) ULint=min(nxpts-1, ULint) LL=max(-0.5, LL) LLint=max(0, LLint) //print/d "start",LL, UL, LLint, ULint ALPprofile=0 if (LLint==ULint) // within 1 pixel if (ALPwidthPx==0) // special case width=0 => get full pixel fract=1 else fract=UL-LL endif //print "1 px fract", fract ALPprofile = WV2D[LLint][p]*fract else // spans more than one pixel // add all full width contributions if (ULint-LLint > 1) for (kk=(LLint+1); kk<=(ULint-1); kk+=1) //print "kk",kk ALPprofile=ALPprofile + WV2D[kk][p] endfor endif // lower partial pixel fract=LL-(LLint-0.5) fract=1-fract //print "lower fract", fract ALPprofile=ALPprofile + WV2D[LLint][p]*fract // upper partial pixel fract=UL-(ULint-0.5) //print "upper fract", fract ALPprofile=ALPprofile + WV2D[ULint][p]*fract endif appendtograph/w=ALP#G0 ALPprofile vs ALPy modifygraph/w=ALP#G0 mirror=2 label/w=ALP#G0 bottom "Y Value" endif // V or H endif SetDataFolder SaveDataFolder end //--------------------------------// Function ALPresetParms() string SaveDataFolder variable nxpts, nypts, X0, Y0, dx, dy SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal,ALPwidthPx, ALPwidthVal, ALPgraphing svar ALPsourceWindow, ALPsourceWave, ALPmessage wave ALPprofile, ALPx, ALPy wave wv2d=ImageNameToWaveRef(ALPsourceWindow, ALPsourceWave) nxpts=dimsize(wv2d,0) nypts=dimsize(wv2d,1) x0=dimoffset(wv2d,0) y0=dimoffset(wv2d,1) dx=dimdelta(wv2d,0) dy=dimdelta(wv2d,1) if (ALPtype==0) // H ALPctrPx=floor(nypts/2) ALPctrVal=y0 + dy*ALPctrPx ALPwidthPx=1 ALPwidthVal=dy elseif(ALPtype==1) // V ALPctrPx=floor(nxpts/2) ALPctrVal=x0 + dx*ALPctrPx ALPwidthPx=1 ALPwidthVal=dx endif SetDataFolder SaveDataFolder end //--------------------------------// Function ALPgetGraphInfo() // get info about 2D waves in top graph string SaveDataFolder,graphlist, topgraph, imagelist variable nxpts, nypts, X0, Y0, dx, dy SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal,ALPwidthPx, ALPwidthVal, ALPgraphing svar ALPsourceWindow, ALPsourceWave, ALPmessage wave ALPprofile, ALPx, ALPy graphlist=winlist("*",";","WIN:1") topgraph=stringfromlist(0, graphlist) //print "top=", topgraph imagelist=ImageNameList(topgraph, ";") //print "2D", imagelist if (strlen(imagelist)>0) // yes, there is an image in top graph ALPsourceWindow=topgraph ALPsourceWave=stringfromlist(0, imagelist) ALPmessage="Image: "+ALPsourceWave ALPresetParms() return 0 endif // If user is returning to ALP window, but last topwin had no image, // presumably wants to return to last window which did have an image. // This typically happens when a Save&Graph is performed. // check if last image window exists, go there DoWindow $ALPsourceWindow if (v_flag) // yes, dont reset return 0 else ALPsourceWindow="" ALPsourceWave="" ALPmessage="No image in top graph" ALPprofile=0 ALPx=NaN ALPy=NaN ALPctrPx=0 ALPctrVal=0 ALPwidthPx=0 ALPwidthVal=0 endif SetDataFolder SaveDataFolder end //--------------------------------// Function ALPmakePanel() string SaveDataFolder SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal,ALPwidthPx, ALPwidthVal, ALPgraphing NewPanel /K=1/W=(44,76,514,439) as "Alternate Image Line Profile v1.0" DoWindow/C ALP SetDrawLayer UserBack CheckBox TypeVertical,pos={15.00,8.00},size={84.00,19.00},proc=ALPvCheckProc,title="Vertical " CheckBox TypeVertical,fSize=14,value= 0,side= 1 CheckBox TypeVertical,value= (ALPtype==1) // 0=H, 1=V, 2=diag CheckBox TypeHorizontal,pos={15.00,29.00},size={82.00,19.00},proc=ALPhCheckProc,title="Horizontal " CheckBox TypeHorizontal,fSize=14,side= 1 CheckBox TypeHorizontal,value= (ALPtype==0) // 0=H, 1=V, 2=diag SetVariable CenterPx,pos={126.00,8.00},size={149.00,22.00},title="Center Pixel " SetVariable CenterPx,fSize=14, value=ALPctrPx, limits={0,inf,1}, proc=ALPSetPixelsProc SetVariable CenterVal,pos={126.00,31.00},size={149.00,22.00} SetVariable CenterVal,fSize=14, value=ALPctrVal, proc=ALPSetValsProc if (ALPtype==0) // 0=H, 1=V, 2=diag SetVariable CenterVal,title="Center Y " elseif (ALPtype==1) SetVariable CenterVal,title="Center X " endif SetVariable WidthPx,pos={302.00,9.00},size={149.00,22.00},title="Width Pixel " SetVariable WidthPx,fSize=14, value=ALPwidthPx, limits={0,inf,1}, proc=ALPSetPixelsProc SetVariable WidthVal,pos={301.00,33.00},size={149.00,22.00}, proc=ALPSetValsProc SetVariable WidthVal,fSize=14, limits={0,inf,1}, value=ALPwidthVal if (ALPtype==0) // 0=H, 1=V, 2=diag SetVariable WidthVal,title="Width Y " elseif (ALPtype==1) SetVariable WidthVal,title="Width X " endif Button SaveButton,pos={6.00,60.00},size={50.00,25.00},title="Save",fSize=14 Button SaveButton, proc=ALPsaveGraphButtonProc Button SaveGraphButton,pos={62.00,60.00},size={100.00,25.00},title="Save & Graph" Button SaveGraphButton, fSize=14, proc=ALPsaveGraphButtonProc CheckBox OneGraph,pos={168.00,63.0},size={91.00,19.00},proc=ALPOneGraphCheckProc CheckBox OneGraph,fSize=14,side= 1,title="One Graph " if (ALPgraphing) CheckBox OneGraph, value=1 // 0=separate, 1=single else CheckBox OneGraph, value=0 endif CheckBox MultiGraphs,pos={274.00,63.0},size={124.00,19.00},proc=ALPmultiGraphCheckProc CheckBox MultiGraphs,fSize=14,value= 0,side= 1,title="Separate Graphs " if (ALPgraphing) CheckBox MultiGraphs, value=0 // 0=separate, 1=single else CheckBox MultiGraphs, value=1 endif Button HelpButton,pos={406.00,60.00},size={50.00,25.00},title="Help",fSize=14 Button HelpButton,proc=ALPhelpButtonProc wave profile=root:packages:ALP:ALPprofile wave ALPx=root:packages:ALP:ALPx Display/W=(193,90,581,332)/FG=(FL,$"",$"",$"")/HOST=# profile ModifyGraph mirror=2 appendtograph ALPx ModifyGraph hideTrace(ALPx)=1 // prevents graph from loosing some settings when profile killed RenameWindow #,G0 SetActiveSubwindow ## TitleBox title0,pos={6.00,340.00},size={57.00,17.00},fSize=13,frame=0 TitleBox title0,variable= ALPmessage Setwindow kwtopwin hook(ALPhook)=ALPWindowHook SetDataFolder SaveDataFolder End //--------------------------------// Function ALPWindowHook(s) STRUCT WMWinHookStruct &s Variable hookResult = 0 string SaveDataFolder,graphlist, topgraph, imagelist SaveDataFolder=GetDataFolder(1) setDataFolder root:Packages:ALP svar ALPsourceWindow switch(s.eventCode) case 0: // Activate graphlist=winlist("*",";","WIN:1") topgraph=stringfromlist(0, graphlist) if (cmpstr(topgraph, ALPsourceWindow)==0) // same as last window used ALPupdate() else ALPgetGraphInfo() if (strlen(ALPsourceWindow)!=0) ALPupdate() endif endif break case 1: // Deactivate DrawAction/W=$ALPsourceWindow getgroup=ALP, delete // delete existing lines break case 17: // Kill vote DrawAction/W=$ALPsourceWindow getgroup=ALP, delete // delete existing lines break endswitch setdatafolder SaveDataFolder return hookResult // 0 if nothing done, else 1 End //--------------------------------// Function ALPhCheckProc(cba) : CheckBoxControl STRUCT WMCheckboxAction &cba switch( cba.eventCode ) case 2: // mouse up Variable checked = cba.checked nvar ALPtype=root:packages:ALP:ALPtype if (checked) CheckBox TypeVertical, value=0 ALPtype=0 SetVariable CenterVal, win=ALP, title="Center Y " SetVariable WidthVal, win=ALP, title="Width Y " else CheckBox TypeVertical, value=1 ALPtype=1 SetVariable CenterVal, win=ALP, title="Center X " SetVariable WidthVal, win=ALP, title="Width X " endif ALPresetParms() ALPupdate() break case -1: // control being killed break endswitch return 0 End //--------------------------------// Function ALPvCheckProc(cba) : CheckBoxControl STRUCT WMCheckboxAction &cba switch( cba.eventCode ) case 2: // mouse up Variable checked = cba.checked nvar ALPtype=root:packages:ALP:ALPtype if (checked) CheckBox TypeHorizontal, value=0 ALPtype=1 SetVariable CenterVal, win=ALP, title="Center X " SetVariable WidthVal, win=ALP, title="Width X " else CheckBox TypeHorizontal, value=1 ALPtype=0 SetVariable CenterVal, win=ALP, title="Center Y " SetVariable WidthVal, win=ALP, title="Width Y " endif ALPresetParms() ALPupdate() break case -1: // control being killed break endswitch return 0 End //--------------------------------// Function ALPOneGraphCheckProc(cba) : CheckBoxControl STRUCT WMCheckboxAction &cba switch( cba.eventCode ) case 2: // mouse up Variable checked = cba.checked nvar ALPgraphing=root:packages:ALP:ALPgraphing if (checked) CheckBox MultiGraphs, value=0 ALPgraphing=1 // 0=separate, 1=single else CheckBox MultiGraphs, value=1 ALPgraphing=0 // 0=separate, 1=single endif break case -1: // control being killed break endswitch return 0 End //--------------------------------// Function ALPmultiGraphCheckProc(cba) : CheckBoxControl STRUCT WMCheckboxAction &cba switch( cba.eventCode ) case 2: // mouse up Variable checked = cba.checked nvar ALPgraphing=root:packages:ALP:ALPgraphing if (checked) CheckBox OneGraph, value=0 ALPgraphing=0 // 0=separate, 1=single else CheckBox OneGraph, value=1 ALPgraphing=1 // 0=separate, 1=single endif break case -1: // control being killed break endswitch return 0 End //--------------------------------// Function ALPSetPixelsProc(sva) : SetVariableControl STRUCT WMSetVariableAction &sva switch( sva.eventCode ) case 1: // mouse up case 2: // Enter key case 3: // Live update Variable dval = sva.dval String sval = sva.sval ALPpxToVal() ALPupdate() break case -1: // control being killed break endswitch return 0 End //--------------------------------// Function ALPSetValsProc(sva) : SetVariableControl STRUCT WMSetVariableAction &sva switch( sva.eventCode ) case 1: // mouse up case 2: // Enter key case 3: // Live update Variable dval = sva.dval String sval = sva.sval ALPvalToPx() ALPupdate() break case -1: // control being killed break endswitch return 0 End //--------------------------------// Function ALPpxToVal() String SaveDataFolder variable nxpts, nypts, X0, Y0, dx, dy, UL, LL SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal, ALPwidthPx, ALPwidthVal svar ALPsourceWindow, ALPsourceWave wave wv2d=ImageNameToWaveRef(ALPsourceWindow, ALPsourceWave) nxpts=dimsize(wv2d,0) nypts=dimsize(wv2d,1) x0=dimoffset(wv2d,0) y0=dimoffset(wv2d,1) dx=dimdelta(wv2d,0) dy=dimdelta(wv2d,1) // bounds checking ALPctrPx=max(0, ALPctrPx) ALPwidthPx=max(0, ALPwidthPx) if (ALPtype==0) // 0=H, 1=V, 2=diag // bounds checking ALPctrPx=min(nypts-1, ALPctrPx) ALPwidthPx=min(2*nypts, ALPwidthPx) // conversion ALPctrVal=y0 + ALPctrPx*dy ALPwidthVal=ALPwidthPx*dy elseif (ALPtype==1) // 0=H, 1=V, 2=diag // bounds checking ALPctrPx=min(nxpts-1, ALPctrPx) ALPwidthPx=min(2*nxpts, ALPwidthPx) // conversion ALPctrVal=x0 + ALPctrPx*dx ALPwidthVal=ALPwidthPx*dx endif setdatafolder SaveDataFolder end //--------------------------------// Function ALPvalToPx() String SaveDataFolder variable nxpts, nypts, X0, Y0, dx, dy, UL, LL SaveDataFolder=GetDataFolder(1) SetDataFolder root:Packages:ALP nvar ALPtype, ALPctrPx, ALPctrVal, ALPwidthPx, ALPwidthVal svar ALPsourceWindow, ALPsourceWave wave wv2d=ImageNameToWaveRef(ALPsourceWindow, ALPsourceWave) nxpts=dimsize(wv2d,0) nypts=dimsize(wv2d,1) x0=dimoffset(wv2d,0) y0=dimoffset(wv2d,1) dx=dimdelta(wv2d,0) dy=dimdelta(wv2d,1) ALPwidthVal=max(0, ALPwidthVal) if (ALPtype==0) // 0=H, 1=V, 2=diag // bounds checking ALPctrVal=max(ALPctrVal, y0) ALPctrVal=min(ALPctrVal, y0+(nypts-1)*dy) ALPwidthVal=min(ALPwidthVal,y0+2*(nypts)*dy) // conversion ALPctrPx=(ALPctrVal-y0)/dy ALPwidthPx=ALPwidthVal/dy elseif (ALPtype==1) // 0=H, 1=V, 2=diag // bounds checking ALPctrVal=max(ALPctrVal, x0) ALPctrVal=min(ALPctrVal, x0+(nxpts-1)*dx) ALPctrVal=min(ALPctrVal, x0+2*(nxpts-1)*dx) // conversion ALPctrPx=(ALPctrVal-x0)/dx ALPwidthPx=ALPwidthVal/dx endif setdatafolder SaveDataFolder end //------------------------------------------------------------------// Function ALPstackTracesButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba switch( ba.eventCode ) case 2: // mouse up ALPstackTraces() break case -1: // control being killed break endswitch return 0 End //------------------------------------------------------------------// Function ALPstackTraces() string trname, previoustrace, ECLtrname, str variable ctr, ii, jj, yoff, ymin, ymax, prevoffset variable spacing spacing=1.05 ctr=0 prevoffset=0 yoff=0 do trname=stringfromlist(ctr,tracenamelist("",";",5)) // top window trace list if (strlen(trname)==0) break endif wave/z YY=TraceNameToWaveRef("",trname) ymin=wavemin(YY) ymax=wavemax(YY) // YY = YY < 0 ? 0 : YY // zero clip and normalize // YY/=ymax // ymin=0 // ymax=1 if (prevoffset!=0) yoff = prevoffset -ymin ModifyGraph offset($trname)={0,yoff} prevoffset=yoff + (ymax-ymin)*spacing else ModifyGraph offset($trname)={0,0} // first one is shifted to zero prevoffset=ymax*spacing endif ctr+=1 while (1) end //------------------------------------------------------------------// Function ALPnormTracesButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba switch( ba.eventCode ) case 2: // mouse up ALPnormTraces() break case -1: // control being killed break endswitch return 0 End //------------------------------------------------------------------// Function ALPnormTraces() string trname, previoustrace, ECLtrname, str variable ctr, ii, jj, yoff, ymin, ymax, prevoffset variable spacing spacing=1.05 ctr=0 prevoffset=0 yoff=0 //print tracenamelist("",";",5) do trname=stringfromlist(ctr,tracenamelist("",";",5)) // top window trace list if (strlen(trname)==0) break endif wave/z YY=TraceNameToWaveRef("",trname) ymin=0 //wavemin(YY) ymax=wavemax(YY) YY=YY-ymin YY=YY/(ymax-ymin) ctr+=1 while (1) end //------------------------------------------------------------------// Function ALPtagsOnOffButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba string ctrlname, str variable ii switch( ba.eventCode ) case 2: // mouse up ctrlname=ba.ctrlName str=GetUserData("",ctrlname,"") ii=strsearch(str, "on",0) if (ii>=0) ALPtoggleTags(0) Button $ctrlname userdata="off" else ALPtoggleTags(1) Button $ctrlname userdata="on" endif break case -1: // control being killed break endswitch return 0 End //------------------------------------------------------------------// // assumes relevant waves all have names like: ABCprofileZN, // where ABC, Z any text and N an integer // // Tags are assumed to have names like: ProfileWavetagN // where N an integer Function ALPtoggleTags(onoff) variable onoff string trname, str, tagname, annolist variable ctr, ii, jj, xpnt if (onoff) // turn on ctr=0 do trname=stringfromlist(ctr,tracenamelist("",";",5)) // top window trace list if (strlen(trname)==0) break // end of trace list endif str=Note($trname) //print ctr, trname, str tagname="ProfileWaveTag"+num2str(ctr) Tag/N=$tagname/X=10/Y=10/I=1 $trname, 1, str ctr+=1 while(1) else annolist=Annotationlist("") ctr=0 do tagname=stringfromlist(ctr,annolist) if (strlen(tagname)==0) break // end of trace list endif Tag/K/N=$tagname ctr+=1 while (1) endif End //------------------------------------------------------------------// Function ALPsaveGraphButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba String ctrlName ctrlName=ba.ctrlName variable ii, jj, kk string wname, wnamex, winnam, str, notetext, tagname, wrec nvar ALPtype=root:packages:ALP:ALPtype // 0=H, 1=V, 2=diag nvar ALPctrPx=root:packages:ALP:ALPctrPx nvar ALPctrVal=root:packages:ALP:ALPctrVal nvar ALPwidthPx=root:packages:ALP:ALPwidthPx nvar ALPwidthVal=root:packages:ALP:ALPwidthVal nvar ALPgraphing=root:packages:ALP:ALPgraphing // 0=separate, 1=single svar ALPmessage=root:packages:ALP:ALPmessage svar ALPsourceWindow=root:packages:ALP:ALPsourceWindow svar ALPsourceWave=root:packages:ALP:ALPsourceWave wave ALPprofile=root:packages:ALP:ALPprofile wave ALPx=root:packages:ALP:ALPx wave ALPy=root:packages:ALP:ALPy switch( ba.eventCode ) case 2: // mouse up if ((strlen(ALPsourceWave)==0) || (numtype(strlen(ALPsourceWave))!=0)) // if no data, quit break endif ii=0 do // find an unused wave name if (ALPtype==0) // 0=H, 1=V, 2=diag wname="root:"+ALPsourceWave+"_Xprofile"+num2str(ii) elseif (ALPtype==1) wname="root:"+ALPsourceWave+"_Yprofile"+num2str(ii) else print "copy type not yet supported" endif if (!exists(wname)) break endif ii+=1 while(ii<100) if (ii>=100) print "too many profiles" abort endif // copy the waves Duplicate/O ALPprofile, $wname wave profile=$wname if (ALPtype==0) // 0=H, 1=V, 2=diag wnamex="root:"+ALPsourceWave+"XprofileX"+num2str(ii) Duplicate/O ALPx, $wnamex elseif (ALPtype==1) wnamex="root:"+ALPsourceWave+"XprofileY"+num2str(ii) Duplicate/O ALPy, $wnamex endif wave profilex=$wnamex // store profile info in wave note notetext="Image:"+ALPsourceWave if (ALPtype==0) // 0=H, 1=V, 2=diag notetext+= " Y Center:"+num2str(ALPctrVal)+" Width:"+num2str(ALPwidthVal) elseif (ALPtype==1) // 0=H, 1=V, 2=diag notetext+= " X Center:"+num2str(ALPctrVal)+" Width:"+num2str(ALPwidthVal) endif Note $wname, notetext Note $wnamex, notetext ALPmessage="Saved: "+wname if (cmpstr(ctrlName, "SaveButton")==0) // if only save, we are done here break endif // continue with graphing options if (ALPgraphing==0) // 0=separate, 1=single graph winnam=ALPsourceWave+"_profile"+num2str(ii) else winnam="ALPprofiles" endif DoWindow $winnam if (!V_Flag) // if window doesnt exist, make it Display/K=1/W=(150, 310, 150+475, 310+250) $wname DoWindow/C $winnam modifygraph mirror=2 // copy the 2D window axis label: str=WinRecreation(ALPsourceWindow,1) // parent 2D window if (ALPtype==0) // 0=H, 1=V, 2=diag // is image plotted vs top or bottm x axis? wrec=winrecreation(ALPsourceWindow,0) kk=strsearch(wrec,"AppendImage/T",0) if (kk>=0) kk=strsearch(str, "Label/Z top",0) else kk=strsearch(str, "Label/Z bottom",0) endif elseif (ALPtype==1) // 0=H, 1=V, 2=diag kk=strsearch(str, "Label/Z left",0) endif kk=strsearch(str, "\"",kk) jj=strsearch(str, "\"",kk+1) str=str[kk+1, jj-1] Label bottom str ControlBar 24 if (ALPgraphing==1) // 0=separate, 1=single // single graph has some display control buttons: ctrlname= "StackButton" Button $ctrlname title="Stack",size={45,20},pos={275,2}, fSize=11, proc=ALPstackTracesButtonProc Button $ctrlname, font=Tahoma, fsize=12 ctrlname= "NormButton" Button $ctrlname title="Norm",size={45,20},pos={335,2}, fSize=11, proc=ALPnormTracesButtonProc Button $ctrlname, font=Tahoma, fsize=12 ctrlname= "TagsButton" Button $ctrlname title="Tags 0/1",size={60,20},pos={200,2}, fSize=11, proc=ALPtagsOnOffButtonProc Button $ctrlname userdata="on" Button $ctrlname, font=Tahoma, fsize=12 else // separate graphs if (ALPtype==0) // 0=H, 1=V, 2=diag str=wname + " Y Center:"+num2str(ALPctrVal)+" Width:"+num2str(ALPwidthVal) elseif (ALPtype==1) // 0=H, 1=V, 2=diag str=wname + " X Center:"+num2str(ALPctrVal)+" Width:"+num2str(ALPwidthVal) endif TitleBox title0 title=str, pos={5,5}, frame=0, font=Tahoma endif else // window exists, add new wave AppendtoGraph/W=$winnam $wname endif if (ALPgraphing==1) // 1=single, show data for each profile in a tag tagname="ProfileWaveTag"+num2str(ii) notetext = "\\F'Tahoma'"+notetext str=parsefilepath(3,wname,":",0,0) // only trace name, not full path Tag/W=$winnam/N=$tagname/X=10/Y=10/I=1 $str, 1, notetext endif break endswitch return 0 End //------------------------------------------------------------------// Function ALPhelpButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba string ctrlname, str variable ii switch( ba.eventCode ) case 2: // mouse up dowindow ALPhelp if (!v_flag) ALPshowhelp() else dowindow/F ALPhelp endif break case -1: // control being killed break endswitch return 0 End //------------------------------------------------------------------// Function ALPshowhelp() String nb = "ALPhelp" NewNotebook/N=$nb/F=1/V=1/K=0/ENCG={3,1}/W=(435.75,39.5,806.25,400.25) Notebook $nb defaultTab=36 Notebook $nb showRuler=0, rulerUnits=2, updating={1, 1} Notebook $nb newRuler=Normal, justification=0, margins={0,0,468}, spacing={0,0,0}, tabs={}, rulerDefaults={"Arial",11,0,(0,0,0)} Notebook $nb ruler=Normal, text="\t\t", fStyle=1, text=" ALP Alternate Line Profile\r" Notebook $nb fStyle=-1, text="\r" Notebook $nb text="Why ALP?\r" Notebook $nb text="The Igor 7 image line profile has fewer features than in Igor 6: \r" Notebook $nb text="- The profile graph cannnot be modified, or the data explored, \r" Notebook $nb text=" for example with a cursor.\r" Notebook $nb text="- Does not take wave scaling into account.\r" Notebook $nb text="- No longer possible to graph a profile, it can only be saved.\r" Notebook $nb text="- The saved wave is now a triplet. This is not visible in the \r" Notebook $nb text=" default New Graph menu, inexperienced users can not easily graph\r" Notebook $nb text=" it themselves. Also, inexperienced users do not know how to graph\r" Notebook $nb text=" one column of a triplet vs another.\r" Notebook $nb text="- The lines defining the profile are hard to see on dark images.\r" Notebook $nb text="- If a profile limit goes outside the image, the profile is NaN, instead\r" Notebook $nb text=" of truncating at the edge of the image. \r" Notebook $nb text="\r" Notebook $nb text="\r" Notebook $nb text="ALP is an Alternate Line Profile package designed to meet typical needs.\r" Notebook $nb text="- The profile graph is fully accessible.\r" Notebook $nb text="- Image wave scaling is used.\r" Notebook $nb text="- The profile can be specified in pixel or scaled units.\r" Notebook $nb text="- There are two graphing options, together in one graph or separate \r" Notebook $nb text=" graphs. The single graph option facilitates comparison of profiles\r" Notebook $nb text=" from different images.\r" Notebook $nb text="- The profile lines on the image are easily visible.\r" Notebook $nb text="- The profiles are saved as three one-D waves, for easy discovery and\r" Notebook $nb text=" use. These are the profile, and the corresponding X and Y coords. The\r" Notebook $nb text=" coordinates are in scaled wave units.\r" Notebook $nb text="\r" Notebook $nb fStyle=1, text="Planned features:\r" Notebook $nb fStyle=-1, text="- Image waves displayed vs X or Y waves.\r" Notebook $nb text="- Diagonal profiles (but not freeform).\r" Notebook $nb text="\r" Notebook $nb fStyle=1, text="Using ALP\r" Notebook $nb fStyle=-1, text="- Start it from the menu Image/Alt Line Profile...\r" Notebook $nb text="- When you click on the ALP window, it checks if the top graph includes\r" Notebook $nb text=" an image. If so, it places the profile lines on the image.\r" Notebook $nb text="- When you leave the ALP window, the profile lines are removed from \r" Notebook $nb text=" the image.\r" Notebook $nb text="- If you return to ALP, it remembers if the top graph was the last used.\r" Notebook $nb text=" You can modify the working image, then go back to ALP without loosing\r" Notebook $nb text=" the profile settings.\r" Notebook $nb text="- The width is FULL width, not half.\r" Notebook $nb text="- The profile is the SUM of the data over the width, not the average.\r" Notebook $nb text="- Sub-pixel interpolation is used, so a profile of width 1.1 is different from\r" Notebook $nb text=" width 1. This is an estimate of the profile from a higher res image.\r" Notebook $nb text="- Special case: if width =0, the profile is the current row or column. For\r" Notebook $nb text=" example if the center = 2.23, and width=0, the profile is as if center\r" Notebook $nb text=" is exactly 2.0 and the width is exactly 1 pixel. This makes it easy to\r" Notebook $nb text=" examine specific rows and columns. \r" Notebook $nb text="- There is a message area at the bottom of the panel, giving some\r" Notebook $nb text=" information about what is happening.\r" Notebook $nb text="- The profile details are in the wave notes of the saved waves." Notebook $nb selection={startOfFile,startOfFile}, findText={"",1} Notebook $nb findText={"Using ALP",1} end