text: # Copyright Google Inc. 2021
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  # http://www.apache.org/licenses/LICENSE-2.0
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  
  from bokeh.models import ColumnDataSource, HoverTool, Paragraph
  from bokeh.plotting import figure
  from bokeh.palettes import all_palettes
  from bokeh.layouts import column
  
  from modules.base import BaseModule
  from utils import run_query
  from states import NAMES_TO_CODES
  
  
  QUERY = """
      SELECT
        pm10.year AS year,
        pm10.avg AS pm10,
        pm25_frm.avg AS pm25_frm,
        pm25_nonfrm.avg AS pm25_nonfrm,
        lead.avg AS lead
      FROM
        ( SELECT avg(arithmetic_mean) as avg, EXTRACT(YEAR from date_local) as year
          FROM `bigquery-public-data.epa_historical_air_quality.pm10_daily_summary`
          WHERE state_name = '%(state)s'
          GROUP BY year
        ) AS pm10
      JOIN
        ( SELECT avg(arithmetic_mean) as avg, EXTRACT(YEAR from date_local) as year
          FROM `bigquery-public-data.epa_historical_air_quality.pm25_frm_daily_summary`
          WHERE state_name = '%(state)s'
          GROUP BY year
        ) AS pm25_frm ON pm10.year = pm25_frm.year
      JOIN
        ( SELECT avg(arithmetic_mean) as avg, EXTRACT(YEAR from date_local) as year
          FROM `bigquery-public-data.epa_historical_air_quality.pm25_nonfrm_daily_summary`
          WHERE state_name = '%(state)s'
          GROUP BY year
        ) AS pm25_nonfrm ON pm10.year = pm25_nonfrm.year
      JOIN
        ( SELECT avg(arithmetic_mean) * 100 as avg, EXTRACT(YEAR from date_local) as year
          FROM `bigquery-public-data.epa_historical_air_quality.lead_daily_summary`
          WHERE state_name = "%(state)s"
          GROUP BY year
        ) AS lead ON pm10.year = lead.year
      ORDER BY
        year
  """
  
  TITLE = 'Evolution of air pollutant levels:'
  
  
  class Module(BaseModule):
  
      def __init__(self):
          super().__init__()
          self.source = None
          self.plot = None
          self.title = None
  
      def fetch_data(self, state):
          return run_query(
              QUERY % {'state': state},
              cache_key=('air-%s' % NAMES_TO_CODES[state]))
  
  # [START make_plot]
      def make_plot(self, dataframe):
          self.source = ColumnDataSource(data=dataframe)
          palette = all_palettes['Set2'][6]
          hover_tool = HoverTool(tooltips=[
              ("Value", "$y"),
              ("Year", "@year"),
          ])
          self.plot = figure(
              plot_width=600, plot_height=300, tools=[hover_tool],
              toolbar_location=None)
          columns = {
              'pm10': 'PM10 Mass (µg/m³)',
              'pm25_frm': 'PM2.5 FRM (µg/m³)',
              'pm25_nonfrm': 'PM2.5 non FRM (µg/m³)',
              'lead': 'Lead (¹/₁₀₀ µg/m³)',
          }
          for i, (code, label) in enumerate(columns.items()):
              self.plot.line(
                  x='year', y=code, source=self.source, line_width=3,
                  line_alpha=0.6, line_color=palette[i], legend=label)
  
          self.title = Paragraph(text=TITLE)
          return column(self.title, self.plot)
  # [END make_plot]
  
      def update_plot(self, dataframe):
          self.source.data.update(dataframe)
  
      def busy(self):
          self.title.text = 'Updating...'
          self.plot.background_fill_color = "#efefef"
  
      def unbusy(self):
          self.title.text = TITLE
          self.plot.background_fill_color = "white"
  