Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2702165
Initial implementation of the new Duration Spec
LuisFSegalla Jul 9, 2025
2d2bf5a
Update Duration spec
LuisFSegalla Jul 10, 2025
763662b
Updates for the PR
LuisFSegalla Jul 11, 2025
3c51577
Removed DURATION and updated concat concat method
LuisFSegalla Jul 15, 2025
13f38b3
docstring tidy up
LuisFSegalla Jul 15, 2025
301d34a
Updated schema
LuisFSegalla Jul 18, 2025
cf2a2a5
Updated Specs
LuisFSegalla Jul 18, 2025
6eeccd7
Updated tests
LuisFSegalla Jul 18, 2025
6e27691
PR changes
LuisFSegalla Jul 23, 2025
7968f78
Updated calculate method on ConstantDuration class
LuisFSegalla Jul 24, 2025
c6e036f
Updated tests
LuisFSegalla Jul 24, 2025
84323dd
Updated Specs
LuisFSegalla Jul 24, 2025
9ee85ea
Updated schema.json
LuisFSegalla Jul 24, 2025
ffb8eb7
PR changes
LuisFSegalla Jul 25, 2025
b928267
Updated documentation
LuisFSegalla Jul 25, 2025
51635a6
Enforced version of Pillow to fix broken cli tests
LuisFSegalla Jul 25, 2025
c04a517
Removing unreacheable part of the code
LuisFSegalla Jul 25, 2025
5c37b6f
Removing fly function
LuisFSegalla Jul 28, 2025
b97a946
Remove type ignores
coretl Jul 28, 2025
466bd52
Moved Pillow dependency to dev
LuisFSegalla Jul 28, 2025
5e09873
Updated check statements on Dimension class
LuisFSegalla Jul 28, 2025
8127d55
Made bounds default to false and changed Duration return
LuisFSegalla Jul 28, 2025
633b197
Updated tests based on new `bounds` change
LuisFSegalla Jul 28, 2025
b4e9470
Updated spec.py
LuisFSegalla Jul 28, 2025
1be894d
Updated tests
LuisFSegalla Jul 28, 2025
63f86ea
Updated test
LuisFSegalla Jul 29, 2025
27e4038
Updated docs
LuisFSegalla Jul 29, 2025
0ecbfe4
Updated README.md
LuisFSegalla Jul 29, 2025
9c81919
Fix typos
LuisFSegalla Jul 29, 2025
0322a09
Remove DURATION after rebase
LuisFSegalla Jul 29, 2025
ec79cb0
Small changes
LuisFSegalla Jul 29, 2025
698016d
Fixing __rmatmul__
LuisFSegalla Jul 30, 2025
8480790
Updated tests to improve code coverage
LuisFSegalla Jul 30, 2025
bba0105
Updated Tests
LuisFSegalla Jul 30, 2025
6e997f1
Updated README.md
LuisFSegalla Jul 30, 2025
d0d7cb3
Updating cases where ConstantDuration was used to use @ instead
LuisFSegalla Jul 30, 2025
12e3983
Fix docs
LuisFSegalla Jul 30, 2025
2555880
Updated all tests to use @ instead of ConstantDuration
LuisFSegalla Jul 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ An example ScanSpec of a 2D snaked grid flyscan inside a circle spending 0.4s at
each point:

```python
from scanspec.specs import Line, fly
from scanspec.specs import Line, Fly
from scanspec.regions import Circle

grid = Line(y, 2.1, 3.8, 12) * ~Line(x, 0.5, 1.5, 10)
spec = fly(grid, 0.4) & Circle(x, y, 1.0, 2.8, radius=0.5)
spec = Fly(0.4 @ grid) & Circle(x, y, 1.0, 2.8, radius=0.5)
```

