class cSBIGtheskyX: def __init__(self,night): # CCD control through the SkyX # Define attributes # hard code things since CAMAL is simple. can put into config file later self.dataPath = "C:/camal/data/" + night + "/" self.finaldataPath = "C:/camal/final/" + night + "/" self.night = night self.name = 'SBIG' self.program = 'theskyX' self.filters = { '823' : 'Blue', '860' : 'Clear', '780' : 'Lunar', '0' : 'Red' } self.filterindices = { 'Blue' : 2, 'Clear' : 3, 'Lunar' : 4, 'Red' : 0 } self.frametype = { 'LIGHT' : 1, 'BIAS' : 2, 'DARK' : 3, 'FLAT' : 4 } self.xbin = 2 self.ybin = 2 self.asynchronous = False # set up logger logger_name = self.name log_file = 'logs/' + night + '/' + self.name # setting up imager logger fmt = "%(asctime)s [%(filename)s:%(lineno)s - %(funcName)s()] %(levelname)s: %(message)s" datefmt = "%Y-%m-%dT%H:%M:%S" self.logger = logging.getLogger(logger_name) formatter = logging.Formatter(fmt,datefmt=datefmt) formatter.converter = time.gmtime fileHandler = logging.FileHandler(log_file, mode='a') fileHandler.setFormatter(formatter) console = logging.StreamHandler() console.setFormatter(formatter) console.setLevel(logging.INFO) self.logger.setLevel(logging.DEBUG) self.logger.addHandler(fileHandler) self.logger.addHandler(console) def connect(self, cooler=True): # Connect to an instance of Maxim's camera control. # (This launches the app if needed) self.logger.info('Connecting to theSkyX') thesky = Dispatch("theSkyX.Application") #should already be open bc of launching telescope.. self.CAMERA = Dispatch("CCDSoft2XAdaptor.CCDSoft5Camera") self.IMAGE = Dispatch("CCDSoft2XAdaptor.ccdsoft5Image") # Connect to the camera self.logger.info('Connecting to camera') try: self.CAMERA.Connect() self.nfailed = 0 except: self.recover() # Set binning self.CAMERA.BinX = self.xbin self.CAMERA.BinY = self.ybin self.logger.info("Camera binning set to %dx%d" % (self.xbin,self.ybin)) # Asynchronous? aka return before command complete self.CAMERA.Asynchronous = self.asynchronous # Set to full frame self.setFrame('full') # Turn AutoSave off self.CAMERA.AutoSaveOn = False # Cool CDD if cooler == True: self.coolCCD() def Expose(self,exptime,exptype,filterlam): filt = self.filterindices[self.filters[str(filterlam)]] if exptype == 1 or exptype == 4: # Science or flat image self.logger.info("Exposing light frame...") self.CAMERA.FilterIndexZeroBased = filt self.CAMERA.ExposureTime = exptime self.CAMERA.Frame = exptype # Take Image self.CAMERA.TakeImage() # Attach this image to IMAGE object for saving self.IMAGE.AttachToActive() while not self.CAMERA.IsExposureComplete: time.sleep(1) self.logger.info("Light frame exposure and download complete!") if exptype == 2 or exptype == 3: # Bias or dark image, shutter closed self.logger.info("Exposing Dark frame...") self.CAMERA.ExposureTime = exptime self.CAMERA.Frame = exptype self.CAMERA.TakeImage() # Attach this image to IMAGE object for saving self.IMAGE.AttachToActive() while not self.CAMERA.IsExposureComplete: time.sleep(1) self.logger.info("Dark frame exposure and download complete!") def saveImage(self,filename): try: self.IMAGE.Path = filename self.IMAGE.Save() self.logger.info("saved file to " + filename) except: self.logger.error("Cannot save file") raise EnvironmentError, 'Halting program' def setFrame(self,opt,l=0,b=0,r=0,t=0): if opt == 'full': self.CAMERA.Subframe = 0 self.logger.info("Camera set to full-frame mode") elif opt == 'sub': "Left 0 , Bottom 0 , Top, Right" " Must give unbinned pixel coordinates " self.CAMERA.SubframeLeft = l self.CAMERA.SubframeRight = r self.CAMERA.SubframeBottom = b self.CAMERA.SubframeTop = t self.CAMERA.Subframe = 1 self.logger.info("Camera set to subframe. Note: Inputs must ignore binning.") else: self.logger.error("Set opt to either 'full' or 'sub'. If sub, give coordinates") def coolCCD(self): # Determine SetPoint Temp if cooler not on, make divisible by 5 if self.CAMERA.RegulateTemperature == 0: ambTemp = self.CAMERA.Temperature if ambTemp < 15: settemp = -5 elif (ambTemp >= 15) & (ambTemp < 20): settemp = 0 elif (ambTemp >= 20) & (ambTemp < 25): settemp = 5 else: settemp = round(ambTemp-20) - round(ambTemp)%5 else: # make a set temp if cooler already on ambTemp = round(self.CAMERA.Temperature) if self.CAMERA.ThermalElectricCoolerPower > 30: # sign: +/- : Temperature larger/smaller than set point sign = (self.CAMERA.Temperature - self.CAMERA.TemperatureSetPoint)/abs(self.CAMERA.Temperature - self.CAMERA.TemperatureSetPoint) settemp = round(self.CAMERA.TemperatureSetPoint + sign * 5) else: settemp = round(self.CAMERA.TemperatureSetPoint) # Set Temp and turn on cooling self.CAMERA.TemperatureSetPoint = settemp self.CAMERA.RegulateTemperature = 1 # Turn on cooling time.sleep(5) self.logger.info("Cooling camera to " + str(settemp) + " C , Amb Temp= " + str(ambTemp)) self.logger.info("Waiting for Camera Temperature to match Set Temp to within 0.4 Celcius" ) time0 = time.time() it = 0 while (abs(self.CAMERA.Temperature - self.CAMERA.TemperatureSetPoint) > 0.4) or (self.CAMERA.ThermalElectricCoolerPower > 50): time.sleep(10) # sleep until temp and settemp match if time.time() - time0 > 600.0: # If Temperature still too high (low)..raise (lower) settemp sign = (self.CAMERA.Temperature - self.CAMERA.TemperatureSetPoint)/abs(self.CAMERA.Temperature - self.CAMERA.TemperatureSetPoint) settemp = settemp + sign * 5 self.logger.info("Cooling Took Too Long, changing settemp to " +str(settemp)) self.CAMERA.TemperatureSetPoint = settemp time0 = time.time() self.logger.warning('Camera failed to Cool! Time: ' + str(it)) it += 1 if it > 3: self.logger.error('Camera failed to cool!') mail.send("SBIG Camera failed to Cool","please do something") sys.exit() def shutDown(self): if self.CAMERA.RegulateTemperature == 1: # Warm up cooler self.CAMERA.TemperatureSetPoint = self.CAMERA.Temperature + 10.0 self.logger.info('Warming Up CCD to Amb. Temp.') time.sleep(25) # Turn Cooler Off self.CAMERA.RegulateTemperature = 0 # Quit from camera, disconnect self.logger.info('Disconnecting and Quitting CAMERA') self.CAMERA.Disconnect() def restartthesky(self): self.logger.info('Killing maxim') subprocess.call(['Taskkill','/IM','theSkyX.exe','/F']) time.sleep(15) self.logger.info('Reconnecting') self.connect() def recover(self): self.nfailed = self.nfailed + 1 try: self.shutDown() except: pass if self.nfailed == 1: # attempt to reconnect self.logger.warning('Camera failed to connect; retrying') self.connect() elif self.nfailed == 2: # then restart maxim self.logger.warning('Camera failed to connect; restarting maxim') self.restartthesky() elif self.nfailed == 3: self.logger.error('Camera failed to connect!') mail.send("SBIG Camera failed to connect","please do something",level="serious") sys.exit()
if filterName not in self.getFilters(): raise InvalidFilterPositionException("Invalid filter %s." % filter) self.filterChange(filter, self.getFilter()) self._ccdsoft.FilterIndexZeroBased = self._getFilterPosition(filter) def getFilter(self): return self._getFilterName(self._ccdsoft.FilterIndexZeroBased) class InvalidExposureTime(ChimeraException): pass if __name__ == '__main__': ccdsoft = Dispatch("CCDSoft.Camera") ccdsoft.Connect() ccdsoft.Asynchronous = 0 ccdsoft.ImageReduction = 0 # Disable any possible data reduction ccdsoft.ExposureTime = 1.0 ccdsoft.Frame = 1 ccdsoft.TakeImage() while not bool(ccdsoft.IsExposureComplete): time.sleep(.1) print 'Done taking image.' img = Dispatch("CCDSoft.Image") img.AttachToActive() pix = np.transpose(np.array(img.DataArray))