Convert a 3-columns data stored in a string to 3 waves

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.

 

 

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.

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.

variable numItems = ItemsInList(S_value, "\r")
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.

Here is how you can do it by writing the string to a temp file and then using LoadWave:

Function LoadFromTempFile(dataStr, columnInfoStr)
    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

 

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):

Function StringToWave(String in)
    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):

Function StringToWave(String in)
    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

 

In reply to 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:

Function Demo()
    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.

 

Here is a simpler version of KurtB's solution:

Function Demo()
    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

 

In reply to by hrodstein

hrodstein wrote:

Here is a simpler version of KurtB's solution:

Function Demo()
    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

 

Thank you Howard,

I had failed to find PutScrapText. Much easier than going via the Notebook!

Cheers, Kurt