LoadWave with .ibw files

I'm using LoadWave to import .ibw files.  The name of the wave is stored in the file and as far as I could see the /A or /N flags apparently don't work for this format, I can only use /O to force overwriting the existing wave if any. But what if I don't remember what the wave name was when the file was created ? (I'm dealing with lots of different 4D waves created by other experiments). I guess there should be a programmatic way to know it (apart from parsing somehow the history record after loading) or change the destination wave name but I don't find it.

I'm still using Igor 8, my apologies if this was addressed in a newer version, anyway I will upgrade soon :)
 

Perhaps one of these options might solve your problem.

* Load into a temporary folder, find the name, and process?

* Parse the .ibw file in a line-by-line manner to obtain the name before loading?

 

Load into a temporary folder, find the name, and process?

Yes, this is an option to explore

Parse the .ibw file in a line-by-line manner to obtain the name before loading?

Well, then I could as well define my own binary format without relying on .ibw ... :)  Actually the reason I want to stick to .ibw is that the loading is fast (my files are several Gb), apparently faster than other formats (hdf5, raw binary). For me .ibw is a good format, the problem of wave name handling by LoadWave appears as a minor shortcoming that could be easily corrected by WM.  At the moment I'm rewriting all my old code so as to save all .ibw  with the same wave name but it's stupid.

 

 

 

 

 

So the idea is to read the wave name without actually loading the file? As a little exercise, I went ahead and did the bit peeking. This script should be able to read the wave names of all ibw file versions (see also the attached file):

function/S readIBWname(string path)
    int fileID, version
    Open/Z/R fileID as path
    if (V_flag != 0)
        return ""
    endif
    
    FBinRead/B=3/F=2/U fileID, version
    int length = 20 + 12*(version>3)
    int offset =  6 + 8*(version==1) + 16*(version==2) + 20*(version==3) + (64 + 22)*(version>3)
    if (version > 5)
        FSetPos fileID, 56
        FBinRead/B=3/F=2/U fileID, length
        FStatus fileID
        offset = V_logEOF-length
    endif
    
    string name = PadString("", length, char2num(" "))
    FSetPos  fileID, offset
    FBinRead fileID, name
    
    Close fileID
    return UnpadString(name,0)
end

Use via e.g.:

print readIBWname("pathToAFileOnDisk")
read IBW names_0.ipf (702 bytes)

Wow, thanks! And my apologies to jjweimer for not having taken seriously his second suggestion, I didn't have the courage to try reverse engineering of the ibw structure.

Where did you get the info about different versions ?

 

I'm now using it like this:

function loadibw(string path, string destname)
 
LoadWave/O path
 
string ibwname=readIBWname(path)
 
if(cmpstr(ibwname, destname)!=0)
    print "ibw wave:", ibwname, "->", destname
    killwaves/z $destname
    rename $ibwname, $destname
endif    
    
end

 

You can get all the details about the structure of ibw files from the technical note #003 and the file-write header. See here:

C:\Program Files\WaveMetrics\Igor Pro XX Folder\Technical Notes\Igor Tech Notes\TN003 Igor binary format\TN003.ifn

C:\Program Files\WaveMetrics\Igor Pro XX Folder\Technical Notes\Igor Pro Tech Notes\PTN003 Writing Packed Files\Source\IgorBin.h

So you are loading the wave anyway in your code? If you use LoadWave, why don't you grab the loaded wave name from S_waveNames then? Like this:

LoadWave/O path
// string ibwname=readIBWname(path)
string ibwname=StringFromList(0,S_waveNames)

EDIT: I also strongly advise against code like this:

killwaves/z $destname
rename $ibwname, $destname

This is destined to fail if $destname is, e.g., plotted in a graph. What you want instead is:

Duplicate/O $ibwname, $destname

"So you are loading the wave anyway in your code? If you use LoadWave, why don't you grab the loaded wave name from S_waveNames then?"

Oops, apparently I did not read the manual to the end :(, now I did:

LoadWave sets the following variables:
V_flag        Number of waves loaded.
S_fileName    Name of the file being loaded.
S_path        File system path to the folder containing the file.
S_waveNames    Semicolon-separated list of the names of loaded waves.

Sorry for having bothered you all with this apparently trivial question, maybe my formulation wasn't clear enough so you did not point out the solution immediately. That said your functions will be very useful for me, on other occasions.  

"I also strongly advise against code like this:"

Yes I agree, I also started with duplicate then modified it this way when started to handle huge (several Gb) waves,  worrying that making another copy it might sometime run out of RAM space... 

So the final (and safe) code would be like:

function loadibw(string path, string destname)
 
LoadWave/O path
 
string ibwname=stringfromlist(0,S_waveNames) 
 
if(cmpstr(ibwname, destname)!=0)
    print "ibw wave:", ibwname, "->", destname
    Duplicate/O $ibwname, $destname
    killwaves $ibwname
endif    
    
end

 

Good that this has been solved. If anything, this exercise should give you a good starting point for parsing npy files in your other thread. You just would need to follow the format definition and attack the header via FBinRead. Then, when you have all the dimensions and data types at hand, load the core data via GBLaodWave from the npy file. I could give it a try, but I don't have an useful example and also already had my fix of bit hacking for today.

 I could give it a try, but I don't have an useful example and also already had my fix of bit hacking for today.

No worry, I also love hacking (when I have time - teaching already takes more than half of it ...) but at this time I'm happy to have a working solution to the file handling problem and can finally get to do some physics with the data. 
I've got tens of thousands of X-ray images and have to think how to process them and what information can be extracted (some modelling but the models I had tried so far are not quite good yet, also look at inter-image correlations etc.).  I'm sure I will need some hacking to optimize the code (e.g. some parts can be much faster on GPU) so as to have my codes running in reasonable time.
Thanks again for your help.