Math in applescript: Handler gets stuck and CPU is at 0%

Hey guys,

I’m using a handler to take a list of records, make come calculations using the data in each record, and then append the results from the calculations to each record in the list.

I have the handler built, and it works perfectly for small lists, but stops working with larger lists or records. When it stops working, it doesn’t seem to be stuck in a loop or anything (which would make it get stuck in all cases), because the cpu goes to 0% and there is simply no activity.

The culprit must be that I’m using the Satimage scripting addition to provide three functions: inverse tangent, absolute value, and a simple sort. I can do the sort and absolute value functions without the addition, but the inverses tangent is another problem.

Anyways, here’s the handler and a call for it. If you shrink down the (simplified) list of records to five or so (sometimes more) then it works fine, but if you copy the list of records over and over again to make it bigger, like over 20, then the handler hangs with no activity. At the bottom of the post is a record from the list as I’m actually using it (which was made using this exact handler)

On a side note, I originally found this problem when I had these calculations being performed inside the handler I use to fetch data and make the list of records, but the problem persists when it happened afterwards as a separate handler, and this way is easier for pleading to the community.

ALMOST FORGOT, here’s a link to the scripting addition I’m using: http://www.satimage.fr/software/downloads/Satimage374.pkg

Thanks,

Tim

on directionality(cpInfo)
	set outputList to {}
	repeat with CP in cpInfo
		set eigenvalues to eigenvalues of CP
		set eigenvalues to sortlist (eigenvalues)
		set theta to (atan ((abs ((item 3 of eigenvalues) / (item 2 of eigenvalues))) ^ (1 / 2)))
		set phi to (atan ((abs ((item 3 of eigenvalues) / (item 1 of eigenvalues))) ^ (1 / 2)))
		set end of outputList to CP & {theta:theta, phi:phi}
	end repeat
	return outputList
end directionality

return directionality({{eigenvalues:{-0.9597067, -0.8515133, 1.037286}}, {eigenvalues:{-0.6967747, -0.663849, 0.4989427}}, {eigenvalues:{-0.7110512, -0.6271766, 0.4827656}}, {eigenvalues:{-0.006542409, -0.003578518, 0.04239628}}, {eigenvalues:{-0.008725163, -0.006836066, 0.05433055}}, {eigenvalues:{-0.006010937, -0.002223808, 0.03224129}}, {eigenvalues:{-0.001855394, -0.001145129, 0.01483521}}, {eigenvalues:{-0.03390511, -0.03304477, 0.1504457}}, {eigenvalues:{-0.03119456, -0.02933444, 0.1415584}}, {eigenvalues:{-0.003994763, -0.003015927, 0.02664459}}, {eigenvalues:{-0.003536827, -0.003140148, 0.0272672}}, {eigenvalues:{-0.003078962, -4.091325E-4, 0.02010834}}, {eigenvalues:{-0.05565543, -0.05536525, 0.1782501}}})
{CP:"307", rankSignature:"(3,-1)", del:"-0.7739336E+00", rho:"0.4056540E+00", eigenvalues:{-0.9597067, -0.8515133, 1.037286}, theta:0.834655257394, phi:0.804827084365}

Model: MBP-r
AppleScript: 2.2.2
Browser: Safari 536.25
Operating System: Mac OS X (10.8)

FWIW, I tried it using the sort and atan from ASObjC Runner without striking any problems:

on directionality(cpInfo)
	set outputList to {}
	repeat with CP in cpInfo
		set eigenvalues to eigenvalues of CP
		tell application id "au.com.myriad-com.ASObjC-Runner"
			set eigenvalues to rearrange list eigenvalues
			set {theta, phi} to do trig on ¬
				{((my doAbs((item 3 of eigenvalues) / (item 2 of eigenvalues))) ^ (1 / 2)), ¬
					((my doAbs((item 3 of eigenvalues) / (item 1 of eigenvalues))) ^ (1 / 2))} ¬
					using function "atan"
		end tell
		set end of outputList to CP & {theta:theta, phi:phi}
	end repeat
	return outputList
end directionality

on doAbs(aVal)
	if aVal < 0 then return -aVal
	return aVal
end doAbs

That was using your sample data, copied and pasted until there were about 1500-odd records.

Thanks Shane,

