FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment · Issue #4900 · matplotlib/matplotlib · GitHub

Repository navigation

UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment #4900

Closed

Description

plt.clf()
fig, ax = plt.subplots(1,2, sharey=True)
plt.setp(ax.flat, aspect=1.0, adjustable='box-forced')
#fig.set_size_inches(16,8)
sns.despine(fig=fig)
#scale = 'logit'
scale = None
plot.plot_year_dist(df_mesh[(df_mesh['Year'] >= min_y) & (df_mesh['Year'] <= 2009)],col='min_VolFirstP',col_label="Year",thresh=10,file_prefix='individual_', ax=ax[0],color=sns.xkcd_rgb['black'],label='Individual Volume [%s-2009]' % min_y,marker="o", scale = scale)
plot.plot_year_dist(df[(df['Year'] >= min_y) & (df['Year'] <= 2009)],col='min_VolFirstP',col_label="Year",thresh=10,file_prefix='pair_', ax=ax[0],color=sns.xkcd_rgb['red'],label='Pair Volume [%s-2009]' % min_y, marker="s", scale = scale)


plot.plot_year_dist(df_mesh[(df_mesh['Year'] >= min_y) & (df_mesh['Year'] <= 2009)],col='min_TFirstP',col_label="Years",thresh=3,file_prefix='individual_', ax=ax[1],color=sns.xkcd_rgb['black'],label='Individual Time [%s-2009]' % min_y,marker="o", scale = scale)
plot.plot_year_dist(df[(df['Year'] >= min_y) & (df['Year'] <= 2009)],col='min_TFirstP',col_label="Years",thresh=3,file_prefix='pair_', ax=ax[1],color=sns.xkcd_rgb['red'],label='Pair Time [%s-2009]' % min_y,marker="s", scale = scale)

for i in range(2):
    ax[i].set_yscale("logit", p_min=1e-4)
    ax[i].legend(bbox_to_anchor=(0., 1.02, 1., .102), borderaxespad=0., frameon=True, fancybox=True)

plt.savefig("temp.pdf",bbox_inches='tight')

When running the above code I am getting the following error:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-75-76bd951dfd46> in <module>()
     19 
     20 
---> 21 plt.savefig("Novelty_year_dist_logit.pdf",bbox_inches='tight')
     22 plt.savefig("Novelty_year_dist_logit.eps",bbox_inches='tight')

/usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in savefig(*args, **kwargs)
    575 def savefig(*args, **kwargs):
    576     fig = gcf()
--> 577     res = fig.savefig(*args, **kwargs)
    578     draw()   # need this if 'transparent=True' to reset colors
    579     return res

/usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in savefig(self, *args, **kwargs)
   1474             self.set_frameon(frameon)
   1475 
-> 1476         self.canvas.print_figure(*args, **kwargs)
   1477 
   1478         if frameon:

/usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.pyc in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2156                     orientation=orientation,
   2157                     dryrun=True,
-> 2158                     **kwargs)
   2159                 renderer = self.figure._cachedRenderer
   2160                 bbox_inches = self.figure.get_tightbbox(renderer)

/usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_pdf.pyc in print_pdf(self, filename, **kwargs)
   2483                 RendererPdf(file, image_dpi),
   2484                 bbox_inches_restore=_bbox_inches_restore)
-> 2485             self.figure.draw(renderer)
   2486             renderer.finalize()
   2487         finally:

/usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, *args, **kwargs)
     57     def draw_wrapper(artist, renderer, *args, **kwargs):
     58         before(artist, renderer)
---> 59         draw(artist, renderer, *args, **kwargs)
     60         after(artist, renderer)
     61 

/usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in draw(self, renderer)
   1083         dsu.sort(key=itemgetter(0))
   1084         for zorder, a, func, args in dsu:
-> 1085             func(*args)
   1086 
   1087         renderer.close_group('figure')

/usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, *args, **kwargs)
     57     def draw_wrapper(artist, renderer, *args, **kwargs):
     58         before(artist, renderer)
---> 59         draw(artist, renderer, *args, **kwargs)
     60         after(artist, renderer)
     61 

/usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in draw(self, renderer, inframe)
   2004             self.apply_aspect(pos)
   2005         else:
-> 2006             self.apply_aspect()
   2007 
   2008         artists = []

/usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in apply_aspect(self, position)
   1191         fig_aspect = figH / figW
   1192         if self._adjustable in ['box', 'box-forced']:
-> 1193             if aspect_scale_mode == "log":
   1194                 box_aspect = A * self.get_data_ratio_log()
   1195             else:

UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment

However, running the example explained in http://stackoverflow.com/a/13663328/1650159 doesn't give this error.

Additional Info:

def plot_year_dist(df,col='',col_label="",thresh=0,file_prefix='',outFolder=DEFAULT_OUTPUT,\
    ax=None,color=sns.xkcd_rgb['black'],label='',scale=None,**kwargs):
  saveFig = False
  if ax is None:
    plt.clf()
    ax = plt.gca()
    saveFig = True
  filename = file_prefix+col+"_year_dist.png"
  df_g = df[[col,'Year']].groupby('Year').count()
  df_g["filtered"] = df[[col,"Year"]][df[col] <= thresh].groupby("Year").count()
  df_g["prop"] = df_g["filtered"]/df_g[col]
  #print df_g.index
  #print df_g
  x = df_g.index.values
  y = df_g["prop"].values
  if scale == 'logit':
    y = np.log10(y/(1.0-y))

  ax.plot(x,y, linestyle='-',markersize=3.0,color=color,label=label,**kwargs)

  print "Finished generating histogram"
  ax.set_xlabel(col_label)
  ax.set_ylabel("Proportion (<= %s)" % thresh)
  if scale == 'logit':
    ax.set_ylabel("$log_{10}(p/1-p)$ [$p = P(X<= %s)$]" % thresh)
  if saveFig:
    plt.savefig(outFolder+"/"+filename)
  print "Plot saved in %s." % (filename)

