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

Provide convenient way to override dimensions #714

Closed
philippjfr opened this issue Jun 7, 2016 · 10 comments
Closed

Provide convenient way to override dimensions #714

philippjfr opened this issue Jun 7, 2016 · 10 comments
Labels
type: feature A major new feature

Comments

@philippjfr
Copy link
Member

philippjfr commented Jun 7, 2016

One of the major recurring issues we are seeing is that it is fairly difficult to change any options which have been set on a Dimension object, including ranges, formatters, units etc. One easy solution to that would be to provide a convenience method on all Dimensioned objects, which traverses the object and replaces the dimensions, much like the relabel method allows setting the label and group on a nested object.

Deciding on the name and appropriate signature is the major issue here but we should also decide whether it should allow renaming dimensions, which I believe would be very useful too.

Ignoring the name of the method for now (I'll use redimension but I'm sure we can come up with something better), here are some signatures I can see being supported:

Provide a dictionary mapping from the old name to the new Dimension settings:

# As a dictionary
obj.redimension({'x': dict(name='Time', unit='s', range=(0, 100))})

# As a dimension object
obj.redimension({'x': hv.Dimension(name='Time', unit='s')})

Alternatively we can do it directly as kwargs:

# As a dictionary
obj.redimension(x=dict(name='Time', unit='s', range=(0, 100)))

# As a dimension object
obj.redimension(x=hv.Dimension(name='Time', unit='s'))

Passing a dictionary would override individual attributes, while passing a dimension would completely override the previous dimension. It could also have a depth argument (just like relabel), but I think that should be set to be infinite by default.

@jlstevens
Copy link
Contributor

jlstevens commented Jun 7, 2016

Sounds good, and I like the keyword syntax.

I know redim is not a word but then neither is redimension really. I think redim as analogous to relabel is nice and short. While we are at it, anything else X you might want to change on a HoloViews object that makes sense to have a reX method?

@philippjfr
Copy link
Member Author

I think relabel and redim are the main ones, since those are the two main things that make up a Dimensioned object.

@philippjfr
Copy link
Member Author

Just a quick note that implementing this is all very trivial except for one aspect, if we want to allow renaming of dimensions, which I'd argue for strongly, we'll have to provide a way for the data interfaces to change the name of a dimension in the underlying datastructure.

@philippjfr philippjfr added the type: feature A major new feature label Jun 7, 2016
@jbednar
Copy link
Member

jbednar commented Jun 7, 2016

I vote for redim. Changing the name of a dimension also sounds important. The kw version seems far more convenient, though it presumably only works if the name can be a Python attribute name, which I guess must be true in this case?

I know redim is not a word but then neither is redimension really.

Well... redimension, v. t.

@philippjfr
Copy link
Member Author

Sounds good. Only question to settle now is whether it should allow controlling the depth or whether it should apply throughout a nested object and what the correct default is.

@jbednar
Copy link
Member

jbednar commented Jun 7, 2016

Seems like we should do the same for relabel and redim, both in capability and in default value. I know it's been discussed, but I can't remember whether relabel allows you to control the depth.

@philippjfr
Copy link
Member Author

It does, however I'd argue that the depth behavior isn't entirely appropriate in this case. That's because many top-level objects don't in fact have any dimensions (e.g. Layout and Overlay), so in a Layout of Overlays the default depth of 0 or 1 we use for relabel will do nothing. The other thing is that unlike groups and labels a particular dimension usually occurs only at one specific level anyway so having to manually adjust the depth for what is already an unambiguous request seems awkward.

@jbednar
Copy link
Member

jbednar commented Jun 7, 2016

Sounds like redim needs to be infinitely deep by default, then?

@philippjfr
Copy link
Member Author

philippjfr commented Jun 7, 2016

Hmm, thinking about it more there is another mechanism we use to match specific objects that is currently used by the select, traverse and map methods. There you can supply a list of either types, functions, or type.group.label specs to match on, that would look something like this:

# Using types
layout.redim([hv.Points, hv.Image], x={'name': Longitude'})

# Using type.group.label specs
layout.redim(['Image.Map'], x={'name': Longitude'})

# Using a function
layout.redim([lambda el: isinstance(el, hv.Image) and 'Latitude' in el.kdims],
             x={'name': Longitude'})

Everywhere we support this I'd also enable support for supplying just a single matching criterion rather than a list of them.

@jlstevens
Copy link
Contributor

Ok, I think we can close this issue now the PR has been merged.

With specs=None by default, I believe that is essentially infinitely deep unless specified otherwise. Seems like reasonable behavior to me. Anyway, I will close this issue now, but I am happy to reopen it if we want to discuss things further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature A major new feature
Projects
None yet
Development

No branches or pull requests

3 participants