2017-02-17 1 views
1

Je voudrais définir la plage d'un axe datetime en utilisant un bouton. Cependant, la commandePython, Bokeh: Comment changer la plage de l'axe datetime

f.x_range = Range1d(start=start_date, end=end_date) 

ne fonctionne pas. En cliquant sur le bouton rien ne se passe. Je ne reçois aucune erreur, ni dans les fenêtres du terminal exécutant le serveur Bokeh, ni dans la sortie console de mon navigateur Web Chrome.

Vous trouverez tout le code ci-dessous. Je suis reconnaissant pour tout conseil.

Merci,

Julian

# Import libraries 
from bokeh.io import curdoc 
from bokeh.models import ColumnDataSource, DatetimeTickFormatter, Select, Range1d 
from bokeh.models.widgets import Button 
from bokeh.layouts import layout 
from bokeh.plotting import figure 
from datetime import datetime, timedelta 
from math import radians 


# Create figure 
f=figure(x_axis_type='datetime') 

# Create sample datetime data 
date_time = [datetime(2017,1,1) + timedelta(days=x) for x in range(0,365)] 

# Create ColumnDataSource 
source = ColumnDataSource(dict(datetime=date_time,parameter=range(0,365))) 

# Create Line 
f.line(x='datetime',y='parameter',color='olive',line_color='black',source=source) 

# Update xaxis function 
def update_xaxis(): 
    start_date = datetime(year=int(select_start_year.value), month=int(select_start_month.value), day=int(select_start_day.value)) 
    end_date = datetime(year=int(select_end_year.value), month=int(select_end_month.value), day=int(select_end_day.value))  
    f.x_range = Range1d(start=start_date, end=end_date) 

# Set date format for x axis 
f.xaxis.formatter=DatetimeTickFormatter(formats=dict(
    seconds=["%Y-%m-%d %H:%M:%S"], 
    minsec=["%Y-%m-%d %H:%M:%S"], 
    minutes=["%Y-%m-%d %H:%M:%S"], 
    hourmin=["%Y-%m-%d %H:%M:%S"], 
    hours=["%Y-%m-%d %H:%M:%S"], 
    days=["%Y-%m-%d %H:%M:%S"], 
    months=["%Y-%m-%d %H:%M:%S"], 
    years=["%Y-%m-%d %H:%M:%S"], 
    )) 
f.xaxis.major_label_orientation=radians(90) 

# Create Select and Button widgets 
options=[("2015","2015"),("2016","2016"),("2017","2017")] 
select_start_year=Select(title="Start Year",value="2017",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12")] 
select_start_month=Select(title="Start Month",value="01",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12"),("13","13"),("14","14"),("15","15"),("16","16"),("17","17"),("18","18"),("19","19"),("20","20"),("21","21"),("22","22"),("23","23"),("24","25"),("25","26"),("27","27"),("28","28"),("29","29"),("30","30"),("31","31")] 
select_start_day=Select(title="Start Day",value="01",options=options) 
options=[("2015","2015"),("2016","2016"),("2017","2017")] 
select_end_year=Select(title="End Year",value="2017",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12")] 
select_end_month=Select(title="End Month",value="06",options=options) 
options=[("01","01"),("02","02"),("03","03"),("04","04"),("05","05"),("06","06"),("07","07"),("08","08"),("09","09"),("10","10"),("11","11"),("12","12"),("13","13"),("14","14"),("15","15"),("16","16"),("17","17"),("18","18"),("19","19"),("20","20"),("21","21"),("22","22"),("23","23"),("24","25"),("25","26"),("27","27"),("28","28"),("29","29"),("30","30"),("31","31")] 
select_end_day=Select(title="End Day",value="01",options=options) 
button = Button(label='Set Date') 

# Update x axis range on click 
button.on_click(update_xaxis) 

# Add elements to curdoc 
lay_out=layout([[f],[select_start_year],[select_start_month],[select_start_day],[select_end_year],[select_end_month],[select_end_day],[button]]) 
curdoc().add_root(lay_out) 

Répondre

2

Je cernées la solution. Tout d'abord, j'ai utilisé le widget Datepicker, qui est beaucoup plus élégant que trois widgets Select. Ensuite, vous devez convertir la valeur datetime à partir du DatePicker en une valeur float/integer, qui représente les secondes écoulées w.r.t. une date de référence, à savoir le 1er janvier 1970. Unix calcule cette valeur en secondes, Java Script a besoin de cette valeur en millisecondes, d'où la multiplication par 1000. Voici le code:

# Import libraries 
from bokeh.io import curdoc 
from bokeh.models import ColumnDataSource, DatetimeTickFormatter, DatePicker 
from bokeh.models.widgets import Button 
from bokeh.layouts import layout, column, row 
from bokeh.plotting import figure 
from datetime import datetime, timedelta 
from math import radians 


# Create figure 
f=figure(x_axis_type='datetime') 

# Create sample datetime data 
date_time = [datetime(2017,1,1) + timedelta(days=x) for x in range(0,365)] 

# Create ColumnDataSource 
source = ColumnDataSource(dict(datetime=date_time,parameter=range(0,365))) 

# Create Line 
f.line(x='datetime',y='parameter',color='olive',line_color='black',source=source) 

# Update xaxis function 
def update_xaxis(): 
    # Calculate time delta from reference time in seconds 
    timestamp_start = (datetime.combine(datepicker_start.value, datetime.min.time()) 
         - datetime(1970, 1, 1))/timedelta(seconds=1) 
    timestamp_end = (datetime.combine(datepicker_end.value, datetime.min.time()) 
         - datetime(1970, 1, 1))/timedelta(seconds=1) 
    f.x_range.start = int(timestamp_start)*1e3 # Multiply by 1e3 as JS timestamp is in milliseconds 
    f.x_range.end = int(timestamp_end)*1e3 # Multiply by 1e3 as JS timestamp is in milliseconds 

# Set date format for x axis 
f.xaxis.formatter=DatetimeTickFormatter(formats=dict(
    seconds=["%Y-%m-%d %H:%M:%S"], 
    minsec=["%Y-%m-%d %H:%M:%S"], 
    minutes=["%Y-%m-%d %H:%M:%S"], 
    hourmin=["%Y-%m-%d %H:%M:%S"], 
    hours=["%Y-%m-%d %H:%M:%S"], 
    days=["%Y-%m-%d %H:%M:%S"], 
    months=["%Y-%m-%d %H:%M:%S"], 
    years=["%Y-%m-%d %H:%M:%S"], 
    )) 
f.xaxis.major_label_orientation=radians(90) 

# Create Datepicker and Button widgets 
datepicker_start = DatePicker(title='Start Date') 
datepicker_end = DatePicker(title='End Date') 
button = Button(label='Set Date') 

# Update x axis range on click 
button.on_click(update_xaxis) 

# Add elements to curdoc 
lay_out=layout([[row(f, 
        column(button, 
          row(datepicker_start,datepicker_end)))]]) 
curdoc().add_root(lay_out)