scanspec.specs#

Spec and its subclasses.

Inheritance diagram of scanspec.specs

Members

Spec

A serializable representation of the type and parameters of a scan.

step

Step scan, with num frames of given duration at each frame in the spec.

fly

Flyscan, zipping with fixed duration for every frame.

VARIABLE_DURATION

A string returned from Spec.duration to signify it produces a different duration for each point

pydantic model scanspec.specs.ConstantDuration[source]#

Apply a constant duration to every point in a Spec.

Typically applied with the @ modifier.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Linspace

spec = 0.1 @ Linspace("x", 1, 2, 3)
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-1.png

Show JSON schema
{
   "title": "ConstantDuration",
   "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
   "type": "object",
   "properties": {
      "constant_duration": {
         "description": "The value at each point",
         "title": "Constant Duration",
         "type": "number"
      },
      "spec": {
         "anyOf": [
            {
               "$ref": "#/$defs/Spec"
            },
            {
               "type": "null"
            }
         ],
         "default": null,
         "description": "Spec contaning the path to be followed"
      },
      "type": {
         "const": "ConstantDuration",
         "default": "ConstantDuration",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "constant_duration"
   ]
}

Fields:
field constant_duration: float [Required]#

The value at each point

field spec: Spec[Axis] | None = None#

Spec contaning the path to be followed

field type: Literal['ConstantDuration'] = 'ConstantDuration'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

class scanspec.specs.Spec[source]#

A serializable representation of the type and parameters of a scan.

Abstract baseclass for the specification of a scan. Supports operators:

  • *: Outer Product of two Specs or ints, nesting the second within the first.

  • @: ConstantDuration of the Spec, setting a constant duration for each point.

  • ~: Snake the Spec, reversing every other iteration of it

axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

frames(bounds: bool = False) Dimension[Axis][source]#

Expand all the scan Dimension and return them.

midpoints() Midpoints[Axis][source]#

Return Midpoints that can be iterated point by point.

shape() tuple[int, ...][source]#

Return the final, simplified shape of the scan.

zip(other: Spec[OtherAxis]) Zip[Axis | OtherAxis][source]#

Zip the Spec with another, iterating in tandem.

concat(other: Spec[Axis]) Concat[Axis][source]#

Concat the Spec with another, iterating one after the other.

serialize() Mapping[str, Any][source]#

Serialize the Spec to a dictionary.

static deserialize(obj: Any) Spec[Any][source]#

Deserialize a Spec from a dictionary.

pydantic model scanspec.specs.Product[source]#

Outer product of two Specs, nesting inner within outer.

This means that inner will run in its entirety at each point in outer.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace("y", 1, 2, 3) * Linspace("x", 3, 4, 12))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-2.png

An inner integer can be used to repeat the same point many times.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace("y", 1, 2, 3) * 2)
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-3.png

An outer integer can be used to repeat the same scan many times.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(2 * ~Linspace.bounded("x", 3, 4, 1))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-4.png

If you want snaked axes to have no gap between iterations you can do:

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace, Product

spec = Fly(Product(2, ~Linspace.bounded("x", 3, 4, 1), gap=False))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-5.png

Note

There is no turnaround arrow at x=4

