atomscale 0.8.3__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. atomscale-0.9.0/PKG-INFO +119 -0
  2. atomscale-0.9.0/README.md +70 -0
  3. atomscale-0.9.0/docs/_static/AtomscaleLogoFull.png +0 -0
  4. atomscale-0.9.0/docs/_static/custom.css +38 -0
  5. {atomscale-0.8.3 → atomscale-0.9.0}/docs/conf.py +11 -27
  6. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/index.rst +1 -0
  7. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/inspect-results.rst +35 -0
  8. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/poll-timeseries.rst +27 -4
  9. atomscale-0.9.0/docs/guides/poll-trajectory.rst +219 -0
  10. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/quickstart.rst +23 -7
  11. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/search-data.rst +43 -1
  12. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/stream-rheed.rst +43 -13
  13. {atomscale-0.8.3 → atomscale-0.9.0}/docs/guides/upload-data.rst +19 -4
  14. {atomscale-0.8.3 → atomscale-0.9.0}/docs/index.rst +6 -6
  15. {atomscale-0.8.3 → atomscale-0.9.0}/docs/modules.rst +2 -0
  16. {atomscale-0.8.3 → atomscale-0.9.0}/pyproject.toml +1 -1
  17. atomscale-0.9.0/src/atomscale/similarity/__init__.py +23 -0
  18. atomscale-0.9.0/src/atomscale/similarity/polling.py +293 -0
  19. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/__init__.py +10 -2
  20. atomscale-0.9.0/src/atomscale/timeseries/_polling_utils.py +29 -0
  21. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/polling.py +4 -24
  22. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/registry.py +2 -1
  23. atomscale-0.9.0/src/atomscale.egg-info/PKG-INFO +119 -0
  24. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale.egg-info/SOURCES.txt +7 -1
  25. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale.egg-info/requires.txt +1 -1
  26. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_polling.py +287 -0
  27. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_similarity_trajectory.py +1 -1
  28. atomscale-0.8.3/PKG-INFO +0 -66
  29. atomscale-0.8.3/README.md +0 -17
  30. atomscale-0.8.3/src/atomscale.egg-info/PKG-INFO +0 -66
  31. {atomscale-0.8.3 → atomscale-0.9.0}/.github/workflows/release.yml +0 -0
  32. {atomscale-0.8.3 → atomscale-0.9.0}/.github/workflows/testing.yml +0 -0
  33. {atomscale-0.8.3 → atomscale-0.9.0}/.github/workflows/upgrade_dependencies.yml +0 -0
  34. {atomscale-0.8.3 → atomscale-0.9.0}/.gitignore +0 -0
  35. {atomscale-0.8.3 → atomscale-0.9.0}/.pre-commit-config.yaml +0 -0
  36. {atomscale-0.8.3 → atomscale-0.9.0}/CHANGELOG.md +0 -0
  37. {atomscale-0.8.3 → atomscale-0.9.0}/LICENSE +0 -0
  38. {atomscale-0.8.3 → atomscale-0.9.0}/MANIFEST.in +0 -0
  39. {atomscale-0.8.3 → atomscale-0.9.0}/atomicds-shim-dist/pyproject.toml +0 -0
  40. {atomscale-0.8.3 → atomscale-0.9.0}/docs/Makefile +0 -0
  41. {atomscale-0.8.3 → atomscale-0.9.0}/docs/_templates/custom-class-template.rst +0 -0
  42. {atomscale-0.8.3 → atomscale-0.9.0}/docs/_templates/custom-module-template.rst +0 -0
  43. {atomscale-0.8.3 → atomscale-0.9.0}/docs/make.bat +0 -0
  44. {atomscale-0.8.3 → atomscale-0.9.0}/examples/general_use.ipynb +0 -0
  45. {atomscale-0.8.3 → atomscale-0.9.0}/examples/rheed_streaming.ipynb +0 -0
  46. {atomscale-0.8.3 → atomscale-0.9.0}/examples/timeseries_polling.ipynb +0 -0
  47. {atomscale-0.8.3 → atomscale-0.9.0}/examples/vxwse2-placeholder/task1_films.ipynb +0 -0
  48. {atomscale-0.8.3 → atomscale-0.9.0}/examples/vxwse2-placeholder/task1_sapphire.ipynb +0 -0
  49. {atomscale-0.8.3 → atomscale-0.9.0}/examples/vxwse2-placeholder/task2_composition.ipynb +0 -0
  50. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.10.txt +0 -0
  51. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.10_extras.txt +0 -0
  52. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.11.txt +0 -0
  53. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.11_extras.txt +0 -0
  54. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.12.txt +0 -0
  55. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.12_extras.txt +0 -0
  56. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.9.txt +0 -0
  57. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-macos-latest_py3.9_extras.txt +0 -0
  58. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.10.txt +0 -0
  59. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.10_extras.txt +0 -0
  60. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.11.txt +0 -0
  61. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.11_extras.txt +0 -0
  62. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.12.txt +0 -0
  63. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.12_extras.txt +0 -0
  64. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.9.txt +0 -0
  65. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-ubuntu-latest_py3.9_extras.txt +0 -0
  66. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.10.txt +0 -0
  67. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.10_extras.txt +0 -0
  68. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.11.txt +0 -0
  69. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.11_extras.txt +0 -0
  70. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.12.txt +0 -0
  71. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.12_extras.txt +0 -0
  72. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.9.txt +0 -0
  73. {atomscale-0.8.3 → atomscale-0.9.0}/requirements/requirements-windows-latest_py3.9_extras.txt +0 -0
  74. {atomscale-0.8.3 → atomscale-0.9.0}/setup.cfg +0 -0
  75. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomicds/__init__.py +0 -0
  76. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/__init__.py +0 -0
  77. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/client.py +0 -0
  78. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/core/__init__.py +0 -0
  79. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/core/client.py +0 -0
  80. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/core/files.py +0 -0
  81. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/core/utils.py +0 -0
  82. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/__init__.py +0 -0
  83. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/group.py +0 -0
  84. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/metrology.py +0 -0
  85. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/optical.py +0 -0
  86. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/photoluminescence.py +0 -0
  87. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/raman.py +0 -0
  88. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/rheed_image.py +0 -0
  89. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/rheed_video.py +0 -0
  90. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/similarity_trajectory.py +0 -0
  91. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/unknown.py +0 -0
  92. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/results/xps.py +0 -0
  93. /atomscale-0.8.3/src/atomscale/timeseries/similarity.py → /atomscale-0.9.0/src/atomscale/similarity/provider.py +0 -0
  94. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/Cargo.lock +0 -0
  95. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/Cargo.toml +0 -0
  96. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/__init__.py +0 -0
  97. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/rheed_stream.pyi +0 -0
  98. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/src/initialize.rs +0 -0
  99. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/src/lib.rs +0 -0
  100. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/src/upload.rs +0 -0
  101. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/streaming/src/utils.rs +0 -0
  102. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/align.py +0 -0
  103. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/metrology.py +0 -0
  104. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/optical.py +0 -0
  105. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/provider.py +0 -0
  106. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/rheed.py +0 -0
  107. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale/timeseries/sample.py +0 -0
  108. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale.egg-info/dependency_links.txt +0 -0
  109. {atomscale-0.8.3 → atomscale-0.9.0}/src/atomscale.egg-info/top_level.txt +0 -0
  110. {atomscale-0.8.3 → atomscale-0.9.0}/tests/__init__.py +0 -0
  111. {atomscale-0.8.3 → atomscale-0.9.0}/tests/_mock_http_server.py +0 -0
  112. {atomscale-0.8.3 → atomscale-0.9.0}/tests/conftest.py +0 -0
  113. {atomscale-0.8.3 → atomscale-0.9.0}/tests/data/test_rheed.mp4 +0 -0
  114. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_atomicds_alias.py +0 -0
  115. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_client.py +0 -0
  116. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_core.py +0 -0
  117. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_metrology.py +0 -0
  118. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_optical.py +0 -0
  119. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_photoluminescence.py +0 -0
  120. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_raman.py +0 -0
  121. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_rheed_image.py +0 -0
  122. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_rheed_stream.py +0 -0
  123. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_rheed_video.py +0 -0
  124. {atomscale-0.8.3 → atomscale-0.9.0}/tests/test_xps.py +0 -0
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: atomscale
3
+ Version: 0.9.0
4
+ Summary: Python SDK for Atomscale.
5
+ Author-email: Atomscale <info@atomscale.ai>
6
+ License: GPL-3.0-only
7
+ Project-URL: Homepage, https://www.atomscale.ai
8
+ Project-URL: Documentation, https://atomscale-ai.github.io/sdk
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Topic :: Scientific/Engineering
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: Unix
18
+ Classifier: Operating System :: MacOS
19
+ Requires-Python: <3.13,>=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: numpy
23
+ Requires-Dist: pandas
24
+ Requires-Dist: monty
25
+ Requires-Dist: pillow
26
+ Requires-Dist: networkx
27
+ Requires-Dist: requests
28
+ Requires-Dist: rich
29
+ Requires-Dist: matplotlib
30
+ Requires-Dist: pycocotools
31
+ Requires-Dist: trackpy
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest; extra == "dev"
34
+ Requires-Dist: pytest-httpserver; extra == "dev"
35
+ Requires-Dist: pytest-cov; extra == "dev"
36
+ Requires-Dist: pytest-order; extra == "dev"
37
+ Requires-Dist: pytest-dependency; extra == "dev"
38
+ Requires-Dist: pytest-asyncio; extra == "dev"
39
+ Requires-Dist: ruff>=0.9.0; extra == "dev"
40
+ Requires-Dist: ty; extra == "dev"
41
+ Requires-Dist: types-requests; extra == "dev"
42
+ Requires-Dist: pandas-stubs; extra == "dev"
43
+ Requires-Dist: pre-commit>=4.0.0; extra == "dev"
44
+ Provides-Extra: docs
45
+ Requires-Dist: sphinx>=6.2; extra == "docs"
46
+ Requires-Dist: sphinx-autodoc-typehints>=1.24; extra == "docs"
47
+ Requires-Dist: sphinxawesome-theme>=5.0; extra == "docs"
48
+ Dynamic: license-file
49
+
50
+ <p align="center">
51
+ <img src="docs/_static/AtomscaleLogoFull.png" alt="Atomscale" width="300">
52
+ </p>
53
+
54
+ <h1 align="center">Python SDK</h1>
55
+
56
+ <p align="center">
57
+ <a href="https://github.com/atomscale-ai/sdk/actions/workflows/testing.yml?query=branch%3Amain"><img src="https://github.com/atomscale-ai/sdk/actions/workflows/testing.yml/badge.svg?branch=main" alt="Testing"></a>
58
+ <a href="https://github.com/atomscale-ai/sdk/releases/"><img src="https://img.shields.io/github/tag/atomscale-ai/sdk?include_prereleases=&sort=semver&color=blue" alt="GitHub tag"></a>
59
+ <img src="https://img.shields.io/badge/Python-3.10+-blue.svg?logo=python&logoColor=white" alt="Python">
60
+ <a href="#license"><img src="https://img.shields.io/badge/License-MPL_2.0-blue" alt="License"></a>
61
+ </p>
62
+
63
+ <p align="center">
64
+ <a href="https://atomscale-ai.github.io/sdk/"><img src="https://img.shields.io/badge/view-Documentation-blue?style=for-the-badge" alt="Documentation"></a>
65
+ </p>
66
+
67
+ ---
68
+
69
+ The official Python SDK for the [Atomscale](https://www.atomscale.ai) platform. Upload RHEED videos, stream live data, search the catalogue, and retrieve analysis results programmatically.
70
+
71
+ ## Features
72
+
73
+ - **Unified Client** – Single interface for uploads, search, and downloads
74
+ - **Live Streaming** – Push or pull RHEED frames in real-time
75
+ - **Flexible Search** – Filter by keywords, data type, status, or time bounds
76
+ - **Rich Results** – Access timeseries, diffraction graphs, and processed videos
77
+ - **Polling Utilities** – Sync, async, and threaded options for monitoring updates
78
+
79
+ ## Installation
80
+
81
+ ```bash
82
+ pip install atomscale
83
+ ```
84
+
85
+ > **Note:** The package was renamed from `atomicds`. Importing `atomicds` still works but emits a `DeprecationWarning`.
86
+
87
+ ## Quick Start
88
+
89
+ ```python
90
+ from atomscale import Client
91
+
92
+ # Create a client (reads AS_API_KEY from environment)
93
+ client = Client()
94
+
95
+ # Upload files
96
+ client.upload(files=["rheed_video.mp4"])
97
+
98
+ # Search the catalogue
99
+ results = client.search(keywords=["GaN"], status="success")
100
+
101
+ # Fetch analysis results
102
+ items = client.get(results["Data ID"].to_list())
103
+ for item in items:
104
+ print(item.timeseries_data.tail())
105
+ ```
106
+
107
+ ## Documentation
108
+
109
+ Full documentation is available at **[atomscale-ai.github.io/sdk](https://atomscale-ai.github.io/sdk/)**.
110
+
111
+ - [Quickstart Guide](https://atomscale-ai.github.io/sdk/guides/quickstart.html)
112
+ - [Upload Data](https://atomscale-ai.github.io/sdk/guides/upload-data.html)
113
+ - [Search the Catalogue](https://atomscale-ai.github.io/sdk/guides/search-data.html)
114
+ - [Stream RHEED Video](https://atomscale-ai.github.io/sdk/guides/stream-rheed.html)
115
+ - [API Reference](https://atomscale-ai.github.io/sdk/modules.html)
116
+
117
+ ## License
118
+
119
+ This project is licensed under the [Mozilla Public License 2.0](LICENSE).
@@ -0,0 +1,70 @@
1
+ <p align="center">
2
+ <img src="docs/_static/AtomscaleLogoFull.png" alt="Atomscale" width="300">
3
+ </p>
4
+
5
+ <h1 align="center">Python SDK</h1>
6
+
7
+ <p align="center">
8
+ <a href="https://github.com/atomscale-ai/sdk/actions/workflows/testing.yml?query=branch%3Amain"><img src="https://github.com/atomscale-ai/sdk/actions/workflows/testing.yml/badge.svg?branch=main" alt="Testing"></a>
9
+ <a href="https://github.com/atomscale-ai/sdk/releases/"><img src="https://img.shields.io/github/tag/atomscale-ai/sdk?include_prereleases=&sort=semver&color=blue" alt="GitHub tag"></a>
10
+ <img src="https://img.shields.io/badge/Python-3.10+-blue.svg?logo=python&logoColor=white" alt="Python">
11
+ <a href="#license"><img src="https://img.shields.io/badge/License-MPL_2.0-blue" alt="License"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://atomscale-ai.github.io/sdk/"><img src="https://img.shields.io/badge/view-Documentation-blue?style=for-the-badge" alt="Documentation"></a>
16
+ </p>
17
+
18
+ ---
19
+
20
+ The official Python SDK for the [Atomscale](https://www.atomscale.ai) platform. Upload RHEED videos, stream live data, search the catalogue, and retrieve analysis results programmatically.
21
+
22
+ ## Features
23
+
24
+ - **Unified Client** – Single interface for uploads, search, and downloads
25
+ - **Live Streaming** – Push or pull RHEED frames in real-time
26
+ - **Flexible Search** – Filter by keywords, data type, status, or time bounds
27
+ - **Rich Results** – Access timeseries, diffraction graphs, and processed videos
28
+ - **Polling Utilities** – Sync, async, and threaded options for monitoring updates
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install atomscale
34
+ ```
35
+
36
+ > **Note:** The package was renamed from `atomicds`. Importing `atomicds` still works but emits a `DeprecationWarning`.
37
+
38
+ ## Quick Start
39
+
40
+ ```python
41
+ from atomscale import Client
42
+
43
+ # Create a client (reads AS_API_KEY from environment)
44
+ client = Client()
45
+
46
+ # Upload files
47
+ client.upload(files=["rheed_video.mp4"])
48
+
49
+ # Search the catalogue
50
+ results = client.search(keywords=["GaN"], status="success")
51
+
52
+ # Fetch analysis results
53
+ items = client.get(results["Data ID"].to_list())
54
+ for item in items:
55
+ print(item.timeseries_data.tail())
56
+ ```
57
+
58
+ ## Documentation
59
+
60
+ Full documentation is available at **[atomscale-ai.github.io/sdk](https://atomscale-ai.github.io/sdk/)**.
61
+
62
+ - [Quickstart Guide](https://atomscale-ai.github.io/sdk/guides/quickstart.html)
63
+ - [Upload Data](https://atomscale-ai.github.io/sdk/guides/upload-data.html)
64
+ - [Search the Catalogue](https://atomscale-ai.github.io/sdk/guides/search-data.html)
65
+ - [Stream RHEED Video](https://atomscale-ai.github.io/sdk/guides/stream-rheed.html)
66
+ - [API Reference](https://atomscale-ai.github.io/sdk/modules.html)
67
+
68
+ ## License
69
+
70
+ This project is licensed under the [Mozilla Public License 2.0](LICENSE).
@@ -0,0 +1,38 @@
1
+ /* Override hardcoded logo dimensions */
2
+ img[alt="Logo"] {
3
+ height: 48px !important;
4
+ width: auto !important;
5
+ max-height: none !important;
6
+ }
7
+
8
+ /* Target the header/nav area logo specifically */
9
+ header img[alt="Logo"],
10
+ nav img[alt="Logo"],
11
+ a img[alt="Logo"] {
12
+ height: 25px !important;
13
+ width: auto !important;
14
+ position: relative;
15
+ top: -5px;
16
+ }
17
+
18
+ /* Force badges to display inline horizontally */
19
+ p > a.reference.external,
20
+ p > img {
21
+ display: inline !important;
22
+ margin-right: 4px;
23
+ }
24
+
25
+ p > a.reference.external > img {
26
+ display: inline !important;
27
+ vertical-align: middle;
28
+ }
29
+
30
+ /* Reduce space between h1 and badges, add space below badges */
31
+ section > h1 {
32
+ margin-bottom: 0.25rem !important;
33
+ }
34
+
35
+ section > p:first-of-type {
36
+ margin-top: 0 !important;
37
+ margin-bottom: 1.5rem !important;
38
+ }
@@ -72,37 +72,21 @@ pygments_style = "sphinx"
72
72
  # -- Options for HTML output -------------------------------------------------
73
73
  # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
74
74
 
75
- html_theme = "alabaster"
76
- # html_static_path = ['_static']
75
+ html_theme = "sphinxawesome_theme"
76
+
77
+ html_static_path = ["_static"]
78
+ html_css_files = ["custom.css"]
79
+ html_logo = "_static/AtomscaleLogoFull.png"
80
+ html_title = "Python SDK"
77
81
 
78
- # Theme options are theme-specific and customize the look and feel of a theme
79
- # further. For a list of options available for each theme, see the
80
- # documentation.
81
- #
82
82
  html_theme_options = {
83
- "github_button": True,
84
- "github_type": "star&v=2",
85
- "github_user": "atomic-data-sciences",
86
- "github_repo": "api-client",
87
- "github_banner": True,
88
- "description": "Python SDK",
83
+ "show_breadcrumbs": True,
84
+ "show_prev_next": True,
85
+ "logo_light": "_static/AtomscaleLogoFull.png",
86
+ "logo_dark": "_static/AtomscaleLogoFull.png",
89
87
  }
90
88
 
91
- # Custom sidebar templates, must be a dictionary that maps document names
92
- # to template names.
93
- #
94
- # The default sidebars (for documents that don't match any pattern) are
95
- # defined by theme itself. Builtin themes are using these templates by
96
- # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
97
- # 'searchbox.html']``.
98
- #
99
- html_sidebars = {
100
- "**": [
101
- "about.html",
102
- "navigation.html",
103
- "searchbox.html",
104
- ]
105
- }
89
+ html_permalinks_icon = "<span>#</span>"
106
90
 
107
91
  # -- Options for HTMLHelp output ---------------------------------------------
108
92
 
@@ -13,3 +13,4 @@ single workflow so you can jump straight to what you need.
13
13
  inspect-results
14
14
  stream-rheed
15
15
  poll-timeseries
16
+ poll-trajectory
@@ -21,6 +21,11 @@ Each item in ``analysed`` is a subclass of
21
21
  :class:`atomscale.results.RHEEDVideoResult` or
22
22
  :class:`atomscale.results.RHEEDImageResult`, depending on the source data.
23
23
 
24
+ .. note::
25
+
26
+ The :meth:`get` call fetches metadata and analysis artefacts for each ID.
27
+ For large result sets, consider batching or filtering first.
28
+
24
29
  Inspect time series data
25
30
  ------------------------
26
31
 
@@ -34,6 +39,21 @@ Inspect time series data
34
39
  The timeseries frame contains specular intensity, strain metrics, cluster IDs,
35
40
  and other summary features for every frame in the video.
36
41
 
42
+ .. list-table:: Common timeseries columns
43
+ :header-rows: 1
44
+ :widths: 30 70
45
+
46
+ * - Column
47
+ - Description
48
+ * - ``timestamp``
49
+ - Frame timestamp in seconds
50
+ * - ``specular_intensity``
51
+ - Specular spot brightness
52
+ * - ``strain``
53
+ - Computed strain metric
54
+ * - ``cluster_id``
55
+ - Pattern cluster assignment
56
+
37
57
  Work with extracted frames
38
58
  --------------------------
39
59
 
@@ -47,6 +67,11 @@ Work with extracted frames
47
67
  ``pattern_graph`` exposes the detected diffraction network as a NetworkX graph,
48
68
  while :meth:`get_pattern_dataframe` returns a tidy table describing each spot.
49
69
 
70
+ .. tip::
71
+
72
+ Use ``figure.savefig("snapshot.png")`` to export plots for reports or
73
+ publications.
74
+
50
75
  Download processed videos
51
76
  -------------------------
52
77
 
@@ -58,3 +83,13 @@ Download processed videos
58
83
  )
59
84
 
60
85
  The files are saved as MP4 (one per data ID) and mirror what you see in the UI.
86
+
87
+ .. caution::
88
+
89
+ Downloaded videos can be large. Ensure you have sufficient disk space and
90
+ consider filtering to only the IDs you need.
91
+
92
+ .. seealso::
93
+
94
+ - :doc:`poll-timeseries` – Poll for live timeseries updates
95
+ - :doc:`poll-trajectory` – Poll similarity trajectory data
@@ -14,6 +14,12 @@ analysis. This guide summarises the four helper entry points in
14
14
  - **Async background task** with :func:`start_polling_task` – fire-and-forget
15
15
  inside an asyncio application.
16
16
 
17
+ .. tip::
18
+
19
+ For similarity trajectory data that tracks structure-property relationships,
20
+ see :doc:`poll-trajectory` instead. That API auto-stops when the trajectory
21
+ completes.
22
+
17
23
  Shared setup
18
24
  ------------
19
25
 
@@ -41,9 +47,7 @@ Synchronous polling
41
47
 
42
48
  Loop over :func:`iter_poll` to fetch fresh rows on a fixed cadence. The helper
43
49
  waits ``interval`` seconds between polls so a simple ``for`` loop is enough to
44
- keep the script going. Use ``distinct_by`` to avoid duplicates,
45
- ``max_polls`` to stop automatically, and ``fire_immediately=False`` to skip the
46
- first immediate request if you only want timed polls.
50
+ keep the script going.
47
51
 
48
52
  .. code-block:: python
49
53
 
@@ -61,13 +65,19 @@ first immediate request if you only want timed polls.
61
65
  print(f"Poll {idx}: latest timestamp -> {latest_timestamp(result)}")
62
66
  print(result.tail())
63
67
 
68
+ .. note::
69
+
70
+ The iterator uses **drift-corrected scheduling** to maintain accurate timing
71
+ even when individual polls are slow. Use ``distinct_by`` to avoid processing
72
+ duplicate data, and ``fire_immediately=False`` to skip the initial poll.
73
+
64
74
  Background thread helper
65
75
  ------------------------
66
76
 
67
77
  Use :func:`start_polling_thread` when you want updates but cannot block the
68
78
  main thread (for example, inside a GUI or acquisition loop). The helper spawns
69
79
  a daemon thread, starts polling immediately, and forwards each update to your
70
- callback. Call ``stop_event.set()`` to shut it down cleanly.
80
+ callback.
71
81
 
72
82
  .. code-block:: python
73
83
 
@@ -91,6 +101,11 @@ callback. Call ``stop_event.set()`` to shut it down cleanly.
91
101
 
92
102
  # Call stop_event.set() to terminate early.
93
103
 
104
+ .. caution::
105
+
106
+ The callback runs in the polling thread, not the main thread. If you need to
107
+ update UI elements, use thread-safe mechanisms (e.g., ``queue.Queue``).
108
+
94
109
  Async utilities
95
110
  ---------------
96
111
 
@@ -101,6 +116,8 @@ Two helpers integrate with asyncio:
101
116
  * :func:`start_polling_task` creates a background task that awaits the poller
102
117
  in parallel and invokes an (optional) async handler for each result.
103
118
 
119
+ **Async iterator**
120
+
104
121
  .. code-block:: python
105
122
 
106
123
  import asyncio
@@ -121,6 +138,8 @@ Two helpers integrate with asyncio:
121
138
 
122
139
  asyncio.run(stream_updates())
123
140
 
141
+ **Background task**
142
+
124
143
  .. code-block:: python
125
144
 
126
145
  async def handle_async(result):
@@ -141,3 +160,7 @@ Two helpers integrate with asyncio:
141
160
 
142
161
 
143
162
  asyncio.run(main())
163
+
164
+ .. tip::
165
+
166
+ Cancel the task with ``task.cancel()`` to stop polling early in async code.
@@ -0,0 +1,219 @@
1
+ Poll Similarity Trajectory
2
+ ==========================
3
+
4
+ This guide covers the polling helpers in :mod:`atomscale.similarity.polling` for
5
+ monitoring similarity trajectory data. These functions mirror the timeseries
6
+ polling API but are tailored for trajectory workflows:
7
+
8
+ - **Manual loop** with :func:`iter_poll_trajectory` – ideal for scripts that can
9
+ block until each poll finishes.
10
+ - **Background thread** with :func:`start_polling_trajectory_thread` – keeps
11
+ polling while your main thread keeps working.
12
+ - **Async iterator** with :func:`aiter_poll_trajectory` – awaits each update
13
+ inside an async function.
14
+ - **Async background task** with :func:`start_polling_trajectory_task` –
15
+ fire-and-forget inside an asyncio application.
16
+
17
+ .. tip::
18
+
19
+ If you're polling generic timeseries data (e.g., RHEED intensity), see
20
+ :doc:`poll-timeseries` instead. Use this guide for similarity trajectory
21
+ workflows that track structure-property relationships across experiments.
22
+
23
+ Key differences from timeseries polling
24
+ ---------------------------------------
25
+
26
+ .. list-table::
27
+ :header-rows: 1
28
+ :widths: 30 35 35
29
+
30
+ * - Feature
31
+ - Timeseries polling
32
+ - Trajectory polling
33
+ * - Identifier
34
+ - ``data_id``
35
+ - ``source_id`` (data_id or physical_sample_id)
36
+ * - Stop condition
37
+ - Manual (``max_polls`` or custom ``until``)
38
+ - Auto-stops when ``Active`` is ``False``
39
+ * - Return format
40
+ - DataFrame with timeseries data
41
+ - DataFrame with ``Active`` column
42
+
43
+ .. important::
44
+
45
+ **Default stop condition**: Polling stops automatically when no trajectory is
46
+ active (``not df["Active"].any()``). Override this behavior with the ``until``
47
+ parameter if you need custom termination logic.
48
+
49
+ Shared setup
50
+ ------------
51
+
52
+ .. code-block:: python
53
+
54
+ from atomscale.client import Client
55
+ from atomscale.similarity.polling import (
56
+ iter_poll_trajectory,
57
+ aiter_poll_trajectory,
58
+ start_polling_trajectory_thread,
59
+ start_polling_trajectory_task,
60
+ )
61
+
62
+ client = Client(api_key="YOUR_API_KEY")
63
+ source_id = "YOUR_SOURCE_ID" # data_id or physical_sample_id
64
+
65
+ Synchronous polling
66
+ -------------------
67
+
68
+ Loop over :func:`iter_poll_trajectory` to fetch trajectory updates on a fixed
69
+ cadence. Polling stops automatically when the trajectory is no longer active,
70
+ or you can set ``max_polls`` to limit iterations.
71
+
72
+ .. code-block:: python
73
+
74
+ for idx, result in enumerate(
75
+ iter_poll_trajectory(
76
+ client,
77
+ source_id=source_id,
78
+ interval=5.0,
79
+ last_n=10,
80
+ max_polls=10,
81
+ ),
82
+ start=1,
83
+ ):
84
+ print(f"Poll {idx}: {len(result)} rows, active={result['Active'].any()}")
85
+ print(result.tail())
86
+
87
+ .. note::
88
+
89
+ The iterator uses **drift-corrected scheduling** to maintain accurate timing
90
+ even when individual polls are slow.
91
+
92
+ Background thread helper
93
+ ------------------------
94
+
95
+ Use :func:`start_polling_trajectory_thread` when you want updates but cannot
96
+ block the main thread (e.g., inside a GUI or acquisition loop). The helper
97
+ spawns a daemon thread and forwards each update to your callback.
98
+
99
+ .. code-block:: python
100
+
101
+ collected = []
102
+
103
+
104
+ def on_result(result):
105
+ print(f"Thread received {len(result)} rows")
106
+ collected.append(result)
107
+
108
+
109
+ stop_event = start_polling_trajectory_thread(
110
+ client,
111
+ source_id=source_id,
112
+ interval=10.0,
113
+ last_n=10,
114
+ on_result=on_result,
115
+ )
116
+
117
+ # Polling stops automatically when trajectory is inactive.
118
+ # Call stop_event.set() to terminate early.
119
+
120
+ .. caution::
121
+
122
+ The callback runs in the polling thread, not the main thread. If you need to
123
+ update UI elements, use thread-safe mechanisms (e.g., ``queue.Queue``).
124
+
125
+ Async utilities
126
+ ---------------
127
+
128
+ Two helpers integrate with asyncio:
129
+
130
+ * :func:`aiter_poll_trajectory` yields results without blocking the event loop.
131
+ * :func:`start_polling_trajectory_task` creates a background task that invokes
132
+ an (optional) async handler for each result.
133
+
134
+ **Async iterator**
135
+
136
+ .. code-block:: python
137
+
138
+ import asyncio
139
+
140
+
141
+ async def stream_updates():
142
+ async for result in aiter_poll_trajectory(
143
+ client,
144
+ source_id=source_id,
145
+ interval=5.0,
146
+ last_n=10,
147
+ ):
148
+ print(f"Async poll received {len(result)} rows")
149
+ if not result["Active"].any():
150
+ print("Trajectory complete")
151
+
152
+
153
+ asyncio.run(stream_updates())
154
+
155
+ **Background task**
156
+
157
+ .. code-block:: python
158
+
159
+ async def handle_async(result):
160
+ print(f"Task handler received {len(result)} rows")
161
+
162
+
163
+ async def main():
164
+ task = start_polling_trajectory_task(
165
+ client,
166
+ source_id=source_id,
167
+ interval=5.0,
168
+ last_n=5,
169
+ on_result=handle_async,
170
+ )
171
+ await task
172
+
173
+
174
+ asyncio.run(main())
175
+
176
+ .. tip::
177
+
178
+ Cancel the task with ``task.cancel()`` to stop polling early in async code.
179
+
180
+ Custom stop conditions
181
+ ----------------------
182
+
183
+ Override the default stop condition with the ``until`` parameter:
184
+
185
+ .. code-block:: python
186
+
187
+ # Stop after receiving at least 100 data points
188
+ for result in iter_poll_trajectory(
189
+ client,
190
+ source_id=source_id,
191
+ interval=5.0,
192
+ until=lambda df: len(df) >= 100,
193
+ ):
194
+ print(f"Received {len(result)} rows")
195
+
196
+ Error handling
197
+ --------------
198
+
199
+ Use the ``on_error`` callback to handle transient failures without stopping the
200
+ poll loop:
201
+
202
+ .. code-block:: python
203
+
204
+ def handle_error(exc):
205
+ print(f"Poll failed: {exc}, retrying...")
206
+
207
+
208
+ for result in iter_poll_trajectory(
209
+ client,
210
+ source_id=source_id,
211
+ interval=5.0,
212
+ on_error=handle_error,
213
+ ):
214
+ print(f"Received {len(result)} rows")
215
+
216
+ .. warning::
217
+
218
+ Errors are swallowed when ``on_error`` is provided. If you need to fail fast,
219
+ omit the callback and handle exceptions in your loop.
@@ -7,9 +7,13 @@ for calling the Atomscale API.
7
7
  Prerequisites
8
8
  -------------
9
9
 
10
- - Python 3.10 or newer
11
- - An active Atomscale account
12
- - An API key from the Atomscale web app (Profile → Account Management)
10
+ .. important::
11
+
12
+ Before you begin, make sure you have:
13
+
14
+ - Python 3.10 or newer
15
+ - An active Atomscale account
16
+ - An API key from the Atomscale web app (Profile → Account Management)
13
17
 
14
18
  Install the client
15
19
  ------------------
@@ -34,7 +38,12 @@ explicitly if you prefer.
34
38
 
35
39
  client = Client()
36
40
 
37
- Override the endpoint when pointing at staging or a private deployment.
41
+ .. tip::
42
+
43
+ Set ``AS_API_KEY`` in your shell profile (e.g., ``.bashrc`` or ``.zshrc``)
44
+ to avoid hardcoding credentials in scripts.
45
+
46
+ Override the endpoint when pointing at staging or a private deployment:
38
47
 
39
48
  .. code-block:: python
40
49
 
@@ -43,9 +52,16 @@ Override the endpoint when pointing at staging or a private deployment.
43
52
  endpoint="https://api.atomscale.ai/",
44
53
  )
45
54
 
55
+ .. warning::
56
+
57
+ Never commit API keys to version control. Use environment variables or a
58
+ secrets manager instead.
59
+
46
60
  Next steps
47
61
  ----------
48
62
 
49
- - Upload files with :doc:`upload-data`
50
- - Find items in the catalogue with :doc:`search-data`
51
- - Explore results and plots with :doc:`inspect-results`
63
+ .. seealso::
64
+
65
+ - :doc:`upload-data` Upload RHEED videos, images, or XPS files
66
+ - :doc:`search-data` – Find items in the catalogue
67
+ - :doc:`inspect-results` – Explore results and plots