A feature of most serious astronomical CCD cameras is the ability to set and regulate the temperature of the CCD chip via use of thermo-electric cooling (TEC). To this point, the 'cCamera' class has not addressed this feature. The listing show below now includes new constants, a class attribute, and three new methods that add TEC control to the script. (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\\" SETTLE_TIME = 120 # minimum time for stable temp at set point SETTLE_MAX = 480 # maximum time for temp to stabilize ERROR = True NOERROR = False ##------------------------------------------------------------------------------ ## Class: cCamera ##------------------------------------------------------------------------------ class cCamera: def __init__(self): self.__CCDTemp = 'Skip' # CCD Temperature (Skip = don't change temp) 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 setCCDTemp(self,strtemp): if strtemp.upper() == 'SKIP': print "No CCD Cooling Specified" self.__CCDTemp = -99 return NOERROR if strtemp.endswith("C"): try: flttemp = float(strtemp[:-1]) except: print "ERROR: Specified CCD Temperature - Invalid format" return ERROR else: try: flttemp = float(strtemp) except: print "ERROR: Specified CCD Temperature - Invalid format" return ERROR self.__CCDTemp = flttemp return NOERROR def gotoCCDTemp(self): if self.__CCDTemp > -90: # set the CCD temperature set-point self.__CAMERA.TemperatureSetpoint = self.__CCDTemp print "CCD temperature setpoint: %0.2fC" % self.__CCDTemp # make sure the cooler is on, just in case if not self.__CAMERA.CoolerOn: print "Turning CCD cooler on" self.__CAMERA.CoolerOn = True print "Waiting for CCD temperature to stabilize" started = time.time() cnt = 0 # Check CCD temp to stabilize while cnt < SETTLE_TIME and (time.time() - started) < SETTLE_MAX: currentTemp = self.__CAMERA.Temperature if (currentTemp < self.__CCDTemp - 0.5 or currentTemp > self.__CCDTemp + 0.5): cnt = 0 time.sleep(1) cnt += 1 if cnt == SETTLE_TIME and (time.time() - started) < SETTLE_MAX: print "CCD Temperature Stable at %0.2fC" % self.__CAMERA.Temperature try: power = self.__CAMERA.CoolerPower print "CCD Cooler Power: %d%%" % power except: print "CCD cooler power could not be read" return NOERROR return NOERROR else: print "CCD Temperature Did Not Stabilize" return ERROR else: print "Skipping temp stabilization." return NOERROR def warmCCD(self): if self.__CAMERA.CoolerOn: print "Starting to gradually warm CCD temperature to ambient" power = 100 setTemp = self.__CAMERA.Temperature while power > 3: setTemp = setTemp + 5.0 self.__CAMERA.TemperatureSetpoint = setTemp print "CCD temperature setpoint: %0.2fC" % setTemp print "Waiting 2.5 minutes for temperature to rise" time.sleep(150) print "CCD Cooler Temp : %0.2fC" % self.__CAMERA.Temperature try: power = self.__CAMERA.CoolerPower print "CCD Cooler Power: %d%%" % power except: print "CCD cooler power could not be read" power = 0 print "CCD warming complete. Turning CCD cooler off" self.__CAMERA.CoolerOn = False else: print "CCD Cooler is off. CCD warming not necessary." 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 ##The first new method is called 'setCCDTemp' and takes a string (ex. '-15.5C') as its argument. This method first checks to see if the string is 'skip' (meaning don't change the currently set TEC regulated temperature) and if it is, sets the new class attribute '__CCDTemp' to -99. If the string is not 'skip', it strips off the trailing 'C' (if it exists) and then attempts to convert the string to a float. If successful, '__CCDTemp' is set to the float value, and if not successful, the method ends with an invalid format error message and returns an error flag back to the calling routine.
The second new method, 'gotoCCDTemp', sets the MaxIm DL property 'TemperatureSetpoint' to the desired temperature and sets the 'CoolerOn' property to TRUE to activate the TEC. The remainder of the method reads the CCD temperature and looks for it to be stable (setpoint temp plus or minus 0.5C) for a two minute period (SETTLE_TIME) before reading the TEC power and continuing. The method also imposes a maximum of 8 minutes (SETTLE_MAX) for the temperature to become stable before returning an error flag back to the calling routine.
The third method is a simple CCD warming routine that raises the chip's temperature by 5C, waits 150 seconds, then reads the TEC power. If the TEC power is above 3%, the temperature setpoint is raised another 5C and another 2.5 minute wait is initiated. This procedure repeats until the TEC power falls below 3% at which point the 'CoolerOn' property is set to FALSE. (The cooler is also turned off if the method is unable to read the TEC power - as is the case with the MaxIm DL autoguider simulator.) NOTE: This method is probably not really needed since the risk of damaging the CCD by thermal shock from turning off the cooler without warming is minimal or nonexistent.
cCAMERA UNIT TEST
The following listing shows the unit test code for this version of the 'cCamera' class. The script sets the simulator camera up for full-frame mode with 1x1 binning. It then sets a CCD temperature and takes three images then sets a different CCD temperature and takes three more images. The test script then sets the CCD temp to 'Skip' and takes more images to verify that the temperature doesn't change before warming the CCD back to ambient.
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 1x1 testCamera.setBinning(1) # Set CCD Temperature testCamera.setCCDTemp('-20C') # Goto CCD Temperature testCamera.gotoCCDTemp() # Take 3 images for i in range(3): # Expose filter slot 1 (Green) for 10 seconds testCamera.exposeLight(10,1,'m51_G') # Set CCD Temperature testCamera.setCCDTemp('-15C') # Goto CCD Temperature testCamera.gotoCCDTemp() # Take 3 images for i in range(3): # Expose filter slot 1 (Green) for 10 seconds testCamera.exposeLight(10,1,'m51_G') # Set CCD Temperature testCamera.setCCDTemp('skip') # Goto CCD Temperature testCamera.gotoCCDTemp() # Take 3 images for i in range(3): # Expose filter slot 1 (Green) for 10 seconds testCamera.exposeLight(10,1,'m51_G') # Warm the CCD to ambient testCamera.warmCCD()RUNNING THE SCRIPT
Testing this version of the 'cCamera' class follows the same procedure described in Part 1a of this series. The new listing for 'cCamera' can be downloaded from cCamera_1c.zip. Experiment with the script by running it multiple times and by changing the CCD temperature, 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 autoguide tracking during imaging. 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