Giter Site home page Giter Site logo

cand's People

Contributors

mwshinn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

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()    

image

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()

image

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:
image

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()

image

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()

image

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).

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:

  1. Open a PR adding it to https://matplotlib.org/3.3.3/thirdpartypackages/index.html
  2. 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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.