In the previous post there was much user interaction required to choose all the possible options for setting up a simple imaging session. In this post, I'll show how I use an input text file that eliminates the need to make all the selections at run-time. Here is a sample of a typical input text file:
# # Object Command Arguments: [0] = 'OBJECT' # [1] = Object Name Object m34 # # Guidestar Command Arguments: [0] = 'GUIDESTAR' # [1] = AUTO -or- MANUAL Guide Star Selection # [2] = Exposure Length in sec. (Auto mode only) Guidestar Auto 1.0 # # Exposure Command Arguments: [0] = 'LIGHT' # [1] = Filter (L,R,G,B,HA) # [2] = Binning (Positive Integer) # [3] = Exposure Length (Positive Float) # [4] = No. of Images (Positive Integer) # # Light L 1 10.25 3 # Light B 2 584 1 # Light G 2 30 2 # Light R 2 357 1 # Other Parameters Command Arguments: [0] = 'OTHERS' # [1] = CCD Temperature (ex. '-20.0C' or 'Skip') # [2] = Warm CCD After Imaging? (Y/N) # [3] = Slew to Safe Position After # Imaging? (Y/N) Others -20C Y YA new class called 'cParser' has been created to parse the text file and strip out commands and the parameters associated with each command. The code listing of the 'cParser' class follows:
import sys import string INPUTPATH = "c:\\Imaging_Scripts\\input_files\\" COMMANDS = ('OBJECT','LIGHT','OTHERS','GUIDESTAR') ERROR = True NOERROR = False ##------------------------------------------------------------------------------ ## Class: cParser ##------------------------------------------------------------------------------ class cParser: def __init__(self): self.__cmdArgument = [] def missing(self,filename): try: f = open(INPUTPATH + filename) f.close() return NOERROR except IOError: return ERROR def parseFile(self,filename): if not self.missing(filename): f = open(INPUTPATH + filename, "r") while True: setup = [] text = f.readline() if text == "": f.close() break if text[0] == "#": continue line = text.split(" ") if line[0].upper() not in COMMANDS: print " ERROR: Invalid Command - %s" % line[0].upper() f.close() return None else: for i in range(len(line)): line[i] = line[i].replace('\n','') setup.append(line[i].upper()) self.__cmdArgument.append(setup) return self.__cmdArgument else: print " Error: Input file %s not found" % filename return None ## ## END OF 'cParser' Class ##As shown in the listing, the expected path to the input text files is defined by the constant "INPUTPATH" and indicates I've chosen to create a sub-directory off of the main directory that holds all my Python classes and scripts. The next line defines a constant called 'COMMANDS' that is a tuple of all valid commands that the parser recognizes. The heart of the 'cParser' class is contained in the 'parseFile()' method. This method reads through the input file line-by-line while ignoring any lines that begins with a '#' character. The contents of a line containing a valid command is parsed using the 'split' string function where the splitting character is a space. The command and parameters associated with that command are built into a list which is then appended to the class attribute list '__cmdArgument'. This process repeats for each command that is found until a line is read containing an empty string. The empty string is considered an end-of-file character and terminates the parsing operation. At this point the contents of the class attribute '__cmdArgument' is passed back to the calling routine thus returning a list that contains lists of commands and parameters.
The following code is a listing of the unit test for this module. It simply prompts the user to enter a filename for the input file then parses the file and prints out lists of commands and parameters found in the file.
if __name__ == '__main__': # instantiate the class cmdFile = cParser() # prompt for the filename of the input command file print filename = raw_input("Enter input command filename: ") if not cmdFile.missing(filename): cmds = cmdFile.parseFile(filename) else: print "ERROR: Input command file not found" raise EnvironmentError, 'Halting program' print for cmdsAndParams in cmds: print cmdsAndParams printThe following is a listing of the script that demonstrates how to make use of the input text file.
import cMount_4 import cCamera_4 import cParser_4 filterDictionary = {'R':0,'G':1,'B':2,'L':3,'HA':4} # create an instance of the mount and camera class testMount = cMount_4.cMount() testCamera = cCamera_4.cCamera() cmdFile = cParser_4.cParser() # get imaging location print print "The Sky6 location is %s" % testMount.getImagingLocation() # prompt for the filename of the input command file print filename = raw_input("Enter input command filename: ") if not cmdFile.missing(filename): cmds = cmdFile.parseFile(filename) else: print "ERROR: Input command file not found" raise EnvironmentError, 'Halting program' autoGuide = False warmCCD = False slewSafePosition = False autoGuideStarSelect = False print if len(cmds) > 0: for stringcmd in cmds: if stringcmd[0] == 'OBJECT': obj = stringcmd[1] print "Object: %s" % obj if stringcmd[0] == 'LIGHT': filterName = stringcmd[1] binning = stringcmd[2] exp = float(stringcmd[3]) noImages = int(stringcmd[4]) print "Filter: %s" % filterName print "Binning: %s" % binning print "Exposure: %02.2f" % exp print "No. Images: %d" % noImages if stringcmd[0] == 'OTHERS': temp = stringcmd[1] print "CCD Temp: %s" % temp if stringcmd[2] == 'Y': print "Warm CCD?: Yes" warmCCD = True else: print "Warm CCD?: No" if stringcmd[3] == 'Y': print "Slew to Safe Position?: Yes" slewSafePosition = True else: print "Slew to Safe Position?: No" if stringcmd[0] == 'GUIDESTAR': autoGuide = True if stringcmd[1] == 'AUTO': autoGuideStarSelect = True guideExp = float(stringcmd[2]) print testCamera.setCCDTemp(temp) testCamera.gotoCCDTemp() print if not testMount.findObject(obj): if testMount.checkObjectInWest(): print "%s is west of the meridian" % obj else: print "%s is east of the meridian" % obj print times = testMount.getTimes() print "System Date = %s" % times['Date Now'] print "System Time = %s" % times['Time Now'] if times.has_key('Rise time'): hms = testMount.getAngleToDMS(times['Rise time']) print "%s rise time = %02.0f:%02.0f:%02.0f" % (obj,hms[0],hms[1], hms[2]) if times.has_key('Transit time'): hms = testMount.getAngleToDMS(times['Transit time']) print "%s transit time = %02.0f:%02.0f:%02.0f" % (obj,hms[0],hms[1], hms[2]) if times.has_key('Set time'): hms = testMount.getAngleToDMS(times['Set time']) print "%s set time = %02.0f:%02.0f:%02.0f" % (obj,hms[0],hms[1], hms[2]) else: print "ERROR: Object not found" raise EnvironmentError, 'Halting program' #begin test print if not testMount.slewToObject(obj): # Reset guide star positions for next test testCamera.resetGuideStar() print testCamera.setBinning(int(binning)) testCamera.setFullFrame() fileName = "%s_%s_%sx%s" % (obj,filterName,binning,binning) if autoGuide: if autoGuideStarSelect: if testCamera.autoGuide(True,guideExp): testCamera.stopAutoGuide() else: if testCamera.autoGuide(False,0.0): testCamera.stopAutoGuide() # Make sure autoguider is running if testCamera.checkGuiderRunning(): print for i in range(noImages): testCamera.exposeLight(exp,filterDictionary[filterName.upper()], fileName) # Stop autoguider after all images complete testCamera.stopAutoGuide() else: print "ERROR - Autoguider not running as expected" else: print for i in range(noImages): testCamera.exposeLight(exp,filterDictionary[filterName.upper()], fileName) else: print "ERROR: During slew to object" raise EnvironmentError, 'Halting program' # warm the CCD to ambient if warmCCD: print testCamera.warmCCD() # slew to safe position if slewSafePosition: print testMount.slewToAzAlt(90.0,75.0,"safe") print print "Script Complete!"After importing the 'cCamera', 'cMount', and 'cParser' modules, each class is instantiated. The user is then prompted for the name of the input text file, its existence is verified by the 'missing()' method, and the file is parsed by the 'parseFile()' method. The next block of code strips out the parameters for each command and associates these parameters with local variables to be used throughout the remainder of the script. The next step is to set the CCD temperature and to wait for the CCD temperature to stabilize (unless 'skip' is specified). After finding the object to image in the Sky6 database, the scope is commanded to slew to the object. If the 'GUIDESTAR' command has been specified, autoguiding will then start with either automatic or manual guide star selection. Finally, after tracking errors have converged (if applicable), the images will be taken using the parameters found with the 'LIGHT' command. After all images are collected, the CCD temperature will be warmed back to ambient if the appropriate parameter is set in the 'OTHERS' command. Likewise, if the appropriate parameter is set, the scope will be commanded to slew to a hard-coded safe position (azimuth of 90 degrees, altitude of 75 degrees).
RUNNING THE SCRIPT
Like in the previous post, before executing this script the Sky6 simulator must be manually connected to the telescope control system using the usual procedure. Also, the imaging and guide cameras in MaxIm DL should be first connected to the simulated cameras. The python script can then be executed from the IDE in the normal manner. The source listing for files used by this script can be downloaded from chapter_4.zip. Experiment with the script by running it multiple times by editing and saving the input text file to select different commands and parameters. (Note: Leave off (or comment out using '#' character) the 'GUIDESTAR' command to perform imaging with no autoguiding.)
WHAT'S NEXT?
One deficiency with this script is all status messages only go to the screen. Ideally, it would be good to also echo status of the imaging session to a log file for later analysis. In the next post, I will present a new class that handles data logging with time-stamps on each message. Implementing this capability will also require some changes to the 'cCamera' and 'cMount' class modules.
CLICK HERE FOR NEXT POST IN THIS SERIES
No comments:
Post a Comment