def create(self): """Create :py:mod:`rts2saf.devices.CCD` based on properties stored in configuration. Optionally fetch filter offsets from CCD and/or check if device is present. :return: :py:mod:`rts2saf.devices.CCD` if success else None """ # configuration has been read in, now create objects # create object CCD self.ccd= CCD( debug =self.debug, name =self.rt.cfg['CCD_NAME'], ftws =self.ftws, binning =self.rt.cfg['CCD_BINNING'], window =self.rt.cfg['WINDOW'], pixelSize =float(self.rt.cfg['PIXELSIZE']), baseExposure =float(self.rt.cfg['BASE_EXPOSURE']), logger=self.logger ) if self.check: if not self.ccd.check(proxy=self.proxy): return None if self.fetchOffsets: # fetch the filter offsets if not self.filterOffsets(): return None return self.ccd
def test_deviceClasses(self): logger.info('== {} =='.format(self._testMethodName)) # they are harmless # ToDo: move write from CheckDevices to these classes ft = Filter() self.assertIs(type(ft), Filter, 'no object of type: '.format(type(Filter))) ftw = FilterWheel() self.assertIs(type(ftw), FilterWheel, 'no object of type: '.format(type(FilterWheel))) foc = Focuser() self.assertIs(type(foc), Focuser, 'no object of type: '.format(type(Focuser))) ccd = CCD() self.assertIs(type(ccd), CCD, 'no object of type: '.format(type(CCD)))
class CreateCCD(CreateDevice): """Create device :py:mod:`rts2saf.devices.CCD` :var debug: enable more debug output with --debug and --level :var check: if True check presence of device :var proxy: :py:mod:`rts2.proxy` :var verbose: True, more debug output :var rt: run time configuration, :py:mod:`rts2saf.config.Configuration`, usually read from /usr/local/etc/rts2/rts2saf/rts2saf.cfg :var logger: :py:mod:`rts2saf.log` :var ftws: list of :py:mod:`rts2saf.devices.FilterWheel` :var fetchOffsets: if True call `filterOffsets` """ def __init__( self, ftws=None, fetchOffsets=False, *args, **kw ): super( CreateCCD, self ).__init__( *args, **kw ) self.ftws=ftws self.fetchOffsets=fetchOffsets self.ccd=None def create(self): """Create :py:mod:`rts2saf.devices.CCD` based on properties stored in configuration. Optionally fetch filter offsets from CCD and/or check if device is present. :return: :py:mod:`rts2saf.devices.CCD` if success else None """ # configuration has been read in, now create objects # create object CCD self.ccd= CCD( debug =self.debug, name =self.rt.cfg['CCD_NAME'], ftws =self.ftws, binning =self.rt.cfg['CCD_BINNING'], window =self.rt.cfg['WINDOW'], pixelSize =float(self.rt.cfg['PIXELSIZE']), baseExposure =float(self.rt.cfg['BASE_EXPOSURE']), logger=self.logger ) if self.check: if not self.ccd.check(proxy=self.proxy): return None if self.fetchOffsets: # fetch the filter offsets if not self.filterOffsets(): return None return self.ccd # ToDo # interestingly on can set filter offsets for # filter_offsets_B # filter_offsets_C # but there is no way to specify it via cmd line # or --offsets-file # # filter_offsets_A, etc. see Bootes-2 device andor3 # ftos=self.proxy.getValue(self.ccd.name, 'filter_offsets_B') # print ftos # self.proxy.setValue(self.ccd.name,'filter_offsets_B', '6 7 8') # self.proxy.refresh() # ftos=self.proxy.getValue(self.ccd.name, 'filter_offsets_B') # print ftos # ftos=self.proxy.getValue(self.ccd.name, 'filter_offsets_C') # print ftos # self.proxy.setValue(self.ccd.name,'filter_offsets_C', '16 17 18') # self.proxy.refresh() # ftos=self.proxy.getValue(self.ccd.name, 'filter_offsets_C') # print ftos # sys.exit(1) # Workaround for the above # Device camd provides the following variables # in case multiple filter wheels are present. # This example shows the configuration of Bootes-2: # # CCD andor3 # FLI FTWs: COLWFLT, COLWSLT, COLWGRS # Variables appearing in tab andor3 # variable ftw name filters (read out from device, e.g. COLWGRS) # wheel COLWFLT # wheelA COLWFLT open, R, g, r, i, z, Y, empty8 # wheelB COLWSLT closed, slit1, slit2, slit3, slit4, h.., p.., open # wheelC COLWGRS open, grism1, empty3, empty4, empty5, empty6, empty7, empty8 # # Filters on wheels wheelB, wheelC etc. which are # named open or empty are treated as empty slots. # Only the filter wheel appearing in camd::wheel # is used. # During a focus run filter wheels wheelB, wheelC etc. are # set to a slot named open or empty* def filterOffsets(self, proxy=None): """Fetch for all filter wheels their filter offsets and check if all configured items are present in RTS2 run time environment. :return: True if success else False """ fts=dict() # filters ftos=dict() # filter offsets ccdFtwn=collections.defaultdict(str) # as of 2013-11017 CCD::filter_offsets_X are not filled for i, ftw in enumerate(self.ftws): if i: # FILTB, FILTC, ... ext= chr( 65 + i) # 'A' + i, as it is done in camd.cpp ccdN ='wheel{0}'.format(ext) ftwn=self.proxy.getValue(self.ccd.name, ccdN) ccdFtwn[ftwn] = ccdN fts[ftwn] =self.proxy.getSelection(self.ccd.name, 'FILT{0}'.format(ext)) ftos[ftwn]=self.proxy.getValue(self.ccd.name, 'filter_offsets_{0}'.format(ext)) else: ccdN ='wheel' ftwn=self.proxy.getValue(self.ccd.name, ccdN) ccdFtwn[ftwn] = ccdN fts[ftwn] =self.proxy.getSelection(self.ccd.name, 'filter') ftos[ftwn]=self.proxy.getValue(self.ccd.name, 'filter_offsets') for ftw in self.ftws: # defined in configuration ftIUns= [x.name for x in ftw.filters] # filters from configuration try: ftw.ccdName=ccdFtwn[ftw.name] # these filter wheels names are read back from CCD if self.debug: self.logger.debug('filterOffsets: found filter wheel: {0}, named on CCD: {1}'.format(ftw.name, ftw.ccdName)) except Exception, e: self.logger.error('filterOffsets: {0} {1} configured filter wheel not found, error: {2}'.format(self.ccd.name,ftw.name, e)) return False if len(ftos[ftw.name])==0: self.logger.warn('filterOffsets: {0}, {1} no filter offsets could be read from CCD, but filter wheel/filters are present'.format(self.ccd.name, ftw.name)) if len(fts[ftw.name])==0: self.logger.warn('filterOffsets: {0}, {1} no filters could be read from CCD, but filter wheel/filters are present'.format(self.ccd.name, ftw.name)) else: self.logger.info('filterOffsets: {0}, filter wheel {1} defined filters {2}'.format(self.ccd.name, ftw.name, [x for x in fts[ftw.name]])) self.logger.info('filterOffsets: {0}, filter wheel {1} used filters {2}'.format(self.ccd.name, ftw.name, ftIUns)) ccdOffsets = [ x for x in ftos[ftw.name]] # offsets from CCD ccdFilters = [ x for x in fts[ftw.name]] # filter names from CCD for k, ft in enumerate(ftw.filters): # defined in configuration if ft.name in ccdFilters: for nm in self.rt.cfg['EMPTY_SLOT_NAMES']: # e.g. filter name R must exactly match! p = re.compile(nm) m = p.match(ft.name) if m: ft.OffsetToEmptySlot= 0 if self.debug: self.logger.debug('filterOffsets: {0}, {1} offset set to ZERO'.format(ftw.name, ft.name)) break else: try: ft.OffsetToEmptySlot= ccdOffsets[k] if self.debug: self.logger.debug('filterOffsets: {0}, {1} offset {2} from ccd: {3}'.format(ftw.name, ft.name, ft.OffsetToEmptySlot,self.ccd.name)) except Exception, e: ft.OffsetToEmptySlot= 0 self.logger.warn('filterOffsets: {0}, {1} NO offset from ccd: {2}, setting it to ZERO, error: {3}'.format(ftw.name, ft.name,self.ccd.name, e)) else: self.logger.warn('filterOffsets: {0} filter {1} not found on CCD {2}, ignoring it'.format( ftw.name, ft.name, self.ccd.name))