Is it possible to Setscale by Wavelist
LE1202
Hi
I'm trying to make my program more flexibility, I've got some data with many layer.
I wrote my code like following code in the first time, but if the height of layer change, I have to change all numbers in code by hand, is it possible to Setscale by Wavelist or some other function?
setscale/I x,Dates[0],Dates[(numpnts(Dates)-1)],"dat", Spd196,Spd176,Spd156,Spd136,Spd116,Spd96,Spd76,Spd56,Spd36,Spd16
setscale/I x,Dates[0],Dates[(numpnts(Dates)-1)],"dat",Dir196,Dir176,Dir156,Dir136,Dir116,Dir96,Dir76,Dir56,Dir36,Dir16
Are you writing your own procedures? It is very easy to loop trough waves or pick from a list of waves with WaveList.
Here is a start:
variable i
for (i=0;i<ItemsinList(AllWavesInFolder); i+=1)
wave workwave = StringFromList(i, AllWavesInFolder)
setscale/I x,Dates[0],Dates[(numpnts(Dates)-1)],"dat", workwave
endfor
or
for (i=startvalue;i<=endvalue; i+=1)
string baseName = "Spd" + i // may use sprintf for more controlled output, e.g. to get Spd001
wave workwave = $baseName
setscale/I x,Dates[0],Dates[(numpnts(Dates)-1)],"dat", workwave
endfor
January 31, 2019 at 04:30 am - Permalink
In reply to Are you writing your own… by chozo
I agree that it would be nice if this and a few other functions could take in a string list. A route I sometimes take, when I don't want to go write a whole function for a few special cases, is to use the function at the bottom of this post. The upside is that you don't have to write code, though you would have to copy that function into a Procedure file and have it compiled in the instance of Igor. Then you could run a command like the following:
String wavesToSet="Spd196,Spd176,Spd156,Spd136,Spd116,Spd96,Spd76,Spd56,Spd36,Spd16"
list_operation_g("setscale/I x,Dates[0],Dates[(numpnts(Dates)-1)],\"dat\",%s",wavesToSet,delim=",") //note: delim would be unnecessary if using semi-colons to delimit the list
//and substituting any %i with the current list index, then executing macroStr
function list_operation_g(macroStr,strList,[start,num,delim,iterateWaveColInstead])
String macroStr //macro to execute e.g, display/k=1 %s to plot waves in list
String strList //list to iterate over (e.g., names of waves)
Variable start,num //for specifying a subrange of strList
variable iterateWaveColInstead //optionally pass to iterate down a wave column, column number is passed and wave name is in strList.. pass -1 to use row labels
String delim //expects semi-colon delimited strList, pass to use another delimiter
String delimUsed
if (ParamIsDefault(delim))
delimUsed=";"
else
delimUsed=delim
endif
Variable i,ind; String executeStr, listStr
if (!ParamIsDefault(iterateWaveColInstead) && !numtype(iterateWaveColInstead) && (iterateWaveColInstead>-2))
String ref=strList
WAVE/T wv=$strList
strList=""
Variable rows=dimsize(wv,0)
if (iterateWaveColInstead < 0) //==-1 so row labels
for (i=0;i<rows;i+=1)
strList+=getdimlabel(wv,0,i)+delimUsed
endfor
else
for (i=0;i<rows;i+=1)
strList+=wv[i][iterateWaveColInstead]+delimUsed
endfor
endif
endif
Variable startInd = ParamIsDefault(start) ? 0 : start
Variable numItems=ItemsInList(strList)
Variable maxItems=numItems-startInd
Variable numInds = ParamISDefault(num) ? maxItems : min(startInd+num,maxItems)
for (i=0;i<numInds;i+=1)
ind=i+startInd
listStr=stringfromlist(ind,strList,delimUsed)
executeStr = replacestring("%s",macroStr,listStr)
executeStr = replacestring("%i",executeStr,num2str(i))
Execute/q executeStr
endfor
end
January 31, 2019 at 03:31 pm - Permalink
Thank you for your advices, function is still new to me, I usually use macro to write procedures, I'll take my time to study how to write function, thanks again.
January 31, 2019 at 05:19 pm - Permalink
In reply to Are you writing your own… by chozo
I try to write a loop in function, but program return "expected assignment operator" error to me, which point at StringFromList(num,strList), did I wrote something wrong ?
January 31, 2019 at 05:51 pm - Permalink
In reply to I try to write a loop in… by LE1202
One issue is that a $ is needed:
January 31, 2019 at 07:11 pm - Permalink
In reply to One issue is that a $ is… by gsb
Thanks for your help, I'll check my program carefully.
January 31, 2019 at 09:13 pm - Permalink
Here is another way to do it, which creates a wave-reference wave and runs an operation on all waves in the wave-reference wave.
// Runs SetScale on all waves in root:
// Looks for waves in root:
DFREF Folder=root:
// Counts the number of waves in the folder
Variable n=CountObjectsDFR(Folder, 1)
// Creates a list of all waves in the folder
// WaveList would give you the same information,
// but as a string list instead of a wave-reference wave
Make/FREE/O/WAVE/N=(n) AllWaves=WaveRefIndexedDFR(Folder, p)
// Runs SetScale on all waves in AllWaves. You could replace Start,
// Delta and UnitStr with waves to use different values for the different waves
Variable Start=10
Variable Delta=2
String UnitStr="Apples"
AllWaves[]=MySetScale(Start, Delta, UnitStr, AllWaves[p])
// This could also be done with a for loop
end
Function/WAVE MySetScale(Start, Delta, UnitStr, MyWave)
Variable Start, Delta
String UnitStr
Wave MyWave
// Runs SetScale on MyWave
SetScale/P x, Start, Delta, UnitStr, MyWave
// Allows the function to work without a for loop
Return MyWave
end
February 1, 2019 at 02:43 am - Permalink
olelytken's approach of using WAVE reference waves is, in my opinion, the "right" way to do this. If the list of waves ever gets very large, you will get much better performance if you only need to look up the wave from a name once and then use those wave references for the rest of the work.
In Igor 7 and later, you can use the ListToWaveRefWave function if you have a string list of wave names, such as what you might get from WaveList, or in gsb's example above.
As a bonus, olelytken's code above could be improved slightly by declaring MySetScale as ThreadSafe and then using the MultiThread keyword in the wave assignment statement in Test(). Here's the modified code:
// Runs SetScale on all waves in root:
// Looks for waves in root:
DFREF Folder=root:
// Counts the number of waves in the folder
Variable n=CountObjectsDFR(Folder, 1)
// Creates a list of all waves in the folder
// WaveList would give you the same information,
// but as a string list instead of a wave-reference wave
Make/FREE/O/WAVE/N=(n) AllWaves=WaveRefIndexedDFR(Folder, p)
// Runs SetScale on all waves in AllWaves. You could replace Start,
// Delta and UnitStr with waves to use different values for the different waves
Variable Start=10
Variable Delta=2
String UnitStr="Apples"
Multithread AllWaves[]=MySetScale(Start, Delta, UnitStr, AllWaves[p])
// This could also be done with a for loop
end
ThreadSafe Function/WAVE MySetScale(Start, Delta, UnitStr, MyWave)
Variable Start, Delta
String UnitStr
Wave MyWave
// Runs SetScale on MyWave
SetScale/P x, Start, Delta, UnitStr, MyWave
// Allows the function to work without a for loop
Return MyWave
end
February 1, 2019 at 09:02 am - Permalink
Ooops, forgot the $ in my original post. So much for not testing my suggestions. It's probably a bit too late but anyway, if you want to read more about this execute in the command line:
DisplayHelpTopic "Converting a String into a Reference Using $"
February 4, 2019 at 06:20 pm - Permalink