Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Fixed derived components #1488

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions glue/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,28 +615,28 @@ 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.

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

Expand Down
15 changes: 9 additions & 6 deletions glue/core/link_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand Down
62 changes: 62 additions & 0 deletions glue/dialogs/component_manager/qt/derived_creator.py
Original file line number Diff line number Diff line change
@@ -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_()
157 changes: 157 additions & 0 deletions glue/dialogs/component_manager/qt/derived_creator.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>535</width>
<height>378</height>
</rect>
</property>
<property name="windowTitle">
<string>Derived Component Editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>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.</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QTabWidget" name="tab">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_predefined">
<attribute name="title">
<string>Pre-defined transformations</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
</layout>
</widget>
<widget class="QWidget" name="tab_freeform">
<attribute name="title">
<string>Free-from expression</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_status">
<property name="text">
<string>status</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="button_cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_ok">
<property name="text">
<string>OK</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
Loading