Software Bisque

Take a virtual tour of the Software Bisque campus Watch Steve Bisque discuss the Paramount mount with S&T's Dennis Di Cicco Read the Paramount MYT Review Read about the Paramount Software Suite

A New Messier Marathon Scripting Example
Richard S. Wright Jr.'s Blog

Messier 20. Collect them all in one night!It is Messier season and a staple of March star parties and new Moon gatherings is the annual Messier Marathon where all 110 Messier objects can be viewed from dusk till dawn. If you can nab all 110 objects in a single night visually, well, why not photographically? You do after all have a world class research grade robotic telescope mount (don't you?!?!). Put that robot to work!

Indeed, this has been done a few times, usually with the help of some automation software. I did a little figuring, and if all 110 objects were imaged for 5 minutes and allowing for some slewing time and an occasional autofocus run, you should be able to grab the entire catalog in one night. So... it CAN be done.... Muhahaha.

Aside: I have to make a note here, that I am a conscientious objector to the idea that M101 and M102 are the same object. After reviewing the historical data, and I am in the camp that thinks that M102 is actually the galaxy NGC 5866. For my own purposes alone (Software Bisque catalogs them both as the same target, as do many other source catalogs), I am treating this galaxy as the intended M102. Sometimes I color outside the lines ;-)

Let's also neglect the fact that this year (2019) New Moon does not favor the Messier marathon all that well. Something either at the beginning or end of the night has to be shot/viewed in brighter twilight. We will have to accept that this year at least. Also, five minutes is not a lot of data, you will want a fast scope (optically fast), and a color camera. I am the first in line to tell you that mono gives you better data almost always, but the fact is we don't have time to change filters, and potentially refocus every time, etc. It could be done, but now we are just making things REALLY HARD on ourselves for no reason. This is a technology/programing demo after all, you're not going to get high resolution publication quality images of all 110 targets in a single night.

Back to business... I have 110 objects to shoot in one night, and I do not want to sit at my computer and click slew and expose every 5 minutes all night long. Naturally, my first thought was to create a "take series" file that contained all 110 objects that TheSky LTI could consume and thus chug through the targets all night. There were two reasons I chose not to go this route. For starters, not everyone is using LTI which can change targets in a series (it is still, after all, a Technical Preview), and second, sorting the objects manually was a daunting task. I found some catalogs and lists online for proposed observing orders, but this changes depending on the exact date and your location. There is SO much discussion online about what order to go in, and then I had a better idea... I am a programmer after all.

One of the most under appreciated features of TheSkyX Professional is that it can be scripted. The scripting language I prefer is the built in JavaScript engine, since this is 100% cross platform. In addition to using the built in JavaScript editor, you can send JavaScript programs to TheSkyX over network sockets and automate the night away. This scripting access is so much more than just a list of commands that correspond to menu items or actions in TheSkyX. With the JavaScript engine you have full access to TheSkyX's rich and deep databases, and the astrometry and astronomical computing engine that drives everything. JavaScript is a real programming language too, it has loops, functions, branching logic, etc. Many professional astronomers use this engine to build all sorts of customized imaging workflows, and in fact many third-party automation programs make extensive use of this behind the scenes.

The Code

The full MessierMarathon.js JavaScript program will be included in a future daily build and can be found in the sample scripts folder. The purpose of this article is really two-fold. Yes, it's a useful tool right out of the box, but it does make some compromises to be aware of if you're not a script ninja. It's also meant to be a JavaScript tutorial of sorts for controlling TheSkyX, with what I hope are some best practices tips and highlights some features of the scripting module that you may not have been aware of.

Let's get started. The first thing we need is a list of targets. Hey, first light bulb... this script is good any night you have a list of targets you want to shoot... ahem, it's not just for a Messier Marathon!

We just make an array in JavaScript at the top of our file containing all the objects we want to acquire. This array is outside any functions, and so it's available to all the code in the script.

