From 0e193ea4866f8924d7dd00a0f89afe539acfddf7 Mon Sep 17 00:00:00 2001 From: William Schoenell Date: Wed, 12 Jun 2024 20:18:13 -0700 Subject: [PATCH 1/6] moved catalogs to pverify. they are not used in the core. --- src/chimera/util/catalogs/landolt.py | 65 ------------ src/chimera/util/catalogs/ppm.py | 44 -------- src/chimera/util/catalogs/ucac2.py | 46 --------- src/chimera/util/tests/test_catalog.py | 36 ------- src/chimera/util/tests/test_landolt.py | 29 ------ src/chimera/util/tests/test_vizquery.py | 19 ---- src/chimera/util/vizquery.py | 131 ------------------------ 7 files changed, 370 deletions(-) delete mode 100644 src/chimera/util/catalogs/landolt.py delete mode 100644 src/chimera/util/catalogs/ppm.py delete mode 100644 src/chimera/util/catalogs/ucac2.py delete mode 100644 src/chimera/util/tests/test_catalog.py delete mode 100644 src/chimera/util/tests/test_landolt.py delete mode 100644 src/chimera/util/tests/test_vizquery.py delete mode 100644 src/chimera/util/vizquery.py diff --git a/src/chimera/util/catalogs/landolt.py b/src/chimera/util/catalogs/landolt.py deleted file mode 100644 index a1552a43..00000000 --- a/src/chimera/util/catalogs/landolt.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -*- coding: iso-8859-1 -*- - -#import os - -from chimera.util.vizquery import VizQuery -from chimera.util.position import Position -from chimera.util.coord import Coord -from chimera.util.catalog import Catalog - - -class Landolt (VizQuery, Catalog): - - """ - class Landolt is used to query the landolt II/183A catalog in vizier - it inherits from VizQuery and has all its methods - """ - # Landolt inherited VizQuery, its init should be the same as the - # parent class. to do that I call VizQuery.__init__(self) - - def __init__(self): - VizQuery.__init__(self) - - def getName(self): - return "Landolt" - - def find(self, near=None, limit=9999, **conditions): - - self.useCat("II/183A/") - - if conditions.get("closest", False): - limit = 1 - self.useColumns( - "*POS_EQ_RA_MAIN,*POS_EQ_DEC_MAIN,*ID_MAIN,Vmag,_r", sortBy="_r") - else: - self.useColumns( - "*POS_EQ_RA_MAIN,*POS_EQ_DEC_MAIN,*ID_MAIN,Vmag,_r", sortBy="*POS_EQ_RA_MAIN") - - if near: - self.useTarget(near, radius=conditions.get("radius", 45)) - - x = super(Landolt, self).find(limit) - - for i in x: - RA = i.pop("*POS_EQ_RA_MAIN") - i["RA"] = Coord.fromHMS(str(RA)) - DEC = i.pop("*POS_EQ_DEC_MAIN") - i["DEC"] = Coord.fromDMS(str(DEC)) - ID = i.pop("*ID_MAIN") - i["ID"] = str(ID) - V = i.pop("Vmag") - i["V"] = str(V) - i.pop("_r") - - return x - -if __name__ == '__main__': - - lst = "12:00:00" - lat = "00:00:00" - coords = Position.fromRaDec(lst, lat) - test = Landolt() - test.useTarget(coords, radius=45) - obj = test.find(limit=1) - print obj diff --git a/src/chimera/util/catalogs/ppm.py b/src/chimera/util/catalogs/ppm.py deleted file mode 100644 index 3926501d..00000000 --- a/src/chimera/util/catalogs/ppm.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# -*- coding: iso-8859-1 -*- - -import os - -from chimera.util.catalog import Catalog -from chimera.util.scat import SCatWrapper - - -class PPM (Catalog): - - def __init__(self): - Catalog.__init__(self) - - self.scat = SCatWrapper() - - def getName(self): - return "PPM" - - def getMetadata(self): - return [("PPM_NUM", "arbitrary", "PPM number"), - ("RA", "h:m:s", "Right Ascension (J2000)"), - ("DEC", "d:m:s", "Declination (J2000)"), - ("MAG_J", "mag", "J magnitude (1.2 um) from 2MASS"), - ("SpTyp", "arbitrary", "Spectral type"), - ("R", "arcsec", "Distance from the target")] - - def getMagnitudeBands(self): - return ["V"] - - def find(self, near, limit=None, **conditions): - - scat_options = {"catalog": "ppm", - "near": near or "00:00:00 +00:00:00", - "limit": limit or 100, - "bands": self.getMagnitudeBands(), - "conditions": conditions, - "metadata": self.getMetadata(), - "env": os.environ.update({"PPM_PATH": "/home/henrique/catalogs/"})} - - # OK, run it! - data = self.scat.run(scat_options) - - return data diff --git a/src/chimera/util/catalogs/ucac2.py b/src/chimera/util/catalogs/ucac2.py deleted file mode 100644 index 3592b789..00000000 --- a/src/chimera/util/catalogs/ucac2.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# -*- coding: iso-8859-1 -*- - -import os - -from chimera.util.catalog import Catalog -from chimera.util.scat import SCatWrapper - - -class UCAC2 (Catalog): - - def __init__(self): - Catalog.__init__(self) - - self.scat = SCatWrapper() - - def getName(self): - return "UCAC2" - - def getMetadata(self): - return [("UCAC2_NUM", "arbitrary", "UCAC2 number"), - ("RA", "h:m:s", "Right Ascension (J2000)"), - ("DEC", "d:m:s", "Declination (J2000)"), - ("MAG_J", "mag", "J magnitude (1.2 um) from 2MASS"), - ("MAG_H", "mag", "H magnitude (1.6 um) from 2MASS"), - ("MAG_K", "mag", "Ks magnitude (2.2 um) from 2MASS"), - ("MAG_UCAC", "mag", "Internal UCAC magnitude (red bandpass)"), - ("R", "arcsec", "Distance from the target")] - - def getMagnitudeBands(self): - return ["J", "H", "K", "UCAC"] - - def find(self, near, limit=None, **conditions): - - scat_options = {"catalog": "ucac2", - "near": near or "00:00:00 +00:00:00", - "limit": limit or 100, - "bands": self.getMagnitudeBands(), - "conditions": conditions, - "metadata": self.getMetadata(), - "env": os.environ.update({"UCAC2_PATH": "/home/henrique/catalogs/ucac2/"})} - - # OK, run it! - data = self.scat.run(scat_options) - - return data diff --git a/src/chimera/util/tests/test_catalog.py b/src/chimera/util/tests/test_catalog.py deleted file mode 100644 index d7551dac..00000000 --- a/src/chimera/util/tests/test_catalog.py +++ /dev/null @@ -1,36 +0,0 @@ - -# from chimera.util.catalogs.ucac2 import UCAC2 -# from chimera.util.catalogs.ppm import PPM -# from chimera.util.catalogs.landolt import Landolt - -from nose import SkipTest - - -class TestCatalog (object): - - def test_closest (self): - raise SkipTest() - - # for catalog in [UCAC2, PPM, Landolt]: - for catalog in [Landolt]: - - cat = catalog() - data = cat.find(near="15:18:33.7 +02:04:58", closest=True) - - #assert data.nrows == 1 - - - def test_box (self): - - raise SkipTest() - print - - #for catalog in [UCAC2, PPM, Landolt]: - for catalog in [Landolt]: - - cat = catalog() - data = cat.find(near="15:18:33.7 +02:04:58", box=3600) - - #assert data.nrows > 0 - #print data.nrows - diff --git a/src/chimera/util/tests/test_landolt.py b/src/chimera/util/tests/test_landolt.py deleted file mode 100644 index 8b6a3602..00000000 --- a/src/chimera/util/tests/test_landolt.py +++ /dev/null @@ -1,29 +0,0 @@ - -from nose.tools import assert_raises -from chimera.util.catalogs.landolt import Landolt -from chimera.util.position import Position - -class TestLandolt (object): - - def test_find (self): - - landolt = Landolt() - landolt.useTarget(Position.fromRaDec("14:00:00","-22:00:00"),radius=45) - landolt.constrainColumns({"Vmag":"<10"}) - - data = landolt.find(limit=5) - - for obj in data: - for k,v in obj.items(): - assert k - assert v - print k, v - - def test_find_none (self): - - landolt = Landolt() - #landolt.useTarget(Position.fromRaDec("14:00:00","-22:00:00"),radius=45) - landolt.constrainColumns({"Vmag":"<10"}) - - assert_raises(AssertionError, landolt.find, limit=5) - diff --git a/src/chimera/util/tests/test_vizquery.py b/src/chimera/util/tests/test_vizquery.py deleted file mode 100644 index 74c7d525..00000000 --- a/src/chimera/util/tests/test_vizquery.py +++ /dev/null @@ -1,19 +0,0 @@ - -from chimera.util.vizquery import VizQuery -from chimera.util.position import Position - -class TestVizQuery (object): - - def test_find (self): - x = VizQuery() - x.useCat("II/183A/") - x.useColumns("*POS_EQ_RA_MAIN,*POS_EQ_DEC_MAIN,*ID_MAIN,Vmag,_r", - sortBy="*POS_EQ_RA_MAIN") - x.useTarget(Position.fromRaDec("14:00:00","-22:00:00"),radius=45) - - data = x.find(limit=5) - - for obj in data: - for k,v in obj.items(): - print k, v - print diff --git a/src/chimera/util/vizquery.py b/src/chimera/util/vizquery.py deleted file mode 100644 index 64e03282..00000000 --- a/src/chimera/util/vizquery.py +++ /dev/null @@ -1,131 +0,0 @@ -from chimera.util.votable import VOTable - -from httplib import HTTPConnection -import tempfile -import os -import urllib - - -class VizQuery(object): - - """ - Queries A catalog in Vizier - within a given radius or box of the zenith - """ - - def __init__(self): - self.args = {} - self.args["-mime"] = "xml" - self.columns = None - - def useCat(self, catName): - """ - @param catName: the catalog's name in Vizier - @type catName: str - - Simply sets the catalog's name - """ - - self.args["-source"] = catName - - def useColumns(self, columns, sortBy, reverse=False): - """ - @param columns: list of catalog's columns to use - @type columns: list - - @param sortBy: define which column to sort by - @type sortBy: str - - @param reverse: decide to reverse sort @type reverse: bool - - Define which columns will be fetched and which column will be used - for sorting. - """ - - self.columns = columns.split(",") - - self.args["-out"] = columns - - if reverse: - self.args["-sort"] = "-" + sortBy - else: - self.args["-sort"] = sortBy - - def sortBy(self, column): - """ - One sets here which column to sort by - @param column: name of column to sort by - @type column: str - """ - - def constrainColumns(self, columns): - """ - Use this to add constraints to any of the columns - @param columns: list of dictionaries {COLUMN:condition} - @type columns: list - """ - self.args.update(columns) - - def useTarget(self, center, radius=None, box=None): - """ - @param center: center of search in catalog - @type center: L{Position} - - @param radius: radius of search - @type radius: float - - @param box: box size, if you want a square use an integer - if you want a rectangle use a tuple (ww,hh) - @type box: int | tuple - """ - - self.args["-c"] = str(center) - self.args["-c.eq"] = "J2000" - - if radius: - self.args["-c.rd"] = radius - elif box: - try: - self.args["-c.bd"] = "=%fx%f" % radius - except: - self.args["-c.bd"] = radius - else: - raise TypeError("You must specify either radius or box size") - - def find(self, limit=9999): - """ - @param limit: Number of stars to return from Vizier - @type limit: int - - """ - - assert "-c.rd" in self.args or "-c.bd" in self.args, "No target selected, use useTarget method first." - - self.args["-out.max"] = limit - - results = tempfile.NamedTemporaryFile(mode='w+', - prefix="chimera.vizquery", - dir=tempfile.gettempdir()) - - # query the catalog in Vizier's database - conn = HTTPConnection("webviz.u-strasbg.fr") - - s = urllib.urlencode(self.args) - - conn.request("POST", "/viz-bin/votable", s) - resp = conn.getresponse() - ret = resp.read() - - f = open(results.name, "w") - f.write(ret) - f.close() - - obj = [] - - votable = VOTable(results.name) - - for linha in votable.getDataRows(): - v = [c.getContent() for c in linha.getNodeList()] - obj.append(dict(zip(self.columns, v))) - - return obj From 32aecef05327104deb9908e5a5be4d1614670fb3 Mon Sep 17 00:00:00 2001 From: William Schoenell Date: Wed, 12 Jun 2024 20:19:44 -0700 Subject: [PATCH 2/6] delete unused utils --- src/chimera/util/dumper.py | 229 ------------------------------------- src/chimera/util/scat.py | 178 ---------------------------- 2 files changed, 407 deletions(-) delete mode 100644 src/chimera/util/dumper.py delete mode 100644 src/chimera/util/scat.py diff --git a/src/chimera/util/dumper.py b/src/chimera/util/dumper.py deleted file mode 100644 index f84a3295..00000000 --- a/src/chimera/util/dumper.py +++ /dev/null @@ -1,229 +0,0 @@ -# Taken from http://code.activestate.com/recipes/137951/ -# Originally licensed under the Python License (presumably -# version 2.0.1/2.1.1 or later) -# Relicensed under GPL of use in Chimera - - -def printDict(di, format="%-25s %s"): - for (key, val) in di.items(): - print format % (str(key) + ':', val) - - -def dumpObj(obj, maxlen=77, lindent=24, maxspew=600): - """Print a nicely formatted overview of an object. - - The output lines will be wrapped at maxlen, with lindent of space - for names of attributes. A maximum of maxspew characters will be - printed for each attribute value. - - You can hand dumpObj any data type -- a module, class, instance, - new class. - - Note that in reformatting for compactness the routine trashes any - formatting in the docstrings it prints. - - Example: - >>> class Foo(object): - a = 30 - def bar(self, b): - "A silly method" - return a*b - ... ... ... ... - >>> foo = Foo() - >>> dumpObj(foo) - Instance of class 'Foo' as defined in module __main__ with id 136863308 - Documentation string: None - Built-in Methods: __delattr__, __getattribute__, __hash__, __init__ - __new__, __reduce__, __repr__, __setattr__, - __str__ - Methods: - bar "A silly method" - Attributes: - __dict__ {} - __weakref__ None - a 30 - """ - - import types - - # Formatting parameters. - ltab = 2 # initial tab in front of level 2 text - - # There seem to be a couple of other types; gather templates of them - MethodWrapperType = type(object().__hash__) - - # - # Gather all the attributes of the object - # - objclass = None - objdoc = None - objmodule = '' - - methods = [] - builtins = [] - classes = [] - attrs = [] - for slot in dir(obj): - attr = getattr(obj, slot) - if slot == '__class__': - objclass = attr.__name__ - elif slot == '__doc__': - objdoc = attr - elif slot == '__module__': - objmodule = attr - elif (isinstance(attr, types.BuiltinMethodType) or - isinstance(attr, MethodWrapperType)): - builtins.append(slot) - elif (isinstance(attr, types.MethodType) or - isinstance(attr, types.FunctionType)): - methods.append((slot, attr)) - elif isinstance(attr, types.TypeType): - classes.append((slot, attr)) - else: - attrs.append((slot, attr)) - - # - # Organize them - # - methods.sort() - builtins.sort() - classes.sort() - attrs.sort() - - # - # Print a readable summary of those attributes - # - normalwidths = [lindent, maxlen - lindent] - tabbedwidths = [ltab, lindent - ltab, maxlen - lindent - ltab] - - def truncstring(s, maxlen): - if len(s) > maxlen: - return s[0:maxlen] + ' ...(%d more chars)...' % (len(s) - maxlen) - else: - return s - - # Summary of introspection attributes - if objclass == '': - objclass = type(obj).__name__ - intro = "Instance of class '%s' as defined in module %s with id %d" % \ - (objclass, objmodule, id(obj)) - print '\n'.join(prettyPrint(intro, maxlen)) - - # Object's Docstring - if objdoc is None: - objdoc = str(objdoc) - else: - objdoc = ('"""' + objdoc.strip() + '"""') - print - print prettyPrintCols(('Documentation string:', - truncstring(objdoc, maxspew)), - normalwidths, ' ') - - # Built-in methods - if builtins: - bi_str = delchars(str(builtins), "[']") or str(None) - print - print prettyPrintCols(('Built-in Methods:', - truncstring(bi_str, maxspew)), - normalwidths, ', ') - - # Classes - if classes: - print - print 'Classes:' - for (classname, classtype) in classes: - classdoc = getattr(classtype, '__doc__', None) or '' - print prettyPrintCols(('', - classname, - truncstring(classdoc, maxspew)), - tabbedwidths, ' ') - - # User methods - if methods: - print - print 'Methods:' - for (methodname, method) in methods: - methoddoc = getattr(method, '__doc__', None) or '' - print prettyPrintCols(('', - methodname, - truncstring(methoddoc, maxspew)), - tabbedwidths, ' ') - - # Attributes - if attrs: - print - print 'Attributes:' - for (attr, val) in attrs: - print prettyPrintCols(('', - attr, - truncstring(unicode(val), maxspew)), - tabbedwidths, ' ') - - -def prettyPrintCols(strings, widths, split=' '): - """Pretty prints text in colums, with each string breaking at - split according to prettyPrint. margins gives the corresponding - right breaking point.""" - - assert len(strings) == len(widths) - - strings = map(nukenewlines, strings) - - # pretty print each column - cols = [''] * len(strings) - for i in range(len(strings)): - cols[i] = prettyPrint(strings[i], widths[i], split) - - # prepare a format line - format = ''.join(["%%-%ds" % width for width in widths[0:-1]]) + "%s" - - def formatline(*cols): - return format % tuple(map(lambda s: (s or ''), cols)) - - # generate the formatted text - return '\n'.join(map(formatline, *cols)) - - -def prettyPrint(string, maxlen=75, split=' '): - """Pretty prints the given string to break at an occurrence of - split where necessary to avoid lines longer than maxlen. - - This will overflow the line if no convenient occurrence of split - is found""" - - # Tack on the splitting character to guarantee a final match - string += split - - lines = [] - oldeol = 0 - eol = 0 - while not (eol == -1 or eol == len(string) - 1): - eol = string.rfind(split, oldeol, oldeol + maxlen + len(split)) - lines.append(string[oldeol:eol]) - oldeol = eol + len(split) - - return lines - - -def nukenewlines(string): - """Strip newlines and any trailing/following whitespace; rejoin - with a single space where the newlines were. - - Bug: This routine will completely butcher any whitespace-formatted - text.""" - - if not string: - return '' - lines = string.splitlines() - return ' '.join([line.strip() for line in lines]) - - -def delchars(str, chars): - """Returns a string for which all occurrences of characters in - chars have been removed.""" - - # Translate demands a mapping string of 256 characters; - # whip up a string that will leave all characters unmolested. - identity = ''.join([chr(x) for x in range(256)]) - - return str.translate(identity, chars) diff --git a/src/chimera/util/scat.py b/src/chimera/util/scat.py deleted file mode 100644 index 40a0d63d..00000000 --- a/src/chimera/util/scat.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python -# -*- coding: iso-8859-1 -*- - -import subprocess -import tempfile -import logging -import os - -from types import TupleType, IntType, FloatType - -import asciidata - -# logging.getLogger().setLevel(logging.DEBUG) - - -class SCatWrapper (object): - - __options__ = {"catalog": "-c %s", - "radius": "-r %d", - "box": "-r %d,%d", - "near": "%s", - "limit": "-n %d", - "mag_faint": "-m%d ,%.2f", - "mag_both": "-m%d %.2f,%.2f", } - - # TODO: merge with _make_cmdline_args and simplify - def _make_options_dict(self, conditions, bands): - - scat_options = {} - - # spatial limits - if "box" in conditions and "radius" in conditions: - raise TypeError("radius and box cannot be used together.") - - # scat use half-widths, we use full-width, so divide by 2.0 to satisfy - # scat - if "box" in conditions: - side = conditions.get("box") - - if not type(side) == TupleType: - scat_options.update({"box": (side / 2.0, side / 2.0)}) - else: - - if len(side) >= 2: - scat_options.update( - {"box": (side[0] / 2.0, side[1] / 2.0)}) - else: - logging.warning("Invalid box: %s" % side) - - if "radius" in conditions: - scat_options.update({"radius": conditions.get("radius")}) - - if "closest" in conditions: - scat_options.update({"closest": True}) - try: - del scat_options["radius"] - del scat_options["box"] - except KeyError: - pass - - # magnitude limits - mags = [(k.split("mag")[1], v) - for k, v in conditions.items() if k.startswith("mag")] - - mag_faintest = None - mag_brighter = None - mag_band = None - - for mag, values in mags: - if mag in bands: - if type(values) == TupleType and len(values) >= 2: - mag_brighter = values[0] - mag_faintest = values[1] - mag_band = mag - elif type(values) in (IntType, FloatType): - mag_band = mag - mag_faintest = values - - # scat only accept one magnitude limit - break - - if mag_band: - if mag_brighter: - scat_options.update( - {"mag": (bands.index(mag_band), mag_brighter, mag_faintest)}) - elif mag_faintest: - scat_options.update( - {"mag": (bands.index(mag_band), mag_faintest)}) - - return scat_options - - # TODO: merge with _make_options_dict and simplify - def _make_cmdline_args(self, options): - - catalog = "-c ucac2" - params = "" - near = "00:00:00 +00:00:00" - - if "catalog" in options: - catalog = self.__options__["catalog"] % options.pop("catalog") - - if "near" in options: - near = self.__options__["near"] % options.pop("near") - - if "mag" in options: - values = options.pop("mag") - - if len(values) == 3: - params += " " + self.__options__["mag_both"] % values - elif len(values) == 2: - params += " " + self.__options__["mag_faint"] % values - - if "closest" in options: - value = options.pop("closest") - params += " -a " - - # anyone else? - for opt in options: - - if opt in self.__options__: - try: - arg = self.__options__[opt] % options[opt] - params += " " + arg - except ValueError: - pass - - return "%s %s %s" % (catalog, params, near) - - def _getTempFile(self): - return tempfile.NamedTemporaryFile(mode='w+', - prefix="chimera.scat", - dir=tempfile.gettempdir() - ) - - def run(self, options): - - # update options with the conditions given - options.update(self._make_options_dict( - options.pop("conditions", {}), options.pop("bands", []))) - cmdline_args = self._make_cmdline_args(options) - - logging.debug("Running scat with: %s arguments." % cmdline_args) - - # FIXME: who will close this file? - result = self._getTempFile() - - try: - proc = subprocess.Popen(args=cmdline_args.split(), - executable="scat", - env=options.get("env", os.environ), - stderr=subprocess.STDOUT, - stdout=result) - except OSError: - raise OSError( - "You don't have scat. Try put scat somewhere in your $PATH") - - proc.wait() - - try: - - data = asciidata.open(result.name) - data.toSExtractor() - - metadata = options.get("metadata", []) - - if metadata: - for col, meta in zip(data, metadata): - col.rename(meta[0]) - col.set_unit(meta[1]) - col.set_colcomment(meta[2]) - - data.flush() - - return data - - except: - - return False From d4d0ca311602f47839daae2e98cc2ff9c25e682f Mon Sep 17 00:00:00 2001 From: William Schoenell Date: Wed, 12 Jun 2024 20:32:15 -0700 Subject: [PATCH 3/6] moved astrometry.net to pverify --- src/chimera/core/exceptions.py | 9 --- src/chimera/util/astrometrynet.py | 108 ------------------------------ 2 files changed, 117 deletions(-) delete mode 100644 src/chimera/util/astrometrynet.py diff --git a/src/chimera/core/exceptions.py b/src/chimera/core/exceptions.py index 9b1b8160..171af67b 100644 --- a/src/chimera/core/exceptions.py +++ b/src/chimera/core/exceptions.py @@ -130,15 +130,6 @@ class CantSetScopeException(ChimeraException): fails there because of bright objects or other more astronomical reasons """ - -class NoSolutionAstrometryNetException(ChimeraException): - - """ - This exception is raised to indicate solve-field from astrometry.net - could not find a solution to the field - """ - - class MeadeException(ChimeraException): pass diff --git a/src/chimera/util/astrometrynet.py b/src/chimera/util/astrometrynet.py deleted file mode 100644 index 42f6f4c6..00000000 --- a/src/chimera/util/astrometrynet.py +++ /dev/null @@ -1,108 +0,0 @@ -from subprocess import Popen -import os -import logging -import time - -from chimera.util.sextractor import SExtractor -from chimera.core.exceptions import ChimeraException -from chimera.util.image import Image - -log = logging.getLogger(__name__) - - -class AstrometryNet: - # staticmethod allows to use a single method of a class - @staticmethod - def solveField(fullfilename, findstarmethod="astrometry.net"): - """ - @param: fullfilename entire path to image - @type: str - - @param: findstarmethod (astrometry.net, sex) - @type: str - - Does astrometry to image=fullfilename - Uses either astrometry.net or sex(tractor) as its star finder - """ - - pathname, filename = os.path.split(fullfilename) - pathname = pathname + "/" - basefilename, file_xtn = os.path.splitext(filename) - # *** enforce .fits extension - if file_xtn != ".fits": - raise ValueError("File extension must be .fits it was = %s\n" % file_xtn) - - # *** check whether the file exists or not - if os.path.exists(fullfilename) == False: - raise IOError("You selected image %s It does not exist\n" % fullfilename) - - # version 0.23 changed behavior of --overwrite - # I need to specify an output filename with -o - outfilename = basefilename + "-out" - - image = Image.fromFile(fullfilename) - try: - ra = image["CRVAL1"] # expects to see this in image - except: - raise AstrometryNetException("Need CRVAL1 and CRVAL2 and CD1_1 on header") - try: - dec = image["CRVAL2"] - except: - raise AstrometryNetException("Need CRVAL1 and CRVAL2 and CD1_1 on header") - width = image["NAXIS1"] - height = image["NAXIS2"] - radius = 10.0 * abs(image["CD1_1"]) * width - - wcs_filename = pathname + outfilename + ".wcs" - - if findstarmethod == "astrometry.net": - line = "solve-field %s --no-plots --overwrite -o %s --ra %f --dec %f --radius %f" % ( - fullfilename, outfilename, ra, dec, radius) - elif findstarmethod == "sex": - sexoutfilename = pathname + outfilename + ".xyls" - line = "solve-field %s --no-plots --overwrite -o %s --x-column X_IMAGE --y-column Y_IMAGE " \ - "--sort-column MAG_ISO --sort-ascending --width %d --height %d --ra %f --dec %f --radius %f" % ( - sexoutfilename, outfilename, width, height, ra, dec, radius) - - sex = SExtractor() - sex.config['BACK_TYPE'] = "AUTO" - sex.config['DETECT_THRESH'] = 3.0 - sex.config['DETECT_MINAREA'] = 18.0 - sex.config['VERBOSE_TYPE'] = "QUIET" - sex.config['CATALOG_TYPE'] = "FITS_1.0" - sex.config['CATALOG_NAME'] = sexoutfilename - sex.config['PARAMETERS_LIST'] = ["X_IMAGE", "Y_IMAGE", "MAG_ISO"] - sex.run(fullfilename) - - else: - log.error("Unknown option used in astrometry.net") - - # when there is a solution astrometry.net creates a file with .solved - # added as extension. - is_solved = pathname + outfilename + ".solved" - # if it is already there, make sure to delete it - if os.path.exists(is_solved): - os.remove(is_solved) - log.debug("SOLVE %s" % line) - # *** it would be nice to add a test here to check - # whether astrometrynet is running OK, if not raise a new exception - # like AstrometryNetInstallProblem - log.debug('Starting solve-field...') - t0 = time.time() - solve = Popen(line.split()) # ,env=os.environ) - solve.wait() - log.debug('Solve field finished. Took %3.2f sec' % (time.time() - t0)) - # if solution failed, there will be no file .solved - if (os.path.exists(is_solved) == False): - raise NoSolutionAstrometryNetException( - "Astrometry.net could not find a solution for image: %s %s" % (fullfilename, is_solved)) - - return wcs_filename - - -class AstrometryNetException(ChimeraException): - pass - - -class NoSolutionAstrometryNetException(ChimeraException): - pass From d6b6dc0c3de7f95ca29ada7ca434f8bb5de6ff47 Mon Sep 17 00:00:00 2001 From: William Schoenell Date: Wed, 12 Jun 2024 20:32:33 -0700 Subject: [PATCH 4/6] moved votable to pverify --- src/chimera/util/votable.py | 403 ------------------------------------ 1 file changed, 403 deletions(-) delete mode 100644 src/chimera/util/votable.py diff --git a/src/chimera/util/votable.py b/src/chimera/util/votable.py deleted file mode 100644 index 8fd8fe21..00000000 --- a/src/chimera/util/votable.py +++ /dev/null @@ -1,403 +0,0 @@ -""" Class to handle VOTable - Created: 2005-05-31 by Shui Hung Kwok, shkwok at computer.org - - See http://www.ivoa.net/Documents/latest/VOT.html . -""" - -import sys -from types import * -import xml.sax -import xml.sax.handler - - -class VONode(object): - - """ - Class representing an XML node of a VOTable - """ - - def __init__(self, tagname=('', '')): - self._tagname = tagname - self._nodeList = [] - self._attributes = {} - - def addNode(self, node): - self._nodeList.append(node) - if not isinstance(node, (StringType, UnicodeType)): - name = node.getNamePart() - try: - val = self.__dict__[name] - if isinstance(val, ListType): - val.append(node) - else: - self.__dict__[name] = [val, node] - except: - self.__dict__[name] = node - else: - self.content = node - - def addAttribute(self, attr): - name, value = attr - self._attributes[name] = value - self.__dict__[name] = value - - def addAttributes(self, attrs): - self._attributes.update(attrs) - for k, v in attrs.items(): - self.__dict__[k[1]] = v - - def __getitem__(self, idx): - return self._nodeList[idx].getContent() - - def getAttribute(self, name): - """ Returns attribute by name or '' if not found """ - return self._attributes.get(name) - - def getAttributes(self): - """ Returns all attributes. - """ - res = {} - for (ns, n), at in self._attributes.items(): - res[n] = at - return res - - def getNodeList(self): - """ Returns a list of nodes that are of type VONode - """ - res = [] - for node in self._nodeList: - try: - l = node._nodeList - res.append(node) - except Exception: - pass - return res - - def getContent(self): - """ Returns all strings of the node. - """ - res = [] - for node in self._nodeList: - try: - l = node.lower() - res.append(node) - except Exception: - pass - return ''.join(res) - - def getNamePart(self): - try: - ns, n = self._tagname - return n - except: - return n - - def getNodesByName(self, look4): - """ Returns a list of nodes whose tagname = look4 - """ - res = [] - for node in self._nodeList: - try: - if look4 != node.getNamePart(): - continue - l = node._nodeList - res.append(node) - except Exception: - pass - return res - - def __str__(self): - try: - return self.content - except: - return self.buildName(self._tagname) - - def getNode(self, path): - """ Returns a node for a given path. - Path is of the form /tag1/tag2/tag3. - Path can include array index, like /tag1/tag2[3]/tag4. - """ - node = self - children = [] - pathArray = path.split("/") - - rootName = self.getNamePart() - if rootName != pathArray[1]: - return None - - pathArray = pathArray[2:] - for elem in pathArray: - tmp = elem.replace('[', ']') - list = tmp.split(']') - name = list[0] - if len(list) > 1: - idx = int(list[1]) - else: - idx = 0 - children = node.getNodesByName(name) - nr = len(children) - if idx >= nr: - return None - node = children[idx] - return node - - def getNodesByPath(self, path): - """ Returns an array of VONodes for a given path. - Path is of the form /tag1/tag2/tag3. - Path can include array index, like /tag1/tag2[3]/tag4. - """ - node = self - children = [] - pathArray = path.split("/") - - rootName = self.getNamePart() - if rootName != pathArray[1]: - return None - - pathArray = pathArray[2:] - for elem in pathArray: - tmp = elem.replace('[', ']') - list = tmp.split(']') - name = list[0] - if len(list) > 1: - idx = int(list[1]) - else: - idx = 0 - children = node.getNodesByName(name) - nr = len(children) - if idx >= nr: - return None - node = children[idx] - return children - - def buildName(self, tname): - """ Returns a name with namespace as prefix - or just name if no namespace - Note that the prefix is the real namespace - and not the abbreviation used in the original XML - """ - ns, n = tname - """ - if ns: - return "%s:%s" % (self.qname, n) - else: - return n - """ - return n - - def printAllNodes(self, func=sys.stdout.write, prefix=''): - """ Recursive method to visit all nodes of the tree - and calls the provided function to output the content. - """ - func("%s<%s" % (prefix, self.buildName(self._tagname))) - for ns, v in self._attributes.items(): - func(" %s='%s'" % (self.buildName((ns)), v)) - func(">") - - last = 0 - for n in self._nodeList: - if isinstance(n, (StringType, UnicodeType)): - if last == 2: - func("\n%s" % prefix) - func("%s" % n) - last = 1 - else: - if last <= 1: - func("\n") - n.printAllNodes(func, prefix + ' ') - last = 2 - if last <= 1: - func("\n" % self.buildName(self._tagname)) - else: - func("%s\n" % (prefix, self.buildName(self._tagname))) - - -class VOTableHandler (xml.sax.handler.ContentHandler): - - """ Class implementing callbacks for the SAX parser. - """ - - def __init__(self, vonode=VONode): - # Create a parser - xml.sax.handler.ContentHandler.__init__(self) - self.parser = xml.sax.make_parser() - self.parser.setFeature(xml.sax.handler.feature_namespaces, 1) - self.parser.setContentHandler(self) - self.vonode = vonode - self.sentinel = vonode() - self.currNode = self.sentinel - self.stack = [] - - def startElementNS(self, (urn, name), qname, attrs): - # print "start ", name - self.stack.append(self.currNode) - - self.currNode = self.vonode((urn, name)) - self.currNode.addAttributes(attrs) - - def characters(self, chunk): - buf = chunk.strip() - if len(buf) == 0: - return - self.currNode.addNode(buf) - - def endElementNS(self, (urn, name), qname): - # print "end ", name - newNode = self.currNode - self.currNode = self.stack.pop() - self.currNode.addNode(newNode) - - def parse(self, source): - """ Main entry point. - Source can be URL or file name. - """ - self.parser.parse(source) - return self.sentinel # ._nodeList[0] - - -class VOTable(object): - - """ - Implementation of VOTable - """ - - def __init__(self, source=None, vonode=VONode): - """ - Instantiate a VOTable. - source can be URL, file name or a string representing the VOTable. - vonode is a class representing VONode, must be derived from or - compatible with VONode. - """ - self.vonode = vonode - self.root = None - if source != None: - self.parse(source) - - def parse(self, source): - """ - Invokes XML parser and stores VOTable - in self.root as VONode. - """ - parser = VOTableHandler(self.vonode) - self.root = parser.parse(source) - - def printAllNodes(self, func=sys.stdout.write): - """ - Output entire content as XML. - func is the output method, defined as: - func (outString) - """ - # _nodeList[0] is VOTABLE - # We use _nodeList[0] instead, just in case - # the xml content does not start with VOTABLE, - # we still can print all nodes. - node = self.root._nodeList[0] - node.printAllNodes(func) - - def getNode(self, path): - """ - Returns a VONode of the given path. - """ - return self.root._nodeList[0].getNode(path) - - def getContent(self, path): - """ - Returns the content of a node. - Only strings are returned. - """ - node = self.getNode(path) - return node.getContent() - - def getColumnIdx(self, val): - """ - Returns the column index for the given name - Will return any attribute value matching val. - """ - fields = self.getFields() - for coln, f in enumerate(fields): - if val in f._attributes.values(): - return coln - return -1 - - def getFields(self): - """ - Returns a list of VONode representing all the fields - """ - #table = self.root.VOTABLE.RESOURCE.TABLE - # return table.getNodesByName ('FIELD') - return self.root.VOTABLE.RESOURCE.TABLE.FIELD - - def getParams(self): - """ - Returns a list of VONode representing all PARAMS - """ - return self.root.VOTABLE.RESOURCE.RESOURCE.PARAM - - def getFieldsAttrs(self): - """ - Returns a list of maps that contains attributes. - Returned list looks like this: [{},{},...] - """ - res = [] - fields = self.getFields() - for elem in fields: - try: - res.append(elem.getAttributes()) - except: - pass - return res - - def getDataRows(self): - """ - Returns a list of VONodes representing rows of the table. - Use getData () to extract data from each row. - for x in getDataRows (): - data = getData (x) - #data = [values ...] - """ - tableData = self.root.VOTABLE.RESOURCE.TABLE.DATA.BINARY.STREAM - return tableData._nodeList - - def getData(self, row): - """ - row is a VONode parent of a list of . - Returns a list of values. - """ - res = [] - list = row._nodeList - for elm in list: - try: - res.append(elm.getContent()) - except: - res.append('') - return res - - def append(self, vot): - """ - Appends votable vot to the end of this VOTable. - No tests to see if fields are the same. - vot must have the same fields. - """ - try: - node1 = self.root.VOTABLE.RESOURCE.TABLE.DATA.TABLEDATA - except: - node1 = None - try: - node2 = vot.root.VOTABLE.RESOURCE.TABLE.DATA.TABLEDATA - except: - node2 = None - - if node1: - if node2: - node1._nodeList.extend(node2._nodeList) - else: - if node2: - self.root.VOTABLE.RESOURCE.TABLE.DATA.TABLEDATA = node2 - -if __name__ == '__main__': - votable = VOTable() - votable.parse(sys.argv[1]) - #votable.printAllNodes () - # print [x.getAttribute ('ID') for x in votable.getFields () ] - # print votable.root.VOTABLE.RESOURCE.TABLE.DATA.TABLEDATA.TR[1].TD[1] - print votable.getFields() From d07deadc4396ec47d3aaf96b4e3c175112c00d1c Mon Sep 17 00:00:00 2001 From: William Schoenell Date: Wed, 12 Jun 2024 20:34:27 -0700 Subject: [PATCH 5/6] fixed script exceptions import --- src/scripts/chimera-seeing | 2 -- src/scripts/chimera-weather | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/scripts/chimera-seeing b/src/scripts/chimera-seeing index 042d7ac5..e7fbde58 100644 --- a/src/scripts/chimera-seeing +++ b/src/scripts/chimera-seeing @@ -3,8 +3,6 @@ import datetime import sys -import exceptions - from chimera.core.cli import ChimeraCLI, action from chimera.util.output import red, green diff --git a/src/scripts/chimera-weather b/src/scripts/chimera-weather index 5e68909f..88a1cb35 100644 --- a/src/scripts/chimera-weather +++ b/src/scripts/chimera-weather @@ -2,7 +2,6 @@ import datetime import sys -import exceptions from chimera.core.cli import ChimeraCLI, action from chimera.interfaces.weatherstation import WeatherSafety from chimera.util.output import red, green @@ -37,7 +36,7 @@ class ChimeraWeather(ChimeraCLI): 'sky_transparency'): try: v = self.weatherstation.__getattr__(attr)() - if isinstance(v, exceptions.NotImplementedError) or not v: + if isinstance(v, NotImplementedError) or not v: continue t = red(v.time.__str__()) if datetime.datetime.utcnow() - v.time > datetime.timedelta( minutes=self.options.max_mins) else green(v.time.__str__()) From 1a2eda1136a0bc1d74a83af4ce203fe34d71da91 Mon Sep 17 00:00:00 2001 From: William Schoenell Date: Wed, 12 Jun 2024 20:34:48 -0700 Subject: [PATCH 6/6] moved meade exception out of the core --- src/chimera/core/exceptions.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/chimera/core/exceptions.py b/src/chimera/core/exceptions.py index 171af67b..f93c42c2 100644 --- a/src/chimera/core/exceptions.py +++ b/src/chimera/core/exceptions.py @@ -130,10 +130,6 @@ class CantSetScopeException(ChimeraException): fails there because of bright objects or other more astronomical reasons """ -class MeadeException(ChimeraException): - pass - - class ProgramExecutionException(ChimeraException): pass