diff --git a/glue/config.py b/glue/config.py
index 2d4c20066..328162777 100644
--- a/glue/config.py
+++ b/glue/config.py
@@ -615,11 +615,11 @@ class LinkHelperRegistry(Registry):
"""Stores helper objects that compute many ComponentLinks at once
- The members property is a list of (object, info_string,
- input_labels) tuples. `Object` is the link helper. `info_string`
- describes what `object` does. `input_labels` is a list labeling
- the inputs. ``category`` is a category in which the link funtion will appear
- (defaults to 'General').
+ The members property is a list of (object, info_string, input_labels,
+ output_labels) tuples. `Object` is the link helper. `info_string` describes
+ what `object` does. `input_labels` is a list labeling the inputs, and
+ `output_labels` is a list labeling the outputs. ``category`` is a category
+ in which the link funtion will appear (defaults to 'General').
Each link helper takes a list of ComponentIDs as inputs, and
returns an iterable object (e.g. list) of ComponentLinks.
@@ -627,16 +627,16 @@ class LinkHelperRegistry(Registry):
New helpers can be registered via
@link_helper('Links degrees and arcseconds in both directions',
- ['degree', 'arcsecond'])
+ input_labels=['degree'], output_labels=['arcsecond'])
def new_helper(degree, arcsecond):
return [ComponentLink([degree], arcsecond, using=lambda d: d*3600),
ComponentLink([arcsecond], degree, using=lambda a: a/3600)]
"""
- item = namedtuple('LinkHelper', 'helper info input_labels category')
+ item = namedtuple('LinkHelper', 'helper info input_labels output_labels category')
- def __call__(self, info, input_labels, category='General'):
+ def __call__(self, info, input_labels, output_labels, category='General'):
def adder(func):
- self.add(self.item(func, info, input_labels, category))
+ self.add(self.item(func, info, input_labels, output_labels, category))
return func
return adder
diff --git a/glue/core/link_helpers.py b/glue/core/link_helpers.py
index 0365e7f05..38f3c0427 100644
--- a/glue/core/link_helpers.py
+++ b/glue/core/link_helpers.py
@@ -112,12 +112,13 @@ class MultiLink(LinkCollection):
cids = None
- def __init__(self, *args):
- self.cids = args
+ def __init__(self, cids_left, cids_right):
+ self.cids_left = cids_left
+ self.cids_right = cids_right
def create_links(self, cids_left, cids_right, forwards=None, backwards=None):
- if self.cids is None:
+ if self.cids_left is None or self.cids_right is None:
raise Exception("MultiLink.__init__ was not called before creating links")
if forwards is None and backwards is None:
@@ -134,15 +135,17 @@ def create_links(self, cids_left, cids_right, forwards=None, backwards=None):
self.append(ComponentLink(cids_right, l, func))
def __gluestate__(self, context):
- return {'cids': [context.id(cid) for cid in self.cids]}
+ return {'cids_left': [context.id(cid) for cid in self.cids_left],
+ 'cids_right': [context.id(cid) for cid in self.cids_right]}
@classmethod
def __setgluestate__(cls, rec, context):
- return cls(*[context.object(cid) for cid in rec['cids']])
+ return cls([context.object(cid) for cid in rec['cids_left']],
+ [context.object(cid) for cid in rec['cids_right']])
def multi_link(cids_left, cids_right, forwards=None, backwards=None):
- ml = MultiLink(cids_left + cids_right)
+ ml = MultiLink(cids_left, cids_right)
ml.create_links(cids_left, cids_right, forwards=forwards, backwards=backwards)
return ml
diff --git a/glue/dialogs/component_manager/qt/derived_creator.py b/glue/dialogs/component_manager/qt/derived_creator.py
new file mode 100644
index 000000000..9b1906e45
--- /dev/null
+++ b/glue/dialogs/component_manager/qt/derived_creator.py
@@ -0,0 +1,62 @@
+
+from __future__ import absolute_import, division, print_function
+
+import os
+from collections import deque
+
+from qtpy import QtWidgets, QtCore
+from qtpy.QtCore import Qt
+
+from glue.external.echo import CallbackProperty
+from glue.core.parse import InvalidTagError, ParsedCommand, TAG_RE
+from glue.utils.qt import load_ui, CompletionTextEdit
+
+__all__ = ['EquationEditorDialog']
+
+
+class DerivedComponentEditor(QtWidgets.QDialog):
+
+ def __init__(self, equation=None, references=None, parent=None):
+
+ super(DerivedComponentEditor, self).__init__(parent=parent)
+
+ self.ui = load_ui('derived_creator.ui', self,
+ directory=os.path.dirname(__file__))
+
+ # Populate component combo
+ for label, cid in self.references.items():
+ self.ui.combosel_component.addItem(label, userData=cid)
+
+ # Set up labels for auto-completion
+ labels = ['{' + label + '}' for label in self.references]
+ self.ui.expression.set_word_list(labels)
+
+ # Set initial equation
+ self.ui.expression.insertPlainText(equation)
+
+ self.ui.button_insert.clicked.connect(self._insert_component)
+
+ self.ui.expression.updated.connect(self._update_status)
+ self._update_status()
+
+
+ # Get mapping from label to component ID
+ if references is not None:
+ self.references = references
+ elif data is not None:
+ self.references = OrderedDict()
+ for cid in data.primary_components:
+ self.references[cid.label] = cid
+
+if __name__ == "__main__": # pragma: nocover
+
+ from glue.main import load_plugins
+ from glue.utils.qt import get_qapp
+
+ app = get_qapp()
+ load_plugins()
+
+ from glue.core.data import Data
+ d = Data(label='test1', x=[1, 2, 3], y=[2, 3, 4], z=[3, 4, 5])
+ widget = EquationEditorDialog(d, '')
+ widget.exec_()
diff --git a/glue/dialogs/component_manager/qt/derived_creator.ui b/glue/dialogs/component_manager/qt/derived_creator.ui
new file mode 100644
index 000000000..8e76791c5
--- /dev/null
+++ b/glue/dialogs/component_manager/qt/derived_creator.ui
@@ -0,0 +1,157 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 535
+ 378
+
+
+
+ Derived Component Editor
+
+
+
+ 5
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 10
+
+
+ 5
+
+
+ 10
+
+
+ 5
+
+ -
+
+
+ Derived components are components that are evaluated on-the-fly based on other components. You can either define these using free-form expressions, or existing pre-defined transformations.
+
+
+ Qt::AlignJustify|Qt::AlignVCenter
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 10
+ 5
+
+
+
+
+ -
+
+
+ 0
+
+
+
+ Pre-defined transformations
+
+
+
+ 5
+
+
+ 10
+
+
+ 10
+
+
+ 10
+
+
+ 10
+
+
+
+
+
+ Free-from expression
+
+
+
+ 10
+
+
+ 10
+
+
+ 10
+
+
+ 10
+
+
+
+
+
+ -
+
+
-
+
+
+ status
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Cancel
+
+
+
+ -
+
+
+ OK
+
+
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/glue/dialogs/component_manager/qt/equation_editor.py b/glue/dialogs/component_manager/qt/equation_editor.py
index 1b99ea9b3..58d0a4743 100644
--- a/glue/dialogs/component_manager/qt/equation_editor.py
+++ b/glue/dialogs/component_manager/qt/equation_editor.py
@@ -1,11 +1,12 @@
from __future__ import absolute_import, division, print_function
import os
-from collections import deque, OrderedDict
+from collections import deque
from qtpy import QtWidgets, QtCore
from qtpy.QtCore import Qt
+from glue.external.echo import CallbackProperty
from glue.core.parse import InvalidTagError, ParsedCommand, TAG_RE
from glue.utils.qt import load_ui, CompletionTextEdit
@@ -88,25 +89,18 @@ def format_components(m):
self._cache = self.toPlainText()
-class EquationEditorDialog(QtWidgets.QDialog):
+class EquationEditorDialog(QtWidgets.QWidget):
- def __init__(self, data=None, equation=None, references=None, parent=None):
+ valid = CallbackProperty('')
+ message = CallbackProperty('')
+
+ def __init__(self, equation=None, references=None, parent=None):
super(EquationEditorDialog, self).__init__(parent=parent)
self.ui = load_ui('equation_editor.ui', self,
directory=os.path.dirname(__file__))
- self.equation = equation
-
- # Get mapping from label to component ID
- if references is not None:
- self.references = references
- elif data is not None:
- self.references = OrderedDict()
- for cid in data.primary_components:
- self.references[cid.label] = cid
-
# Populate component combo
for label, cid in self.references.items():
self.ui.combosel_component.addItem(label, userData=cid)
@@ -115,11 +109,9 @@ def __init__(self, data=None, equation=None, references=None, parent=None):
labels = ['{' + label + '}' for label in self.references]
self.ui.expression.set_word_list(labels)
+ # Set initial equation
self.ui.expression.insertPlainText(equation)
- self.ui.button_ok.clicked.connect(self.accept)
- self.ui.button_cancel.clicked.connect(self.reject)
-
self.ui.button_insert.clicked.connect(self._insert_component)
self.ui.expression.updated.connect(self._update_status)
@@ -129,35 +121,35 @@ def _insert_component(self):
label = self.ui.combosel_component.currentText()
self.expression.insertPlainText('{' + label + '}')
- def _update_status(self):
+ def _update_status(self, event=None):
# If the text hasn't changed, no need to check again
- if hasattr(self, '_cache') and self._get_raw_command() == self._cache:
+ if hasattr(self, '_cache') and self._get_raw_command() == self._cache and event is None:
return
if self._get_raw_command() == "":
- self.ui.label_status.setText("")
- self.ui.button_ok.setEnabled(False)
+ self.message = ""
+ self.valid = True
else:
try:
pc = self._get_parsed_command()
- pc.evaluate_test()
+ result = pc.evaluate_test()
except SyntaxError:
- self.ui.label_status.setStyleSheet('color: red')
- self.ui.label_status.setText("Incomplete or invalid syntax")
- self.ui.button_ok.setEnabled(False)
+ self.valid = False
+ self.message = "Incomplete or invalid syntax"
except InvalidTagError as exc:
- self.ui.label_status.setStyleSheet('color: red')
- self.ui.label_status.setText("Invalid component: {0}".format(exc.tag))
- self.ui.button_ok.setEnabled(False)
+ self.valid = False
+ self.message = "Invalid component: {0}".format(exc.tag)
except Exception as exc:
- self.ui.label_status.setStyleSheet('color: red')
- self.ui.label_status.setText(str(exc))
- self.ui.button_ok.setEnabled(False)
+ self.valid = False
+ self.message = str(exc)
else:
- self.ui.label_status.setStyleSheet('color: green')
- self.ui.label_status.setText("Valid expression")
- self.ui.button_ok.setEnabled(True)
+ if result is None:
+ self.valid = False
+ self.message = "Expression should not return None"
+ else:
+ self.valid = True
+ self.message = "Valid expression"
self._cache = self._get_raw_command()
@@ -167,23 +159,3 @@ def _get_raw_command(self):
def _get_parsed_command(self):
expression = self._get_raw_command()
return ParsedCommand(expression, self.references)
-
- def accept(self):
- self.final_expression = self._get_parsed_command()._cmd
- super(EquationEditorDialog, self).accept()
-
- def reject(self):
- self.final_expression = None
- super(EquationEditorDialog, self).reject()
-
-
-if __name__ == "__main__": # pragma: nocover
-
- from glue.utils.qt import get_qapp
-
- app = get_qapp()
-
- from glue.core.data import Data
- d = Data(label='test1', x=[1, 2, 3], y=[2, 3, 4], z=[3, 4, 5])
- widget = EquationEditorDialog(d, '')
- widget.exec_()
diff --git a/glue/dialogs/component_manager/qt/equation_editor.ui b/glue/dialogs/component_manager/qt/equation_editor.ui
index e4ae41a20..92a3e5922 100644
--- a/glue/dialogs/component_manager/qt/equation_editor.ui
+++ b/glue/dialogs/component_manager/qt/equation_editor.ui
@@ -1,38 +1,35 @@
Dialog
-
+
0
0
- 384
- 256
+ 501
+ 398
Derived Component Editor
-
-
- 5
-
+
10
- 5
+ 10
10
- 5
+ 10
-
- Derived components are components that are evaluated on-the-fly based on other components. In the box below, you can compose mathematical expressions that include components from the data. To add a component, select it in the dropdown list and click on 'Insert'. You can also type component names directly, provided that you surround them by curly braces, e.g. {x}. A status message below indicates whether the expression is valid. You can use any variable defined inside your config.py file, as well as numpy.<function>, np.<function> and math.<function> (e.g. np.log10 or math.sqrt). Once you click 'OK', you will be able to name the new component.
+ In the box below, you can compose mathematical expressions that include components from the data. To add a component, select it in the dropdown list and click on 'Insert'. You can also type component names directly, provided that you surround them by curly braces, e.g. {x}. A status message below indicates whether the expression is valid. You can use any variable defined inside your config.py file, as well as numpy.<function>, np.<function> and math.<function> (e.g. np.log10 or math.sqrt). Once you click 'OK', you will be able to name the new component.
Qt::AlignJustify|Qt::AlignVCenter
@@ -65,7 +62,7 @@
-
-
+
0
0
@@ -79,16 +76,26 @@
-
-
+
-
-
+
- status
+ Derived component name:
+
+
+
+ -
+
+
+
+ 100
+ 16777215
+
-
-
+
Qt::Horizontal
@@ -100,23 +107,6 @@
- -
-
-
- Cancel
-
-
-
- -
-
-
- OK
-
-
- true
-
-
-
diff --git a/glue/dialogs/component_manager/qt/function_editor.py b/glue/dialogs/component_manager/qt/function_editor.py
new file mode 100644
index 000000000..aab5a689b
--- /dev/null
+++ b/glue/dialogs/component_manager/qt/function_editor.py
@@ -0,0 +1,188 @@
+from __future__ import absolute_import, division, print_function
+
+import os
+from collections import OrderedDict
+
+try:
+ from inspect import getfullargspec
+except ImportError: # Python 2.7
+ from inspect import getargspec as getfullargspec
+
+from qtpy import QtWidgets
+
+from glue.config import link_function, link_helper
+from glue.utils.qt import load_ui, update_combobox
+
+__all__ = ['FunctionEditorDialog']
+
+
+def get_function_name(item):
+ if hasattr(item, 'display') and item.display is not None:
+ return item.display
+ else:
+ return item.__name__
+
+
+def function_label(function):
+ """ Provide a label for a function
+
+ :param function: A member from the glue.config.link_function registry
+ """
+ args = getfullargspec(function.function)[0]
+ args = ', '.join(args)
+ output = function.output_labels
+ output = ', '.join(output)
+ label = "Link from %s to %s" % (args, output)
+ return label
+
+
+def helper_label(helper):
+ """ Provide a label for a link helper
+
+ :param helper: A member from the glue.config.link_helper registry
+ """
+ return helper.info
+
+
+class FunctionEditorDialog(QtWidgets.QDialog):
+
+ def __init__(self, data=None, references=None, parent=None):
+
+ super(FunctionEditorDialog, self).__init__(parent=parent)
+
+ self.ui = load_ui('function_editor.ui', self,
+ directory=os.path.dirname(__file__))
+
+ # Get mapping from label to component ID
+ if references is not None:
+ self.references = references
+ elif data is not None:
+ self.references = OrderedDict()
+ for cid in data.primary_components:
+ self.references[cid.label] = cid
+
+ # Populate category combo
+ f = [f for f in link_function.members if len(f.output_labels) == 1]
+ categories = sorted(set(l.category for l in f + link_helper.members))
+ for category in categories:
+ self.ui.combosel_category.addItem(category)
+ self.ui.combosel_category.setCurrentIndex(0)
+ self.ui.combosel_category.currentIndexChanged.connect(self._populate_function_combo)
+ self._populate_function_combo()
+
+ self.ui.combosel_function.setCurrentIndex(0)
+ self.ui.combosel_function.currentIndexChanged.connect(self._setup_inputs)
+ self._setup_inputs()
+
+ @property
+ def category(self):
+ return self.ui.combosel_category.currentText()
+
+ @property
+ def function(self):
+ return self.ui.combosel_function.currentData()
+
+ @property
+ def is_helper(self):
+ return self.function is not None and type(self.function).__name__ == 'LinkHelper'
+
+ @property
+ def is_function(self):
+ return self.function is not None and type(self.function).__name__ == 'LinkFunction'
+
+ def _setup_inputs(self, event=None):
+
+ if self.is_function:
+ label = function_label(self.function)
+ input_labels = getfullargspec(self.function.function)[0]
+
+ else:
+ label = helper_label(self.function)
+ input_labels = self.function.input_labels
+
+ self.ui.label_info.setText(label)
+
+ self._clear_input_output_layouts()
+
+ input_message = "The function above takes the following input(s):"
+
+ if len(input_labels) > 1:
+ input_message = input_message.replace('(s)', 's')
+ else:
+ input_message = input_message.replace('(s)', '')
+
+ self.ui.layout_inout.addWidget(QtWidgets.QLabel(input_message), 0, 1, 1, 3)
+
+ spacer1 = QtWidgets.QSpacerItem(10, 5,
+ QtWidgets.QSizePolicy.Expanding,
+ QtWidgets.QSizePolicy.Fixed)
+ spacer2 = QtWidgets.QSpacerItem(10, 5,
+ QtWidgets.QSizePolicy.Expanding,
+ QtWidgets.QSizePolicy.Fixed)
+ self.ui.layout_inout.addItem(spacer1, 0, 0)
+ self.ui.layout_inout.addItem(spacer2, 0, 4)
+
+ row = 0
+ for a in input_labels:
+ row += 1
+ self._add_input_widget(a, row)
+
+ output_message = "This function produces the following output(s) - you can set the label(s) here:"
+
+ if len(self.function.output_labels) > 1:
+ output_message = output_message.replace('(s)', 's')
+ else:
+ output_message = output_message.replace('(s)', '')
+
+ row += 1
+ self.ui.layout_inout.addWidget(QtWidgets.QLabel(output_message), row, 1, 1, 3)
+
+ for a in self.function.output_labels:
+ row += 1
+ self._add_output_widget(a, row)
+
+ def _clear_input_output_layouts(self):
+
+ for row in range(self.ui.layout_inout.rowCount()):
+ for col in range(self.ui.layout_inout.columnCount()):
+ item = self.ui.layout_inout.itemAtPosition(row, col)
+ if item is not None:
+ self.ui.layout_inout.removeItem(item)
+ if item.widget() is not None:
+ item.widget().setParent(None)
+
+ def _add_input_widget(self, name, row):
+ label = QtWidgets.QLabel(name)
+ combo = QtWidgets.QComboBox()
+ update_combobox(combo, list(self.references.items()))
+ self.ui.layout_inout.addWidget(label, row, 1)
+ self.ui.layout_inout.addWidget(combo, row, 2)
+
+ def _add_output_widget(self, name, row):
+ label = QtWidgets.QLabel(name)
+ edit = QtWidgets.QLineEdit()
+ self.ui.layout_inout.addWidget(label, row, 1)
+ self.ui.layout_inout.addWidget(edit, row, 2)
+
+ def _populate_function_combo(self, event=None):
+ """
+ Add name of functions to function combo box
+ """
+ f = [f for f in link_function.members if len(f.output_labels) == 1]
+ functions = ((get_function_name(l[0]), l) for l in f + link_helper.members if l.category == self.category)
+ update_combobox(self.ui.combosel_function, functions)
+ self._setup_inputs()
+
+
+if __name__ == "__main__": # pragma: nocover
+
+ from glue.main import load_plugins
+ from glue.utils.qt import get_qapp
+
+ app = get_qapp()
+ load_plugins()
+
+ from glue.core.data import Data
+ d = Data(label='test1', x=[1, 2, 3], y=[2, 3, 4], z=[3, 4, 5])
+ widget = FunctionEditorDialog(d)
+ widget.exec_()
diff --git a/glue/dialogs/component_manager/qt/function_editor.ui b/glue/dialogs/component_manager/qt/function_editor.ui
new file mode 100644
index 000000000..fd29d0a97
--- /dev/null
+++ b/glue/dialogs/component_manager/qt/function_editor.ui
@@ -0,0 +1,111 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 532
+ 402
+
+
+
+ Derived Component Editor
+
+
+
+ 5
+
+
+ 10
+
+
+ 10
+
+
+ 10
+
+
+ 10
+
+ -
+
+
-
+
+
+ -
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ Info
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ ColorizedCompletionTextEdit
+ QTextEdit
+ glue.dialogs.component_manager.qt.equation_editor
+
+
+
+
+
diff --git a/glue/plugins/coordinate_helpers/link_helpers.py b/glue/plugins/coordinate_helpers/link_helpers.py
index 7afeb82f3..7cdbe9d0e 100644
--- a/glue/plugins/coordinate_helpers/link_helpers.py
+++ b/glue/plugins/coordinate_helpers/link_helpers.py
@@ -23,9 +23,9 @@ class BaseCelestialMultiLink(MultiLink):
frame_in = None
frame_out = None
- def __init__(self, in_lon, in_lat, out_lon, out_lat):
- super(BaseCelestialMultiLink, self).__init__(in_lon, in_lat, out_lon, out_lat)
- self.create_links([in_lon, in_lat], [out_lon, out_lat],
+ def __init__(self, cids_left, cids_right):
+ super(BaseCelestialMultiLink, self).__init__(cids_left, cids_right)
+ self.create_links(cids_left, cids_right,
forwards=self.forward, backwards=self.backward)
def forward(self, in_lon, in_lat):
@@ -40,7 +40,8 @@ def backward(self, in_lon, in_lat):
@link_helper('Link Galactic and FK5 (J2000) Equatorial coordinates',
- input_labels=['l', 'b', 'ra (fk5)', 'dec (fk5)'],
+ input_labels=['l', 'b'],
+ output_labels=['ra (fk5)', 'dec (fk5)'],
category='Astronomy')
class Galactic_to_FK5(BaseCelestialMultiLink):
display = "Galactic <-> FK5 (J2000)"
@@ -49,7 +50,8 @@ class Galactic_to_FK5(BaseCelestialMultiLink):
@link_helper('Link FK4 (B1950) and FK5 (J2000) Equatorial coordinates',
- input_labels=['ra (fk4)', 'dec (fk4)', 'ra (fk5)', 'dec (fk5)'],
+ input_labels=['ra (fk4)', 'dec (fk4)'],
+ output_labels=['ra (fk5)', 'dec (fk5)'],
category='Astronomy')
class FK4_to_FK5(BaseCelestialMultiLink):
display = "FK4 (B1950) <-> FK5 (J2000)"
@@ -58,7 +60,8 @@ class FK4_to_FK5(BaseCelestialMultiLink):
@link_helper('Link ICRS and FK5 (J2000) Equatorial coordinates',
- input_labels=['ra (icrs)', 'dec (icrs)', 'ra (fk5)', 'dec (fk5)'],
+ input_labels=['ra (icrs)', 'dec (icrs)'],
+ output_labels=['ra (fk5)', 'dec (fk5)'],
category='Astronomy')
class ICRS_to_FK5(BaseCelestialMultiLink):
display = "ICRS <-> FK5 (J2000)"
@@ -67,7 +70,8 @@ class ICRS_to_FK5(BaseCelestialMultiLink):
@link_helper('Link Galactic and FK4 (B1950) Equatorial coordinates',
- input_labels=['l', 'b', 'ra (fk4)', 'dec (fk4)'],
+ input_labels=['l', 'b'],
+ output_labels=['ra (fk4)', 'dec (fk4)'],
category='Astronomy')
class Galactic_to_FK4(BaseCelestialMultiLink):
display = "Galactic <-> FK4 (B1950)"
@@ -76,7 +80,8 @@ class Galactic_to_FK4(BaseCelestialMultiLink):
@link_helper('Link ICRS and FK4 (B1950) Equatorial coordinates',
- input_labels=['ra (icrs)', 'dec (icrs)', 'ra (fk4)', 'dec (fk4)'],
+ input_labels=['ra (icrs)', 'dec (icrs)'],
+ output_labels=['ra (fk4)', 'dec (fk4)'],
category='Astronomy')
class ICRS_to_FK4(BaseCelestialMultiLink):
display = "ICRS <-> FK4 (B1950)"
@@ -85,7 +90,8 @@ class ICRS_to_FK4(BaseCelestialMultiLink):
@link_helper('Link ICRS and Galactic coordinates',
- input_labels=['ra (icrs)', 'dec (icrs)', 'l', 'b'],
+ input_labels=['ra (icrs)', 'dec (icrs)'],
+ output_labels=['l', 'b'],
category='Astronomy')
class ICRS_to_Galactic(BaseCelestialMultiLink):
display = "ICRS <-> Galactic"
@@ -94,15 +100,16 @@ class ICRS_to_Galactic(BaseCelestialMultiLink):
@link_helper('Link 3D Galactocentric and Galactic coordinates',
- input_labels=['x (kpc)', 'y (kpc)', 'z (kpc)', 'l (deg)', 'b (deg)', 'distance (kpc)'],
+ input_labels=['x (kpc)', 'y (kpc)', 'z (kpc)'],
+ output_labels=['l (deg)', 'b (deg)', 'distance (kpc)'],
category='Astronomy')
class GalactocentricToGalactic(MultiLink):
display = "3D Galactocentric <-> Galactic"
- def __init__(self, x_id, y_id, z_id, l_id, b_id, d_id):
- super(GalactocentricToGalactic, self).__init__(x_id, y_id, z_id, l_id, b_id, d_id)
- self.create_links([x_id, y_id, z_id], [l_id, b_id, d_id],
+ def __init__(self, cids_left, cids_right):
+ super(GalactocentricToGalactic, self).__init__(cids_left, cids_right)
+ self.create_links(cids_left, cids_right,
self.forward, self.backward)
def forward(self, x_kpc, y_kpc, z_kpc):
diff --git a/glue/plugins/coordinate_helpers/tests/test_link_helpers.py b/glue/plugins/coordinate_helpers/tests/test_link_helpers.py
index 145ffccc3..324f73b16 100644
--- a/glue/plugins/coordinate_helpers/tests/test_link_helpers.py
+++ b/glue/plugins/coordinate_helpers/tests/test_link_helpers.py
@@ -32,7 +32,7 @@
@pytest.mark.parametrize(('conv_class', 'expected'), list(EXPECTED.items()))
def test_conversion(conv_class, expected):
- result = conv_class(lon1, lat1, lon2, lat2)
+ result = conv_class([lon1, lat1], [lon2, lat2])
assert len(result) == 4