Which when plotted looks like:
Expand All @@ -48,8 +48,8 @@ Scan points can be iterated through directly for convenience:
for point in spec.midpoints():
print(point)
# ...
# {'y': 3.1818181818181817, 'x': 0.8333333333333333, 'DURATION': 0.4}
# {'y': 3.1818181818181817, 'x': 0.7222222222222222, 'DURATION': 0.4}
# {'y': 3.1818181818181817, 'x': 0.8333333333333333}
# {'y': 3.1818181818181817, 'x': 0.7222222222222222}
```

or a Path created from the stack of Frames and chunks of a given length
Expand All @@ -60,12 +60,13 @@ from scanspec.core import Path

stack = spec.calculate()
len(stack[0]) # 44
stack[0].axes() # ['y', 'x', 'DURATION']
stack[0].axes() # ['y', 'x']

path = Path(stack, start=5, num=30)
chunk = path.consume(10)
chunk.midpoints # {'x': <ndarray len=10>, 'y': <ndarray len=10>, 'DURATION': <ndarray len=10>}
chunk.midpoints # {'x': <ndarray len=10>, 'y': <ndarray len=10>}
chunk.upper # bounds are same dimensionality as positions
chunk.duration # duration of each frame
```

<!-- README only content. Anything below this line won't be included in index.md -->
Expand Down
4 changes: 2 additions & 2 deletions docs/explanations/technical-terms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ as `Dimension.lower`, `Dimension.midpoints` and `Dimension.upper`.
.. _frame_:

Dimension
-----
---------

A vector of three `Points <point_>` in scan space: lower, midpoint, upper. They
describe the trajectory that should be taken while a detector is active while
Expand All @@ -40,7 +40,7 @@ section.
.. _stack_:

Stack of Dimensions
---------------
-------------------

A repeatable, possibly snaking, series of `Dimension` along a number of `Axes
<axis_>`. In the diagram above, the whole Line produces a single `Dimension`
Expand Down
2 changes: 1 addition & 1 deletion docs/explanations/why-squash-can-change-path.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ is the case.
will fail with `ValueError`

Squash unsnaked axis into a snaked Dimensions
-----------------------------------------
---------------------------------------------

Squashing Dimension objects together will take the snake setting of the slowest
moving Dimension object in the squash. If this squashed Dimension object is nested
Expand Down
9 changes: 5 additions & 4 deletions docs/how-to/iterate-a-spec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ If you need to do a fly scan

If you are conducting a fly scan then you need the frames that the motor moves
through. You can get that from the lower and upper bounds of each point. If the
scan is small enough to fit in memory on the machine you can use the `Spec.frames()`
scan is small enough to fit in memory on the machine you can use the `Fly(spec).frames()`
method to produce a single `Dimension` object containing the entire scan:

>>> segment = spec.frames()
>>> from scanspec.specs import Fly
>>> segment = Fly(spec).frames()
>>> len(segment)
3
>>> segment.lower
Expand Down Expand Up @@ -89,8 +90,8 @@ You may need to know where there is a gap between points, so that you can do
something in the turnaround. For example, if we take the x axis of a grid scan,
you can see it snakes back and forth:

>>> from scanspec.specs import Line, fly
>>> grid = fly(Line("y", 0, 1, 2) * ~Line("x", 1, 2, 3), 0.1)
>>> from scanspec.specs import Line, Fly
>>> grid = Fly(0.1 @ (Line("y", 0, 1, 2) * ~Line("x", 1, 2, 3)))
>>> chunk = grid.frames()
>>> chunk.midpoints["x"]
array([1. , 1.5, 2. , 2. , 1.5, 1. ])
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dev = [
"sphinxcontrib-openapi",
"tox-direct",
"types-mock",
"Pillow==11.0.0",
]

