holoviz-topics / EarthSim

Tools for working with and visualizing environmental simulations.
https://earthsim.holoviz.org
BSD 3-Clause "New" or "Revised" License
65 stars 21 forks source link

implementing param depends #250

Closed kcpevey closed 5 years ago

kcpevey commented 5 years ago

Seems like panels interact() is handy, but from what I've seen in the panel docs https://panel.pyviz.org/user_guide/Interact.html I don't understand how it relates to the previous discussions on @depends. Namely how you get the dependency between existing param objects (I don't want to interact to generate them on the fly).

I guess I'm just still struggling understand and implementing param dependencies. Are there any more notebook examples I can take a look at?

philippjfr commented 5 years ago

Namely how you get the dependency between existing param objects (I don't want to interact to generate them on the fly).

The interact functionality is an alternative to the class/param based approach for people not familiar with parameterized objects and classes. So the two approaches are completely orthogonal.

I guess I'm just still struggling understand and implementing param dependencies.

I've started to write some documentation and examples but am struggling coming up with examples that are simple, interesting and get the point across. In any case I'll add something to the Param user guide later today or tomorrow.

kcpevey commented 5 years ago

simple example:

class projections(param.Parameterized):
    projection      = param.ObjectSelector(default="UTM", objects=["Geographic", "Mercator", "UTM"], precedence=1)
    UTM_zone_hemi   = param.ObjectSelector(default='North', objects=['North', 'South'], precedence=2)
    UTM_zone_num    = param.Integer(52, bounds=(1, 60), precedence=3)

    def get_crs(self):
        if self.projection == 'UTM':
            if self.UTM_zone_hemi == 'South':
                hemi = True
            else:
                hemi = False
            proj = ccrs.UTM(self.UTM_zone_num, southern_hemisphere=hemi)

        elif self.projection == 'Geographic':
            proj = ccrs.PlateCarree()

        elif self.projection == 'Mercator':
            proj = ccrs.GOOGLE_MERCATOR

        return proj

If projection=='UTM', then I want UTM_zone_hemi and UTM_zone_num to appear, otherwise, they should remain hidden.

Tagging @JoshuaQChurch since I asked him about this too

philippjfr commented 5 years ago

If projection=='UTM', then I want UTM_zone_hemi and UTM_zone_num to appear, otherwise, they should remain hidden.

To clarify, you want this to appear where? Or to ask a different way, what will be consuming the output of get_crs?

kcpevey commented 5 years ago

I want UTM_zone_hemi and UTM_zone_num widgets to be hidden until projection='UTM'. Those widgets can appear right under projection.

get_crs is a method I use later to convert the widget input to a ccrs projection (which becomes input to the crs parameter in annotators or gv maps).

Does that answer your question?

philippjfr commented 5 years ago

Yes, thanks. So hiding it dynamically is currently not supported (but probably could be by dynamically setting the precedence). For now you could simply make them constant like this:

class projections(param.Parameterized):
    projection      = param.ObjectSelector(default="UTM", objects=["Geographic", "Mercator", "UTM"], precedence=1)
    UTM_zone_hemi   = param.ObjectSelector(default='North', objects=['North', 'South'], precedence=2)
    UTM_zone_num    = param.Integer(52, bounds=(1, 60), precedence=3)

    @param.depends('projection', watch=True)
    def _watch_utm_projection(self):
        is_utm = self.projection == 'UTM'
        self.params('UTM_zone_hemi').constant = not is_utm
        self.params('UTM_zone_num').constant = not is_utm

    def get_crs(self):
        if self.projection == 'UTM':
            if self.UTM_zone_hemi == 'South':
                hemi = True
            else:
                hemi = False
            proj = ccrs.UTM(self.UTM_zone_num, southern_hemisphere=hemi)

        elif self.projection == 'Geographic':
            proj = ccrs.PlateCarree()

        elif self.projection == 'Mercator':
            proj = ccrs.GOOGLE_MERCATOR

        return proj
kcpevey commented 5 years ago

What is this supposed to do? UTM_zone_hemi and UTM_zone_num behave the same regardless of the selection on projection.

Also - I know I've seen a demo of menus appearing and disappearing based on a selection in a demo. What am I thinking of? Do I just need to reorganize these into two classes?

philippjfr commented 5 years ago

What is this supposed to do?

When rendered using panel, the widgets should be disabled when self.projection != 'UTM' and look something like this:

screen shot 2018-10-17 at 3 31 32 pm

kcpevey commented 5 years ago

That is not happening for me. I last updated all my packages to master on Friday I think. I might be out of date. I'll update and recheck.

philippjfr commented 5 years ago

Also - I know I've seen a demo of menus appearing and disappearing based on a selection in a demo. What am I thinking of? Do I just need to reorganize these into two classes?

That's right, that works by having one parameterized instance being a parameter value on another parameterized.

kcpevey commented 5 years ago

Still not working for me.

screen shot 2018-10-17 at 9 45 43 am

panel 0.1.2.post3+g8ecccf4.dirty param 1.8.1

This isn't relying on any other packages, is it?

philippjfr commented 5 years ago

You need to make an instance of the class for this to work.

kcpevey commented 5 years ago

works for me.