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

Support .collate for DynamicMaps? #1188

Closed
jbednar opened this Issue Mar 10, 2017 · 6 comments

Comments

Projects
None yet
3 participants
@jbednar
Copy link
Contributor

jbednar commented Mar 10, 2017

The example on the holoviews.org home page shows how to use .collate() to turn the illegal "HoloMap of Layouts" construction into the displayable "Layout of HoloMaps", which is very convenient in practice. However, .collate() does not seem to be supported for DynamicMaps.

Here's an example of what I'd want to use that for:

import numpy as np
import holoviews as hv
import imagen as ig
import imagen.transferfn as tf

from imagen.image import FileImage
from imagen.transferfn.sheet_tf import Convolve

hv.notebook_extension()

%opts Image (cmap="gray") {+axiswise}

FileImage.filename = "/Users/jbednar/imagen/doc/images/ellen_arthur.pgm"

kdims = [hv.Dimension('size',                   range=(0.1, 2)),
         hv.Dimension('positive_size',          range=(0.1, 2)),
         hv.Dimension('negative_size',          range=(0.3, 4)),
         hv.Dimension('positive_aspect_ratio',  range=(1.0,10)),
         hv.Dimension('negative_aspect_ratio',  range=(1.0,10))]

Right now, I can easily view one static image along with a slider-controlled dynamic map, but I have to pick a single HoloViews object to return from the callback:

def filtered_images(size,positive_size,negative_size,positive_aspect_ratio,negative_aspect_ratio):
    convolver = Convolve(kernel_pattern=ig.DifferenceOfGaussians(**locals()))
    return FileImage(output_fns=[convolver])[:]

FileImage()[:] + hv.DynamicMap(filtered_images, kdims=kdims)

image

def filtered_images(size,positive_size,negative_size,positive_aspect_ratio,negative_aspect_ratio):
    convolver = Convolve(kernel_pattern=ig.DifferenceOfGaussians(**locals()))
    return convolver.kernel_pattern[:]

FileImage()[:] + hv.DynamicMap(filtered_images, kdims=kdims)

image

But what I want is to make one single callback that returns a Layout of both the two dynamic plots above:

def filtered_images(size,positive_size,negative_size,positive_aspect_ratio,negative_aspect_ratio):
    convolver = Convolve(kernel_pattern=ig.DifferenceOfGaussians(**locals()))
    return convolver.kernel_pattern[:] + FileImage(output_fns=[convolver])[:]

FileImage()[:] + hv.DynamicMap(filtered_images, kdims=kdims).collate()

Unfortunately, that doesn't work, whether I call .collate() (see output below) or not. Of course, I can construct multiple DynamicMaps, using multiple callbacks, but they both need to share the same kernel_pattern state, so I'd also need to make a class to hold that state and change the callbacks to be methods on the object with the shared state. That's ugly, a lot of code, and a pain to set up. Can we just make .collate() work on DynamicMaps, and then people can write one callback to handle all the dynamic stuff in a given final Layout?

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-3c23b390e441> in <module>()
      3     return convolver.kernel_pattern[:] + FileImage(output_fns=[convolver])[:]
      4 
----> 5 FileImage()[:] + hv.DynamicMap(filtered_images, kdims=kdims).collate()

/Users/jbednar/holoviews_git/holoviews/core/spaces.pyc in collate(self, merge_type, drop, drop_constant)
    255         merge_type=merge_type if merge_type else self.__class__
    256         return Collator(self, merge_type=merge_type, drop=drop,
--> 257                         drop_constant=drop_constant)()
    258 
    259 

/Users/jbednar/holoviews_git/holoviews/core/element.pyc in __call__(self)
    592 
    593         components = ndmapping.values()
--> 594         accumulator = ndmapping.last.clone(components[0].data)
    595         for component in components:
    596             accumulator.update(component)

AttributeError: 'NoneType' object has no attribute 'clone'

@jbednar jbednar added the feature label Mar 10, 2017

@jlstevens jlstevens added this to the v1.7.0 milestone Mar 10, 2017

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Mar 10, 2017

A dynamic collate should be something we try to get ready for 1.7. I agree it is important and we can shift the assigned milestone if it turns out to be too tricky.

@philippjfr

This comment has been minimized.

Copy link
Contributor

philippjfr commented Apr 5, 2017

Now implemented, assigning to @jlstevens to document.

@philippjfr philippjfr assigned jlstevens and unassigned philippjfr Apr 5, 2017

@jlstevens

This comment has been minimized.

Copy link
Contributor

jlstevens commented Apr 5, 2017

Now implemented, assigning to @jlstevens to document.

Will do!

@philippjfr

This comment has been minimized.

Copy link
Contributor

philippjfr commented Apr 5, 2017

I'll try to come up with an example.

@jbednar

This comment has been minimized.

Copy link
Contributor Author

jbednar commented Apr 6, 2017

As a start, can you show how to make the above code work? I just tried with the latest master and the same code that didn't work above with or without .collate() still doesn't work with or without .collate(), and it still doesn't give a very useful error message. Are there now arguments that I need to pass to determine how the streams line up, and are there ways the error messages could guide me towards adding those?

@philippjfr philippjfr assigned philippjfr and unassigned jlstevens Apr 10, 2017

@philippjfr

This comment has been minimized.

Copy link
Contributor

philippjfr commented Apr 12, 2017

This has now been implemented and I fixed a bug related to adding more plots to a collated Layout. Going to close this and will be adding some examples to our list of stream examples.

@philippjfr philippjfr closed this Apr 12, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.