subroutine calling itself + passing by reference
daggaz
Main function()
stuff
stuff
subroutine_1(param1,param2)
more stuff
end main function
function subroutine_1(para1,para2)
variable ¶1, ¶2
stuff
if true
...change data, including para1
...subroutine_1(????) <-what goes in here?
else
...other stuff
...break
end subroutine_1
This would be a simple goto statement, but I guess those died with the dinosaurs. Is this even the way to go about with this, or are there more clever solutions? I already keep most of my variables as waves as it is to avoid the whole local/global var mashup.. Sorry if this is a simple question, I havent programmed since my days in C++ and we never got to object orientated..
Try this to see a brief example of self-iteration on a function ...
Function Main()
variable ac = 0, bc = 0
make/O/N=10 test=0
change(ac,bc)
return 0
end
Function Change(ac,bc)
variable ac, bc
wave test
test = ac*p + bc
doupdate
string pStr = "Do you want to increment ac (YES) or bc (NO) or neither (CANCEL) with " + num2str(ac) + ", " + num2str(bc) + "?"
DoAlert/T="Tell Me So", 2, pStr
switch(V_flag)
case 1:
ac += 1
Change(ac,bc)
break
case 2:
bc += 1
Change(ac,bc)
break
case 3:
break
endswitch
return 0
end
After you put this in to the procedure window, do this in the command line
display test
main()
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
August 11, 2012 at 08:43 am - Permalink
I could swear I have run afoul of just that before, but maybe .. i dunno... thanks =)
August 11, 2012 at 09:35 am - Permalink
variable ac=0, bc=0
... use the initial values of ac and bc somehow
Change(ac,bc)
... use the changed values of ac and bc somehow
return 0
end
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
August 11, 2012 at 11:41 am - Permalink
Curious about the IF loop, as apparently I cant use a break statement inside of one. Am I forced to use a case loop, or will IGOR understand to drop the original subroutine when the subroutine calls itself? Or will it run the second iteration of subroutine, and then go back and finish the first iteration? Im hoping its similar to the return statement and is the former and not the latter case.
August 13, 2012 at 05:20 am - Permalink
August 13, 2012 at 05:55 am - Permalink
Break statements do not exist in if expressions because there is no iteration taking place - the code only runs once. If you want to break out of an if statement, that simply means that you should introduce another conditional.
For example:
i = 3
myWave = 4
if (something_else)
break // illegal
i = 4
endif
Then you should achieve this using
i = 3
myWave = 4
if (!something_else)
i = 4
endif
endif
I'm not sure where you're stuck with your scheme. What you're trying to do, a function calling itself, is known as recursion, and it is an accepted technique in every programming language I've used.
Perhaps it would help to realize that, when you call a function in Igor, Igor immediately starts running that function, and will only return to the original function when that function finishes. In other words, functions are never interleaved.
Also, remember that local variables and strings do not have names - they're simply tiny regions of memory somewhere in your computer's memory. Variable names exist so Igor knows what location you're referring to when you're coding, but every function can use whatever names it wants. It's simply an agreement between you and the Igor compiler. When you actually run the code there is no such thing as variable names or string names.
The exceptions are global variables, of course.
August 13, 2012 at 09:36 am - Permalink
You can use the
return
statement to exit from anif... endif
block.Make sure any loose ends are tied up before doing so, however.
Another thought...
I think that when he writes
741 is saying that when a function is called recursively, the second and any following instances of that function operate independently of the the preceding instances of that function. They do not share local variables. For each instance of the function, a separate block of memory is allocated in which that function exists and plays out its life.
August 13, 2012 at 07:37 am - Permalink
August 13, 2012 at 08:18 am - Permalink
Then, pass by reference might be what you need. The change function should return a value that tells whether to call itself again from the main function. Something akin to this ...
variable redoit = 0
variable ac = 0, bc = 0
make/O/N=10 mywave=0
do
redoit = Change(mywave,ac,bc)
ac += 1
bc *= 3
while(redoit=0)
return 0
end
Function Change(mywave,ac,bc)
wave mywave
variable $ac, $bc
mywave = ac*p + bc
if (mywave[0] <= 10)
return 1 // redo the calculations until first value is larger than 10
else
return 0 // do not redo the calculations
endif
end
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
August 13, 2012 at 06:59 pm - Permalink
I can't help thinking that there might be a more straightforward way to code what you want to do, if you could describe the result you're trying to get. Instead of asking about implementation details (as interesting as they might be) perhaps we could help you find an alternate approach to your problem.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
August 14, 2012 at 09:19 am - Permalink
Hmm not sure how to explain it better than thru implementation details.. but I'll give it a try.
I made a program (nearly finished, will upload it soon) which generates synthetic data of sub-diffraction micrograph images in order to test some of our private lab software. The user inputs a number of parameters (the list keeps growing), and the program gets to work generating data. The data consist of randomly placed 2D gaussian profiles (with noise) generated randomly from within the parameter ranges. Each iteration of the program produces two "micrographs"; one with "vesicles", and another with matching "protein" signatures for a specifiéd percent of those vesicles, along with additional nonlocalized signatures representing non-specific binding. By localized, I mean the particle centers between the two images are identical.
In order to optimize the speed (it was real slow in the first build), I divide each image array into zones. When I generate a particle, I then "roll" for a zone, so as to avoid iterating over the entire image. Thing is, with the zones it is now more likely to fill the space (there is logic to avoid overlapping the particles) and this would break my code. The simplest and most logical solution I could think of, was to check each zone for available target pixels based on the incoming particle, something which needs to be done anyhow for targetting. If the available pixels cant accomodate the particle, I simply shrink the particle to match. But if there are no available pixels even for the smallest particles, I need to remove the zone from the list (each zone is actually a set of corner coordinates saved in wave form) so as not to roll it again.
So my zonechecker function rolls a zone, checks it for targets, and if there are none, it needs to kill that zone and restart itself. Otherwise it picks a target pixel and passes that info to the particle drawing subroutine which uses it as the center point. It really is just a simple goto loop that is needed, but things got complicated with object orientated programming.
Well.. thats a lot of words and Im not sure if it helps or if its what you meant, but there ya go =P
August 14, 2012 at 11:46 am - Permalink
August 14, 2012 at 11:48 am - Permalink
If I break this down to avoid GoTo, I get something like this ...
* get data image
* get user input parameters
* create empty model image
* break model image in to zones
-> Loop on All Desired Zones
** create a new zone for model image using input parameters
** check it for targets against data image
--> if (targets exist)
*** save this zone
*** exit this loop
--> else
*** kill this zone
*** exit this loop
-> End Loop on All Desired Zones
* stitch together all viable zones to model image
* display model image
Is this helpful?
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
August 14, 2012 at 01:11 pm - Permalink
August 15, 2012 at 03:01 am - Permalink