def calculateMags(self, photFolder, colors): # Names of the sequence/combined files: color = colors[0] PHOTLIST = glob(photFolder + '/' + self.pplSetup['SEQ_FILE_PREFIX'] + '*-' + color + '.cat.cat') PHOTLIST.sort() if len(PHOTLIST) == 0: PHOTLIST = glob(photFolder + '/Combined-' + color + '.cat.cat') # print(PHOTLIST) if len(PHOTLIST) == 0: printWarning("No files for calculate magnitudes in folder %s" % (photFolder)) return False for f in PHOTLIST: inputFiles = [] for c in colors: inputFiles.append(f.replace('-' + color, '-' + c)) printInfo("Calculate real magnitudes to %s" % (f.replace('-' + color, '-*') + '.pm')) pmopt = { 'out': None, 'comp': None, 'color': colors, 'method': self.opt['method'], 'loadCoeffs': self.opt['useStd'], 'useCoeffs': self.opt['useStd'] or self.opt['adhocStd'], 'makeCoeffs': self.opt['makeStd'] or self.opt['adhocStd'], 'saveCoeffs': self.opt['makeStd'], 'showGraphs': self.opt['showGraphs'], 'observer': self.opt['nameCode'], 'files': inputFiles, } phot = Photometry(pmopt, self.pplSetup) phot.process()
def processCommands(self): try: optlist, args = getopt(self.argv[1:], "c:n:msat:wh", [ 'color=', 'name=', 'make-std', 'use-std', 'adhoc-std', 'show-graph', 'method=', 'overwrite', 'help' ]) except GetoptError: printError('Invalid command line options.') return for o, a in optlist: if a[:1] == ':': a = a[1:] elif o == '-c' or o == '--color': color = a.lower() if not color in self.availableBands: printError( 'Invalid color: %s, use on of these: Gi, g, Bi, b, Ri, r, all' % (a)) exit(1) if color == 'all': self.opt['color'] = ['Ri', 'Gi', 'Bi'] else: self.opt['color'] = [a] elif o == '-n' or o == '--name': self.opt['nameCode'] = a.upper() elif o == '-m' or o == '--make-std': self.opt['makeStd'] = True elif o == '-s' or o == '--use-std': self.opt['useStd'] = True elif o == '-a' or o == '--adhoc-std': self.opt['adhocStd'] = True elif o == '--show-graph': self.opt['showGraphs'] = True elif o == '--camera': self.opt['camera'] = a elif o == '--telescope': self.opt['telescope'] = a elif o == '-t' or o == '--method': if not a in self.mgCalcMethods.keys(): printWarning( 'Invalid mg calculation method %s ; use gcx instead.') else: self.opt['method'] = a elif o == '-w' or o == '--overwrite': self.opt['overwrite'] = True elif o == '-h' or o == '--help': self.usage() exit(0) if self.opt['adhocStd'] and (self.opt['makeStd'] or self.opt['useStd']): printWarning( 'Both -a and either -m or -s option cannot be used at once.') exit(0) if len(args) > 0: self.opt['baseFolder'] = args[0] if args[0].endswith('/'): self.opt['baseFolder'] = args[0][:-1] if self.opt['nameCode'] == None: printWarning('No observer code was given. Use \'XYZ\' instead.') self.opt['nameCode'] = 'XYZ' print('Mg calculation method: ' + self.mgCalcMethods[self.opt['method']])
def inspectRefCat(self, baseFolder): colors = '' if 'Bi' in self.opt['color']: colors += 'b' if 'Gi' in self.opt['color'] or 'Vi' in self.opt['color']: colors += 'v' if 'Ri' in self.opt['color']: colors += 'r' refcatFileName = baseFolder.rstrip('/') + '/ref.cat' print('Inspect refcat %s' % (refcatFileName)) if not exists(refcatFileName): printWarning("Reference catalog %s is missing." % (refcatFileName)) return False rc = Table.read(refcatFileName, format='ascii') #print(rc) varCount = 0 compCount = 0 compColorCount = {'bvr': 0, 'bv': 0, 'vr': 0, 'b': 0, 'v': 0, 'r': 0} for r in rc: if r['ROLE'] == 'C': compCount += 1 has_b = r['MAG_B'] != -1.0 and r['MAG_B'] != '-' has_v = r['MAG_V'] != -1.0 and r['MAG_V'] != '-' has_r = r['MAG_R'] != -1.0 and r['MAG_R'] != '-' if has_b: compColorCount['b'] += 1 if has_v: compColorCount['v'] += 1 if has_r: compColorCount['r'] += 1 if has_b and has_v: compColorCount['bv'] += 1 if has_v and has_r: compColorCount['vr'] += 1 if has_b and has_v and has_r: compColorCount['bvr'] += 1 elif r['ROLE'] == 'V': varCount += 1 if varCount == 0: printWarning('No variable star in reference catalog %s' % (refcatFileName)) return False if compCount == 0: printWarning('No comp star in reference catalog %s' % (refcatFileName)) return False if compColorCount[colors] == 0: if colors == 'bvr': if compColorCount['bv'] > 0: self.opt['color'].remove('Ri') self.opt['useStd'] = False printWarning( 'No R comp stars ; downgrade colors to BV and disable std photometry.' ) return True elif compColorCount['vr'] > 0: self.opt['color'].remove('Bi') self.opt['useStd'] = False printWarning( 'No B comp stars ; downgrade colors to VR and disable std photometry.' ) return True elif compColorCount['v'] > 0: self.opt['color'].remove('Bi') self.opt['color'].remove('Ri') self.opt['useStd'] = False printWarning( 'No B and R comp stars ; downgrade colors to V and disable std photometry.' ) return True printWarning( 'No comp stars to achieve %s photometry with reference catalog %s' % (colors.upper(), refcatFileName)) # TODO: more color downgrade rule return False elif compColorCount[colors] < 3: printWarning( 'Only 1 comp star found to achieve %s photometry with reference catalog %s ; only the comp star method is possible' % (colors.upper(), refcatFileName)) self.opt['method'] = 'comp' printWarning('Downgrade method to best comp star.') return True elif compColorCount[colors] < 5 and (self.opt['method'] != 'comp' or self.opt['makeStd'] or self.opt['adhocStd']): printWarning( 'Only %d comp star found to achieve %s photometry with reference catalog %s; do ensemble or ad-hoc standardization carefully' % (compColorCount[colors], colors.upper(), refcatFileName)) return False return True
def photometry(self, seqFolder, photFolder, refcatFileName, color): # Names of the sequence/combined files: SEQLIST = glob(seqFolder + '/' + self.pplSetup['SEQ_FILE_PREFIX'] + '*-' + color + '.fits') SEQLIST.sort() if len(SEQLIST) == 0: SEQLIST = glob(seqFolder + '/Combined-' + color + '.fits') if len(SEQLIST) == 0: printWarning("No files for photometry in folder %s" % (seqFolder)) return False for f in SEQLIST: print("photometry of %s" % (f)) AST_FILE = photFolder + '/' + basename(f).replace( '.fits', '.ast.fits') PMCAT_FILE = photFolder + '/' + basename(f).replace( '.fits', '.cat') printInfo("Make astrometry for %s" % (f)) if not exists(AST_FILE) or self.opt['overwrite']: print("%s/solve-field %s -D %s -N %s %s" % (self.pplSetup['AST_BIN_FOLDER'], self.SOLVE_ARGS, photFolder, AST_FILE, f)) invoke("%s/solve-field %s -D %s -N %s %s" % (self.pplSetup['AST_BIN_FOLDER'], self.SOLVE_ARGS, photFolder, AST_FILE, f)) fsolved = PMCAT_FILE.replace('.cat', '.solved') if not exists(fsolved): printError("Astrometry of %s failed." % (fsolved)) break else: print("astrometry file %s already exists." % (AST_FILE)) printInfo("Make photometry for %s" % (f)) if not exists(PMCAT_FILE) or self.opt['overwrite']: invoke( "sextractor %s -c %s -CATALOG_NAME %s -CATALOG_TYPE ASCII_HEAD" % (AST_FILE, self.SEX_CFG, PMCAT_FILE)) else: print("photometry file %s already exists." % (PMCAT_FILE)) PMCAT_FILE_FLT = PMCAT_FILE + ".cat" printInfo("Filtering result catalog to %s" % (PMCAT_FILE_FLT)) if not exists(PMCAT_FILE_FLT) or self.opt['overwrite']: opt = { 'ref': refcatFileName, 'out': PMCAT_FILE_FLT, 'color': color, 'files': [PMCAT_FILE], } matcher = CatalogMatcher(opt) matcher.process() else: print("filtered photometry file %s already exists." % (PMCAT_FILE_FLT)) return True
def loadVsxCatalogData(self, objectName, ra = None, dec = None, fov = defFov, auidOnly = True): ''' &coords The central J2000 RA/DEC coordinates for a radius search, expressed sexagesimally (by default), or in decimal degrees if format is set to d. Northern hemisphere coordinates must have the plus () sign URL-encoded as %2B. Space characters between all other figures must be replaced with the URL whitespace character (). The order argument (which see) must also be included in the query string with its value set to 9 in order to prompt VSX to display distances from the central coordinates in the results listing. Default is empty string (no radius search). &ident Object identification for name searches. Space characters must be replaced with the URL whitespace character (+). Other special characters may also need to be URL-encoded. Default is empty string (no name search). &format Explicit specification for format of coords. For sexagesimal, this value should be s. For decimal degrees, this value should be d. Default is s (sexagesimal). &geom The geometry for central coordinate-based searches. For radius searches, this value should be r. For box searches, this value should be b. Default is r (radius search). &size For box searches (geom=b), the width of the box. For radius searches (geom=r), the radius of the circle. Expressed in the units specified by unit (see next). Default is 10.0. &unit The unit of measurement used for the value given in size (see above). For arc degrees, this value should be 1. For arc minutes, this value should be 2. For arc seconds, this value should be 3. Default is 2 (arc minutes). ''' if objectName != None: # https://www.aavso.org/vsx/index.php?view=results.csv&ident=R+Car vsxUrl = "https://www.aavso.org/vsx/index.php?view=api.object&format=json&ident=%s" % (urllib.parse.quote_plus(objectName)) ids = "star=%s" % (urllib.parse.quote_plus(objectName)) f = request.urlopen(vsxUrl) respJson = f.read().decode('UTF-8') resp = json.loads(respJson) sra = deg2hexa(float(resp['VSXObject']['RA2000']) / 15.0) sdec = deg2hexa(float(resp['VSXObject']['Declination2000'])) else: sra = deg2hexa(ra / 15.0) sdec = deg2hexa(dec) if not sdec.startswith('-') and not sdec.startswith('+'): sdec = "+" + sdec coords = sra + sdec vsxUrl = "https://www.aavso.org/vsx/index.php?view=query.votable&format=d&coords=%s&size=%d&unit=2&geom=b" % (coords, fov) # https://www.aavso.org/vsx/index.php?view=query.votable&coords=19:54:17+32:13:08&format=d&size=60&unit=2 f = request.urlopen(vsxUrl) respVOTable = f.read().decode('UTF-8') votable = xmltodict.parse(respVOTable) tableData = votable['VOTABLE']['RESOURCE']['TABLE']['DATA']['TABLEDATA'] if tableData == None: printWarning('No VSX data for this field') return trs = tableData['TR'] nrUnknown = 1 if not isinstance(trs, list): trs = [trs] for tr in trs: # [None, 'PS1-3PI J185203.12+325154.5', 'Lyr', '283.01304000,32.86516000', 'RRAB', '16.810', 'r', '0.400', 'r', '57000.85600', None, '0.839122', None, None, None] auid = tr['TD'][0] if auid == None: if auidOnly: continue auid = '999-VAR-%03d' % (nrUnknown) nrUnknown = nrUnknown + 1 tr['TD'][0] = auid role = 'V' raDeg, decDeg = tr['TD'][3].split(',') ra = deg2hexa(float(raDeg) / 15.0) dec = deg2hexa(float(decDeg)) if not dec.startswith('-'): dec = "+" + dec decDeg = "+" + decDeg label = tr['TD'][1].replace(' ', '_') self.dismissSameAUID(auid) self.writeRecord(auid, role, ra, raDeg, dec, decDeg, '-', '-', '-', '-', '-', '-', label) self.xmatchTable.add_row([auid, raDeg, decDeg, label]) nrUnknown = 1 count = 0 for tr in trs: auid = tr['TD'][0] if auid == None: if auidOnly: continue auid = '999-VAR-%03d' % (nrUnknown) nrUnknown = nrUnknown + 1 role = 'V' raDeg, decDeg = tr['TD'][3].split(',') ra = deg2hexa(float(raDeg) / 15.0) dec = deg2hexa(float(decDeg)) label = tr['TD'][1] constell = tr['TD'][2] vartype = tr['TD'][4] if vartype == None: vartype = "-" period = tr['TD'][11] maxmg = tr['TD'][5] if tr['TD'][6] != None: maxmg += tr['TD'][6] minmg = tr['TD'][7] if tr['TD'][8] != None: minmg += tr['TD'][8] s = "#" + label.ljust(29) + auid.ljust(14) + ra.ljust(15) + dec.ljust(14) + constell.ljust(4) + vartype.ljust(11) + period.ljust(11) + maxmg + " - " + minmg self.cache.append(s) count = count + 1 print("%d variable stars were found in VSX database" % (count))
def processCommands(self): try: optlist, args = getopt(self.argv[1:], "c:n:fm:t:we:h", [ 'color=', 'count-combine=', 'flat', 'master-flat=', 'image-time=', 'overwrite', 'on-error=', 'help', 'calib-folder=', 'debug' ]) except GetoptError: printError('Invalid command line options.') return for o, a in optlist: if a[:1] == ':': a = a[1:] elif o == '-c' or o == '--color': color = a.lower() if not color in self.availableBands: printError( 'Invalid color: %s, use on of these: Gi, g, Bi, b, Ri, r, all' % (a)) exit(1) if color == 'all': self.opt['color'] = ['Gi', 'Ri', 'Bi'] else: self.opt['color'] = [a] elif o == '-f' or o == '--flat': self.opt['flatOnly'] = True elif o == '-m' or o == '--master-flat': self.opt['useMasterFlat'] = True self.opt['masterFlat'] = a elif o == '-n' or o == '--count-combine': self.opt['countCombine'] = int(a) elif o == '-t' or o == '--image-time': if a in ['LT', 'UT']: self.opt['imageTime'] = a else: printWarning( "Bad image time zone value: %s, using default %s instead." % (a, self.opt['imageTime'])) elif o == '-e' or o == '--on-error': if not a in ['noop', 'skip', 'stop']: printWarning( "Bad on-error instruction; available values are: noop, stop, skip." ) else: self.opt['onError'] = a elif o == '--calib-folder': if not isdir(a): printError( "%s is not a folder. Calibration folder option is ignored." % (a)) else: self.opt['calibFolder'] = a elif o == '-w' or o == '--overwrite': self.opt['overwrite'] = True elif o == '--debug': self.opt['debug'] = True elif o == '-h' or o == '--help': self.usage() exit(0) if len(args) > 0: self.opt['baseFolder'] = args[0] if args[0].endswith('/'): self.opt['baseFolder'] = args[0][:-1] if not isdir(self.opt['baseFolder']): printError("Base folder %s not exists or not a directory." % (self.opt['baseFolder'])) exit(1) else: print("base folder: %s" % (self.opt['baseFolder'])) print("colors: " + ' '.join(self.opt['color'])) print("overwrite: " + str(self.opt['overwrite'])) print("count combine: " + str(self.opt['countCombine'])) print("image timezone: " + str(self.opt['imageTime']))