The script of the 'cCamera' class presented in Part 1a of this series suffered from one major problem - it only provided for exposing and downloading an image but did not provide for saving the image to storage media. The script shown below addresses that deficiency. (Python code added to this version of the script is shown in light cyan text; existing code is shown in yellow text.)
import time import os import win32com.client LIGHT_PATH = r"c:\\astro_images\\" ERROR = True NOERROR = False ##------------------------------------------------------------------------------ ## Class: cCamera ##------------------------------------------------------------------------------ class cCamera: def __init__(self): print "Connecting to MaxIm DL..." self.__CAMERA = win32com.client.Dispatch("MaxIm.CCDCamera") self.__CAMERA.DisableAutoShutdown = True try: self.__CAMERA.LinkEnabled = True except: print "... cannot connect to camera" print "--> Is camera hardware attached?" print "--> Is some other application already using camera hardware?" raise EnvironmentError, 'Halting program' if not self.__CAMERA.LinkEnabled: print "... camera link DID NOT TURN ON; CANNOT CONTINUE" raise EnvironmentError, 'Halting program' def generateFilename(self,path,baseName): # path is the path to where the file will be saved baseName.replace(':', '_') # colons become underscores baseName.replace(' ', '_') # blanks become underscores baseName.replace('\\', '_') # backslash becomes underscore # make sure the base filename has an '_' at the end if not baseName.endswith("_"): baseName = baseName + "_" # add 1 to use next available number seqMax = self.getSequenceNumber(path,baseName) seqNext = seqMax + 1 filename = "%s%s%05d.fit" % (path,baseName,seqNext) return filename def getSequenceNumber(self,path,baseName): # get a list of files in the image directory col = os.listdir(path) # Loop over these filenames and see if any match the basename retValue = 0 for name in col: front = name[0:-9] back = name[-9:] if front == baseName: # baseName match found, now get sequence number for this file seqString = name[-9:-4] # get last 5 chars of name (seq number) try: seqInt = int(seqString) if seqInt > retValue: retValue = seqInt # store greatest sequence number except: pass return retValue def exposeLight(self,length,filterSlot,name): print "Exposing light frame..." self.__CAMERA.Expose(length,1,filterSlot) while not self.__CAMERA.ImageReady: time.sleep(1) print "Light frame exposure and download complete!" # save image filename = self.generateFilename(LIGHT_PATH,name) print "Saving light image -> %s" % filename self.__CAMERA.SaveImage(filename) def setFullFrame(self): self.__CAMERA.SetFullFrame() print "Camera set to full-frame mode" def setBinning(self,binmode): tup = (1,2,3) if binmode in tup: self.__CAMERA.BinX = binmode self.__CAMERA.BinY = binmode print "Camera binning set to %dx%d" % (binmode,binmode) return NOERROR else: print "ERROR: Invalid binning specified" return ERROR ## ## END OF 'cCamera' Class ##As you can see, two new methods have been added to the script. The 'generateFilename' script takes as arguments a path and a base name that usually should include the object name, filter, and binning used during the exposure (ex. m106_R_2x2). The first thing this method does is to take the 'baseName' parameter and strip out any characters that should not be in a filename and replace them with the '_' (underscore) character. It also appends an underscore character to 'baseName'. This method then calls the other new method, 'getSequenceNumber', and provides it with the path and new name arguments. The 'getSequenceNumber' method then uses the 'listdir' method of the 'os' object (hence, the new 'import os' at the top of the listing) to generate a list of all files in the directory specified by 'path'. The method then iterates through the list of directory files looking for one with a matching base name. If one is found, it checks the last five characters before '.fit' and tries to convert these characters into an integer. If successful, it returns the highest integer it can find back to the calling method. The 'generateFilename' method then uses this number to assign the next image with a similar base name the next number in the sequence.
Additional new code has been added to the existing 'exposeLight' method. This new code makes the call to the 'generateFilename' method, prints a message to the screen showing the path and filename of the saved image, then calls the MaxIm DL 'SaveImage' method to actually transfer the image to storage.
cCAMERA UNIT TEST
The following listing shows the unit test code for this version of the 'cCamera' class. The main difference is the requirement for the new 'name' parameter in the 'exposeLight' method.
if __name__ == "__main__": # Create an instance of the cCamera class testCamera = cCamera() # Setup MaxIm DL to take a full frame image testCamera.setFullFrame() # Setup binning for 2x2 if not testCamera.setBinning(2): for i in range(4): # Expose filter slot 0 (Red) for 15 seconds testCamera.exposeLight(15,0,'m51_R_2x2') else: print "Images not taken due to previous error"RUNNING THE SCRIPT
Testing this version of the 'cCamera' class follows the same procedure described in Part 1a of this series. Note: Remember that the path specified by the constant 'LIGHT_PATH' must exist prior to running the script. The new listing for 'cCamera' can be downloaded from cCamera_1b.zip. Experiment with the script by running it multiple times and by changing the binning, filter, exposure length, or file base name in the unit test section to verify the script operates as expected.
WHAT'S NEXT?
In the next post I will continue to expand the 'cCamera' class by introducing more methods and properties that allow for control of the camera's thermo-electric cooler (TEC). I will also expand the unit test listing to verify correct operation of the features added to this class.
CLICK HERE FOR NEXT POST IN THIS SERIES
No comments:
Post a Comment