code: def ffill_query_in_range(
      expr,
      lower,
      upper,
      checkpoints=None,
      odo_kwargs=None,
      ts_field=TS_FIELD_NAME,
  ):
      """Query a blaze expression in a given time range properly forward filling
      from values that fall before the lower date.
  
      Parameters
      ----------
      expr : Expr
          Bound blaze expression.
      lower : datetime
          The lower date to query for.
      upper : datetime
          The upper date to query for.
      checkpoints : Expr, optional
          Bound blaze expression for a checkpoints table from which to get a
          computed lower bound.
      odo_kwargs : dict, optional
          The extra keyword arguments to pass to ``odo``.
      ts_field : str, optional
          The name of the timestamp field in the given blaze expression.
  
      Returns
      -------
      raw : pd.DataFrame
          A strict dataframe for the data in the given date range. This may
          start before the requested start date if a value is needed to ffill.
      """
      odo_kwargs = odo_kwargs or {}
      (
          computed_lower,
          materialized_checkpoints,
      ) = get_materialized_checkpoints(
          checkpoints,
          expr.fields,
          lower,
          odo_kwargs,
      )
  
      pred = expr[ts_field] <= upper
  
      if computed_lower is not None:
          # only constrain the lower date if we computed a new lower date
          pred &= expr[ts_field] >= computed_lower
  
      raw = pd.concat(
          (
              materialized_checkpoints,
              odo(expr[pred], pd.DataFrame, **odo_kwargs),
          ),
          ignore_index=True,
      )
      raw.loc[:, ts_field] = raw.loc[:, ts_field].astype(
          "datetime64[ns]"
      )
      return raw
  
imports: from __future__ import division, absolute_import
  from abc import ABCMeta, abstractproperty
  from collections import namedtuple, defaultdict
  from functools import partial
  from itertools import count
  import warnings
  from weakref import WeakKeyDictionary
  import blaze
  from datashape import Date, DateTime, Option, isrecord, isscalar
  import numpy
  from odo import odo
  import pandas
  from six import with_metaclass, PY2, itervalues, iteritems
  from toolz import complement, compose, flip, groupby, identity, memoize, merge
  import toolz.curried.operator
  from catalyst.pipeline.common import AD_FIELD_NAME, SID_FIELD_NAME, TS_FIELD_NAME
  from catalyst.pipeline.data.dataset import DataSet, Column
  from catalyst.pipeline.loaders.utils import check_data_query_args, last_in_date_group, normalize_data_query_bounds, normalize_timestamp_to_query_time, ffill_across_cols
  from catalyst.pipeline.sentinels import NotSpecified
  from catalyst.lib.adjusted_array import AdjustedArray, can_represent_dtype
  from catalyst.lib.adjustment import make_adjustment_from_indices, OVERWRITE
  from catalyst.utils.input_validation import expect_element, ensure_timezone, optionally
  from catalyst.utils.numpy_utils import bool_dtype
  from catalyst.utils.pool import SequentialPool
  from catalyst.utils.preprocess import preprocess
label_desc: Use image node_id 15 for calling a global function with example usage: ffill_query_in_range(expr, lower, upper, checkpoints, odo_kwargs, ts_field) and returns: raw