Read and extract values of variables and waves' name using multithread function from mass # of waves

Hi Jim,

Thanks for the help about extracting value of center of mass. I have tried to extract X axis peak position and center of mass using demo procedure - Thread-at-a-Time Demo
I am also interested in displaying each wave name from the variables. However, I have tried and failed.
I have learned that the I need to introduce string to extract wave name, but I don't know how to put the string with variables.
Please helps!

Here is the modified version to replace min and max value.

#pragma rtGlobals=3		// Use modern global access method.

Menu "Macros"
	"Thread-at-a-Time Demo", ThreadAtATimeDemo()
End

// These control various troubleshooting items and other aspects of the demonstration
Constant kNumDatasetsToProcess = 400		// Number of sample input waves to create and process
Constant kSampleWaveNumPoints = 10000		// Number of points in each sample input wave
Constant kPrintStartThreadMessage = 1
Constant kPrintGotThreadDFMessage = 1
Constant kSimulateVaryingComputationTime = 1

ThreadSafe Function ThreadWorker(wIn, waveIndex)
	WAVE wIn
	Variable waveIndex
////// 
//// String namewave = nameofwave(wIn)  <---I introduce string here
 Wavestats/q wIn
	variable xPeak = V_maxloc
	Variable i,n=numpnts(wIn), massTimesX=0
	for(i=0; i<n; i+=1)
		massTimesX += wIn[i]*pnt2x(wIn,i)
	endfor
	Variable totalMass=sum(wIn)
	Variable centerOfMass= massTimesX/totalMass
  //     printf "Center of Mass: %g", centerofMass
//return centerOfMass


	// This is used to simulate varying computation time
	if (kSimulateVaryingComputationTime > 0)
		Variable randomSecs = abs(enoise(kSimulateVaryingComputationTime))
		Sleep/S randomSecs
	endif
	
	//Variable wMin = WaveMin(wIn)
	//Variable wMax = WaveMax(wIn)
	
	// Create data folder to return to calling thread
	NewDataFolder/S output
	
	// Create output variables
	// Variable/G gMin = wMin
	Variable/G gcenterOfMass =centerOfMass
	Variable/G gxPeak = xPeak
  //     String/G gnamewave=namewave ( I tried to add this but it did not work)
	
	// This tells the calling thread which wave was processed
	Variable/G gWaveIndex = waveIndex
	
	// Send data back to main thread
	ThreadGroupPutDF 0, :
	
	return 0		// Success
End


Function ThreadAtATimeDemo()
	if (IgorVersion() < 6.23)
		Abort "This demo requires Igor Pro 6.23 or later."
	endif

	Variable t0 = StopMSTimer(-2)		// Used to time the function

	DFREF originalDFR = GetDataFolderDFR()

	DFREF outputDFR = GetDataFolderDFR()

	Variable numDatasetsToProcess = kNumDatasetsToProcess
	Variable numDatasetsProcessed = 0
	
	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,3)  outputDFR:results = NaN
	Wave results = outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
      SetDimLabel 1,2,Name,results  ///<----Third column I added for wavename
      
	// Create output table
	DoWindow /F OutputTable
	if (V_flag == 0)
		Edit /N=OutputTable /W=(466,49,906,652) results.ld
	endif

	// Look for sample data
	Variable numPointsInSampleData = kSampleWaveNumPoints