Show JSON schema
{
   "title": "Product",
   "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
   "type": "object",
   "properties": {
      "outer": {
         "anyOf": [
            {
               "$ref": "#/$defs/Spec"
            },
            {
               "type": "integer"
            }
         ],
         "description": "Will be executed once",
         "title": "Outer"
      },
      "inner": {
         "anyOf": [
            {
               "$ref": "#/$defs/Spec"
            },
            {
               "type": "integer"
            }
         ],
         "description": "Will be executed len(outer) times",
         "title": "Inner"
      },
      "gap": {
         "default": true,
         "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
         "title": "Gap",
         "type": "boolean"
      },
      "type": {
         "const": "Product",
         "default": "Product",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "outer",
      "inner"
   ]
}

Fields:
field gap: bool = True#

If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap

field inner: Spec[Axis] | int [Required]#

Will be executed len(outer) times

field outer: Spec[Axis] | int [Required]#

Will be executed once

field type: Literal['Product'] = 'Product'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

pydantic model scanspec.specs.Zip[source]#

Run two Specs in parallel, merging their midpoints together.

Typically formed using Spec.zip.

Stacks of Dimension are merged by:

  • If right creates a stack of a single Dimension object of size 1, expand it to the size of the fastest Dimension object created by left

  • Merge individual Dimension objects together from fastest to slowest

This means that Zipping a Spec producing stack [l2, l1] with a Spec producing stack [r1] will assert len(l1)==len(r1), and produce stack [l2, l1.zip(r1)].

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(
    Linspace("z", 1, 2, 3) * Linspace("y", 3, 4, 5).zip(Linspace("x", 4, 5, 5))
)
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-6.png

Show JSON schema
{
   "title": "Zip",
   "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
   "type": "object",
   "properties": {
      "left": {
         "$ref": "#/$defs/Spec",
         "description": "The left-hand Spec to Zip, will appear earlier in axes"
      },
      "right": {
         "$ref": "#/$defs/Spec",
         "description": "The right-hand Spec to Zip, will appear later in axes"
      },
      "type": {
         "const": "Zip",
         "default": "Zip",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "left",
      "right"
   ]
}

Fields:
field left: Spec[Axis] [Required]#

The left-hand Spec to Zip, will appear earlier in axes

field right: Spec[Axis] [Required]#

The right-hand Spec to Zip, will appear later in axes

field type: Literal['Zip'] = 'Zip'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

pydantic model scanspec.specs.Snake[source]#

Run the Spec in reverse on every other iteration when nested.

Typically created with the ~ operator.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace("y", 1, 3, 3) * ~Linspace("x", 3, 5, 5))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-7.png

Show JSON schema
{
   "title": "Snake",
   "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
   "type": "object",
   "properties": {
      "spec": {
         "$ref": "#/$defs/Spec",
         "description": "The Spec to run in reverse every other iteration"
      },
      "type": {
         "const": "Snake",
         "default": "Snake",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "spec"
   ]
}

Fields:
field spec: Spec[Axis] [Required]#

The Spec to run in reverse every other iteration

field type: Literal['Snake'] = 'Snake'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

pydantic model scanspec.specs.Concat[source]#

Concatenate two Specs together, running one after the other.

Each Dimension of left and right must contain the same axes. Typically formed using Spec.concat.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace("x", 1, 3, 3).concat(Linspace("x", 4, 5, 5)))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-8.png

Show JSON schema
{
   "title": "Concat",
   "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
   "type": "object",
   "properties": {
      "left": {
         "$ref": "#/$defs/Spec",
         "description": "The left-hand Spec to Concat, midpoints will appear earlier"
      },
      "right": {
         "$ref": "#/$defs/Spec",
         "description": "The right-hand Spec to Concat, midpoints will appear later"
      },
      "gap": {
         "default": false,
         "description": "If True, force a gap in the output at the join",
         "title": "Gap",
         "type": "boolean"
      },
      "check_path_changes": {
         "default": true,
         "description": "If True path through scan will not be modified by squash",
         "title": "Check Path Changes",
         "type": "boolean"
      },
      "type": {
         "const": "Concat",
         "default": "Concat",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "left",
      "right"
   ]
}

Fields:
field check_path_changes: bool = True#

If True path through scan will not be modified by squash

field gap: bool = False#

If True, force a gap in the output at the join

field left: Spec[Axis] [Required]#

The left-hand Spec to Concat, midpoints will appear earlier

field right: Spec[Axis] [Required]#

The right-hand Spec to Concat, midpoints will appear later

field type: Literal['Concat'] = 'Concat'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

pydantic model scanspec.specs.Squash[source]#

Squash a stack of Dimension together into a single expanded Dimension object.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace, Squash

spec = Fly(Squash(Linspace("y", 1, 2, 3) * Linspace("x", 0, 1, 4)))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-9.png

Show JSON schema
{
   "title": "Squash",
   "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
   "type": "object",
   "properties": {
      "spec": {
         "$ref": "#/$defs/Spec",
         "description": "The Spec to squash the dimensions of"
      },
      "check_path_changes": {
         "default": true,
         "description": "If True path through scan will not be modified by squash",
         "title": "Check Path Changes",
         "type": "boolean"
      },
      "type": {
         "const": "Squash",
         "default": "Squash",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "spec"
   ]
}

Fields:
field check_path_changes: bool = True#

If True path through scan will not be modified by squash

field spec: Spec[Axis] [Required]#

The Spec to squash the dimensions of

field type: Literal['Squash'] = 'Squash'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

pydantic model scanspec.specs.Linspace[source]#

Linearly spaced frames with start and stop as first and last midpoints.

This class is intended to handle linearly spaced frames defined with a specific number of frames.

See also

Range: For linearly spaced frames defined with a step size.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace("x", 1, 2, 5))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-10.png

Show JSON schema
{
   "title": "Linspace",
   "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
   "type": "object",
   "properties": {
      "axis": {
         "description": "An identifier for what to move",
         "title": "Axis"
      },
      "start": {
         "description": "Midpoint of the first point of the line",
         "title": "Start",
         "type": "number"
      },
      "stop": {
         "description": "Midpoint of the last point of the line",
         "title": "Stop",
         "type": "number"
      },
      "num": {
         "default": 1,
         "description": "Number of frames to produce (defaults to 1)",
         "minimum": 1,
         "title": "Num",
         "type": "integer"
      },
      "type": {
         "const": "Linspace",
         "default": "Linspace",
         "title": "Type",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "axis",
      "start",
      "stop"
   ]
}

Fields:
field axis: Axis [Required]#

An identifier for what to move

field num: int = 1#

Number of frames to produce (defaults to 1)

Constraints:
  • ge = 1

field start: float [Required]#

Midpoint of the first point of the line

field stop: float [Required]#

Midpoint of the last point of the line

field type: Literal['Linspace'] = 'Linspace'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

bounded(lower: float = FieldInfo(annotation=NoneType, required=True, description='Lower bound of the first point of the line'), upper: float = FieldInfo(annotation=NoneType, required=True, description='Upper bound of the last point of the line'), num: int = FieldInfo(annotation=NoneType, required=False, default=1, description='Number of frames to produce (defaults to 1)', metadata=[Ge(ge=1)])) Linspace[OtherAxis][source]#

Specify a Linspace by extreme bounds instead of midpoints.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace.bounded("x", 1, 2, 5))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-11.png
calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

scanspec.specs.Line#

alias of Linspace

pydantic model scanspec.specs.Range[source]#

Linearly spaced frames with start and stop as the bounding midpoints.

step defines the distance between midpoints.

See also

Linspace: For linearly spaced frames defined with a number of frames.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Range

spec = Fly(Range("x", 1, 2, 0.25))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-12.png

Show JSON schema
{
   "title": "Range",
   "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
   "type": "object",
   "properties": {
      "axis": {
         "description": "An identifier for what to move",
         "title": "Axis"
      },
      "start": {
         "description": "Midpoint of the first point of the line",
         "title": "Start",
         "type": "number"
      },
      "stop": {
         "description": "Midpoint of the last point of the line",
         "title": "Stop",
         "type": "number"
      },
      "step": {
         "description": "Step size (defaults to stop - start)",
         "exclusiveMinimum": 0,
         "title": "Step",
         "type": "number"
      },
      "type": {
         "const": "Range",
         "default": "Range",
         "title": "Type",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "axis",
      "start",
      "stop"
   ]
}

Fields:
field axis: Axis [Required]#

An identifier for what to move

field start: float [Required]#

Midpoint of the first point of the line

field step: float [Optional]#

Step size (defaults to stop - start)

Constraints:
  • gt = 0

field stop: float [Required]#

Midpoint of the last point of the line

field type: Literal['Range'] = 'Range'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

bounded(lower: float = FieldInfo(annotation=NoneType, required=True, description='Lower bound of the first point of the line'), upper: float = FieldInfo(annotation=NoneType, required=True, description='Upper bound of the last point of the line'), step: float = FieldInfo(annotation=NoneType, required=True, description='Step size')) Range[OtherAxis][source]#

Specify a Range by extreme bounds instead of midpoints.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Range

spec = Fly(Range.bounded("x", 1, 5, 2))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-13.png
calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

pydantic model scanspec.specs.Ellipse[source]#

Grid of points masked to an elliptical footprint.

Constructs a 2-D scan over an axis-aligned ellipse defined by (x_axis, y_axis), centred at (x_centre, y_centre), with diameters x_diameter and y_diameter. Grid spacing along each axis is controlled by x_step and y_step. If snake is True, the fast axis will zigzag like a snake. If vertical is True, the y axis will be the fast axis.

Starts from one of the four extremes of the ellipse identified by the signs of x_step and y_step.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Ellipse, Fly

# An elliptical region centred at (0, 0) on axes "x" and "y",
# with 10x6 diameters and steps of 0.5 in both directions.
spec = Fly(
    Ellipse(
        "x", 0, 10, 0.5,
        "y", 0, 6,
        snake=True,
        vertical=False,
    )
)
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-14.png

Show JSON schema
{
   "title": "Ellipse",
   "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
   "type": "object",
   "properties": {
      "x_axis": {
         "description": "An identifier for what to move for x",
         "title": "X Axis"
      },
      "x_centre": {
         "description": "x centre of the spiral",
         "title": "X Centre",
         "type": "number"
      },
      "x_diameter": {
         "description": "x width of the spiral",
         "title": "X Diameter",
         "type": "number"
      },
      "x_step": {
         "description": "Spacing along x",
         "exclusiveMinimum": 0,
         "title": "X Step",
         "type": "number"
      },
      "y_axis": {
         "description": "An identifier for what to move for y",
         "title": "Y Axis"
      },
      "y_centre": {
         "description": "y centre of the spiral",
         "title": "Y Centre",
         "type": "number"
      },
      "y_diameter": {
         "description": "y width of the spiral (defaults to x_diameter)",
         "title": "Y Diameter",
         "type": "number"
      },
      "y_step": {
         "description": "Spacing along y (defaults to x_step)",
         "exclusiveMinimum": 0,
         "title": "Y Step",
         "type": "number"
      },
      "snake": {
         "default": false,
         "description": "If True, path zigzag like a snake (defaults to False)",
         "title": "Snake",
         "type": "boolean"
      },
      "vertical": {
         "default": false,
         "description": "If True, y axis is the fast axis (defaults to False)",
         "title": "Vertical",
         "type": "boolean"
      },
      "type": {
         "const": "Ellipse",
         "default": "Ellipse",
         "title": "Type",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "x_axis",
      "x_centre",
      "x_diameter",
      "x_step",
      "y_axis",
      "y_centre"
   ]
}

Fields:
field snake: bool = False#

If True, path zigzag like a snake (defaults to False)

field type: Literal['Ellipse'] = 'Ellipse'#
field vertical: bool = False#

If True, y axis is the fast axis (defaults to False)

field x_axis: Axis [Required]#

An identifier for what to move for x

field x_centre: float [Required]#

x centre of the spiral

field x_diameter: float [Required]#

x width of the spiral

field x_step: float [Required]#

Spacing along x

Constraints:
  • gt = 0

field y_axis: Axis [Required]#

An identifier for what to move for y

field y_centre: float [Required]#

y centre of the spiral

field y_diameter: float [Optional]#

y width of the spiral (defaults to x_diameter)

field y_step: float [Optional]#

Spacing along y (defaults to x_step)

Constraints:
  • gt = 0

axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

pydantic model scanspec.specs.Polygon[source]#

Grid of points masked to a polygonal footprint.

Constructs a 2-D scan over an axis-aligned polygon defined by an ordered list of vertices “(x, y)” given in vertices. The polygon may be convex or concave, and the interior is determined using an even-odd ray-casting rule. Grid spacing along each axis is controlled by x_step and y_step, If snake is True, the fast axis will zigzag like a snake. If vertical is True, the y axis will be the fast axis.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Polygon, Fly

# A triangular region on axes "x" and "y", stepped by 0.2 units
# in both directions.
spec = Fly(
    Polygon(
        x_axis="x",
        y_axis="y",
        vertices=[(0, 0), (5, 0), (2.5, 4)],
        x_step=0.2,
        y_step=0.2,
        snake=True,
        vertical=False,
    )
)
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-15.png

Show JSON schema
{
   "title": "Polygon",
   "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
   "type": "object",
   "properties": {
      "x_axis": {
         "description": "An identifier for what to move for x",
         "title": "X Axis"
      },
      "y_axis": {
         "description": "An identifier for what to move for y",
         "title": "Y Axis"
      },
      "vertices": {
         "description": "List of (x, y) vertices defining the polygon",
         "items": {
            "maxItems": 2,
            "minItems": 2,
            "prefixItems": [
               {
                  "type": "number"
               },
               {
                  "type": "number"
               }
            ],
            "type": "array"
         },
         "title": "Vertices",
         "type": "array"
      },
      "x_step": {
         "description": "Spacing along x",
         "exclusiveMinimum": 0,
         "title": "X Step",
         "type": "number"
      },
      "y_step": {
         "description": "Spacing along y (defaults to x_step)",
         "exclusiveMinimum": 0,
         "title": "Y Step",
         "type": "number"
      },
      "snake": {
         "default": false,
         "description": "If True, path zigzag like a snake (defaults to False)",
         "title": "Snake",
         "type": "boolean"
      },
      "vertical": {
         "default": false,
         "description": "If True, y axis is the fast axis (defaults to False)",
         "title": "Vertical",
         "type": "boolean"
      },
      "type": {
         "const": "Polygon",
         "default": "Polygon",
         "title": "Type",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "x_axis",
      "y_axis",
      "vertices",
      "x_step"
   ]
}

Fields:
field snake: bool = False#

If True, path zigzag like a snake (defaults to False)

field type: Literal['Polygon'] = 'Polygon'#
field vertical: bool = False#

If True, y axis is the fast axis (defaults to False)

field vertices: list[tuple[float, float]] [Required]#

List of (x, y) vertices defining the polygon

field x_axis: Axis [Required]#

An identifier for what to move for x

field x_step: float [Required]#

Spacing along x

Constraints:
  • gt = 0

field y_axis: Axis [Required]#

An identifier for what to move for y

field y_step: float [Optional]#

Spacing along y (defaults to x_step)

Constraints:
  • gt = 0

axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

pydantic model scanspec.specs.Static[source]#

A static frame, repeated num times, with axis at value.

Can be used to set axis=value at every point in a scan.

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace, Static

spec = Fly(Linspace("y", 1, 2, 3).zip(Static("x", 3)))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-16.png

Show JSON schema
{
   "title": "Static",
   "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
   "type": "object",
   "properties": {
      "axis": {
         "description": "An identifier for what to move",
         "title": "Axis"
      },
      "value": {
         "description": "The value at each point",
         "title": "Value",
         "type": "number"
      },
      "num": {
         "default": 1,
         "description": "Number of frames to produce",
         "minimum": 1,
         "title": "Num",
         "type": "integer"
      },
      "type": {
         "const": "Static",
         "default": "Static",
         "title": "Type",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "axis",
      "value"
   ]
}

Fields:
field axis: Axis [Required]#

An identifier for what to move

field num: int = 1#

Number of frames to produce

Constraints:
  • ge = 1

field type: Literal['Static'] = 'Static'#
field value: float [Required]#

The value at each point

axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

pydantic model scanspec.specs.Spiral[source]#

Archimedean spiral of “x_axis” and “y_axis”.

Starts at centre point (“x_start”, “y_start”)”. Produces “num” points in a spiral spanning width of “x_range” and height of “y_range”

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Spiral

spec = Fly(Spiral("x", 1, 10, 2.5, "y", 5, 50))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-17.png

Show JSON schema
{
   "title": "Spiral",
   "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
   "type": "object",
   "properties": {
      "x_axis": {
         "description": "An identifier for what to move for x",
         "title": "X Axis"
      },
      "x_centre": {
         "description": "x centre of the spiral",
         "title": "X Centre",
         "type": "number"
      },
      "x_diameter": {
         "description": "x width of the spiral",
         "title": "X Diameter",
         "type": "number"
      },
      "x_step": {
         "description": "Radial spacing along x",
         "title": "X Step",
         "type": "number"
      },
      "y_axis": {
         "description": "An identifier for what to move for y",
         "title": "Y Axis"
      },
      "y_centre": {
         "description": "y centre of the spiral",
         "title": "Y Centre",
         "type": "number"
      },
      "y_diameter": {
         "description": "y width of the spiral (defaults to x_diameter)",
         "title": "Y Diameter",
         "type": "number"
      },
      "type": {
         "const": "Spiral",
         "default": "Spiral",
         "title": "Type",
         "type": "string"
      }
   },
   "additionalProperties": false,
   "required": [
      "x_axis",
      "x_centre",
      "x_diameter",
      "x_step",
      "y_axis",
      "y_centre"
   ]
}

Fields:
field type: Literal['Spiral'] = 'Spiral'#
field x_axis: Axis [Required]#

An identifier for what to move for x

field x_centre: float [Required]#

x centre of the spiral

field x_diameter: float [Required]#

x width of the spiral

field x_step: float [Required]#

Radial spacing along x

field y_axis: Axis [Required]#

An identifier for what to move for y

field y_centre: float [Required]#

y centre of the spiral

field y_diameter: float [Optional]#

y width of the spiral (defaults to x_diameter)

axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

pydantic model scanspec.specs.Fly[source]#

Move through lower to upper bounds of the Spec rather than stopping.

This is commonly termed a “fly scan” rather than a “step scan”

# Example Spec

from scanspec.plot import plot_spec
from scanspec.specs import Fly, Linspace

spec = Fly(Linspace("x", 1, 2, 3))
plot_spec(spec)

(Source code, png, hires.png, pdf)

../_images/scanspec-specs-18.png

Show JSON schema
{
   "title": "Fly",
   "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
   "type": "object",
   "properties": {
      "spec": {
         "$ref": "#/$defs/Spec",
         "description": "Spec contaning the path to be followed"
      },
      "type": {
         "const": "Fly",
         "default": "Fly",
         "title": "Type",
         "type": "string"
      }
   },
   "$defs": {
      "Concat__Axis_": {
         "additionalProperties": false,
         "description": "Concatenate two Specs together, running one after the other.\n\nEach Dimension of left and right must contain the same axes. Typically\nformed using `Spec.concat`.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 3, 3).concat(Linspace(\"x\", 4, 5, 5)))",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Concat, midpoints will appear earlier"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Concat, midpoints will appear later"
            },
            "gap": {
               "default": false,
               "description": "If True, force a gap in the output at the join",
               "title": "Gap",
               "type": "boolean"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Concat",
               "default": "Concat",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Concat",
         "type": "object"
      },
      "ConstantDuration__Axis_": {
         "additionalProperties": false,
         "description": "Apply a constant duration to every point in a Spec.\n\nTypically applied with the ``@`` modifier.\n\n.. example_spec::\n\n    from scanspec.specs import Linspace\n\n    spec = 0.1 @ Linspace(\"x\", 1, 2, 3)",
         "properties": {
            "constant_duration": {
               "description": "The value at each point",
               "title": "Constant Duration",
               "type": "number"
            },
            "spec": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "null"
                  }
               ],
               "default": null,
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "ConstantDuration",
               "default": "ConstantDuration",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "constant_duration"
         ],
         "title": "ConstantDuration",
         "type": "object"
      },
      "Ellipse__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to an elliptical footprint.\n\nConstructs a 2-D scan over an axis-aligned ellipse defined by\n``(x_axis, y_axis)``, centred at (``x_centre``, ``y_centre``), with\ndiameters ``x_diameter`` and ``y_diameter``. Grid spacing along each axis is\ncontrolled by ``x_step`` and ``y_step``. If ``snake`` is True, the fast\naxis will zigzag like a snake. If ``vertical`` is True, the y axis will be\nthe fast axis.\n\nStarts from one of the four extremes of the ellipse identified by the signs of\n``x_step`` and ``y_step``.\n\n.. example_spec::\n\n    from scanspec.specs import Ellipse, Fly\n\n    # An elliptical region centred at (0, 0) on axes \"x\" and \"y\",\n    # with 10x6 diameters and steps of 0.5 in both directions.\n    spec = Fly(\n        Ellipse(\n            \"x\", 0, 10, 0.5,\n            \"y\", 0, 6,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Ellipse",
               "default": "Ellipse",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Ellipse",
         "type": "object"
      },
      "Fly__Axis_": {
         "additionalProperties": false,
         "description": "Move through lower to upper bounds of the Spec rather than stopping.\n\nThis is commonly termed a \"fly scan\" rather than a \"step scan\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 3))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "Spec contaning the path to be followed"
            },
            "type": {
               "const": "Fly",
               "default": "Fly",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Fly",
         "type": "object"
      },
      "Linspace__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as first and last midpoints.\n\nThis class is intended to handle linearly spaced frames defined with a\nspecific number of frames.\n\n.. seealso::\n    `Range`: For linearly spaced frames defined with a step size.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"x\", 1, 2, 5))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce (defaults to 1)",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Linspace",
               "default": "Linspace",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Linspace",
         "type": "object"
      },
      "Polygon__Axis_": {
         "additionalProperties": false,
         "description": "Grid of points masked to a polygonal footprint.\n\nConstructs a 2-D scan over an axis-aligned polygon defined by an ordered\nlist of vertices \"(x, y)\" given in ``vertices``. The polygon may be convex\nor concave, and the interior is determined using an even-odd ray-casting\nrule. Grid spacing along each axis is controlled by ``x_step`` and ``y_step``,\nIf ``snake`` is True, the fast axis will zigzag like a snake. If ``vertical`` is\nTrue, the y axis will be the fast axis.\n\n.. example_spec::\n\n    from scanspec.specs import Polygon, Fly\n\n    # A triangular region on axes \"x\" and \"y\", stepped by 0.2 units\n    # in both directions.\n    spec = Fly(\n        Polygon(\n            x_axis=\"x\",\n            y_axis=\"y\",\n            vertices=[(0, 0), (5, 0), (2.5, 4)],\n            x_step=0.2,\n            y_step=0.2,\n            snake=True,\n            vertical=False,\n        )\n    )",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "vertices": {
               "description": "List of (x, y) vertices defining the polygon",
               "items": {
                  "maxItems": 2,
                  "minItems": 2,
                  "prefixItems": [
                     {
                        "type": "number"
                     },
                     {
                        "type": "number"
                     }
                  ],
                  "type": "array"
               },
               "title": "Vertices",
               "type": "array"
            },
            "x_step": {
               "description": "Spacing along x",
               "exclusiveMinimum": 0,
               "title": "X Step",
               "type": "number"
            },
            "y_step": {
               "description": "Spacing along y (defaults to x_step)",
               "exclusiveMinimum": 0,
               "title": "Y Step",
               "type": "number"
            },
            "snake": {
               "default": false,
               "description": "If True, path zigzag like a snake (defaults to False)",
               "title": "Snake",
               "type": "boolean"
            },
            "vertical": {
               "default": false,
               "description": "If True, y axis is the fast axis (defaults to False)",
               "title": "Vertical",
               "type": "boolean"
            },
            "type": {
               "const": "Polygon",
               "default": "Polygon",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "y_axis",
            "vertices",
            "x_step"
         ],
         "title": "Polygon",
         "type": "object"
      },
      "Product__Axis_": {
         "additionalProperties": false,
         "description": "Outer product of two Specs, nesting inner within outer.\n\nThis means that inner will run in its entirety at each point in outer.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 3, 4, 12))\n\nAn inner integer can be used to repeat the same point many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3) * 2)\n\nAn outer integer can be used to repeat the same scan many times.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(2 * ~Linspace.bounded(\"x\", 3, 4, 1))\n\nIf you want snaked axes to have no gap between iterations you can do:\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Product\n\n    spec = Fly(Product(2, ~Linspace.bounded(\"x\", 3, 4, 1), gap=False))\n\n.. note:: There is no turnaround arrow at x=4",
         "properties": {
            "outer": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed once",
               "title": "Outer"
            },
            "inner": {
               "anyOf": [
                  {
                     "$ref": "#/$defs/Spec"
                  },
                  {
                     "type": "integer"
                  }
               ],
               "description": "Will be executed len(outer) times",
               "title": "Inner"
            },
            "gap": {
               "default": true,
               "description": "If False and the outer spec is an integer and the inner spec is snaked then the end and start of consecutive iterations of inner will have no gap",
               "title": "Gap",
               "type": "boolean"
            },
            "type": {
               "const": "Product",
               "default": "Product",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "outer",
            "inner"
         ],
         "title": "Product",
         "type": "object"
      },
      "Range__Axis_": {
         "additionalProperties": false,
         "description": "Linearly spaced frames with start and stop as the bounding midpoints.\n\n``step`` defines the distance between midpoints.\n\n.. seealso::\n    `Linspace`: For linearly spaced frames defined with a number of frames.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Range\n\n    spec = Fly(Range(\"x\", 1, 2, 0.25))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "start": {
               "description": "Midpoint of the first point of the line",
               "title": "Start",
               "type": "number"
            },
            "stop": {
               "description": "Midpoint of the last point of the line",
               "title": "Stop",
               "type": "number"
            },
            "step": {
               "description": "Step size (defaults to stop - start)",
               "exclusiveMinimum": 0,
               "title": "Step",
               "type": "number"
            },
            "type": {
               "const": "Range",
               "default": "Range",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "start",
            "stop"
         ],
         "title": "Range",
         "type": "object"
      },
      "Snake__Axis_": {
         "additionalProperties": false,
         "description": "Run the Spec in reverse on every other iteration when nested.\n\nTypically created with the ``~`` operator.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(Linspace(\"y\", 1, 3, 3) * ~Linspace(\"x\", 3, 5, 5))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to run in reverse every other iteration"
            },
            "type": {
               "const": "Snake",
               "default": "Snake",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Snake",
         "type": "object"
      },
      "Spec": {
         "discriminator": {
            "mapping": {
               "Concat": "#/$defs/Concat__Axis_",
               "ConstantDuration": "#/$defs/ConstantDuration__Axis_",
               "Ellipse": "#/$defs/Ellipse__Axis_",
               "Fly": "#/$defs/Fly__Axis_",
               "Linspace": "#/$defs/Linspace__Axis_",
               "Polygon": "#/$defs/Polygon__Axis_",
               "Product": "#/$defs/Product__Axis_",
               "Range": "#/$defs/Range__Axis_",
               "Snake": "#/$defs/Snake__Axis_",
               "Spiral": "#/$defs/Spiral__Axis_",
               "Squash": "#/$defs/Squash__Axis_",
               "Static": "#/$defs/Static__Axis_",
               "Zip": "#/$defs/Zip__Axis_"
            },
            "propertyName": "type"
         },
         "oneOf": [
            {
               "$ref": "#/$defs/Product__Axis_"
            },
            {
               "$ref": "#/$defs/Zip__Axis_"
            },
            {
               "$ref": "#/$defs/Snake__Axis_"
            },
            {
               "$ref": "#/$defs/Concat__Axis_"
            },
            {
               "$ref": "#/$defs/Squash__Axis_"
            },
            {
               "$ref": "#/$defs/Linspace__Axis_"
            },
            {
               "$ref": "#/$defs/Range__Axis_"
            },
            {
               "$ref": "#/$defs/Fly__Axis_"
            },
            {
               "$ref": "#/$defs/ConstantDuration__Axis_"
            },
            {
               "$ref": "#/$defs/Static__Axis_"
            },
            {
               "$ref": "#/$defs/Spiral__Axis_"
            },
            {
               "$ref": "#/$defs/Ellipse__Axis_"
            },
            {
               "$ref": "#/$defs/Polygon__Axis_"
            }
         ]
      },
      "Spiral__Axis_": {
         "additionalProperties": false,
         "description": "Archimedean spiral of \"x_axis\" and \"y_axis\".\n\nStarts at centre point (\"x_start\", \"y_start\")\". Produces \"num\" points in a\nspiral spanning width of \"x_range\" and height of \"y_range\"\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Spiral\n\n    spec = Fly(Spiral(\"x\", 1, 10, 2.5, \"y\", 5, 50))",
         "properties": {
            "x_axis": {
               "description": "An identifier for what to move for x",
               "title": "X Axis"
            },
            "x_centre": {
               "description": "x centre of the spiral",
               "title": "X Centre",
               "type": "number"
            },
            "x_diameter": {
               "description": "x width of the spiral",
               "title": "X Diameter",
               "type": "number"
            },
            "x_step": {
               "description": "Radial spacing along x",
               "title": "X Step",
               "type": "number"
            },
            "y_axis": {
               "description": "An identifier for what to move for y",
               "title": "Y Axis"
            },
            "y_centre": {
               "description": "y centre of the spiral",
               "title": "Y Centre",
               "type": "number"
            },
            "y_diameter": {
               "description": "y width of the spiral (defaults to x_diameter)",
               "title": "Y Diameter",
               "type": "number"
            },
            "type": {
               "const": "Spiral",
               "default": "Spiral",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "x_axis",
            "x_centre",
            "x_diameter",
            "x_step",
            "y_axis",
            "y_centre"
         ],
         "title": "Spiral",
         "type": "object"
      },
      "Squash__Axis_": {
         "additionalProperties": false,
         "description": "Squash a stack of Dimension together into a single expanded Dimension object.\n\nSee Also:\n    `why-squash-can-change-path`\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Squash\n\n    spec = Fly(Squash(Linspace(\"y\", 1, 2, 3) * Linspace(\"x\", 0, 1, 4)))",
         "properties": {
            "spec": {
               "$ref": "#/$defs/Spec",
               "description": "The Spec to squash the dimensions of"
            },
            "check_path_changes": {
               "default": true,
               "description": "If True path through scan will not be modified by squash",
               "title": "Check Path Changes",
               "type": "boolean"
            },
            "type": {
               "const": "Squash",
               "default": "Squash",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "spec"
         ],
         "title": "Squash",
         "type": "object"
      },
      "Static__Axis_": {
         "additionalProperties": false,
         "description": "A static frame, repeated num times, with axis at value.\n\nCan be used to set axis=value at every point in a scan.\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace, Static\n\n    spec = Fly(Linspace(\"y\", 1, 2, 3).zip(Static(\"x\", 3)))",
         "properties": {
            "axis": {
               "description": "An identifier for what to move",
               "title": "Axis"
            },
            "value": {
               "description": "The value at each point",
               "title": "Value",
               "type": "number"
            },
            "num": {
               "default": 1,
               "description": "Number of frames to produce",
               "minimum": 1,
               "title": "Num",
               "type": "integer"
            },
            "type": {
               "const": "Static",
               "default": "Static",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "axis",
            "value"
         ],
         "title": "Static",
         "type": "object"
      },
      "Zip__Axis_": {
         "additionalProperties": false,
         "description": "Run two Specs in parallel, merging their midpoints together.\n\nTypically formed using `Spec.zip`.\n\nStacks of Dimension are merged by:\n\n- If right creates a stack of a single Dimension object of size 1, expand it to\n  the size of the fastest Dimension object created by left\n- Merge individual Dimension objects together from fastest to slowest\n\nThis means that Zipping a Spec producing stack [l2, l1] with a Spec\nproducing stack [r1] will assert len(l1)==len(r1), and produce\nstack [l2, l1.zip(r1)].\n\n.. example_spec::\n\n    from scanspec.specs import Fly, Linspace\n\n    spec = Fly(\n        Linspace(\"z\", 1, 2, 3) * Linspace(\"y\", 3, 4, 5).zip(Linspace(\"x\", 4, 5, 5))\n    )",
         "properties": {
            "left": {
               "$ref": "#/$defs/Spec",
               "description": "The left-hand Spec to Zip, will appear earlier in axes"
            },
            "right": {
               "$ref": "#/$defs/Spec",
               "description": "The right-hand Spec to Zip, will appear later in axes"
            },
            "type": {
               "const": "Zip",
               "default": "Zip",
               "title": "Type",
               "type": "string"
            }
         },
         "required": [
            "left",
            "right"
         ],
         "title": "Zip",
         "type": "object"
      }
   },
   "additionalProperties": false,
   "required": [
      "spec"
   ]
}

Fields:
field spec: Spec[Axis] [Required]#

Spec contaning the path to be followed

field type: Literal['Fly'] = 'Fly'#
axes() list[Axis][source]#

Return the list of axes that are present in the scan.

Ordered from slowest moving to fastest moving.

calculate(bounds: bool = False, nested: bool = False) list[Dimension[Axis]][source]#

Produce a stack of nested Dimension that form the scan.

Ordered from slowest moving to fastest moving.

duration() float | None | Literal['VARIABLE_DURATION'][source]#

Returns the duration of each scan point.

Return value will be one of: - None: No duration defined - float: A constant duration for each point - VARIABLE_DURATION: A different duration for each point

scanspec.specs.step(spec: Spec[Axis], duration: float, num: int = 1) Spec[Axis][source]#

Step scan, with num frames of given duration at each frame in the spec.

Parameters:
  • spec – The source Spec with midpoints to move to and stop

  • duration – The duration of each scan frame

  • num – Number of frames to produce with given duration at each of frame in the spec

Deprecated since version 1.0.0: You should use ConstantDuration instead.

scanspec.specs.fly(spec: Spec[Axis], duration: float) Spec[Axis | str][source]#

Flyscan, zipping with fixed duration for every frame.

Parameters:
  • spec – The source Spec to continuously move

  • duration – How long to spend at each frame in the spec

Deprecated since version 1.0.0: You should use Fly and ConstantDuration instead

scanspec.specs.VARIABLE_DURATION = 'VARIABLE_DURATION'#

A string returned from Spec.duration to signify it produces a different duration for each point