[project.scripts]
Expand Down
124 changes: 124 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,72 @@
"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 Line\n\n spec = Line(\"x\", 1, 3, 3).concat(Line(\"x\", 4, 5, 5))"
},
"ConstantDuration_str_-Input": {
"properties": {
"constant_duration": {
"type": "number",
"title": "Constant Duration",
"description": "The value at each point"
},
"spec": {
"anyOf": [
{
"$ref": "#/components/schemas/Spec-Input"
},
{
"type": "null"
}
],
"description": "Spec contaning the path to be followed"
},
"type": {
"type": "string",
"const": "ConstantDuration",
"title": "Type",
"default": "ConstantDuration"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"constant_duration"
],
"title": "ConstantDuration",
"description": "A special spec used to hold information about the duration of each frame."
},
"ConstantDuration_str_-Output": {
"properties": {
"constant_duration": {
"type": "number",
"title": "Constant Duration",
"description": "The value at each point"
},
"spec": {
"anyOf": [
{
"$ref": "#/components/schemas/Spec-Output"
},
{
"type": "null"
}
],
"description": "Spec contaning the path to be followed"
},
"type": {
"type": "string",
"const": "ConstantDuration",
"title": "Type",
"default": "ConstantDuration"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"constant_duration"
],
"title": "ConstantDuration",
"description": "A special spec used to hold information about the duration of each frame."
},
"DifferenceOf_str_-Input": {
"properties": {
"left": {
Expand Down Expand Up @@ -657,6 +723,48 @@
"title": "Ellipse",
"description": "Mask contains points of axis within an xy ellipse of given radius.\n\n.. example_spec::\n\n from scanspec.regions import Ellipse\n from scanspec.specs import Line\n\n grid = Line(\"y\", 3, 8, 10) * ~Line(\"x\", 1 ,8, 10)\n spec = grid & Ellipse(\"x\", \"y\", 5, 5, 2, 3, 75)"
},
"Fly_str_-Input": {
"properties": {
"spec": {
"$ref": "#/components/schemas/Spec-Input",
"description": "Spec contaning the path to be followed"
},
"type": {
"type": "string",
"const": "Fly",
"title": "Type",
"default": "Fly"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"spec"
],
"title": "Fly",
"description": "Spec that represents a fly scan."
},
"Fly_str_-Output": {
"properties": {
"spec": {
"$ref": "#/components/schemas/Spec-Output",
"description": "Spec contaning the path to be followed"
},
"type": {
"type": "string",
"const": "Fly",
"title": "Type",
"default": "Fly"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"spec"
],
"title": "Fly",
"description": "Spec that represents a fly scan."
},
"GapResponse": {
"properties": {
"gap": {
Expand Down Expand Up @@ -1343,6 +1451,12 @@
{
"$ref": "#/components/schemas/Line_str_"
},
{
"$ref": "#/components/schemas/Fly_str_-Input"
},
{
"$ref": "#/components/schemas/ConstantDuration_str_-Input"
},
{
"$ref": "#/components/schemas/Static_str_"
},
Expand All @@ -1354,6 +1468,8 @@
"propertyName": "type",
"mapping": {
"Concat": "#/components/schemas/Concat_str_-Input",
"ConstantDuration": "#/components/schemas/ConstantDuration_str_-Input",
"Fly": "#/components/schemas/Fly_str_-Input",
"Line": "#/components/schemas/Line_str_",
"Mask": "#/components/schemas/Mask_str_-Input",
"Product": "#/components/schemas/Product_str_-Input",
Expand Down Expand Up @@ -1392,6 +1508,12 @@
{
"$ref": "#/components/schemas/Line_str_"
},
{
"$ref": "#/components/schemas/Fly_str_-Output"
},
{
"$ref": "#/components/schemas/ConstantDuration_str_-Output"
},
{
"$ref": "#/components/schemas/Static_str_"
},
Expand All @@ -1403,6 +1525,8 @@
"propertyName": "type",
"mapping": {
"Concat": "#/components/schemas/Concat_str_-Output",
"ConstantDuration": "#/components/schemas/ConstantDuration_str_-Output",
"Fly": "#/components/schemas/Fly_str_-Output",
"Line": "#/components/schemas/Line_str_",
"Mask": "#/components/schemas/Mask_str_-Output",
"Product": "#/components/schemas/Product_str_-Output",
Expand Down
Loading
Loading