How to show full number in plotly log scale - python

I want to add this:
I.e. the multiplier f (for femto in this case) to every tick, not only the powers of 10, as is the case already for linear scale. Is it possible to change this behavior?
I would prefer an answer that fixes this automatically by changing the behavior of Plotly, don't want to modify every tick manually.

You're trying to modify both the minor and major ticks. Right now nothing's built into Plotly's API to modify the minor tick formatting. However, I found a creative workaround.
You didn't share any programming code. I don't know if you're using a notebook or Plotly express, go, or Plotly as a backend. I don't know how your data is structured or how you called the axis to be log-scaled. That being said, without that information it's difficult to give you a solution that will regardless of what you're working with. (It's always better to share your programming code on a programming forum.)
This uses a Plotly example graph, go, and io. When I use the function io.write_html you may notice that I called several defaults to the defaults. I have to say that the Plotly documentation must not be up to date. The listed defaults are not necessarily defaulted.
This calls for a graph, and Javascript then combines the two into an HTML file that will automatically render in your default browser.
import plotly.graph_objects as go
import plotly.io as io
df = px.data.gapminder().query("year == 2002")
fig = px.scatter(df, x = "gdpPercap", y = "lifeExp", hover_name = "country", log_x = True)
js = '''
setTimeout(function() {
that = document.querySelectorAll('svg g.xtick')
that.forEach(el => el.firstChild.innerHTML = el.firstChild.innerHTML + ' f')
}, 200)
'''
io.write_html(fig = fig, file = "fig2.html", post_script = js,
full_html = True, include_plotlyjs = 'cdn', auto_open = True)
This reflects a 10k f which is something I doubt anyone would be looking for. However, it doesn't look like your data has that.

Related

Using d3.select on a python-generated object

I'm using mpld3 to create a graph in a web app. I want to allow the user to drag the orange line.
I explicitly want to code this drag-and-drop behavior directly in d3.js, because d3.js allows me to set restrictions on the drag behavior (specifically I want to allow only horizontal drag, as shows in this JSFiddle.)
I am having trouble selecting the orange line element. I am getting its ID with mpld3.utils.get_id(), but passing this id on the JS side to either d3.select() or to mpld3.get_element() does not work.
import mpld3
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-1,1,20)
fig, ax = plt.subplots()
ax.plot(x,x**3)
line = ax.plot([0,0],[-1,0])
js = '''
<script src="https://d3js.org/d3.v4.min.js"></script>
'''
html = mpld3.fig_to_html(fig)
print(mpld3.utils.get_id(line)) # gives something like 'el68722312816129664'
with open('pured3_output.html', 'w') as f:
f.write(html+js)
After opening pured3_output.html in the browser, I type this in the browser console:
>>> mpld3.get_element('el68722312816129664')
null
>>> d3.select('#el68722312816129664')
Selection {_groups: Array(1), _parents: Array(1)}
I don't know what it's returning but it's clearly not the right thing, because, d3.select('#el68722312816129664').remove() doesn't do anything.
I'm not particularly attached to using mpld3, compared to other packages built on top of d3.js, such as Plotly. I am using mpld3 so far because it seems simple and lightweight. (By the way, Plotly did not allow me to do what I wanted without touching the d3.js.). If this question is for some reason hard to solve in mpld3 (I don't see why it should be), please let me know how you would do it with a different package.

Put additional data on existing figure

I'm solving the optimization problem by different methods (for study).
The idea is written bellow:
instance = class_with_diff_methods()
instance.create_some_func()
instance.optimization_method_one()
instance.create_data_for_plot()
instance.display()
instance.optimization_method_two()
instance.create_data_for_plot()
instance.display()
So I wanted to add the new data iteratively, without saving and I implemented my idea this way:
`
import matplotlib.pyplot as plt
def display(self):
if not self.__plot_exists:
self.figure = plt.figure()
plt.scatter( self.data[0], self.data[1])
plt.plot( self.data[0], self.appdata)
self.figure.show()
self.__plot_exists = True
else:
plt.plot( self.data[0], self.appdata)
plt.show( block=False)`
This works, but the problem is that I don't really understand, why I even need (it necessary) using "self.figure" in the first part of the code and why I should use "plt.show()" instead of just "self.figure.show" at the last line.
I would be grateful for links, that will help me clearly understand how this works.
The plt.show() method is native from matplotlib, it is what launches the GUI. Check out their documentation if you would like to know about these types of things:
https://matplotlib.org/contents.html

Sympy plot _backend.ax appears as a list object, won't let me set xlabel

I'm trying to use sympy to plot an implicitly defined function in python, and have found the built-in plotting functionality to be sorely lacking. The source code recommends using _backend to directly modify the matplotlib axis and figure objects. Here's an abbreviated version of my code:
import matplotlib
from sympy import symbols, exp, plot_implicit, Eq
V,I = symbols('V I')
#define implicit equation to plot
eq1 = Eq(exp(I+V)-I,0)
#plot equation
p1 = plot_implicit(eq1, V,I)
#use _backend.ax to set xlabel and title of plot
axis = p1._backend.ax
axis.set_xlabel('Voltage (V)')
axis.set_title('ooga')
p1._backend.fig.savefig('test.png')
p1.show()
But when I run it, I get the following output:
plot generated without specified axis label and title
AttributeError: 'list' object has no attribute 'set_xlabel'
Why isn't this working? I don't understand why my axis object is being saved as a list. (Also, I find it rather odd that I get any plot output at all, as this would seem to imply the plot is being generated before I call p1.show())
Edit:
I've resolved the issue by following JohanC's recommendation to use move_sympyplot_to_axes from this post. Unfortunately I was unable to get ._backend working as intended, but this solution works well enough for my purposes.

