cand's People
cand's Issues
Intermittently occuring font-related error
Max,
I'm wondering if you can help me diagnose an issue that may or may not be idiosyncratic. I sometimes (but not always) get a font-related RuntimeError when using Canvas. I think I've found the source of the error but I'm not sure how to fix it.
Sometimes when I run a script that uses Canvas, the following statement is printed to console when writing the figure to file:
/System/Library/Fonts/Helvetica.ttc normal 7 normal roman
while other times, the following statement is printed to console:
/Library/Fonts/Helvetica.ttf normal 7 normal roman
In the latter case, the file is written successfully. In the former case, the message "The PDF backend does not currently support the selected font." is written to console followed by "RuntimeError: TrueType font is missing table". These two scenarios occur while running the exact same script. I confirmed that the PDF backend being used (module://backend_interagg) is the same in both scenarios. I don't understand how the location of the font on my file system is determined under the hood or why it randomly varies across repeated iterations.
Any advice?
Save pdf error
I get this issue when I save as a pdf. It seems to save anyhow, but I'm not sure why I’m getting it:
File "gp_intro_fig.py", line 63, in
main()
File "gp_intro_fig.py", line 60, in main
make_figure()
File "gp_intro_fig.py", line 54, in make_figure
c.save("../ThesisLatex/Chapter1/gp_intro.pdf")
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/paranoid/decorators.py", line 126, in _decorated
returnvalue = func(*args, **kwargs)
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/CanD-0.0.1-py3.6.egg/cand/canvas.py", line 866, in save
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/fitz/fitz.py", line 2686, in save
return _fitz.Document_save(self, filename, garbage, clean, deflate, incremental, ascii, expand, linear, pretty, encryption, permissions, owner_pw, user_pw)
RuntimeError: Can't do incremental writes when changing encryption
Legend title size does not get updated
Maybe it's not a CanD issue but I have not figured out why it's doing so and how to fix it. If I have a plot and want to set a fontsize, I do:
c.set_font("Lucida", size=18)
That works for all parts of the plot (which is also a bit not good -- how could I have two sizes, one for titles and one for ticks?) except for legend title. I have no idea why. Passing the size directly to matplotlib works (commented line). Here is my code and example:
from cand import Canvas, Vector, Point
import matplotlib.pyplot as plt
palette2 = ["navy", "blue", "dodgerblue","slategrey"]
# CanD
a = 6
c = Canvas(a*4+4, 20, "cm")
# set font
c.set_font("Lucida", size=18)
c.add_grid(["cond1"], 1, Point(2, 2, "cm"), Point(a*4, 18.1, "cm"), spacing=Vector(.5, 1, "cm"), unitname="grid")
# extract data
ax = c.axes["cond1"]
for i, col in enumerate(palette2):
x, y = None, None
y = np.arange(3)*i
x = np.array([1,2,3])
# plot
ax.scatter(x,y,color=col, label=f"{col}")
ax.set_xticks(x)
ax.set_ylabel("y-ax")
ax.set_xlabel("x-ax")
# ax.legend(title="Colour", fontsize=8, title_fontsize=14)
ax.legend(title="Colour")
c.show()
x-axis labels go out of picture if rotated
Hi,
If the plot has some x labels that are long and rotated, they go out of the picture and there is no obvious way to squeeze them in. Changing the y-axis limits also doesn't work - it zooms in in the graph but the relative space for the labels does not change. How can I squeeze the information there?
from cand import Canvas, Vector, Point
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
tmp = pd.DataFrame({
'labels': ['my_first_label', 'my_second_label', 'another'],
'values_mean': [5,6,7],
'values_std': [0.5, 0.4, 0.6],
})
# CanD
a = 14
b = 10
c = Canvas(a, b, "cm")
# set font
c.set_font("Arial", size=10)
# letters
c.add_text("A)", Point(.05, 0.98), weight="bold")
### GRID
c.add_grid(["barplot"], 1, Point(2, 1, "cm"), Point(a-.5, b-1, "cm"), spacing=Vector(.5, 2.5, "cm"))
# plot
c.axes["barplot"].bar(tmp['labels'], tmp['values_mean'], yerr=tmp['values_std'])
# change labels and rotation
c.axes["barplot"].set_xticks(list(c.axes["barplot"].get_xticks()))
c.axes["barplot"].set_xticklabels([x.replace('_', ' ') for x in tmp['labels'].values], rotation=90, ha='center')
# this does not help
# c.axes["barplot"].set_ylim(2,8)
c.show()
Remove show_jupyter from the documentation
c.show() has the functionality described by c.show_jupyter() in the documentation.
Function for axis sharing
Will do/done. Thanks.
I have been now playing with the sharing. It has a problem with sharing an axis more than one so chaining the previous won't work. I have made the following workaround:
if i>0:
# sharey, take the before last axis and sharey with the last plotted one, cannot share 2 axis
c.ax(a[i]).sharey(c.ax(a[i-1]))
# need to rescale all axis
c.ax(a[i]).autoscale()
# remove ticks from shared y axes
plt.setp(ax.get_yticklabels(), visible=False)
# remove ylabel
ax.set_ylabel('')
and I think it does the job but at the same time, I'm not 100 % sure that it won't break eventually, that the axis will have correct labels/ticks and scale. Could you please check?
Originally posted by @jankaWIS in #13 (comment)
Following this issue/discussion that we had, would you be interested in adding this function to CanD? I guess it could be generalised further and also adapted.
def sharey(a, source):
"""
Takes axis a that we want to share with axis source. `Update correspondingly to the type of the passed arguments.
Parameters:
a: str or matplotlib axis, axis that we want to be shared
source: str or matplotlib axis, axis that will be the source of the scale and labels
"""
if isinstance(a, str) and isinstance(source, str):
# sharey, take the first axis and sharey with the last plotted one
c.ax(a).sharey(c.ax(source))
# need to rescale all axis
c.ax(a).autoscale()
# remove ticks from shared y axes
plt.setp(c.ax(a).get_yticklabels(), visible=False)
# remove ylabel
c.ax(a).set_ylabel('')
elif isinstance(a, str) and isinstance(source, str):
# sharey, take the first axis and sharey with the last plotted one
a.sharey(source)
# need to rescale all axis
a.autoscale()
# remove ticks from shared y axes
plt.setp(a.get_yticklabels(), visible=False)
# remove ylabel
a.set_ylabel('')
else:
raise TypeError("Only strings or matplotlib axes are allowed types.")
CanD does not handle seaborn figure level plots
I'm not sure if there is a simple way for you to fix it but I have noticed that CanD
cannot handle seaborn
's figure level plots (typically FacetGrid
plots) like displot
, relplot
, catplot
(see this part of seaborn docs) since you're effectively plotting on an axis if I understand Cand correctly and those are not axis-level plots. So for example:
from cand import Canvas, Vector, Point
import seaborn as sns
df = sns.load_dataset("planets")
# Create a canvas
c = Canvas(6, 6, "inch")
# top left
c.add_axis("levels", Point(0.05, 0.05, "figure"), Point(0.45, 0.95, "figure"))
ax1 = c.ax("levels")
sns.displot(data=df, x="mass", hue="number", ax=ax1)
# Top right
c.add_axis("answers", Point(0.55, 0.05, "figure"), Point(0.95, 0.95, "figure"))
ax2 = c.ax("answers")
sns.displot(data=df, x="year", hue="method", legend=True, ax=ax2)
c.show()
will yield two seaborn warnings:
/Users/user/anaconda3/lib/python3.8/site-packages/seaborn/distributions.py:2163: UserWarning: `displot` is a figure-level function and does not accept the ax= paramter. You may wish to try histplot.
warnings.warn(msg, UserWarning)
and yield a typical problem of empty places for axes with plots below:
If one uses axes feature plots, like the recommended histplot
, all works well:
from cand import Canvas, Vector, Point
import seaborn as sns
df = sns.load_dataset("planets")
# Create a canvas
c = Canvas(12, 6, "inch")
# top left
c.add_axis("levels", Point(0.05, 0.05, "figure"), Point(0.45, 0.95, "figure"))
ax1 = c.ax("levels")
sns.histplot(data=df, x="mass", hue="number", ax=ax1)
# Top right
c.add_axis("answers", Point(0.55, 0.05, "figure"), Point(0.95, 0.95, "figure"))
ax2 = c.ax("answers")
sns.histplot(data=df, x="year", hue="method", ax=ax2)
c.show()
Would there be a way to fix this? Although some of the seaborn plots are replacible (it's possible to go around this limitation), it is often quite a pain and it would be great if one could use your package to overcome the pain of having two FacetGrids next to each other.
Thanks
Fontsizes in axes and legend don't get updated
Hi,
Maybe this is related to #14. How do you change fontsize on x and y axes? Or of a legend? I could not find any reference in the docs.
Doing c.ax("myaxis1").set_xlabel('x', fontsize=font_size)
does not change anything.
And using c.ax("myaxis1").legend(fontsize=legend_size)
somehow scales the entire box and the line length but not the text size.
font_size=18
legend_size=6
# CanD
a = 6
b = 6
c = Canvas(a, b, "cm")
# set font
c.set_font("Arial", size=10)
c.add_axis("myaxis1", Point(2, 2, "cm"), Point(5.5, 5.5, "cm"))
c.ax("myaxis1").plot([1, 2, 3], [1, 2, 3], label='b')
c.ax("myaxis1").plot([1, 2, 3], [1, 1.5, 2], label='o')
# set labels
c.ax("myaxis1").set_ylabel('y')
c.ax("myaxis1").set_xlabel('x', fontsize=font_size)
#legend
c.ax("myaxis1").legend(fontsize=legend_size)
c.show()
Thanks!
Helvetica broken with fontant
Helvetica worked for me in the long ago version I used (https://github.com/mwshinn/canvas/blob/548eeb2470fb75213b16f7df13dd46a760a23c9a/canvas.py) but no longer works for me in this version with fontant — I get this error. I’m not sure what I should do to fix this — it would be nice if this defaulted back to subpar behavior with a warning when this happened rather than refusing to run:
Warning, italic font not found
Warning, bold font not found
Warning, bold-italic font not found
Traceback (most recent call last):
File "gp_intro_fig.py", line 63, in
main()
File "gp_intro_fig.py", line 60, in main
make_figure()
File "gp_intro_fig.py", line 51, in make_figure
c.add_figure_labels([(chr(ord('A')+i), plot_names[i]) ])
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/paranoid/decorators.py", line 126, in _decorated
returnvalue = func(*args, **kwargs)
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/CanD-0.0.1-py3.6.egg/cand/canvas.py", line 648, in add_figure_labels
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/CanD-0.0.1-py3.6.egg/cand/canvas.py", line 545, in add_text
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/CanD-0.0.1-py3.6.egg/cand/canvas.py", line 181, in _get_font
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/CanD-0.0.1-py3.6.egg/cand/fontant.py", line 491, in find_font
File "/Users/jasminestone/anaconda3/envs/tf1py36/lib/python3.6/site-packages/CanD-0.0.1-py3.6.egg/cand/fontant.py", line 487, in filter_if_exists
cand.fontant.NoFontFoundError: No selected fonts have weight = "bold", options are:
"regular"
Text cannot be rotated
I'm sorry if I missed something but I cannot find it in the docs nor in the c.add_text()
help. How can I rotate text? I mean in this way, eg. by adding a rotation
keyword. Thanks.
Dark mode jupyter c.show()
In jupyter dark mode, c.show() is hard to view because the text blends in with the background. It would be good to add a light grey splash or a white splash to the background of the canvas in c.show() when used in a jupyter notebook.
Install also dependencies when installing a package
Hii @mwshinn, I have just been installing your package (on Win) and got into missing dependencies (paranoid
). I have noticed then that you're also responsible for that package. Would it be possible to install those (and possibly other) dependencies along the way as it is done eg when one uses conda or pip? Just to make it more user friendly. Besides that one just fyi I was also missing fitz
which I have not seen in the list of dependencies (I guess it's under PyMuPDF
but it's not that obvious).
Feature request: support for LaTeX-style italicization in Canvas.add_text() method
Problems with fonts
Hi, I have tried to run your example and run into two main issues:
c.set_font("Lucida Std")
raises
AttributeError: 'Canvas' object has no attribute 'set_font'
and if this is commented out, then one gets the following error at the very end:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-1d62387b4596> in <module>
32 # Save as a .pdf file, and then show the result
33 # c.save("demo_plot.pdf")
---> 34 c.show()
~/anaconda3/lib/python3.8/site-packages/cand/canvas.py in show(self, **kwargs)
866 tmp = tempfile.mkstemp('.png')[1]
867 self.tmpfiles.append(tmp)
--> 868 self.save(tmp, **kwargs)
869 # Display, either in a new window, or in Jupyter
870 if in_jupyter:
~/anaconda3/lib/python3.8/site-packages/paranoid/decorators.py in _decorated(*args, **kwargs)
124 _check_accepts(func, argvals)
125 _check_requires(func, argvals)
--> 126 returnvalue = func(*args, **kwargs)
127 _check_returns(func, returnvalue)
128 _check_ensures(func, returnvalue, argvals)
~/anaconda3/lib/python3.8/site-packages/cand/canvas.py in save(self, filename, dpi, *args, **kwargs)
709 filetype = next(ft for ft in filetypes if filename.endswith("."+ft))
710 assert (dpi is None) or filename.endswith(".png"), "DPI argument only supported for png files"
--> 711 self.fix_fonts()
712 matplotlib.rc('pdf', fonttype=42) # This embeds (rather than subsets) all fonts in PDFs.
713 # Lazy importing of matplotlib backend. See https://matplotlib.org/3.3.1/tutorials/introductory/usage.html#the-builtin-backends
~/anaconda3/lib/python3.8/site-packages/cand/canvas.py in fix_fonts(self)
575 manually as well.
576 """
--> 577 fprops = self._get_font()
578 fprops_bold = self._get_font(weight="bold")
579 fprops_it = self._get_font(style="italic")
~/anaconda3/lib/python3.8/site-packages/cand/canvas.py in _get_font(self, weight, style, size, stretch)
113 self.__class__._fm = matplotlib.font_manager.FontManager()
114 fp = matplotlib.font_manager.FontProperties(weight=weight, style=style, size=size, family=self.font, stretch=stretch)
--> 115 fontfile = self.__class__._fm.findfont(fp, fallback_to_default=False)
116 fprops = matplotlib.font_manager.FontProperties(fname=fontfile, size=size)
117 return fprops
~/anaconda3/lib/python3.8/site-packages/matplotlib/font_manager.py in findfont(self, prop, fontext, directory, fallback_to_default, rebuild_if_missing)
1309 "font.serif", "font.sans-serif", "font.cursive", "font.fantasy",
1310 "font.monospace"])
-> 1311 filename = self._findfont_cached(
1312 prop, fontext, directory, fallback_to_default, rebuild_if_missing,
1313 rc_params)
~/anaconda3/lib/python3.8/site-packages/matplotlib/font_manager.py in _findfont_cached(self, prop, fontext, directory, fallback_to_default, rebuild_if_missing, rc_params)
1361 fallback_to_default=False)
1362 else:
-> 1363 raise ValueError(f"Failed to find font {prop}, and fallback "
1364 f"to the default font was disabled")
1365 else:
ValueError: Failed to find font Helvetica Neue LT Std:style=normal:variant=normal:weight=roman:stretch=normal:size=8.0, and fallback to the default font was disabled
Any ideas about that?
Thanks.
Add to matplotlib 3rd party packages
This package looks neat and well made. I'd recommend you increase the visibility by:
- Open a PR adding it to https://matplotlib.org/3.3.3/thirdpartypackages/index.html
- add a
"Framework :: Matplotlib"
Trove classifier.
Theres also some tips on this discourse post https://discourse.matplotlib.org/t/docs-for-a-method-wrapping-a-matplotlib-method/21055/8?u=ianhi (and the replies) about making a 3rd party package. Including that you should tweet @matplotlib
about it.
Use_latex preamble issue
I get the following error when doing c.use_latex(preamble=r'\usepackage{bm}')
`/scratch/jts58/devenv/lib/python3.7/site-packages/CanD-0.0.1-py3.7.egg/cand/canvas.py:698: UserWarning: FixedFormatter should only be used together with FixedLocator
ax.set_yticklabels(labels)
AttributeError Traceback (most recent call last)
in
104
105
--> 106 make_figure()
in make_figure()
98 c.add_figure_labels([(chr(ord('A')+i), plot_names[i]) ])
99 c.ax(plot_names[i]).set_title(titles[i])
--> 100 c.show()
101 c.save("../ThesisLatex/Chapter1/Figs/Raster/gp_intro.png", dpi=300)
102 c.save("../ThesisLatex/Chapter1/Figs/Vector/gp_intro.pdf")
/scratch/jts58/devenv/lib/python3.7/site-packages/CanD-0.0.1-py3.7.egg/cand/canvas.py in show(self, **kwargs)
1008 if in_jupyter and 'transparent' not in kwargs.keys():
1009 kwargs['transparent'] = False
-> 1010 self.save(tmp, **kwargs)
1011 # Display, either in a new window, or in Jupyter
1012 if in_jupyter:
/scratch/jts58/devenv/lib/python3.7/site-packages/paranoid/decorators.py in _decorated(*args, **kwargs)
124 _check_accepts(func, argvals)
125 _check_requires(func, argvals)
--> 126 returnvalue = func(*args, **kwargs)
127 _check_returns(func, returnvalue)
128 _check_ensures(func, returnvalue, argvals)
/scratch/jts58/devenv/lib/python3.7/site-packages/CanD-0.0.1-py3.7.egg/cand/canvas.py in save(self, filename, dpi, *args, **kwargs)
806 if self.latex_preamble is not None:
807 preamble = matplotlib.rcParams.setdefault('pgf.preamble', [])
--> 808 preamble.append(self.latex_preamble)
809 elif self.backend == "default":
810 from matplotlib.backends.backend_agg import FigureCanvasAgg
AttributeError: 'str' object has no attribute 'append'`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.