create a procedure to solve equations
daviddoji
In a console I know how to do it:
1- I create a wave for the coefficients (for example: PolyCoefs = {1,2,3,...})
2- Then I use the built-in function, FindRoots/P=PolyCoefs. It generates a new wave called "W_polyRoots" with the roots of the equation with coefficients 1+2*x+3*x^2+...
I´m not too keen on Igor programming (I don´t know how to create the panel even!) but I have written some small procedures which I can execute in the console. This is my next step in Igor!
Thanks for your suggestions and sorry for my English!
Your code will read the contents either by linking the SerVariable to a variable in the datafolder, or you can use ControlInfo to read it's contents. Based on the number of coefficients (ItemsInList), you can build the coefficient wave and run FindRoots.
Results can be printed in the command window or displayed in another SetVariable control on your panel.
April 24, 2013 at 09:05 am - Permalink
"Polynomial Solver", Poly_Solver_X()
end
Function Poly_Solver_X()
NewPanel/k=1 /w=(20,400,300,530)/N=PolySolverPanel
string example = "A,B,C"
titlebox title1 pos={5,5}, size={160,30}, title="Enter a comma separated list of coefficients"
setvariable coef_setvar pos={5,30}, size={160,30},noproc, value=_STR:example, help = {"Enter a comma separated list such as 1,5,3"}
button solvebutton, pos={5,60}, size={100, 30}, title="Solve Polynomial", proc=solve_proc
//If you wish to display results in the panel, make another SetVariable Control here, position below the button
end
Function Solve_Proc(CtrlName) : ButtonControl
String CtrlName
controlinfo/w=PolySolverPanel coef_setvar //retrieve text
string coeflist = s_value
variable num_coef = itemsinlist(s_value, ",") //number of coefficients entered
Make/o/N=(num_coef) PolyCoefWave
variable i
for (i=0; i<num_coef; i+=1)
polyCoefWave[i] = str2num(stringfromlist(i, coeflist, ","))
endfor
FindRoots/P=polyCoefWave
//Add code here to report results from W_polyRoots however you see fit
end
April 24, 2013 at 09:37 am - Permalink
April 24, 2013 at 12:03 pm - Permalink
Thanks for all. It makes exactly what I need.
If I want to display in the same panel the solutions of the polynomial equation, I make what you suggest in the procedure (create a setvariable under the button):
setvariable poly_roots pos={5,90}, size={160,30},noproc, value=W_polyCoef
But it doesn´t work. The procedure creates a wave called "W_polyCoef" and I want to show in the panel the values of this new wave.
Any hints?
April 25, 2013 at 08:10 am - Permalink
After the fit, populate a string with the numbers from W_PolyRoots, similar to how I first created the PolyCoefWave from a string. Remove the value assignment from your setvariable (still create it though).
for (i=0; i<numpnts(w_polyroots); i+=1) //for each root found
results_string += "Root" + num2str(i+1) + " = " num2str(w_PolyRoots[i]) + " " //Add text to report the Root value
endfor
SetVariable poly_roots value=_STR:results_string //Assign text from results_string to the SetVariable
Also, make sure the setvariable is large enough to display the text.
April 25, 2013 at 09:22 am - Permalink
April 25, 2013 at 10:28 am - Permalink
Good point
April 25, 2013 at 10:29 am - Permalink
Menu "User Procedures"
"Polynomial Solver", Poly_Solver_X()
end
Function Poly_Solver_X()
NewPanel/k=1 /w=(20,400,300,530)/N=PolySolver
string example = "A,B,C"
titlebox title1 pos={5,5}, size={160,30}, title="Enter a comma separated list of coefficients"
setvariable coef_setvar pos={5,30}, size={160,30},noproc, value=_STR:example, help = {"Enter a comma separated list such as 1,5,3"}
button solvebutton, pos={5,60}, size={100, 30}, title="Solve Polynomial", proc=solve_proc
//If you wish to display results in the panel, make another SetVariable Control here, position below the button
end
Function Solve_Proc(CtrlName) : ButtonControl
String CtrlName
controlinfo/w=PolySolver coef_setvar //retrieve text
string coeflist = s_value
variable num_coef = itemsinlist(s_value, ",") //number of coefficients entered
Make/o/N=(num_coef) PolyCoef
variable i
for (i=0; i<num_coef; i+=1)
polyCoef[i] = str2num(stringfromlist(i, coeflist, ","))
endfor
FindRoots/P=polyCoef
string results_string
wave W_polyRoots
setvariable poly_roots pos={5,90}, size={160,30},noproc, value=_STR:results_string
for (i=0; i<numpnts(W_polyRoots); i+=1) //for each root found
results_string += "Root" + num2str(i+1) + " = " num2str(i=0;W_polyRoots[i]) + " " //Add text to report the Root value
endfor
//Add code here to report results from W_polyRoots however you see fit
end
But it doesn´t complile. It fails at the end (num2str()It tells me:
expected a keyword or and object name
April 29, 2013 at 02:05 am - Permalink
shouldn't that be something like:
April 29, 2013 at 02:57 am - Permalink
Now it compiles, but the panel doesn´t show the solutions, although it creates the wave with them (W_polyRoots) because the wave W_polyRoots has a real and a complex subwaves as s.r.chinn pointed.
It gives me the following error:
While executing an user function, the following error ocurred: attemp to use a null string variable.
In my case, I will only need the real part.
April 29, 2013 at 06:11 am - Permalink
This occurs when you try to do something with the string before it actually contains anything. Try this:
String CtrlName
controlinfo/w=PolySolver coef_setvar //retrieve text
string coeflist = s_value
variable num_coef = itemsinlist(s_value, ",") //number of coefficients entered
Make/D/o/N=(num_coef) PolyCoef
variable i
// for (i=0; i<num_coef; i+=1)
// polyCoef[i] = str2num(stringfromlist(i, coeflist, ","))
// endfor
polyCoef = str2num(stringfromlist(p, coeflist, ",")) //this is quicker than the for-loop
FindRoots/P=polyCoef
wave W_polyRoots
string results_string=""
for (i=0; i<numpnts(W_polyRoots); i+=1) //for each root found
results_string += "Root" + num2str(i+1) + " = " + num2str(W_polyRoots[i]) + "; " //Add text to report the Root value
endfor
setvariable poly_roots pos={5,90}, size={160,30},noproc, value=_STR:results_string
//Add code here to report results from W_polyRoots however you see fit
end
April 29, 2013 at 06:39 am - Permalink
You need to change
wave W_polyRoots
setvariable poly_roots pos={5,90}, size={160,30},noproc, value=_STR:results_string
for (i=0; i<numpnts(W_polyRoots); i+=1) //for each root found
results_string += "Root" + num2str(i+1) + " = " num2str(i=0;W_polyRoots[i]) + " " //Add text to report the Root value
endfor
//Add code here to report results from W_polyRoots however you see fit
end
to
wave W_polyRoots
for (i=0; i<numpnts(W_polyRoots); i+=1) //for each root found
results_string += "Root" + num2str(i+1) + " = " num2str(i=0;W_polyRoots[i]) + " " //Add text to report the Root value
endfor
setvariable poly_roots pos={5,90}, size={160,30},noproc, value=_STR:results_string
//Add code here to report results from W_polyRoots however you see fit
end
This seems to work.
Also, you might want to check for complex results and for unique solutions.
April 29, 2013 at 06:40 am - Permalink
I´ll try to figure out how to solve the issue with the imaginary numbers although it isn´t a problem for me
April 29, 2013 at 07:20 am - Permalink
EDIT: I see an empty igor section so here is the line I tried to write above...
results_string += "Root" + num2str(i+1) + " = " num2str(real(W_polyRoots[i])) + " " //inserted REAL command to use the real component.
April 29, 2013 at 09:27 am - Permalink