temscript 2.0.0__tar.gz → 2.1.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.
- {temscript-2.0.0/temscript.egg-info → temscript-2.1.0}/PKG-INFO +26 -5
- {temscript-2.0.0 → temscript-2.1.0}/README.md +11 -1
- {temscript-2.0.0 → temscript-2.1.0}/docs/changelog.rst +14 -1
- {temscript-2.0.0 → temscript-2.1.0}/docs/instrument.rst +7 -0
- temscript-2.1.0/docs/requirements.txt +4 -0
- {temscript-2.0.0 → temscript-2.1.0}/scripts/test_microscope.py +1 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/_com.py +24 -1
- {temscript-2.0.0 → temscript-2.1.0}/temscript/_instrument_com.py +10 -10
- {temscript-2.0.0 → temscript-2.1.0}/temscript/base_microscope.py +41 -6
- {temscript-2.0.0 → temscript-2.1.0}/temscript/enums.py +10 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/microscope.py +11 -2
- {temscript-2.0.0 → temscript-2.1.0}/temscript/null_microscope.py +6 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/remote_microscope.py +6 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/server.py +11 -2
- temscript-2.1.0/temscript/version.py +1 -0
- {temscript-2.0.0 → temscript-2.1.0/temscript.egg-info}/PKG-INFO +26 -5
- {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/SOURCES.txt +1 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/entry_points.txt +0 -1
- temscript-2.0.0/temscript/version.py +0 -1
- {temscript-2.0.0 → temscript-2.1.0}/LICENSE +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/MANIFEST.in +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/Makefile +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/about.rst +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/conf.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/index.rst +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/make.bat +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/microscope.rst +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/restrictions.rst +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/docs/server.rst +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/pyproject.toml +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/scripts/run_null_server.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/scripts/test_camera_acquisition.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/scripts/test_instrument.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/scripts/test_json_encoder.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/setup.cfg +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/setup.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/__init__.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/_instrument_stubs.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/instrument.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript/marshall.py +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/dependency_links.txt +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/requires.txt +0 -0
- {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: temscript
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: TEM Scripting adapter for FEI microscopes
|
|
5
5
|
Home-page: https://github.com/niermann/temscript
|
|
6
6
|
Author: Tore Niermann
|
|
@@ -21,6 +21,19 @@ Classifier: Operating System :: OS Independent
|
|
|
21
21
|
Requires-Python: >=3.4
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy
|
|
25
|
+
Dynamic: author
|
|
26
|
+
Dynamic: author-email
|
|
27
|
+
Dynamic: classifier
|
|
28
|
+
Dynamic: description
|
|
29
|
+
Dynamic: description-content-type
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: license
|
|
32
|
+
Dynamic: platform
|
|
33
|
+
Dynamic: project-url
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
24
37
|
|
|
25
38
|
# About
|
|
26
39
|
|
|
@@ -58,7 +71,17 @@ On Windows platforms the package provides the Python wrapper
|
|
|
58
71
|
to the scripting COM interface. However, trying to instantiate this wrapper
|
|
59
72
|
will fail, if the scripting COM classes are not installed locally.
|
|
60
73
|
|
|
61
|
-
### Installation from
|
|
74
|
+
### Installation from PyPI (using pip)
|
|
75
|
+
|
|
76
|
+
This assumes you have connection to the internet.
|
|
77
|
+
|
|
78
|
+
Execute from the command line (assuming you have your python interpreter in the path, this might require superuser or
|
|
79
|
+
administrator privileges):
|
|
80
|
+
|
|
81
|
+
python3 -m pip install --upgrade pip
|
|
82
|
+
python3 -m pip install temscript
|
|
83
|
+
|
|
84
|
+
### Offline-Installation from wheels file (using pip)
|
|
62
85
|
|
|
63
86
|
This assumes you have downloaded the wheels file <downloaded-wheels-file>.whl
|
|
64
87
|
|
|
@@ -129,5 +152,3 @@ LICENCE.txt file for any details.
|
|
|
129
152
|
All product and company names are trademarks or registered trademarks of
|
|
130
153
|
their respective holders. Use of them does not imply any affiliation
|
|
131
154
|
with or endorsement by them.
|
|
132
|
-
|
|
133
|
-
|
|
@@ -34,7 +34,17 @@ On Windows platforms the package provides the Python wrapper
|
|
|
34
34
|
to the scripting COM interface. However, trying to instantiate this wrapper
|
|
35
35
|
will fail, if the scripting COM classes are not installed locally.
|
|
36
36
|
|
|
37
|
-
### Installation from
|
|
37
|
+
### Installation from PyPI (using pip)
|
|
38
|
+
|
|
39
|
+
This assumes you have connection to the internet.
|
|
40
|
+
|
|
41
|
+
Execute from the command line (assuming you have your python interpreter in the path, this might require superuser or
|
|
42
|
+
administrator privileges):
|
|
43
|
+
|
|
44
|
+
python3 -m pip install --upgrade pip
|
|
45
|
+
python3 -m pip install temscript
|
|
46
|
+
|
|
47
|
+
### Offline-Installation from wheels file (using pip)
|
|
38
48
|
|
|
39
49
|
This assumes you have downloaded the wheels file <downloaded-wheels-file>.whl
|
|
40
50
|
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
Version 2.1.0
|
|
5
|
+
^^^^^^^^^^^^^
|
|
6
|
+
|
|
7
|
+
* Changed default apartment model to COINIT_APARTMENTTHREADED to increase compatibility with comtypes
|
|
8
|
+
* COM initialization respects setting from sys.coinit_flags
|
|
9
|
+
|
|
10
|
+
Version 2.0.1
|
|
11
|
+
^^^^^^^^^^^^^
|
|
12
|
+
|
|
13
|
+
* Added Talos as ProductFamily
|
|
14
|
+
* Added more graceful behavior for unsupported ProductFamily query and unknown future families.
|
|
15
|
+
* Added column valves state to Microscope classes.
|
|
16
|
+
|
|
4
17
|
Version 2.0.0
|
|
5
18
|
^^^^^^^^^^^^^
|
|
6
19
|
|
|
@@ -11,7 +24,7 @@ Version 2.0.0
|
|
|
11
24
|
* Support of the fluorescent screen
|
|
12
25
|
* Separation of STEM detectors and CCD cameras in high level interface
|
|
13
26
|
* Deprecation of the methods 'get_detectors', 'get_detector_param', 'set_detector_params', and 'get_optics_state' of
|
|
14
|
-
'Microscope' and related classes. See docs for further details.
|
|
27
|
+
'Microscope' and related classes. See docs for further details.
|
|
15
28
|
* Deprecation of the property 'AcqParams' of 'STEMDetector'. See docs for further details.
|
|
16
29
|
* Deprecation of the use of 'speed' and 'method' keywords in position dictionary of the 'set_stage_position' method.
|
|
17
30
|
* Abstract base class for high level interface
|
|
@@ -13,6 +13,13 @@ The interface is described in detail in the scripting manual of your microscope
|
|
|
13
13
|
The manual is your ultimate reference, this documentation will only describe the
|
|
14
14
|
python wrapper to the COM interface.
|
|
15
15
|
|
|
16
|
+
The COM apartment model will automatically be initialized as ``COINIT_APARTMENTTHREADED``
|
|
17
|
+
(this changed in Version 2.1.0, it was ``COINIT_MULTITHREADED`` before). However, if the
|
|
18
|
+
apartment model was already initialized as ``COINIT_MULTITHREADED`` before `temscript`
|
|
19
|
+
was imported, `temscript` will also work. If you want a specific apartment model, set the
|
|
20
|
+
variable ``sys.coinit_flags`` before importing `temscript`.
|
|
21
|
+
|
|
22
|
+
|
|
16
23
|
Enumerations
|
|
17
24
|
^^^^^^^^^^^^
|
|
18
25
|
|
|
@@ -34,6 +34,7 @@ print("Microscope.get_microscope_id():", microscope.get_microscope_id())
|
|
|
34
34
|
print("Microscope.get_version():", microscope.get_version())
|
|
35
35
|
print("Microscope.get_voltage():", microscope.get_voltage())
|
|
36
36
|
print("Microscope.get_vacuum():", microscope.get_vacuum())
|
|
37
|
+
print("Microscope.get_column_valves_open():", microscope.get_column_valves_open())
|
|
37
38
|
print("Microscope.get_stage_holder():", microscope.get_stage_holder())
|
|
38
39
|
print("Microscope.get_stage_status():", microscope.get_stage_status())
|
|
39
40
|
print("Microscope.get_stage_limits():", microscope.get_stage_limits())
|
|
@@ -6,6 +6,7 @@ __all__ = 'UUID', 'CLSCTX_ALL', 'IUnknown', 'co_create_instance', 'SafeArray', '
|
|
|
6
6
|
|
|
7
7
|
# COM constants
|
|
8
8
|
COINIT_MULTITHREADED = 0
|
|
9
|
+
COINIT_APARTMENTTHREADED = 2
|
|
9
10
|
CLSCTX_ALL = 0x17
|
|
10
11
|
|
|
11
12
|
|
|
@@ -370,5 +371,27 @@ class SafeArray:
|
|
|
370
371
|
|
|
371
372
|
|
|
372
373
|
_ole32 = ctypes.oledll.ole32
|
|
373
|
-
_ole32.CoInitializeEx(None, ctypes.c_int(COINIT_MULTITHREADED))
|
|
374
374
|
_oleauto = ctypes.windll.oleaut32
|
|
375
|
+
|
|
376
|
+
def initialize_com(flags=None):
|
|
377
|
+
RPC_E_CHANGED_MODE = -2147417850
|
|
378
|
+
|
|
379
|
+
# The comtypes package allows to specify the apartment model by
|
|
380
|
+
# setting sys.coinit_flags in advance. We copy this behavior.
|
|
381
|
+
if flags is None:
|
|
382
|
+
import sys
|
|
383
|
+
flags = getattr(sys, "coinit_flags", None)
|
|
384
|
+
|
|
385
|
+
if flags is None:
|
|
386
|
+
# If we don't have explicit flags, try STA first and fall back to MTA
|
|
387
|
+
# if COM is already initialized to MTA.
|
|
388
|
+
try:
|
|
389
|
+
_ole32.CoInitializeEx(None, ctypes.c_int(COINIT_APARTMENTTHREADED))
|
|
390
|
+
except WindowsError as exc:
|
|
391
|
+
if exc.winerror == RPC_E_CHANGED_MODE:
|
|
392
|
+
_ole32.CoInitializeEx(None, ctypes.c_int(COINIT_MULTITHREADED))
|
|
393
|
+
else:
|
|
394
|
+
# Otherwise, use the apartment model we got
|
|
395
|
+
_ole32.CoInitializeEx(None, flags)
|
|
396
|
+
|
|
397
|
+
initialize_com()
|
|
@@ -26,7 +26,7 @@ class LongProperty(BaseProperty):
|
|
|
26
26
|
|
|
27
27
|
def __get__(self, obj, objtype=None):
|
|
28
28
|
if self._get_index is None:
|
|
29
|
-
raise AttributeError("Attribute %
|
|
29
|
+
raise AttributeError("Attribute %s is not readable" % self._name)
|
|
30
30
|
result = ctypes.c_long(-1)
|
|
31
31
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_void_p)(self._get_index, "get_property")
|
|
32
32
|
prototype(obj.get(), ctypes.byref(result))
|
|
@@ -34,7 +34,7 @@ class LongProperty(BaseProperty):
|
|
|
34
34
|
|
|
35
35
|
def __set__(self, obj, value):
|
|
36
36
|
if self._put_index is None:
|
|
37
|
-
raise AttributeError("Attribute %
|
|
37
|
+
raise AttributeError("Attribute %s is not writable" % self._name)
|
|
38
38
|
value = int(value)
|
|
39
39
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_long)(self._put_index, "put_property")
|
|
40
40
|
prototype(obj.get(), value)
|
|
@@ -43,7 +43,7 @@ class LongProperty(BaseProperty):
|
|
|
43
43
|
class VariantBoolProperty(BaseProperty):
|
|
44
44
|
def __get__(self, obj, objtype=None):
|
|
45
45
|
if self._get_index is None:
|
|
46
|
-
raise AttributeError("Attribute %
|
|
46
|
+
raise AttributeError("Attribute %s is not readable" % self._name)
|
|
47
47
|
result = ctypes.c_short(-1)
|
|
48
48
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_void_p)(self._get_index, "get_property")
|
|
49
49
|
prototype(obj.get(), ctypes.byref(result))
|
|
@@ -51,7 +51,7 @@ class VariantBoolProperty(BaseProperty):
|
|
|
51
51
|
|
|
52
52
|
def __set__(self, obj, value):
|
|
53
53
|
if self._put_index is None:
|
|
54
|
-
raise AttributeError("Attribute %
|
|
54
|
+
raise AttributeError("Attribute %s is not writable" % self._name)
|
|
55
55
|
bool_value = 0xffff if value else 0x0000
|
|
56
56
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_short)(self._put_index, "put_property")
|
|
57
57
|
prototype(obj.get(), bool_value)
|
|
@@ -60,7 +60,7 @@ class VariantBoolProperty(BaseProperty):
|
|
|
60
60
|
class DoubleProperty(BaseProperty):
|
|
61
61
|
def __get__(self, obj, objtype=None):
|
|
62
62
|
if self._get_index is None:
|
|
63
|
-
raise AttributeError("Attribute %
|
|
63
|
+
raise AttributeError("Attribute %s is not readable" % self._name)
|
|
64
64
|
result = ctypes.c_double(-1)
|
|
65
65
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_void_p)(self._get_index, "get_property")
|
|
66
66
|
prototype(obj.get(), ctypes.byref(result))
|
|
@@ -68,7 +68,7 @@ class DoubleProperty(BaseProperty):
|
|
|
68
68
|
|
|
69
69
|
def __set__(self, obj, value):
|
|
70
70
|
if self._put_index is None:
|
|
71
|
-
raise AttributeError("Attribute %
|
|
71
|
+
raise AttributeError("Attribute %s is not writable" % self._name)
|
|
72
72
|
value = float(value)
|
|
73
73
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_double)(self._put_index, "put_property")
|
|
74
74
|
prototype(obj.get(), value)
|
|
@@ -77,7 +77,7 @@ class DoubleProperty(BaseProperty):
|
|
|
77
77
|
class StringProperty(BaseProperty):
|
|
78
78
|
def __get__(self, obj, objtype=None):
|
|
79
79
|
if self._get_index is None:
|
|
80
|
-
raise AttributeError("Attribute %
|
|
80
|
+
raise AttributeError("Attribute %s is not readable" % self._name)
|
|
81
81
|
result = BStr()
|
|
82
82
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_void_p)(self._get_index, "get_property")
|
|
83
83
|
prototype(obj.get(), result.byref())
|
|
@@ -85,7 +85,7 @@ class StringProperty(BaseProperty):
|
|
|
85
85
|
|
|
86
86
|
def __set__(self, obj, value):
|
|
87
87
|
if self._put_index is None:
|
|
88
|
-
raise AttributeError("Attribute %
|
|
88
|
+
raise AttributeError("Attribute %s is not writable" % self._name)
|
|
89
89
|
value = BStr(str(value))
|
|
90
90
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_void_p)(self._put_index, "put_property")
|
|
91
91
|
prototype(obj.get(), BStr(value).get())
|
|
@@ -100,7 +100,7 @@ class EnumProperty(BaseProperty):
|
|
|
100
100
|
|
|
101
101
|
def __get__(self, obj, objtype=None):
|
|
102
102
|
if self._get_index is None:
|
|
103
|
-
raise AttributeError("Attribute %
|
|
103
|
+
raise AttributeError("Attribute %s is not readable" % self._name)
|
|
104
104
|
result = ctypes.c_int(-1)
|
|
105
105
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_void_p)(self._get_index, "get_property")
|
|
106
106
|
prototype(obj.get(), ctypes.byref(result))
|
|
@@ -108,7 +108,7 @@ class EnumProperty(BaseProperty):
|
|
|
108
108
|
|
|
109
109
|
def __set__(self, obj, value):
|
|
110
110
|
if self._put_index is None:
|
|
111
|
-
raise AttributeError("Attribute %
|
|
111
|
+
raise AttributeError("Attribute %s is not writable" % self._name)
|
|
112
112
|
value = int(value)
|
|
113
113
|
prototype = ctypes.WINFUNCTYPE(ctypes.HRESULT, ctypes.c_long)(self._put_index, "put_property")
|
|
114
114
|
prototype(obj.get(), value)
|
|
@@ -18,7 +18,7 @@ def set_attr_from_dict(obj, attr_name, mapping, key, ignore_errors=False):
|
|
|
18
18
|
If no such *key* is in the dict, nothing is done.
|
|
19
19
|
Any TypeErrors or ValueErrors are silently ignored, if *ignore_errors is set.
|
|
20
20
|
|
|
21
|
-
Returns true is *key* was present in *map* and the attribute was successfully set. Otherwise False is returned.
|
|
21
|
+
Returns true is *key* was present in *map* and the attribute was successfully set. Otherwise, False is returned.
|
|
22
22
|
"""
|
|
23
23
|
try:
|
|
24
24
|
value = mapping.pop(key)
|
|
@@ -43,7 +43,7 @@ def set_enum_attr_from_dict(obj, attr_name, enum_type, mapping, key, ignore_erro
|
|
|
43
43
|
If no such *key* is in the dict nothing is done.
|
|
44
44
|
Any TypeErrors or ValueErrors are silently ignored, if *ignore_errors is set.
|
|
45
45
|
|
|
46
|
-
Returns true is *key* was present in *map* and the attribute was successfully set. Otherwise False is returned.
|
|
46
|
+
Returns true is *key* was present in *map* and the attribute was successfully set. Otherwise, False is returned.
|
|
47
47
|
"""
|
|
48
48
|
try:
|
|
49
49
|
value = mapping.pop(key)
|
|
@@ -73,11 +73,15 @@ STAGE_AXES = frozenset(('x', 'y', 'z', 'a', 'b'))
|
|
|
73
73
|
|
|
74
74
|
class BaseMicroscope(ABC):
|
|
75
75
|
"""
|
|
76
|
-
|
|
76
|
+
Abstract base class for microscope classes.
|
|
77
|
+
|
|
78
|
+
Do not use `BaseMicroscope` directly, instead instantiate
|
|
79
|
+
one of the subclasses, like :class:`Microscope` or :class:`RemoteMicroscope`. The Subclasses
|
|
80
|
+
implement all the abstract methods.
|
|
77
81
|
"""
|
|
78
82
|
@abstractmethod
|
|
79
83
|
def get_family(self):
|
|
80
|
-
"""Return product family (see :class:`ProductFamily`): "TITAN", "TECNAI", ..."""
|
|
84
|
+
"""Return product family (see :class:`ProductFamily` for values): "TITAN", "TECNAI", ..."""
|
|
81
85
|
raise NotImplementedError
|
|
82
86
|
|
|
83
87
|
@abstractmethod
|
|
@@ -124,6 +128,29 @@ class BaseMicroscope(ABC):
|
|
|
124
128
|
"""
|
|
125
129
|
raise NotImplementedError
|
|
126
130
|
|
|
131
|
+
@abstractmethod
|
|
132
|
+
def get_column_valves_open(self):
|
|
133
|
+
"""
|
|
134
|
+
Returns state of the column valves.
|
|
135
|
+
|
|
136
|
+
:return: `True`, if column valves are open. `False`, otherwise.
|
|
137
|
+
|
|
138
|
+
.. versionadded: 2.1.0
|
|
139
|
+
"""
|
|
140
|
+
raise NotImplementedError
|
|
141
|
+
|
|
142
|
+
@abstractmethod
|
|
143
|
+
def set_column_valves_open(self, state):
|
|
144
|
+
"""
|
|
145
|
+
Set state of the column valves. The column valves are opened, if `True` is passes as *state*
|
|
146
|
+
|
|
147
|
+
:param state: `True`, if column valves should be opened. `False`, if they should be closed.
|
|
148
|
+
:type state: bool
|
|
149
|
+
|
|
150
|
+
.. versionadded: 2.0.1
|
|
151
|
+
"""
|
|
152
|
+
raise NotImplementedError
|
|
153
|
+
|
|
127
154
|
@abstractmethod
|
|
128
155
|
def get_stage_holder(self):
|
|
129
156
|
"""Return holder currently in stage (see :class:`StageHolderType`)"""
|
|
@@ -614,7 +641,11 @@ class BaseMicroscope(ABC):
|
|
|
614
641
|
def get_indicated_camera_length(self):
|
|
615
642
|
"""
|
|
616
643
|
Return (indicated) camera length in meters in diffraction modes.
|
|
617
|
-
|
|
644
|
+
|
|
645
|
+
.. note::
|
|
646
|
+
The scripting manual states, that this function always returns 0,
|
|
647
|
+
if microscope is in imaging mode. In STEM mode this
|
|
648
|
+
function works reportedly nevertheless.
|
|
618
649
|
|
|
619
650
|
.. versionadded:: 1.0.9
|
|
620
651
|
"""
|
|
@@ -624,7 +655,11 @@ class BaseMicroscope(ABC):
|
|
|
624
655
|
def get_indicated_magnification(self):
|
|
625
656
|
"""
|
|
626
657
|
Return (indicated) magnification in imaging modes.
|
|
627
|
-
|
|
658
|
+
|
|
659
|
+
.. note::
|
|
660
|
+
The scripting manual states, that this function always returns 0,
|
|
661
|
+
if microscope is in diffraction mode. In STEM mode this
|
|
662
|
+
function works reportedly nevertheless.
|
|
628
663
|
|
|
629
664
|
.. note::
|
|
630
665
|
On Titan 1.1 software this method returns 0.0 regardless of used mode. See :ref:`restrictions`.
|
|
@@ -179,8 +179,18 @@ class AcqExposureMode(IntEnum):
|
|
|
179
179
|
|
|
180
180
|
|
|
181
181
|
class ProductFamily(IntEnum):
|
|
182
|
+
UNDEFINED = -1
|
|
182
183
|
TECNAI = 0
|
|
183
184
|
TITAN = 1
|
|
185
|
+
TALOS = 2
|
|
186
|
+
FUTURE_3 = 3 # Future family #3
|
|
187
|
+
FUTURE_4 = 4 # Future family #4
|
|
188
|
+
FUTURE_5 = 5 # Future family #5
|
|
189
|
+
FUTURE_6 = 6 # Future family #6
|
|
190
|
+
FUTURE_7 = 7 # Future family #7
|
|
191
|
+
FUTURE_8 = 8 # Future family #8
|
|
192
|
+
FUTURE_9 = 9 # Future family #9
|
|
193
|
+
FUTURE_2 = TALOS # Alias
|
|
184
194
|
|
|
185
195
|
|
|
186
196
|
class ScreenPosition(IntEnum):
|
|
@@ -30,7 +30,10 @@ class Microscope(BaseMicroscope):
|
|
|
30
30
|
self._tem_vacuum = tem.Vacuum
|
|
31
31
|
self._tem_camera = tem.Camera
|
|
32
32
|
self._tem_control = tem.InstrumentModeControl
|
|
33
|
-
|
|
33
|
+
try:
|
|
34
|
+
self._family = tem.Configuration.ProductFamily
|
|
35
|
+
except Exception:
|
|
36
|
+
self._family = ProductFamily.UNDEFINED
|
|
34
37
|
|
|
35
38
|
def get_family(self):
|
|
36
39
|
return ProductFamily(self._family).name
|
|
@@ -64,11 +67,17 @@ class Microscope(BaseMicroscope):
|
|
|
64
67
|
gauges[name] = g.Pressure
|
|
65
68
|
return {
|
|
66
69
|
"status": VacuumStatus(self._tem_vacuum.Status).name,
|
|
67
|
-
"column_valves_open": self.
|
|
70
|
+
"column_valves_open": self.get_column_valves_open(),
|
|
68
71
|
"pvp_running": self._tem_vacuum.PVPRunning,
|
|
69
72
|
"gauges(Pa)": gauges,
|
|
70
73
|
}
|
|
71
74
|
|
|
75
|
+
def get_column_valves_open(self):
|
|
76
|
+
return self._tem_vacuum.ColumnValvesOpen
|
|
77
|
+
|
|
78
|
+
def set_column_valves_open(self, state):
|
|
79
|
+
self._tem_vacuum.ColumnValvesOpen = state
|
|
80
|
+
|
|
72
81
|
def get_stage_holder(self):
|
|
73
82
|
return self._tem_stage.Holder.name
|
|
74
83
|
|
|
@@ -141,6 +141,12 @@ class NullMicroscope(BaseMicroscope):
|
|
|
141
141
|
"gauges(Pa)": {},
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
def get_column_valves_open(self):
|
|
145
|
+
return self._column_valves
|
|
146
|
+
|
|
147
|
+
def set_column_valves_open(self, state):
|
|
148
|
+
self._column_valves = bool(state)
|
|
149
|
+
|
|
144
150
|
def get_stage_holder(self):
|
|
145
151
|
return StageHolderType.SINGLE_TILT.name
|
|
146
152
|
|
|
@@ -142,6 +142,12 @@ class RemoteMicroscope(BaseMicroscope):
|
|
|
142
142
|
def get_vacuum(self):
|
|
143
143
|
return self._request("GET", "/v1/vacuum")[1]
|
|
144
144
|
|
|
145
|
+
def get_column_valves_open(self):
|
|
146
|
+
return self._request("GET", "/v1/column_valves_open")[1]
|
|
147
|
+
|
|
148
|
+
def set_column_valves_open(self, state):
|
|
149
|
+
self._request_with_json_body("PUT", "/v1/column_valves_open", state)
|
|
150
|
+
|
|
145
151
|
def get_stage_holder(self):
|
|
146
152
|
return self._request("GET", "/v1/stage_holder")[1]
|
|
147
153
|
|
|
@@ -16,7 +16,7 @@ class MicroscopeHandler(BaseHTTPRequestHandler):
|
|
|
16
16
|
"condenser_stigmator", "diffraction_shift", "screen_current", "screen_position",
|
|
17
17
|
"illumination_mode", "condenser_mode", "illuminated_area", "probe_defocus", "convergence_angle",
|
|
18
18
|
"stem_magnification", "stem_rotation", "spot_size_index", "dark_field_mode", "beam_blanked",
|
|
19
|
-
"instrument_mode", 'optics_state', 'state')
|
|
19
|
+
"instrument_mode", 'optics_state', 'state', 'column_valves_open')
|
|
20
20
|
|
|
21
21
|
PUT_V1_FORWARD = ("image_shift", "beam_shift", "beam_tilt", "projection_mode", "magnification_index",
|
|
22
22
|
"defocus", "intensity", "diffraction_shift", "objective_stigmator", "condenser_stigmator",
|
|
@@ -126,6 +126,13 @@ class MicroscopeHandler(BaseHTTPRequestHandler):
|
|
|
126
126
|
response = self.get_microscope().set_detector_param(name, decoded_content)
|
|
127
127
|
elif endpoint == "normalize":
|
|
128
128
|
self.get_microscope().normalize(decoded_content)
|
|
129
|
+
elif endpoint == "column_valves_open":
|
|
130
|
+
state = bool(decoded_content)
|
|
131
|
+
assert isinstance(self.server, MicroscopeServer)
|
|
132
|
+
if self.server.allow_column_valves_open or not state:
|
|
133
|
+
self.get_microscope().set_column_valves_open(state)
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError("Opening of column valves is prohibited.")
|
|
129
136
|
else:
|
|
130
137
|
raise KeyError("Unknown endpoint: '%s'" % endpoint)
|
|
131
138
|
return response
|
|
@@ -166,17 +173,19 @@ class MicroscopeHandler(BaseHTTPRequestHandler):
|
|
|
166
173
|
|
|
167
174
|
|
|
168
175
|
class MicroscopeServer(HTTPServer, object):
|
|
169
|
-
def __init__(self, server_address=('', 8080), microscope_factory=None):
|
|
176
|
+
def __init__(self, server_address=('', 8080), microscope_factory=None, allow_column_valves_open=True):
|
|
170
177
|
"""
|
|
171
178
|
Run a microscope server.
|
|
172
179
|
|
|
173
180
|
:param server_address: (address, port) tuple
|
|
174
181
|
:param microscope_factory: callable creating the BaseMicroscope instance to use
|
|
182
|
+
:param allow_column_valves_open: Allow remote client to open column valves
|
|
175
183
|
"""
|
|
176
184
|
if microscope_factory is None:
|
|
177
185
|
from .microscope import Microscope
|
|
178
186
|
microscope_factory = Microscope
|
|
179
187
|
self.microscope = microscope_factory()
|
|
188
|
+
self.allow_column_valves_open = allow_column_valves_open
|
|
180
189
|
super(MicroscopeServer, self).__init__(server_address, MicroscopeHandler)
|
|
181
190
|
|
|
182
191
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.1.0'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: temscript
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: TEM Scripting adapter for FEI microscopes
|
|
5
5
|
Home-page: https://github.com/niermann/temscript
|
|
6
6
|
Author: Tore Niermann
|
|
@@ -21,6 +21,19 @@ Classifier: Operating System :: OS Independent
|
|
|
21
21
|
Requires-Python: >=3.4
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy
|
|
25
|
+
Dynamic: author
|
|
26
|
+
Dynamic: author-email
|
|
27
|
+
Dynamic: classifier
|
|
28
|
+
Dynamic: description
|
|
29
|
+
Dynamic: description-content-type
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: license
|
|
32
|
+
Dynamic: platform
|
|
33
|
+
Dynamic: project-url
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
24
37
|
|
|
25
38
|
# About
|
|
26
39
|
|
|
@@ -58,7 +71,17 @@ On Windows platforms the package provides the Python wrapper
|
|
|
58
71
|
to the scripting COM interface. However, trying to instantiate this wrapper
|
|
59
72
|
will fail, if the scripting COM classes are not installed locally.
|
|
60
73
|
|
|
61
|
-
### Installation from
|
|
74
|
+
### Installation from PyPI (using pip)
|
|
75
|
+
|
|
76
|
+
This assumes you have connection to the internet.
|
|
77
|
+
|
|
78
|
+
Execute from the command line (assuming you have your python interpreter in the path, this might require superuser or
|
|
79
|
+
administrator privileges):
|
|
80
|
+
|
|
81
|
+
python3 -m pip install --upgrade pip
|
|
82
|
+
python3 -m pip install temscript
|
|
83
|
+
|
|
84
|
+
### Offline-Installation from wheels file (using pip)
|
|
62
85
|
|
|
63
86
|
This assumes you have downloaded the wheels file <downloaded-wheels-file>.whl
|
|
64
87
|
|
|
@@ -129,5 +152,3 @@ LICENCE.txt file for any details.
|
|
|
129
152
|
All product and company names are trademarks or registered trademarks of
|
|
130
153
|
their respective holders. Use of them does not imply any affiliation
|
|
131
154
|
with or endorsement by them.
|
|
132
|
-
|
|
133
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '2.0.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|