[historical, see next paragraph] Likewise, a script called ACP-Shutdown.xxx will be run when ACP shuts down before any auto actions you may have enabled in ACP preferences.
The ACP-Shutdown.xxx script isn't what is commonly wanted. Instead, most people are looking for a way to run custom shutdown code at the end of an observing plan. The "standard" actions taken when a #shutdown directive is at the end of an observing plan is often just fine, but sometimes more or different things are needed. There are two ways to do this:
Sub Main()
Telescope.Park
End Sub
This will call the Telescope.Park method, and the auto-home/close logic will take care of your dome. The logic in Telescope.Park tries its very best to assure that your scope is parked before closing the shutter or roof.
By default ACP does not "see" this component and its member functions. To activate it for ACP it must be registered with the Windows OS. On Windows 7 and later, with User Account Control enabled (the default for those versions of Windows), this is a real pain. You need to have a 32-bit command (CMD) window running in administrator mode. It's different on 32- and 64 bit systems, and with UAC off (common on Observatory control computers) you don't need to mess with administrator mode. So:
64 bit, UAC on:
64 bit, UAC off:
32 bit, UAC on:
32 bit, UAC off:
If you see a success popup, it's ready to go. If you see a failure popup, there is a mistake in the code or XML.
Util.Script.xxx
Any method, and all variables defined outside the scope of a property or method implementation, in the running script are accessible this way. For example, the standard AcquireImages.js script contains a variable called targetName, which contains the name of the target currently being acquired.
Util.Script.SUP.property-or-method
All of ACP's standard scripts define a global variable SUP which is the handle to the initialized AcquireSupport library. Thus, using the running-script access syntax described in the previous section, you can access AcquireSupport. It is chock full of useful methods, and its properties can be used to learn a lot about the running script. Have a look at AcquireSupport.wsc with a text editor. It is a Windows Script Component, so using PrimalScript will make looking at it easier.
The simplest way to debug custom user actions is via MsgBox() statements within your code. Be sure to remove them before going into production, though! Otherwise your observing work will stop if one of them are displayed, requiring you to click OK to proceed.
There are also a couple of additional levels of debugging available. User Actions are contained within a supplied template Windows Script Component (WSC), which is "known" to ACP's standard scripts. Once enabled the functions in UserActions.wsc are automatically called by ACP at the appropriate times during ACP's standard script execution cycles.
For general information on WSCs see Reusable Code, where you will find information about the Error Switch and the Debug Switch. Each of these switches is in the XML framework of UserActions.wsc and may be edited with Notepad, etc. Their function is also explained in this section of ACP help. By using the Error Switch and/or Debug Switch, you can cause UserActions.wsc to pop up an error message if any run-time error occurs. By using the Debug Switch, you can cause UserActions to invoke your script debugger on a Stop (VBS) or debugger (JS) statement, or any run time error.
For information on how to install and use Visual Studio 2006/2008/2010 etc. or the Microsoft Office Script Debugger (recommended) see Debugging.
When you are running "live" under ACP (AcquireImages or live observing on the web, same thing) the parameters to TargetStart(), TargetEnd(), AcquireImage() and ImageComplete() will differ. See the comments for each of these functions in template UserActions. YOu can tell if you are running under ACP by testing if you can get the boolean Util.Script.RESUMEPLAN. If it returns a value and doesn't raise an error, then you are running under ACP. With this it is possible to have logic in the UserActions that runs under either ACP or Scheduler, depending.
The SlewStart() function is called with parameters that contain the J2000 equatorial coordinates of the slew destination. You could use these, for example, to perform special safety tests before each slew. Returning False will stop the script with an error.
The AcquireImage() function provides a way to completely replace the normal final/data image acquisition process. When called, any pending autofocus will have been completed and the scope will be pointed at the target (via a pointing update as needed). The implementation of AcquireImage is responsible for everything related to acquiring the image including any needed flip (for image duration), filter selection, focus shifs for same, handling of the guider, and acquisition of the image. The function can return True to indicate that it wants the normal image acquisition process to be done by ACP's logic, False to cause the entier run to be terminated, or "ok" to cause ACP to skip its image acquisition logic and proceed to the next image (within a count, repeat or target loop). In other words, this function handles a single image within the flow of ACP image acquisition process. Consider using a $TAG directive to allow the function to decide whether it should handle the current image or defer to ACP's normal logic. When using from Scheduler, you could put a special string into the Description field of the ImageSet or Observation to trigger this.
The ImageStart() function is called with parameters that allow you to modify the image acquisition. The exposure interval, binning, and sub frame fraction can be altered, resulting in a change from the parameters specified in the plan or script that is doing the image acquisition. Two other parameters which must not be changed specify the filter that is selected and whether or not this is a pointing exposure. You can tell what type of exposure it is by looking at the exposure interval. It is positive for lights, 0 for biases, and negative for darks.
One way to use this feature is to alter the exposure interval to compensate for a filter's transmissivity when doing a pointing exposure. When combined with the Filter Info feature, you could use the selected imaging filter for pointing exposures as well. You could also force pointing exposures to be acquired at binning levels other than the default chosen by ACP.
The ImageEnd() function is special. It is called with a parameter that is the full path/name of the final (closed) image file. With this information, you could apply special post-processing of the image. For example, you could mail the file to a user, or extract science information using a program such as IRAF or the PinPoint engine, etc. Scripts can start shell programs such as IRAF and pass command line parameters to same (see documentation on the WScript.Shell object in the Windows Script 5.6 documentation). Do not rename or move the image file in this action! Use the ImageComplete() function described in the next section.
The ImageComplete() function is called with a parameter that is the full path/name of the final (closed) image file, after all post-acquisition processing has been completed. It may have been plate-solved and/or calibrated. This event allows you to (among other things) change the final file path/name of the just-acquired and processed image.
The TargetStart() function is called with parameters that allow you to examine or modify virtually anything about the upcoming target. You could use this function, for example, to offset from the given coordinates or alter the name. Returning False will stop the script with an error.
The TargetEnd() function is called with parameters that allow you to examine virtually anything about the just-finished target and do some post-acquisition task, then decide whether or not to continue acquisition, and even start a new observing run. Returning False will stop the script with an error.
The Shutdown() function is called when an ACP plan uses the #shutdown directive, or when any script calls the Shutdown() method of the AcquireSupport library. This can be used to override or augment the default observatory shutdown logic. If this method returns True, the default logic is skipped, otherwise the default logic is executed after the logic in the custom action. This is not the same as the ACP Shutdown script, which runs when ACP itself is shut down.
Occasionally, upgrades to ACP will add new user actions. When this happens, you must merge your custom action code into the new template, as the new actions must exist as methods in your UserActions.wsc. The ACP installer always creates a file UserActionsTemplate.wsc which contains the current set of user actions. To migrate, you have two choices. Which one you use depends on your comfort level:
This uses the ImageComplete() function to open then apply some simple processing steps to the FITS image (which has already been saved to disk, right?) and then create a PNG image with the same name in the same folder. This is a great addition to ACP when it's being used by young people for whom you are trying to engage for art or science astronomy. They can download and immediately see a pleasing image of the object they just photographed with your observatory. I encourage you to work with JavaScript as it is the world's most widely used language now, so your skills will transfer. Here's how to add this via the UserActions hooks provided with ACP:
function ImageComplete(ImageFile)
{
var D = new ActiveXObject("MaxIm.Document");
var pfn = ImageFile.replace(/\.fts/, ".png");
D.OpenFile(ImageFile);
D.KernelFilter(5, 20);
D.DDP(0, true, true, 0, 0, 100);
D.RemoveGradient();
D.SaveFile(pfn, 7, true, 0, 0);
D.Close(); // Important!
D = null;
return true;
}
After doing this, every image acquired will result in not only a FITS image but also a nice looking PNG image of the same name in the same folder.