var Objects = ["M1",  "M2",  "M3",  "M4",  "M5",  "M6",  "M7",  "M8",  "M9",
              "M10", "M11", "M12", "M13", "M14", "M15", "M16", "M17", "M18", "M19",
              "M20", "M21", "M22", "M23", "M24", "M25", "M26", "M27", "M28", "M29",
              "M30", "M31", "M32", "M33", "M34", "M35", "M36", "M37", "M38", "M39",
              "M40", "M41", "M42", "M43", "M44", "M45", "M46", "M47", "M48", "M49",
              "M50", "M51", "M52", "M53", "M54", "M55", "M56", "M57", "M58", "M59",
              "M60", "M61", "M62", "M63", "M64", "M65", "M66", "M67", "M68", "M69",
              "M70", "M71", "M72", "M73", "M74", "M75", "M76", "M77", "M78", "M79",
              "M80", "M81", "M82", "M83", "M84", "M85", "M86", "M87", "M88", "M89",
              "M90", "M91", "M92", "M93", "M94", "M95", "M96", "M97", "M98", "M99",
              "M100", "M101", "NGC5866", "M103", "M104", "M105", "M106", "M107", "M108", "M109",

This lists every single object separately, but many objects can appear together in the same field of view. I'll leave it as an exercise for the reader to figure out what all will show up in your particular field of view. For example, M31, M32, and M110 are often imaged at the same time. Leave one of the objects in the list to center on that target or replace it with another object that TheSkyX can find that will center the frame how you want it. I've also pruned some targets that I've already acquired data for (in my own copy), as I am working on my own Messier poster and so I'm hoping to clean up my own list of missing objects for this.

Next is a whole group of variables the end user can tweak to change the behavior of the script:

// Globals that you can muck with
var nExposures = 1;                 // Number of exposures per target
var exposureTime = 300.0;       // Number of seconds for each exposure
var exposureDelay = 5.0;         // Delay between exposures
var ditherArcSeconds = 10.0;   // Dither amount per exposure (in arc seconds)
var focusEveryXObjects = 15;  // Refocus every so many targets (just make arbitrarily
                                                 // large to skip)
var minAltitude = 10.0;            // Minimum altitude at which something can be imaged
var waitRetryDelay = 30 * 60; // If we run out of targets, wait this long (in seconds)
                                               // and try clearing the list again
var FileName = "MessierLog";  // Log file as .txt (don't put .txt)

I've generalized a few things because as I've said this is far more useful than just for a Messier marathon. I'm quite sure I'm going to use this myself for a number of other projects. I could just create a list of two or three objects and let it crank all night if I wanted. You can change the number of exposures, add a delay between each one, dither between them, refocus periodically, and set a minimum altitude the object must have before imaging it. There's also a log file name you can set, and a one-time pause parameter in case we run out of targets that are above the horizon. I should explain a few of these in more detail.

For starters, there is no provision for guiding. Five minutes unguided on a Paramount is not uncommon and is usually more than long enough to get data in individual subs above the read noise of your camera and still get plenty of dynamic range captured. Train your PEC... unguided just makes imaging ridiculously easier. If you can't go five minutes, don't waste the night, just take two 2 minute exposures, or one four minute exposure, or heaven help you, four or five one minute exposures (don't forget to factor in image download time if your camera is slow).

I put in a delay before each exposure. Specifically, for a marathon type project, right after a slew to a target, the scope may still be vibrating from the move. Give it a few seconds to dampen unless you have a very short imaging train and you KNOW this isn't necessary. Remember, you only have one single exposure to grab the target, it has to be perfect.

The dither is a bit of a hack I confess. I might steal the dither routine from the unguided dither script for this in an update down the road, but it just moves to the East between exposures. If you opt for a couple of one or two minute exposures (don't have a Paramount maybe<g>), I always recommend dithering so you can reject outliers during stacking.

A best practice with any program or script that takes a long time is to provide the user with feedback all along the way. This function writes periodic updates to both the RunJavaScript output window, and to a text file that is saved in the scripting directory.

function logOutput(logText)

We'll update the user about progress all along the way, and we'll see this both on screen, and in the logged text file. This text file output is somewhat limited due to security concerns that are as they say, "above my pay grade". No special characters (including dots), so we append the .txt for you, and it HAS to go in the scripting folder, nowhere else. Other than that, you can write whatever you want to the file ;-)

Yes, I know that a minimum altitude of 10 degrees is pretty ridiculous under normal circumstances, but for a Marathon/technical demo it might be necessary. Normally, I'd probably set this to more like 40 degrees give or take.

After each object is imaged, it is removed from the list. If the script gets through the entire list and there are still objects to be imaged (but they are too low, or haven't risen yet), then the script will wait for a user specified amount of time (in this case, 30 minutes) and then attempt to start processing the list again. Speaking of which...

Imaging a List of Objects

The list of targets is simply in alphabetical order. How do we determine what order to image these in? The function findNextCandidate() does this for us. It goes through the list and computes each objects current altitude and azimuth values. Objects to the West, which are setting are given precedence over objects to the East, which are rising. On the Western side of the meridian, the object with the lowest altitude is taken first, since the clock is ticking quickly on its availability. Once the Western side of the meridian is cleared, we begin working on objects rising to the East. In this case, we give precedence to the objects that are the highest, giving other objects time to rise higher before we acquire them.

I'm not going to list the entire function here, but it is a good example of how to find an object with TheSkyX, get its current location both in RA/DEC and Alt/Az, and then make decisions based on the objects current location. The function finds the best object in the list given the above criteria, and then removes it from the list. This target is then imaged, and we repeat the process to get and remove the next target from the list. If no object in the list is above the minimum altitude, the function returns "None", and the script will pause for the specified amount of time, just once mind you, and then attempt to reprocess the list again. The script could be modified to compute when the next target will be ready... hmmm... I'll also leave that as an exercise for the reader.

Let's follow the basic flow of the program. We define some functions first, and then loose code just starts executing from the top to the bottom of the script (this was a stumbling block for me when I first learned JavaScript... where is the function "main"?).

var out = "Imaging ";
out += Objects.length;
out += " Targets, starting at ";
out += Date();

Easy enough to see what's going on here. We create our text log file, and write to it and display to the user that we are starting our image run, report how many objects are in the list, and print the value of the Date() function, which also contains the time. It's always a good idea to record the time when things are happening.

Next we connect to the imager and the telescope mount (or verify we are connected, as you probably are already setup and running when you start this script). Setting up the camera demonstrates a few interesting features.

// Make sure we are connected to the imager
try {
    var Imager = ccdsoftCamera;
    Imager.Autoguider = 0;
    Imager.Asynchronous = 0;
    Imager.Autosave = 1;
    Imager.Delay = exposureDelay;
    Imager.ExposureTime = exposureTime;
    Imager.BinX = 1;
    Imager.BinY = 1;
    throw new Error("No connection to the main imager!");

If you want the script to wait on exposures to complete, you need to make sure and set the Asynchronous property to 0. Also, saving your images tends to improve your mood when you wake up the next morning to see how things went, so we set Autosave to 1 as well. Note the try/catch semantics here. If you cannot for some reason connect to the camera, the scripting engine will throw an exception and terminate with a message "Cannot connect to device". Well, which device? I like to use this exception handling mechanism to construct a custom and more specific message about what might be wrong. You don't have to throw an exception either, you could do something different, display the message elsewhere, etc.

Now, the main course... the ProcessList() function loops until there are no more targets above the horizon (or the minimum altitude specified) and returns. Then we look at the object list and see if there are any remaining (if the length of the list is not zero, then we have some stragglers).

// Process the list of targets

// Were they all processed, or were remaining targets just too low?
// If there are still targets in the list, wait... and do, just one more iteration
if(Objects.length != 0) {
       out = There are ";
       out += Objects.length;
       out = " objects remaining, that are too low. Waiting ";
       out += waitRetryDelay;
       out += " seconds. ";
       out += Date();

       // Wait and then take a one second sacrificial image.
       Imager.Delay = waitRetryDelay;
       Imager.ExposureTime = 1;
       Imager.AutoSavePrefix = "WaitFrame"; // Reset to object name on next good image


       Imager.Delay = exposureDelay;        // Reset for resume

       Imager.ExposureTime = exposureTime;

       out = "Attempting to resume at ";
       out += Date();

       ProcessList();                       // Give the list another crack

There is no delay timer in the JavaScript engine (I suppose you could loop and keep checking Date(), but... horrors). Instead, to pause the script I just take a sacrificial image and use the image delay to cause it to wait. This delay value can be hours if you need it to be. I also rename the files prefix to "WaitFrame", so you know this one second exposure can be discarded. The main loop that images each object already prefixes the file name with the name of the target, so hopefully in the morning you'll find a folder full of files with names that start with M1, through M110!

Good luck Messier Warriors! But also... as I've pointed out, this can easily be generalized into a list of galaxies for example to process in your super nova search program, or add a handful of objects you're interested in and just let your system accumulated data for a few nights. Literally... TheSkyX is the limit ;-)







Posted 02-27-2019 12:47 PM by Richard Wright


christianadesouza wrote re: A New Messier Marathon Scripting Example
on 03-15-2019 2:33 AM

nice post


© 2019 Software Bisque, Inc. 862 Brickyard Circle, Golden, CO 80403-8058 USA - phone: +1 303 278 4478 fax: +1 303 278 0045