PyCharm - Auto Completion for matplotlib (and other imported modules)

I am using PyCharm 2016.1 and Python 2.7 on Windows 10 and imported the matplotlib module.
As the matplotlib module ist very extensive and I am relatively new to Python, I hoped the Auto Complete function in PyCharm could help me to get an overview of the existent properties/ functions of an object. It would be more convenient as digging through the api documentation every time, not knowing what to look for an where to find it.
For example:
from matplotlib import pyplot as plt
fig, ax = plt.subplots()
When I type ax. there ist no auto completion for the properties, functions etc. of the axis, I only get the suggestions list.
I already tried this and imported the axis module directly with:
import matplotlib.axis as axis
or
from matplotlib.axis import Axis as axis
Smart Auto Completion and 'Collect run-time types information' is already enabled.
Is there a way to enable the auto completion like described or is there another IDE that supports that?
I believe your problem is highlighted here:
https://intellij-support.jetbrains.com/hc/en-us/community/posts/205816499-Improving-collecting-run-time-type-information-for-code-insight?sort_by=votes
Tldr return types can vary, so it cant be figured out at compile time.
Most accepted way is to use a type hint, since it can only figure out what type it as run time :
import matplotlib.axes._axes as axes
fig = plt.figure(figsize=(5,10))
ax1 = fig.add_subplot(3,1,1) # type:axes.Axes
ax1.set_xlabel('Test') <- now autocompletes
You can also try an assert isinstance:
import matplotlib.axes._axes as axes
fig = plt.figure(figsize=(5,10))
ax1 = fig.add_subplot(3,1,1)
assert isinstance(ax1, axes.Axes)
ax1.set_xlabel('Test')
It wont find the autocomplete if you do it after the method you are looking for:
ax1.set_xlabel('Test')
assert isinstance(ax1, axes.Axes)
With this, you shouldnt let isinstance dictate the control flow of your code, if you are trying to run a method that doesnt exist on an object, it should crash, however, if your different object has a method of the same name (!) then you have inadvertently reached that goal without annotations being there. So I like it better, since you want it to crash early and in the correct place. YMMV
From the doc:
Assertions should not be used to test for failure cases that can
occur because of bad user input or operating system/environment
failures, such as a file not being found. Instead, you should raise an
exception, or print an error message, or whatever is appropriate. One
important reason why assertions should only be used for self-tests of
the program is that assertions can be disabled at compile time.
If Python is started with the -O option, then assertions will be
stripped out and not evaluated. So if code uses assertions heavily,
but is performance-critical, then there is a system for turning them
off in release builds. (But don't do this unless it's really
necessary.
https://wiki.python.org/moin/UsingAssertionsEffectively
Alternatively, if you dont want to add to your code in this fashion, and have Ipython/jupyter installed through anoconda, you can get the code completion from the console by right clicking the code to be ran and choosing "execute selection in console"
In addition to Paul's answer. If you are using fig, ax = plt.subplots() , you could use figure type hint. See below example:
from matplotlib import pyplot as plt
import matplotlib.axes._axes as axes
import matplotlib.figure as figure
fig, ax = plt.subplots() # type:figure.Figure, axes.Axes
ax.
fig.

Visualizing data with matplotlib

In Matlab, you can use drawnow to view a calculation's result while it's in progress. I have tried a similar syntax in Python, both with matplotlib and mayavi.
I know it's possible to animate in one dimension with ion and set_data. However, animating in two dimensions (via imshow) is useful and I couldn't find an easy way to do that.
I know it's possible to animate using a function call but that's not as useful for algorithm development (since you can't use IPython's %run and query your program).
In matplotlib, I can use
N = 16
first_image = arange(N*N).reshape(N,N)
myobj = imshow(first_image)
for i in arange(N*N):
first_image.flat[i] = 0
myobj.set_data(first_image)
draw()
to animate an image but this script doesn't respond to <Cntrl-C> -- it hangs and disables future animations (on this machine). Despite this SO answer, different ways of invoking this animation process does not work. How do I view 2D data as it's being calculated?
EDIT: I have since made a package called python-drawnow to implement the following answer.
You just want to visualize the data from some complicated computation and not smoothly animate an image, correct? Then you can just define some simple functions:
def drawnow(draw_fig, wait_secs=1):
"""
draw_fig: (callable, no args by use of python's global scope) your
function to draw the figure. it should include the figure() call --
just like you'd normally do it. However, you must leave out the
show().
wait_secs : optional, how many seconds to wait. note that if this is 0
and your computation is fast, you don't really see the plot update.
does not work in ipy-qt. only works in the ipython shell.
"""
close()
draw_fig()
draw()
time.sleep(wait_secs)
def drawnow_init():
ion()
An example of this:
def draw_fig():
figure()
imshow(z, interpolation='nearest')
#show()
N = 16
x = linspace(-1, 1, num=N)
x, y = meshgrid(x, x)
z = x**2 + y**2
drawnow_init()
for i in arange(2*N):
z.flat[i] = 0
drawnow(draw_fig)
Notice this requires that the variables you're plotting be global. This shouldn't be a problem since it seems that the variables you want to visualize are global.
This method responds fine to cntrl-c and is visible even during fast computations (through wait_secs.

Categories