Changeset 938


Ignore:
Timestamp:
May 14, 2020 4:33:07 PM (3 years ago)
Author:
ilavsky
Message:

Igor 9 related changes

Location:
trunk/User Procedures
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/User Procedures/CanSAS/HDF5gateway.ipf

    r803 r938  
    22#pragma version=1.01
    33
     4#if(IgorVersion()<9)    //no need to include, Igor 9 has this by default. 
    45#include <HDF5 Browser>
    5 
     6#endif
    67
    78//1.01 rmoeved KillWaves/Z which took surprisngly long time. Not needed.
     
    939940        endif
    940941
     942        Variable err
    941943        if ( 0 )
    942944                STRUCT HDF5DataInfo di  // Defined in HDF5 Browser.ipf.
    943945                InitHDF5DataInfo(di)    // Initialize structure.
     946#if(IgorVersion()<9)
    944947                HDF5AttributeInfo(fileID, "/", 1, "file_name", 0, di)
     948#else
     949                err = HDF5AttributeInfo(fileID, "/", 1, "file_name", 0, di)
     950#endif         
    945951                Print di
    946952        endif
     
    949955        String/G file_path = S_path
    950956        String/G file_name = fileName
     957
    951958        return fileID
    952959End
  • trunk/User Procedures/CanSAS/IRNI_NexusSupport.ipf

    r893 r938  
    582582                endif
    583583        endfor
    584         //HDf5Browser#LoadGroupButtonProc("LoadGroup")
    585        
    586         //HDf5Browser#CloseFileButtonProc("CloseFIle")
    587        
    588         //KillWindow $(browserName)
     584
    589585end
    590586
  • trunk/User Procedures/Indra 2/IN2_GeneralProcedures.ipf

    r936 r938  
    11IN2G_FindNu#pragma rtGlobals=2          // Use modern global access method.
    2 #pragma version = 2.22
     2#pragma version = 2.23
    33#pragma IgorVersion = 7.05
    44
     
    3535//*************************************************************************/
    3636//
     37//2.23 add IN2G_AddButtonsToBrowser(), which calls IN2G_ExtractInfoFromFldrname(). Use: adds button (via hooks functions) tgo DataBrowser and that will extract info from SampleName strings we are using.
    3738//2.22 minor fix to IN2G_ColorTopGrphRainbow
    3839                //added         IN2G_RemoveDataFromGraph(topGraphStr = "IRB1_ATSASInterfacePanel#DataDisplay")
     
    507508End
    508509
     510//Does not seem we can modify DataBrowser right clcik menu...
     511//Menu "DataBrowser"
     512//              "Samplenames-to-Values", IN2G_ExtractInfoFromFldrname()
     513//end
     514
     515//here is add to Browser button, it will be in after compile hooks.
     516Function IN2G_AddButtonsToBrowser()
     517
     518        ModifyBrowser appendUserButton={'SampleName-to-Values',"IN2G_ExtractInfoFromFldrname()"}
     519
     520end
     521//************************************************************************************************
     522//************************************************************************************************
     523
    509524Function IN2G_SaveTopGraphJpg()
    510525                string topWindow=WinName(0,1)
     
    514529                string topWindow=WinName(0,1)
    515530                SaveGraphCopy /I /W=$(topWindow)                                                //this is pxp
     531end
     532
     533
     534//************************************************************************************************
     535//************************************************************************************************
     536
     537Function IN2G_ExtractInfoFromFldrname()
     538
     539        string SelectedWaveNm=GetBrowserSelection (0, 1)
     540        if(strlen(SelectedWaveNm)<=3)           //path must contain at least "root:"
     541                        return 0
     542        endif
     543                //check for wave type, need string wave with foldernames...
     544        if(WaveType($(SelectedWaveNm),1)!=2)            //not text wave, bail out...
     545                        return 0
     546        endif
     547        Wave/T SampleName = $(SelectedWaveNm)
     548        if(WaveDims(SampleName)!=1)                     //thsi is not 1D array of somethign, which should be names.
     549                return 0
     550        endif
     551        variable i, imax=numpnts(SampleName)
     552       
     553        DFref oldDf=GetDataFolderDFR()
     554        setDataFolder GetWavesDataFolderDFR(SampleName)
     555        make/O/N=(imax) TimeWave, TemperatureWave, PercentWave, OrderWave
     556        String DataFolderName
     557        For(i=0;i<imax;i+=1)
     558                DataFolderName = SampleName[i]
     559                TimeWave[i]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     560                TemperatureWave[i]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     561                PercentWave[i]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     562                OrderWave[i]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
     563        endfor
     564        //clean up and leave only thoser who contain some numbers in tehm.
     565        string ReportExisting=""
     566        if(sum(TimeWave)<=0 || numtype(sum(TimeWave))!=0)
     567                KillWaves  TimeWave
     568        else
     569                ReportExisting+= " TimeWave;"
     570        endif
     571        if(sum(TemperatureWave)<=0 || numtype(sum(TemperatureWave))!=0)
     572                KillWaves  TemperatureWave
     573        else
     574                ReportExisting+= " TemperatureWave;"
     575        endif
     576        if(sum(PercentWave)<=0|| numtype(sum(PercentWave))!=0)
     577                KillWaves  PercentWave
     578        else
     579                ReportExisting+= " PercentWave;"
     580        endif
     581        if(sum(OrderWave)<=0|| numtype(sum(OrderWave))!=0)
     582                KillWaves  OrderWave
     583        else
     584                ReportExisting+= " OrderWave;"
     585        endif
     586        print "Processed wave :"+SelectedWaveNm
     587        print "Extracted following data from names :"+ReportExisting
     588       
     589        setDataFolder oldDf
     590end
     591
     592//**********************************************************************************************************
     593
     594
     595Function IN2G_IdentifyNameComponent(NameStr, whichComp)
     596                string NameStr, whichComp               //"_xyzC",  _xyzmin, _xyzpct, _xyz
     597               
     598                string NameStrLoc=StringFromList(ItemsInList(NameStr, ":")-1, NameStr, ":"  )
     599                string result="", tmpStr
     600                variable i
     601                if(StringMatch(whichComp, "_xyz"))
     602                        FOr(i=ItemsInList(NameStrLoc, "_")-1;i>=0;i-=1)
     603                                tmpStr = StringFromList(i, NameStrLoc, "_")
     604                                if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$"))
     605                                        return str2num(tmpStr)
     606                                endif
     607                        endfor
     608                endif
     609                FOr(i=0;i<ItemsInList(NameStrLoc, "_");i+=1)
     610                        tmpStr = StringFromList(i, NameStrLoc, "_")
     611                        strswitch(whichComp)                                    // string switch
     612                                case "_xyzC":                                           // execute if case matches expression
     613                                        if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+C$" ))
     614                                                return str2num(tmpStr)
     615                                        endif
     616                                        break                                                   // exit from switch
     617                                case "_xyzmin": // execute if case matches expression
     618                                        if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+min$" ))
     619                                                return str2num(tmpStr)
     620                                        endif
     621                                        break
     622                                case "_xyzpct": // execute if case matches expression
     623                                        if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+pct$" ))
     624                                                return str2num(tmpStr)
     625                                        endif
     626                                        break
     627                        endswitch               
     628                endfor
     629        return Nan
    516630end
    517631
  • trunk/User Procedures/Indra 2/IN2_Load Indra 2.ipf

    r854 r938  
    6262#include "::CanSAS:IRNI_NexusSupport", version>=1.14
    6363
     64#if(IgorVersion()<9)    //no need to include, Igor 9 has this by default. 
    6465#include <HDF5 Browser>
     66#endif
    6567
     68
  • trunk/User Procedures/Indra 2/IN2_USAXS.ipf

    r933 r938  
    182182        IN2G_CheckPlatformGUIFonts()
    183183        IN2G_ResetSizesForALlPanels(WindowProcNames)
     184        IN2G_AddButtonsToBrowser()              //adds button to DataBrowser.
     185
    184186        //and print in history which version of codeis being used for future reference.
    185187        string file= StringFromList((ItemsInList(FunctionPath("LoadUSAXSMacros"), ":")-1), FunctionPath("LoadUSAXSMacros"), ":")
  • trunk/User Procedures/Indra 2/IN3_Calculations.ipf

    r870 r938  
    27852785       
    27862786        Silent 1       
     2787        //Duplicate FitIntensity, root:FitIntensityOrig, root:DSMErrorsOrig
     2788        //Duplicate Qvector, root:QvectorOrig
     2789       
    27872790       
    27882791        DsmErrors=FitIntensity*(SmErrors/SmIntensity)                                           //error proportional to input data
     
    27902793        variable i=1, imax=numpnts(FitIntensity)
    27912794        Redimension/N=(numpnts(FitIntensity)) DsmErrors
     2795        Variable start = StopMSTimer(-2)
    27922796        Do
    27932797                if( (numtype(FitIntensity[i-1])==0) && (numtype(FitIntensity[i])==0) && (numtype(FitIntensity[i+1])==0) )
     
    27972801        i+=1
    27982802        while (i<imax-1)
    2799 
     2803        Variable theend = StopMSTimer(-2)
     2804        print "IN3_GetErrors took : "+num2str((theend-start)/100)
    28002805        DsmErrors[0]=DsmErrors[1]                                                                       //some error needed for 1st point
    28012806        DsmErrors[imax-1]=DsmErrors[imax-2]                                                             //and error for last point     
    28022807
    28032808        Smooth /E=2 3, DsmErrors
    2804        
     2809        //abort
    28052810end
    28062811
  • trunk/User Procedures/Indra 2/IN3_FlyScan.ipf

    r848 r938  
    305305                endif
    306306        endif
    307        
     307
    308308        variable i
    309309        string FileName
     
    324324                endif
    325325        endfor
    326         //HDf5Browser#LoadGroupButtonProc("LoadGroup")
    327        
    328         //HDf5Browser#CloseFileButtonProc("CloseFIle")
    329        
    330         //KillWindow $(browserName)
    331326end
    332327
  • trunk/User Procedures/Irena/IR1_ImportData.ipf

    r901 r938  
    22//#pragma rtGlobals=2           // Use modern global access method.
    33#pragma version=2.40
     4
     5#if(IgorVersion()<9)    //no need to include, Igor 9 has this by default. 
    46#include <HDF5 Browser>
     7#endif
     8
     9
    510Constant IR1IversionNumber = 2.37
    611Constant IR1IversionNumber2 = 2.36
     
    31813186                endif
    31823187        endfor
    3183         //HDf5Browser#LoadGroupButtonProc("LoadGroup")
    3184        
    3185         //HDf5Browser#CloseFileButtonProc("CloseFIle")
    3186        
    3187         //KillWindow $(browserName)
    31883188end
    31893189
  • trunk/User Procedures/Irena/IR1_Main.ipf

    r935 r938  
    333333        IN2G_CheckForGraphicsSetting(0)
    334334        IN2G_ResetSizesForALlPanels(WindowProcNames)
     335        IN2G_AddButtonsToBrowser()              //adds button to DataBrowser.
    335336
    336337        //and print in history which version of codeis being used for future reference.
  • trunk/User Procedures/Irena/IR2_DataMiner.ipf

    r935 r938  
    697697                                Wave TmpWv=TemperatureWv
    698698                                Redimension/N=(NumberOfExtractedItems+1) TmpWv
    699                                 TmpWv[NumberOfExtractedItems] = IR3B_IdentifyNameComponent(DataFolderName, "_xyzC")
     699                                TmpWv[NumberOfExtractedItems] = IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
    700700                elseif(StringMatch(KeyString, "Extract_xyzmin"))                //_xyzC, _xyzmin, _xyzpct, _xyz
    701701                                Wave/Z TmpWv=TimeWv
     
    705705                                Wave TmpWv=TimeWv
    706706                                Redimension/N=(NumberOfExtractedItems+1) TmpWv
    707                                 TmpWv[NumberOfExtractedItems] = IR3B_IdentifyNameComponent(DataFolderName, "_xyzmin")
     707                                TmpWv[NumberOfExtractedItems] = IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
    708708                elseif(StringMatch(KeyString, "Extract_xyz"))           //_xyzC, _xyzmin, _xyzpct, _xyz
    709709                                Wave/Z TmpWv=OrderWv
     
    713713                                Wave TmpWv=OrderWv
    714714                                Redimension/N=(NumberOfExtractedItems+1) OrderWv
    715                                 TmpWv[NumberOfExtractedItems] = IR3B_IdentifyNameComponent(DataFolderName, "_xyz")
     715                                TmpWv[NumberOfExtractedItems] = IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    716716                elseif(StringMatch(KeyString, "Extract_xyzpct"))                //_xyzC, _xyzmin, _xyzpct, _xyz
    717717                                Wave/Z TmpWv=PercentWv
     
    721721                                Wave TmpWv=PercentWv
    722722                                Redimension/N=(NumberOfExtractedItems+1) PercentWv
    723                                 TmpWv[NumberOfExtractedItems] = IR3B_IdentifyNameComponent(DataFolderName, "_xyzpct")
     723                                TmpWv[NumberOfExtractedItems] = IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
    724724                //done with special name based waves...
    725725                else            ///all others.
     
    764764end
    765765//**********************************************************************************************************
    766 //**********************************************************************************************************
    767 
    768 
    769 static Function IR3B_IdentifyNameComponent(NameStr, whichComp)
    770                 string NameStr, whichComp               //"_xyzC",  _xyzmin, _xyzpct, _xyz
    771                
    772                 string NameStrLoc=StringFromList(ItemsInList(NameStr, ":")-1, NameStr, ":"  )
    773                 string result="", tmpStr
    774                 variable i
    775                 if(StringMatch(whichComp, "_xyz"))
    776                         FOr(i=ItemsInList(NameStrLoc, "_")-1;i>=0;i-=1)
    777                                 tmpStr = StringFromList(i, NameStrLoc, "_")
    778                                 if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$"))
    779                                         return str2num(tmpStr)
    780                                 endif
    781                         endfor
    782                 endif
    783                 FOr(i=0;i<ItemsInList(NameStrLoc, "_");i+=1)
    784                         tmpStr = StringFromList(i, NameStrLoc, "_")
    785                         strswitch(whichComp)                                    // string switch
    786                                 case "_xyzC":                                           // execute if case matches expression
    787                                         if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+C$" ))
    788                                                 return str2num(tmpStr)
    789                                         endif
    790                                         break                                                   // exit from switch
    791                                 case "_xyzmin": // execute if case matches expression
    792                                         if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+min$" ))
    793                                                 return str2num(tmpStr)
    794                                         endif
    795                                         break
    796                                 case "_xyzpct": // execute if case matches expression
    797                                         if(GrepString(tmpStr, "^[-+]?[0-9]*\.?[0-9]+pct$" ))
    798                                                 return str2num(tmpStr)
    799                                         endif
    800                                         break
    801                         endswitch               
    802                 endfor
    803         return Nan
    804 end
    805766//**********************************************************************************************************
    806767//**********************************************************************************************************
  • trunk/User Procedures/Irena/IR3_SimpleFits.ipf

    r932 r938  
    18761876                        Note /K/NOCR ResuldQ, NoteWithResults
    18771877                        break
    1878                 case "Volume Size Distribution":        // nothng to do here...
    1879                         break
    1880                 case "Number Size Distribution":        // nothng to do here...
     1878                case "Volume Size Distribution":        // nothing to do here...
     1879                        break
     1880                case "Number Size Distribution":        // nothing to do here...
    18811881                        break
    18821882                default:                        // optional default expression executed
     
    19401940                Wave/Z GuinierRg
    19411941                if(!WaveExists(GuinierRg))
    1942                         make/O/N=0 GuinierRg, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare
     1942                        make/O/N=0 GuinierRg, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    19431943                        make/O/N=0/T SampleName
    19441944                        SetScale/P x 0,1,"A", GuinierRg
     
    19461946                endif
    19471947                curlength = numpnts(GuinierRg)
    1948                 redimension/N=(curlength+1) SampleName,GuinierRg, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare
     1948                redimension/N=(curlength+1) SampleName,GuinierRg, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    19491949                SampleName[curlength] = DataFolderName
    1950                 GuinierRg[curlength] = Guinier_Rg
    1951                 GuinierI0[curlength] = Guinier_I0
    1952                 GuinierQmin[curlength] = DataQstart
    1953                 GuinierQmax[curlength] = DataQEnd
    1954                 GuinierChiSquare[curlength] = AchievedChiSquare
     1950                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     1951                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     1952                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     1953                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
     1954                GuinierRg[curlength]                            = Guinier_Rg
     1955                GuinierI0[curlength]                            = Guinier_I0
     1956                GuinierQmin[curlength]                  = DataQstart
     1957                GuinierQmax[curlength]                  = DataQEnd
     1958                GuinierChiSquare[curlength]     = AchievedChiSquare
    19551959                IR3J_GetTableWithresults()
    19561960        elseif(stringmatch(SimpleModel,"Guinier Rod"))
     
    19591963                Wave/Z GuinierRc
    19601964                if(!WaveExists(GuinierRc))
    1961                         make/O/N=0 GuinierRc, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare
     1965                        make/O/N=0 GuinierRc, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    19621966                        make/O/N=0/T SampleName
    19631967                        SetScale/P x 0,1,"A", GuinierRc
     
    19651969                endif
    19661970                curlength = numpnts(GuinierRc)
    1967                 redimension/N=(curlength+1) SampleName,GuinierRc, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare
     1971                redimension/N=(curlength+1) SampleName,GuinierRc, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    19681972                SampleName[curlength] = DataFolderName
     1973                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     1974                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     1975                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     1976                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    19691977                GuinierRc[curlength] = Guinier_Rg
    19701978                GuinierI0[curlength] = Guinier_I0
     
    19781986                Wave/Z GuinierTh
    19791987                if(!WaveExists(GuinierTh))
    1980                         make/O/N=0 GuinierTh, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare
     1988                        make/O/N=0 GuinierTh, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    19811989                        make/O/N=0/T SampleName
    19821990                        SetScale/P x 0,1,"A", GuinierTh
     
    19841992                endif
    19851993                curlength = numpnts(GuinierTh)
    1986                 redimension/N=(curlength+1) SampleName,GuinierTh, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare
     1994                redimension/N=(curlength+1) SampleName,GuinierTh, GuinierI0, GuinierQmin, GuinierQmax, GuinierChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    19871995                SampleName[curlength] = DataFolderName
     1996                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     1997                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     1998                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     1999                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    19882000                GuinierTh[curlength] = sqrt(12)*Guinier_Rg
    19892001                GuinierI0[curlength] = Guinier_I0
     
    19972009                Wave/Z PorodConstant
    19982010                if(!WaveExists(PorodConstant))
    1999                         make/O/N=0 PorodConstant, PorodBackground, PorodQmin, PorodQmax, PorodChiSquare
     2011                        make/O/N=0 PorodConstant, PorodBackground, PorodQmin, PorodQmax, PorodChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    20002012                        make/O/N=0/T SampleName
    20012013                        SetScale/P x 0,1,"cm3/A", PorodConstant                 //this may be worng, I suspect
     
    20032015                endif
    20042016                curlength = numpnts(PorodConstant)
    2005                 redimension/N=(curlength+1) SampleName,PorodConstant, PorodBackground, PorodQmin, PorodQmax, PorodChiSquare
     2017                redimension/N=(curlength+1) SampleName,PorodConstant, PorodBackground, PorodQmin, PorodQmax, PorodChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    20062018                SampleName[curlength] = DataFolderName
     2019                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     2020                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     2021                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     2022                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    20072023                PorodConstant[curlength] = Porod_Constant
    20082024                PorodBackground[curlength]=DataBackground
     
    20162032                Wave/Z SphereRadius
    20172033                if(!WaveExists(SphereRadius))
    2018                         make/O/N=0 SphereRadius, SphereScalingFactor, SphereBackground, SphereQmin, SphereQmax, SphereChiSquare
     2034                        make/O/N=0 SphereRadius, SphereScalingFactor, SphereBackground, SphereQmin, SphereQmax, SphereChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    20192035                        make/O/N=0/T SampleName
    20202036                        SetScale/P x 0,1,"A", SphereRadius
     
    20222038                endif
    20232039                curlength = numpnts(SphereRadius)
    2024                 redimension/N=(curlength+1) SampleName,SphereRadius, SphereScalingFactor, SphereBackground, SphereQmin, SphereQmax, SphereChiSquare
     2040                redimension/N=(curlength+1) SampleName,SphereRadius, SphereScalingFactor, SphereBackground, SphereQmin, SphereQmax, SphereChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    20252041                SampleName[curlength] = DataFolderName
     2042                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     2043                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     2044                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     2045                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    20262046                SphereRadius[curlength] = Sphere_Radius
    20272047                SphereScalingFactor[curlength] = Sphere_ScalingConstant
     
    20362056                Wave/Z SpheroidRadius
    20372057                if(!WaveExists(SpheroidRadius))
    2038                         make/O/N=0 SpheroidRadius, SpheroidScalingFactor, SpheroidAspectRatio, SpheroidBackground, SpheroidQmin, SpheroidQmax, SpheroidChiSquare
     2058                        make/O/N=0 SpheroidRadius, SpheroidScalingFactor, SpheroidAspectRatio, SpheroidBackground, SpheroidQmin, SpheroidQmax, SpheroidChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    20392059                        make/O/N=0/T SampleName
    20402060                        SetScale/P x 0,1,"A", SpheroidRadius
     
    20422062                endif
    20432063                curlength = numpnts(SpheroidRadius)
    2044                 redimension/N=(curlength+1) SampleName,SpheroidRadius, SpheroidScalingFactor, SpheroidAspectRatio, SpheroidBackground, SpheroidQmin, SpheroidQmax, SpheroidChiSquare
     2064                redimension/N=(curlength+1) SampleName,SpheroidRadius, SpheroidScalingFactor, SpheroidAspectRatio, SpheroidBackground, SpheroidQmin, SpheroidQmax, SpheroidChiSquare, TimeWave, TemperatureWave, PercentWave, OrderWave
    20452065                SampleName[curlength]                   = DataFolderName
     2066                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     2067                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     2068                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     2069                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    20462070                SpheroidRadius[curlength]                       = Spheroid_Radius
    20472071                SpheroidScalingFactor[curlength] = Spheroid_ScalingConstant
     
    20572081                Wave/Z Rg
    20582082                if(!WaveExists(Rg))
    2059                         make/O/N=0 Rg, VolumeFraction, MeanDiaVolDist, ModeDiaVolDist, MeadianDiaVolDist
     2083                        make/O/N=0 Rg, VolumeFraction, MeanDiaVolDist, ModeDiaVolDist, MeadianDiaVolDist, TimeWave, TemperatureWave, PercentWave, OrderWave
    20602084                        make/O/N=0/T SampleName
    20612085                        SetScale/P x 0,1,"A", Rg, MeanDiaVolDist, ModeDiaVolDist, MeadianDiaVolDist
     
    20632087                endif
    20642088                curlength = numpnts(Rg)
    2065                 redimension/N=(curlength+1) SampleName,Rg, VolumeFraction, MeanDiaVolDist, ModeDiaVolDist, MeadianDiaVolDist
     2089                redimension/N=(curlength+1) SampleName,Rg, VolumeFraction, MeanDiaVolDist, ModeDiaVolDist, MeadianDiaVolDist, TimeWave, TemperatureWave, PercentWave, OrderWave
    20662090                SampleName[curlength]                   = DataFolderName
     2091                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     2092                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     2093                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     2094                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    20672095                Rg[curlength]                                           = VOlSD_Rg
    20682096                VolumeFraction[curlength]               = VolSD_Volume
     
    20772105                Wave/Z NumPartsPercm3
    20782106                if(!WaveExists(NumPartsPercm3))
    2079                         make/O/N=0 NumPartsPercm3, MeanDiaNumDist, ModeDiaNumDist, MeadianDiaNumDist
     2107                        make/O/N=0 NumPartsPercm3, MeanDiaNumDist, ModeDiaNumDist, MeadianDiaNumDist, TimeWave, TemperatureWave, PercentWave, OrderWave
    20802108                        make/O/N=0/T SampleName
    20812109                        SetScale/P x 0,1,"A", MeanDiaNumDist, ModeDiaNumDist, MeadianDiaNumDist
     
    20832111                endif
    20842112                curlength = numpnts(NumPartsPercm3)
    2085                 redimension/N=(curlength+1) SampleName, NumPartsPercm3, MeanDiaNumDist, ModeDiaNumDist, MeadianDiaNumDist
     2113                redimension/N=(curlength+1) SampleName, NumPartsPercm3, MeanDiaNumDist, ModeDiaNumDist, MeadianDiaNumDist, TimeWave, TemperatureWave, PercentWave, OrderWave
    20862114                SampleName[curlength]                   = DataFolderName
     2115                TimeWave[curlength]                             =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzmin")
     2116                TemperatureWave[curlength]      =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzC")
     2117                PercentWave[curlength]                  =       IN2G_IdentifyNameComponent(DataFolderName, "_xyzpct")
     2118                OrderWave[curlength]                            =       IN2G_IdentifyNameComponent(DataFolderName, "_xyz")
    20872119                NumPartsPercm3[curlength]               = NumSD_NumPartPerCm3
    20882120                MeanDiaNumDist[curlength]               = NumSD_MeanDiameter
     
    20912123
    20922124                //IR3J_GetTableWithresults()
     2125        endif
     2126        if(sum(TimeWave)<=0 || numtype(sum(TimeWave))!=0)
     2127                KillWaves/Z  TimeWave
     2128        endif
     2129        if(sum(TemperatureWave)<=0 || numtype(sum(TemperatureWave))!=0)
     2130                KillWaves/Z  TemperatureWave
     2131        endif
     2132        if(sum(PercentWave)<=0|| numtype(sum(PercentWave))!=0)
     2133                KillWaves/Z  PercentWave
     2134        endif
     2135        if(sum(OrderWave)<=0|| numtype(sum(OrderWave))!=0)
     2136                KillWaves/Z  OrderWave
    20932137        endif
    20942138       
  • trunk/User Procedures/Nika/NI1_HDF5Browser.ipf

    r750 r938  
    2424        string CalledFrom,  fileName, PathName
    2525       
     26        abort "General HDF5 load is broken due to Igor 9 code modifications. Remind author to fix it (and send example data set, please)"
    2627        //CalledFrom ... "Nika" or "Irena"
    2728        Wave/Z/T GroupNames=$("root:Packages:"+CalledFrom+"HDF5Loader:GroupNames")
     
    101102
    102103
    103 
    104104Structure NI2HDF5BrowserData
    105105        SVAR browserName
     
    123123        SVAR datasetInfo                                                // Panel readout info for currently-selected dataset
    124124EndStructure
    125 
     125//
    126126static Function CreateHDF5BrowserGlobals(newBrowserName)
    127127        String newBrowserName
     
    154154        SetDataFolder savedDataFolder
    155155End
    156 
     156//
    157157Function/S NI2_SetBrowserDataFolder(browserName)                // Pass "" for browserName to set to master browser folder.
    158158        String browserName
     
    169169        return savedDataFolder
    170170End
    171 
    172 static Function SetNI2HDF5BrowserData(browserName, bd)
    173         String browserName
    174         STRUCT NI2HDF5BrowserData &bd
    175        
    176         String savedDataFolder = NI2_SetBrowserDataFolder(browserName)
    177        
    178         // These statements set the structure fields to reference the corresponding waves and variables in the data folder.
    179        
    180         SVAR bd.browserName
    181        
    182         Wave/T bd.groupsList
    183         Wave/T bd.groupAttributesList
    184         Wave/T bd.datasetsList
    185         Wave/T bd.datasetAttributesList
    186        
    187         Wave/T bd.groupFullPaths
    188         SVAR bd.groupPath
    189 
    190         SVAR bd.hyperSelectionWavePath
    191        
    192         NVAR bd.fileID
    193         SVAR bd.fileName
    194         SVAR bd.path
    195         SVAR bd.fullPath
    196         NVAR bd.readOnly
    197        
    198         SVAR bd.datasetInfo
    199        
    200         SetDataFolder savedDataFolder
    201 End
    202 
    203 static Function CountSlashes(item)
    204         String item
    205        
    206         Variable slashes = 0
    207         Variable pos = 0
    208        
    209         do
    210                 pos = strsearch(item, "/", pos)
    211                 if (pos < 0)
    212                         break
    213                 endif
    214                 slashes += 1
    215                 pos += 1
    216         while (1)
    217 
    218         return slashes
    219 End
    220 
    221 Function/S NI2_GetGroupHierarchy(fileID, startPath, level, mode)
    222         Variable fileID
    223         String startPath
    224         Variable level
    225         Variable mode                   // 0 to just get group names; 1 to get full path to each group.
    226 
    227         String result = ""
    228 
    229         String indent = ""                      // Used only for mode 0.
    230         Variable i, j
    231 
    232 #if Exists("HDF5ListGroup")     
    233        
    234         // This gives full hierarchy with full paths
    235         HDF5ListGroup /F /R /TYPE=1 fileID, startPath
    236         result = S_HDF5ListGroup
    237        
    238         if (mode == 0)                          // Want just names, not full paths
    239                 result = ""
    240                 Variable numItems = ItemsInList(S_HDF5ListGroup)
    241                 for(i=0; i<numItems; i+=1)
    242                         String item = StringFromList(i, S_HDF5ListGroup)
    243                         level = CountSlashes(item)
    244                         indent = ""
    245                         for(j=0; j<level; j+=1)
    246                                 indent += "    "
    247                         endfor
    248                         item = ParseFilePath(0, item, "/", 1, 0)                        // Get last element
    249                         item = indent + item                                            // Prepend indentation
    250                         result += item + ";"           
    251                 endfor 
    252         endif
    253        
    254         return result
    255 #else
    256         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    257 #endif
    258 End
    259 
    260 static Function/S GetFileHierarchy(bd, mode)
    261         STRUCT NI2HDF5BrowserData &bd
    262         Variable mode                                           // 0 to just get group names; 1 to get full path to each group.
    263        
    264         if (bd.fileID == 0)                                                     // No file is open?
    265                 return ""
    266         endif
    267        
    268         String hierarchy, rootName
    269         if (mode == 1)
    270                 rootName = "/"                                  // For purposes of storing full path, use true root name
    271         else
    272                 rootName = "root"                                       // For display purposes, use "root" as root name
    273         endif
    274         hierarchy = rootName + ";" + NI2_GetGroupHierarchy(bd.fileID, "/", 1, mode)
    275        
    276         return hierarchy
    277 End
    278 
    279 static Function ResetListSelections(bd, resetGroupsList, resetGroupAttributesList, resetDatasetsList, resetDatasetAttributesList)
    280         STRUCT NI2HDF5BrowserData &bd
    281         Variable resetGroupsList, resetGroupAttributesList, resetDatasetsList, resetDatasetAttributesList
    282 
    283         if (resetGroupsList)
    284                 ListBox GroupsList, win=$bd.browserName, selRow=0
    285         endif
    286         if (resetGroupAttributesList)
    287                 ListBox GroupAttributesList, win=$bd.browserName, selRow=0
    288         endif
    289         if (resetDatasetsList)
    290                 ListBox DatasetsList, win=$bd.browserName, selRow=0
    291         endif
    292         if (resetDatasetAttributesList)
    293                 ListBox DatasetAttributesList, win=$bd.browserName, selRow=0
    294         endif
    295 End
    296 
    297 Function/S NI2_HDF5GetObjectFullPath(groupPath, objectName)
    298         String groupPath                                        // Path to parent group
    299         String objectName                               // Name of dataset or group in parent group
    300        
    301         String fullPath
    302        
    303         if (CmpStr(groupPath, "/") == 0)
    304                 fullPath = "/" + objectName
    305         else
    306                 fullPath = groupPath + "/" + objectName
    307         endif
    308        
    309         return fullPath
    310 End
    311 
    312 Function/S NI2_GetTextPreviewString(tw)
    313         Wave/T tw                                               // tw has already been flattened to 1D.
    314        
    315         String preview, temp
    316         Variable len
    317        
    318         Variable row, numRows, totalLength
    319        
    320         totalLength = 0
    321 
    322         numRows = numpnts(tw)
    323         if (numRows == 0)
    324                 return ""
    325         endif
    326        
    327         preview = ""
    328         row = 0
    329         do
    330                 temp = tw[row]
    331                 temp = ReplaceString("\r", temp, "<CR>", 1)     // Convert CR to "\r"
    332                 temp = ReplaceString("\n", temp, "<LF>", 1)     // Convert LF to "\n"
    333 
    334                 len = strlen(temp)
    335                 if (len > 128)
    336                         if (numRows == 1)
    337                                 sprintf preview, "\"%s\" . . . (%d characters total)", temp[0,127], len
    338                         else
    339                                 preview += " . . . <Strings too long to display here>"
    340                         endif
    341                        
    342                         row = numRows                                                   // To prevent extra . . .
    343                         break
    344                 endif
    345 
    346                 preview += "\"" + temp + "\""
    347                 row += 1
    348                 totalLength += len
    349 
    350                 if (row >= numRows)
    351                         break
    352                 endif
    353                 if (totalLength >= 256)                         // Enough is enough
    354                         break
    355                 endif
    356 
    357                 preview += ", "
    358         while(1)
    359 
    360         if (row < numRows)
    361                 preview += " . . ."
    362         endif
    363 
    364         return preview
    365 End
    366 
    367 Function/S NI2_GetNumericPreviewString(w)
    368         Wave w                                                  // w has already been flattened to 1D.
    369 
    370         String preview, temp
    371        
    372         Variable row, numRows, totalLength
    373        
    374         totalLength = 0
    375 
    376         numRows = numpnts(w)
    377         if (numRows == 0)
    378                 return ""
    379         endif
    380        
    381         preview = ""
    382         row = 0
    383         do
    384                 sprintf temp, "%g", w[row]
    385                 preview += temp
    386                 row += 1
    387                 totalLength += strlen(temp)
    388 
    389                 if (row >= numRows)
    390                         break
    391                 endif
    392                 if (totalLength >= 256)                                 // Enough is enough
    393                         break
    394                 endif
    395 
    396                 preview += ", "
    397         while(1)
    398 
    399         if (row < numRows)
    400                 preview += " . . ."
    401         endif
    402        
    403         return preview
    404 End
    405 
    406 Function/S NI2_GetPreviewString(locationID, objectType, di, fullPath, attributeName)
    407         Variable locationID
    408         Variable objectType                                             // 1 = group, 2 = dataset
    409         STRUCT NI2_HDF5DataInfo &di
    410         String fullPath                                                 // Full path to group or dataset
    411         String attributeName                                    // "" if this is a dataset, not an attribute
    412        
    413         String value = "<Can't display here>"
    414         String temp
    415        
    416         Variable rank = di.ndims
    417         Variable dim, numElements
    418        
    419         if (rank == 0)
    420                 numElements = 1
    421         else
    422                 numElements = di.dims[0]
    423                 for(dim=1; dim<rank; dim+=1)
    424                         numElements *= di.dims[dim]             
    425                 endfor
    426         endif
    427 
    428 #if Exists("HDF5LoadData")     
    429         strswitch(di.datatype_class_str)
    430                 case "H5T_INTEGER":
    431                 case "H5T_FLOAT":
    432                 case "H5T_ENUM":
    433                 case "H5T_OPAQUE":
    434                 case "H5T_BITFIELD":
    435                         if (numElements > 100)
    436                                 value = "<Too big to display here>"     // It would take too long to load.
    437                                 break
    438                         endif
    439                        
    440                         HDF5LoadData /A=attributeName /N=tempNumericAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
    441                         if (V_flag != 0)
    442                                 value = "ERROR!"
    443                         else
    444                                 Wave tempNumericAttributeWave
    445                                
    446                                 if (rank > 1)
    447                                         // So we can treat multi-dimensional wave as one big row.
    448                                         Redimension/N=(numElements)/E=1 tempNumericAttributeWave
    449                                 endif
    450                                
    451                                 value = NI2_GetNumericPreviewString(tempNumericAttributeWave)
    452                         endif
    453                         KillWaves/Z tempNumericAttributeWave
    454                         break                           
    455 
    456                 case "H5T_REFERENCE":
    457                         if (numElements > 10)
    458                                 value = "<Too big to display here>"     // It would take too long to load.
    459                                 break
    460                         endif
    461                
    462                         HDF5LoadData /A=attributeName /N=tempTextAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
    463                         if (V_flag != 0)
    464                                 value = "ERROR!"
    465                         else
    466                                 if (rank > 1)
    467                                         wave tempTextAttributeWave
    468                                         // So we can treat multi-dimensional wave as one big row.
    469                                         Redimension/N=(numElements)/E=1 tempTextAttributeWave
    470                                 endif
    471                                
    472                                 // Remove the prefix (e.g., "D:" for a dataset, which is there for
    473                                 // programmatic use but would confuse in a preview.
    474                                 Wave/T references = tempTextAttributeWave                       // Created by HDF5LoadData
    475                                 String tmp
    476                                 Variable npnts=numpnts(references), len
    477                                 Variable i
    478                                 for(i=0; i<npnts; i+=1)
    479                                         tmp = references[i]
    480                                         len = strlen(tmp)
    481                                         references[i] = tmp[2,len]
    482                                 endfor
    483                                
    484                                 value = NI2_GetTextPreviewString(references)
    485                         endif
    486                         KillWaves/Z tempTextAttributeWave
    487                         break                           
    488 
    489                 case "H5T_STRING":
    490                         if (numElements > 100)
    491                                 value = "<Too big to display here>"     // It would take too long to load.
    492                                 break
    493                         endif
    494                
    495                         HDF5LoadData /A=attributeName /N=tempTextAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
    496                         if (V_flag != 0)
    497                                 value = "ERROR!"
    498                         else
    499                                 if (rank > 1)
    500                                         // So we can treat multi-dimensional wave as one big row.
    501                                         Redimension/N=(numElements)/E=1 tempTextAttributeWave
    502                                 endif
    503                                 value = NI2_GetTextPreviewString(tempTextAttributeWave)
    504                         endif
    505                         KillWaves/Z tempTextAttributeWave
    506                         break                           
    507                        
    508                 case "H5T_TIME":
    509                 case "H5T_COMPOUND":
    510                 case "H5T_VLEN":
    511                 case "H5T_ARRAY":
    512                         value = "<Can't display this type here>"
    513                         break
    514         endswitch
    515        
    516         return value
    517 #else
    518         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    519 #endif
    520 End
    521 
    522 static Function FillDatasetsList(bd)
    523         STRUCT NI2HDF5BrowserData &bd
    524 
    525 #if Exists("HDF5ListGroup")     
    526         HDF5ListGroup /TYPE=2 bd.fileID, bd.groupPath
    527         Variable numItemsInList = ItemsInList(S_HDF5ListGroup)
    528        
    529         if (numItemsInList == 0)
    530                 Redimension/N=0 bd.datasetsList
    531         else
    532                 Redimension/N=(numItemsInList, 5) bd.datasetsList
    533                 SetDimLabel 1, 0, Dataset, bd.datasetsList
    534                 SetDimLabel 1, 1, Rank, bd.datasetsList
    535                 SetDimLabel 1, 2, 'Dim Sizes', bd.datasetsList
    536                 SetDimLabel 1, 3, Type, bd.datasetsList
    537                 SetDimLabel 1, 4, Value, bd.datasetsList
    538                 bd.datasetsList[][0] = StringFromList(p, S_HDF5ListGroup)
    539        
    540                 String dataset
    541                 Variable i, numDatasets
    542                 numDatasets = ItemsInList(S_HDF5ListGroup)
    543                 for(i=0; i<numDatasets; i+=1)
    544                         dataset = StringFromList(i, S_HDF5ListGroup)
    545                         String fullPath = NI2_HDF5GetObjectFullPath(bd.groupPath, dataset)
    546                         STRUCT NI2_HDF5DataInfo di
    547                         NI2_InitHDF5DataInfo(di)                        // Set input fields.
    548                         HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
    549                        
    550                         Variable rank = di.ndims
    551                         bd.datasetsList[i][1] = num2istr(rank)
    552                        
    553                         String dimsStr=""
    554                         Variable dim
    555                         for(dim=0; dim<rank; dim+=1)
    556                                 dimsStr += num2istr(di.dims[dim]) + ";"
    557                         endfor
    558                         bd.datasetsList[i][2] = dimsStr
    559 
    560                         bd.datasetsList[i][3] = di.datatype_str
    561 
    562                         String preview = NI2_GetPreviewString(bd.fileID, 2, di, fullPath, "")
    563                         bd.datasetsList[i][4] = preview
    564                 endfor
    565         endif
    566 #else
    567         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    568 #endif
    569 End
    570                
    571 static Function FillGroupAttributesList(bd)
    572         STRUCT NI2HDF5BrowserData &bd
    573 
    574 #if Exists("HDF5ListAttributes")       
    575         Variable numAttributes = 0
    576         String groupPath = bd.groupPath
    577         if (strlen(groupPath) > 0)
    578                 HDF5ListAttributes/TYPE=1 bd.fileID, groupPath
    579                 numAttributes = ItemsInList(S_HDF5ListAttributes)
    580         endif
    581        
    582         if (numAttributes == 0)
    583                 Redimension/N=0 bd.groupAttributesList
    584         else
    585                 Redimension/N=(numAttributes, 5) bd.groupAttributesList
    586                 SetDimLabel 1, 0, Attribute,bd.groupAttributesList
    587                 SetDimLabel 1, 1, Rank,bd.groupAttributesList
    588                 SetDimLabel 1, 2, 'Dim Sizes',bd.groupAttributesList
    589                 SetDimLabel 1, 3, Type,bd.groupAttributesList
    590                 SetDimLabel 1, 4, Value,bd.groupAttributesList
    591                 bd.groupAttributesList[][0] = StringFromList(p, S_HDF5ListAttributes)
    592        
    593                 String attribute
    594                 Variable i
    595                 for(i=0; i<numAttributes; i+=1)
    596                         String attributeName
    597                         attributeName = StringFromList(i, S_HDF5ListAttributes)
    598                         attribute = attributeName
    599 
    600                         STRUCT NI2_HDF5DataInfo di
    601                         NI2_InitHDF5DataInfo(di)                        // Set input fields.
    602                         HDF5AttributeInfo(bd.fileID, groupPath, 1, attribute, 0, di)
    603                        
    604                         Variable rank = di.ndims
    605                         bd.groupAttributesList[i][1] = num2istr(rank)
    606                        
    607                         String dimsStr=""
    608                         Variable dim
    609                         for(dim=0; dim<rank; dim+=1)
    610                                 dimsStr += num2istr(di.dims[dim]) + ";"
    611                         endfor
    612                         bd.groupAttributesList[i][2] = dimsStr
    613 
    614                         bd.groupAttributesList[i][3] = di.datatype_str
    615 
    616                         String preview = NI2_GetPreviewString(bd.fileID, 1, di, groupPath, attributeName)
    617                         bd.groupAttributesList[i][4] = preview
    618                 endfor
    619         endif
    620 #else
    621         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    622 #endif
    623 End
    624                
    625 static Function FillDatasetAttributesList(bd)
    626         STRUCT NI2HDF5BrowserData &bd
    627 
    628 #if Exists("HDF5ListAttributes")       
    629         Variable numAttributes = 0
    630         String datasetPath = NI2_SelectedDatasetPath(bd)
    631         if (strlen(datasetPath) > 0)
    632                 HDF5ListAttributes/TYPE=2 bd.fileID, datasetPath
    633                 numAttributes = ItemsInList(S_HDF5ListAttributes)
    634         endif
    635        
    636         if (numAttributes == 0)
    637                 Redimension/N=0 bd.datasetAttributesList
    638         else
    639                 Redimension/N=(numAttributes, 5) bd.datasetAttributesList
    640                 SetDimLabel 1, 0, Attribute,bd.datasetAttributesList
    641                 SetDimLabel 1, 1, Rank,bd.datasetAttributesList
    642                 SetDimLabel 1, 2, 'Dim Sizes',bd.datasetAttributesList
    643                 SetDimLabel 1, 3, Type,bd.datasetAttributesList
    644                 SetDimLabel 1, 4, Value,bd.datasetAttributesList
    645                 bd.datasetAttributesList[][0] = StringFromList(p, S_HDF5ListAttributes)
    646        
    647                 String attribute
    648                 Variable i
    649                 for(i=0; i<numAttributes; i+=1)
    650                         String attributeName
    651                         attributeName = StringFromList(i, S_HDF5ListAttributes)
    652                         attribute = attributeName
    653 
    654                         STRUCT NI2_HDF5DataInfo di
    655                         NI2_InitHDF5DataInfo(di)                        // Set input fields.
    656                         HDF5AttributeInfo(bd.fileID, datasetPath, 2, attribute, 0, di)
    657                        
    658                         Variable rank = di.ndims
    659                         bd.datasetAttributesList[i][1] = num2istr(rank)
    660                        
    661                         String dimsStr=""
    662                         Variable dim
    663                         for(dim=0; dim<rank; dim+=1)
    664                                 dimsStr += num2istr(di.dims[dim]) + ";"
    665                         endfor
    666                         bd.datasetAttributesList[i][2] = dimsStr
    667 
    668                         bd.datasetAttributesList[i][3] = di.datatype_str
    669 
    670                         String preview = NI2_GetPreviewString(bd.fileID, 2, di, datasetPath, attributeName)
    671                         bd.datasetAttributesList[i][4] = preview
    672                 endfor
    673         endif
    674 #else
    675         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    676 #endif
    677 End
    678        
    679 static Function FillLists(bd)
    680         STRUCT NI2HDF5BrowserData &bd
    681 
    682         if (bd.fileID == 0)                                                     // No file is open?
    683                 Redimension/N=(0) bd.groupsList
    684                 Redimension/N=(0) bd.groupAttributesList
    685                 Redimension/N=(0) bd.datasetsList
    686                 Redimension/N=(0) bd.datasetAttributesList
    687                 return -1
    688         endif
    689        
    690         Variable numItemsInList
    691         String hierarchy
    692        
    693         // Show entire hierarchy in Groups list.
    694         hierarchy = GetFileHierarchy(bd, 0)     
    695         numItemsInList = ItemsInList(hierarchy)
    696         Redimension/N=(numItemsInList) bd.groupsList
    697         bd.groupsList = StringFromList(p, hierarchy)
    698        
    699         // The groupFullPaths wave stores the full path to each group
    700         hierarchy = GetFileHierarchy(bd, 1)     
    701         numItemsInList = ItemsInList(hierarchy)
    702         Redimension/N=(numItemsInList) bd.groupFullPaths
    703         bd.groupFullPaths = StringFromList(p, hierarchy)
    704        
    705         // Show datasets in current group in Datasets list.
    706         FillDatasetsList(bd)
    707        
    708         // Show attributes of currently-selected group.
    709         FillGroupAttributesList(bd)
    710        
    711         // Show attributes of currently-selected dataset.
    712         FillDatasetAttributesList(bd)
    713 End
    714 
    715 Function/S NI2_SelectedGroupName(bd)
    716         STRUCT NI2HDF5BrowserData &bd
    717        
    718         if (numpnts(bd.groupsList) == 0)
    719                 return ""
    720         endif
    721 
    722         ControlInfo/W=$bd.browserName GroupsList
    723         Variable selRow = V_value
    724         String groupName = bd.groupsList[selRow]
    725 
    726         // Group names may have leading spaces at this point. The spaces are used to create
    727         // indentation in the list to show the hierarchy. We must remove the leading spaces.
    728         sscanf groupName, " %s", groupName
    729 
    730         if (strlen(groupName) > 0)
    731                 return groupName
    732         endif
    733 
    734         return ""
    735 End
    736 
    737 Function/S NI2_SelectedGroupPath(bd)
    738         STRUCT NI2HDF5BrowserData &bd
    739        
    740         String groupPath = bd.groupPath
    741 
    742         return groupPath
    743 End
    744 
    745 Function/S NI2_SelectedDatasetName(bd)
    746         STRUCT NI2HDF5BrowserData &bd
    747        
    748         if (numpnts(bd.datasetsList) == 0)
    749                 return ""
    750         endif
    751 
    752         ControlInfo/W=$bd.browserName DatasetsList
    753         Variable selRow = V_value
    754         String datasetName = bd.datasetsList[selRow][0]
    755         if (strlen(datasetName) > 0)
    756                 return datasetName
    757         endif
    758 
    759         return ""
    760 End
    761 
    762 Function/S NI2_SelectedDatasetPath(bd)
    763         STRUCT NI2HDF5BrowserData &bd
    764 
    765         String datasetName = NI2_SelectedDatasetName(bd)
    766         if (strlen(datasetName) == 0)
    767                 return ""                                               // Nothing is selected
    768         endif
    769        
    770         String datasetPath = bd.groupPath
    771         if (CmpStr(datasetPath[strlen(datasetPath)-1],"/") != 0)
    772                 datasetPath += "/"
    773         endif
    774         datasetPath += datasetName
    775 
    776         return datasetPath
    777 End
    778 
    779 Function/S NI2_SelectedAttributeName(bd, isGroupAttribute)
    780         STRUCT NI2HDF5BrowserData &bd
    781         Variable isGroupAttribute
    782 
    783         String controlName
    784         if (isGroupAttribute)
    785                 controlName = "GroupAttributesList"
    786                 Wave/T list = bd.groupAttributesList
    787         else
    788                 controlName = "DatasetAttributesList"
    789                 Wave/T list = bd.datasetAttributesList
    790         endif
    791        
    792         if (numpnts(list) == 0)
    793                 return ""
    794         endif
    795 
    796         ControlInfo/W=$bd.browserName $controlName
    797         Variable selRow = V_value
    798         String attributeName = list[selRow][0]
    799        
    800         if (strlen(attributeName) > 0)
    801                 return attributeName
    802         endif
    803 
    804         return ""
    805 End
    806 
    807 Function/S NI2_SelectedAttributePath(bd, isGroupAttribute)
    808         STRUCT NI2HDF5BrowserData &bd
    809         Variable isGroupAttribute
    810 
    811         String attributeName = NI2_SelectedAttributeName(bd, isGroupAttribute)
    812         if (strlen(attributeName) == 0)
    813                 return ""                                               // Nothing is selected
    814         endif
    815        
    816         String path
    817         if (isGroupAttribute)
    818                 path = NI2_SelectedGroupPath(bd)
    819         else
    820                 path = NI2_SelectedDatasetPath(bd)
    821         endif
    822        
    823         path += "/" + attributeName
    824 
    825         return path
    826 End
    827 
    828 StrConstant NI2_kLoadAllMembersString = "_Load_All_Members_"
    829 
    830 static Function SetMembersPopupMenu(bd)
    831         STRUCT NI2HDF5BrowserData &bd
    832        
    833 #if Exists("HDF5OpenFile")     
    834         Variable hideMembers
    835         String memberList
    836 
    837         hideMembers = 1
    838         memberList = NI2_kLoadAllMembersString + ";"
    839        
    840         if (bd.fileID != 0)                             // File is open for this browser?
    841                 String fullPath
    842                
    843                 fullPath = NI2_SelectedDatasetPath(bd)
    844                 if (strlen(fullPath) > 0)
    845                         STRUCT NI2_HDF5DataInfo di
    846                         NI2_InitHDF5DataInfo(di)
    847                         HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
    848                         if (CmpStr(di.datatype_class_str, "H5T_COMPOUND") == 0)
    849                                 hideMembers = 0
    850                                
    851                                 ControlInfo /W=$bd.browserName Members
    852                                 Variable selectedItemNumber = V_Value
    853                                 STRUCT NI2_HDF5DatatypeInfo dti
    854                                 NI2_InitHDF5DatatypeInfo(dti)
    855                                 if (HDF5TypeInfo(bd.fileID, fullPath, "", "", 1, dti))
    856                                         memberList += "HDF5TypeInfo Error!"
    857                                 else
    858                                         memberList += dti.names
    859                                         if (selectedItemNumber > dti.nmembers+1)        // +1 because of "_Load_All_Members_" item.
    860                                                 selectedItemNumber = 1          // Force menu selection to be in bounds.
    861                                         endif
    862                                 endif
    863                                 PopupMenu Members, win=$bd.browserName, mode=selectedItemNumber
    864                         endif
    865                 endif
    866         endif
    867        
    868         PopupMenu Members, win=$bd.browserName, disable=hideMembers
    869        
    870         String cmd                              // What a pain. Can't use local variable with PopupMenu value=
    871         sprintf cmd, "PopupMenu Members, win=%s, value=\"%s\"", bd.browserName, memberList
    872         Execute cmd
    873 #else
    874         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    875 #endif
    876 End
    877 
    878 Function NI2_HDF5GetReadOnlySetting(browserName)
    879         String browserName
    880        
    881         Variable result
    882         ControlInfo /W=$browserName ReadOnly
    883         result = V_value
    884         return result
    885 End
    886 
    887 Function NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
    888         STRUCT NI2HDF5BrowserData &bd
    889         Variable &isCompound                                    // Output: If non-zero, a compound dataset is selected.
    890         Variable &compMode                                              // Output: Value suitable for passing to HDF5LoadData /COMP flag.
    891         String &memberName                                              // Output: If "" load all members.
    892        
    893         isCompound = 0
    894         memberName = ""
    895        
    896         ControlInfo /W=$bd.browserName Members
    897         if (V_disable == 0)
    898                 isCompound = 1
    899                 memberName = S_value
    900                 if (CmpStr(memberName, NI2_kLoadAllMembersString) == 0)
    901                         memberName = ""
    902                 endif
    903         endif
    904 
    905         compMode = isCompound && strlen(memberName)>0
    906 End
    907 
    908 Function NI2_HDF5GetTranspose2DSetting(browserName)
    909         String browserName
    910        
    911         Variable result
    912         ControlInfo /W=$browserName Transpose2DDatasets
    913         result = V_value
    914         return result
    915 End
    916 
    917 static Function HDF5GetLoadDatasetOptions(browserName, tableDisplayMode, graphDisplayMode)
    918         String browserName
    919         Variable &tableDisplayMode, &graphDisplayMode
    920        
    921         ControlInfo /W=$browserName DisplayInTable
    922         tableDisplayMode = V_value - 1                                          // 0=no; 1=display; 2=append
    923        
    924         ControlInfo /W=$browserName DisplayInGraph
    925         graphDisplayMode = V_value - 1                                          // 0=no; 1=display; 2=append
    926        
    927         return tableDisplayMode || graphDisplayMode
    928 End
    929 
    930 static Function MembersPopupProc(ctrlName,popNum,popStr) : PopupMenuControl
    931         String ctrlName
    932         Variable popNum
    933         String popStr
    934        
    935         String browserName = NI2_HDF5GetTopBrowserName()
    936        
    937         STRUCT NI2HDF5BrowserData bd
    938         SetNI2HDF5BrowserData(browserName, bd)
    939        
    940         NI2_HDF5DisplaySelectedDataset(bd)
    941 End
    942 
    943 static Function SetButtonStates(bd)
    944         STRUCT NI2HDF5BrowserData &bd
    945        
    946         if (bd.fileID == 0)                             // No file is open for this browser?
    947                 Button CreateFile, win=$bd.browserName, disable=2               // Enable Create
    948                 Button OpenFile, win=$bd.browserName, disable=0         // Enable Open
    949                 Button CloseFile, win=$bd.browserName, disable=2                // Disable Close
    950                 Button LoadGroup, win=$bd.browserName, disable=2                // Disable Load Group
    951                 Button SaveDataFolder, win=$bd.browserName, disable=2   // Disable Save Data Folder
    952                 Button LoadDataset, win=$bd.browserName, disable=2      // Disable Load Dataset
    953                 Button SaveWaves, win=$bd.browserName, disable=2                // Disable Save Waves
    954         else
    955                 Button CreateFile, win=$bd.browserName, disable=2               // Disable Create
    956                 Button OpenFile, win=$bd.browserName, disable=2         // Disable Open
    957                 Button CloseFile, win=$bd.browserName, disable=0                // Enable Close
    958                
    959                 String groupName = NI2_SelectedGroupName(bd)
    960                 Variable code = strlen(groupName) > 0 ? 0:2
    961                 Button LoadGroup, win=$bd.browserName, disable=code     // Enable Load Group
    962                 code = bd.readOnly == 0 ? 0:2
    963                 Button SaveDataFolder, win=$bd.browserName, disable=code        // Enable Save Data Folder
    964                
    965                 String datasetName = NI2_SelectedDatasetName(bd)
    966                 code = strlen(datasetName) > 0 ? 0:2
    967                 Button LoadDataset, win=$bd.browserName, disable=code   // Enable Load Dataset
    968                 code = bd.readOnly == 0 ? 0:2
    969                 Button SaveWaves, win=$bd.browserName, disable=code             // Enable Save Waves
    970                 //overwrite the code above...
    971                 Button LoadGroup, win=$bd.browserName, disable=2        // Disable Load Dataset
    972                 Button LoadDataset, win=$bd.browserName, disable=2      // Disable Load Dataset
    973         endif
    974         SetMembersPopupMenu(bd)
    975         SetGraphButtonTitle(bd.browserName)
    976         SetTableButtonTitle(bd.browserName)
    977         SetDumpButtonTitle(bd.browserName)
    978         SetVariable HyperSelectionWave, win=$bd.browserName, value= bd.hyperSelectionWavePath
    979 End
    980 
    981 static Function DrawFilePath(bd)
    982         STRUCT NI2HDF5BrowserData &bd
    983        
    984         // TitleBox FilePath, win=$bd.browserName, title=bd.fullPath                    // This is limited to 63 characters.
    985         TitleBox FilePath, win=$bd.browserName, variable=bd.fullPath
    986 End
    987 
    988 static Function DrawGroupPath(bd)
    989         STRUCT NI2HDF5BrowserData &bd
    990        
    991         TitleBox GroupPath, win=$bd.browserName, variable=bd.groupPath
    992 End
    993 
    994 static Function DrawDatasetInfo(bd)
    995         STRUCT NI2HDF5BrowserData &bd
    996        
    997         TitleBox Dataset, win=$bd.browserName, variable=bd.datasetInfo
    998 End
    999 
    1000 static Function UpdateAfterFileCreateOrOpen(isCreate, browserName, fileID, path, fileName)
    1001         Variable isCreate
    1002         String browserName
    1003         Variable fileID
    1004         String path, fileName
    1005        
    1006         STRUCT NI2HDF5BrowserData bd
    1007         SetNI2HDF5BrowserData(browserName, bd)
    1008 
    1009         ResetListSelections(bd, 1, 1, 1, 1)
    1010 
    1011         bd.fileID = fileID
    1012         bd.fileName = fileName
    1013         bd.path = path
    1014         bd.fullPath = path + fileName
    1015         DrawFilePath(bd)
    1016        
    1017         bd.readOnly = isCreate ? 0 : NI2_HDF5GetReadOnlySetting(browserName)
    1018 
    1019         bd.groupPath = "/"
    1020         DrawGroupPath(bd)
    1021 
    1022         SetButtonStates(bd)
    1023 
    1024         FillLists(bd)
    1025        
    1026         NI2_UpdateAfterGroupSelected(bd, "/")
    1027        
    1028         String datasetName = NI2_SelectedDatasetName(bd)
    1029         if (strlen(datasetName) > 0)
    1030                 NI2_SelectDataset(bd, datasetName)
    1031         endif
    1032 End
    1033 
    1034 static Function CreateFileButtonProc(ctrlName) : ButtonControl
    1035         String ctrlName
    1036        
    1037 #if Exists("HDF5OpenFile")     
    1038         String browserName = NI2_HDF5GetTopBrowserName()
    1039 
    1040         STRUCT NI2HDF5BrowserData bd
    1041         SetNI2HDF5BrowserData(browserName, bd)
    1042        
    1043         Variable fileID
    1044        
    1045         HDF5CreateFile /I /O fileID  as ""
    1046         if (V_flag == 0)                // Create OK?
    1047                 UpdateAfterFileCreateOrOpen(1, browserName, fileID, S_path, S_fileName)
    1048         endif
    1049 #else
    1050         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1051 #endif
    1052 End
    1053 
    1054 static Function OpenFileButtonProc(ctrlName) : ButtonControl
    1055         String ctrlName
    1056        
    1057 #if Exists("HDF5OpenFile")     
    1058         String browserName = NI2_HDF5GetTopBrowserName()
    1059        
    1060         Variable readOnly = NI2_HDF5GetReadOnlySetting(browserName)
    1061        
    1062         Variable locFileID
    1063        
    1064         if (readOnly)
    1065                 HDF5OpenFile/R locFileID as ""
    1066         else
    1067                 HDF5OpenFile locFileID as ""
    1068         endif
    1069        
    1070         if (V_flag == 0)                                        // Open OK?
    1071                 UpdateAfterFileCreateOrOpen(0, browserName, locFileID, S_path, S_fileName)
    1072         endif
    1073 #else
    1074         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1075 #endif
    1076 End
    1077 
    1078 // This detects if the file is no longer open, such as if you save the experiment, quit Igor and then reopen the experiment.
    1079 Function NI2_FileWasUnexpectedlyClosed(bd)
    1080         STRUCT NI2HDF5BrowserData &bd
    1081 
    1082 #if Exists("HDF5OpenFile")     
    1083         if (bd.fileID == 0)
    1084                 return 0                                // File is closed but not unexpectedly.
    1085         endif
    1086        
    1087         HDF5ListAttributes/Q /TYPE=1 /Z bd.fileID , "/"         // Try to list the attributes of the root of the file.
    1088         if (V_flag != 0)
    1089                 return 1                                                                // Error: Assume file was closed.
    1090         endif
    1091        
    1092         return 0
    1093 #else
    1094         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1095 #endif
    1096 End
    1097 
    1098 static Function FileWasClosed(bd)                       // Does cleanup after a file is closed.
    1099         STRUCT NI2HDF5BrowserData &bd
    1100 
    1101         bd.fileID = 0
    1102         Redimension/N=(0) bd.groupFullPaths
    1103         bd.groupPath = ""
    1104         bd.fileName = ""
    1105         bd.path = ""
    1106         bd.fullPath = ""
    1107         bd.datasetInfo = ""
    1108 
    1109         DrawFilePath(bd)
    1110         SetButtonStates(bd)
    1111         FillLists(bd)
    1112 End
    1113 
    1114 static Function CloseFileButtonProc(ctrlName) : ButtonControl
    1115         String ctrlName
    1116        
    1117 #if Exists("HDF5OpenFile")     
    1118         String browserName = NI2_HDF5GetTopBrowserName()
    1119 
    1120         STRUCT NI2HDF5BrowserData bd
    1121         SetNI2HDF5BrowserData(browserName, bd)
    1122 
    1123         HDF5CloseFile bd.fileID
    1124         CloseSavePanels()
    1125         FileWasClosed(bd)
    1126 #else
    1127         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1128 #endif
    1129 End
    1130 
    1131 static Function LoadDatasetButtonProc(ctrlName) : ButtonControl
    1132         String ctrlName
    1133 
    1134 #if Exists("HDF5OpenFile")     
    1135         String browserName
    1136         STRUCT NI2HDF5BrowserData bd
    1137        
    1138         if(stringmatch(ctrlName,"AddGrouptoList"))
    1139                
    1140                 browserName = NI2_HDF5GetTopBrowserName()
    1141        
    1142                 SetNI2HDF5BrowserData(browserName, bd)
    1143                
    1144                 Wave/T DataSetNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":DataSetNames")
    1145                 Wave/T GroupNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames")
    1146                 SVAR BrowserNameFldr=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":BrowserNameFldr")
    1147                 Redimension/N=(numpnts(DataSetNames)+1) GroupNames
    1148                 GroupNames[numpnts(GroupNames)-1]=NI2_SelectedGroupPath(bd)
    1149                 BrowserNameFldr = NI2_HDF5GetTopBrowserName()
    1150         elseif(stringmatch(ctrlName,"ClearDatasetList"))
    1151                 browserName = NI2_HDF5GetTopBrowserName()       
    1152                 SetNI2HDF5BrowserData(browserName, bd)         
    1153                 Wave/T DataSetNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":DataSetNames")
    1154                 Wave/T GroupNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames")
    1155                 SVAR BrowserNameFldr=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":BrowserNameFldr")
    1156                 Redimension/N=(0) DataSetNames, GroupNames
    1157 //              DataSetNames[numpnts(DataSetNames)-1]=NI2_SelectedDatasetPath(bd)
    1158                 BrowserNameFldr = NI2_HDF5GetTopBrowserName()           
    1159         else            //Old LoadDataset button...
    1160        
    1161                 browserName = NI2_HDF5GetTopBrowserName()
    1162        
    1163                 SetNI2HDF5BrowserData(browserName, bd)
    1164                
    1165                 String datasetPath = NI2_SelectedDatasetPath(bd)
    1166        
    1167                 String slabWaveStr = ""
    1168                 ControlInfo /W=$bd.browserName UseHyperSelection
    1169                 if (V_value)                                                            // Use Hyperselection is checked?
    1170                         slabWaveStr = bd.hyperSelectionWavePath
    1171                 endif
    1172                 WAVE/Z slabWave = $slabWaveStr                  // It is OK if wave does not exist and slabWave is NULL. HDF5LoadData will simply ignore /SLAB.
    1173                
    1174                 Variable isCompound
    1175                 String memberName
    1176                 Variable compMode
    1177                 NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
    1178        
    1179                 // If isFormalImage is true, we are loading an image written
    1180                 // according to the HDF5 Image and Palette Specification.
    1181                 Variable isFormalImage = 0
    1182                 if (!isCompound)
    1183                         String savedDataFolder = NI2_SetBrowserDataFolder("")                   // tempClassAttribute goes in master HDF5Browser data folder
    1184                         HDF5LoadData /Z /O /N=tempClassAttribute /A="CLASS" /Q /VAR=1 bd.fileID, datasetPath
    1185                         if (V_flag == 0)
    1186                                 WAVE/T tempClassAttribute                       // HDF5LoadData will have created this string
    1187                                 if (CmpStr(tempClassAttribute[0],"IMAGE") == 0)
    1188                                         isFormalImage = 1
    1189                                 endif   
    1190                                 KillWaves/Z tempClassAttribute
    1191                         endif
    1192                         SetDataFolder savedDataFolder
    1193                 endif
    1194                
    1195                 Variable tableDisplayMode, graphDisplayMode             // 0=no; 1=display; 2=append
    1196                 HDF5GetLoadDatasetOptions(bd.browserName, tableDisplayMode, graphDisplayMode)
    1197                
    1198                 if (isFormalImage)
    1199                         HDF5LoadImage /O /GRPH=(graphDisplayMode) /T=(tableDisplayMode) bd.fileID, datasetPath
    1200                 else
    1201                         Variable transpose2D = NI2_HDF5GetTranspose2DSetting(bd.browserName)
    1202                         HDF5LoadData /O /SLAB=slabWave /TRAN=(transpose2D) /COMP={compMode,memberName} /GRPH=(graphDisplayMode) /T=(tableDisplayMode) bd.fileID, datasetPath
    1203                 endif
    1204         endif
    1205 #else
    1206         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1207 #endif
    1208 End
    1209 
    1210 static Function LoadGroupButtonProc(ctrlName) : ButtonControl
    1211         String ctrlName
    1212 
    1213 #if Exists("HDF5OpenFile")     
    1214         String browserName = NI2_HDF5GetTopBrowserName()
    1215 
    1216         STRUCT NI2HDF5BrowserData bd
    1217         SetNI2HDF5BrowserData(browserName, bd)
    1218        
    1219         String groupPath = NI2_SelectedGroupPath(bd)
    1220 
    1221         ControlInfo /W=$bd.browserName LoadGroupsRecursively
    1222         if (V_value)                                                                    // Use LoadGroupsRecursively is checked?
    1223                 HDF5LoadGroup /O /R /T /IMAG=1 :, bd.fileID, groupPath
    1224         else
    1225                 HDF5LoadGroup /O /T /IMAG=1 :, bd.fileID, groupPath
    1226         endif
    1227 
    1228         // For debugging
    1229         Variable numItems
    1230         Variable debug = 1
    1231         if (debug)
    1232                 Wave/Z/T groupPaths = root:groupPaths
    1233                 if (WaveExists(groupPaths))
    1234                         numItems = ItemsInList(S_groupPaths)
    1235                         Redimension/N=(numItems) groupPaths
    1236                         groupPaths = StringFromList(p, S_groupPaths)
    1237                 endif
    1238 
    1239                 Wave/Z/T dataFolderPaths = root:dataFolderPaths
    1240                 if (WaveExists(dataFolderPaths))
    1241                         numItems = ItemsInList(S_dataFolderPaths)
    1242                         Redimension/N=(numItems) dataFolderPaths
    1243                         dataFolderPaths = StringFromList(p, S_dataFolderPaths)
    1244                 endif
    1245 
    1246                 Wave/Z/T wavePaths = root:wavePaths
    1247                 if (WaveExists(wavePaths))
    1248                         numItems = ItemsInList(S_objectPaths)
    1249                         Redimension/N=(numItems) wavePaths
    1250                         wavePaths = StringFromList(p, S_objectPaths)
    1251                 endif
    1252         endif
    1253 #else
    1254         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1255 #endif
    1256 End
    1257 
     171//
     172//static Function SetNI2HDF5BrowserData(browserName, bd)
     173//      String browserName
     174//      STRUCT NI2HDF5BrowserData &bd
     175//     
     176//      String savedDataFolder = NI2_SetBrowserDataFolder(browserName)
     177//     
     178//      // These statements set the structure fields to reference the corresponding waves and variables in the data folder.
     179//     
     180//      SVAR bd.browserName
     181//     
     182//      Wave/T bd.groupsList
     183//      Wave/T bd.groupAttributesList
     184//      Wave/T bd.datasetsList
     185//      Wave/T bd.datasetAttributesList
     186//     
     187//      Wave/T bd.groupFullPaths
     188//      SVAR bd.groupPath
     189//
     190//      SVAR bd.hyperSelectionWavePath
     191//     
     192//      NVAR bd.fileID
     193//      SVAR bd.fileName
     194//      SVAR bd.path
     195//      SVAR bd.fullPath
     196//      NVAR bd.readOnly
     197//     
     198//      SVAR bd.datasetInfo
     199//     
     200//      SetDataFolder savedDataFolder
     201//End
     202//
     203//static Function CountSlashes(item)
     204//      String item
     205//     
     206//      Variable slashes = 0
     207//      Variable pos = 0
     208//     
     209//      do
     210//              pos = strsearch(item, "/", pos)
     211//              if (pos < 0)
     212//                      break
     213//              endif
     214//              slashes += 1
     215//              pos += 1
     216//      while (1)
     217//
     218//      return slashes
     219//End
     220//
     221//Function/S NI2_GetGroupHierarchy(fileID, startPath, level, mode)
     222//      Variable fileID
     223//      String startPath
     224//      Variable level
     225//      Variable mode                   // 0 to just get group names; 1 to get full path to each group.
     226//
     227//      String result = ""
     228//
     229//      String indent = ""                      // Used only for mode 0.
     230//      Variable i, j
     231//
     232//#if Exists("HDF5ListGroup")   
     233//     
     234//      // This gives full hierarchy with full paths
     235//      HDF5ListGroup /F /R /TYPE=1 fileID, startPath
     236//      result = S_HDF5ListGroup
     237//     
     238//      if (mode == 0)                          // Want just names, not full paths
     239//              result = ""
     240//              Variable numItems = ItemsInList(S_HDF5ListGroup)
     241//              for(i=0; i<numItems; i+=1)
     242//                      String item = StringFromList(i, S_HDF5ListGroup)
     243//                      level = CountSlashes(item)
     244//                      indent = ""
     245//                      for(j=0; j<level; j+=1)
     246//                              indent += "    "
     247//                      endfor
     248//                      item = ParseFilePath(0, item, "/", 1, 0)                        // Get last element
     249//                      item = indent + item                                            // Prepend indentation
     250//                      result += item + ";"           
     251//              endfor 
     252//      endif
     253//     
     254//      return result
     255//#else
     256//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     257//#endif
     258//End
     259//
     260//static Function/S GetFileHierarchy(bd, mode)
     261//      STRUCT NI2HDF5BrowserData &bd
     262//      Variable mode                                           // 0 to just get group names; 1 to get full path to each group.
     263//     
     264//      if (bd.fileID == 0)                                                     // No file is open?
     265//              return ""
     266//      endif
     267//     
     268//      String hierarchy, rootName
     269//      if (mode == 1)
     270//              rootName = "/"                                  // For purposes of storing full path, use true root name
     271//      else
     272//              rootName = "root"                                       // For display purposes, use "root" as root name
     273//      endif
     274//      hierarchy = rootName + ";" + NI2_GetGroupHierarchy(bd.fileID, "/", 1, mode)
     275//     
     276//      return hierarchy
     277//End
     278//
     279//static Function ResetListSelections(bd, resetGroupsList, resetGroupAttributesList, resetDatasetsList, resetDatasetAttributesList)
     280//      STRUCT NI2HDF5BrowserData &bd
     281//      Variable resetGroupsList, resetGroupAttributesList, resetDatasetsList, resetDatasetAttributesList
     282//
     283//      if (resetGroupsList)
     284//              ListBox GroupsList, win=$bd.browserName, selRow=0
     285//      endif
     286//      if (resetGroupAttributesList)
     287//              ListBox GroupAttributesList, win=$bd.browserName, selRow=0
     288//      endif
     289//      if (resetDatasetsList)
     290//              ListBox DatasetsList, win=$bd.browserName, selRow=0
     291//      endif
     292//      if (resetDatasetAttributesList)
     293//              ListBox DatasetAttributesList, win=$bd.browserName, selRow=0
     294//      endif
     295//End
     296//
     297//Function/S NI2_HDF5GetObjectFullPath(groupPath, objectName)
     298//      String groupPath                                        // Path to parent group
     299//      String objectName                               // Name of dataset or group in parent group
     300//     
     301//      String fullPath
     302//     
     303//      if (CmpStr(groupPath, "/") == 0)
     304//              fullPath = "/" + objectName
     305//      else
     306//              fullPath = groupPath + "/" + objectName
     307//      endif
     308//     
     309//      return fullPath
     310//End
     311//
     312//Function/S NI2_GetTextPreviewString(tw)
     313//      Wave/T tw                                               // tw has already been flattened to 1D.
     314//     
     315//      String preview, temp
     316//      Variable len
     317//     
     318//      Variable row, numRows, totalLength
     319//     
     320//      totalLength = 0
     321//
     322//      numRows = numpnts(tw)
     323//      if (numRows == 0)
     324//              return ""
     325//      endif
     326//     
     327//      preview = ""
     328//      row = 0
     329//      do
     330//              temp = tw[row]
     331//              temp = ReplaceString("\r", temp, "<CR>", 1)     // Convert CR to "\r"
     332//              temp = ReplaceString("\n", temp, "<LF>", 1)     // Convert LF to "\n"
     333//
     334//              len = strlen(temp)
     335//              if (len > 128)
     336//                      if (numRows == 1)
     337//                              sprintf preview, "\"%s\" . . . (%d characters total)", temp[0,127], len
     338//                      else
     339//                              preview += " . . . <Strings too long to display here>"
     340//                      endif
     341//                     
     342//                      row = numRows                                                   // To prevent extra . . .
     343//                      break
     344//              endif
     345//
     346//              preview += "\"" + temp + "\""
     347//              row += 1
     348//              totalLength += len
     349//
     350//              if (row >= numRows)
     351//                      break
     352//              endif
     353//              if (totalLength >= 256)                         // Enough is enough
     354//                      break
     355//              endif
     356//
     357//              preview += ", "
     358//      while(1)
     359//
     360//      if (row < numRows)
     361//              preview += " . . ."
     362//      endif
     363//
     364//      return preview
     365//End
     366//
     367//Function/S NI2_GetNumericPreviewString(w)
     368//      Wave w                                                  // w has already been flattened to 1D.
     369//
     370//      String preview, temp
     371//     
     372//      Variable row, numRows, totalLength
     373//     
     374//      totalLength = 0
     375//
     376//      numRows = numpnts(w)
     377//      if (numRows == 0)
     378//              return ""
     379//      endif
     380//     
     381//      preview = ""
     382//      row = 0
     383//      do
     384//              sprintf temp, "%g", w[row]
     385//              preview += temp
     386//              row += 1
     387//              totalLength += strlen(temp)
     388//
     389//              if (row >= numRows)
     390//                      break
     391//              endif
     392//              if (totalLength >= 256)                                 // Enough is enough
     393//                      break
     394//              endif
     395//
     396//              preview += ", "
     397//      while(1)
     398//
     399//      if (row < numRows)
     400//              preview += " . . ."
     401//      endif
     402//     
     403//      return preview
     404//End
     405//
     406//Function/S NI2_GetPreviewString(locationID, objectType, di, fullPath, attributeName)
     407//      Variable locationID
     408//      Variable objectType                                             // 1 = group, 2 = dataset
     409//      STRUCT NI2_HDF5DataInfo &di
     410//      String fullPath                                                 // Full path to group or dataset
     411//      String attributeName                                    // "" if this is a dataset, not an attribute
     412//     
     413//      String value = "<Can't display here>"
     414//      String temp
     415//     
     416//      Variable rank = di.ndims
     417//      Variable dim, numElements
     418//     
     419//      if (rank == 0)
     420//              numElements = 1
     421//      else
     422//              numElements = di.dims[0]
     423//              for(dim=1; dim<rank; dim+=1)
     424//                      numElements *= di.dims[dim]             
     425//              endfor
     426//      endif
     427//
     428//#if Exists("HDF5LoadData")   
     429//      strswitch(di.datatype_class_str)
     430//              case "H5T_INTEGER":
     431//              case "H5T_FLOAT":
     432//              case "H5T_ENUM":
     433//              case "H5T_OPAQUE":
     434//              case "H5T_BITFIELD":
     435//                      if (numElements > 100)
     436//                              value = "<Too big to display here>"     // It would take too long to load.
     437//                              break
     438//                      endif
     439//                     
     440//                      HDF5LoadData /A=attributeName /N=tempNumericAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
     441//                      if (V_flag != 0)
     442//                              value = "ERROR!"
     443//                      else
     444//                              Wave tempNumericAttributeWave
     445//                             
     446//                              if (rank > 1)
     447//                                      // So we can treat multi-dimensional wave as one big row.
     448//                                      Redimension/N=(numElements)/E=1 tempNumericAttributeWave
     449//                              endif
     450//                             
     451//                              value = NI2_GetNumericPreviewString(tempNumericAttributeWave)
     452//                      endif
     453//                      KillWaves/Z tempNumericAttributeWave
     454//                      break                           
     455//
     456//              case "H5T_REFERENCE":
     457//                      if (numElements > 10)
     458//                              value = "<Too big to display here>"     // It would take too long to load.
     459//                              break
     460//                      endif
     461//             
     462//                      HDF5LoadData /A=attributeName /N=tempTextAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
     463//                      if (V_flag != 0)
     464//                              value = "ERROR!"
     465//                      else
     466//                              if (rank > 1)
     467//                                      wave tempTextAttributeWave
     468//                                      // So we can treat multi-dimensional wave as one big row.
     469//                                      Redimension/N=(numElements)/E=1 tempTextAttributeWave
     470//                              endif
     471//                             
     472//                              // Remove the prefix (e.g., "D:" for a dataset, which is there for
     473//                              // programmatic use but would confuse in a preview.
     474//                              Wave/T references = tempTextAttributeWave                       // Created by HDF5LoadData
     475//                              String tmp
     476//                              Variable npnts=numpnts(references), len
     477//                              Variable i
     478//                              for(i=0; i<npnts; i+=1)
     479//                                      tmp = references[i]
     480//                                      len = strlen(tmp)
     481//                                      references[i] = tmp[2,len]
     482//                              endfor
     483//                             
     484//                              value = NI2_GetTextPreviewString(references)
     485//                      endif
     486//                      KillWaves/Z tempTextAttributeWave
     487//                      break                           
     488//
     489//              case "H5T_STRING":
     490//                      if (numElements > 100)
     491//                              value = "<Too big to display here>"     // It would take too long to load.
     492//                              break
     493//                      endif
     494//             
     495//                      HDF5LoadData /A=attributeName /N=tempTextAttributeWave /O /Q /TYPE=(objectType) /VAR=0 /Z locationID, fullPath
     496//                      if (V_flag != 0)
     497//                              value = "ERROR!"
     498//                      else
     499//                              if (rank > 1)
     500//                                      // So we can treat multi-dimensional wave as one big row.
     501//                                      Redimension/N=(numElements)/E=1 tempTextAttributeWave
     502//                              endif
     503//                              value = NI2_GetTextPreviewString(tempTextAttributeWave)
     504//                      endif
     505//                      KillWaves/Z tempTextAttributeWave
     506//                      break                           
     507//                     
     508//              case "H5T_TIME":
     509//              case "H5T_COMPOUND":
     510//              case "H5T_VLEN":
     511//              case "H5T_ARRAY":
     512//                      value = "<Can't display this type here>"
     513//                      break
     514//      endswitch
     515//     
     516//      return value
     517//#else
     518//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     519//#endif
     520//End
     521//
     522//static Function FillDatasetsList(bd)
     523//      STRUCT NI2HDF5BrowserData &bd
     524//
     525//#if Exists("HDF5ListGroup")   
     526//      HDF5ListGroup /TYPE=2 bd.fileID, bd.groupPath
     527//      Variable numItemsInList = ItemsInList(S_HDF5ListGroup)
     528//     
     529//      if (numItemsInList == 0)
     530//              Redimension/N=0 bd.datasetsList
     531//      else
     532//              Redimension/N=(numItemsInList, 5) bd.datasetsList
     533//              SetDimLabel 1, 0, Dataset, bd.datasetsList
     534//              SetDimLabel 1, 1, Rank, bd.datasetsList
     535//              SetDimLabel 1, 2, 'Dim Sizes', bd.datasetsList
     536//              SetDimLabel 1, 3, Type, bd.datasetsList
     537//              SetDimLabel 1, 4, Value, bd.datasetsList
     538//              bd.datasetsList[][0] = StringFromList(p, S_HDF5ListGroup)
     539//     
     540//              String dataset
     541//              Variable i, numDatasets
     542//              Variable err
     543//              numDatasets = ItemsInList(S_HDF5ListGroup)
     544//              for(i=0; i<numDatasets; i+=1)
     545//                      dataset = StringFromList(i, S_HDF5ListGroup)
     546//                      String fullPath = NI2_HDF5GetObjectFullPath(bd.groupPath, dataset)
     547//#if(IgorVersion()<9)
     548//                      STRUCT NI2_HDF5DataInfo di
     549//                      NI2_InitHDF5DataInfo(di)                        // Set input fields.
     550//                      HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
     551//#else
     552//                      STRUCT HDF5DataInfo di
     553//                      InitHDF5DataInfo(di)                    // Set input fields.
     554//                      err = HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
     555//#endif               
     556//                     
     557//                     
     558//                      Variable rank = di.ndims
     559//                      bd.datasetsList[i][1] = num2istr(rank)
     560//                     
     561//                      String dimsStr=""
     562//                      Variable dim
     563//                      for(dim=0; dim<rank; dim+=1)
     564//                              dimsStr += num2istr(di.dims[dim]) + ";"
     565//                      endfor
     566//                      bd.datasetsList[i][2] = dimsStr
     567//
     568//                      bd.datasetsList[i][3] = di.datatype_str
     569//
     570//                      String preview = NI2_GetPreviewString(bd.fileID, 2, di, fullPath, "")
     571//                      bd.datasetsList[i][4] = preview
     572//              endfor
     573//      endif
     574//#else
     575//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     576//#endif
     577//End
     578//             
     579//static Function FillGroupAttributesList(bd)
     580//      STRUCT NI2HDF5BrowserData &bd
     581//
     582//#if Exists("HDF5ListAttributes")     
     583//      Variable numAttributes = 0
     584//      String groupPath = bd.groupPath
     585//      if (strlen(groupPath) > 0)
     586//              HDF5ListAttributes/TYPE=1 bd.fileID, groupPath
     587//              numAttributes = ItemsInList(S_HDF5ListAttributes)
     588//      endif
     589//     
     590//      if (numAttributes == 0)
     591//              Redimension/N=0 bd.groupAttributesList
     592//      else
     593//              Redimension/N=(numAttributes, 5) bd.groupAttributesList
     594//              SetDimLabel 1, 0, Attribute,bd.groupAttributesList
     595//              SetDimLabel 1, 1, Rank,bd.groupAttributesList
     596//              SetDimLabel 1, 2, 'Dim Sizes',bd.groupAttributesList
     597//              SetDimLabel 1, 3, Type,bd.groupAttributesList
     598//              SetDimLabel 1, 4, Value,bd.groupAttributesList
     599//              bd.groupAttributesList[][0] = StringFromList(p, S_HDF5ListAttributes)
     600//     
     601//              String attribute
     602//              Variable i
     603//              for(i=0; i<numAttributes; i+=1)
     604//                      String attributeName
     605//                      attributeName = StringFromList(i, S_HDF5ListAttributes)
     606//                      attribute = attributeName
     607//
     608//                      STRUCT NI2_HDF5DataInfo di
     609//                      NI2_InitHDF5DataInfo(di)                        // Set input fields.
     610//                      HDF5AttributeInfo(bd.fileID, groupPath, 1, attribute, 0, di)
     611//                     
     612//                      Variable rank = di.ndims
     613//                      bd.groupAttributesList[i][1] = num2istr(rank)
     614//                     
     615//                      String dimsStr=""
     616//                      Variable dim
     617//                      for(dim=0; dim<rank; dim+=1)
     618//                              dimsStr += num2istr(di.dims[dim]) + ";"
     619//                      endfor
     620//                      bd.groupAttributesList[i][2] = dimsStr
     621//
     622//                      bd.groupAttributesList[i][3] = di.datatype_str
     623//
     624//                      String preview = NI2_GetPreviewString(bd.fileID, 1, di, groupPath, attributeName)
     625//                      bd.groupAttributesList[i][4] = preview
     626//              endfor
     627//      endif
     628//#else
     629//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     630//#endif
     631//End
     632//             
     633//static Function FillDatasetAttributesList(bd)
     634//      STRUCT NI2HDF5BrowserData &bd
     635//
     636//#if Exists("HDF5ListAttributes")     
     637//      Variable numAttributes = 0
     638//      String datasetPath = NI2_SelectedDatasetPath(bd)
     639//      if (strlen(datasetPath) > 0)
     640//              HDF5ListAttributes/TYPE=2 bd.fileID, datasetPath
     641//              numAttributes = ItemsInList(S_HDF5ListAttributes)
     642//      endif
     643//     
     644//      if (numAttributes == 0)
     645//              Redimension/N=0 bd.datasetAttributesList
     646//      else
     647//              Redimension/N=(numAttributes, 5) bd.datasetAttributesList
     648//              SetDimLabel 1, 0, Attribute,bd.datasetAttributesList
     649//              SetDimLabel 1, 1, Rank,bd.datasetAttributesList
     650//              SetDimLabel 1, 2, 'Dim Sizes',bd.datasetAttributesList
     651//              SetDimLabel 1, 3, Type,bd.datasetAttributesList
     652//              SetDimLabel 1, 4, Value,bd.datasetAttributesList
     653//              bd.datasetAttributesList[][0] = StringFromList(p, S_HDF5ListAttributes)
     654//     
     655//              String attribute
     656//              Variable i
     657//              for(i=0; i<numAttributes; i+=1)
     658//                      String attributeName
     659//                      attributeName = StringFromList(i, S_HDF5ListAttributes)
     660//                      attribute = attributeName
     661//
     662//                      STRUCT NI2_HDF5DataInfo di
     663//                      NI2_InitHDF5DataInfo(di)                        // Set input fields.
     664//                      HDF5AttributeInfo(bd.fileID, datasetPath, 2, attribute, 0, di)
     665//                     
     666//                      Variable rank = di.ndims
     667//                      bd.datasetAttributesList[i][1] = num2istr(rank)
     668//                     
     669//                      String dimsStr=""
     670//                      Variable dim
     671//                      for(dim=0; dim<rank; dim+=1)
     672//                              dimsStr += num2istr(di.dims[dim]) + ";"
     673//                      endfor
     674//                      bd.datasetAttributesList[i][2] = dimsStr
     675//
     676//                      bd.datasetAttributesList[i][3] = di.datatype_str
     677//
     678//                      String preview = NI2_GetPreviewString(bd.fileID, 2, di, datasetPath, attributeName)
     679//                      bd.datasetAttributesList[i][4] = preview
     680//              endfor
     681//      endif
     682//#else
     683//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     684//#endif
     685//End
     686//     
     687//static Function FillLists(bd)
     688//      STRUCT NI2HDF5BrowserData &bd
     689//
     690//      if (bd.fileID == 0)                                                     // No file is open?
     691//              Redimension/N=(0) bd.groupsList
     692//              Redimension/N=(0) bd.groupAttributesList
     693//              Redimension/N=(0) bd.datasetsList
     694//              Redimension/N=(0) bd.datasetAttributesList
     695//              return -1
     696//      endif
     697//     
     698//      Variable numItemsInList
     699//      String hierarchy
     700//     
     701//      // Show entire hierarchy in Groups list.
     702//      hierarchy = GetFileHierarchy(bd, 0)     
     703//      numItemsInList = ItemsInList(hierarchy)
     704//      Redimension/N=(numItemsInList) bd.groupsList
     705//      bd.groupsList = StringFromList(p, hierarchy)
     706//     
     707//      // The groupFullPaths wave stores the full path to each group
     708//      hierarchy = GetFileHierarchy(bd, 1)     
     709//      numItemsInList = ItemsInList(hierarchy)
     710//      Redimension/N=(numItemsInList) bd.groupFullPaths
     711//      bd.groupFullPaths = StringFromList(p, hierarchy)
     712//     
     713//      // Show datasets in current group in Datasets list.
     714//      FillDatasetsList(bd)
     715//     
     716//      // Show attributes of currently-selected group.
     717//      FillGroupAttributesList(bd)
     718//     
     719//      // Show attributes of currently-selected dataset.
     720//      FillDatasetAttributesList(bd)
     721//End
     722//
     723//Function/S NI2_SelectedGroupName(bd)
     724//      STRUCT NI2HDF5BrowserData &bd
     725//     
     726//      if (numpnts(bd.groupsList) == 0)
     727//              return ""
     728//      endif
     729//
     730//      ControlInfo/W=$bd.browserName GroupsList
     731//      Variable selRow = V_value
     732//      String groupName = bd.groupsList[selRow]
     733//
     734//      // Group names may have leading spaces at this point. The spaces are used to create
     735//      // indentation in the list to show the hierarchy. We must remove the leading spaces.
     736//      sscanf groupName, " %s", groupName
     737//
     738//      if (strlen(groupName) > 0)
     739//              return groupName
     740//      endif
     741//
     742//      return ""
     743//End
     744//
     745//Function/S NI2_SelectedGroupPath(bd)
     746//      STRUCT NI2HDF5BrowserData &bd
     747//     
     748//      String groupPath = bd.groupPath
     749//
     750//      return groupPath
     751//End
     752//
     753//Function/S NI2_SelectedDatasetName(bd)
     754//      STRUCT NI2HDF5BrowserData &bd
     755//     
     756//      if (numpnts(bd.datasetsList) == 0)
     757//              return ""
     758//      endif
     759//
     760//      ControlInfo/W=$bd.browserName DatasetsList
     761//      Variable selRow = V_value
     762//      String datasetName = bd.datasetsList[selRow][0]
     763//      if (strlen(datasetName) > 0)
     764//              return datasetName
     765//      endif
     766//
     767//      return ""
     768//End
     769//
     770//Function/S NI2_SelectedDatasetPath(bd)
     771//      STRUCT NI2HDF5BrowserData &bd
     772//
     773//      String datasetName = NI2_SelectedDatasetName(bd)
     774//      if (strlen(datasetName) == 0)
     775//              return ""                                               // Nothing is selected
     776//      endif
     777//     
     778//      String datasetPath = bd.groupPath
     779//      if (CmpStr(datasetPath[strlen(datasetPath)-1],"/") != 0)
     780//              datasetPath += "/"
     781//      endif
     782//      datasetPath += datasetName
     783//
     784//      return datasetPath
     785//End
     786//
     787//Function/S NI2_SelectedAttributeName(bd, isGroupAttribute)
     788//      STRUCT NI2HDF5BrowserData &bd
     789//      Variable isGroupAttribute
     790//
     791//      String controlName
     792//      if (isGroupAttribute)
     793//              controlName = "GroupAttributesList"
     794//              Wave/T list = bd.groupAttributesList
     795//      else
     796//              controlName = "DatasetAttributesList"
     797//              Wave/T list = bd.datasetAttributesList
     798//      endif
     799//     
     800//      if (numpnts(list) == 0)
     801//              return ""
     802//      endif
     803//
     804//      ControlInfo/W=$bd.browserName $controlName
     805//      Variable selRow = V_value
     806//      String attributeName = list[selRow][0]
     807//     
     808//      if (strlen(attributeName) > 0)
     809//              return attributeName
     810//      endif
     811//
     812//      return ""
     813//End
     814//
     815//Function/S NI2_SelectedAttributePath(bd, isGroupAttribute)
     816//      STRUCT NI2HDF5BrowserData &bd
     817//      Variable isGroupAttribute
     818//
     819//      String attributeName = NI2_SelectedAttributeName(bd, isGroupAttribute)
     820//      if (strlen(attributeName) == 0)
     821//              return ""                                               // Nothing is selected
     822//      endif
     823//     
     824//      String path
     825//      if (isGroupAttribute)
     826//              path = NI2_SelectedGroupPath(bd)
     827//      else
     828//              path = NI2_SelectedDatasetPath(bd)
     829//      endif
     830//     
     831//      path += "/" + attributeName
     832//
     833//      return path
     834//End
     835//
     836//StrConstant NI2_kLoadAllMembersString = "_Load_All_Members_"
     837//
     838//static Function SetMembersPopupMenu(bd)
     839//      STRUCT NI2HDF5BrowserData &bd
     840//     
     841//#if Exists("HDF5OpenFile")   
     842//      Variable hideMembers
     843//      String memberList
     844//
     845//      hideMembers = 1
     846//      memberList = NI2_kLoadAllMembersString + ";"
     847//     
     848//      if (bd.fileID != 0)                             // File is open for this browser?
     849//              String fullPath
     850//             
     851//              fullPath = NI2_SelectedDatasetPath(bd)
     852//              if (strlen(fullPath) > 0)
     853//                      STRUCT NI2_HDF5DataInfo di
     854//                      NI2_InitHDF5DataInfo(di)
     855//                      HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
     856//                      if (CmpStr(di.datatype_class_str, "H5T_COMPOUND") == 0)
     857//                              hideMembers = 0
     858//                             
     859//                              ControlInfo /W=$bd.browserName Members
     860//                              Variable selectedItemNumber = V_Value
     861//                              STRUCT NI2_HDF5DatatypeInfo dti
     862//                              NI2_InitHDF5DatatypeInfo(dti)
     863//                              if (HDF5TypeInfo(bd.fileID, fullPath, "", "", 1, dti))
     864//                                      memberList += "HDF5TypeInfo Error!"
     865//                              else
     866//                                      memberList += dti.names
     867//                                      if (selectedItemNumber > dti.nmembers+1)        // +1 because of "_Load_All_Members_" item.
     868//                                              selectedItemNumber = 1          // Force menu selection to be in bounds.
     869//                                      endif
     870//                              endif
     871//                              PopupMenu Members, win=$bd.browserName, mode=selectedItemNumber
     872//                      endif
     873//              endif
     874//      endif
     875//     
     876//      PopupMenu Members, win=$bd.browserName, disable=hideMembers
     877//     
     878//      String cmd                              // What a pain. Can't use local variable with PopupMenu value=
     879//      sprintf cmd, "PopupMenu Members, win=%s, value=\"%s\"", bd.browserName, memberList
     880//      Execute cmd
     881//#else
     882//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     883//#endif
     884//End
     885//
     886//Function NI2_HDF5GetReadOnlySetting(browserName)
     887//      String browserName
     888//     
     889//      Variable result
     890//      ControlInfo /W=$browserName ReadOnly
     891//      result = V_value
     892//      return result
     893//End
     894//
     895//Function NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
     896//      STRUCT NI2HDF5BrowserData &bd
     897//      Variable &isCompound                                    // Output: If non-zero, a compound dataset is selected.
     898//      Variable &compMode                                              // Output: Value suitable for passing to HDF5LoadData /COMP flag.
     899//      String &memberName                                              // Output: If "" load all members.
     900//     
     901//      isCompound = 0
     902//      memberName = ""
     903//     
     904//      ControlInfo /W=$bd.browserName Members
     905//      if (V_disable == 0)
     906//              isCompound = 1
     907//              memberName = S_value
     908//              if (CmpStr(memberName, NI2_kLoadAllMembersString) == 0)
     909//                      memberName = ""
     910//              endif
     911//      endif
     912//
     913//      compMode = isCompound && strlen(memberName)>0
     914//End
     915//
     916//Function NI2_HDF5GetTranspose2DSetting(browserName)
     917//      String browserName
     918//     
     919//      Variable result
     920//      ControlInfo /W=$browserName Transpose2DDatasets
     921//      result = V_value
     922//      return result
     923//End
     924//
     925//static Function HDF5GetLoadDatasetOptions(browserName, tableDisplayMode, graphDisplayMode)
     926//      String browserName
     927//      Variable &tableDisplayMode, &graphDisplayMode
     928//     
     929//      ControlInfo /W=$browserName DisplayInTable
     930//      tableDisplayMode = V_value - 1                                          // 0=no; 1=display; 2=append
     931//     
     932//      ControlInfo /W=$browserName DisplayInGraph
     933//      graphDisplayMode = V_value - 1                                          // 0=no; 1=display; 2=append
     934//     
     935//      return tableDisplayMode || graphDisplayMode
     936//End
     937//
     938//static Function MembersPopupProc(ctrlName,popNum,popStr) : PopupMenuControl
     939//      String ctrlName
     940//      Variable popNum
     941//      String popStr
     942//     
     943//      String browserName = NI2_HDF5GetTopBrowserName()
     944//     
     945//      STRUCT NI2HDF5BrowserData bd
     946//      SetNI2HDF5BrowserData(browserName, bd)
     947//     
     948//      NI2_HDF5DisplaySelectedDataset(bd)
     949//End
     950//
     951//static Function SetButtonStates(bd)
     952//      STRUCT NI2HDF5BrowserData &bd
     953//     
     954//      if (bd.fileID == 0)                             // No file is open for this browser?
     955//              Button CreateFile, win=$bd.browserName, disable=2               // Enable Create
     956//              Button OpenFile, win=$bd.browserName, disable=0         // Enable Open
     957//              Button CloseFile, win=$bd.browserName, disable=2                // Disable Close
     958//              Button LoadGroup, win=$bd.browserName, disable=2                // Disable Load Group
     959//              Button SaveDataFolder, win=$bd.browserName, disable=2   // Disable Save Data Folder
     960//              Button LoadDataset, win=$bd.browserName, disable=2      // Disable Load Dataset
     961//              Button SaveWaves, win=$bd.browserName, disable=2                // Disable Save Waves
     962//      else
     963//              Button CreateFile, win=$bd.browserName, disable=2               // Disable Create
     964//              Button OpenFile, win=$bd.browserName, disable=2         // Disable Open
     965//              Button CloseFile, win=$bd.browserName, disable=0                // Enable Close
     966//             
     967//              String groupName = NI2_SelectedGroupName(bd)
     968//              Variable code = strlen(groupName) > 0 ? 0:2
     969//              Button LoadGroup, win=$bd.browserName, disable=code     // Enable Load Group
     970//              code = bd.readOnly == 0 ? 0:2
     971//              Button SaveDataFolder, win=$bd.browserName, disable=code        // Enable Save Data Folder
     972//             
     973//              String datasetName = NI2_SelectedDatasetName(bd)
     974//              code = strlen(datasetName) > 0 ? 0:2
     975//              Button LoadDataset, win=$bd.browserName, disable=code   // Enable Load Dataset
     976//              code = bd.readOnly == 0 ? 0:2
     977//              Button SaveWaves, win=$bd.browserName, disable=code             // Enable Save Waves
     978//              //overwrite the code above...
     979//              Button LoadGroup, win=$bd.browserName, disable=2        // Disable Load Dataset
     980//              Button LoadDataset, win=$bd.browserName, disable=2      // Disable Load Dataset
     981//      endif
     982//      SetMembersPopupMenu(bd)
     983//      SetGraphButtonTitle(bd.browserName)
     984//      SetTableButtonTitle(bd.browserName)
     985//      SetDumpButtonTitle(bd.browserName)
     986//      SetVariable HyperSelectionWave, win=$bd.browserName, value= bd.hyperSelectionWavePath
     987//End
     988//
     989//static Function DrawFilePath(bd)
     990//      STRUCT NI2HDF5BrowserData &bd
     991//     
     992//      // TitleBox FilePath, win=$bd.browserName, title=bd.fullPath                    // This is limited to 63 characters.
     993//      TitleBox FilePath, win=$bd.browserName, variable=bd.fullPath
     994//End
     995//
     996//static Function DrawGroupPath(bd)
     997//      STRUCT NI2HDF5BrowserData &bd
     998//     
     999//      TitleBox GroupPath, win=$bd.browserName, variable=bd.groupPath
     1000//End
     1001//
     1002//static Function DrawDatasetInfo(bd)
     1003//      STRUCT NI2HDF5BrowserData &bd
     1004//     
     1005//      TitleBox Dataset, win=$bd.browserName, variable=bd.datasetInfo
     1006//End
     1007//
     1008//static Function UpdateAfterFileCreateOrOpen(isCreate, browserName, fileID, path, fileName)
     1009//      Variable isCreate
     1010//      String browserName
     1011//      Variable fileID
     1012//      String path, fileName
     1013//     
     1014//      STRUCT NI2HDF5BrowserData bd
     1015//      SetNI2HDF5BrowserData(browserName, bd)
     1016//
     1017//      ResetListSelections(bd, 1, 1, 1, 1)
     1018//
     1019//      bd.fileID = fileID
     1020//      bd.fileName = fileName
     1021//      bd.path = path
     1022//      bd.fullPath = path + fileName
     1023//      DrawFilePath(bd)
     1024//     
     1025//      bd.readOnly = isCreate ? 0 : NI2_HDF5GetReadOnlySetting(browserName)
     1026//
     1027//      bd.groupPath = "/"
     1028//      DrawGroupPath(bd)
     1029//
     1030//      SetButtonStates(bd)
     1031//
     1032//      FillLists(bd)
     1033//     
     1034//      NI2_UpdateAfterGroupSelected(bd, "/")
     1035//     
     1036//      String datasetName = NI2_SelectedDatasetName(bd)
     1037//      if (strlen(datasetName) > 0)
     1038//              NI2_SelectDataset(bd, datasetName)
     1039//      endif
     1040//End
     1041//
     1042//static Function CreateFileButtonProc(ctrlName) : ButtonControl
     1043//      String ctrlName
     1044//     
     1045//#if Exists("HDF5OpenFile")   
     1046//      String browserName = NI2_HDF5GetTopBrowserName()
     1047//
     1048//      STRUCT NI2HDF5BrowserData bd
     1049//      SetNI2HDF5BrowserData(browserName, bd)
     1050//     
     1051//      Variable fileID
     1052//     
     1053//      HDF5CreateFile /I /O fileID  as ""
     1054//      if (V_flag == 0)                // Create OK?
     1055//              UpdateAfterFileCreateOrOpen(1, browserName, fileID, S_path, S_fileName)
     1056//      endif
     1057//#else
     1058//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1059//#endif
     1060//End
     1061//
     1062//static Function OpenFileButtonProc(ctrlName) : ButtonControl
     1063//      String ctrlName
     1064//     
     1065//#if Exists("HDF5OpenFile")   
     1066//      String browserName = NI2_HDF5GetTopBrowserName()
     1067//     
     1068//      Variable readOnly = NI2_HDF5GetReadOnlySetting(browserName)
     1069//     
     1070//      Variable locFileID
     1071//     
     1072//      if (readOnly)
     1073//              HDF5OpenFile/R locFileID as ""
     1074//      else
     1075//              HDF5OpenFile locFileID as ""
     1076//      endif
     1077//     
     1078//      if (V_flag == 0)                                        // Open OK?
     1079//              UpdateAfterFileCreateOrOpen(0, browserName, locFileID, S_path, S_fileName)
     1080//      endif
     1081//#else
     1082//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1083//#endif
     1084//End
     1085//
     1086//// This detects if the file is no longer open, such as if you save the experiment, quit Igor and then reopen the experiment.
     1087//Function NI2_FileWasUnexpectedlyClosed(bd)
     1088//      STRUCT NI2HDF5BrowserData &bd
     1089//
     1090//#if Exists("HDF5OpenFile")   
     1091//      if (bd.fileID == 0)
     1092//              return 0                                // File is closed but not unexpectedly.
     1093//      endif
     1094//     
     1095//      HDF5ListAttributes/Q /TYPE=1 /Z bd.fileID , "/"         // Try to list the attributes of the root of the file.
     1096//      if (V_flag != 0)
     1097//              return 1                                                                // Error: Assume file was closed.
     1098//      endif
     1099//     
     1100//      return 0
     1101//#else
     1102//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1103//#endif
     1104//End
     1105//
     1106//static Function FileWasClosed(bd)                     // Does cleanup after a file is closed.
     1107//      STRUCT NI2HDF5BrowserData &bd
     1108//
     1109//      bd.fileID = 0
     1110//      Redimension/N=(0) bd.groupFullPaths
     1111//      bd.groupPath = ""
     1112//      bd.fileName = ""
     1113//      bd.path = ""
     1114//      bd.fullPath = ""
     1115//      bd.datasetInfo = ""
     1116//
     1117//      DrawFilePath(bd)
     1118//      SetButtonStates(bd)
     1119//      FillLists(bd)
     1120//End
     1121//
     1122//static Function CloseFileButtonProc(ctrlName) : ButtonControl
     1123//      String ctrlName
     1124//     
     1125//#if Exists("HDF5OpenFile")   
     1126//      String browserName = NI2_HDF5GetTopBrowserName()
     1127//
     1128//      STRUCT NI2HDF5BrowserData bd
     1129//      SetNI2HDF5BrowserData(browserName, bd)
     1130//
     1131//      HDF5CloseFile bd.fileID
     1132//      CloseSavePanels()
     1133//      FileWasClosed(bd)
     1134//#else
     1135//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1136//#endif
     1137//End
     1138//
     1139//static Function LoadDatasetButtonProc(ctrlName) : ButtonControl
     1140//      String ctrlName
     1141//
     1142//#if Exists("HDF5OpenFile")   
     1143//      String browserName
     1144//      STRUCT NI2HDF5BrowserData bd
     1145//     
     1146//      if(stringmatch(ctrlName,"AddGrouptoList"))
     1147//             
     1148//              browserName = NI2_HDF5GetTopBrowserName()
     1149//     
     1150//              SetNI2HDF5BrowserData(browserName, bd)
     1151//             
     1152//              Wave/T DataSetNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":DataSetNames")
     1153//              Wave/T GroupNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames")
     1154//              SVAR BrowserNameFldr=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":BrowserNameFldr")
     1155//              Redimension/N=(numpnts(DataSetNames)+1) GroupNames
     1156//              GroupNames[numpnts(GroupNames)-1]=NI2_SelectedGroupPath(bd)
     1157//              BrowserNameFldr = NI2_HDF5GetTopBrowserName()
     1158//      elseif(stringmatch(ctrlName,"ClearDatasetList"))
     1159//              browserName = NI2_HDF5GetTopBrowserName()       
     1160//              SetNI2HDF5BrowserData(browserName, bd)         
     1161//              Wave/T DataSetNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":DataSetNames")
     1162//              Wave/T GroupNames=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames")
     1163//              SVAR BrowserNameFldr=$("root:Packages:"+NI2_GetHDF5LoaderLocString()+":BrowserNameFldr")
     1164//              Redimension/N=(0) DataSetNames, GroupNames
     1165////            DataSetNames[numpnts(DataSetNames)-1]=NI2_SelectedDatasetPath(bd)
     1166//              BrowserNameFldr = NI2_HDF5GetTopBrowserName()           
     1167//      else            //Old LoadDataset button...
     1168//     
     1169//              browserName = NI2_HDF5GetTopBrowserName()
     1170//     
     1171//              SetNI2HDF5BrowserData(browserName, bd)
     1172//             
     1173//              String datasetPath = NI2_SelectedDatasetPath(bd)
     1174//     
     1175//              String slabWaveStr = ""
     1176//              ControlInfo /W=$bd.browserName UseHyperSelection
     1177//              if (V_value)                                                            // Use Hyperselection is checked?
     1178//                      slabWaveStr = bd.hyperSelectionWavePath
     1179//              endif
     1180//              WAVE/Z slabWave = $slabWaveStr                  // It is OK if wave does not exist and slabWave is NULL. HDF5LoadData will simply ignore /SLAB.
     1181//             
     1182//              Variable isCompound
     1183//              String memberName
     1184//              Variable compMode
     1185//              NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
     1186//     
     1187//              // If isFormalImage is true, we are loading an image written
     1188//              // according to the HDF5 Image and Palette Specification.
     1189//              Variable isFormalImage = 0
     1190//              if (!isCompound)
     1191//                      String savedDataFolder = NI2_SetBrowserDataFolder("")                   // tempClassAttribute goes in master HDF5Browser data folder
     1192//                      HDF5LoadData /Z /O /N=tempClassAttribute /A="CLASS" /Q /VAR=1 bd.fileID, datasetPath
     1193//                      if (V_flag == 0)
     1194//                              WAVE/T tempClassAttribute                       // HDF5LoadData will have created this string
     1195//                              if (CmpStr(tempClassAttribute[0],"IMAGE") == 0)
     1196//                                      isFormalImage = 1
     1197//                              endif   
     1198//                              KillWaves/Z tempClassAttribute
     1199//                      endif
     1200//                      SetDataFolder savedDataFolder
     1201//              endif
     1202//             
     1203//              Variable tableDisplayMode, graphDisplayMode             // 0=no; 1=display; 2=append
     1204//              HDF5GetLoadDatasetOptions(bd.browserName, tableDisplayMode, graphDisplayMode)
     1205//             
     1206//              if (isFormalImage)
     1207//                      HDF5LoadImage /O /GRPH=(graphDisplayMode) /T=(tableDisplayMode) bd.fileID, datasetPath
     1208//              else
     1209//                      Variable transpose2D = NI2_HDF5GetTranspose2DSetting(bd.browserName)
     1210//                      HDF5LoadData /O /SLAB=slabWave /TRAN=(transpose2D) /COMP={compMode,memberName} /GRPH=(graphDisplayMode) /T=(tableDisplayMode) bd.fileID, datasetPath
     1211//              endif
     1212//      endif
     1213//#else
     1214//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1215//#endif
     1216//End
     1217//
     1218//static Function LoadGroupButtonProc(ctrlName) : ButtonControl
     1219//      String ctrlName
     1220//
     1221//#if Exists("HDF5OpenFile")   
     1222//      String browserName = NI2_HDF5GetTopBrowserName()
     1223//
     1224//      STRUCT NI2HDF5BrowserData bd
     1225//      SetNI2HDF5BrowserData(browserName, bd)
     1226//     
     1227//      String groupPath = NI2_SelectedGroupPath(bd)
     1228//
     1229//      ControlInfo /W=$bd.browserName LoadGroupsRecursively
     1230//      if (V_value)                                                                    // Use LoadGroupsRecursively is checked?
     1231//              HDF5LoadGroup /O /R /T /IMAG=1 :, bd.fileID, groupPath
     1232//      else
     1233//              HDF5LoadGroup /O /T /IMAG=1 :, bd.fileID, groupPath
     1234//      endif
     1235//
     1236//      // For debugging
     1237//      Variable numItems
     1238//      Variable debug = 1
     1239//      if (debug)
     1240//              Wave/Z/T groupPaths = root:groupPaths
     1241//              if (WaveExists(groupPaths))
     1242//                      numItems = ItemsInList(S_groupPaths)
     1243//                      Redimension/N=(numItems) groupPaths
     1244//                      groupPaths = StringFromList(p, S_groupPaths)
     1245//              endif
     1246//
     1247//              Wave/Z/T dataFolderPaths = root:dataFolderPaths
     1248//              if (WaveExists(dataFolderPaths))
     1249//                      numItems = ItemsInList(S_dataFolderPaths)
     1250//                      Redimension/N=(numItems) dataFolderPaths
     1251//                      dataFolderPaths = StringFromList(p, S_dataFolderPaths)
     1252//              endif
     1253//
     1254//              Wave/Z/T wavePaths = root:wavePaths
     1255//              if (WaveExists(wavePaths))
     1256//                      numItems = ItemsInList(S_objectPaths)
     1257//                      Redimension/N=(numItems) wavePaths
     1258//                      wavePaths = StringFromList(p, S_objectPaths)
     1259//              endif
     1260//      endif
     1261//#else
     1262//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1263//#endif
     1264//End
     1265//
    12581266Function NI2_AttachListWaves(bd)
    1259         STRUCT NI2HDF5BrowserData &bd
     1267        STRUCT HDF5BrowserData &bd
    12601268       
    12611269        ListBox GroupsList win=$bd.browserName, listWave=bd.groupsList
     
    12641272        ListBox DatasetAttributesList win=$bd.browserName, listWave=bd.datasetAttributesList
    12651273End
    1266 
    1267 Function NI2_HDF5BrowserPanelHook(infoStr)
    1268         String infoStr
    1269 
    1270 #if Exists("HDF5OpenFile")     
    1271         String browserName= StringByKey("WINDOW",infoStr)
    1272         String event= StringByKey("EVENT",infoStr)
    1273 
    1274         STRUCT NI2HDF5BrowserData bd
    1275         SetNI2HDF5BrowserData(browserName, bd)
    1276 
    1277         strswitch(event)
    1278                 case "activate":                                // We do not get this on Windows when the panel is first created.
    1279                         // This detects if the file is no longer open, such as if you save the experiment, quit Igor and then reopen the experiment.
    1280                         if (NI2_FileWasUnexpectedlyClosed(bd))
    1281                                 Printf "The file \"%s\" is no longer open.\r", bd.fileName
    1282                                 FileWasClosed(bd)
    1283                         endif
    1284                        
    1285                         SetGraphButtonTitle(browserName)
    1286                         SetTableButtonTitle(browserName)
    1287                         SetDumpButtonTitle(browserName)
    1288                         break
    1289 
    1290                 case "resize":
    1291                         NI2_HDF5ResizeBrowser(browserName)
    1292                         break
    1293                        
    1294                 case "moved":                   // This message was added in Igor Pro 5.04B07.
    1295                         // If this is the last HDF5 browser, save the browser window size and position.
    1296                         if (strlen(NI2_HDF5GetIndxBrowserName(1)) == 0)
    1297                                 SetPrefWindowCoords(browserName)
    1298                         endif
    1299                         break
    1300                        
    1301                 case "kill":
    1302                         if (bd.fileID != 0)
    1303                                 HDF5CloseFile bd.fileID
    1304                                 bd.fileID = 0
    1305                                 CloseSavePanels()
    1306                         endif
    1307                         KillDataFolder root:Packages:HDF5Browser:$browserName
    1308                         break
    1309         endswitch
    1310        
    1311         return 0
    1312 #else
    1313         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1314 #endif
    1315 End
    1316 
    1317 Function NI2_SelectDataset(bd, datasetName)
    1318         STRUCT NI2HDF5BrowserData &bd
    1319         String datasetName
    1320 
    1321 #if Exists("HDF5OpenFile")     
    1322         String info
    1323 
    1324         if (strlen(datasetName) == 0)
    1325                 info = ""
    1326         else
    1327                 String fullPath
    1328                 fullPath = NI2_HDF5GetObjectFullPath(bd.groupPath, datasetName)
    1329                 STRUCT NI2_HDF5DataInfo di
    1330                 NI2_InitHDF5DataInfo(di)                        // Set input fields.
    1331                 HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
    1332                 // Print s
    1333                 sprintf info, "%s, class=%s", datasetName, di.datatype_class_str
    1334         endif
    1335         bd.datasetInfo = info
    1336         DrawDatasetInfo(bd)
    1337         SetButtonStates(bd)
    1338         FillDatasetAttributesList(bd)
    1339 #else
    1340         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1341 #endif
    1342 End
    1343 
    1344 Function NI2_UpdateAfterGroupSelected(bd, fullGroupPath)
    1345         STRUCT NI2HDF5BrowserData &bd
    1346         String fullGroupPath
    1347        
    1348         Variable selectedGroupChanged = CmpStr(bd.groupPath, fullGroupPath) != 0
    1349 
    1350         bd.groupPath = fullGroupPath
    1351         DrawGroupPath(bd)
    1352         FillGroupAttributesList(bd)
    1353         FillDatasetsList(bd)
    1354 
    1355         if (selectedGroupChanged)
    1356                 ResetListSelections(bd, 0, 1, 1, 1)
    1357                 String datasetName = ""
    1358                 if (numpnts(bd.datasetsList) > 0)
    1359                         datasetName = bd.datasetsList[0][0]
    1360                 endif
    1361                 NI2_SelectDataset(bd, datasetName)
    1362         endif
    1363         SetButtonStates(bd)
    1364 End
    1365 
    1366 static Function GroupsListActionProc(s, bd) : ListboxControl
    1367         STRUCT WMListboxAction &s
    1368         STRUCT NI2HDF5BrowserData &bd
    1369        
    1370         String browserName = s.win
    1371         Variable result = 0                                                                     // As of now, the return value must always be zero.
    1372        
    1373         switch(s.eventCode)
    1374                 case 4:                                         // Cell selection
    1375                         String fullGroupPath = bd.groupFullPaths[s.row]
    1376                         NI2_UpdateAfterGroupSelected(bd, fullGroupPath)
    1377                         // Printf "Row=%d, column=%d, path=%s\r", s.row, s.col, fullGroupPath
    1378                         if (NI2_HDF5BrowserDumpIsVisible())
    1379                                 NI2_HDF5DisplayDumpOfSelGroup(bd)
    1380                         endif
    1381                         break   
    1382         endswitch
    1383 
    1384         return result
    1385 End
    1386 
    1387 static Function GroupAttributesListActionProc(s, bd) : ListboxControl
    1388         STRUCT WMListboxAction &s
    1389         STRUCT NI2HDF5BrowserData &bd
    1390        
    1391         String browserName = s.win
    1392         Variable result = 0                                                                     // As of now, the return value must always be zero.
    1393        
    1394         switch(s.eventCode)
    1395                 case 3:                                         // Double-click
    1396                         break;
    1397                        
    1398                 case 4:                                         // Cell selection
    1399                         // Printf "Row=%d, column=%d\r", s.row, s.col
    1400                         NI2_HDF5DisplaySelAttribute(bd,  1)                             // Update various windows if they are displayed
    1401                         break   
    1402         endswitch
    1403 
    1404         return result
    1405 End
    1406 
    1407 Function NI2_HandleDatasetDoubleClick(s, bd)
    1408         STRUCT WMListboxAction &s
    1409         STRUCT NI2HDF5BrowserData &bd
    1410 
    1411 #if Exists("HDF5OpenFile")     
    1412         String datasetPath = NI2_SelectedDatasetPath(bd)
    1413         if (strlen(datasetPath) == 0)
    1414                 return -1
    1415         endif
    1416        
    1417         STRUCT NI2_HDF5DataInfo di
    1418         NI2_InitHDF5DataInfo(di)
    1419         HDF5DatasetInfo(bd.fileID, datasetPath, 0, di)
    1420         switch(di.datatype_class)
    1421                 default:
    1422                         // Load dataset here.
    1423                         break   
    1424         endswitch
    1425 #else
    1426         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    1427 #endif
    1428 End
    1429 
    1430 static Function DatasetsListActionProc(s, bd) : ListboxControl
    1431         STRUCT WMListboxAction &s
    1432         STRUCT NI2HDF5BrowserData &bd
    1433        
    1434         String browserName = s.win
    1435         Variable result = 0                                                                     // As of now, the return value must always be zero.
    1436        
    1437         switch(s.eventCode)
    1438                 case 3:                                         // Double-click
    1439                         NI2_HandleDatasetDoubleClick(s, bd)
    1440                         break;
    1441                        
    1442                 case 4:                                         // Cell selection
    1443                         String name = bd.datasetsList[s.row][0]
    1444                         NI2_SelectDataset(bd, name)
    1445                         // Printf "Row=%d, column=%d, name=%s\r", s.row, s.col, name
    1446                         NI2_HDF5DisplaySelectedDataset(bd)                                      // Update various windows if they are displayed
    1447                         break   
    1448         endswitch
    1449        
    1450         return result
    1451 End
    1452 
    1453 static Function DatasetAttributesListActionProc(s, bd) : ListboxControl
    1454         STRUCT WMListboxAction &s
    1455         STRUCT NI2HDF5BrowserData &bd
    1456        
    1457         String browserName = s.win
    1458         Variable result = 0                                                                     // As of now, the return value must always be zero.
    1459        
    1460         switch(s.eventCode)
    1461                 case 3:                                         // Double-click
    1462                         break;
    1463                        
    1464                 case 4:                                         // Cell selection
    1465                         // Printf "Row=%d, column=%d\r", s.row, s.col
    1466                         NI2_HDF5DisplaySelAttribute(bd,  0)                             // Update various windows if they are displayed
    1467                         break   
    1468         endswitch
    1469        
    1470         return result
    1471 End
    1472 
    1473 static Function ListBoxActionProc(s) : ListboxControl
    1474         STRUCT WMListboxAction &s
    1475 
    1476         String browserName = s.win
    1477 
    1478         STRUCT NI2HDF5BrowserData bd
    1479         SetNI2HDF5BrowserData(browserName, bd)
    1480        
    1481         Variable result = 0                                                     // As of now, the return value must always be zero.
    1482        
    1483         strswitch(s.ctrlName)
    1484                 case "GroupsList":
    1485                         result = GroupsListActionProc(s, bd)
    1486                         break
    1487                        
    1488                 case "GroupAttributesList":
    1489                         result = GroupAttributesListActionProc(s, bd)
    1490                         break
    1491                        
    1492                 case "DatasetsList":
    1493                         result = DatasetsListActionProc(s, bd)
    1494                         break
    1495                
    1496                 case "DatasetAttributesList":
    1497                         result = DatasetAttributesListActionProc(s, bd)
    1498                         break
    1499         endswitch
    1500        
    1501         return result
    1502 End
    1503 
    1504 static Function SetGraphButtonTitle(browserName)
    1505         String browserName
    1506        
    1507         if (NI2_HDF5BrowserGraphIsVisible())
    1508                 Button Graph, win=$browserName, title="Hide Graph"
    1509         else
    1510                 Button Graph, win=$browserName, title="Show Graph"
    1511         endif   
    1512 End
    1513 
    1514 static Function GraphButtonProc(ctrlName) : ButtonControl
    1515         String ctrlName
    1516 
    1517         String browserName = NI2_HDF5GetTopBrowserName()
    1518        
    1519         if (NI2_HDF5BrowserGraphIsVisible())
    1520                 KillWIndow/Z HDF5BrowserGraph
    1521         else
    1522                 NI2_HDF5CreateBrowserGraph()                            // Create if it does not exist.
    1523         endif
    1524         SetGraphButtonTitle(browserName)
    1525 End
    1526 
    1527 static Function SetTableButtonTitle(browserName)
    1528         String browserName
    1529        
    1530         if (NI2_HDF5BrowserTableIsVisible())
    1531                 Button Table, win=$browserName, title="Hide Table"
    1532         else
    1533                 Button Table, win=$browserName, title="Show Table"
    1534         endif   
    1535 End
    1536 
    1537 static Function TableButtonProc(ctrlName) : ButtonControl
    1538         String ctrlName
    1539 
    1540         String browserName = NI2_HDF5GetTopBrowserName()
    1541        
    1542         if (NI2_HDF5BrowserTableIsVisible())
    1543                 KillWIndow/Z HDF5BrowserTable
    1544         else
    1545                 NI2_HDF5CreateBrowserTable()                            // Create if it does not exist.
    1546         endif
    1547         SetTableButtonTitle(browserName)
    1548 End
    1549 
    1550 static Function SetDumpButtonTitle(browserName)
    1551         String browserName
    1552        
    1553         if (NI2_HDF5BrowserDumpIsVisible())
    1554                 Button Dump, win=$browserName, title="Hide Dump"
    1555         else
    1556                 Button Dump, win=$browserName, title="Show Dump"
    1557         endif   
    1558 End
    1559 
    1560 static Function DumpButtonProc(ctrlName) : ButtonControl
    1561         String ctrlName
    1562 
    1563         String browserName = NI2_HDF5GetTopBrowserName()
    1564        
    1565         if (NI2_HDF5BrowserDumpIsVisible())
    1566                 Notebook HDF5DumpNotebook, visible=0
    1567         else
    1568                 NI2_HDF5CreateDumpWindow()                                              // Create if it does not exist.
    1569                 DoWindow/F HDF5DumpNotebook                     // Show it.
    1570         endif
    1571         SetDumpButtonTitle(browserName)
    1572 End
    1573 
    1574 static Function HelpButtonProc(ctrlName) : ButtonControl
    1575         String ctrlName
    1576 
    1577         DisplayHelpTopic "The HDF5 Browser"
    1578 End
    1579 
    1580 static Function CreateHDF5BrowserPanel(browserName)
    1581         String browserName
    1582        
    1583         Variable isMacintosh = 0
    1584         if (CmpStr(IgorInfo(2),"Macintosh") == 0)
    1585                 isMacintosh = 1
    1586         endif
    1587 
    1588         // Determine panel size and position
    1589         Variable left, top, right, bottom
    1590         GetPrefWindowCoords("HDF5Browser", left, top, right, bottom)    // See if prefs set.
    1591         if (right-left<200 || bottom-top<200)
    1592                 // These values are calculated to fill a typical 17 inch screen (832x624) on Macintosh.
    1593                 left = 5
    1594                 top = 50
    1595                 right = 1020
    1596                 bottom = 625
    1597         endif
    1598        
    1599         Variable readOnly, loadGroupsRecursively, transpose2DDatasets
    1600         GetPrefBrowserSettings(readOnly, loadGroupsRecursively, transpose2DDatasets)
    1601 
    1602         NewPanel /W=(left, top, right, bottom)/K=1 as "HDF5 Browser"
    1603        
    1604         DoWindow/C $browserName
    1605         DoWindow/T $browserName, browserName
    1606        
    1607         // This marks this control panel as an HDF5 browser.
    1608         SetWindow kwTopWin, userdata(HDF5BrowserName)=browserName
    1609        
    1610         SetDrawLayer ProgBack
    1611 
    1612         SetDrawEnv fstyle= 1
    1613         DrawText 18,75,"File:"
    1614 
    1615         SetDrawEnv fstyle= 1
    1616         DrawText 18,103,"Selected Group:"
    1617 
    1618         SetDrawEnv fstyle= 1
    1619         DrawText 18,130,"Selected Dataset:"
    1620 
    1621         TitleBox FilePath,pos={55,57},size={706,21}
    1622 
    1623         left = isMacintosh ? 150 : 125
    1624         TitleBox GroupPath,pos={left,86},size={658,20}
    1625         TitleBox Dataset,pos={left,113},size={13,21}
    1626 
    1627         CheckBox UseHyperSelection,pos={15,155},size={110,14},title="Use Hyperselection",value= 0
    1628         CheckBox UseHyperSelection,help={"For experts only. Allows loading a subset of a dataset."}
    1629 
    1630         SetVariable HyperSelectionWave,pos={140,155},size={340,16},title="Hyper Selection Wave:"
    1631         SetVariable HyperSelectionWave,help={"Enter full path to wave containing hyperselection information. See HDF5LoadData /SLAB keyword help."}
    1632 
    1633         CheckBox LoadGroupsRecursively,pos={15,181},size={137,14},title="Load Groups Recursively",value=loadGroupsRecursively
    1634         CheckBox LoadGroupsRecursively,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, the Load Group button loads subgroups."}
    1635        
    1636         Button CreateFile,pos={15,8},size={125,20},proc=NikaHDF5Browser#CreateFileButtonProc,title="Create HDF5 File", disable=1
    1637         Button OpenFile,pos={159,8},size={125,20},proc=NikaHDF5Browser#OpenFileButtonProc,title="Open HDF5 File"
    1638         Button CloseFile,pos={296,8},size={125,20},proc=NikaHDF5Browser#CloseFileButtonProc,title="Close HDF5 File"
    1639         Button Help,pos={435,8},size={50,20},proc=NikaHDF5Browser#HelpButtonProc,title="Help"
    1640         CheckBox ReadOnly,pos={186,32},size={68,14},title="Read Only",proc=HDF5BrowserPrefCheckboxProc,value=readOnly
    1641 
    1642         // Start Preview
    1643 
    1644         Button Graph,pos={556,27},size={90,20},proc=NikaHDF5Browser#GraphButtonProc,title="Show Graph"
    1645         Button Graph help={"Shows or hides a graph which displays the last dataset or attribute that you selected."}
    1646 
    1647         Button Table,pos={672,27},size={90,20},proc=NikaHDF5Browser#TableButtonProc,title="Show Table"
    1648         Button Table help={"Shows or hides a table which displays the last dataset or attribute that you selected."}
    1649 
    1650         Button Dump,pos={556,59},size={90,20},proc=NikaHDF5Browser#DumpButtonProc,title="Show Dump"
    1651         Button Dump help={"Shows or hides a window which displays a dump of the last dataset or attribute that you selected."}
    1652 
    1653         CheckBox ShowAttributesInDump,pos={653,71},size={100,14},title="Show Attributes In Dump"
    1654         CheckBox ShowAttributesInDump help={"Check to display the dataset's attributes in the dump window."}
    1655 
    1656         CheckBox ShowDataInDump,pos={653,56},size={114,14},title="Show Data In Dump"
    1657         CheckBox ShowDataInDump,help={"Check to display data in the dump window. For large datasets this can take a long time."}
    1658 
    1659         GroupBox PreviewOptions,pos={543,5},size={258,87},title="Preview Options"
    1660 
    1661         // End Preview
    1662 
    1663         TitleBox GroupsTitle,pos={15,230},size={50,16},disable=2,title="Groups",fSize=14
    1664         TitleBox GroupsTitle,frame=0,fStyle=1
    1665 
    1666         ListBox GroupsList,pos={15,250},size={306,170}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
    1667         ListBox GroupsList,fSize=14
    1668 
    1669         Button LoadGroup,pos={80,224},size={100,20},proc=NikaHDF5Browser#LoadGroupButtonProc,title="Load Group"
    1670         Button LoadGroup,help={"Loads the currently selected group into the current data folder."}
    1671 
    1672         Button SaveDataFolder,pos={194,224},size={120,20},proc=NikaHDF5Browser#SaveDataFolderButtonProc,title="Save Data Folder"
    1673         Button SaveDataFolder,help={"Saves a data folder in the currently selected group. Available if the current HDF5 file is open for read/write."}
    1674 
    1675         TitleBox GroupAttributesTitle,pos={15,435},size={111,16},disable=2,title="Group Attributes"
    1676         TitleBox GroupAttributesTitle,fSize=14,frame=0,fStyle=1
    1677 
    1678         ListBox GroupAttributesList,pos={15,455},size={306,109}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
    1679         ListBox GroupAttributesList, widths={175,40,80,120,1000}, userColumnResize= 1   // userColumnResize requires Igor Pro 5.02.
    1680         ListBox GroupAttributesList,fSize=14
    1681 
    1682         TitleBox DatasetsTitle,pos={341,230},size={62,16},disable=2,title="Datasets"
    1683         TitleBox DatasetsTitle,fSize=14,frame=0,fStyle=1
    1684 
    1685         ListBox DatasetsList,pos={341,250},size={459,170}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
    1686         ListBox DatasetsList, widths={175,40,80,120,1000}, userColumnResize= 1  // userColumnResize requires Igor Pro 5.02.
    1687         ListBox DatasetsList,fSize=14
    1688 
    1689         TitleBox DatasetAttributesTitle,pos={341,435},size={123,16},disable=2,title="Dataset Attributes"
    1690         TitleBox DatasetAttributesTitle,fSize=14,frame=0,fStyle=1
    1691 
    1692         ListBox DatasetAttributesList,pos={341,455},size={459,109}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
    1693         ListBox DatasetAttributesList, widths={175,40,80,120,1000}, userColumnResize= 1 // userColumnResize requires Igor Pro 5.02.
    1694         ListBox DatasetAttributesList,fSize=14
    1695 
    1696 
    1697         Button LoadDataset,pos={415,224},size={100,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Load Dataset"
    1698         Button LoadDataset,help={"Loads the currently selected dataset into the current data folder."}
    1699 
    1700         Button SaveWaves,pos={529,224},size={100,20},proc=NikaHDF5Browser#SaveWavesButtonProc,title="Save Waves"
    1701         Button SaveWaves,help={"Saves waves in the currently selected group. Available if the current HDF5 file is open for read/write."}
    1702 
    1703         CheckBox Transpose2DDatasets,pos={189,181},size={130,14},title="Transpose 2D Datasets",value=transpose2DDatasets
    1704         CheckBox Transpose2DDatasets,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, 2D datasets are transposed so that Igor image plots will match HDFView."}
    1705 
    1706         PopupMenu Members,pos={342,194},size={216,24},title="Members"
    1707         PopupMenu Members,mode=1,value= #"\"Load All Members\""
    1708         PopupMenu Members proc=HDF5Browser#MembersPopupProc
    1709         PopupMenu Members,help={"Choose the compound member to preview or load."}
    1710         //Nika stuff
    1711 //      Wave/O/N=0/T DataSetNames, GroupNames           //these are pointes to waht user wants to get into Igor...
    1712         TitleBox NikaDataSetsTitle,pos={801,10},size={62,16},disable=2,title="Selected Datasets"
    1713         TitleBox NikaDataSetsTitle,fSize=14,frame=0,fStyle=1
    1714 
    1715         string tempWvName="root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames"
    1716         ListBox NikaGroupList,pos={755,35},size={220,200}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
    1717         ListBox NikaGroupList, widths={175,40,80,120,1000}, userColumnResize= 1 // userColumnResize requires Igor Pro 5.02.
    1718         ListBox NikaGroupList,fSize=14, listwave=$(tempWvName)
    1719 
    1720         Button AddGrouptoList,pos={600,200},size={150,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Add Group to Nika List"
    1721         Button AddGrouptoList,help={"Loads the currently selected Group into the current data folder."}
    1722         Button ClearDatasetList,pos={600,200},size={150,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Clear Nika List"
    1723         Button ClearDatasetList,help={"Clears Nika list of selected datasets"}
    1724 
    1725 
    1726         // Load Dataset Options
    1727         PopupMenu DisplayInTable,pos={565,123},size={200,24},title="Table:"
    1728         PopupMenu DisplayInTable,mode=2,value= #"\"No Table;Display in New Table;Append to Top Table\""
    1729         PopupMenu DisplayInGraph,pos={563,154},size={203,24},title="Graph:"
    1730         PopupMenu DisplayInGraph,mode=2,value= #"\"No Graph;Display in New Graph;Append to Top Graph\""
    1731         GroupBox LoadDatasetOptions,pos={542,100},size={258,87},title="Load Dataset Options"
    1732        
    1733         NI2_HDF5ResizeBrowser(browserName)              // Needed because we used preferred browser size.
    1734        
    1735         SetWindow kwTopWin,hook=NI2_HDF5BrowserPanelHook
    1736 EndMacro
    1737 
    1738 
    1739 static Function/S NI2_GetHDF5LoaderLocString()
    1740        
    1741         string CurPanelName = WinName(0,64)
    1742         if(stringmatch(CurPanelName[0,3],"Nika"))
    1743                 return "NikaHDF5Loader"
    1744         elseif(stringmatch(CurPanelName[0,4],"Irena"))
    1745                 return "IrenaHDF5Loader"
    1746         else
    1747                 return ""
    1748         endif
    1749 end
    1750 
    1751 Function NI2_HDF5BrowserPrefCheckboxProc(ctrlName,checked) : CheckBoxControl
    1752         String ctrlName
    1753         Variable checked
    1754        
    1755         STRUCT NI2_HDF5BrowserPrefs prefs
    1756        
    1757         NI2_HDF5BrowserLoadPackagePrefs(prefs)
    1758         strswitch(ctrlName)
    1759                 case "ReadOnly":
    1760                         prefs.readOnly = checked
    1761                         break
    1762                
    1763                 case "LoadGroupsRecursively":
    1764                         prefs.loadGroupsRecursively = checked
    1765                         break
    1766                
    1767                 case "Transpose2DDatasets":
    1768                         prefs.transpose2DDatasets = checked
    1769                         break
    1770                        
    1771                 case "SaveGroupsRecursively":
    1772                         prefs.saveGroupsRecursively = checked
    1773                         break
    1774                        
    1775                 case "IncludeIgorAttributes":
    1776                         prefs.includeIgorAttributes = checked
    1777                         break
    1778                
    1779         endswitch
    1780         NI2_HDF5BrowserSavePackagePrefs(prefs)
    1781 End
    1782 
     1274//
     1275//Function NI2_HDF5BrowserPanelHook(infoStr)
     1276//      String infoStr
     1277//
     1278//#if Exists("HDF5OpenFile")   
     1279//      String browserName= StringByKey("WINDOW",infoStr)
     1280//      String event= StringByKey("EVENT",infoStr)
     1281//
     1282//      STRUCT NI2HDF5BrowserData bd
     1283//      SetNI2HDF5BrowserData(browserName, bd)
     1284//
     1285//      strswitch(event)
     1286//              case "activate":                                // We do not get this on Windows when the panel is first created.
     1287//                      // This detects if the file is no longer open, such as if you save the experiment, quit Igor and then reopen the experiment.
     1288//                      if (NI2_FileWasUnexpectedlyClosed(bd))
     1289//                              Printf "The file \"%s\" is no longer open.\r", bd.fileName
     1290//                              FileWasClosed(bd)
     1291//                      endif
     1292//                     
     1293//                      SetGraphButtonTitle(browserName)
     1294//                      SetTableButtonTitle(browserName)
     1295//                      SetDumpButtonTitle(browserName)
     1296//                      break
     1297//
     1298//              case "resize":
     1299//                      NI2_HDF5ResizeBrowser(browserName)
     1300//                      break
     1301//                     
     1302//              case "moved":                   // This message was added in Igor Pro 5.04B07.
     1303//                      // If this is the last HDF5 browser, save the browser window size and position.
     1304//                      if (strlen(NI2_HDF5GetIndxBrowserName(1)) == 0)
     1305//                              SetPrefWindowCoords(browserName)
     1306//                      endif
     1307//                      break
     1308//                     
     1309//              case "kill":
     1310//                      if (bd.fileID != 0)
     1311//                              HDF5CloseFile bd.fileID
     1312//                              bd.fileID = 0
     1313//                              CloseSavePanels()
     1314//                      endif
     1315//                      KillDataFolder root:Packages:HDF5Browser:$browserName
     1316//                      break
     1317//      endswitch
     1318//     
     1319//      return 0
     1320//#else
     1321//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1322//#endif
     1323//End
     1324//
     1325//Function NI2_SelectDataset(bd, datasetName)
     1326//      STRUCT NI2HDF5BrowserData &bd
     1327//      String datasetName
     1328//
     1329//#if Exists("HDF5OpenFile")   
     1330//      String info
     1331//
     1332//      if (strlen(datasetName) == 0)
     1333//              info = ""
     1334//      else
     1335//              String fullPath
     1336//              fullPath = NI2_HDF5GetObjectFullPath(bd.groupPath, datasetName)
     1337//              STRUCT NI2_HDF5DataInfo di
     1338//              NI2_InitHDF5DataInfo(di)                        // Set input fields.
     1339//              HDF5DatasetInfo(bd.fileID, fullPath, 0, di)
     1340//              // Print s
     1341//              sprintf info, "%s, class=%s", datasetName, di.datatype_class_str
     1342//      endif
     1343//      bd.datasetInfo = info
     1344//      DrawDatasetInfo(bd)
     1345//      SetButtonStates(bd)
     1346//      FillDatasetAttributesList(bd)
     1347//#else
     1348//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1349//#endif
     1350//End
     1351//
     1352//Function NI2_UpdateAfterGroupSelected(bd, fullGroupPath)
     1353//      STRUCT NI2HDF5BrowserData &bd
     1354//      String fullGroupPath
     1355//     
     1356//      Variable selectedGroupChanged = CmpStr(bd.groupPath, fullGroupPath) != 0
     1357//
     1358//      bd.groupPath = fullGroupPath
     1359//      DrawGroupPath(bd)
     1360//      FillGroupAttributesList(bd)
     1361//      FillDatasetsList(bd)
     1362//
     1363//      if (selectedGroupChanged)
     1364//              ResetListSelections(bd, 0, 1, 1, 1)
     1365//              String datasetName = ""
     1366//              if (numpnts(bd.datasetsList) > 0)
     1367//                      datasetName = bd.datasetsList[0][0]
     1368//              endif
     1369//              NI2_SelectDataset(bd, datasetName)
     1370//      endif
     1371//      SetButtonStates(bd)
     1372//End
     1373//
     1374//static Function GroupsListActionProc(s, bd) : ListboxControl
     1375//      STRUCT WMListboxAction &s
     1376//      STRUCT NI2HDF5BrowserData &bd
     1377//     
     1378//      String browserName = s.win
     1379//      Variable result = 0                                                                     // As of now, the return value must always be zero.
     1380//     
     1381//      switch(s.eventCode)
     1382//              case 4:                                         // Cell selection
     1383//                      String fullGroupPath = bd.groupFullPaths[s.row]
     1384//                      NI2_UpdateAfterGroupSelected(bd, fullGroupPath)
     1385//                      // Printf "Row=%d, column=%d, path=%s\r", s.row, s.col, fullGroupPath
     1386//                      if (NI2_HDF5BrowserDumpIsVisible())
     1387//                              NI2_HDF5DisplayDumpOfSelGroup(bd)
     1388//                      endif
     1389//                      break   
     1390//      endswitch
     1391//
     1392//      return result
     1393//End
     1394//
     1395//static Function GroupAttributesListActionProc(s, bd) : ListboxControl
     1396//      STRUCT WMListboxAction &s
     1397//      STRUCT NI2HDF5BrowserData &bd
     1398//     
     1399//      String browserName = s.win
     1400//      Variable result = 0                                                                     // As of now, the return value must always be zero.
     1401//     
     1402//      switch(s.eventCode)
     1403//              case 3:                                         // Double-click
     1404//                      break;
     1405//                     
     1406//              case 4:                                         // Cell selection
     1407//                      // Printf "Row=%d, column=%d\r", s.row, s.col
     1408//                      NI2_HDF5DisplaySelAttribute(bd,  1)                             // Update various windows if they are displayed
     1409//                      break   
     1410//      endswitch
     1411//
     1412//      return result
     1413//End
     1414//
     1415//Function NI2_HandleDatasetDoubleClick(s, bd)
     1416//      STRUCT WMListboxAction &s
     1417//      STRUCT NI2HDF5BrowserData &bd
     1418//
     1419//#if Exists("HDF5OpenFile")   
     1420//      String datasetPath = NI2_SelectedDatasetPath(bd)
     1421//      if (strlen(datasetPath) == 0)
     1422//              return -1
     1423//      endif
     1424//     
     1425//      STRUCT NI2_HDF5DataInfo di
     1426//      NI2_InitHDF5DataInfo(di)
     1427//      HDF5DatasetInfo(bd.fileID, datasetPath, 0, di)
     1428//      switch(di.datatype_class)
     1429//              default:
     1430//                      // Load dataset here.
     1431//                      break   
     1432//      endswitch
     1433//#else
     1434//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     1435//#endif
     1436//End
     1437//
     1438//static Function DatasetsListActionProc(s, bd) : ListboxControl
     1439//      STRUCT WMListboxAction &s
     1440//      STRUCT NI2HDF5BrowserData &bd
     1441//     
     1442//      String browserName = s.win
     1443//      Variable result = 0                                                                     // As of now, the return value must always be zero.
     1444//     
     1445//      switch(s.eventCode)
     1446//              case 3:                                         // Double-click
     1447//                      NI2_HandleDatasetDoubleClick(s, bd)
     1448//                      break;
     1449//                     
     1450//              case 4:                                         // Cell selection
     1451//                      String name = bd.datasetsList[s.row][0]
     1452//                      NI2_SelectDataset(bd, name)
     1453//                      // Printf "Row=%d, column=%d, name=%s\r", s.row, s.col, name
     1454//                      NI2_HDF5DisplaySelectedDataset(bd)                                      // Update various windows if they are displayed
     1455//                      break   
     1456//      endswitch
     1457//     
     1458//      return result
     1459//End
     1460//
     1461//static Function DatasetAttributesListActionProc(s, bd) : ListboxControl
     1462//      STRUCT WMListboxAction &s
     1463//      STRUCT NI2HDF5BrowserData &bd
     1464//     
     1465//      String browserName = s.win
     1466//      Variable result = 0                                                                     // As of now, the return value must always be zero.
     1467//     
     1468//      switch(s.eventCode)
     1469//              case 3:                                         // Double-click
     1470//                      break;
     1471//                     
     1472//              case 4:                                         // Cell selection
     1473//                      // Printf "Row=%d, column=%d\r", s.row, s.col
     1474//                      NI2_HDF5DisplaySelAttribute(bd,  0)                             // Update various windows if they are displayed
     1475//                      break   
     1476//      endswitch
     1477//     
     1478//      return result
     1479//End
     1480//
     1481//static Function ListBoxActionProc(s) : ListboxControl
     1482//      STRUCT WMListboxAction &s
     1483//
     1484//      String browserName = s.win
     1485//
     1486//      STRUCT NI2HDF5BrowserData bd
     1487//      SetNI2HDF5BrowserData(browserName, bd)
     1488//     
     1489//      Variable result = 0                                                     // As of now, the return value must always be zero.
     1490//     
     1491//      strswitch(s.ctrlName)
     1492//              case "GroupsList":
     1493//                      result = GroupsListActionProc(s, bd)
     1494//                      break
     1495//                     
     1496//              case "GroupAttributesList":
     1497//                      result = GroupAttributesListActionProc(s, bd)
     1498//                      break
     1499//                     
     1500//              case "DatasetsList":
     1501//                      result = DatasetsListActionProc(s, bd)
     1502//                      break
     1503//             
     1504//              case "DatasetAttributesList":
     1505//                      result = DatasetAttributesListActionProc(s, bd)
     1506//                      break
     1507//      endswitch
     1508//     
     1509//      return result
     1510//End
     1511//
     1512//static Function SetGraphButtonTitle(browserName)
     1513//      String browserName
     1514//     
     1515//      if (NI2_HDF5BrowserGraphIsVisible())
     1516//              Button Graph, win=$browserName, title="Hide Graph"
     1517//      else
     1518//              Button Graph, win=$browserName, title="Show Graph"
     1519//      endif   
     1520//End
     1521//
     1522//static Function GraphButtonProc(ctrlName) : ButtonControl
     1523//      String ctrlName
     1524//
     1525//      String browserName = NI2_HDF5GetTopBrowserName()
     1526//     
     1527//      if (NI2_HDF5BrowserGraphIsVisible())
     1528//              KillWIndow/Z HDF5BrowserGraph
     1529//      else
     1530//              NI2_HDF5CreateBrowserGraph()                            // Create if it does not exist.
     1531//      endif
     1532//      SetGraphButtonTitle(browserName)
     1533//End
     1534//
     1535//static Function SetTableButtonTitle(browserName)
     1536//      String browserName
     1537//     
     1538//      if (NI2_HDF5BrowserTableIsVisible())
     1539//              Button Table, win=$browserName, title="Hide Table"
     1540//      else
     1541//              Button Table, win=$browserName, title="Show Table"
     1542//      endif   
     1543//End
     1544//
     1545//static Function TableButtonProc(ctrlName) : ButtonControl
     1546//      String ctrlName
     1547//
     1548//      String browserName = NI2_HDF5GetTopBrowserName()
     1549//     
     1550//      if (NI2_HDF5BrowserTableIsVisible())
     1551//              KillWIndow/Z HDF5BrowserTable
     1552//      else
     1553//              NI2_HDF5CreateBrowserTable()                            // Create if it does not exist.
     1554//      endif
     1555//      SetTableButtonTitle(browserName)
     1556//End
     1557//
     1558//static Function SetDumpButtonTitle(browserName)
     1559//      String browserName
     1560//     
     1561//      if (NI2_HDF5BrowserDumpIsVisible())
     1562//              Button Dump, win=$browserName, title="Hide Dump"
     1563//      else
     1564//              Button Dump, win=$browserName, title="Show Dump"
     1565//      endif   
     1566//End
     1567//
     1568//static Function DumpButtonProc(ctrlName) : ButtonControl
     1569//      String ctrlName
     1570//
     1571//      String browserName = NI2_HDF5GetTopBrowserName()
     1572//     
     1573//      if (NI2_HDF5BrowserDumpIsVisible())
     1574//              Notebook HDF5DumpNotebook, visible=0
     1575//      else
     1576//              NI2_HDF5CreateDumpWindow()                                              // Create if it does not exist.
     1577//              DoWindow/F HDF5DumpNotebook                     // Show it.
     1578//      endif
     1579//      SetDumpButtonTitle(browserName)
     1580//End
     1581//
     1582//static Function HelpButtonProc(ctrlName) : ButtonControl
     1583//      String ctrlName
     1584//
     1585//      DisplayHelpTopic "The HDF5 Browser"
     1586//End
     1587//
     1588//static Function CreateHDF5BrowserPanel(browserName)
     1589//      String browserName
     1590//     
     1591//      Variable isMacintosh = 0
     1592//      if (CmpStr(IgorInfo(2),"Macintosh") == 0)
     1593//              isMacintosh = 1
     1594//      endif
     1595//
     1596//      // Determine panel size and position
     1597//      Variable left, top, right, bottom
     1598//      GetPrefWindowCoords("HDF5Browser", left, top, right, bottom)    // See if prefs set.
     1599//      if (right-left<200 || bottom-top<200)
     1600//              // These values are calculated to fill a typical 17 inch screen (832x624) on Macintosh.
     1601//              left = 5
     1602//              top = 50
     1603//              right = 1020
     1604//              bottom = 625
     1605//      endif
     1606//     
     1607//      Variable readOnly, loadGroupsRecursively, transpose2DDatasets
     1608//      GetPrefBrowserSettings(readOnly, loadGroupsRecursively, transpose2DDatasets)
     1609//
     1610//      NewPanel /W=(left, top, right, bottom)/K=1 as "HDF5 Browser"
     1611//     
     1612//      DoWindow/C $browserName
     1613//      DoWindow/T $browserName, browserName
     1614//     
     1615//      // This marks this control panel as an HDF5 browser.
     1616//      SetWindow kwTopWin, userdata(HDF5BrowserName)=browserName
     1617//     
     1618//      SetDrawLayer ProgBack
     1619//
     1620//      SetDrawEnv fstyle= 1
     1621//      DrawText 18,75,"File:"
     1622//
     1623//      SetDrawEnv fstyle= 1
     1624//      DrawText 18,103,"Selected Group:"
     1625//
     1626//      SetDrawEnv fstyle= 1
     1627//      DrawText 18,130,"Selected Dataset:"
     1628//
     1629//      TitleBox FilePath,pos={55,57},size={706,21}
     1630//
     1631//      left = isMacintosh ? 150 : 125
     1632//      TitleBox GroupPath,pos={left,86},size={658,20}
     1633//      TitleBox Dataset,pos={left,113},size={13,21}
     1634//
     1635//      CheckBox UseHyperSelection,pos={15,155},size={110,14},title="Use Hyperselection",value= 0
     1636//      CheckBox UseHyperSelection,help={"For experts only. Allows loading a subset of a dataset."}
     1637//
     1638//      SetVariable HyperSelectionWave,pos={140,155},size={340,16},title="Hyper Selection Wave:"
     1639//      SetVariable HyperSelectionWave,help={"Enter full path to wave containing hyperselection information. See HDF5LoadData /SLAB keyword help."}
     1640//
     1641//      CheckBox LoadGroupsRecursively,pos={15,181},size={137,14},title="Load Groups Recursively",value=loadGroupsRecursively
     1642//      CheckBox LoadGroupsRecursively,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, the Load Group button loads subgroups."}
     1643//     
     1644//      Button CreateFile,pos={15,8},size={125,20},proc=NikaHDF5Browser#CreateFileButtonProc,title="Create HDF5 File", disable=1
     1645//      Button OpenFile,pos={159,8},size={125,20},proc=NikaHDF5Browser#OpenFileButtonProc,title="Open HDF5 File"
     1646//      Button CloseFile,pos={296,8},size={125,20},proc=NikaHDF5Browser#CloseFileButtonProc,title="Close HDF5 File"
     1647//      Button Help,pos={435,8},size={50,20},proc=NikaHDF5Browser#HelpButtonProc,title="Help"
     1648//      CheckBox ReadOnly,pos={186,32},size={68,14},title="Read Only",proc=HDF5BrowserPrefCheckboxProc,value=readOnly
     1649//
     1650//      // Start Preview
     1651//
     1652//      Button Graph,pos={556,27},size={90,20},proc=NikaHDF5Browser#GraphButtonProc,title="Show Graph"
     1653//      Button Graph help={"Shows or hides a graph which displays the last dataset or attribute that you selected."}
     1654//
     1655//      Button Table,pos={672,27},size={90,20},proc=NikaHDF5Browser#TableButtonProc,title="Show Table"
     1656//      Button Table help={"Shows or hides a table which displays the last dataset or attribute that you selected."}
     1657//
     1658//      Button Dump,pos={556,59},size={90,20},proc=NikaHDF5Browser#DumpButtonProc,title="Show Dump"
     1659//      Button Dump help={"Shows or hides a window which displays a dump of the last dataset or attribute that you selected."}
     1660//
     1661//      CheckBox ShowAttributesInDump,pos={653,71},size={100,14},title="Show Attributes In Dump"
     1662//      CheckBox ShowAttributesInDump help={"Check to display the dataset's attributes in the dump window."}
     1663//
     1664//      CheckBox ShowDataInDump,pos={653,56},size={114,14},title="Show Data In Dump"
     1665//      CheckBox ShowDataInDump,help={"Check to display data in the dump window. For large datasets this can take a long time."}
     1666//
     1667//      GroupBox PreviewOptions,pos={543,5},size={258,87},title="Preview Options"
     1668//
     1669//      // End Preview
     1670//
     1671//      TitleBox GroupsTitle,pos={15,230},size={50,16},disable=2,title="Groups",fSize=14
     1672//      TitleBox GroupsTitle,frame=0,fStyle=1
     1673//
     1674//      ListBox GroupsList,pos={15,250},size={306,170}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
     1675//      ListBox GroupsList,fSize=14
     1676//
     1677//      Button LoadGroup,pos={80,224},size={100,20},proc=NikaHDF5Browser#LoadGroupButtonProc,title="Load Group"
     1678//      Button LoadGroup,help={"Loads the currently selected group into the current data folder."}
     1679//
     1680//      Button SaveDataFolder,pos={194,224},size={120,20},proc=NikaHDF5Browser#SaveDataFolderButtonProc,title="Save Data Folder"
     1681//      Button SaveDataFolder,help={"Saves a data folder in the currently selected group. Available if the current HDF5 file is open for read/write."}
     1682//
     1683//      TitleBox GroupAttributesTitle,pos={15,435},size={111,16},disable=2,title="Group Attributes"
     1684//      TitleBox GroupAttributesTitle,fSize=14,frame=0,fStyle=1
     1685//
     1686//      ListBox GroupAttributesList,pos={15,455},size={306,109}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
     1687//      ListBox GroupAttributesList, widths={175,40,80,120,1000}, userColumnResize= 1   // userColumnResize requires Igor Pro 5.02.
     1688//      ListBox GroupAttributesList,fSize=14
     1689//
     1690//      TitleBox DatasetsTitle,pos={341,230},size={62,16},disable=2,title="Datasets"
     1691//      TitleBox DatasetsTitle,fSize=14,frame=0,fStyle=1
     1692//
     1693//      ListBox DatasetsList,pos={341,250},size={459,170}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
     1694//      ListBox DatasetsList, widths={175,40,80,120,1000}, userColumnResize= 1  // userColumnResize requires Igor Pro 5.02.
     1695//      ListBox DatasetsList,fSize=14
     1696//
     1697//      TitleBox DatasetAttributesTitle,pos={341,435},size={123,16},disable=2,title="Dataset Attributes"
     1698//      TitleBox DatasetAttributesTitle,fSize=14,frame=0,fStyle=1
     1699//
     1700//      ListBox DatasetAttributesList,pos={341,455},size={459,109}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
     1701//      ListBox DatasetAttributesList, widths={175,40,80,120,1000}, userColumnResize= 1 // userColumnResize requires Igor Pro 5.02.
     1702//      ListBox DatasetAttributesList,fSize=14
     1703//
     1704//
     1705//      Button LoadDataset,pos={415,224},size={100,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Load Dataset"
     1706//      Button LoadDataset,help={"Loads the currently selected dataset into the current data folder."}
     1707//
     1708//      Button SaveWaves,pos={529,224},size={100,20},proc=NikaHDF5Browser#SaveWavesButtonProc,title="Save Waves"
     1709//      Button SaveWaves,help={"Saves waves in the currently selected group. Available if the current HDF5 file is open for read/write."}
     1710//
     1711//      CheckBox Transpose2DDatasets,pos={189,181},size={130,14},title="Transpose 2D Datasets",value=transpose2DDatasets
     1712//      CheckBox Transpose2DDatasets,proc=HDF5BrowserPrefCheckboxProc,help={"When checked, 2D datasets are transposed so that Igor image plots will match HDFView."}
     1713//
     1714//      PopupMenu Members,pos={342,194},size={216,24},title="Members"
     1715//      PopupMenu Members,mode=1,value= #"\"Load All Members\""
     1716//      PopupMenu Members proc=HDF5Browser#MembersPopupProc
     1717//      PopupMenu Members,help={"Choose the compound member to preview or load."}
     1718//      //Nika stuff
     1719////    Wave/O/N=0/T DataSetNames, GroupNames           //these are pointes to waht user wants to get into Igor...
     1720//      TitleBox NikaDataSetsTitle,pos={801,10},size={62,16},disable=2,title="Selected Datasets"
     1721//      TitleBox NikaDataSetsTitle,fSize=14,frame=0,fStyle=1
     1722//
     1723//      string tempWvName="root:Packages:"+NI2_GetHDF5LoaderLocString()+":GroupNames"
     1724//      ListBox NikaGroupList,pos={755,35},size={220,200}, mode=2, proc=NikaHDF5Browser#ListBoxActionProc
     1725//      ListBox NikaGroupList, widths={175,40,80,120,1000}, userColumnResize= 1 // userColumnResize requires Igor Pro 5.02.
     1726//      ListBox NikaGroupList,fSize=14, listwave=$(tempWvName)
     1727//
     1728//      Button AddGrouptoList,pos={600,200},size={150,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Add Group to Nika List"
     1729//      Button AddGrouptoList,help={"Loads the currently selected Group into the current data folder."}
     1730//      Button ClearDatasetList,pos={600,200},size={150,20},proc=NikaHDF5Browser#LoadDatasetButtonProc,title="Clear Nika List"
     1731//      Button ClearDatasetList,help={"Clears Nika list of selected datasets"}
     1732//
     1733//
     1734//      // Load Dataset Options
     1735//      PopupMenu DisplayInTable,pos={565,123},size={200,24},title="Table:"
     1736//      PopupMenu DisplayInTable,mode=2,value= #"\"No Table;Display in New Table;Append to Top Table\""
     1737//      PopupMenu DisplayInGraph,pos={563,154},size={203,24},title="Graph:"
     1738//      PopupMenu DisplayInGraph,mode=2,value= #"\"No Graph;Display in New Graph;Append to Top Graph\""
     1739//      GroupBox LoadDatasetOptions,pos={542,100},size={258,87},title="Load Dataset Options"
     1740//     
     1741//      NI2_HDF5ResizeBrowser(browserName)              // Needed because we used preferred browser size.
     1742//     
     1743//      SetWindow kwTopWin,hook=NI2_HDF5BrowserPanelHook
     1744//EndMacro
     1745//
     1746//
     1747//static Function/S NI2_GetHDF5LoaderLocString()
     1748//     
     1749//      string CurPanelName = WinName(0,64)
     1750//      if(stringmatch(CurPanelName[0,3],"Nika"))
     1751//              return "NikaHDF5Loader"
     1752//      elseif(stringmatch(CurPanelName[0,4],"Irena"))
     1753//              return "IrenaHDF5Loader"
     1754//      else
     1755//              return ""
     1756//      endif
     1757//end
     1758//
     1759//Function NI2_HDF5BrowserPrefCheckboxProc(ctrlName,checked) : CheckBoxControl
     1760//      String ctrlName
     1761//      Variable checked
     1762//     
     1763//      STRUCT NI2_HDF5BrowserPrefs prefs
     1764//     
     1765//      NI2_HDF5BrowserLoadPackagePrefs(prefs)
     1766//      strswitch(ctrlName)
     1767//              case "ReadOnly":
     1768//                      prefs.readOnly = checked
     1769//                      break
     1770//             
     1771//              case "LoadGroupsRecursively":
     1772//                      prefs.loadGroupsRecursively = checked
     1773//                      break
     1774//             
     1775//              case "Transpose2DDatasets":
     1776//                      prefs.transpose2DDatasets = checked
     1777//                      break
     1778//                     
     1779//              case "SaveGroupsRecursively":
     1780//                      prefs.saveGroupsRecursively = checked
     1781//                      break
     1782//                     
     1783//              case "IncludeIgorAttributes":
     1784//                      prefs.includeIgorAttributes = checked
     1785//                      break
     1786//             
     1787//      endswitch
     1788//      NI2_HDF5BrowserSavePackagePrefs(prefs)
     1789//End
     1790//
    17831791Function NI2_CreateNewHDF5Browser(WhereFrom)
    17841792        string WhereFrom                        //Nika or Irena
     
    18031811        CreateHDF5BrowserGlobals(browserName)
    18041812       
    1805         CreateHDF5BrowserPanel(browserName)
     1813        HDF5Browser#CreateHDF5BrowserPanel(browserName)
    18061814
    1807         STRUCT NI2HDF5BrowserData bd
    1808         SetNI2HDF5BrowserData(browserName, bd)
     1815        STRUCT HDF5BrowserData bd
     1816
     1817#if(IgorVersion()<9)
     1818        //STRUCT NI2HDF5BrowserData bd
     1819        HDF5Browser#SetHDF5BrowserData(browserName, bd)
     1820        NI2_AttachListWaves(bd)
     1821        HDF5Browser#SetButtonStates(bd)
     1822#else
     1823        HDF5Browser#SetHDF5BrowserData(browserName, bd)
     1824        NI2_AttachListWaves(bd)
     1825        HDF5Browser#SetButtonStates(bd)
     1826#endif
     1827
    18091828       
    1810         NI2_AttachListWaves(bd)
    1811         SetButtonStates(bd)
    18121829End
    1813 
    1814 Static Function IsHDF5Browser(name)
    1815         String name                     // Name of a window
    1816        
    1817         if (WinType(name) != 7)
    1818                 return 0                                // Not a control panel window
    1819         endif
    1820        
    1821         String data = GetUserData(name, "", "HDF5BrowserName")  // HDF5BrowserName property is set by CreateHDF5BrowserPanel
    1822         if (CmpStr(data,name) == 0)                     // Is this an HDF5Browser?
    1823                 return 1
    1824         endif
    1825        
    1826         return 0
    1827 End
    1828 
    1829 Function/S NI2_HDF5GetIndxBrowserName(index)
    1830         Variable index
    1831        
    1832         if (index < 0)
    1833                 return ""                               // Bad index
    1834         endif
    1835        
    1836         String panelName
    1837        
    1838         Variable i = 0
    1839         do
    1840                 panelName = WinName(i, 64)
    1841                 if (strlen(panelName) == 0)
    1842                         break
    1843                 endif
    1844                
    1845                 if (IsHDF5Browser(panelName))           // Is this an HDF5Browser?
    1846                         if (index == 0)
    1847                                 return panelName
    1848                         endif
    1849                         index -= 1
    1850                 endif
    1851                
    1852                 i += 1
    1853         while(1)
    1854        
    1855         return ""               // No HDF5 browser with that index
    1856 End
    1857 
    1858 Function/S NI2_HDF5GetTopBrowserName()
    1859         String browserName = NI2_HDF5GetIndxBrowserName(0)
    1860         return browserName
    1861 End
    1862 
    1863 Function NI2_HDF5AreAnyBrowsersOpen()
    1864         String browserName = NI2_HDF5GetIndxBrowserName(0)
    1865         if (strlen(browserName) > 0)
    1866                 return 1
    1867         endif
    1868         return 0
    1869 End
    1870 
    1871 // FixCloseHDF5FileButtons()
    1872 // If experiment was saved with an HDF5 file open, it is no longer open but the panel's Open
    1873 // and Close buttons will be out-of-sync. This fixes that.
    1874 static Function FixCloseHDF5FileButtons()
    1875 
    1876         STRUCT NI2HDF5BrowserData bd
    1877         String browserName
    1878        
    1879         Variable index = 0
    1880         do
    1881                 browserName = NI2_HDF5GetIndxBrowserName(index)
    1882                 if (strlen(browserName) == 0)
    1883                         break
    1884                 endif
    1885                
    1886                 SetNI2HDF5BrowserData(browserName, bd)
    1887                 if (NI2_FileWasUnexpectedlyClosed(bd))
    1888                         FileWasClosed(bd)
    1889                 endif
    1890                
    1891                 index += 1
    1892         while(1)
    1893 End
    1894 
    1895 static Function AfterFileOpenHook(refNum,file,pathName,type,creator,kind)
    1896         Variable refNum,kind
    1897         String file,pathName,type,creator
    1898 
    1899         // DoAlert 0, "AfterFileOpenHook"               // For debugging
    1900        
    1901         switch (kind)
    1902                 case 1:                                                                         // Packed experiment
    1903                 case 2:                                                                         // Unpacked experiment
    1904                         FixCloseHDF5FileButtons()               // If experiment was saved with an HDF5 file open, it is no longer open
    1905                 break
    1906         endswitch
    1907 
    1908         return 0
    1909 End
    1910 
    1911 // ************* Start of HDF5 Browser Display Routines ***************
    1912 
    1913 static Function WaveRank(w)
    1914         Wave w
    1915        
    1916         Variable dimension
    1917         for(dimension=3; dimension>=0; dimension-=1)
    1918                 if (DimSize(w, dimension) > 0)
    1919                         return dimension+1
    1920                 endif
    1921         endfor
    1922        
    1923         return 0
    1924 End
    1925 
    1926 // *** DISPLAY IN DUMP WINDOW ***
    1927 
    1928 Function NI2_HDF5BrowserDumpIsVisible() // Returns true if dump window exists and is visible.
    1929                                                                         // Returns false if it does not exist or is invisible.
    1930         DoWindow  HDF5DumpNotebook
    1931         if (V_flag == 0)
    1932                 return 0                                        // Does not exist
    1933         endif
    1934        
    1935         String name
    1936         Variable index = 0
    1937         do
    1938                 name = WinName(index, 16, 1)
    1939                 if (strlen(name) == 0)
    1940                         return 0                                // Did not find HDF5DumpNotebook among visible notebooks.
    1941                 endif
    1942                 if (CmpStr(name, "HDF5DumpNotebook") == 0)
    1943                         return 1                                // Found HDF5DumpNotebook among visible notebooks
    1944                 endif
    1945                 index += 1
    1946         while(1)
    1947        
    1948         return 0                                                // This will never execute.                                                     
    1949 End
    1950 
    1951 Function NI2_HDF5BrowserDumpHook(infoStr)
    1952         String infoStr
    1953 
    1954         String event= StringByKey("EVENT",infoStr)
    1955 
    1956         strswitch(event)
    1957                 case "activate":                                // We do not get this on Windows when the panel is first created.
    1958                         break
    1959                        
    1960                 case "resize":
    1961                 case "moved":                                   // This message was added in Igor Pro 5.04B07.
    1962                         SetPrefWindowCoords("HDF5DumpNotebook")
    1963                         break
    1964         endswitch
    1965        
    1966         return 0
    1967 End
    1968 
    1969 Function NI2_HDF5CreateDumpWindow()
    1970         DoWindow HDF5DumpNotebook
    1971         if (V_flag == 0)
    1972                 Variable left, top, right, bottom
    1973                 GetPrefWindowCoords("HDF5DumpNotebook", left, top, right, bottom)
    1974                 if (right > left)                                                                                       // Were prefs ever set?
    1975                         NewNotebook /F=0 /N=HDF5DumpNotebook/K=1 /W=(left, top, right, bottom)
    1976                 else
    1977                         NewNotebook/F=0/N=HDF5DumpNotebook/K=1
    1978                 endif
    1979                 SetWindow HDF5DumpNotebook,hook=HDF5BrowserDumpHook
    1980                 if (NumType(FontSizeHeight("Courier New", 12, 0)) == 0)         // Courier New exists?
    1981                         Notebook HDF5DumpNotebook font="Courier New", fSize=12
    1982                 endif
    1983                 Notebook HDF5DumpNotebook text="A dump will appear here when you click a dataset.\r"
    1984         endif
    1985 End
    1986 
    1987 // CleanupDump(dump)
    1988 // Removes nulls, converts \n to CR, etc. Dump of NASA strings can contain lots of such "garbage".
    1989 // For an example, see the attribute /StructMetadata.O_GLOSDS in the NASA sample file MISRAERO.h5.
    1990 static Function/S CleanupDump(dump)
    1991         String dump
    1992        
    1993         // Convert literal string "\000" to "". Null characters are represented in dump by "\000"
    1994         dump = ReplaceString("\\000", dump, "", 1)
    1995        
    1996         // Convert literal string "\r\n" to CR
    1997         dump = ReplaceString("\\r\\n", dump, "\r", 1)
    1998        
    1999         // Convert literal string "\r" to CR
    2000         dump = ReplaceString("\\r", dump, "\r", 1)
    2001        
    2002         // Convert literal string "\n" to CR
    2003         dump = ReplaceString("\\n", dump, "\r", 1)
    2004        
    2005         // Convert literal string "\t" to tab
    2006         dump = ReplaceString("\\t", dump, "\t", 1)
    2007        
    2008         // Convert CRLF to CR
    2009         dump = ReplaceString("\r\n", dump, "\r", 1)
    2010        
    2011         // Convert LF to CR
    2012         dump = ReplaceString("\n", dump, "\r", 1)
    2013        
    2014         return dump
    2015 End
    2016 
    2017 Function NI2_HDF5DisplayDumpOfSelGroup(bd)
    2018         STRUCT NI2HDF5BrowserData &bd
    2019        
    2020 #if Exists("HDF5OpenFile")     
    2021         String path = NI2_SelectedGroupPath(bd)
    2022         if (strlen(path) == 0)
    2023                 return -1
    2024         endif
    2025        
    2026         ControlInfo /W=$bd.browserName ShowAttributesInDump
    2027         Variable showAttributes = V_value
    2028         HDF5Dump /Q /H=1 /ATTR=(showAttributes) /G=path bd.fullPath                                     // This sets S_HDF5Dump.
    2029         S_HDF5Dump = CleanupDump(S_HDF5Dump)   
    2030        
    2031         NI2_HDF5CreateDumpWindow()
    2032        
    2033         Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
    2034         Notebook HDF5DumpNotebook text=S_HDF5Dump
    2035         Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
    2036 #else
    2037         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    2038 #endif
    2039 End
    2040 
    2041 static Function DisplayDumpOfSelectedDataset(bd)
    2042         STRUCT NI2HDF5BrowserData &bd
    2043        
    2044 #if Exists("HDF5OpenFile")     
    2045         String datasetPath = NI2_SelectedDatasetPath(bd)
    2046         if (strlen(datasetPath) == 0)
    2047                 return -1
    2048         endif
    2049        
    2050         ControlInfo /W=$bd.browserName ShowAttributesInDump
    2051         Variable showAttributes = V_value
    2052         ControlInfo /W=$bd.browserName ShowDataInDump
    2053         Variable showData = V_value
    2054         HDF5Dump /Q /ATTR=(showAttributes) /H=(!showData) /D=datasetPath bd.fullPath                    // This sets S_HDF5Dump.
    2055         S_HDF5Dump = CleanupDump(S_HDF5Dump)   
    2056        
    2057         NI2_HDF5CreateDumpWindow()
    2058        
    2059         Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
    2060         Notebook HDF5DumpNotebook text=S_HDF5Dump
    2061         Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
    2062 #else
    2063         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    2064 #endif
    2065 End
    2066 
    2067 static Function DisplayDumpOfSelectedAttribute(bd, isGroupAttribute)
    2068         STRUCT NI2HDF5BrowserData &bd
    2069         Variable isGroupAttribute
    2070        
    2071 #if Exists("HDF5OpenFile")     
    2072         String path = NI2_SelectedAttributePath(bd, isGroupAttribute)
    2073         if (strlen(path) == 0)
    2074                 return -1
    2075         endif
    2076        
    2077         HDF5Dump /Q /A=path bd.fullPath                                 // This sets S_HDF5Dump.
    2078         S_HDF5Dump = CleanupDump(S_HDF5Dump)   
    2079        
    2080         NI2_HDF5CreateDumpWindow()
    2081        
    2082         Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
    2083         Notebook HDF5DumpNotebook text=S_HDF5Dump
    2084         Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
    2085 #else
    2086         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    2087 #endif
    2088 End
    2089 
    2090 // *** DISPLAY IN GRAPH ***
    2091 
    2092 Function NI2_HDF5BrowserGraphIsVisible()                // Returns true if dump window exists and is visible.
    2093                                                                                 // Returns false if it does not exist or is invisible.
    2094         DoWindow  HDF5BrowserGraph
    2095         if (V_flag == 0)
    2096                 return 0                                        // Does not exist
    2097         endif
    2098        
    2099         // Graphs are always visible so we don't need to check that.
    2100        
    2101         return 1                                                // This will never execute.                                                     
    2102 End
    2103 
    2104 Function NI2_HDF5BrowserGraphHook(infoStr)
    2105         String infoStr
    2106 
    2107         String event= StringByKey("EVENT",infoStr)
    2108 
    2109         strswitch(event)
    2110                 case "activate":                                // We do not get this on Windows when the panel is first created.
    2111                         break
    2112                        
    2113                 case "resize":
    2114                 case "moved":                                   // This message was added in Igor Pro 5.04B07.
    2115                         SetPrefWindowCoords("HDF5BrowserGraph")
    2116                         break
    2117         endswitch
    2118        
    2119         return 0
    2120 End
    2121 
    2122 Function NI2_HDF5CreateBrowserGraph()
    2123         DoWindow HDF5BrowserGraph
    2124         if (V_flag == 0)
    2125                 Variable left, top, right, bottom
    2126                 GetPrefWindowCoords("HDF5BrowserGraph", left, top, right, bottom)
    2127                 if (right > left)                                                                       // Were prefs ever set?
    2128                         Display /K=1 /W=(left, top, right, bottom)
    2129                 else
    2130                         Display /K=1
    2131                 endif
    2132                 DoWindow/C HDF5BrowserGraph
    2133                 SetWindow HDF5BrowserGraph,hook=HDF5BrowserGraphHook
    2134         endif
    2135 End
    2136 
    2137 static Function SetImageLayer(ctrlName,varNum,varStr,varName) : SetVariableControl
    2138         String ctrlName
    2139         Variable varNum
    2140         String varStr
    2141         String varName
    2142 
    2143         NVAR imageLayer = root:Packages:HDF5Browser:imageLayer
    2144 
    2145         ModifyImage /W=HDF5BrowserGraph BrowserWave, plane=varNum
    2146 End
    2147 
    2148 static Function DisplayGraphOfSelectedData(bd, isAttribute, objectType, listOfWavesLoaded)              // The data is already loaded into waves specified by listOfWavesLoaded
    2149         STRUCT NI2HDF5BrowserData &bd
    2150         Variable isAttribute
    2151         Variable objectType                             // Host object type of attribute. 1=group, 2=dataset
    2152         String listOfWavesLoaded
    2153 
    2154         NI2_HDF5CreateBrowserGraph()
    2155 
    2156         String firstWaveLoaded = StringFromList(0, listOfWavesLoaded)
    2157         Wave browserWave = root:Packages:HDF5Browser:$firstWaveLoaded
    2158         Variable newDataIsText = WaveType(browserWave) == 0
    2159 
    2160         Variable oldRank = 0, newRank = 0
    2161         if (strlen(TraceNameList("HDF5BrowserGraph", ";", 1)) > 0)
    2162                 oldRank = 1                                     
    2163         endif
    2164         if (strlen(ImageNameList("HDF5BrowserGraph", ";")) > 0)
    2165                 oldRank = 2
    2166         endif
    2167         newRank = WaveRank(browserWave) // Will be zero for zero-point wave
    2168 
    2169         String savedDataFolder = NI2_SetBrowserDataFolder("")                                   // browserWave goes in master HDF5Browser data folder
    2170 
    2171         Variable displayedDimensionalityChanged = (oldRank <= 1) != (newRank <= 1)      // Switching between 1D and >1D ?
    2172         Variable index, browserWaveIsDisplayed
    2173         String waveLoaded, nameOfGraphWave
    2174        
    2175         // Remove any waves in graph not in listOfWavesLoaded or all waves if dimensionality changed
    2176         index = 0
    2177         do
    2178                 if (oldRank == 1)
    2179                         Wave/Z graphWave = WaveRefIndexed("HDF5BrowserGraph", index, 1)
    2180                         if (!WaveExists(graphWave))
    2181                                 break
    2182                         endif
    2183                         nameOfGraphWave = NameOfWave(graphWave)
    2184                 else
    2185                         nameOfGraphWave = StringFromList(index, ImageNameList("HDF5BrowserGraph", ";" ))
    2186                         if (strlen(nameOfGraphWave) == 0)
    2187                                 break
    2188                         endif
    2189                 endif
    2190                
    2191                 Variable waveIsInListOfLoadedWaves = WhichListItem(nameOfGraphWave, listOfWavesLoaded) >= 0
    2192                 if (displayedDimensionalityChanged || !waveIsInListOfLoadedWaves)
    2193                         if (oldRank == 1)
    2194                                 RemoveFromGraph /W=HDF5BrowserGraph $nameOfGraphWave
    2195                         endif
    2196                         if (oldRank > 1)
    2197                                 RemoveImage /W=HDF5BrowserGraph $nameOfGraphWave
    2198                         endif
    2199                         index -= 1
    2200                 endif
    2201                 if (!waveIsInListOfLoadedWaves)
    2202                         KillWaves/Z $nameOfGraphWave
    2203                 endif
    2204                
    2205                 index += 1
    2206         while(1)
    2207 
    2208         // Append any waves to graph in listOfWavesLoaded
    2209         index = 0
    2210         do
    2211                 waveLoaded = StringFromList(index, listOfWavesLoaded)
    2212                 if (strlen(waveLoaded) == 0)
    2213                         break
    2214                 endif
    2215                 Wave browserWave = root:Packages:HDF5Browser:$waveLoaded
    2216                 Variable browserWaveType = WaveType(browserWave)
    2217                 nameOfGraphWave = waveLoaded
    2218 
    2219                 CheckDisplayed /W=HDF5BrowserGraph browserWave
    2220                 browserWaveIsDisplayed = V_flag
    2221                
    2222                 if (!newDataIsText)
    2223                         if (browserWaveType != 0)                               // When loading compound data we can get a mix of numeric and non-numeric.
    2224                                 if (browserWaveIsDisplayed == 0)
    2225                                         if (newRank <= 1)
    2226                                                 AppendToGraph /W=HDF5BrowserGraph browserWave
    2227                                                 if (displayedDimensionalityChanged)
    2228                                                         SetAxis/A left
    2229                                                 endif
    2230                                         else
    2231                                                 AppendImage /W=HDF5BrowserGraph browserWave
    2232                                                 if (displayedDimensionalityChanged)
    2233                                                         SetAxis/A/R left                                                                        // Reverse left axis like NewImage does.
    2234                                                 endif
    2235                                         endif
    2236                                 endif
    2237        
    2238                                 if (newRank >= 2)
    2239                                         NVAR formalImageType = root:Packages:HDF5Browser:formalImageType
    2240                                         switch (formalImageType)                                                        // browserPalette would be created by HDF5LoadImage
    2241                                                 case 0:                                                                                         // Not a formal image.
    2242                                                 case 1:                                                                                         // No palette wave loaded.
    2243                                                         ModifyImage /W=HDF5BrowserGraph $nameOfGraphWave ctab= {*,*,Grays,0}
    2244                                                         break
    2245                                                        
    2246                                                 case 2:                                                                                         // Palette wave was loaded.
    2247                                                         Wave browserPalette = root:Packages:HDF5Browser:browserPalette
    2248                                                         ModifyImage /W=HDF5BrowserGraph $nameOfGraphWave, cindex=browserPalette
    2249                                                         break
    2250                                         endswitch
    2251                                 endif
    2252                         endif
    2253                 endif
    2254 
    2255                 if (newDataIsText)                                              // Display a snippet of the text wave.
    2256                         if (browserWaveType == 0)               // When loading compound data we can get a mix of numeric and non-numeric.
    2257                                 String text
    2258                                 Wave/T w = root:Packages:HDF5Browser:$nameOfGraphWave
    2259                                 if (numpnts(w) > 0)
    2260                                         text = CleanupDump(w[0])
    2261                                 else
    2262                                         text = ""
    2263                                 endif
    2264                                 if ( (strlen(text) > 256) || (numpnts(w)>1) )
    2265                                         text = "A snippet of the text:\r\r" + text[0,255]                       
    2266                                 endif                   
    2267                                 TextBox/C/N=browserTextbox/W=HDF5BrowserGraph/A=LT text
    2268                         endif
    2269                 else
    2270                         TextBox/K/N=browserTextbox/W=HDF5BrowserGraph
    2271                 endif
    2272                
    2273                 index += 1
    2274         while(1)
    2275        
    2276         // Show Image Layer control if displaying a stack of images
    2277         Variable numDims = WaveDims(browserWave)
    2278         Variable isStack = 0
    2279         if (!newDataIsText && newRank>2)
    2280                 if (DimSize(browserWave,2) == 3)
    2281                         // Igor assumes that this is an RGB wave using direct color.
    2282                         if (numDims > 3)
    2283                                 isStack = 1                     // This is a stack of RGB images.
    2284                         endif
    2285                 else
    2286                         isStack = 1                     // This is a stack of indexed color images.
    2287                 endif
    2288         endif
    2289        
    2290         if (isStack)
    2291                 Variable/G root:Packages:HDF5Browser:imageLayer = 0
    2292                 Variable dim, numLayers
    2293                
    2294                 numLayers = 1
    2295                 for(dim=2; dim<numDims; dim+=1)
    2296                         numLayers *= DimSize(browserWave, dim)
    2297                 endfor
    2298                
    2299                 ControlBar/W=HDF5BrowserGraph 25
    2300                 SetVariable ImageLayer win=HDF5BrowserGraph, title="Layer",size={100,20},format="%d"
    2301                 SetVariable ImageLayer win=HDF5BrowserGraph, proc=HDF5Browser#SetImageLayer
    2302                 SetVariable ImageLayer win=HDF5BrowserGraph, value=imageLayer, limits={0,numLayers-1,1}
    2303         else
    2304                 KillControl/W=HDF5BrowserGraph ImageLayer
    2305                 ControlBar/W=HDF5BrowserGraph 0
    2306         endif
    2307                
    2308         String title = "HDF5 Preview - "
    2309         if (isAttribute)
    2310                 title += NI2_SelectedAttributeName(bd, objectType==1)
    2311         else
    2312                 title += NI2_SelectedDatasetName(bd)
    2313         endif
    2314         title = title[0,39]                             // Unfortunately titles are limited to 40 characters.
    2315         DoWindow /T HDF5BrowserGraph, title
    2316        
    2317         SetDataFolder savedDataFolder
    2318 End
    2319 
    2320 // *** DISPLAY IN TABLE ***
    2321 
    2322 Function NI2_HDF5BrowserTableIsVisible()                // Returns true if dump window exists and is visible.
    2323                                                                                 // Returns false if it does not exist or is invisible.
    2324         DoWindow  HDF5BrowserTable
    2325         if (V_flag == 0)
    2326                 return 0                                        // Does not exist
    2327         endif
    2328        
    2329         // Tables are always visible so we don't need to check that.
    2330        
    2331         return 1                                                // This will never execute.                                                     
    2332 End
    2333 
    2334 Function NI2_HDF5BrowserTableHook(infoStr)
    2335         String infoStr
    2336 
    2337         String event= StringByKey("EVENT",infoStr)
    2338 
    2339         strswitch(event)
    2340                 case "activate":                                // We do not get this on Windows when the panel is first created.
    2341                         break
    2342                        
    2343                 case "resize":
    2344                 case "moved":                                   // This message was added in Igor Pro 5.04B07.
    2345                         SetPrefWindowCoords("HDF5BrowserTable")
    2346                         break
    2347         endswitch
    2348        
    2349         return 0
    2350 End
    2351 
    2352 Function NI2_HDF5CreateBrowserTable()
    2353         DoWindow HDF5BrowserTable
    2354         if (V_flag == 0)
    2355                 Variable left, top, right, bottom
    2356                 GetPrefWindowCoords("HDF5BrowserTable", left, top, right, bottom)
    2357                 if (right > left)                                                                       // Were prefs ever set?
    2358                         Edit /K=1 /W=(left, top, right, bottom)
    2359                 else
    2360                         Edit /K=1
    2361                 endif
    2362                 DoWindow/C HDF5BrowserTable
    2363                 SetWindow HDF5BrowserTable,hook=HDF5BrowserTableHook
    2364         endif
    2365 End
    2366 
    2367 static Function DisplayTableOfSelectedData(bd, isAttribute, objectType, listOfWavesLoaded)              // The data is already loaded into waves listed by listOfWavesLoaded
    2368         STRUCT NI2HDF5BrowserData &bd
    2369         Variable isAttribute
    2370         Variable objectType                             // Host object type of attribute. 1=group, 2=dataset
    2371         String listOfWavesLoaded
    2372        
    2373         NI2_HDF5CreateBrowserTable()
    2374 
    2375         String waveLoaded
    2376         Variable index
    2377        
    2378         // Remove any waves in table not in listOfWavesLoaded
    2379         index = 0
    2380         do
    2381                 Wave/Z tableWave = WaveRefIndexed("HDF5BrowserTable", index, 3)
    2382                 if (!WaveExists(tableWave))
    2383                         break
    2384                 endif
    2385                
    2386                 String nameOfTableWave = NameOfWave(tableWave)
    2387                 if (WhichListItem(nameOfTableWave, listOfWavesLoaded) < 0)
    2388                         RemoveFromTable /W=HDF5BrowserTable tableWave
    2389                         KillWaves/Z tableWave
    2390                         index -= 1
    2391                 endif
    2392                
    2393                 index += 1
    2394         while(1)
    2395 
    2396         // Append any waves to table in listOfWavesLoaded
    2397         index = 0
    2398         do
    2399                 waveLoaded = StringFromList(index, listOfWavesLoaded)
    2400                 if (strlen(waveLoaded) == 0)
    2401                         break
    2402                 endif
    2403                 Wave browserWave = root:Packages:HDF5Browser:$waveLoaded
    2404        
    2405                 CheckDisplayed /W=HDF5BrowserTable browserWave
    2406                 if (V_flag == 0)
    2407                         AppendToTable /W=HDF5BrowserTable browserWave
    2408                 endif
    2409                
    2410                 index += 1
    2411         while(1)
    2412 
    2413         String title = "HDF5 Preview - "
    2414         if (isAttribute)
    2415                 title += NI2_SelectedAttributeName(bd, objectType==1)
    2416         else
    2417                 title += NI2_SelectedDatasetName(bd)
    2418         endif
    2419         title = title[0,39]                             // Unfortunately titles are limited to 40 characters.
    2420         DoWindow /T HDF5BrowserTable, title
    2421 End
    2422 
    2423 static Function RemoveFromGraphAndTable(w)
    2424         Wave w
    2425        
    2426         String name = NameOfWave(w)
    2427        
    2428         if (NI2_HDF5BrowserGraphIsVisible())
    2429                 CheckDisplayed /W=HDF5BrowserGraph w
    2430                 if (V_flag != 0)
    2431                         Variable isImage = strlen(ImageNameList("HDF5BrowserGraph", ";")) > 0
    2432                         if (isImage)
    2433                                 RemoveImage /W=HDF5BrowserGraph $name
    2434                         else
    2435                                 RemoveFromGraph /W=HDF5BrowserGraph $name
    2436                         endif
    2437                 endif
    2438         endif
    2439        
    2440         if (NI2_HDF5BrowserTableIsVisible())
    2441                 CheckDisplayed /W=HDF5BrowserTable w
    2442                 if (V_flag != 0)
    2443                         RemoveFromTable /W=HDF5BrowserTable w
    2444                 endif
    2445         endif
    2446 End
    2447 
    2448 //      KillConflictingBrowserWaves(new_class_str, enumMode)
    2449 //      "Conflicting" means that a wave is text and we are going
    2450 // to use the same name to load a numeric wave or vice versa.
    2451 // This function removes conflicting waves from the browser graph
    2452 // and table and then kills them.
    2453 static Function KillConflictingBrowserWaves(new_class_str, enumMode)
    2454         String new_class_str                            // Class of data we are about to load.
    2455         Variable enumMode
    2456 
    2457         String browserDF = "root:Packages:HDF5Browser"
    2458         Variable numWaves = CountObjects(browserDF, 1)
    2459         Variable i
    2460 
    2461         for(i=0; i<numWaves; i+=1)
    2462                 String name = GetIndexedObjName(browserDF, 1, i)
    2463                 if (strlen(name)>=11 && CmpStr(name[0,11],"browserWave")==0)    // Is this a browser display wave?
    2464                         Wave w = $(browserDF + ":" + name)
    2465 
    2466                         Variable oldDataIsText
    2467                         oldDataIsText = WaveType(w) == 0
    2468        
    2469                         Variable newDataIsText
    2470                        
    2471                         newDataIsText = 0
    2472                         strswitch(new_class_str)
    2473                                 case "H5T_STRING":
    2474                                 case "H5T_REFERENCE":
    2475                                         newDataIsText = 1
    2476                                         break
    2477                                        
    2478                                 case "H5T_ENUM":
    2479                                         if (enumMode == 1)
    2480                                                 newDataIsText = 1
    2481                                         endif
    2482                                         break
    2483                                        
    2484                                 case "H5T_COMPOUND":
    2485                                         // If we are loading all members of a compound dataset
    2486                                         // at this point we need to know the class of the compound
    2487                                         // member corresponding to the current wave. However, this
    2488                                         // is very complicated to do and I decided not to attempt it.
    2489                                         // The result is that, if we have an existing brower_<member>
    2490                                         // wave whose type is string and we try to load a numeric wave
    2491                                         // with the same name, HDF5LoadWave will get a "Can't overwrite
    2492                                         // text with numeric and vice versa" error.
    2493                                         break
    2494                         endswitch
    2495                        
    2496                         if (newDataIsText != oldDataIsText)
    2497                                 RemoveFromGraphAndTable(w)
    2498                                 KillWaves w
    2499                                 // Printf "Killed %s\r", name
    2500                         endif
    2501                 endif
    2502         endfor
    2503 End
    2504 
    2505 static Function LoadSelectedDataForDisplay(bd, isAttribute, objectType, listOfWavesLoaded, errorMessage)
    2506         STRUCT NI2HDF5BrowserData &bd
    2507         Variable isAttribute
    2508         Variable objectType                                     // Host object type of attribute. 1=group, 2=dataset
    2509         String &listOfWavesLoaded               // Output: List of waves loaded.
    2510         String &errorMessage                            // Output: Error message or ""
    2511        
    2512 #if Exists("HDF5OpenFile")     
    2513         Variable err = 0
    2514         errorMessage = ""
    2515 
    2516         Wave/Z browserWave = root:Packages:HDF5Browser:browserWave
    2517        
    2518         String path
    2519         if (isAttribute)
    2520                 if (objectType == 1)
    2521                         path = NI2_SelectedGroupPath(bd)
    2522                 else
    2523                         path = NI2_SelectedDatasetPath(bd)
    2524                 endif
    2525         else
    2526                 path = NI2_SelectedDatasetPath(bd)
    2527         endif
    2528         if (strlen(path) == 0)
    2529                 return -1
    2530         endif
    2531        
    2532         String attributeName = ""
    2533         if (isAttribute)
    2534                 attributeName = NI2_SelectedAttributeName(bd, objectType==1)
    2535                 if (strlen(attributeName) == 0)
    2536                         return -1
    2537                 endif
    2538         endif
    2539 
    2540         STRUCT NI2_HDF5DataInfo di
    2541         NI2_InitHDF5DataInfo(di)
    2542         if (isAttribute)
    2543                 HDF5AttributeInfo(bd.fileID, path, objectType, attributeName, 0, di)
    2544         else
    2545                 HDF5DatasetInfo(bd.fileID, path, 0, di)
    2546         endif
    2547        
    2548         String datatype_class_str = di.datatype_class_str
    2549 
    2550         STRUCT NI2_HDF5DatatypeInfo dti
    2551         NI2_InitHDF5DatatypeInfo(dti)                                   // Sets input fields.
    2552 
    2553         Variable isCompound = 0
    2554         Variable compMode = 0
    2555         String memberName = ""
    2556         if (!isAttribute)                       // We support viewing members only for datasets, not for attributes.
    2557                 NI2_HDF5GetCompLoadInfo(bd, isCompound, compMode, memberName)
    2558         endif
    2559        
    2560         if (compMode != 0)                      // Are we loading a member of a compound datatype?
    2561                 err = HDF5TypeInfo(bd.fileID, path, "", memberName, 1, dti)
    2562                 if (err != 0)
    2563                         return err
    2564                 endif
    2565                 datatype_class_str = dti.type_class_str
    2566         else
    2567                 // If array, we need to know about the base datatype of the array
    2568                 if (CmpStr(datatype_class_str, "H5T_ARRAY") == 0)
    2569                         if (isAttribute)
    2570                                 HDF5AttributeInfo(bd.fileID, path, objectType, attributeName, 2, di)            // 2 means get info on base datatype of array
    2571                         else
    2572                                 HDF5DatasetInfo(bd.fileID, path, 2, di) // 2 means get info on base datatype of array
    2573                         endif
    2574                 endif
    2575                 datatype_class_str = di.datatype_class_str
    2576         endif
    2577 
    2578         err = NI2_HDF5CheckDataClass(datatype_class_str, errorMessage)
    2579         if (err != 0)
    2580                 if (WaveExists(browserWave))
    2581                         Redimension/N=(0) browserWave           // Don't leave browserWave around which a user might
    2582                 endif                                                                                           // think goes with the selected item in the control panel
    2583                 return err
    2584         endif
    2585        
    2586         String savedDataFolder = NI2_SetBrowserDataFolder("")                                   // tempClassAttribute goes in master HDF5Browser data folder
    2587        
    2588         // If isFormalImage is true, we are loading an image written
    2589         // according to the HDF5 Image and Palette Specification.
    2590         Variable isFormalImage = 0
    2591         if (!isAttribute && !isCompound)
    2592                 HDF5LoadData /Z /O /N=tempClassAttribute /A="CLASS" /Q /VAR=1 bd.fileID, path
    2593                 if (V_flag == 0)
    2594                         WAVE/T tempClassAttribute                       // HDF5LoadData will have created this string
    2595                         if (CmpStr(tempClassAttribute[0],"IMAGE") == 0)
    2596                                 isFormalImage = 1
    2597                         endif   
    2598                         KillWaves/Z tempClassAttribute
    2599                 endif
    2600         endif
    2601 
    2602         SetDataFolder savedDataFolder
    2603        
    2604         Variable enumMode = 1                                           // 0: Load enum into numeric wave; 1: load enum into text wave.
    2605        
    2606         // If browserWave exists and we are switching from a text wave to a numeric wave
    2607         // or vice-versa then we must remove browserWave from the graph and table and
    2608         // kill it. Otherwise we will get an error when HDF5LoadData tries to overwrite
    2609         // a text wave with numeric or vice versa.
    2610         KillConflictingBrowserWaves(datatype_class_str, enumMode)       // Also removes them from graph and table.
    2611        
    2612         savedDataFolder = NI2_SetBrowserDataFolder("")                                  // browser waves go in master HDF5Browser data folder
    2613 
    2614         String slabWaveStr = ""
    2615         ControlInfo /W=$bd.browserName UseHyperSelection
    2616         if (V_value)                                                            // Use Hyperselection is checked?
    2617                 slabWaveStr = bd.hyperSelectionWavePath
    2618         endif
    2619         WAVE/Z slabWave = $slabWaveStr                  // It is OK if wave does not exist and slabWave is NULL. HDF5LoadData will simply ignore /SLAB.
    2620 
    2621         if (isFormalImage)
    2622                 String browserPaletteName = "browserPalette"
    2623                 HDF5LoadImage /O /N=browserWave /PALN=browserPaletteName /Q bd.fileID, path
    2624                 Variable/G formalImageType = 1          // Means formal image with no palette
    2625                 listOfWavesLoaded = StringFromList(0, S_waveNames)      // We count only the image as loaded, not the palette.
    2626                 if (WhichListItem(browserPaletteName, S_waveNames) >= 0)
    2627                         formalImageType = 2                                     // Means formal image with palette
    2628                 endif
    2629         else
    2630                 KillWaves/Z browserPalette
    2631 
    2632                 Variable transpose2D = NI2_HDF5GetTranspose2DSetting(bd.browserName)
    2633 
    2634                 // Note that when loading all members of a compound dataset this
    2635                 // will create a family of waves named browserWave_<member>.
    2636                 // Also when loading a VLEN dataset it will create a family of
    2637                 // waves named browserWave<digit>. Otherwise it just creates
    2638                 // one wave named browserWave.
    2639                 HDF5LoadData /O /IGOR=-1 /N=browserWave /COMP={compMode,memberName} /TRAN=(transpose2D) /A=attributeName /TYPE=(objectType) /ENUM=(enumMode) /SLAB=slabWave /Q /VAR=0 bd.fileID, path
    2640 
    2641                 Variable/G formalImageType = 0          // Not a formal image
    2642                 listOfWavesLoaded = S_waveNames
    2643         endif
    2644        
    2645         errorMessage = GetRTErrMessage()
    2646         err = GetRTError(1)
    2647 
    2648         SetDataFolder savedDataFolder
    2649         return err
    2650 #else
    2651         Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
    2652 #endif
    2653 End
    2654 
    2655 Function NI2_HDF5DisplaySelectedDataset(bd)
    2656         STRUCT NI2HDF5BrowserData &bd
    2657 
    2658         if (NI2_HDF5BrowserDumpIsVisible())
    2659                 DisplayDumpOfSelectedDataset(bd)
    2660         endif
    2661 
    2662         String listOfWavesLoaded = ""   
    2663        
    2664         Variable needToLoadData = NI2_HDF5BrowserGraphIsVisible() || NI2_HDF5BrowserTableIsVisible()
    2665         if (needToLoadData)
    2666                 String errorMessage
    2667                 if (LoadSelectedDataForDisplay(bd, 0, 2, listOfWavesLoaded, errorMessage) != 0)
    2668                         DoAlert 0, errorMessage
    2669                         return -1
    2670                 endif
    2671         endif
    2672 
    2673         if (NI2_HDF5BrowserGraphIsVisible())
    2674                 DisplayGraphOfSelectedData(bd, 0, 1, listOfWavesLoaded)
    2675         endif
    2676 
    2677         if (NI2_HDF5BrowserTableIsVisible())
    2678                 DisplayTableOfSelectedData(bd, 0, 1, listOfWavesLoaded)
    2679         endif
    2680 End
    2681 
    2682 Function NI2_HDF5DisplaySelAttribute(bd,  isGroupAttribute)
    2683         STRUCT NI2HDF5BrowserData &bd
    2684         Variable isGroupAttribute
    2685        
    2686         if (NI2_HDF5BrowserDumpIsVisible())
    2687                 DisplayDumpOfSelectedAttribute(bd, isGroupAttribute)
    2688         endif
    2689        
    2690         Variable objectType = isGroupAttribute ? 1:2
    2691        
    2692         String listOfWavesLoaded = ""
    2693        
    2694         Variable needToLoadData = NI2_HDF5BrowserGraphIsVisible() || NI2_HDF5BrowserTableIsVisible()
    2695         if (needToLoadData)
    2696                 String errorMessage
    2697                 if (LoadSelectedDataForDisplay(bd, 1, objectType, listOfWavesLoaded, errorMessage))
    2698                         DoAlert 0, errorMessage
    2699                         return -1
    2700                 endif
    2701         endif
    2702 
    2703         if (NI2_HDF5BrowserGraphIsVisible())
    2704                 DisplayGraphOfSelectedData(bd, 1, objectType, listOfWavesLoaded)
    2705         endif
    2706 
    2707         if (NI2_HDF5BrowserTableIsVisible())
    2708                 DisplayTableOfSelectedData(bd, 1, objectType, listOfWavesLoaded)
    2709         endif
    2710 End
    2711 
    2712 // ************* End of HDF5 Browser Display Routines ***************
    2713 
    2714 // ************* Start of HDF5 Browser Resize Routines ***************
    2715 
    2716 static Function MinWindowSize(winName,minwidth,minheight)
    2717         String winName
    2718         Variable minwidth,minheight
    2719 
    2720         GetWindow $winName wsize
    2721         Variable width= max(V_right-V_left,minwidth)
    2722         Variable height= max(V_bottom-V_top,minheight)
    2723         MoveWindow/W=$winName V_left, V_top, V_left+width, V_top+height
    2724 End
    2725 
    2726 Function NI2_PositionControlRelative(panelName, control, masterControl, xMode, yMode, dx, dy)
    2727         String panelName
    2728         String control, masterControl           // Positions control relative to masterControl.
    2729         Variable xMode          // 0 = relative to master left, 1 = relative to master right, 2 = do not set x position.
    2730         Variable yMode          // 0 = relative to master top, 1 = relative to master bottom, 2 = do not set y position.
    2731         Variable dx, dy
    2732        
    2733         ControlInfo/W=$panelName $masterControl
    2734         Variable masterLeft = V_left, masterTop = V_top
    2735         Variable masterRight = masterLeft+V_width, masterBottom=masterTop+V_height
    2736        
    2737         ControlInfo/W=$panelName $control
    2738         Variable controlLeft = V_left, controlTop = V_top
    2739        
    2740         Variable left, top
    2741        
    2742         switch(xMode)
    2743                 case 0:
    2744                         left = masterLeft + dx
    2745                         break
    2746        
    2747                 case 1:
    2748                         left = masterRight + dx
    2749                         break
    2750                
    2751                 case 2:
    2752                         left = controlLeft
    2753                         break
    2754         endswitch
    2755        
    2756         switch(yMode)
    2757                 case 0:
    2758                         top = masterTop + dy
    2759                         break
    2760        
    2761                 case 1:
    2762                         top = masterBottom + dy
    2763                         break
    2764                
    2765                 case 2:
    2766                         top = controlTop
    2767                         break
    2768         endswitch
    2769 
    2770         ModifyControl $control, win=$panelName, pos={left, top}
    2771 End
    2772 
    2773 Function NI2_OffsetControls(panelName, controlList, dx, dy)
    2774         String panelName
    2775         String controlList      // Semicolon-separated list of control names
    2776         Variable dx, dy
    2777        
    2778         String name
    2779         Variable index = 0
    2780         do
    2781                 name = StringFromList(index, controlList)
    2782                 if (strlen(name) == 0)
    2783                         break
    2784                 endif
    2785                
    2786                 ControlInfo/W=$panelName $name
    2787                 ModifyControl $name, win=$panelName, pos={V_left+dx,V_top+dy}
    2788 
    2789                 index += 1
    2790         while(1)
    2791 End
    2792 
    2793 Function NI2_HDF5ResizeBrowser(browserName)
    2794         String browserName
    2795 
    2796         Variable statusCode= 0
    2797 
    2798         String win = browserName
    2799 
    2800         GetWindow $browserName wsizeDC
    2801         Variable winLeft=V_left, winTop=V_top, winRight=V_right, winBottom=V_bottom
    2802         Variable winWidth = winRight - winLeft, winHeight = winBottom - winTop
    2803 
    2804         if (winWidth<800 || winHeight<500)
    2805                 return 0                                                // Too small.
    2806         endif
    2807        
    2808         // Set preferred browser window size. We would like to also do this
    2809         // when the browser is moved without resizing but we get no message
    2810         // from Igor when a window is moved.
    2811         SetPrefWindowCoords(browserName)
    2812        
    2813         Variable leftBorder=15, hSpaceBetweenLists=20, rightBorder=15
    2814         Variable listsTop, vSpaceBetweenLists = 30, bottomBorder = 10
    2815        
    2816         ControlInfo/W=$browserName GroupsList
    2817         listsTop = V_top
    2818        
    2819         Variable hSpaceForLists = winRight - winLeft - leftBorder - hSpaceBetweenLists - rightBorder
    2820         Variable vSpaceForLists = winBottom - listsTop - vSpaceBetweenLists - bottomBorder
    2821        
    2822         Variable groupListsWidth = .3 * hSpaceForLists
    2823         Variable datasetListsWidth = .45 * hSpaceForLists
    2824         Variable NikaListsWidth = .23 * hSpaceForLists
    2825        
    2826         Variable groupListsHeight = .65 * vSpaceForLists
    2827         Variable attributeListsHeight = .35 * vSpaceForLists
    2828        
    2829         Variable left, top
    2830        
    2831         // Set Groups list coordinates
    2832         left = leftBorder
    2833         top = listsTop
    2834         ListBox GroupsList, win=$browserName, pos={left, top}, size={groupListsWidth, groupListsHeight}
    2835        
    2836         // Set Group Attributes list coordinates
    2837         left = leftBorder
    2838         top = listsTop + groupListsHeight + vSpaceBetweenLists
    2839         ListBox GroupAttributesList, win=$browserName, pos={left, top}, size={groupListsWidth, attributeListsHeight}
    2840        
    2841         top -= 20
    2842         TitleBox GroupAttributesTitle, win=$browserName, pos={left, top}
    2843 
    2844         // Remember where DatasetsList is. it is used to position other control.
    2845         ControlInfo/W=$browserName DatasetsList
    2846         Variable oldDatasetsListRight = V_Left + V_Width
    2847        
    2848         // Set Datasets list coordinates
    2849         left = leftBorder + groupListsWidth + hSpaceBetweenLists
    2850         top = listsTop
    2851         ListBox DatasetsList, win=$browserName, pos={left, top}, size={datasetListsWidth, groupListsHeight}
    2852        
    2853         // Determine how DatasetsList right edge changed. This is used to position other control.
    2854         ControlInfo/W=$browserName DatasetsList
    2855         Variable changeInDatsetsListRight = (V_Left + V_Width) - oldDatasetsListRight
    2856        
    2857         // Set Datasets Title
    2858         top -= 20
    2859         TitleBox DatasetsTitle, win=$browserName, pos={left, top}
    2860        
    2861         // Set Load Dataset Button
    2862         NI2_PositionControlRelative(browserName, "LoadDataset", "DatasetsTitle", 1, 2, 20, 0)
    2863 //      NI2_PositionControlRelative(browserName, "AddGrouptoList", "DatasetsTitle", 1, 2, 0, -20)
    2864 
    2865 
    2866         // Set Save Waves Button
    2867         NI2_PositionControlRelative(browserName, "SaveWaves", "LoadDataset", 1, 2, 20, 0)
    2868 
    2869         // Set Members popup menu
    2870         NI2_PositionControlRelative(browserName, "Members", "DatasetsTitle", 0, 2, 0, 0)
    2871        
    2872         // Set Dataset Attributes list coordinates
    2873         left = leftBorder + groupListsWidth + hSpaceBetweenLists
    2874         top = listsTop + groupListsHeight + vSpaceBetweenLists
    2875         ListBox DatasetAttributesList, win=$browserName, pos={left, top}, size={datasetListsWidth, attributeListsHeight}
    2876        
    2877         top -= 20
    2878         TitleBox DatasetAttributesTitle, win=$browserName, pos={left, top}
    2879 
    2880         // Set Preview Options
    2881         String list = "PreviewOptions;Graph;Table;Dump;ShowAttributesInDump;ShowDataInDump;"
    2882         NI2_OffsetControls(browserName, list, changeInDatsetsListRight, 0)
    2883 
    2884         // Set Load Dataset Options
    2885         list = "LoadDatasetOptions;DisplayInTable;DisplayInGraph;"
    2886         NI2_OffsetControls(browserName, list, changeInDatsetsListRight, 0)
    2887 
    2888         //Set Nika controls
    2889         // Set Datasets list coordinates
    2890         left = leftBorder + groupListsWidth + hSpaceBetweenLists+datasetListsWidth+hSpaceBetweenLists
    2891         top = listsTop
    2892 
    2893         ListBox NikaGroupList, win=$browserName, pos={left, top}, size={NikaListsWidth, groupListsHeight}
    2894         // Set Load Dataset Button
    2895         NI2_PositionControlRelative(browserName, "NikaDataSetsTitle", "NikaGroupList", 0, 0, 30, -20)
    2896         Button AddGrouptoList,win=$browserName, pos={left, top-150}, size={NikaListsWidth, 20}
    2897         Button ClearDatasetList,win=$browserName, pos={left, top-100}, size={NikaListsWidth, 20}
    2898 
     1830//
     1831//Static Function IsHDF5Browser(name)
     1832//      String name                     // Name of a window
     1833//     
     1834//      if (WinType(name) != 7)
     1835//              return 0                                // Not a control panel window
     1836//      endif
     1837//     
     1838//      String data = GetUserData(name, "", "HDF5BrowserName")  // HDF5BrowserName property is set by CreateHDF5BrowserPanel
     1839//      if (CmpStr(data,name) == 0)                     // Is this an HDF5Browser?
     1840//              return 1
     1841//      endif
     1842//     
     1843//      return 0
     1844//End
     1845//
     1846//Function/S NI2_HDF5GetIndxBrowserName(index)
     1847//      Variable index
     1848//     
     1849//      if (index < 0)
     1850//              return ""                               // Bad index
     1851//      endif
     1852//     
     1853//      String panelName
     1854//     
     1855//      Variable i = 0
     1856//      do
     1857//              panelName = WinName(i, 64)
     1858//              if (strlen(panelName) == 0)
     1859//                      break
     1860//              endif
     1861//             
     1862//              if (IsHDF5Browser(panelName))           // Is this an HDF5Browser?
     1863//                      if (index == 0)
     1864//                              return panelName
     1865//                      endif
     1866//                      index -= 1
     1867//              endif
     1868//             
     1869//              i += 1
     1870//      while(1)
     1871//     
     1872//      return ""               // No HDF5 browser with that index
     1873//End
     1874//
     1875//Function/S NI2_HDF5GetTopBrowserName()
     1876//      String browserName = NI2_HDF5GetIndxBrowserName(0)
     1877//      return browserName
     1878//End
     1879//
     1880//Function NI2_HDF5AreAnyBrowsersOpen()
     1881//      String browserName = NI2_HDF5GetIndxBrowserName(0)
     1882//      if (strlen(browserName) > 0)
     1883//              return 1
     1884//      endif
     1885//      return 0
     1886//End
     1887//
     1888//// FixCloseHDF5FileButtons()
     1889//// If experiment was saved with an HDF5 file open, it is no longer open but the panel's Open
     1890//// and Close buttons will be out-of-sync. This fixes that.
     1891//static Function FixCloseHDF5FileButtons()
     1892//
     1893//      STRUCT NI2HDF5BrowserData bd
     1894//      String browserName
     1895//     
     1896//      Variable index = 0
     1897//      do
     1898//              browserName = NI2_HDF5GetIndxBrowserName(index)
     1899//              if (strlen(browserName) == 0)
     1900//                      break
     1901//              endif
     1902//             
     1903//              SetNI2HDF5BrowserData(browserName, bd)
     1904//              if (NI2_FileWasUnexpectedlyClosed(bd))
     1905//                      FileWasClosed(bd)
     1906//              endif
     1907//             
     1908//              index += 1
     1909//      while(1)
     1910//End
     1911//
     1912//static Function AfterFileOpenHook(refNum,file,pathName,type,creator,kind)
     1913//      Variable refNum,kind
     1914//      String file,pathName,type,creator
     1915//
     1916//      // DoAlert 0, "AfterFileOpenHook"               // For debugging
     1917//     
     1918//      switch (kind)
     1919//              case 1:                                                                         // Packed experiment
     1920//              case 2:                                                                         // Unpacked experiment
     1921//                      FixCloseHDF5FileButtons()               // If experiment was saved with an HDF5 file open, it is no longer open
     1922//              break
     1923//      endswitch
     1924//
     1925//      return 0
     1926//End
     1927//
     1928//// ************* Start of HDF5 Browser Display Routines ***************
     1929//
     1930//static Function WaveRank(w)
     1931//      Wave w
     1932//     
     1933//      Variable dimension
     1934//      for(dimension=3; dimension>=0; dimension-=1)
     1935//              if (DimSize(w, dimension) > 0)
     1936//                      return dimension+1
     1937//              endif
     1938//      endfor
     1939//     
     1940//      return 0
     1941//End
     1942//
     1943//// *** DISPLAY IN DUMP WINDOW ***
     1944//
     1945//Function NI2_HDF5BrowserDumpIsVisible()       // Returns true if dump window exists and is visible.
     1946//                                                                      // Returns false if it does not exist or is invisible.
     1947//      DoWindow  HDF5DumpNotebook
     1948//      if (V_flag == 0)
     1949//              return 0                                        // Does not exist
     1950//      endif
     1951//     
     1952//      String name
     1953//      Variable index = 0
     1954//      do
     1955//              name = WinName(index, 16, 1)
     1956//              if (strlen(name) == 0)
     1957//                      return 0                                // Did not find HDF5DumpNotebook among visible notebooks.
     1958//              endif
     1959//              if (CmpStr(name, "HDF5DumpNotebook") == 0)
     1960//                      return 1                                // Found HDF5DumpNotebook among visible notebooks
     1961//              endif
     1962//              index += 1
     1963//      while(1)
     1964//     
     1965//      return 0                                                // This will never execute.                                                     
     1966//End
     1967//
     1968//Function NI2_HDF5BrowserDumpHook(infoStr)
     1969//      String infoStr
     1970//
     1971//      String event= StringByKey("EVENT",infoStr)
     1972//
     1973//      strswitch(event)
     1974//              case "activate":                                // We do not get this on Windows when the panel is first created.
     1975//                      break
     1976//                     
     1977//              case "resize":
     1978//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
     1979//                      SetPrefWindowCoords("HDF5DumpNotebook")
     1980//                      break
     1981//      endswitch
     1982//     
     1983//      return 0
     1984//End
     1985//
     1986//Function NI2_HDF5CreateDumpWindow()
     1987//      DoWindow HDF5DumpNotebook
     1988//      if (V_flag == 0)
     1989//              Variable left, top, right, bottom
     1990//              GetPrefWindowCoords("HDF5DumpNotebook", left, top, right, bottom)
     1991//              if (right > left)                                                                                       // Were prefs ever set?
     1992//                      NewNotebook /F=0 /N=HDF5DumpNotebook/K=1 /W=(left, top, right, bottom)
     1993//              else
     1994//                      NewNotebook/F=0/N=HDF5DumpNotebook/K=1
     1995//              endif
     1996//              SetWindow HDF5DumpNotebook,hook=HDF5BrowserDumpHook
     1997//              if (NumType(FontSizeHeight("Courier New", 12, 0)) == 0)         // Courier New exists?
     1998//                      Notebook HDF5DumpNotebook font="Courier New", fSize=12
     1999//              endif
     2000//              Notebook HDF5DumpNotebook text="A dump will appear here when you click a dataset.\r"
     2001//      endif
     2002//End
     2003//
     2004//// CleanupDump(dump)
     2005//// Removes nulls, converts \n to CR, etc. Dump of NASA strings can contain lots of such "garbage".
     2006//// For an example, see the attribute /StructMetadata.O_GLOSDS in the NASA sample file MISRAERO.h5.
     2007//static Function/S CleanupDump(dump)
     2008//      String dump
     2009//     
     2010//      // Convert literal string "\000" to "". Null characters are represented in dump by "\000"
     2011//      dump = ReplaceString("\\000", dump, "", 1)
     2012//     
     2013//      // Convert literal string "\r\n" to CR
     2014//      dump = ReplaceString("\\r\\n", dump, "\r", 1)
     2015//     
     2016//      // Convert literal string "\r" to CR
     2017//      dump = ReplaceString("\\r", dump, "\r", 1)
     2018//     
     2019//      // Convert literal string "\n" to CR
     2020//      dump = ReplaceString("\\n", dump, "\r", 1)
     2021//     
     2022//      // Convert literal string "\t" to tab
     2023//      dump = ReplaceString("\\t", dump, "\t", 1)
     2024//     
     2025//      // Convert CRLF to CR
     2026//      dump = ReplaceString("\r\n", dump, "\r", 1)
     2027//     
     2028//      // Convert LF to CR
     2029//      dump = ReplaceString("\n", dump, "\r", 1)
     2030//     
     2031//      return dump
     2032//End
     2033//
     2034//Function NI2_HDF5DisplayDumpOfSelGroup(bd)
     2035//      STRUCT NI2HDF5BrowserData &bd
     2036//     
     2037//#if Exists("HDF5OpenFile")   
     2038//      String path = NI2_SelectedGroupPath(bd)
     2039//      if (strlen(path) == 0)
     2040//              return -1
     2041//      endif
     2042//     
     2043//      ControlInfo /W=$bd.browserName ShowAttributesInDump
     2044//      Variable showAttributes = V_value
     2045//      HDF5Dump /Q /H=1 /ATTR=(showAttributes) /G=path bd.fullPath                                     // This sets S_HDF5Dump.
     2046//      S_HDF5Dump = CleanupDump(S_HDF5Dump)   
     2047//     
     2048//      NI2_HDF5CreateDumpWindow()
     2049//     
     2050//      Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
     2051//      Notebook HDF5DumpNotebook text=S_HDF5Dump
     2052//      Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
     2053//#else
     2054//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     2055//#endif
     2056//End
     2057//
     2058//static Function DisplayDumpOfSelectedDataset(bd)
     2059//      STRUCT NI2HDF5BrowserData &bd
     2060//     
     2061//#if Exists("HDF5OpenFile")   
     2062//      String datasetPath = NI2_SelectedDatasetPath(bd)
     2063//      if (strlen(datasetPath) == 0)
     2064//              return -1
     2065//      endif
     2066//     
     2067//      ControlInfo /W=$bd.browserName ShowAttributesInDump
     2068//      Variable showAttributes = V_value
     2069//      ControlInfo /W=$bd.browserName ShowDataInDump
     2070//      Variable showData = V_value
     2071//      HDF5Dump /Q /ATTR=(showAttributes) /H=(!showData) /D=datasetPath bd.fullPath                    // This sets S_HDF5Dump.
     2072//      S_HDF5Dump = CleanupDump(S_HDF5Dump)   
     2073//     
     2074//      NI2_HDF5CreateDumpWindow()
     2075//     
     2076//      Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
     2077//      Notebook HDF5DumpNotebook text=S_HDF5Dump
     2078//      Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
     2079//#else
     2080//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     2081//#endif
     2082//End
     2083//
     2084//static Function DisplayDumpOfSelectedAttribute(bd, isGroupAttribute)
     2085//      STRUCT NI2HDF5BrowserData &bd
     2086//      Variable isGroupAttribute
     2087//     
     2088//#if Exists("HDF5OpenFile")   
     2089//      String path = NI2_SelectedAttributePath(bd, isGroupAttribute)
     2090//      if (strlen(path) == 0)
     2091//              return -1
     2092//      endif
     2093//     
     2094//      HDF5Dump /Q /A=path bd.fullPath                                 // This sets S_HDF5Dump.
     2095//      S_HDF5Dump = CleanupDump(S_HDF5Dump)   
     2096//     
     2097//      NI2_HDF5CreateDumpWindow()
     2098//     
     2099//      Notebook HDF5DumpNotebook selection={startOfFile, endOfFile}
     2100//      Notebook HDF5DumpNotebook text=S_HDF5Dump
     2101//      Notebook HDF5DumpNotebook selection={startOfFile, startOfFile}, findText={"",1}
     2102//#else
     2103//      Abort "Hdf5 xop is not found. Reinstall xops using one of the Installers or link the hdf5.xop from Igor distribution to your Igor extensions folder"
     2104//#endif
     2105//End
     2106//
     2107//// *** DISPLAY IN GRAPH ***
     2108//
     2109//Function NI2_HDF5BrowserGraphIsVisible()              // Returns true if dump window exists and is visible.
     2110//                                                                              // Returns false if it does not exist or is invisible.
     2111//      DoWindow  HDF5BrowserGraph
     2112//      if (V_flag == 0)
     2113//              return 0                                        // Does not exist
     2114//      endif
     2115//     
     2116//      // Graphs are always visible so we don't need to check that.
     2117//     
     2118//      return 1                                                // This will never execute.                                                     
     2119//End
     2120//
     2121//Function NI2_HDF5BrowserGraphHook(infoStr)
     2122//      String infoStr
     2123//
     2124//      String event= StringByKey("EVENT",infoStr)
     2125//
     2126//      strswitch(event)
     2127//              case "activate":                                // We do not get this on Windows when the panel is first created.
     2128//                      break
     2129//                     
     2130//              case "resize":
     2131//              case "moved":                                   // This message was added in Igor Pro 5.04B07.
     2132//                      SetPrefWindowCoords("HDF5BrowserGraph")
     2133//                      break
     2134//      endswitch
     2135//     
     2136//      return 0
     2137//End
     2138//
     2139//Function NI2_HDF5CreateBrowserGraph()
     2140//      DoWindow HDF5BrowserGraph
     2141//      if (V_flag == 0)
     2142//              Variable left, top, right, bottom
     2143//              GetPrefWindowCoords("HDF5BrowserGraph", left, top, right, bottom)
     2144//              if (right > left)                                                                       // Were prefs ever set?
     2145//                      Display /K=1 /W=(left, top, right, bottom)
     2146//              else
     2147//                      Display /K=1
     2148//              endif
     2149//              DoWindow/C HDF5BrowserGraph
     2150//              SetWindow HDF5BrowserGraph,hook=HDF5BrowserGraphHook
     2151//      endif
     2152//End
     2153//
     2154//static Function SetImageLayer(ctrlName,varNum,varStr,varName) : SetVariableControl
     2155//      String ctrlName
     2156//      Variable varNum
     2157//      String varStr
     2158//      String varName
     2159//
     2160//      NVAR imageLayer = root:Packages:HDF5Browser:imageLayer
     2161//
     2162//      ModifyImage /W=HDF5BrowserGraph BrowserWave, plane=varNum
     2163//End
     2164//
     2165//static Function DisplayGraphOfSelectedData(bd, isAttribute, objectType, listOfWavesLoaded)            // The data is already loaded into waves specified by listOfWavesLoaded
     2166//      STRUCT NI2HDF5BrowserData &bd
     2167//      Variable isAttribute
     2168//      Variable objectType                             // Host object type of attribute. 1=group, 2=dataset
     2169//      String listOfWavesLoaded
     2170//
     2171//      NI2_HDF5CreateBrowserGraph()
     2172//
     2173//      String firstWaveLoaded = StringFromList(0, listOfWavesLoaded)
     2174//      Wave browserWave = root:Packages:HDF5Browser:$firstWaveLoaded
     2175//      Variable newDataIsText = WaveType(browserWave) == 0
     2176//
     2177//      Variable oldRank = 0, newRank = 0
     2178//      if (strlen(TraceNameList("HDF5BrowserGraph", ";", 1)) > 0)
     2179//              oldRank = 1                                     
     2180//      endif
     2181//      if (strlen(ImageNameList("HDF5BrowserGraph", ";")) > 0)
     2182//              oldRank = 2
     2183//      endif
     2184//      newRank = WaveRank(browserWave) // Will be zero for zero-point wave
     2185//
     2186//      String savedDataFolder = NI2_SetBrowserDataFolder("")                                   // browserWave goes in master HDF5Browser data folder
     2187//
     2188//      Variable displayedDimensionalityChanged = (oldRank <= 1) != (newRank <= 1)      // Switching between 1D and >1D ?
     2189//      Variable index, browserWaveIsDisplayed
     2190//      String waveLoaded, nameOfGraphWave
     2191//     
     2192//      // Remove any waves in graph not in listOfWavesLoaded or all waves if dimensionality changed
     2193//      index = 0
     2194//      do
     2195//              if (oldRank == 1)
     2196//                      Wave/Z graphWave = WaveRefIndexed("HDF5BrowserGraph", index, 1)
     2197//                      if (!WaveExists(graphWave))
     2198//                              break
     2199//                      endif
     2200//                      nameOfGraphWave = NameOfWave(graphWave)
     2201//              else
     2202//                      nameOfGraphWave = StringFromList(index, ImageNameList("HDF5BrowserGraph", ";" ))
     2203//                      if (strlen(nameOfGraphWave) == 0)
     2204//                              break
     2205//                      endif
     2206//              endif
     2207//             
     2208//              Variable waveIsInListOfLoadedWaves = WhichListItem(nameOfGraphWave, listOfWavesLoaded) >= 0
     2209//              if (displayedDimensionalityChanged || !waveIsInListOfLoadedWaves)
     2210//                      if (oldRank == 1)
     2211//                              RemoveFromGraph /W=HDF5BrowserGraph $nameOfGraphWave
     2212//                      endif
     2213//                      if (oldRank > 1)
     2214//                              RemoveImage /W=HDF5BrowserGraph $nameOfGraphWave
     2215//                      endif
     2216//                      index -= 1
     2217//              endif
     2218//              if (!waveIsInListOfLoadedWaves)
     2219//                      KillWaves/Z $nameOfGraphWave
     2220//              endif
     2221//             
     2222//              index += 1
     2223//      while(1)
     2224//
     2225//      // Append any waves to graph in listOfWavesLoaded
     2226//      index = 0
     2227//      do
     2228//              waveLoaded = StringFromList(index, listOfWavesLoaded)
     2229//              if (strlen(waveLoaded) == 0)
     2230//                      break
     2231//              endif
     2232//              Wave browserWave = root:Packages:HDF5Browser:$waveLoaded
     2233//              Variable browserWaveType = WaveType(browserWave)
     2234//              nameOfGraphWave = waveLoaded
     2235//
     2236//              CheckDisplayed /W=HDF5BrowserGraph browserWave
     2237//              browserWaveIsDisplayed = V_flag
     2238//             
     2239//              if (!newDataIsText)
     2240//                      if (browserWaveType != 0)