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

Average rating
(0 votes)

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

Back to top