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.
Files changed (43) hide show
  1. {temscript-2.0.0/temscript.egg-info → temscript-2.1.0}/PKG-INFO +26 -5
  2. {temscript-2.0.0 → temscript-2.1.0}/README.md +11 -1
  3. {temscript-2.0.0 → temscript-2.1.0}/docs/changelog.rst +14 -1
  4. {temscript-2.0.0 → temscript-2.1.0}/docs/instrument.rst +7 -0
  5. temscript-2.1.0/docs/requirements.txt +4 -0
  6. {temscript-2.0.0 → temscript-2.1.0}/scripts/test_microscope.py +1 -0
  7. {temscript-2.0.0 → temscript-2.1.0}/temscript/_com.py +24 -1
  8. {temscript-2.0.0 → temscript-2.1.0}/temscript/_instrument_com.py +10 -10
  9. {temscript-2.0.0 → temscript-2.1.0}/temscript/base_microscope.py +41 -6
  10. {temscript-2.0.0 → temscript-2.1.0}/temscript/enums.py +10 -0
  11. {temscript-2.0.0 → temscript-2.1.0}/temscript/microscope.py +11 -2
  12. {temscript-2.0.0 → temscript-2.1.0}/temscript/null_microscope.py +6 -0
  13. {temscript-2.0.0 → temscript-2.1.0}/temscript/remote_microscope.py +6 -0
  14. {temscript-2.0.0 → temscript-2.1.0}/temscript/server.py +11 -2
  15. temscript-2.1.0/temscript/version.py +1 -0
  16. {temscript-2.0.0 → temscript-2.1.0/temscript.egg-info}/PKG-INFO +26 -5
  17. {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/SOURCES.txt +1 -0
  18. {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/entry_points.txt +0 -1
  19. temscript-2.0.0/temscript/version.py +0 -1
  20. {temscript-2.0.0 → temscript-2.1.0}/LICENSE +0 -0
  21. {temscript-2.0.0 → temscript-2.1.0}/MANIFEST.in +0 -0
  22. {temscript-2.0.0 → temscript-2.1.0}/docs/Makefile +0 -0
  23. {temscript-2.0.0 → temscript-2.1.0}/docs/about.rst +0 -0
  24. {temscript-2.0.0 → temscript-2.1.0}/docs/conf.py +0 -0
  25. {temscript-2.0.0 → temscript-2.1.0}/docs/index.rst +0 -0
  26. {temscript-2.0.0 → temscript-2.1.0}/docs/make.bat +0 -0
  27. {temscript-2.0.0 → temscript-2.1.0}/docs/microscope.rst +0 -0
  28. {temscript-2.0.0 → temscript-2.1.0}/docs/restrictions.rst +0 -0
  29. {temscript-2.0.0 → temscript-2.1.0}/docs/server.rst +0 -0
  30. {temscript-2.0.0 → temscript-2.1.0}/pyproject.toml +0 -0
  31. {temscript-2.0.0 → temscript-2.1.0}/scripts/run_null_server.py +0 -0
  32. {temscript-2.0.0 → temscript-2.1.0}/scripts/test_camera_acquisition.py +0 -0
  33. {temscript-2.0.0 → temscript-2.1.0}/scripts/test_instrument.py +0 -0
  34. {temscript-2.0.0 → temscript-2.1.0}/scripts/test_json_encoder.py +0 -0
  35. {temscript-2.0.0 → temscript-2.1.0}/setup.cfg +0 -0
  36. {temscript-2.0.0 → temscript-2.1.0}/setup.py +0 -0
  37. {temscript-2.0.0 → temscript-2.1.0}/temscript/__init__.py +0 -0
  38. {temscript-2.0.0 → temscript-2.1.0}/temscript/_instrument_stubs.py +0 -0
  39. {temscript-2.0.0 → temscript-2.1.0}/temscript/instrument.py +0 -0
  40. {temscript-2.0.0 → temscript-2.1.0}/temscript/marshall.py +0 -0
  41. {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/dependency_links.txt +0 -0
  42. {temscript-2.0.0 → temscript-2.1.0}/temscript.egg-info/requires.txt +0 -0
  43. {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
1
+ Metadata-Version: 2.2
2
2
  Name: temscript
3
- Version: 2.0.0
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 wheels file (using pip)
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 wheels file (using pip)
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
 
@@ -0,0 +1,4 @@
1
+ sphinx
2
+ sphinx_rtd_theme
3
+ readthedocs-sphinx-search
4
+ numpy
@@ -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 %sis not readable" % self._name)
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 %sis not writable" % self._name)
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 %sis not readable" % self._name)
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 %sis not writable" % self._name)
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 %sis not readable" % self._name)
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 %sis not writable" % self._name)
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 %sis not readable" % self._name)
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 %sis not writable" % self._name)
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 %sis not readable" % self._name)
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 %sis not writable" % self._name)
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
- Base class for Microscope classes. Do not use directly.
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
- If microscope is in imaging mode, 0 is returned.
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
- If microscope is in diffraction mode, 0 is returned.
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
- self._family = tem.Configuration.ProductFamily
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._tem_vacuum.ColumnValvesOpen,
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
1
+ Metadata-Version: 2.2
2
2
  Name: temscript
3
- Version: 2.0.0
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 wheels file (using pip)
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
-
@@ -11,6 +11,7 @@ docs/index.rst
11
11
  docs/instrument.rst
12
12
  docs/make.bat
13
13
  docs/microscope.rst
14
+ docs/requirements.txt
14
15
  docs/restrictions.rst
15
16
  docs/server.rst
16
17
  scripts/run_null_server.py
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  temscript-server = temscript.server:run_server
3
-
@@ -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