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

Update Customizing Plots Docs with more description about .options #2923

Merged
merged 10 commits into from
Aug 13, 2018

Conversation

ahuang11
Copy link
Collaborator

@ahuang11 ahuang11 commented Aug 4, 2018

Somewhat addresses #2916

This task turned out to be more difficult than I initially imagined (kudos to you guys for writing all the docs!)

There seems to be redundancy across places in the docs, and I'm not sure if it's appropriate to remove them or leave them there. Maybe it's best to wait for #2485 so it's not necessary to show other methods of customization in detail besides .options besides a brief mention? I think, that way, the documentation can be more straightforward and clear for the average user.

(I'm not sure why the muted alpha stuff is still showing as commits if it's already merged into master).

Perhaps, it's more helpful to update the FAQ or create a cheat sheet first while the core developers can discuss the best way forward for the customization docs?

@philippjfr
Copy link
Member

Thanks so much for going through these. Would you mind clearing the notebooks? Makes it easier/possible to review the changes and avoids bloating the repository.

"instance",
"_Feature"
],
"window_display": false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assume these are from various notebook extensions you have? Would you mind clearing these. Check out #1617 for a small script to do this.

"\n",
"`.opts` is essentially the Python script version of `%%opts`: in both, you'll have to manually categorize whether an option is a style, plot, or norm option.\n",
"\n",
"Ultimately, `.options` method is preferred because using `.opts` requires extreme verbosity in nested dictionaries, which can get overwhelming fast."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small typo in form of a double space here.

@philippjfr
Copy link
Member

philippjfr commented Aug 4, 2018

These changes look great to me, just had two small comments.

@ahuang11
Copy link
Collaborator Author

ahuang11 commented Aug 4, 2018

I'm having trouble with using jq to clear the notebook output (presumably because I'm using a Windows Subystem Linux). Maybe you can help me do it?

I tried installing from sudo apt-get install jq and also conda install jq; both end up jq: 1 compile error

@philippjfr
Copy link
Member

For now you could just push the changes in this commit to your branch: 68b23ed

Not sure what's wrong with jq but it would be good to work out a cross-platform solution.

@philippjfr
Copy link
Member

I'm happy to see this merged but will give @jbednar and @jlstevens a chance to review.

Copy link
Member

@jbednar jbednar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

"cell_type": "markdown",
"metadata": {},
"source": [
"Here it is, again, with the `.options` method, which is the simplest way of customizing because it will automatically deduce whether an option is a style, plot, or norm option. In addition, `.options` is portable across notebook environments and `.py` scripts, and also will be saved on export, unlike `%%opts`."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean to be "saved on export"? To a .py script? If so, maybe "is portable across notebook environments and .py scripts, including exporting the notebook to a .py file, unlike %%opts.".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

I remember when I first started using HoloViews, this was one of the main issues I encountered, and I had little clue on how to use port the magic to .py script.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, here you need to move hv.renderer to a subsequent cell. The %%opts cell magic is only applied to the output of the cell, when it's displayed, not to everything in it.

Copy link
Collaborator Author

@ahuang11 ahuang11 Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I understand that's only applied to the output of the cell (if I wanted to do the whole notebook I believe I can do %opts).

However, my point with this statement:
also will be saved on export, unlike %%opts`
is that when you do a renderer.save() on objects modified by cell magic, the options don't embed into the saved.html unlike using the .options()

obj = obj.options(width=1000)
hv.renderer('bokeh').save(obj, 'test2')
display(HTML('test2.html'))  # this will have width = 1000 embedded in the html

So I guess to clarify, I should reword to

and also will be embbed to the export file, unlike `%%opts`."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I wasn't clear -- renderer.save() should keep all options that have been modified on the object; if it didn't, that would be a very strange bug. But the point here is that you're doing renderer.save() on an object that has not yet been modified by cell magic, which is why you are failing to see any effect. At that point, the cell magic application is still in the future! You have to do the renderer.save() after the cell has been displayed, because cell magics are applied only on the output of the cell, which hasn't yet occurred by the time you are saving it. So all of the wordings you are suggesting are incorrect; %%opts does change the object in a way that will export; you just have to make sure that (a) the object is in fact affected by the cell magic (by returning it as the output of the cell), and (b) that you don't save it until after it has been returned as the output of the cell. Does that make sense now?

Copy link
Collaborator Author

@ahuang11 ahuang11 Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks for clarifying! I see your point now and learned something new! I wonder if I'm the only one who encountered this before? If not maybe should have it as another FAQ?

"
Q: Why isn't my %%opts magic applied when exported?
A: You're probably doing renderer.save() on an object that has not yet been modified by cell magic, which is why you are failing to see any effect. At that point, the cell magic application is still in the future! You have to do the renderer.save() after the cell has been displayed, because cell magics are applied only on the output of the cell, which hasn't yet occurred by the time you are saving it. So all of the wordings you are suggesting are incorrect; %%opts does change the object in a way that will export; you just have to make sure that (a) the object is in fact affected by the cell magic (by returning it as the output of the cell), and (b) that you don't save it until after it has been returned as the output of the cell. Does that make sense now?
"

image

Copy link
Member

@jbednar jbednar Aug 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make it more general:

Q: Why isn't my %%opts cell magic being applied to my HoloViews object?
A: %%opts is convenient because it tab-completes, but it can be confusing because of the "magic" way that it works. Specifically, if you use it at the top of a Jupyter notebook cell, the indicated options will be applied to the return value of that cell, if it's a HoloViews object. So, if you want a given object to get customized, you need to make sure it is returned from the cell, or the options won't ever be applied, and you should only access it after it has been returned, or the options won't yet have been applied. For instance, if you use renderer.save() to export an object and only then return that object as the output of a cell, the exported object won't have the options applied, because they don't get applied until the object is returned (during IPython's "display hooks" processing). So to make sure that options get applied, (a) return the object from a cell, and then (b) access it (e.g. for exporting) after the object has been returned. To avoid confusion, you may prefer to use .options() directly on the object to ensure that the options have been applied before exporting.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, another FAQ:

Q: Why are my .options() settings not having any effect?
A: By default, .options() returns a copy of your object, rather than modifying your original object. In HoloViews, making a copy of the object is cheap, because only the metadata is copied, not the data, and returning a copy makes it simple to work with a variety of differently customized versions of any given object. You can pass clone=False to .options() if you wish to modify the object in place.

"cell_type": "markdown",
"metadata": {},
"source": [
"When using ``.options`` to apply options directly to an individual object we do not have to explicitly declare which object the options apply to, however often it is useful to set options on a composite object. In these cases the options can be declared as a dictionary of the type name and the options. The code below is therefore equivalent to the syntax we used above:"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@philippjfr, does .options only accept a type name, or does it also accept a fully qualified type.group.label string?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type.group.label is valid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that's what I thought. The text needs to be updated here to reflect that.

@philippjfr philippjfr merged commit 86e9202 into holoviz:master Aug 13, 2018
@jbednar
Copy link
Member

jbednar commented Aug 13, 2018

Thanks, @ahuang11!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants