Convert a 3-columns data stored in a string to 3 waves
maru
I executed a shell command using Igor. The result will be stored in a string S_value as a 3-columns data; each column has a header.
LoadWave has plenty of options to import data in text files to waves.
I wonder if there is a similar function I can use to import data in a string to waves.
Currently, I am using a for loop to retrieve the three values in each row and assign them to the corresponding waves.
Is there a better idea to convert the formated string (with numeric data) to waves?
You could use code like this to write the string to a temporary file and then use LoadWave to load the data.
Since you already have a solution, I recommend using the temporary file approach only if you have so much data in the string that your current approach takes a significant amount of time.
April 12, 2022 at 08:05 am - Permalink
It is not really clear to me what you are trying to do (the string contains data as 3 x 3 matrix, i.e., 3 rows x 3 columns?) but maybe you are looking for this function: ListToTextWave(). This function converts a string list to a wave. You then have another line to convert the text wave to a numerical wave.
April 12, 2022 at 08:44 am - Permalink
My data stored in the string looks like:
column1, column2, column3,
1, 2, 3,
5, 1, 2
...
Each columns may contain 1000 values.
And here is my current code.
Make/O/N=(numItems) yy, ee, xx
string line
variable i
For(i=0; i<numItems; i++)
line = StringFromList(i, S_value, "\r")
yy[i] = str2num(StringFromlist(0, line, ","))
ee[i] = str2num(StringFromlist(1, line, ","))
xx[i] = str2num(StringFromlist(2, line, ","))
Endfor
Writing the string to a temporary file sounds a good workaround. Thank you.
ListToTextWave() will convert the string list to a text wave.
However, each element in the textwave will contain 3 text values separated by ",".
I guess I need to use StringFromList to get these values just as my current code.
April 12, 2022 at 05:23 pm - Permalink
Here is how you can do it by writing the string to a temp file and then using LoadWave:
String dataStr // Contains data
String columnInfoStr // Contains string for /B flag or ""
String fileName = "TempDataFile.csv"
Variable refNum
Open/P=IgorUserFiles refNum as fileName
FBinWrite refNum, dataStr
Close refNum
LoadWave/G/O/D/P=IgorUserFiles/A/B=columnInfoStr fileName
DeleteFile/P=IgorUserFiles fileName
End
Function Demo()
String dataStr = ""
dataStr += "1,2,3\r"
dataStr += "2,3,4\r"
dataStr += "3,4,5\r"
String columnInfoStr = "N=yy;N=ee;N=xx;"
LoadFromTempFile(dataStr, columnInfoStr)
End
April 12, 2022 at 05:57 pm - Permalink
Do you want to have each column in a separate wave? How about this, which creates a 2D wave (assumes that each value is terminated by a comma and that you have three columns; you can of course check for all that):
Wave/T textW = ListToTextWave(ReplaceString("\r",in,""),",")
Make/O/D/N=(numpnts(textW)/3,3) numW = str2num(textW[3*p+q])
End
EDIT: Here the code including Howard's demo (note that this is slightly different, since here the last value in each row is not terminated with a comma):
Wave/T textW = ListToTextWave(ReplaceString("\r",in,","),",")
Make/O/D/N=(numpnts(textW)/3,3) numW = str2num(textW[3*p+q])
End
Function Demo()
String dataStr = ""
dataStr += "1,2,3\r"
dataStr += "2,3,4\r"
dataStr += "3,4,5\r"
StringToWave(dataStr)
End
April 12, 2022 at 06:00 pm - Permalink
Thank you very much! Both suggestions worked perfectly.
April 12, 2022 at 08:13 pm - Permalink
In reply to Thank you very much! Both… by maru
A somewhat cumbersome alternative that uses LoadWave is to get the string data to the clipboard and use this as the 'filename'. I struggled to find a neat way of doing this, but found a workaround going via a notebook and invoking the Edit-Copy menu:
String dataStr = ""
dataStr += "C1,C2,C3\r"
dataStr += "1,2,3\r"
dataStr += "2,3,4\r"
dataStr += "3,4,5\r"
NewNotebook /F=0/N=TempNB
Notebook TempNB text=dataStr
Notebook TempNB selection={startOfFile, endOfFile}
DoIgorMenu "Edit", "Copy"
KillWindow TempNB
LoadWave/A/J/D/W/K=0 "Clipboard"
End
This has the (perhaps unnecessary) advantage of not needing to know about the separators in the data.
April 13, 2022 at 01:06 am - Permalink
Here is a simpler version of KurtB's solution:
String dataStr = ""
dataStr += "C1,C2,C3\r"
dataStr += "1,2,3\r"
dataStr += "2,3,4\r"
dataStr += "3,4,5\r"
PutScrapText dataStr
LoadWave/A/J/D/W/K=0 "Clipboard"
End
April 13, 2022 at 04:41 am - Permalink
In reply to Here is a simpler version of… by hrodstein
Thank you Howard,
I had failed to find PutScrapText. Much easier than going via the Notebook!
Cheers, Kurt
April 13, 2022 at 04:52 am - Permalink
I never thought using clipboard. Great idea. Thank you!
April 13, 2022 at 04:30 pm - Permalink