//	NewDataFolder /O :SampleData
	DFREF inputDFR = :
	String name
	Variable i
	for(i=0; i<numDatasetsToProcess; i+=1)
	
	sprintf name, "(%d)", i		// wave0, wave1
	//	Make/O/D/N=(numPointsInSampleData) inputDFR:$name = gnoise(1)  (disabled)
		SetDimLabel 0,i,$name,results
	endfor

	// Create threads
	Variable numThreads = ThreadProcessorCount
	Variable threadGroupID = ThreadGroupCreate(numThreads)
	
	SetDataFolder inputDFR		// Needed for WaveRefIndexed
	
	// Dispatch threads and collect output
	Variable threadIndex
	Variable waveIndex = 0
	do
		// Start any free threads
		do
			if (waveIndex >= numDatasetsToProcess)
				break								// No more input data to dispatch to a thread
			endif
			
			// Find a free thread
			threadIndex = ThreadGroupWait(threadGroupID, -2)		// Requires Igor Pro 6.23
			threadIndex -= 1	// Because ThreadGroupWait returns threadIndex+1
			if (threadIndex < 0)
				break			// No free threads
			endif
		
			// Start thread
			Wave wIn = WaveRefIndexed("", waveIndex, 4)
	
			ThreadStart threadGroupID, threadIndex, ThreadWorker(wIn, waveIndex)
			if (kPrintStartThreadMessage)
				Printf "Started thread %d\r", threadIndex		// For debugging only
			endif
			waveIndex += 1
		while(1)
		
		// See if thread output is available
		DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			NVAR gWaveIndex = dfr:gWaveIndex
		//	NVAR gnamewave= dfr:$namewave  <---- I tried this but  it did not work because of string function I believe.
		
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		//	results[gWaveIndex][2] = $namewave   <-----It did not work
			// Update the output table
			DoUpdate

			// For debugging only
			if (kPrintGotThreadDFMessage)
				Printf "Got data for wave %d: CenterOfMass=%g, Peak=%g\r", gWaveIndex, gcenterOfMass, gxPeak
			endif
			
			numDatasetsProcessed += 1
			
			// This is a free data folder that would be killed automatically by Igor.
			// Nonetheless we explicitly kill it here and now.
			KillDataFolder dfr
		endif
	while(numDatasetsProcessed < numDatasetsToProcess)
		
	Variable dummy = ThreadGroupRelease(threadGroupID)
	
	Variable t1 = StopMSTimer(-2)
	Variable elapsedTime = (t1 - t0) / 1E6
	Printf "Finished ThreadAtATimeDemo in %.2f seconds.\r", elapsedTime

	SetDataFolder originalDFR
End

Function CleanupExperiment()	// We call this to prepare the experiment for shipping
	DoWindow /K OutputTable			// The table is recreated by the demo
	KillWaves/Z results					// Output wave is recreated by the demo
	KillDataFolder /Z root:SampleData	// Sample data is recreated by the demo
End



Thank you very much!
I don't know that this is the *only* problem, but this:

		NVAR gnamewave= dfr:$namewave // NVAR is for (numeric) Variable/G

needs to be:

		SVAR gnamewave= dfr:$namewave  // SVAR for String/Gs


--Jim Prouty
Software Engineer, WaveMetrics, Inc.
JimProuty wrote: I don't know that this is the *only* problem, but this:

		NVAR gnamewave= dfr:$namewave // NVAR is for (numeric) Variable/G

needs to be:

		SVAR gnamewave= dfr:$namewave  // SVAR for String/Gs


--Jim Prouty
Software Engineer, WaveMetrics, Inc.


Thanks, I just learned the function of SVAR.
Here is what I added to:
In the function of
ThreadSafe Function ThreadWorker(wIn, waveIndex)

I introduced
string NameWave =NameofWave(wIn) 

      String/G gNameWave=NameWave 


Then, in the function of
Function ThreadAtATimeDemo()

I added one column to the table
 	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,3)  outputDFR:results = NaN
	Wave results = outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
      SetDimLabel 1,2,Name,results

And introduced SVAR for wave name
 DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			SVAR gNameWave= dfr:gNameWave
			NVAR gWaveIndex = dfr:gWaveIndex
		   
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		      results[gWaveIndex][2] = gNameWave


But, I received error saying
  results[gWaveIndex][2] = gNameWave 

unknown/inappropriate name or symbol...
with my current knowledge, I don't know where is the error and I need your help.

Thank you!

Here is the code:
#pragma rtGlobals=3		// Use modern global access method.

Menu "Macros"
	"Thread-at-a-Time Demo", ThreadAtATimeDemo()
End

// These control various troubleshooting items and other aspects of the demonstration
Constant kNumDatasetsToProcess = 400		// Number of sample input waves to create and process
Constant kSampleWaveNumPoints = 10000		// Number of points in each sample input wave
Constant kPrintStartThreadMessage = 1
Constant kPrintGotThreadDFMessage = 1
Constant kSimulateVaryingComputationTime = 1

ThreadSafe Function ThreadWorker(wIn, waveIndex)
	WAVE wIn
	Variable waveIndex
	String NameWave = NameofWave(wIn)
  Wavestats/q wIn
	variable xPeak = V_maxloc
	Variable i,n=numpnts(wIn), massTimesX=0
	for(i=0; i<n; i+=1)
		massTimesX += wIn[i]*pnt2x(wIn,i)
	endfor
	Variable totalMass=sum(wIn)
	Variable centerOfMass= massTimesX/totalMass
  //     printf "Center of Mass: %g", centerofMass