Activity

  1. WeatherGod commented on Aug 11, 2015

    Member

    Looks like this piece of code is the problem part:

            if self.name != 'polar':
                xscale, yscale = self.get_xscale(), self.get_yscale()
                if xscale == "linear" and yscale == "linear":
                    aspect_scale_mode = "linear"
                elif xscale == "log" and yscale == "log":
                    aspect_scale_mode = "log"
                elif ((xscale == "linear" and yscale == "log") or
                      (xscale == "log" and yscale == "linear")):
                    if aspect != "auto":
                        warnings.warn(
                            'aspect is not supported for Axes with xscale=%s, '
                            'yscale=%s' % (xscale, yscale))
                        aspect = "auto"
                else:  # some custom projections have their own scales.
                    pass
            else:
                aspect_scale_mode = "linear"
    

    It has two branches where aspect_scale_mode is left undefined. Probably
    have it set to None or something like that. I'll put together a PR.

    On Tue, Aug 11, 2015 at 6:31 AM, Shubhanshu Mishra <notifications@github.com

    wrote:

    plt.clf()
    fig, ax = plt.subplots(1,2, sharey=True)
    plt.setp(ax.flat, aspect=1.0, adjustable='box-forced')#fig.set_size_inches(16,8)
    sns.despine(fig=fig)#scale = 'logit'
    scale = None
    plot.plot_year_dist(df_mesh[(df_mesh['Year'] >= min_y) & (df_mesh['Year'] <= 2009)],col='min_VolFirstP',col_label="Year",thresh=10,file_prefix='individual_', ax=ax[0],color=sns.xkcd_rgb['black'],label='Individual Volume [%s-2009]' % min_y,marker="o", scale = scale)
    plot.plot_year_dist(df[(df['Year'] >= min_y) & (df['Year'] <= 2009)],col='min_VolFirstP',col_label="Year",thresh=10,file_prefix='pair_', ax=ax[0],color=sns.xkcd_rgb['red'],label='Pair Volume [%s-2009]' % min_y, marker="s", scale = scale)

    plot.plot_year_dist(df_mesh[(df_mesh['Year'] >= min_y) & (df_mesh['Year'] <= 2009)],col='min_TFirstP',col_label="Years",thresh=3,file_prefix='individual_', ax=ax[1],color=sns.xkcd_rgb['black'],label='Individual Time [%s-2009]' % min_y,marker="o", scale = scale)
    plot.plot_year_dist(df[(df['Year'] >= min_y) & (df['Year'] <= 2009)],col='min_TFirstP',col_label="Years",thresh=3,file_prefix='pair_', ax=ax[1],color=sns.xkcd_rgb['red'],label='Pair Time [%s-2009]' % min_y,marker="s", scale = scale)
    for i in range(2):
    ax[i].set_yscale("logit", p_min=1e-4)
    ax[i].legend(bbox_to_anchor=(0., 1.02, 1., .102), borderaxespad=0., frameon=True, fancybox=True)

    plt.savefig("temp.pdf",bbox_inches='tight')

    When running the above code I am getting the following error:


    UnboundLocalError Traceback (most recent call last)
    in ()
    19
    20
    ---> 21 plt.savefig("Novelty_year_dist_logit.pdf",bbox_inches='tight')
    22 plt.savefig("Novelty_year_dist_logit.eps",bbox_inches='tight')

    /usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in savefig(_args, *_kwargs)
    575 def savefig(_args, *_kwargs):
    576 fig = gcf()
    --> 577 res = fig.savefig(_args, *_kwargs)
    578 draw() # need this if 'transparent=True' to reset colors
    579 return res

    /usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in savefig(self, _args, *_kwargs)
    1474 self.set_frameon(frameon)
    1475
    -> 1476 self.canvas.print_figure(_args, *_kwargs)
    1477
    1478 if frameon:

    /usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.pyc in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, *_kwargs)
    2156 orientation=orientation,
    2157 dryrun=True,
    -> 2158 *_kwargs)
    2159 renderer = self.figure._cachedRenderer
    2160 bbox_inches = self.figure.get_tightbbox(renderer)

    /usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_pdf.pyc in print_pdf(self, filename, **kwargs)
    2483 RendererPdf(file, image_dpi),
    2484 bbox_inches_restore=_bbox_inches_restore)
    -> 2485 self.figure.draw(renderer)
    2486 renderer.finalize()
    2487 finally:

    /usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, _args, *_kwargs)
    57 def draw_wrapper(artist, renderer, _args, *_kwargs):
    58 before(artist, renderer)
    ---> 59 draw(artist, renderer, _args, *_kwargs)
    60 after(artist, renderer)
    61

    /usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in draw(self, renderer)
    1083 dsu.sort(key=itemgetter(0))
    1084 for zorder, a, func, args in dsu:
    -> 1085 func(*args)
    1086
    1087 renderer.close_group('figure')

    /usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, _args, *_kwargs)
    57 def draw_wrapper(artist, renderer, _args, *_kwargs):
    58 before(artist, renderer)
    ---> 59 draw(artist, renderer, _args, *_kwargs)
    60 after(artist, renderer)
    61

    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in draw(self, renderer, inframe)
    2004 self.apply_aspect(pos)
    2005 else:
    -> 2006 self.apply_aspect()
    2007
    2008 artists = []

    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in apply_aspect(self, position)
    1191 fig_aspect = figH / figW
    1192 if self._adjustable in ['box', 'box-forced']:
    -> 1193 if aspect_scale_mode == "log":
    1194 box_aspect = A * self.get_data_ratio_log()
    1195 else:

    UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment

    However, running the example explained in
    http://stackoverflow.com/a/13663328/1650159 doesn't give this error.

    Additional Info:

    def plot_year_dist(df,col='',col_label="",thresh=0,file_prefix='',outFolder=DEFAULT_OUTPUT,
    ax=None,color=sns.xkcd_rgb['black'],label='',scale=None,**kwargs):
    saveFig = False
    if ax is None:
    plt.clf()
    ax = plt.gca()
    saveFig = True
    filename = file_prefix+col+"_year_dist.png"
    df_g = df[[col,'Year']].groupby('Year').count()
    df_g["filtered"] = df[[col,"Year"]][df[col] <= thresh].groupby("Year").count()
    df_g["prop"] = df_g["filtered"]/df_g[col]
    #print df_g.index
    #print df_g
    x = df_g.index.values
    y = df_g["prop"].values
    if scale == 'logit':
    y = np.log10(y/(1.0-y))

    ax.plot(x,y, linestyle='-',markersize=3.0,color=color,label=label,**kwargs)

    print "Finished generating histogram"
    ax.set_xlabel(col_label)
    ax.set_ylabel("Proportion (<= %s)" % thresh)
    if scale == 'logit':
    ax.set_ylabel("$log_{10}(p/1-p)$ [$p = P(X<= %s)$]" % thresh)
    if saveFig:
    plt.savefig(outFolder+"/"+filename)
    print "Plot saved in %s." % (filename)

    —
    Reply to this email directly or view it on GitHub
    #4900.

  2. WeatherGod commented on Aug 11, 2015

    Member

    I just tried making a test based off of your example, but I don't know 1)
    the scale of your data and 2) the p_min argument doesn't seem to be valid.
    I am not sure how that works for you. Could you try making a more
    simplified version of your script that demonstrates the problem and can
    easily be made into a test.

    On Tue, Aug 11, 2015 at 8:56 AM, Benjamin Root ben.root@ou.edu wrote:

    Looks like this piece of code is the problem part:

            if self.name != 'polar':
                xscale, yscale = self.get_xscale(), self.get_yscale()
                if xscale == "linear" and yscale == "linear":
                    aspect_scale_mode = "linear"
                elif xscale == "log" and yscale == "log":
                    aspect_scale_mode = "log"
                elif ((xscale == "linear" and yscale == "log") or
                      (xscale == "log" and yscale == "linear")):
                    if aspect != "auto":
                        warnings.warn(
                            'aspect is not supported for Axes with xscale=%s, '
                            'yscale=%s' % (xscale, yscale))
                        aspect = "auto"
                else:  # some custom projections have their own scales.
                    pass
            else:
                aspect_scale_mode = "linear"
    

    It has two branches where aspect_scale_mode is left undefined. Probably
    have it set to None or something like that. I'll put together a PR.

    On Tue, Aug 11, 2015 at 6:31 AM, Shubhanshu Mishra <
    notifications@github.com> wrote:

    plt.clf()
    fig, ax = plt.subplots(1,2, sharey=True)
    plt.setp(ax.flat, aspect=1.0, adjustable='box-forced')#fig.set_size_inches(16,8)
    sns.despine(fig=fig)#scale = 'logit'
    scale = None
    plot.plot_year_dist(df_mesh[(df_mesh['Year'] >= min_y) & (df_mesh['Year'] <= 2009)],col='min_VolFirstP',col_label="Year",thresh=10,file_prefix='individual_', ax=ax[0],color=sns.xkcd_rgb['black'],label='Individual Volume [%s-2009]' % min_y,marker="o", scale = scale)
    plot.plot_year_dist(df[(df['Year'] >= min_y) & (df['Year'] <= 2009)],col='min_VolFirstP',col_label="Year",thresh=10,file_prefix='pair_', ax=ax[0],color=sns.xkcd_rgb['red'],label='Pair Volume [%s-2009]' % min_y, marker="s", scale = scale)

    plot.plot_year_dist(df_mesh[(df_mesh['Year'] >= min_y) & (df_mesh['Year'] <= 2009)],col='min_TFirstP',col_label="Years",thresh=3,file_prefix='individual_', ax=ax[1],color=sns.xkcd_rgb['black'],label='Individual Time [%s-2009]' % min_y,marker="o", scale = scale)
    plot.plot_year_dist(df[(df['Year'] >= min_y) & (df['Year'] <= 2009)],col='min_TFirstP',col_label="Years",thresh=3,file_prefix='pair_', ax=ax[1],color=sns.xkcd_rgb['red'],label='Pair Time [%s-2009]' % min_y,marker="s", scale = scale)
    for i in range(2):
    ax[i].set_yscale("logit", p_min=1e-4)
    ax[i].legend(bbox_to_anchor=(0., 1.02, 1., .102), borderaxespad=0., frameon=True, fancybox=True)

    plt.savefig("temp.pdf",bbox_inches='tight')

    When running the above code I am getting the following error:


    UnboundLocalError Traceback (most recent call last)
    in ()
    19
    20
    ---> 21 plt.savefig("Novelty_year_dist_logit.pdf",bbox_inches='tight')
    22 plt.savefig("Novelty_year_dist_logit.eps",bbox_inches='tight')

    /usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in savefig(_args, *_kwargs)
    575 def savefig(_args, *_kwargs):
    576 fig = gcf()
    --> 577 res = fig.savefig(_args, *_kwargs)
    578 draw() # need this if 'transparent=True' to reset colors
    579 return res

    /usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in savefig(self, _args, *_kwargs)
    1474 self.set_frameon(frameon)
    1475
    -> 1476 self.canvas.print_figure(_args, *_kwargs)
    1477
    1478 if frameon:

    /usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.pyc in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, *_kwargs)
    2156 orientation=orientation,
    2157 dryrun=True,
    -> 2158 *_kwargs)
    2159 renderer = self.figure._cachedRenderer
    2160 bbox_inches = self.figure.get_tightbbox(renderer)

    /usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_pdf.pyc in print_pdf(self, filename, **kwargs)
    2483 RendererPdf(file, image_dpi),
    2484 bbox_inches_restore=_bbox_inches_restore)
    -> 2485 self.figure.draw(renderer)
    2486 renderer.finalize()
    2487 finally:

    /usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, _args, *_kwargs)
    57 def draw_wrapper(artist, renderer, _args, *_kwargs):
    58 before(artist, renderer)
    ---> 59 draw(artist, renderer, _args, *_kwargs)
    60 after(artist, renderer)
    61

    /usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in draw(self, renderer)
    1083 dsu.sort(key=itemgetter(0))
    1084 for zorder, a, func, args in dsu:
    -> 1085 func(*args)
    1086
    1087 renderer.close_group('figure')

    /usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, _args, *_kwargs)
    57 def draw_wrapper(artist, renderer, _args, *_kwargs):
    58 before(artist, renderer)
    ---> 59 draw(artist, renderer, _args, *_kwargs)
    60 after(artist, renderer)
    61

    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in draw(self, renderer, inframe)
    2004 self.apply_aspect(pos)
    2005 else:
    -> 2006 self.apply_aspect()
    2007
    2008 artists = []

    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in apply_aspect(self, position)
    1191 fig_aspect = figH / figW
    1192 if self._adjustable in ['box', 'box-forced']:
    -> 1193 if aspect_scale_mode == "log":
    1194 box_aspect = A * self.get_data_ratio_log()
    1195 else:

    UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment

    However, running the example explained in
    http://stackoverflow.com/a/13663328/1650159 doesn't give this error.

    Additional Info:

    def plot_year_dist(df,col='',col_label="",thresh=0,file_prefix='',outFolder=DEFAULT_OUTPUT,
    ax=None,color=sns.xkcd_rgb['black'],label='',scale=None,**kwargs):
    saveFig = False
    if ax is None:
    plt.clf()
    ax = plt.gca()
    saveFig = True
    filename = file_prefix+col+"_year_dist.png"
    df_g = df[[col,'Year']].groupby('Year').count()
    df_g["filtered"] = df[[col,"Year"]][df[col] <= thresh].groupby("Year").count()
    df_g["prop"] = df_g["filtered"]/df_g[col]
    #print df_g.index
    #print df_g
    x = df_g.index.values
    y = df_g["prop"].values
    if scale == 'logit':
    y = np.log10(y/(1.0-y))

    ax.plot(x,y, linestyle='-',markersize=3.0,color=color,label=label,**kwargs)

    print "Finished generating histogram"
    ax.set_xlabel(col_label)
    ax.set_ylabel("Proportion (<= %s)" % thresh)
    if scale == 'logit':
    ax.set_ylabel("$log_{10}(p/1-p)$ [$p = P(X<= %s)$]" % thresh)
    if saveFig:
    plt.savefig(outFolder+"/"+filename)
    print "Plot saved in %s." % (filename)

    —
    Reply to this email directly or view it on GitHub
    #4900.

  3. napsternxg commented on Aug 11, 2015

    Author

    Hi @WeatherGod thanks for looking into this.
    The code is supposed to ensure that each subplot is square in shape.

    Here is another set of code which I am running before running the above lines of code:

    import numpy as np
    import matplotlib.pyplot as plt
    
    from matplotlib import scale as mscale
    from matplotlib import transforms as mtransforms
    from matplotlib import ticker as mticker
    from numpy import ma
    
    class ProbaFormatter(mticker.Formatter):
        '''Probability formatter (using Math text)'''
        def __call__(self, x, pos=None):
            s = ''
            if 0.01 <= x <= 0.99:
                if x in [.01, 0.1, 0.5, 0.9, 0.99]:
                    s = '{:.2f}'.format(x)
            elif x < 0.01:
                if mticker.is_decade(x):
                    s = '$10^{%.0f}$' % np.log10(x)
            elif x > 0.99:
                if mticker.is_decade(1-x):
                    s = '$1-10^{%.0f}$' % np.log10(1-x)
            return s
    
        def format_data_short(self, value):
            'return a short formatted string representation of a number'
            return '%-12g' % value
    
    class LogitScale(mscale.ScaleBase):
        """
        Scales data in range 0,1 to -infty, +infty
        """
    
        # The scale class must have a member ``name`` that defines the
        # string used to select the scale.
        name = 'logit'
    
        def __init__(self, axis, **kwargs):
            """
            Any keyword arguments passed to ``set_xscale`` and
            ``set_yscale`` will be passed along to the scale's
            constructor.
    
            thresh: The degree above which to crop the data.
            """
            mscale.ScaleBase.__init__(self)
            p_min = kwargs.pop("p_min", 1e-2)
            if not (0 <p_min < 0.5):
                raise ValueError("p_min must be between 0 and 0.5 excluded")
            p_max = kwargs.pop("p_max", 1-p_min)
            if not (0.5 < p_max < 1):
                raise ValueError("p_max must be between 0.5 and 1 excluded")
            self.p_min = p_min
            self.p_max = p_max
    
        def get_transform(self):
            """
            Override this method to return a new instance that does the
            actual transformation of the data.
            """
            return self.LogitTransform(self.p_min, self.p_max)
    
        def set_default_locators_and_formatters(self, axis):        
            expon_major = np.arange(1, 18)
            # ..., 0.01, 0.1, 0.5, 0.9, 0.99, ...
            axis.set_major_locator(mticker.FixedLocator(
                    list(1/10.**(expon_major)) + \
                    [0.5] + \
                    list(1-1/10.**(expon_major ))
                    ))
            minor_ticks = [0.2,0.3,0.4,0.6,0.7, 0.8]
            for i in range(2,17):
                minor_ticks.extend(1/10.**i * np.arange(2,10))
                minor_ticks.extend(1-1/10.**i * np.arange(2,10))   
            axis.set_minor_locator(mticker.FixedLocator(minor_ticks))
            axis.set_major_formatter(ProbaFormatter())
            axis.set_minor_formatter(ProbaFormatter())
    
        def limit_range_for_scale(self, vmin, vmax, minpos):
            return max(vmin, self.p_min), min(vmax, self.p_max)
    
        class LogitTransform(mtransforms.Transform):
            input_dims = 1
            output_dims = 1
            is_separable = True
    
            def __init__(self, p_min, p_max):
                mtransforms.Transform.__init__(self)
                self.p_min = p_min
                self.p_max = p_max
    
            def transform_non_affine(self, a):
                """logit transform (base 10)"""
                p_over = a > self.p_max
                p_under = a < self.p_min
                # saturate extreme values:
                a_sat = np.where(p_over, self.p_max, a)
                a_sat = np.where(p_under, self.p_min, a_sat)
                return np.log10(a_sat / (1-a_sat))
    
            def inverted(self):
                return LogitScale.InvertedLogitTransform(self.p_min, self.p_max)
    
        class InvertedLogitTransform(mtransforms.Transform):
            input_dims = 1
            output_dims = 1
            is_separable = True
    
            def __init__(self, p_min, p_max):
                mtransforms.Transform.__init__(self)
                self.p_min = p_min
                self.p_max = p_max
    
            def transform_non_affine(self, a):
                """sigmoid transform (base 10)"""
                return 1/(1+10**(-a))
    
            def inverted(self):
                return LogitScale.LogitTransform(self.p_min, self.p_max)
    
    mscale.register_scale(LogitScale)

    p_min argument is for controlling the parameters of the logit scale.

  4. WeatherGod commented on Aug 11, 2015

    Member

    Ah, that would explain why the logit scale wasn't working (matplotlib has
    its own logit scale available).

    This example, though isn't a SSCCE: http://sscce.org/
    It isn't short, nor is it self-contained (I don't have the data, nor do I
    want the data). The example doesn't need the extra bells and whistles, and
    it can have fake data generated using np.logspace(). The x-data doesn't
    need to be dates, either, for the purposes of the demonstration.

    On Tue, Aug 11, 2015 at 12:43 PM, Shubhanshu Mishra <
    notifications@github.com> wrote:

    Hi @WeatherGod https://github.com/WeatherGod thanks for looking into
    this. Here is another set of code which I am running before running the
    above lines of code:

    import numpy as npimport matplotlib.pyplot as plt
    from matplotlib import scale as mscalefrom matplotlib import transforms as mtransformsfrom matplotlib import ticker as mtickerfrom numpy import ma
    class ProbaFormatter(mticker.Formatter):
    '''Probability formatter (using Math text)'''
    def call(self, x, pos=None):
    s = ''
    if 0.01 <= x <= 0.99:
    if x in [.01, 0.1, 0.5, 0.9, 0.99]:
    s = '{:.2f}'.format(x)
    elif x < 0.01:
    if mticker.is_decade(x):
    s = '$10^{%.0f}$' % np.log10(x)
    elif x > 0.99:
    if mticker.is_decade(1-x):
    s = '$1-10^{%.0f}$' % np.log10(1-x)
    return s

    def format_data_short(self, value):
        'return a short formatted string representation of a number'
        return '%-12g' % value
    

    class LogitScale(mscale.ScaleBase):
    """ Scales data in range 0,1 to -infty, +infty """

    # The scale class must have a member ``name`` that defines the
    # string used to select the scale.
    name = 'logit'
    
    def __init__(self, axis, **kwargs):
        """        Any keyword arguments passed to ``set_xscale`` and        ``set_yscale`` will be passed along to the scale's        constructor.        thresh: The degree above which to crop the data.        """
        mscale.ScaleBase.__init__(self)
        p_min = kwargs.pop("p_min", 1e-2)
        if not (0 <p_min < 0.5):
            raise ValueError("p_min must be between 0 and 0.5 excluded")
        p_max = kwargs.pop("p_max", 1-p_min)
        if not (0.5 < p_max < 1):
            raise ValueError("p_max must be between 0.5 and 1 excluded")
        self.p_min = p_min
        self.p_max = p_max
    
    def get_transform(self):
        """        Override this method to return a new instance that does the        actual transformation of the data.        """
        return self.LogitTransform(self.p_min, self.p_max)
    
    def set_default_locators_and_formatters(self, axis):
        expon_major = np.arange(1, 18)
        # ..., 0.01, 0.1, 0.5, 0.9, 0.99, ...
        axis.set_major_locator(mticker.FixedLocator(
                list(1/10.**(expon_major)) + \
                [0.5] + \
                list(1-1/10.**(expon_major ))
                ))
        minor_ticks = [0.2,0.3,0.4,0.6,0.7, 0.8]
        for i in range(2,17):
            minor_ticks.extend(1/10.**i * np.arange(2,10))
            minor_ticks.extend(1-1/10.**i * np.arange(2,10))
        axis.set_minor_locator(mticker.FixedLocator(minor_ticks))
        axis.set_major_formatter(ProbaFormatter())
        axis.set_minor_formatter(ProbaFormatter())
    
    def limit_range_for_scale(self, vmin, vmax, minpos):
        return max(vmin, self.p_min), min(vmax, self.p_max)
    
    class LogitTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True
    
        def __init__(self, p_min, p_max):
            mtransforms.Transform.__init__(self)
            self.p_min = p_min
            self.p_max = p_max
    
        def transform_non_affine(self, a):
            """logit transform (base 10)"""
            p_over = a > self.p_max
            p_under = a < self.p_min
            # saturate extreme values:
            a_sat = np.where(p_over, self.p_max, a)
            a_sat = np.where(p_under, self.p_min, a_sat)
            return np.log10(a_sat / (1-a_sat))
    
        def inverted(self):
            return LogitScale.InvertedLogitTransform(self.p_min, self.p_max)
    
    class InvertedLogitTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True
    
        def __init__(self, p_min, p_max):
            mtransforms.Transform.__init__(self)
            self.p_min = p_min
            self.p_max = p_max
    
        def transform_non_affine(self, a):
            """sigmoid transform (base 10)"""
            return 1/(1+10**(-a))
    
        def inverted(self):
            return LogitScale.LogitTransform(self.p_min, self.p_max)
    

    mscale.register_scale(LogitScale)

    p_min argument is for controlling the parameters of the logit scale.

    —
    Reply to this email directly or view it on GitHub
    #4900 (comment)
    .

  5. napsternxg commented on Aug 11, 2015

    Author

    I am using version 1.4.3 in which the logit scale is not present. Hence I had to write this class.

    >>> plt.yscale("logit")
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-4-7096907d257b> in <module>()
    ----> 1 plt.yscale("logit")
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in yscale(*args, **kwargs)
       1558     """
       1559     ax = gca()
    -> 1560     ax.set_yscale(*args, **kwargs)
       1561     draw_if_interactive()
       1562 
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in set_yscale(self, value, **kwargs)
       2852         if value.lower() == 'log' and 'nonposy' not in kwargs.keys():
       2853             kwargs['nonposy'] = 'clip'
    -> 2854         self.yaxis._set_scale(value, **kwargs)
       2855         self.autoscale_view(scalex=False)
       2856         self._update_transScale()
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/axis.pyc in _set_scale(self, value, **kwargs)
        703 
        704     def _set_scale(self, value, **kwargs):
    --> 705         self._scale = mscale.scale_factory(value, self, **kwargs)
        706         self._scale.set_default_locators_and_formatters(self)
        707 
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/scale.pyc in scale_factory(scale, axis, **kwargs)
        503 
        504     if scale not in _scale_mapping:
    --> 505         raise ValueError("Unknown scale type '%s'" % scale)
        506 
        507     return _scale_mapping[scale](axis, **kwargs)
    
    ValueError: Unknown scale type 'logit'
    
    
    >>> matplotlib.__version__
    '1.4.3'
  6. WeatherGod commented on Aug 11, 2015

    Member

    Ah, I was testing with the master branch, which has it, but is a little bit
    different. In any case, I still need an SSCCE, even if it doesn't work for
    you. I have no clue what fake data to use in my test. This is what I have
    so far:
    master...WeatherGod:fix_4900,
    but the result looks terrible.

    On Tue, Aug 11, 2015 at 1:32 PM, Shubhanshu Mishra <notifications@github.com

    wrote:

    I am using version 1.4.3 in which the logit scale is not present. Hence I
    had to write this class.

    plt.yscale("logit")---------------------------------------------------------------------------ValueError Traceback (most recent call last) in ()----> 1 plt.yscale("logit")
    /usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in yscale(_args, *_kwargs)
    1558 """ 1559 ax = gca()-> 1560 ax.set_yscale(_args, *_kwargs) 1561 draw_if_interactive() 1562 /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in set_yscale(self, value, *_kwargs) 2852 if value.lower() == 'log' and 'nonposy' not in kwargs.keys(): 2853 kwargs['nonposy'] = 'clip'-> 2854 self.yaxis._set_scale(value, *_kwargs) 2855 self.autoscale_view(scalex=False) 2856 self._update_transScale()/usr/local/lib/python2.7/dist-packages/matplotlib/axis.pyc in _set_scale(self, value, *_kwargs) 703 704 def _set_scale(self, value, *_kwargs):--> 705 self._scale = mscale.scale_factory(value, self, *_kwargs) 706 self._scale.set_default_locators_and_formatters(self) 707 /usr/local/lib/python2.7/dist-packages/matplotlib/scale.pyc in scale_factory(scale, axis, *_kwargs) 503 504 if scale not in _scale_mapping:--> 505 raise ValueError("Unknown scale type '%s'" % scale) 506 507 return _scale_mapping[scale](axis, **kwargs)ValueError: Unknown scale type 'logit'>>> matplotlib.version'1.4.3'

    —
    Reply to this email directly or view it on GitHub
    #4900 (comment)
    .

  7. napsternxg commented on Aug 11, 2015

    Author

    This is an SSCE using matplotlib version 1.4.3

    import matplotlib
    matplotlib.use("Agg")
    import matplotlib.pyplot as plt
    matplotlib.__version__
    import numpy as np
    
    from matplotlib import scale as mscale
    from matplotlib import transforms as mtransforms
    from matplotlib import ticker as mticker
    from numpy import ma
    
    class ProbaFormatter(mticker.Formatter):
        '''Probability formatter (using Math text)'''
        def __call__(self, x, pos=None):
            s = ''
            if 0.01 <= x <= 0.99:
                if x in [.01, 0.1, 0.5, 0.9, 0.99]:
                    s = '{:.2f}'.format(x)
            elif x < 0.01:
                if mticker.is_decade(x):
                    s = '$10^{%.0f}$' % np.log10(x)
            elif x > 0.99:
                if mticker.is_decade(1-x):
                    s = '$1-10^{%.0f}$' % np.log10(1-x)
            return s
    
        def format_data_short(self, value):
            'return a short formatted string representation of a number'
            return '%-12g' % value
    
    class LogitScale(mscale.ScaleBase):
        """
        Scales data in range 0,1 to -infty, +infty
        """
    
        # The scale class must have a member ``name`` that defines the
        # string used to select the scale.
        name = 'logit'
    
        def __init__(self, axis, **kwargs):
            """
            Any keyword arguments passed to ``set_xscale`` and
            ``set_yscale`` will be passed along to the scale's
            constructor.
    
            thresh: The degree above which to crop the data.
            """
            mscale.ScaleBase.__init__(self)
            p_min = kwargs.pop("p_min", 1e-2)
            if not (0 <p_min < 0.5):
                raise ValueError("p_min must be between 0 and 0.5 excluded")
            p_max = kwargs.pop("p_max", 1-p_min)
            if not (0.5 < p_max < 1):
                raise ValueError("p_max must be between 0.5 and 1 excluded")
            self.p_min = p_min
            self.p_max = p_max
    
        def get_transform(self):
            """
            Override this method to return a new instance that does the
            actual transformation of the data.
            """
            return self.LogitTransform(self.p_min, self.p_max)
    
        def set_default_locators_and_formatters(self, axis):        
            expon_major = np.arange(1, 18)
            # ..., 0.01, 0.1, 0.5, 0.9, 0.99, ...
            axis.set_major_locator(mticker.FixedLocator(
                    list(1/10.**(expon_major)) + \
                    [0.5] + \
                    list(1-1/10.**(expon_major ))
                    ))
            minor_ticks = [0.2,0.3,0.4,0.6,0.7, 0.8]
            for i in range(2,17):
                minor_ticks.extend(1/10.**i * np.arange(2,10))
                minor_ticks.extend(1-1/10.**i * np.arange(2,10))   
            axis.set_minor_locator(mticker.FixedLocator(minor_ticks))
            axis.set_major_formatter(ProbaFormatter())
            axis.set_minor_formatter(ProbaFormatter())
    
        def limit_range_for_scale(self, vmin, vmax, minpos):
            return max(vmin, self.p_min), min(vmax, self.p_max)
    
        class LogitTransform(mtransforms.Transform):
            input_dims = 1
            output_dims = 1
            is_separable = True
    
            def __init__(self, p_min, p_max):
                mtransforms.Transform.__init__(self)
                self.p_min = p_min
                self.p_max = p_max
    
            def transform_non_affine(self, a):
                """logit transform (base 10)"""
                p_over = a > self.p_max
                p_under = a < self.p_min
                # saturate extreme values:
                a_sat = np.where(p_over, self.p_max, a)
                a_sat = np.where(p_under, self.p_min, a_sat)
                return np.log10(a_sat / (1-a_sat))
    
            def inverted(self):
                return LogitScale.InvertedLogitTransform(self.p_min, self.p_max)
    
        class InvertedLogitTransform(mtransforms.Transform):
            input_dims = 1
            output_dims = 1
            is_separable = True
    
            def __init__(self, p_min, p_max):
                mtransforms.Transform.__init__(self)
                self.p_min = p_min
                self.p_max = p_max
    
            def transform_non_affine(self, a):
                """sigmoid transform (base 10)"""
                return 1/(1+10**(-a))
    
            def inverted(self):
                return LogitScale.LogitTransform(self.p_min, self.p_max)
    
    mscale.register_scale(LogitScale)
    
    
    x = np.arange(10)
    y = np.linspace(1e-4, 1-1e-4, x.size)
    y1 = np.linspace(1e-2, 0.8-1e-4, x.size)
    
    fig, axes = plt.subplots(2, 1, sharey=True)
    plt.setp(axes.flat, aspect=1.0, adjustable='box-forced')
    
    axes[0].plot(x,y)
    axes[1].plot(x,y1)
    axes[0].set_yscale("logit")
    axes[1].set_yscale("logit")
    plt.savefig("Logit_check.png")

    Running the above code gives the following error:

    UnboundLocalError                         Traceback (most recent call last)
    <ipython-input-19-56aae623735e> in <module>()
    ----> 1 plt.savefig("Logit_check.png")
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.pyc in savefig(*args, **kwargs)
        575 def savefig(*args, **kwargs):
        576     fig = gcf()
    --> 577     res = fig.savefig(*args, **kwargs)
        578     draw()   # need this if 'transparent=True' to reset colors
        579     return res
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in savefig(self, *args, **kwargs)
       1474             self.set_frameon(frameon)
       1475 
    -> 1476         self.canvas.print_figure(*args, **kwargs)
       1477 
       1478         if frameon:
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/backend_bases.pyc in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
       2209                 orientation=orientation,
       2210                 bbox_inches_restore=_bbox_inches_restore,
    -> 2211                 **kwargs)
       2212         finally:
       2213             if bbox_inches and restore_bbox:
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_agg.pyc in print_png(self, filename_or_obj, *args, **kwargs)
        519 
        520     def print_png(self, filename_or_obj, *args, **kwargs):
    --> 521         FigureCanvasAgg.draw(self)
        522         renderer = self.get_renderer()
        523         original_dpi = renderer.dpi
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_agg.pyc in draw(self)
        467 
        468         try:
    --> 469             self.figure.draw(self.renderer)
        470         finally:
        471             RendererAgg.lock.release()
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, *args, **kwargs)
         57     def draw_wrapper(artist, renderer, *args, **kwargs):
         58         before(artist, renderer)
    ---> 59         draw(artist, renderer, *args, **kwargs)
         60         after(artist, renderer)
         61 
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/figure.pyc in draw(self, renderer)
       1083         dsu.sort(key=itemgetter(0))
       1084         for zorder, a, func, args in dsu:
    -> 1085             func(*args)
       1086 
       1087         renderer.close_group('figure')
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/artist.pyc in draw_wrapper(artist, renderer, *args, **kwargs)
         57     def draw_wrapper(artist, renderer, *args, **kwargs):
         58         before(artist, renderer)
    ---> 59         draw(artist, renderer, *args, **kwargs)
         60         after(artist, renderer)
         61 
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in draw(self, renderer, inframe)
       2004             self.apply_aspect(pos)
       2005         else:
    -> 2006             self.apply_aspect()
       2007 
       2008         artists = []
    
    /usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.pyc in apply_aspect(self, position)
       1191         fig_aspect = figH / figW
       1192         if self._adjustable in ['box', 'box-forced']:
    -> 1193             if aspect_scale_mode == "log":
       1194                 box_aspect = A * self.get_data_ratio_log()
       1195             else:
    
    UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment
    
    
  8. added this to the milestone on Feb 15, 2016
  9. duncanmmacleod commented on Oct 4, 2017

    Contributor

    This still seems to be an issue using matplotlib 2.0.2:

    import numpy
    
    from matplotlib import pyplot
    from matplotlib.scale import (register_scale, LinearScale)
    
    
    class MyScale(LinearScale):
        name = 'myscale'
    
    register_scale(MyScale)
    
    
    fig = pyplot.figure()
    ax = fig.gca()
    ax.imshow(numpy.random.rand(5, 5))
    ax.set_xscale('myscale')
    fig.show()

    Here the traceback is:

    Traceback (most recent call last):
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/backends/backend_macosx.py", line 136, in _draw
        self.figure.draw(renderer)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/artist.py", line 63, in draw_wrapper
        draw(artist, renderer, *args, **kwargs)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/figure.py", line 1144, in draw
        renderer, self, dsu, self.suppressComposite)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/image.py", line 139, in _draw_list_compositing_images
        a.draw(renderer)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/artist.py", line 63, in draw_wrapper
        draw(artist, renderer, *args, **kwargs)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 2364, in draw
        self.apply_aspect()
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 1437, in apply_aspect
        if aspect_scale_mode == "log":
    UnboundLocalError: local variable 'aspect_scale_mode' referenced before assignment
    
  10. duncanmmacleod commented on Oct 4, 2017

    Contributor

    It seems to me the problem is that the scales are referred by name, rather than by type, e.g.

    xscale == 'linear'
    

    rather than

    isinstance(xscale_, LinearScale)
    

    I'm not familiar with why the scales are referred to absolutely, rather than relatively, can someone comment?

  11. tacaswell commented on Oct 4, 2017

    Member

    @phobson probably understands this best right now.

  12. tacaswell commented on Oct 4, 2017

    Member

    The git blame on that function is all pretty old (2007 - 2010) so the original motivation may be lost to the sands of time.

  13. phobson commented on Oct 9, 2017

    Member

    @tacaswell getting back from vacation, will take a look at this tomorrow,

  14. jbndlr commented on Aug 23, 2018

    Any news on this? Running into the same error when creating custom scales and trying to save the resulting figure.

  15. anntzer commented on Aug 23, 2018

    Contributor

    A simple repro is

    plot([.1, .9], [.01, .99]); xscale("logit"); yscale("logit"); gca().set_aspect(1)
    

    Looks like a correct fix should "simply" be along the lines of

    diff --git i/lib/matplotlib/axes/_base.py w/lib/matplotlib/axes/_base.py
    index 6d7a01cbd..7ecb57c44 100644
    --- i/lib/matplotlib/axes/_base.py
    +++ w/lib/matplotlib/axes/_base.py
    @@ -1458,23 +1458,15 @@ class _AxesBase(martist.Artist):
     
             aspect = self.get_aspect()
     
    -        if self.name != 'polar':
    +        if self.name == 'polar':
    +            aspect_scale_mode = 'linear'
    +        else:
                 xscale, yscale = self.get_xscale(), self.get_yscale()
    -            if xscale == "linear" and yscale == "linear":
    -                aspect_scale_mode = "linear"
    -            elif xscale == "log" and yscale == "log":
    -                aspect_scale_mode = "log"
    -            elif ((xscale == "linear" and yscale == "log") or
    -                  (xscale == "log" and yscale == "linear")):
    -                if aspect != "auto":
    -                    warnings.warn(
    -                        'aspect is not supported for Axes with xscale=%s, '
    -                        'yscale=%s' % (xscale, yscale), stacklevel=2)
    -                    aspect = "auto"
    -            else:  # some custom projections have their own scales.
    -                pass
    -        else:
    -            aspect_scale_mode = "linear"
    +            if xscale != yscale and aspect != 'auto':
    +                cbook._warn_external('aspect is not supported for Axes with '
    +                                     'different scales (xscale=%s, yscale=%s).'
    +                                     % (xscale, yscale))
    +                aspect = 'auto'
     
             if aspect == 'auto':
                 self._set_position(position, which='active')
    @@ -1489,12 +1481,18 @@ class _AxesBase(martist.Artist):
             fig_aspect = figH / figW
             if self._adjustable in ['box', 'box-forced']:
                 if self in self._twinned_axes:
    -                raise RuntimeError("Adjustable 'box' is not allowed in a"
    -                                   " twinned Axes.  Use 'datalim' instead.")
    -            if aspect_scale_mode == "log":
    -                box_aspect = A * self.get_data_ratio_log()
    -            else:
    -                box_aspect = A * self.get_data_ratio()
    +                raise RuntimeError("Adjustable 'box' is not allowed in a "
    +                                   "twinned Axes; use 'datalim' instead")
    +            trf_xmin, trf_xmax = (self.xaxis.get_transform()
    +                                  .transform(self.get_xbound()))
    +            trf_ymin, trf_ymax = (self.yaxis.get_transform()
    +                                  .transform(self.get_ybound()))
    +
    +            xsize = max(abs(trf_xmax - trf_xmin), 1e-30)
    +            ysize = max(abs(trf_ymax - trf_ymin), 1e-30)
    +
    +            box_aspect = A * ysize / xsize
    +
                 pb = position.frozen()
                 pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect)
                 self._set_position(pb1.anchored(self.get_anchor(), pb), 'active')@@ -1489,12 +1481,18 @@ class _AxesBase(martist.Artist):
             fig_aspect = figH / figW
             if self._adjustable in ['box', 'box-forced']:
                 if self in self._twinned_axes:
    -                raise RuntimeError("Adjustable 'box' is not allowed in a"
    -                                   " twinned Axes.  Use 'datalim' instead.")
    -            if aspect_scale_mode == "log":
    -                box_aspect = A * self.get_data_ratio_log()
    -            else:
    -                box_aspect = A * self.get_data_ratio()
    +                raise RuntimeError("Adjustable 'box' is not allowed in a "
    +                                   "twinned Axes; use 'datalim' instead")
    +            trf_xmin, trf_xmax = (self.xaxis.get_transform()
    +                                  .transform(self.get_xbound()))
    +            trf_ymin, trf_ymax = (self.yaxis.get_transform()
    +                                  .transform(self.get_ybound()))
    +
    +            xsize = max(abs(trf_xmax - trf_xmin), 1e-30)
    +            ysize = max(abs(trf_ymax - trf_ymin), 1e-30)
    +
    +            box_aspect = A * ysize / xsize
    +
                 pb = position.frozen()
                 pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect)
                 self._set_position(pb1.anchored(self.get_anchor(), pb), 'active')
    

    and deprecate get_data_ratio/get_data_ratio_log (the fix just applies the actual scale transform to the data limits and computes the ratio from that). Except that this will break custom projections that override get_data_ratio (which is explicitly defined as a overridable method), so we need to figure out how to handle that (perhaps change the behavior of the default get_data_ratio instead to make it do the proper calculation).

    Edit (note to self): @efiring suggested we could put this behavior into get_data_ratio so that overriding get_data_ratio still works.

  16. zc62 commented on May 3, 2019

    @phobson

    Ran into this problem when trying to set equal axis for a symlog-symlog plot. The error occurs at

    if aspect_scale_mode == "log":

    Any chance for this to get some attention?

    It looks like only linear and log scales are supported. Using other scales such as symlog and logit will trigger the bug. (Actually this is an unimplemented feature.)

    EDIT: nvm, there is an issue for the feature now.

  17. modified the milestones: , v3.2.0 on Jul 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL