# DataRange1d min\_interval not working

**URL:** <https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627>\
**Category:** Community Support\
**Created:** [November 12, 2021, 1:56pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627 "2021-11-12T13:56:42Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Patrick\_Wright](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/patrick_wright/32/1241_2.png) [@Patrick\_Wright](https://discourse.bokeh.org/u/Patrick_Wright)\
**Post date:** [November 12, 2021, 1:56pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627/1 "2021-11-12T13:56:42Z")

</div>

I am using DataRange1d to define properties of the y axis for my web application, viewable here:  
[https://www.snowpacktracker.com/btac/stormtracker/tetons](https://www.snowpacktracker.com/btac/stormtracker/tetons)

The code to support this is somewhat extensive so I don’t have a minimal, reproducible example, however, the code to set up the figure panels looks like:

```auto
  p = figure(
      title="Relative Humidity",
      name="relative_humidity_fig",
      x_axis_type='datetime',
      x_range = (start,end),
      y_axis_label='%',
      y_range=DataRange1d(
        only_visible=True,
        min_interval=20.
      ),
      width=width, height=height,
      tools=tools,
      toolbar_location='above'
  )

```

The `only_visible` parameter works well, allowing the range to scale only to the line glyphs that are toggled on in the legend. However, I would like to set a minimum range for the y axes using `min_interval` ([ranges — Bokeh 2.4.2 Documentation](https://docs.bokeh.org/en/latest/docs/reference/models/ranges.html#bokeh.models.DataRange1d.min_interval)). For example, I would like to enforce a minimum range of 20% for the relative humidity panel. I have tried various values for this parameter, but cannot see any changes in the y-axis range. Am I misunderstanding this parameter, or is there a different way to do this?

Other relevant info:  
bokeh==2.4.1  
ColumnDataSource for each panel built from a Pandas Dataframe  
Python 3.8.6

I also hope to do a write-up soon to include in the Showcase gallery, as we have been developing this web application using Bokeh for years now, and have learned some things along the way regarding Flask, Heroku, and Bokeh. Thanks for the continued support!

---

<div class="post-metadata">

**Author:** ![Bryan](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/bryan/32/3625_2.png) [@Bryan](https://discourse.bokeh.org/u/Bryan)\
**Post date:** [November 12, 2021, 8:53pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627/2 "2021-11-12T20:53:08Z")

</div>

> [@Patrick\_Wright](#):
>
> The code to support this is somewhat extensive so I don’t have a minimal, reproducible example,

Hi @Patrick_Wright unfortunately without an MRE it’s not really possible to speculate whether somethign like this is a usage issue, or an actual bug, or something else. Perhaps you can construct a purpose-written, much simpler toy example that replicates what you are seeing in isolation so that it can be investigated directly? Otherwise there’s not much I can do beyond pointing at this example with `min_interval` as a possible basis for comparison:

[https://github.com/bokeh/bokeh/blob/branch-3.0/examples/howto/prevent\_user\_zooming\_or\_panning\_too\_far.py](https://github.com/bokeh/bokeh/blob/branch-3.0/examples/howto/prevent_user_zooming_or_panning_too_far.py)

---

<div class="post-metadata">

**Author:** ![Patrick\_Wright](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/patrick_wright/32/1241_2.png) [@Patrick\_Wright](https://discourse.bokeh.org/u/Patrick_Wright)\
**Post date:** [November 14, 2021, 7:26pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627/3 "2021-11-14T19:26:50Z")

</div>

@Bryan I was able to make a minimal, reproducible example. The following code snippet (180 lines) makes one figure, similar to how I make all the figures on my production web app ([Snowpack Tracker](https://www.snowpacktracker.com/btac/stormtracker/tetons)). I simply grabbed some snippets of recent data and pasted them into the code, then making a Pandas dataframe and ColumnDataSource with this data exactly as I do in my full code.

Note lines 35-37, where I have:

```auto
y_range=DataRange1d(
  only_visible=True,
  min_interval=50.
)

```

My interpretation of the [docs](https://docs.bokeh.org/en/latest/docs/reference/models/ranges.html#bokeh.models.DataRange1d.min_interval) is that the `min_interval` setting should not allow the y-axis to zoom in further than 50 data units. In this case, I am plotting relative humidity data with units of “%”, and the full range of the data is from approximately 88% to 100% (12 data units). So, with `min_interval=50.`, I would expect the y-axis range to not reduce beyond 50 units (e.g. 50% to 100%). Would this require setting a minimum or maximum bound to have one end of the interval bounded? I tried playing with the `bounds` and `end` parameters, but did not see any changes.

My end goal is to be able to update my figures with the date range slider or radio buttons to various date ranges (which updates the CDS for each figure), and then let the y-axis auto-scale to the range of visible data for the glyphs that are toggled on in the legend. However, I would like to set a minimum range that the y-axis cannot “zoom” beyond (using `min_interval`). I can also drop my date range slider and radio buttons into this example, but because the issue is present without these widgets, I did not include them.

If you put this code snippet in a file named `main.py`, put in a directory and run with `bokeh serve`, it should work.  
`bokeh==2.4.1`

Thanks!

```auto
#!/usr/bin/env python
'''
min_span not working, minimal reproducible example
Author: P. Wright, Inversion Labs
Created: Nov 14, 2021
'''
import pandas as pd
from bokeh.models import Legend,DataRange1d,ColumnDataSource
from bokeh.plotting import figure, curdoc
from bokeh.layouts import gridplot

def make_rh_fig(panel_df, start, end):
  '''
  Create the relative humidity panel and plot data
  CDS created in-place

  Parameters
  ----------
  panel_df: the pandas dataframe for this panel
  start: the global start date
  end: the global end date

  Returns
  -------
  p: Bokeh Figure object
  '''
  panel_df['Date'] = panel_df.index.tz_localize(None)
  cds = ColumnDataSource(data=panel_df)
  p = figure(
      title="Relative Humidity",
      name="relative_humidity_fig",
      x_axis_type='datetime',
      x_range = (start,end),
      y_axis_label='%',
      y_range=DataRange1d(
        only_visible=True,
        min_interval=50.,
        end=100.
      )
  )
  legenddict={}
  items=[]
  tooltips=[("Date", "@Date_hover")]
  legenddict['foo'] = p.line(x='Date', y='foo',
                      line_width=2, color='blue',
                      alpha=0.8, name='foo', source=cds)

  items.append(('foo',[legenddict['foo']]))
  legend1 = Legend(items=items[0:],)
  p.add_layout(legend1, 'below')
  return p

#---------------------------------------------
# TEST DATA
#---------------------------------------------

datetime = [
'2021-11-11 12:00:00',
'2021-11-11 13:00:00',
'2021-11-11 14:00:00',
'2021-11-11 15:00:00',
'2021-11-11 16:00:00',
'2021-11-11 17:00:00',
'2021-11-11 18:00:00',
'2021-11-11 19:00:00',
'2021-11-11 20:00:00',
'2021-11-11 21:00:00',
'2021-11-11 22:00:00',
'2021-11-11 23:00:00',
'2021-11-12 00:00:00',
'2021-11-12 01:00:00',
'2021-11-12 02:00:00',
'2021-11-12 03:00:00',
'2021-11-12 04:00:00',
'2021-11-12 05:00:00',
'2021-11-12 06:00:00',
'2021-11-12 07:00:00',
'2021-11-12 08:00:00',
'2021-11-12 09:00:00',
'2021-11-12 10:00:00',
'2021-11-12 11:00:00',
'2021-11-12 12:00:00',
'2021-11-12 13:00:00',
'2021-11-12 14:00:00',
'2021-11-12 15:00:00',
'2021-11-12 16:00:00',
'2021-11-12 17:00:00',
'2021-11-12 18:00:00',
'2021-11-12 19:00:00',
'2021-11-12 20:00:00',
'2021-11-12 21:00:00',
'2021-11-12 22:00:00',
'2021-11-12 23:00:00',
'2021-11-13 00:00:00',
'2021-11-13 01:00:00',
'2021-11-13 02:00:00',
'2021-11-13 03:00:00',
'2021-11-13 04:00:00',
'2021-11-13 05:00:00',
'2021-11-13 06:00:00',
'2021-11-13 07:00:00',
'2021-11-13 08:00:00',
'2021-11-13 09:00:00',
'2021-11-13 10:00:00',
'2021-11-13 11:00:00',
'2021-11-13 12:00:00']

rh = [
 88.0,
 88.0,
 92.0,
 93.0,
 93.0,
 94.0,
 94.0,
 93.0,
 93.0,
 93.0,
 93.0,
 94.0,
 94.0,
 94.0,
 94.0,
 94.0,
 95.0,
 95.0,
 97.0,
 98.0,
 98.0,
 98.0,
 98.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
 99.0,
100.0,
 99.0,
 98.0,
 98.0,
 97.0,
 99.0,
 99.0,
100.0,
100.0,
100.0,
100.0,
 99.0,
 99.0,
 99.0,
 98.0]

df_dict = {'dt':datetime,'data':rh}
df_test = pd.DataFrame(data=df_dict['data'],
  columns=['foo'],
  index=pd.to_datetime(df_dict['dt'])
  )

#---------------------------------------------
# MAKE FIGURE
#---------------------------------------------
global_start = df_test.index.min()
global_end = df_test.index.max()
relative_humidity_fig = make_rh_fig(
    df_test,
    global_start,
    global_end
)

grid = gridplot(
  children = [relative_humidity_fig],
  ncols=1,
)

curdoc().add_root(grid)

```

---

<div class="post-metadata">

**Author:** ![Bryan](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/bryan/32/3625_2.png) [@Bryan](https://discourse.bokeh.org/u/Bryan)\
**Post date:** [November 14, 2021, 8:31pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627/4 "2021-11-14T20:31:03Z")

</div>

@Patrick_Wright `min_interval` really only applies to user interactions (e.g. manual zooming with a scroll wheel) If you tell the range to have a smaller interval, either explicitly by setting `start` and `end` yourself, or by asking for auto-ranging and supplying data with a smaller range than the min interval, then Bokeh assumes you know what you want, and gives those precedence. I guess the user interaction part could be made more evident in the docs. cc @Timo

In the code above, it starts out with an interval smaller than 50 due to auto-ranging (which has precedence) If you scroll zoom out so the range is larger than 50, and then try to zoom back in, the range stops you from going back down below 50 _with the zoom tool_. All of that is expected behavior to me. Since it sounds like that is not what you want, it seems like you might want to manually manage your range `start` and `end` according to your specific needs (i.e. just use a “dumb” `Range1d` instead of `DataRange1d`).

---

<div class="post-metadata">

**Author:** ![Patrick\_Wright](https://discourse.bokeh.org/user_avatar/discourse.bokeh.org/patrick_wright/32/1241_2.png) [@Patrick\_Wright](https://discourse.bokeh.org/u/Patrick_Wright)\
**Post date:** [November 14, 2021, 9:24pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627/5 "2021-11-14T21:24:11Z")

</div>

@Bryan OK, makes sense. I did not understand that this applies only to user interactions, which could be made more clear in the docs. I will try a more manual solution to get what I need. However, I need to stick with `DataRange1d` since I really like the functionality of `only_visible=True`. One easy solution I might try to enforce a minimum range for the y range is to plot a max and min “dummy” line with `alpha=0.0` that won’t show up but will force the y-range when the data is of a smaller range. Such as:  
`dummy_min = p.line(x='Date', y=80, alpha=0.0, name='dummy_min')`  
`dummy_max = p.line(x='Date', y=100, alpha=0.0, name='dummy_max')`

Thanks again for the continued assistance!

---

<div class="post-metadata">

**Author:** ![system](https://discourse-uploads.bokeh.org/original/2X/1/14eb24f9e10e4e9b78e3f10f66c04ffa96446e5a.svg) [@system](https://discourse.bokeh.org/u/system)\
**Post date:** [February 12, 2022, 9:24pm UTC](https://discourse.bokeh.org/t/datarange1d-min-interval-not-working/8627/6 "2022-02-12T21:24:38Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