//return centerOfMass


	// This is used to simulate varying computation time
	if (kSimulateVaryingComputationTime > 0)
		Variable randomSecs = abs(enoise(kSimulateVaryingComputationTime))
		Sleep/S randomSecs
	endif
	
	//Variable wMin = WaveMin(wIn)
	//Variable wMax = WaveMax(wIn)
	
	// Create data folder to return to calling thread
	NewDataFolder/S output
	
	// Create output variables
	// Variable/G gMin = wMin
	Variable/G gcenterOfMass =centerOfMass
	Variable/G gxPeak = xPeak
      String/G gNameWave=NameWave
	
	// This tells the calling thread which wave was processed
	Variable/G gWaveIndex = waveIndex
	
	// Send data back to main thread
	ThreadGroupPutDF 0, :
	
	return 0		// Success
End


Function ThreadAtATimeDemo()
	if (IgorVersion() < 6.23)
		Abort "This demo requires Igor Pro 6.23 or later."
	endif

	Variable t0 = StopMSTimer(-2)		// Used to time the function

	DFREF originalDFR = GetDataFolderDFR()

	DFREF outputDFR = GetDataFolderDFR()

	Variable numDatasetsToProcess = kNumDatasetsToProcess
	Variable numDatasetsProcessed = 0
	
	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,3)  outputDFR:results = NaN
	Wave results = outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
      SetDimLabel 1,2,Name,results
      
	// Create output table
	DoWindow /F OutputTable
	if (V_flag == 0)
		Edit /N=OutputTable /W=(466,49,906,652) results.ld
	endif

	// Look for sample data
	Variable numPointsInSampleData = kSampleWaveNumPoints
//	NewDataFolder /O :SampleData
	DFREF inputDFR = :
	String name
	Variable i
	for(i=0; i<numDatasetsToProcess; i+=1)
	
	sprintf name, "(%d)", i		// wave0, wave1
	//	Make/O/D/N=(numPointsInSampleData) inputDFR:$name = gnoise(1)
		SetDimLabel 0,i,$name,results
	endfor

	// Create threads
	Variable numThreads = ThreadProcessorCount
	Variable threadGroupID = ThreadGroupCreate(numThreads)
	
	SetDataFolder inputDFR		// Needed for WaveRefIndexed
	
	// Dispatch threads and collect output
	Variable threadIndex
	Variable waveIndex = 0
	do
		// Start any free threads
		do
			if (waveIndex >= numDatasetsToProcess)
				break								// No more input data to dispatch to a thread
			endif
			
			// Find a free thread
			threadIndex = ThreadGroupWait(threadGroupID, -2)		// Requires Igor Pro 6.23
			threadIndex -= 1	// Because ThreadGroupWait returns threadIndex+1
			if (threadIndex < 0)
				break			// No free threads
			endif
		
			// Start thread
			Wave wIn = WaveRefIndexed("", waveIndex, 4)

			ThreadStart threadGroupID, threadIndex, ThreadWorker(wIn, waveIndex)
			if (kPrintStartThreadMessage)
				Printf "Started thread %d\r", threadIndex		// For debugging only
			endif
			waveIndex += 1
		while(1)
		
		// See if thread output is available
		DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			SVAR gNameWave= dfr:gNameWave
			NVAR gWaveIndex = dfr:gWaveIndex
		   
		
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		      results[gWaveIndex][2] = gNameWave
			// Update the output table
			DoUpdate

			// For debugging only
			if (kPrintGotThreadDFMessage)
				Printf "Got data for wave %d: CenterOfMass=%g, Peak=%g\r", gWaveIndex, gcenterOfMass, gxPeak
			endif
			
			numDatasetsProcessed += 1
			
			// This is a free data folder that would be killed automatically by Igor.
			// Nonetheless we explicitly kill it here and now.
			KillDataFolder dfr
		endif
	while(numDatasetsProcessed < numDatasetsToProcess)
		
	Variable dummy = ThreadGroupRelease(threadGroupID)
	
	Variable t1 = StopMSTimer(-2)
	Variable elapsedTime = (t1 - t0) / 1E6
	Printf "Finished ThreadAtATimeDemo in %.2f seconds.\r", elapsedTime

	SetDataFolder originalDFR
End

Function CleanupExperiment()	// We call this to prepare the experiment for shipping
	DoWindow /K OutputTable			// The table is recreated by the demo
	KillWaves/Z results					// Output wave is recreated by the demo
	KillDataFolder /Z root:SampleData	// Sample data is recreated by the demo
End


Thanks, I just learned the function of SVAR.
Here is what I added to:
In the function of
ThreadSafe Function ThreadWorker(wIn, waveIndex)

I introduced
string NameWave =NameofWave(wIn) 

      String/G gNameWave=NameWave 


Then, in the function of
Function ThreadAtATimeDemo()

I added one column to the table
 	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,3)  outputDFR:results = NaN
	Wave results = outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
      SetDimLabel 1,2,Name,results

And introduced SVAR for wave name
 DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			SVAR gNameWave= dfr:gNameWave
			NVAR gWaveIndex = dfr:gWaveIndex
		   
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		      results[gWaveIndex][2] = gNameWave


But, I received error saying
  results[gWaveIndex][2] = gNameWave 

unknown/inappropriate name or symbol...
with my current knowledge, I don't know where is the error and I need your help.



Note that the results wave is numeric.
The string is not.
You can't assign a string to a number.

--Jim Prouty
Software Engineer, WaveMetrics, Inc.
JimProuty wrote:

Thanks, I just learned the function of SVAR.
Here is what I added to:
In the function of
ThreadSafe Function ThreadWorker(wIn, waveIndex)

I introduced
string NameWave =NameofWave(wIn) 

      String/G gNameWave=NameWave 


Then, in the function of
Function ThreadAtATimeDemo()

I added one column to the table
 	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,3)  outputDFR:results = NaN
	Wave results = outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
      SetDimLabel 1,2,Name,results

And introduced SVAR for wave name
 DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			SVAR gNameWave= dfr:gNameWave
			NVAR gWaveIndex = dfr:gWaveIndex
		   
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		      results[gWaveIndex][2] = gNameWave


But, I received error saying
  results[gWaveIndex][2] = gNameWave 

unknown/inappropriate name or symbol...
with my current knowledge, I don't know where is the error and I need your help.



Note that the results wave is numeric.
The string is not.
You can't assign a string to a number.

--Jim Prouty
Software Engineer, WaveMetrics, Inc.


Thank you.
Are there any ways to extract wave name as well as the two variables to the table using this algorithm? If so, you are welcome to make changes.
I guess the problem is the
gWaveIndex
? I noticed that gWaveIndex was assigned as variable. But I don't know how to convert it to string.
Please bear in mind, I am new to IGOR and I try my best to understand programming syntax as a biologist. I need your advices and suggestions.

Thank you again.
JimProuty wrote:

Thanks, I just learned the function of SVAR.
Here is what I added to:
In the function of
ThreadSafe Function ThreadWorker(wIn, waveIndex)

I introduced
string NameWave =NameofWave(wIn) 

      String/G gNameWave=NameWave 


Then, in the function of
Function ThreadAtATimeDemo()

I added one column to the table
 	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,3)  outputDFR:results = NaN
	Wave results = outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
      SetDimLabel 1,2,Name,results

And introduced SVAR for wave name
 DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			SVAR gNameWave= dfr:gNameWave
			NVAR gWaveIndex = dfr:gWaveIndex
		   
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		      results[gWaveIndex][2] = gNameWave


But, I received error saying
  results[gWaveIndex][2] = gNameWave 

unknown/inappropriate name or symbol...
with my current knowledge, I don't know where is the error and I need your help.



Note that the results wave is numeric.
The string is not.
You can't assign a string to a number.

--Jim Prouty
Software Engineer, WaveMetrics, Inc.


Hello Jim,

Thank you for pointing out the error again. I have fixed the incomparability (text vs. numeric)
I got what I want with the minimal knowledge of programming.
Here is the code, just in case someone is interested in trimming it.


#pragma rtGlobals=3		// Use modern global access method.

Menu "Macros"
	"Read_CM_Peak_MultiThreads", ThreadAtATimeDemo()
End

// These control various troubleshooting items and other aspects of the demonstration
Constant kNumDatasetsToProcess = 10 	// Number of sample input waves to create and process
Constant kSampleWaveNumPoints = 10000		// Number of points in each sample input wave
Constant kPrintStartThreadMessage = 1
Constant kPrintGotThreadDFMessage = 1
Constant kSimulateVaryingComputationTime = 1

