Source code for hscmap.catalog

from pprint import pformat
from .hook import Hook
from .utils import uid
from .typecheck import TypeCheck, V4


[docs]class Catalog: def __init__(self, window, ra, dec, columns, *, name, color=None): ''' Represents a catalog. Note: You should use :attr:`hscmap.window.Window.catalogs` to create a new :class:`Catalog` instaed of directly using the constructor. Args: window(:class:`hscmap.window.Window`): Owner window ra (ndarray): RA in degrees dec (ndarray): DEC in degrees columns (dict<str, ndarray> | (str, ndarray)[]): Additional columns ''' color = color or [0, 1, 0, 0.75] TypeCheck(V4)(color) assert len(ra) == len(dec) self._name = name self._id = uid() self._window = window if isinstance(columns, dict): columns = list(columns.items()) self._ra = ra self._dec = dec self._columns = columns self._color = color self.hook = Hook() def call_on_click(*args): self.on_click(*args) self._on_click_cb = \ self._window._callback.new(call_on_click, persistent=True) self._on_change_cb = \ self._window._callback.new(self._on_change, persistent=True) self._send() def _send(self): self._window._channel.send({ 'type': 'add_catalog', 'args': { 'id': self._id, 'ra': self._ra, 'dec': self._dec, 'name': self._name, 'columns': self._columns, 'color': self._color, 'on_click': self._on_click_cb.api, 'on_change': self._on_change_cb.api, } })
[docs] def remove(self): ''' Removes this catalog. ''' self._on_click_cb.remove() self._on_change_cb.remove() self._window._channel.send({ 'type': 'remove_catalog', 'args': { 'id': self._id, } }) self.hook.call('remove')
@property def name(self): ''' Name of this catalog. Can be set and read. ''' return self._name @name.setter def name(self, name): TypeCheck(str)(name) self._name = name self._update(name=name) @property def color(self): ''' Color of markers. Can be set and read. It's type should be ``[float, float, float, float]``. ''' return self._color @color.setter def color(self, color): TypeCheck(V4)(color) self._color = color self._update(color=color)
[docs] def set_coords(self, ra, dec, columns=[]): ''' Updates its objects' coordinates and columns. Types of arameters are the same as :class:`~hscmap.catalog.Catalog`. ''' assert len(ra) == len(dec) if isinstance(columns, dict): columns = list(columns.items()) self._ra = ra self._dec = dec self._column = columns self._update(ra=ra, dec=dec, columns=columns)
def _update(self, *, name=None, color=None, ra=None, dec=None, columns=None): self._window._channel.send({ 'type': 'update_catalog', 'args': { 'id': self._id, 'name': name, 'color': color, 'ra': ra, 'dec': dec, 'columns': columns, }, }) def _on_change(self, attrs): self._name = attrs['name'] self._color = attrs['color']
[docs] def on_click(self, index): ''' Callback for clicking objects of this catalog. This method can be overwritten by user. It accepts an index of clicked object. Example: :: res = sql.query('SELECT ...') catalog = w.catalogs.from_query_result(res) indices = [] def on_click(index): indices.append(index) catalog.on_click = on_click ''' pass
def _restore(self): self._send() def __repr__(self): return f'<Catalog name={self._name} len={len(self._ra)}>'
[docs]class CatalogManager: ''' Manages catalogs that belongs to a hscmap window. See Also: :attr:`~hscmap.window.Window.catalogs` ''' def __init__(self, window): self._window = window self._members = {} self._window.hook.on('restore', self._on_window_restore)
[docs] def new(self, ra, dec, *, name=None, columns=[], color=None): ''' Makes new catalog. Args: ra (ndarray): RA in degrees dec (ndarray): Dec in degrees columns (dict<str, ndarray> | (str, ndarray)[]): Additional columns name (str): catalog name color ([float, float, float, float]): marker color Returns: :class:`~hscmap.catalog.Catalog` Example: :: n = 100 a = numpy.random.uniform(150, 151, n) d = numpy.random.uniform(1, 2, n) w.jump_to(a[0], d[0], 1) random_catalog = w.catalogs.new(a, d) See Also: :attr:`hscmap.window.Window.catalogs` ''' if name is None: name = f'catalog-{len(self._members) + 1}' cat = Catalog(self._window, ra, dec, columns, name=name, color=color) self._members[cat._id] = cat def on_remove(): self._members.pop(cat._id, None) cat.hook.on('remove', on_remove) return cat
[docs] def from_query_result(self, res, *, name=None, color=None): ''' Makes new catalog plot from a resutltant object generated by ``hscdata.sql.query``. Args: res (hscdata.sql._QueryResult): Query result name (str): Catalog name color ([float, float, float, float]): Marker color Returns: :class:`~hscmap.catalog.Catalog` Example: :: import hscdata.sql as sql res = sql.query(""" SELECT object_id ,ra ,dec ,i_cmodel_mag ,i_cmodel_magsigma ,y_cmodel_mag ,y_cmodel_magsigma FROM pdr2_wide.forced WHERE boxSearch(coord, 151.38831350334513, 151.40458586556656, 0.06900732437557724, 0.0825390607736913) AND isprimary """, isNullColumn=False) catalog = w.catalogs.from_query_result(res) ''' return self.new(res.ra, res.dec, name=name, columns=res._dictionary, color=color)
[docs] def clear(self): ''' Clear all catalogs managed by this object. ''' cats = list(self._members.values()) for cat in cats: cat.remove()
@property def members(self): ''' All catalogs on the window. Returns: List of :class:`~hscmap.catalog.Catalog` ''' return list(self._members.values()) def _on_window_restore(self): for cat in self._members.values(): cat._restore() def __repr__(self): return f'<CatalogManager {pformat(self._members)}>'