Use a listbox to select a group of waves, duplicate and apply an operation

I sometimes find myself needing to perform a simple operation on many waves. In my case this is usually applying a different normalizing factor to each wave. This snippet illustrates the use of listboxes to select 1D waves, preview and edit the names of output waves, and input the normalizing factors. Output waves are forced to be non-liberal, and potential name conflicts are highlighted in the listbox. The interface is a bit like Igor's rename objects dialog.

menu "Macros"
    "Normalize Waves",  /Q
end

function NormalizeWaves()
    dowindow /k NormPanel
    NewDataFolder /O root:Packages
    NewDataFolder /O root:Packages:Normalizer
    DFREF dfr=root:Packages:Normalizer
   
    make /o /n=(0,3)/T dfr:w_newList /WAVE=w_newList
    make /o/W/U /n=(3,5,3) dfr:w_color/WAVE=w_color
    w_color={{0,0,0},{65535,0,0}}
    MatrixTranspose w_color
    make /o /n=(0,3,3) dfr:w_selection /WAVE=w_selection
    SetDimLabel 2,1,backColors,w_selection  // define plane 1 as background colors
   
    make /o /n=3 /T dfr:w_titles /wave=w_titles
    w_titles={"input","mm","output"}

    wave /T w_wavelist=ListToTextWave(wavelist("*",";","DIMS:1"), ";")
    killwaves /Z dfr:w_wavelist
    movewave w_wavelist dfr:w_wavelist
    make /o/n=(numpnts(w_wavelist)) dfr:w_waveselection /wave=w_waveselection
   
    string /G dfr:s_edit=""
   
    NewPanel /K=1/N=NormPanel/W=(100,100,950,560) as "Normalize"
    ModifyPanel /W=NormPanel fixedSize=1
    ListBox listboxWaves,win=NormPanel, pos={20, 40},size={200, 350}, listwave=w_wavelist, selwave=w_waveselection, mode=9
    button buttonGrabWaves win=NormPanel, pos={250,180},size={50,50},title=">",  proc=normButtons
    ListBox listboxOut,win=NormPanel, mode=6, selwave=w_selection, titlewave=w_titles, pos={330, 40},size={500, 350}, editstyle=1
    ListBox listboxOut,win=NormPanel, colorwave=w_color, listwave=w_newList,widths={150,50,150}, fsize=16, proc=normListBox
    Button buttonDoIt win=NormPanel,pos={780,410},size={50,30},title="Do It",  proc=normButtons
    Button buttonCancel win=NormPanel,pos={700,410},size={60,30},title="Cancel",  proc=normButtons
end

// wrapper for buttons
function normButtons(ba)
    STRUCT WMButtonAction &ba
   
    DFREF dfr=root:Packages:Normalizer 
    wave /T w_wavelist=dfr:w_wavelist
    wave w_waveselection=dfr:w_waveselection
    wave /T w_newList=dfr:w_newList
    wave w_selection=dfr:w_selection
    wave w_color=dfr:w_color
    variable i,count
   
    switch( ba.eventCode )
        case 2: // mouse up    
            if(stringmatch(ba.ctrlName, "buttonGrabWaves"))
                count=numpnts(w_wavelist)
                for (i=0;i<count;i+=1)
                    if (w_waveselection[i])
                        variable rowsinwave=dimsize(w_newList, 0)
                        FindValue /TEXT=w_wavelist[i] w_newList
                        if (V_value==-1 || v_value>rowsinwave) // add a wave
                            w_newList[dimsize(w_newList, 0)][]={{w_wavelist[i]},{"0"},{CleanupName(w_wavelist[i]+"_cm",0)}}
                            w_selection[dimsize(w_selection, 0)][]={{0},{2},{2}}
                            normSanityCheck()
                        endif
                    endif
                endfor
            elseif(stringmatch(ba.ctrlName, "buttonDoIt"))     
                count=dimsize(w_newList, 0)
                for (i=0;i<count;i+=1)
                    if (waveexists($w_newList[i][2]))
                        doalert 1, "Overwrite "+w_newList[i][2]+"?"
                        if (v_flag==2)
                            continue
                        endif
                    endif
                    wave w=$w_newList[i][0]
                    variable factor=str2num(w_newList[i][1])
                    duplicate /o w $w_newList[i][2]/wave=w2
                    w2=w/(factor/10)
                    // output is forced to be non-liberal
                    printf "Duplicate /O %s %s\r", possiblyquotename(w_newList[i][0]), w_newList[i][2]
                    printf "%s = %s / %g\r", w_newList[i][2], possiblyquotename(w_newList[i][0]), factor/10
                endfor         
                redimension /N=(0,-1,-1,-1) w_newList, w_selection
               
            elseif(stringmatch(ba.ctrlName, "buttonCancel"))   
                dowindow /k NormPanel
            endif
            break
        case -1: // control being killed
            break
    endswitch

    return 0
end

// check sanity of edits
function normListBox(lba) : ListBoxControl
    STRUCT WMListboxAction &lba

    Variable row = lba.row
    Variable col = lba.col
    WAVE/T/Z listWave = lba.listWave
    WAVE/Z selWave = lba.selWave
   
    DFREF dfr=root:Packages:Normalizer
    SVAR s_edit=dfr:s_edit
   
    switch( lba.eventCode )
        case -1: // control being killed
            break
        case 1:
            selWave[][1,2][0]=selWave & ~1
            // stop edit when cell loses focus
            // so that bg color is visible
            break
        case 6: // begin edit
            s_edit=listWave[row][col]
            break
        case 7: // finish edit
            if(col==1)
                if(numtype(str2num(listWave[row][col]))==2)
                    listWave[row][col]=s_edit
                else
                    listWave[row][col]=num2str(str2num(listWave[row][col]))
                endif
            elseif(col==2)
                listWave[row][col]=CleanupName( listWave[row][col],0)
                normSanityCheck()
            endif
            break
    endswitch

    return 0
end

function normSanityCheck()

    DFREF dfr=root:Packages:Normalizer 
    wave /T listWave=dfr:w_newList
    wave selWave=dfr:w_selection
   
    variable i,j,i_max=dimsize(listWave, 0)
   
    selWave[][2][%backcolors]=0
   
    for (i=0; i<i_max; i+=1)
        for (j=i+1; j<i_max; j+=1)
            if (stringmatch(listWave[i][2], listWave[j][2]))
                selWave[i][2][%backcolors]=1
                selWave[j][2][%backcolors]=1
            endif
        endfor
        if(waveexists($listWave[i][2]))
            selWave[i][2][%backcolors]=1
        endif
    endfor 
end

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More