ThreadSafe Function ThreadWorker(wIn, waveIndex)
	WAVE wIn
	Variable waveIndex
	String NameWave = NameofWave(wIn)
  Wavestats/q/z wIn
	variable xPeak = V_maxloc
	Variable i,n=numpnts(wIn), massTimesX=0
	for(i=0; i<n; i+=1)
		massTimesX += wIn[i]*pnt2x(wIn,i)
	endfor
	Variable totalMass=sum(wIn)
	Variable centerOfMass= massTimesX/totalMass
  //     printf "Center of Mass: %g", centerofMass
//return centerOfMass


	// This is used to simulate varying computation time
	if (kSimulateVaryingComputationTime > 0)
		Variable randomSecs = abs(enoise(kSimulateVaryingComputationTime))
		Sleep/S randomSecs
	endif
	
	//Variable wMin = WaveMin(wIn)
	//Variable wMax = WaveMax(wIn)
	
	// Create data folder to return to calling thread
	NewDataFolder/S output
	
	// Create output variables
	// Variable/G gMin = wMin
	Variable/G gcenterOfMass =centerOfMass
	Variable/G gxPeak = xPeak
      String/G gNameWave=NameWave
	
	// This tells the calling thread which wave was processed
	Variable/G gWaveIndex = waveIndex
	
	// Send data back to main thread
	ThreadGroupPutDF 0, :
	
	return 0		// Success
End


Function ThreadAtATimeDemo()
	if (IgorVersion() < 6.23)
		Abort "This demo requires Igor Pro 6.23 or later."
	endif

	Variable t0 = StopMSTimer(-2)		// Used to time the function

	DFREF originalDFR = GetDataFolderDFR()

	DFREF outputDFR = GetDataFolderDFR()

	Variable numDatasetsToProcess = kNumDatasetsToProcess
	Variable numDatasetsProcessed = 0
	
	// Make output wave
	Make/O/D/N=(numDatasetsToProcess,2)  outputDFR:results = NaN
	wave results= outputDFR:results
	SetDimLabel 1,0,CenterOfMass,results
	SetDimLabel 1,1,Peak,results
	
	make/O /T/N=(numDatasetsToProcess)  outputDFR:resultstext
	Wave/t resultstext = outputDFR:resultstext
     // SetDimLabel 0,0,name,resultstext
            
     // Make/T/N=(numpnts(numWave)) textWave = num2str(numWave)
     // str2num
      
	// Create output table
	DoWindow /F OutputTable
	if (V_flag == 0)
		Edit /N=OutputTable /W=(466,49,906,652) results.ld
		Edit/N=OutputTableText resultstext
	endif

	// Look for sample data
	Variable numPointsInSampleData = kSampleWaveNumPoints
//	NewDataFolder /O :SampleData

	DFREF inputDFR = :
	String name 
	Variable i
	for(i=0; i<numDatasetsToProcess; i+=1)
	
	sprintf name, "(%d)", i		// wave0, wave1
	//	Make/O/D/N=(numPointsInSampleData) inputDFR:$name = gnoise(1)
		SetDimLabel 0,i,$name,results
	endfor


	// Create threads
	Variable numThreads = ThreadProcessorCount
	Variable threadGroupID = ThreadGroupCreate(numThreads)
	
	SetDataFolder inputDFR		// Needed for WaveRefIndexed
	
	// Dispatch threads and collect output
	Variable threadIndex
    Variable waveIndex = 0
	do
		// Start any free threads
		do
			if (waveIndex >= numDatasetsToProcess)
				break								// No more input data to dispatch to a thread
			endif
			
			// Find a free thread
			threadIndex = ThreadGroupWait(threadGroupID, -2)		// Requires Igor Pro 6.23
			threadIndex -= 1	// Because ThreadGroupWait returns threadIndex+1
			if (threadIndex < 0)
				break			// No free threads
			endif
		
			// Start thread
			Wave wIn = WaveRefIndexed("", waveIndex, 4)

			ThreadStart threadGroupID, threadIndex, ThreadWorker(wIn, waveIndex)
			if (kPrintStartThreadMessage)
				Printf "Started thread %d\r", threadIndex		// For debugging only
			endif
			waveIndex += 1
		while(1)
		
		// See if thread output is available
		DFREF dfr = ThreadGroupGetDFR(threadGroupID, 0)
		if (DataFolderRefStatus(dfr) != 0)
			// Process results
			NVAR gcenterOfMass = dfr:gcenterOfMass
			NVAR gxPeak = dfr:gxPeak
			SVAR gNameWave= dfr:gNameWave
			NVAR gWaveIndex = dfr:gWaveIndex
		   
		
			results[gWaveIndex][0] = gcenterOfMass
			results[gWaveIndex][1] = gxPeak
		  resultstext[gWaveIndex][0] =gNameWave
			// Update the output table
			DoUpdate

			// For debugging only
			if (kPrintGotThreadDFMessage)
				Printf "Got data for wave %d: CenterOfMass=%g, Peak=%g\r", gWaveIndex, gcenterOfMass, gxPeak
			endif
			
			numDatasetsProcessed += 1
			
			// This is a free data folder that would be killed automatically by Igor.
			// Nonetheless we explicitly kill it here and now.
			KillDataFolder dfr
		endif
	while(numDatasetsProcessed < numDatasetsToProcess)
		
	Variable dummy = ThreadGroupRelease(threadGroupID)
	
	Variable t1 = StopMSTimer(-2)
	Variable elapsedTime = (t1 - t0) / 1E6
	Printf "Finished ThreadAtATimeDemo in %.2f seconds.\r", elapsedTime

	SetDataFolder originalDFR