However, I hated having to use the osax file in the first place, and having the object c runner in the background all the time just for the very limited use of the inverse tangent function is undesirable. Might you know of another alternative? Ideally I’d have my own library of math functions with an inverse tangent handler, but I’m probably too lazy and finding the appropriate code to port to applescript could be a chore.

From the fact that it worked fine with the runner, I can assume that my problem is the Satimage.osax file? Seems weird that an inverse tangent function that works fine 5 times in a few milliseconds should break down if ran 500 times. Really strange.

Also, these scripts are to be deployed on other people’s, and the installation script I’ve written works find for copying the script, services, and osax files, but to have it handle the installation of the runner would be another thing to deal with.

Do you have any suggestions for someone who wants to do math in applescript, but without an osax file, or at least with a working osax file?

Thanks,

Tim

Hello!

Try this:

I see Shane beat me to it. :slight_smile:

You better stick with the osax or AsObj-C runner, unless you want the the inverse tangent implemented with a tailor series, which doesn’t behave that bad, but still.

I believe the main problem in your code was that you used the property name eigenvalues as a variable.

set outputlist to {}
set cpInfo to {{eigenvalues:{-0.9597067, -0.8515133, 1.037286}}, {eigenvalues:{-0.6967747, -0.663849, 0.4989427}}, {eigenvalues:{-0.7110512, -0.6271766, 0.4827656}}, {eigenvalues:{-0.006542409, -0.003578518, 0.04239628}}, {eigenvalues:{-0.008725163, -0.006836066, 0.05433055}}, {eigenvalues:{-0.006010937, -0.002223808, 0.03224129}}, {eigenvalues:{-0.001855394, -0.001145129, 0.01483521}}, {eigenvalues:{-0.03390511, -0.03304477, 0.1504457}}, {eigenvalues:{-0.03119456, -0.02933444, 0.1415584}}, {eigenvalues:{-0.003994763, -0.003015927, 0.02664459}}, {eigenvalues:{-0.003536827, -0.003140148, 0.0272672}}, {eigenvalues:{-0.003078962, -4.091325E-4, 0.02010834}}, {eigenvalues:{-0.05565543, -0.05536525, 0.1782501}}}

set outputlist to directionality(cpInfo, outputlist)
log outputlist

(*eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365, eigenvalues:-0.9597067, -0.8515133, 1.037286, theta:0.834655257394, phi:0.804827084365*)

on directionality(cpInfo, outputlist)
	script o
		property L : cpInfo
	end script
	set outputlist to {}
	set {c, i, fail} to {count cpInfo, 1, false}
	try
		repeat c times
			set MyEigenValues to eigenvalues of item i of o's L
			set MyEigenValues to sortlist (MyEigenValues)
			set theta to (atan ((abs ((item 3 of MyEigenValues) / (item 2 of MyEigenValues))) ^ (1 / 2)))
			set phi to (atan ((abs ((item 3 of MyEigenValues) / (item 1 of MyEigenValues))) ^ (1 / 2)))
			set end of outputlist to item i of o's L & {theta:theta, phi:phi}
		end repeat
	on error e number n
” Christopher Stone
		set {cr, sep} to {return, "------------------------------------------"}
		set errmsg to sep & cr & "Error: " & e & cr & sep & cr & "Error 
Number: " & n & cr & sep
		tell application "SystemUIServer"
			activate
			display dialog errmsg
		end tell
		set fail to true
	end try
	if fail then return null
	return outputlist
end directionality

Thanks McUsr,

I don’t know where you guys come up with this stuff. Every time I appeal to this community, the knowledge of my own incompetence in programming is reinforced!

However, when running your script in applescript editor, it still hangs and there’s no CPU activity (jumps to 1.5% or so every minute, but there’s nothing really going on).

Can I ask you guys if the same “hanging” occurs with my script when running on your computers? Shane, when you run my code with ~1500 records, does it complete? I ask for two reasons, 1) I’m wondering if it’s just me, and 2) The script that this handler is a part of has two ways to getting information, which are basically the same: the handler that fetches desired data from a huge text file can do so by searching for strings in the text file (particular numbers), or by systematically fetching all such data from the text file. At first, my calculation and appending of theta and phi to the record was being done in the same handler that fetches the data, and it was only working if numbers were specified. Numbers being specified tends to greatly reduce the number of records in the list, since there’s sometimes thousands of such data in the text file and I wouldn’t normally specify more than 30 or so numbers.

I think that the large list is what’s killing the current handler, but I want to know if this no activity hanging occurs on your computers as well.

Thanks,

Tim

Why? It can be invisible, and it’s actually less intrusive than a scripting addition, in that it runs in its own memory partition.

It looks that way, although I’m a bit surprised.

Assuming they are being deployed as applets, you can bundle Runner in with them, and include code to launch it invisibly and quit when finished. Then there’s nothing to install.

Not really. You could write the whole thing as an ASObjC app, if what you are really after is something self-contained. But even that isn’t quite so simple because atan isn’t accessible to ASObjC without something like Myriad Helpers, which means using either Xcode or AppleScriptObjC Explorer.

I just loaded Satimage.osax, and yes, it completes. Same version, I think (Get Info says “For 10.6 only”, but I’m running 10.8.1)…

Hi Shane,

Actually, the “installer” I wrote just copies all the scripts and services I wrote to the scripts and services folders in the user’s home folder so that the services become available through the menubar. I’ve read a little about doing applets, but not in depth. If I already have all of the scrips written (calling to other scrips for handlers as well), what kind of investment am I looking at to have a finished product, and what is the execution like on another (or my) machine? Similar to running a service, or would the user open the applet and have that trigger the main script?

I’ve only tiny experience with Xcode, and this would mean considerably more time invested then making an applet, correct?

Thanks,

Tim

That’s so strange. I’m running 10.8.1 too… Couldn’t have anything to do with hardware? I’ve got one of the new i7’s and an SSD, which is the main difference from my old setup…

I just thought of something. Is it necessary that the .osax file be in the main ScriptingAdditions folder located in the Library folder of the drive root folder? I moved the .osax file to the ScriptingAdditions folder within the Library folder in the user home folder. But if that’s a problem, shouldn’t it not work at all rather than just with large files?

Another solution… there is a unix command line tool “bc” which can allow you to do math and is already on everyone’s computer. I haven’t used it much so I can’t help with the code but it does have the arctangent function you need. So just figure out the bc command and run it from applescript with “do shell script”. See the wikipedia description for bc here.

It’s basically having it as a standalone app. But by the sound of things that’s not really what you’re after.

Yes. It would actually be very easy in AppleScriptObjC Explorer because it has has built-in access to trig stuff via Myriad Helpers, but you’d have to do it within 30 days or the trial period would run out :frowning: And unless you had other uses for Explorer, it would be silly buying it for one job. Much and all as it would help me pay my bills :slight_smile:

Want to swap? :wink:

I doubt it (I’m on an i5 iMac).

That’s probably a good solution. where’s DJ when we need him?

I guess your scripts are having more to it than just this handler. Are you sure this is were the fail lies?

try inserting this handler with messages during your script, the file name you specify will pop up in your console log. Don’t insert statements within the loop, but before and after!

to logit(log_string, log_file)
	do shell script ¬
		"echo `date '+%Y-%m-%d %T: '`\"" & log_string & ¬
		"\" >> $HOME/Library/Logs/" & log_file & ".log"
end logit

I’ll copy up your dataset to 1500 records, and come back real soon with the result in the mean time.

It would look strange; me sitting in a coffee shop with an iMac on the table… :slight_smile:

Hello. It ran flawlessly from within script debugger with 1755 records in 3.77 seconds.

bc stands for before Christ I believe, and is really a terrible tool, but I guess it is usable. after you have “formatted” a script to feed it! :slight_smile:

I’m pretty sure. I can run just this handler with the record I provided in my original post (actually I have to copy it about a dozen times) and the no activity hanging occurs. Also, If i comment out this handler and change the arguments in the main script accordingly, it works perfectly with all the files I use it on, the biggest of which gives me close to 1000 records.

Hi! :slight_smile:

Please insert logstatements, and try - on error - end try blocks too, so you can see precisely where it hangs.

You should have logstatements before and after the loop within the handler, and before and after the call to the handler.

You see, I put in an errorhandler within the handler, and if something had gone awry inside it, you would have known, by seing the error message.

I don’t get it. It’s such a simple handler anyways. I can copy just this handler to a new script and try it with 273 records and it just sits there “Running”.

The whole process include like 40 handlers in 7 script files, but there was never any problems until this handler. At least never any problems like this. There were some infinite loops here and there when I’d been working late and got negligent…

And I think you’re right about the meaning of BC, but I can’t foresee much complicated math in the future of this script, so it might do the trick…