-- ================================================================== -- 20DayAuto.scpt - Stephen Randall - 2012 -- -------------------------------------------------- -- AppleScript that automatically downloads new files from APL, runs calculations, makes plots, and -- updates the Cassini server. -- Maintenence/Debugging help: -- + Make sure that you're not using Mail.app on this computer. If you need/want to, you -- will need to edit the email warning code. -- + The script is dependent on file structure. If the script needs to move to -- another computer, a number of changes will be needed. -- + File names need to stay relatively consistent. If they ever go to v38, code will be needed -- to account for that. -- + In the case of a crash, the event log should be of some help. In addition, the program should -- be able to perform a clean run the next time it's called by doing some error checking and -- correcting before re-running. -- + The name of the temporary directory is found in a .txt file in local_chems_files. There is an un-enforced -- agreement between this script and the IDL routine that they should both use that directory. Breaking -- that agreement will cause the script to perform in unpredictable ways. -- + Avoid moving and changing items in the local_chems_files directory. -- + I assume that APL will release [but not necessarily update] the PHA and Basic Rates data at the same -- time. If this is not the case, it's possible for the IDL routine to be called without the necessary data. -- + The file-name parsing towards the end is dependent on the default naming convention of the IDL -- routines. Please don't change those. -- + It is assumed that the location of XQuartz.app is /Applications/Utilities. -- + In addition, the final file moves and clean-up is dependent on the current system set-up. If you move -- the folders where the output is stored, the clean-up code will have to be modified accordingly. -- + The ephem files are listed in defaults.txt. This is separate from the file names listed in the phaflux and -- phaplot default files. -- + There exists a "kill switch" when running the IDL routines. This is in place to prevent IDL from getting -- stuck in a loop when it's reading a data file without all the correct information. While the script is -- supposed to clean up after itself in this case, its behavior is technically undefined. -- ================================================================== global emailSubject global emailContent global periodoffset -- initialize global email related variables set emailSubject to "No files downloaded from APL today" set emailContent to "No new files found" -- Logging function on log_text(msg) set theLine to (do shell script "date +'%Y-%m-%d %H:%M:%S'" as string) & " " & msg do shell script "echo " & quoted form of theLine & " >> ~/local_chems_files/20DayAuto_events.log" end log_text -- ================================================================== -- Get the latest files from the APL server -- ================================================================== do shell script "/usr/local/bin/python3 ~/local_chems_files/getCHEMSFiles.py > ~/local_chems_files/pyout.txt" -- If we couldn't connect to the APL servers, then send an email try set pyout to read (file "Macintosh HD:Users:stephen:local_chems_files:pyout.txt") set pylines to count paragraphs in pyout if pylines is greater than 3 then my log_text("rsync failed to connect, email sent") set theSubject to "Script Notification: rsync Connect Failed" set dateToday to date string of (current date) set theContent to "The Cassini/CHEMS script ran this morning (" & dateToday & "), but rsync failed to connect to the APL servers." do shell script "cat << EOF | /usr/sbin/sendmail -t From: CASSINI MacSubject: " & theSubject & " Date: " & dateToday & " To: Douglas C. Hamilton CC: Scott " & theContent & " EOF" -- tell application "Mail" -- Create the message -- set theMessage to make new outgoing message with properties {subject:theSubject, content:theContent, visible:false} -- Set the recipients -- tell theMessage -- make new to recipient with properties {name:"Doug Hamilton", address:"dch@umd.edu"} -- make new to recipient with properties {name:"Scott Lasley", address:"slasley@space.umd.edu"} -- send -- end tell -- delay 20 -- let the message send -- quit -- end tell return end if on error -- Do nothing; this is the normal behavior end try -- ================================================================== -- Create a temporary directory to work in; set up the log file -- ================================================================== do shell script "rm -f ~/local_chems_files/20DayAuto_events.log" set tf to (open for access (file "Users:stephen:local_chems_files:temp_dir.txt")) set temp_dir to (read tf for (get eof tf)) if fileExists(temp_dir) then do shell script "rm -r " & quoted form of temp_dir do shell script "mkdir " & quoted form of temp_dir -- ================================================================== -- Figure out which periods to update -- Periods must include at least one file from newFiles.txt [both pha and sci] and must have all files necessary -- in the 20-day period -- ================================================================== try set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:newTrange.txt") with write permission on error number error_number my log_text(error_number) close access (file "Macintosh HD:Users:stephen:local_chems_files:newTrange.txt") set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:newTrange.txt") with write permission end try set eof of write_file to 0 write "Time Range (yyyy ddd hhmm)" to write_file set periods to {} set pcount to 1 set the end of periods to pcount set AppleScript's text item delimiters to "/" try set new_files to 1 set newFilesList to (read file "Macintosh HD:Users:stephen:local_chems_files:newFiles.txt" as {text}) set emailSubject to ((count paragraphs of newFilesList) - 1 as text) & " files downloaded from APL" set emailContent to "Downloaded and processed these files from APL: " & newFilesList as text -- repeat with file_path in paragraphs of (read file "Macintosh HD:Users:stephen:local_chems_files:newFiles.txt" as {text}) repeat with file_path in paragraphs of newFilesList my log_text("file_path = " & file_path) if length of file_path is greater than 0 then set file_name to (text item 6 of file_path) set doy to (text 15 through 17 of file_name) as integer set y to (text 11 through 14 of file_name) as integer set ud to ((doy div 20) as integer) * 20 + 20 set ld to (ud - 20) if not (periods contains ((y as text) & formatDay(ud))) then set item pcount of periods to ((y as text) & formatDay(ud)) set pcount to 1 + pcount set the end of periods to pcount my log_text("tryNewPeriod(" & file_path & ", " & file_name & ", " & y & ", " & ud & ", " & ld & ", " & write_file & ")") tryNewPeriod(file_path, file_name, y, ud, ld, write_file) -- Take care of values that need to trigger multiple periods if (y - 1) mod 4 is equal to 0 and doy ≤ 4 and not (periods contains ((y as text) & formatDay(4))) then my log_text("tryNewPeriod(" & file_path & ", " & file_name & ", " & y & ", " & 4 & ", " & 350 & ", " & write_file & ")") tryNewPeriod(file_path, file_name, y, 4, 350, write_file) set item pcount of periods to ((y as text) & formatDay(4)) set pcount to 1 + pcount set the end of periods to pcount else if doy ≤ 5 and not (periods contains ((y as text) & formatDay(5))) then my log_text("tryNewPeriod(" & file_path & ", " & file_name & ", " & y & ", " & 5 & ", " & 350 & ", " & write_file & ")") tryNewPeriod(file_path, file_name, y, 5, 350, write_file) set item pcount of periods to ((y as text) & formatDay(5)) set pcount to 1 + pcount set the end of periods to pcount else if doy ≥ 350 and not (periods contains ((y as text) & formatDay(380))) then my log_text("tryNewPeriod(" & file_path & ", " & file_name & ", " & y & ", " & 380 & ", " & 0 & ", " & write_file & ")") tryNewPeriod(file_path, file_name, y, 380, 0, write_file) set item pcount of periods to ((y as text) & formatDay(380)) set pcount to 1 + pcount set the end of periods to pcount end if end if end if end repeat on error msg number num set new_files to 0 my log_text("No new files") end try repeat with p in periods set txt to "period info: " my log_text(txt & p) end repeat close access write_file -- Attempt to add the new period to the list on tryNewPeriod(file_path, file_name, y, ud, ld, write_file) -- Set special cases set yoff to 0 if ud is equal to 20 then set ld to 1 if ud is equal to 380 then -- 360 ≤ doy set ld to 350 if y mod 4 is equal to 0 then set ud to 4 else set ud to 5 end if set yoff to 1 end if -- Test if the necessary file is there set fn to necessaryFile((text items 4 through 5 of file_path) as text, file_name, ud, y + yoff) if ud ≤ 5 and yoff is equal to 0 then set y to y - 1 -- 5/11/15 remove check for fileExists to create plots every day (hopefully) -- if fileExists(fn) then -- writeFile(write_file, ld, ud, y) -- end if writeFile(write_file, ld, ud, y) if fileExists(fn) then set periodoffset to 0 else set periodoffset to 20 end if end tryNewPeriod -- Return the name of the necessary file for the period on necessaryFile(dir, file_name, ud, y) return ("/Users/stephen/" & dir & "/" & (text 1 through 10 of file_name) & y & formatDay(ud) & (text 18 through end of file_name)) end necessaryFile -- Write the file on writeFile(write_file, ld, ud, y) write formatPeriod(ld, ud, y) to write_file end writeFile -- Tests a file's existence on fileExists(posixPath) set ex to ((do shell script "if test -e " & quoted form of posixPath & "; then echo 1; else echo 0; fi") as integer) as boolean if ex then my log_text(posixPath & " exists") else my log_text(posixPath & " doesn't exist") end if return ex end fileExists -- Formats an integer to three digits on formatDay(day_num) set z to "" if day_num < 100 then set z to "0" if day_num < 10 then set z to "00" return z & day_num end formatDay -- Formats the entire period on formatPeriod(ld, ud, y) set yt to y if ld > ud then set yt to y + 1 return & y & " " & formatDay(ld) & " 0000-" & yt & " " & formatDay(ud) & " 0000" end formatPeriod -- ================================================================== -- Use those periods to update the flux file listing and xdr file listing -- ================================================================== try set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:newFluxList.txt") with write permission on error number error_number my log_text(error_number) close access (file "Macintosh HD:Users:stephen:local_chems_files:newFluxList.txt") set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:newFluxList.txt") with write permission end try set eof of write_file to 0 set AppleScript's text item delimiters to " " set counter to 0 try repeat with period in paragraphs of (read file "Macintosh HD:Users:stephen:local_chems_files:newTrange.txt" as {text}) if counter is not equal to 0 then if counter is equal to 2 then set newline to return else if counter is equal to 1 then set newline to "" set counter to counter + 1 end if write newline & temp_dir & "/" & (text item 1 of period) & (text item 2 of period) & "_0000-" & (text item 4 of period) & "_0000_00060Flux_incr.txt" to write_file else set counter to counter + 1 end if end repeat on error msg number num my log_text((num as string) & " - " & msg) end try close access write_file try set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:newxdrList.txt") with write permission on error number error_number my log_text(error_number) close access (file "Macintosh HD:Users:stephen:local_chems_files:newxdrList.txt") set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:newxdrList.txt") with write permission end try set eof of write_file to 0 set AppleScript's text item delimiters to " " set counter to 0 try repeat with period in paragraphs of (read file "Macintosh HD:Users:stephen:local_chems_files:newTrange.txt" as {text}) if counter is not equal to 0 then if counter is equal to 2 then set newline to return else if counter is equal to 1 then set newline to "" set counter to counter + 1 end if set filepre to temp_dir & "/" & (text item 1 of period) & (text item 2 of period) & (text item 3 of period) & (text item 4 of period) & "0000_" write newline & filepre & "00-07PHAhist.xdr" to write_file if newline is equal to "" then set newline to return write newline & filepre & "08-15PHAhist.xdr" to write_file write newline & filepre & "16-23PHAhist.xdr" to write_file write newline & filepre & "24-31PHAhist.xdr" to write_file write newline & filepre & "00-31PHAhist.xdr" to write_file else set counter to counter + 1 end if end repeat on error msg number num my log_text((num as string) & " - " & msg) end try close access write_file -- ================================================================== -- Run the IDL routines to calculate flux and make plots [Incomplete; need to read in periods and tempdir] -- phaflux.pro needs to be able to iterate through the period array and take the custom flux file list -- Note that IDL needs X11 to be running -- ================================================================== -- set msg to "Opening Xquartz" -- do shell script "/usr/bin/open /Applications/Utilities/XQuartz.app" set msg to "IDL starting" my log_text(msg) -- Sometimes, APL will release incomplete data files. In that case, IDL will continue running forever. To counter this, -- the IDL routine is confined to 3 hours; any longer and the script is killed. set msg to "IDL time out" set idl_complete to 0 with timeout of 10800 seconds do shell script "export IDL_DIR=/Applications/exelis/idl; source $IDL_DIR/bin/idl_setup.bash; /usr/local/bin/idl < ~/IDL/Master_Program/IDLCalls.pro >> ~/local_chems_files/20DayAuto_events.log" set idl_complete to 1 set msg to "IDL routine successful" end timeout my log_text(msg) if idl_complete is equal to 1 then -- Refresh the Finder do shell script "killall Finder" delay 12 -- ================================================================== -- Hit the created files with a pstopdf and then delete the .ps files -- ================================================================== do shell script "find " & quoted form of temp_dir & " -name \"*ps\" -exec pstopdf {} \\;" do shell script "find " & quoted form of temp_dir & " -name \"*ps\" -exec rm {} \\;" set msg to "Converted to pdfs; removed all postscripts" my log_text(msg) delay 8 -- ================================================================== -- Put the new files up on the server [cURL] and move the files [flux and output] into the correct folders -- Finish by deleting the temporary folder -- ================================================================== set AppleScript's text item delimiters to ":" set td to (temp_dir as POSIX file) as string set msg to "Searching " & td & " for files ..." set filename to "" my log_text(msg) tell application "Finder" to set file_list to every file of folder td if number of items in file_list > 0 then repeat with i from 1 to number of items in file_list set file_path to ((item i of file_list) as string) set file_name to last text item of file_path set fy to text 1 through 4 of file_name set ch to text 30 through 30 of (file_name as string) set msg to file_name & " ..." my log_text(msg) if ch is equal to "u" then -- flux file do shell script "cd " & quoted form of temp_dir & "; mv -f " & file_name & " ~/cassini_data/20day_FluxCalc/" & fy & "/flux_incr/" set msg to "Moved " & file_name & " into ~/cassini_data/20day_FluxCalc/" & fy & "/flux_incr/" my log_text(msg) else if ch is equal to "M" then -- mpqvt plot do shell script "cd " & quoted form of temp_dir & "; curl --digest -u mimidata:chems4u -T " & file_name & " http://space.umd.edu/Projects/Cassini/chemsdata/chemsPHA/" & fy & "/" set msg to "Uploaded http://space.umd.edu/Projects/Cassini/chemsdata/chemsPHA/" & fy & "/" & file_name set emailContent to emailContent & " " & msg my log_text(msg) do shell script "cd " & quoted form of temp_dir & "; mv -f " & file_name & " ~/cassini_data/MPQvs_t/" & fy & "/" set msg to "Moved " & file_name & " into ~/cassini_data/MPQvs_t/" & fy & "/" my log_text(msg) else if ch is equal to "P" then -- .xdr file do shell script "cd " & quoted form of temp_dir & "; mv -f " & file_name & " ~/Documents/phaplot_xdr/" set msg to "Moved " & file_name & " into ~/Documents/phaplot_xdr/" my log_text(msg) else -- spectrogram set s to text 29 through 29 of (file_name as string) if s is not equal to "3" then do shell script "cd " & quoted form of temp_dir & "; curl --digest -u mimidata:chems4u -T " & file_name & " http://space.umd.edu/Projects/Cassini/chemsdata/chemsscience/" & fy & "/" set msg to "Uploaded http://space.umd.edu/Projects/Cassini/chemsdata/chemsscience/" & fy & "/" & file_name set emailContent to emailContent & " " & msg my log_text(msg) end if do shell script "cd " & quoted form of temp_dir & "; mv -f " & file_name & " ~/cassini_data/20day_FluxCalc/" & fy & "/" set msg to "Moved " & file_name & " into ~/cassini_data/20day_FluxCalc/" & fy & "/" my log_text(msg) end if end repeat -- Set the new "latest period" set period_line to first paragraph of (read file "Macintosh HD:Users:stephen:local_chems_files:latest_period.txt" as {text}) set AppleScript's text item delimiters to " " set period_data to every text item of period_line log period_data set period_number to ((item 1 of period_data) as string) & ((item 2 of period_data) as string) log period_number set new_number to (text 1 through 7 of file_name) log new_number # get the day of year for today set nowdoy to (do shell script "date +%Y%j") if (new_number > period_number) and (new_number < nowdoy) then set period_number to new_number set msg to "Set period number to " & period_number set emailContent to emailContent & " " & msg my log_text(msg) try set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:latest_period.txt") with write permission on error number error_number my log_text(error_number) close access (file "Macintosh HD:Users:stephen:local_chems_files:latest_period.txt") set write_file to open for access (file "Macintosh HD:Users:stephen:local_chems_files:latest_period.txt") with write permission end try set eof of write_file to 0 --write (text 1 through 4 of file_name) & " " & ((text 5 through 7 of file_name as integer) + periodoffset) to write_file -- 7/21/15 sel remove periodoffset write (text 1 through 4 of file_name) & " " & (text 5 through 7 of file_name) to write_file close access write_file end if do shell script "cd /Users/stephen/local_chems_files; curl --digest -u mimidata:chems4u -T latest_period.txt http://space.umd.edu/Projects/Cassini/chemsdata/" set msg to "Uploaded latest_period.txt" my log_text(msg) else set msg to "Didn't find any files" my log_text(msg) end if if new_files is equal to 1 then do shell script "cd /Users/stephen/local_chems_files; curl --digest -u mimidata:chems4u -T newFiles.txt http://space.umd.edu/Projects/Cassini/chemsdata/" set msg to "Uploaded newFiles.txt" my log_text(msg) end if end if -- Send daily email message set dateToday to date string of (current date) do shell script "cat << EOF | /usr/sbin/sendmail -t From: CASSINI Mac Subject: " & emailSubject & " Date: " & dateToday & " To: Douglas C. Hamilton CC: Scott " & emailContent & " EOF" -- Clean up after ourselves set AppleScript's text item delimiters to "" do shell script "rm -r " & quoted form of temp_dir set msg to "Script complete" my log_text(msg)