Two indented loops

Good evening to everybody,

I have a problem during the developing of a function for Igor. A couple of weeks ago, I had a very useful tip from John Weeks, how to make a for loop in a user defined function. This function essentially creates a certain number of gaussian peaks defined through the variable "points", shifted by the values contained in the wave "BEs" and multiplied by the values contained in the wave "exp_dump". Now, I'm trying to edit this function introducing a higher level of complexity. As you can see below, I would like to create, with this new modified function, the same set of data but using several different waves for the "exp_dump", since every single "exp_dump" wave contains a different decay mode. In few words, I want to replicate the same calculation contained in the old function but using different waves for the "exp_dump". In principle, I could do this manually, but the problem is that the "exp_dump" waves are provided by the our experimental equipment, and the number of these waves are so high that I really need for a code......For sake of clarity, I have reported below both the old core and the new function that I'm trying to develop.
Many thanks for your support,

Duncan

//"OLD FUNCTION"
Function simulation(points,FWHM,V_index,theta)
    variable points
    variable FWHM
    variable V_index
    variable theta
 
    variable i
    string N1s_peak_
 
    WAVE BEs
    WAVE BE_scale
    WAVE exp_dump
 
    for (i = 0; i<points; i+=1) //Here I simply create the different gaussian peaks dumped by the values contained in the exp_dump wave.....
        N1s_peak_ = "N1s_peak_" + num2str(i)
        Make/O/N=161 $N1s_peak_/WAVE=wout
        Variable x0 = BEs[i]
        Variable x1 = exp_dump[i]
        wout =  x1*(0.0355 + 0.95*((V_index)*(exp(-((BE_scale - x0)/(0.525*(FWHM)))^2))
    endfor


//"NEW FUNCTION"

    .......
        variable q //this will be the index over the different "exp_dump_" waves coming out for the experiment
    variable i
    string N1s_peak_
 
    WAVE BEs
    WAVE BE_scale
    WAVE $exp_dump_ //I guess this is also not the way to use $ in a UDF.....
 
    for (q = 0; q<lambda_points; q+=1) // I would like to use something like this.....
        Variable x3 = $exp_dump_    // I don't know how to implement this one. I was thinking to two co-indented for loops......
        for (i = 0; i<points; i+=1)
            N1s_peak_ = "N1s_peak_" + num2str(i)
            Make/O/N=161 $N1s_peak_/WAVE=wout
            Variable x1 = BEs[i]
            Variable x2 = exp_dump[i]
            wout =  x2*(0.0355 + 0.95*((V_index)*(exp(-((BE_scale - x1)/(0.525*(FWHM)))^2)) // Here I don't know how to introduce the second dependency, with q that varies over the different "exp_dump" waves......
        endfor
    endfor
I am guessing that you have a series of exp_dump waves named something like "exp_dump_1", "exp_dump_2", etc., and that they all are located in the current data folder. A reference to one of the waves can be obtained using  Wave w = $("exp_dump_" + num2str(j)); just as you do for the output wout.

Modify your new code like this:

//WAVE $exp_dump_ //I guess this is also not the way to use $ in a UDF.....
Variable j
 for (j = 0; j<lambda_points; j+=1) // I would like to use something like this.....
    //Variable x3 = $exp_dump_    // I don't know how to implement this one. I was thinking to two co-indented for loops......
        Wave w = $("exp_dump_" + num2str(j))
    for (i = 0; i<points; i+=1)
        N1s_peak_ = "N1s_peak_" + num2str(i)
        Make/O/N=161 $N1s_peak_/WAVE=wout
        Variable x1 = BEs[i]
        //Variable x2 = exp_dump[i]
                Variable x2 = w[i]
        wout =  x2*(0.0355 + 0.95*((V_index)*(exp(-((BE_scale - x1)/(0.525*(FWHM)))^2))
                // Here I don't know how to introduce the second dependency, with q that varies over the different "exp_dump" waves......
    endfor
endfor


Also note that you should avoid using "q" as loop index because it is a built in function in Igor.
Many thanks jtigor! This solves the problems that I had. Since I want to save all the results that I obtain in the second for loop for all the js of the first for loop, I have modified the code adding a second index in the "N1s_peak_" waves:

for (j = 0; j<lambda_points; j+=1)
       Wave w = $("exp_dump_" + num2str(j))
        for (i = 0; i<points; i+=1)
            N1s_peak_ = "N1s_peak_" + num2str(j) + num2str(i) // I have added here a new index for the "N1s_peak_" waves.
            Make/O/N=161 $N1s_peak_/WAVE=wout
            Variable x1 = BEs[i]
            Variable x2 = w[i]
            wout =  x2*(0.0355 + 0.95*((V_index)*(exp(-((BE_scale - x1)/(0.525*(FWHM)))^2))
        endfor
    endfor


Again, thanks a lot for your support! It was extremely helpful!

Duncan


jtigor wrote:
I am guessing that you have a series of exp_dump waves named something like "exp_dump_1", "exp_dump_2", etc., and that they all are located in the current data folder. A reference to one of the waves can be obtained using  Wave w = $("exp_dump_" + num2str(j)); just as you do for the output wout.

Modify your new code like this:

//WAVE $exp_dump_ //I guess this is also not the way to use $ in a UDF.....
Variable j
 for (j = 0; j<lambda_points; j+=1) // I would like to use something like this.....
    //Variable x3 = $exp_dump_    // I don't know how to implement this one. I was thinking to two co-indented for loops......
        Wave w = $("exp_dump_" + num2str(j))
    for (i = 0; i<points; i+=1)
        N1s_peak_ = "N1s_peak_" + num2str(i)
        Make/O/N=161 $N1s_peak_/WAVE=wout
        Variable x1 = BEs[i]
        //Variable x2 = exp_dump[i]
                Variable x2 = w[i]
        wout =  x2*(0.0355 + 0.95*((V_index)*(exp(-((BE_scale - x1)/(0.525*(FWHM)))^2))
                // Here I don't know how to introduce the second dependency, with q that varies over the different "exp_dump" waves......
    endfor
endfor


Also note that you should avoid using "q" as loop index because it is a built in operation in Igor.

Hi to all again,

I'm back with a problem. Here is the code on which I'm working on:

for (j = 0; j<lambda_points; j+=1)
        Wave w = $("exp_dump_" + num2str(j))
            for (i = 0; i<points; i+=1)
                N1s_peak_ = "N1s_peak_" + num2str(j) + num2str(i)
                Make/O/N=161 $N1s_peak_/WAVE=sim
                Variable x1 = BEs[i]
                Variable x2 = w[i]
                sim =  x2*(0.0355 + 0.95*((V_index)*(exp(-((BE_scale - x1)/(0.525*(FWHM)))^2)) + (1-V_index)*(1/((BE_scale-x1)^2+0.5*FWHM)) + ((theta)*((BE_scale - x1)/(1+abs(BE_scale - x1))))))
            endfor
            for (i = 0; i<points; i+=1)
            summation_ = "summation_" + num2str(j)
            Make/O/N=161 $summation_/WAVE=wout
            //SetScale/I x 397, 405, "161", $summation_
                Wave p = $("N1s_peak_" + num2str(j) + num2str(i))
                Variable x3 = p[j][i]
                    wout = wout + x3
                endfor
endfor


So, in the second for loop within the primary one I want to make a summation of the waves previously generated by the first indented for loop (i.e. "N1s_peak_"). The function runs with no problems but, when I go to the results, in the "summation" waves (correctly indexed by j) I find that all the 161 values are zero. Where do I make a mistake? Could somebody help me?

Many thanks in advance for your help,

Duncan
I suggest that you break your multiple for-loops out. For example, create a function that makes one N1sPeak based on an input index.

Function GenerateOneN1sPeak(... , index)
...
end


Once that works, put it in a for-loop ...

Function GenerateN1sPeakSet(HowMany)
      variable HowMany

       variable ic

       for (ic=0;ic<HowMany;ic+=1)
              GenerateOneN1sPeak(... , ic)
       endfor
       return
end


Build your code this way. You can debug it a lot easier (and we can read it better to help you).

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
Many thanks jjweimer, for sure now it is easier to read it!
This is a really good tip! Thanks!

Duncan