End

Function CleanupExperiment()	// We call this to prepare the experiment for shipping
	DoWindow /K OutputTable			// The table is recreated by the demo
	DoWindow/K OutputTabletext
	KillWaves/Z results					// Output wave is recreated by the demo
	KillDataFolder /Z root:SampleData	// Sample data is recreated by the demo
End

Another approach (instead of using two waves one for numeric results and one for text) is to create your results wave as a text wave and write the numeric values to it using either sprintf or num2str. How you will use the results determines whether this approach is appropriate. If you need the values for further calculations, then this will probably end up being more trouble than it's worth.
jtigor wrote: Another approach (instead of using two waves one for numeric results and one for text) is to create your results wave as a text wave and write the numeric values to it using either sprintf or num2str. How you will use the results determines whether this approach is appropriate. If you need the values for further calculations, then this will probably end up being more trouble than it's worth.


Hi jtigor,
Obtaining such values have made my life so much easier!!!
I see your point. I will try to change the output into string using num2str. If I got stuck in doing such changes, I will seek help here.

Thanks!
jtigor wrote: Another approach (instead of using two waves one for numeric results and one for text) is to create your results wave as a text wave and write the numeric values to it using either sprintf or num2str. How you will use the results determines whether this approach is appropriate. If you need the values for further calculations, then this will probably end up being more trouble than it's worth.


This can be a good technique. I think it's worth pointing out that when transmitting values via text you have to be *very* careful that you preserve the necessary precision of the numbers. A round-trip through num2str/str2num will truncate the values to 6 digits.

The num-string-num conversions are also slow. Since you are going to the trouble of writing threaded code, I presume speed is important to you.

As jtigor says, how you use the results is a crucial consideration.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Perhaps you could replace the text wave of names with a string variable. This ...


if (DataFolderRefStatus(dfr) != 0)
// Process results
	NVAR gcenterOfMass = dfr:gcenterOfMass
	NVAR gxPeak = dfr:gxPeak
	SVAR gNameWave= dfr:gNameWave
	NVAR gWaveIndex = dfr:gWaveIndex
 
 
	results[gWaveIndex][0] = gcenterOfMass
	results[gWaveIndex][1] = gxPeak
	resultstext[gWaveIndex][0] =gNameWave


... becomes this ...


// create results as a 2 column matrix
Make/O/D/N=(numDatasetsToProcess,2)  outputDFR:results = NaN
// create gListInfo to store content in the same place that you create gCenterOfMass
// make sure it is initialized to be blank
String/G gListInfo = ""

if (DataFolderRefStatus(dfr) != 0)
// Process results
	NVAR/DFREF=dfr gcenterOfMass, gxPeak, gWaveIndex
	SVAR/DFREF=dfr gNameWave, gListInfo   // create gListInfo when you create gNameWave
	results[gWaveIndex][0] = gcenterOfMass
	results[gWaveIndex][1] = gxPeak
	gListInfo += num2str(gWaveIndex) + "=" + gNameWave + ";" // one option with num2str (use this or below, not both!)
	sprintf("%s%d=%s;",gListInfo,gWaveIndex,gNameWave) // alternative with sprint (use this or above, not both!)


Your processing afterward is then a case of extracting the keyword=value set from gListInfo.

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville