diff --git a/altair/examples/interactive_layered_crossfilter.py b/altair/examples/interactive_layered_crossfilter.py
index edde1957..bf5e3d3f 100644
--- a/altair/examples/interactive_layered_crossfilter.py
+++ b/altair/examples/interactive_layered_crossfilter.py
@@ -26,13 +26,13 @@ base = alt.Chart().mark_bar().encode(
     height=130
 )
 
-# gray background with selection
-background = base.encode(
-    color=alt.value('#ddd')
-).add_selection(brush)
+# blue background with selection
+background = base.add_selection(brush)
 
-# blue highlights on the transformed data
-highlight = base.transform_filter(brush)
+# yellow highlights on the transformed data
+highlight = base.encode(
+    color=alt.value('goldenrod')
+).transform_filter(brush)
 
 # layer the two charts & repeat
 alt.layer(
diff --git a/altair/vegalite/v3/api.py b/altair/vegalite/v3/api.py
index 44663262..d148d3d8 100644
--- a/altair/vegalite/v3/api.py
+++ b/altair/vegalite/v3/api.py
@@ -93,7 +93,8 @@ def _prepare_data(data, context):
 
     # if data is still not a recognized type, then return
     if not isinstance(data, (dict, core.Data, core.UrlData,
-                             core.InlineData, core.NamedData)):
+                             core.InlineData, core.NamedData,
+                             core.GraticuleGenerator, core.SequenceGenerator)):
         warnings.warn("data of type {} not recognized".format(type(data)))
 
     return data
@@ -1962,3 +1963,25 @@ def _combine_subchart_data(data, subcharts):
             subcharts = [remove_data(c) for c in subcharts]
 
     return data, subcharts
+
+
+@utils.use_signature(core.SequenceParams)
+def sequence(start, stop=None, step=Undefined, as_=Undefined, **kwds):
+  """Sequence generator."""
+  if stop is None:
+    start, stop = 0, start
+  params = core.SequenceParams(
+    start=start, stop=stop, step=step, **{'as': as_}
+  )
+  return core.SequenceGenerator(sequence=params, **kwds)
+
+
+@utils.use_signature(core.GraticuleParams)
+def graticule(**kwds):
+  """Graticule generator."""
+  if not kwds:
+      # graticule: True indicates default parameters
+      graticule = True
+  else:
+      graticule = core.GraticuleParams(**kwds)
+  return core.GraticuleGenerator(graticule=graticule)
\ No newline at end of file
diff --git a/doc/user_guide/data.rst b/doc/user_guide/data.rst
index 33dc1e48..d5e02604 100644
--- a/doc/user_guide/data.rst
+++ b/doc/user_guide/data.rst
@@ -229,6 +229,52 @@ With it, the above chart can be reproduced as follows:
 Notice that unlike the pandas ``melt`` function we must explicitly specify the columns
 to be folded. The ``as_`` argument is optional, with the default being ``["key", "value"]``.
 
+
+.. _data-generated:
+
+Generated Data
+~~~~~~~~~~~~~~
+At times it is convenient to not use an external data source, but rather generate data for
+display within the chart specification itself. The benefit is that the chart specification
+can be made much smaller for generated data than for embedded data.
+
+Sequence Generator
+^^^^^^^^^^^^^^^^^^
+Here is an example of using the :func:`sequence` function to generate a sequence of  *x*
+data, along with a :ref:`user-guide-calculate-transform` to compute *y* data.
+
+.. altair-plot::
+
+   import altair as alt
+
+   # Note that the following generator is functionally similar to
+   # data = pd.DataFrame({'x': np.arange(0, 10, 0.1)})
+   data = alt.sequence(0, 10, 0.1, as_='x')
+
+   alt.Chart(data).transform_calculate(
+       y='sin(datum.x)'
+   ).mark_line().encode(
+       x='x:Q',
+       y='y:Q',
+   )
+
+Graticule Generator
+^^^^^^^^^^^^^^^^^^^
+Another type of data that is convenient to generate in the chart itself is the latitude/longitude
+lines on a geographic visualization, known as a graticule. These can be created using Altair's
+:func:`graticule` generator function. Here is a simple example:
+
+.. altair-plot::
+
+   import altair as alt
+
+   data = alt.graticule(step=[15, 15])
+
+   alt.Chart(data).mark_geoshape().project(
+       'orthographic',
+       rotate=[0, -45, 0]
+   )
+
 .. _Pandas: http://pandas.pydata.org/
 .. _Pandas pivot documentation: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.pivot.html
 .. _Pandas melt documentation: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.melt.html#pandas.DataFrame.melt
diff --git a/doc/user_guide/faq.rst b/doc/user_guide/faq.rst
index f5d3598b..cd0a69f6 100644
--- a/doc/user_guide/faq.rst
+++ b/doc/user_guide/faq.rst
@@ -209,4 +209,4 @@ And then enable the data transformer::
     import altair as alt
     alt.data_transformers.enable('data_server')
 
-Note that this approach may not work on some cloud-based Jupyter notebook services.
+Note that this may not approach on some cloud-based Jupyter notebook services.

Refine data generator support
Vega-Lite supports _data generators_ for geo spheres, geo graticules, and numeric sequences: https://vega.github.io/vega-lite/docs/data.html#data-generators

Altair includes auto-generated classes (e.g., `alt.GraticuleGenerator`, `alt.GraticuleParams`) corresponding to these features. However, passing a generator class as the data for a Chart can result in warning output:

```
UserWarning: data of type <class ‘altair.vegalite.v3.schema.core.SphereGenerator’> not recognized
warnings.warn(“data of type {} not recognized”.format(type(data)))
```

Moreover, code like `alt.GraticuleGenerator(graticule=alt.GraticuleParams(...))` feels unnecessarily verbose. Perhaps a more concise syntax would be helpful? For example, merging the generator and params into a single call... For comparison, the Vega-Lite JavaScript API includes top-level methods for generators (`vl.graticule()`); https://observablehq.com/@vega/vega-lite-cartographic-projections provides an example of their use.

diff --git a/altair/vegalite/v3/tests/test_api.py b/altair/vegalite/v3/tests/test_api.py
index 60b8fb2e..f556376d 100644
--- a/altair/vegalite/v3/tests/test_api.py
+++ b/altair/vegalite/v3/tests/test_api.py
@@ -840,3 +840,22 @@ def test_facet(chart_type, facet_arg):
         assert dct['facet'] == expected
     else:
         assert dct['facet'][facet_arg] == expected
+
+
+def test_sequence():
+    data = alt.sequence(100)
+    assert data.to_dict() == {'sequence': {'start': 0, 'stop': 100}}
+
+    data = alt.sequence(5, 10)
+    assert data.to_dict() == {'sequence': {'start': 5, 'stop': 10}}
+
+    data = alt.sequence(0, 1, 0.1, as_='x')
+    assert data.to_dict() == {'sequence': {'start': 0, 'stop': 1, 'step': 0.1, 'as': 'x'}}
+
+
+def test_graticule():
+    data = alt.graticule()
+    assert data.to_dict() == {'graticule': True}
+
+    data = alt.graticule(step=[15, 15])
+    assert data.to_dict() == {'graticule': {'step': [15, 15]}}
\ No newline at end of file

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
-e git+https://github.com/altair-viz/altair.git@93846e70ad7fed56e02001f5af4c1bfed1ba3e3e#egg=altair
attrs==22.2.0
Babel==2.11.0
backcall==0.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
commonmark==0.9.1
decorator==5.1.1
docutils==0.17.1
entrypoints==0.4
flake8==5.0.4
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==1.1.1
ipython==7.16.3
ipython-genutils==0.2.0
jedi==0.17.2
Jinja2==3.0.3
jsonschema==3.2.0
m2r==0.3.1
MarkupSafe==2.0.1
mccabe==0.7.0
mistune==0.8.4
numpy==1.19.5
packaging==21.3
pandas==1.1.5
parso==0.7.1
pexpect==4.9.0
pickleshare==0.7.5
pluggy==1.0.0
prompt-toolkit==3.0.36
ptyprocess==0.7.0
py==1.11.0
pycodestyle==2.9.1
pyflakes==2.5.0
Pygments==2.14.0
pyparsing==3.1.4
pyrsistent==0.18.0
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
recommonmark==0.7.1
requests==2.27.1
six==1.17.0
snowballstemmer==2.2.0
Sphinx==4.3.2
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==1.2.3
toolz==0.12.0
traitlets==4.3.3
typing_extensions==4.1.1
urllib3==1.26.20
vega-datasets==0.9.0
wcwidth==0.2.13
zipp==3.6.0

name: altair
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - attrs==22.2.0
      - babel==2.11.0
      - backcall==0.2.0
      - charset-normalizer==2.0.12
      - commonmark==0.9.1
      - decorator==5.1.1
      - docutils==0.17.1
      - entrypoints==0.4
      - flake8==5.0.4
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==1.1.1
      - ipython==7.16.3
      - ipython-genutils==0.2.0
      - jedi==0.17.2
      - jinja2==3.0.3
      - jsonschema==3.2.0
      - m2r==0.3.1
      - markupsafe==2.0.1
      - mccabe==0.7.0
      - mistune==0.8.4
      - numpy==1.19.5
      - packaging==21.3
      - pandas==1.1.5
      - parso==0.7.1
      - pexpect==4.9.0
      - pickleshare==0.7.5
      - pluggy==1.0.0
      - prompt-toolkit==3.0.36
      - ptyprocess==0.7.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pyrsistent==0.18.0
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - recommonmark==0.7.1
      - requests==2.27.1
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==4.3.2
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==1.2.3
      - toolz==0.12.0
      - traitlets==4.3.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - vega-datasets==0.9.0
      - wcwidth==0.2.13
      - zipp==3.6.0
prefix: /opt/conda/envs/altair

altair/vegalite/v3/tests/test_api.py::test_sequence altair/vegalite/v3/tests/test_api.py::test_graticule
altair/vegalite/v3/tests/test_api.py::test_chart_data_types altair/vegalite/v3/tests/test_api.py::test_chart_infer_types altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args0-kwargs0] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args1-kwargs1] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args2-kwargs2] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args3-kwargs3] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args4-kwargs4] altair/vegalite/v3/tests/test_api.py::test_multiple_encodings[args5-kwargs5] altair/vegalite/v3/tests/test_api.py::test_chart_operations altair/vegalite/v3/tests/test_api.py::test_selection_to_dict altair/vegalite/v3/tests/test_api.py::test_selection_expression altair/vegalite/v3/tests/test_api.py::test_facet[None-chart] altair/vegalite/v3/tests/test_api.py::test_facet[None-layer] altair/vegalite/v3/tests/test_api.py::test_facet[None-facet_encoding] altair/vegalite/v3/tests/test_api.py::test_facet[facet-chart] altair/vegalite/v3/tests/test_api.py::test_facet[facet-layer] altair/vegalite/v3/tests/test_api.py::test_facet[facet-facet_encoding] altair/vegalite/v3/tests/test_api.py::test_facet[row-chart] altair/vegalite/v3/tests/test_api.py::test_facet[row-layer] altair/vegalite/v3/tests/test_api.py::test_facet[row-facet_encoding] altair/vegalite/v3/tests/test_api.py::test_facet[column-chart] altair/vegalite/v3/tests/test_api.py::test_facet[column-layer] altair/vegalite/v3/tests/test_api.py::test_facet[column-facet_encoding] altair/vegalite/v3/tests/test_api.py::test_facet_parse altair/vegalite/v3/tests/test_api.py::test_facet_parse_data altair/vegalite/v3/tests/test_api.py::test_selection altair/vegalite/v3/tests/test_api.py::test_transforms altair/vegalite/v3/tests/test_api.py::test_filter_transform_selection_predicates altair/vegalite/v3/tests/test_api.py::test_resolve_methods altair/vegalite/v3/tests/test_api.py::test_layer_encodings altair/vegalite/v3/tests/test_api.py::test_add_selection altair/vegalite/v3/tests/test_api.py::test_repeat_add_selections altair/vegalite/v3/tests/test_api.py::test_facet_add_selections altair/vegalite/v3/tests/test_api.py::test_compound_add_selections[layer] altair/vegalite/v3/tests/test_api.py::test_compound_add_selections[concat] altair/vegalite/v3/tests/test_api.py::test_compound_add_selections[hconcat] altair/vegalite/v3/tests/test_api.py::test_compound_add_selections[vconcat] altair/vegalite/v3/tests/test_api.py::test_selection_property altair/vegalite/v3/tests/test_api.py::test_LookupData altair/vegalite/v3/tests/test_api.py::test_themes altair/vegalite/v3/tests/test_api.py::test_chart_from_dict altair/vegalite/v3/tests/test_api.py::test_consolidate_datasets altair/vegalite/v3/tests/test_api.py::test_consolidate_InlineData altair/vegalite/v3/tests/test_api.py::test_deprecated_encodings altair/vegalite/v3/tests/test_api.py::test_repeat altair/vegalite/v3/tests/test_api.py::test_data_property altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data.json-concat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_with_same_data[data1-concat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data.json-concat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-layer] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-hconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-vconcat] altair/vegalite/v3/tests/test_api.py::test_subcharts_different_data[data1-concat] altair/vegalite/v3/tests/test_api.py::test_layer_facet altair/vegalite/v3/tests/test_api.py::test_layer_errors altair/vegalite/v3/tests/test_api.py::test_resolve[layer] altair/vegalite/v3/tests/test_api.py::test_resolve[hconcat] altair/vegalite/v3/tests/test_api.py::test_resolve[vconcat] altair/vegalite/v3/tests/test_api.py::test_resolve[concat] altair/vegalite/v3/tests/test_api.py::test_resolve[facet] altair/vegalite/v3/tests/test_api.py::test_resolve[facet_encoding] altair/vegalite/v3/tests/test_api.py::test_resolve[repeat]
altair/vegalite/v3/api.py altair/examples/interactive_layered_crossfilter.py doc/user_guide/data.rst doc/user_guide/faq.rst
altair/vegalite/v3/api.py altair/examples/interactive_layered_crossfilter.py doc/user_guide/data.rst doc/user_guide/faq.rst