Skip to content

Commit

Permalink
Updated package links. Minor docu changes. (#4)
Browse files Browse the repository at this point in the history
* Updated package links. Minor docu changes.

* Code quality imporvements.
  • Loading branch information
igor-shavrin committed Jun 14, 2021
1 parent eee2e39 commit 032cce3
Show file tree
Hide file tree
Showing 14 changed files with 57 additions and 56 deletions.
4 changes: 2 additions & 2 deletions TimeTaggerRPC/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""RPC for Swabian Instruments' Time Tagger"""

__version__ = '0.0.4a7'
__author__ = 'Igor Shavrin'
__version__ = '0.0.4a8'
__author__ = 'Igor Shavrin'
5 changes: 1 addition & 4 deletions TimeTaggerRPC/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

# Load enum definitions and construct enum classes
definitions = self.enum_definitions() #
definitions = self.enum_definitions() #
for name, (enum_type, args) in definitions.items():
self.__dict__[name] = getattr(enum, enum_type)(name, args)
self._pyroRelease()
Expand All @@ -32,6 +32,3 @@ def createProxy(host: str = 'localhost', port: int = 23000, _objectId: str = 'Ti

uri = f"PYRO:{_objectId}@{host}:{port}"
return TTProxy(uri)



39 changes: 19 additions & 20 deletions TimeTaggerRPC/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@


EXCLUDED_LIBRARY_MEMBERS = [
'TimeTaggerBase', 'IteratorBase', 'Iterator', 'FlimAbstract',
'TimeTaggerVirtual', 'createTimeTaggerVirtual',
'CustomMeasurement', 'CustomMeasurementBase',
'TimeTaggerBase', 'IteratorBase', 'Iterator', 'FlimAbstract',
'TimeTaggerVirtual', 'createTimeTaggerVirtual',
'CustomMeasurement', 'CustomMeasurementBase',
'TimeTagStream', 'FileReader', 'TimeTagStreamBuffer',
'setLogger', 'setCustomBitFileName', 'hasTimeTaggerVirtualLicense',
'setFrontend', 'setLanguageInfo', 'flashLicense',
Expand All @@ -33,13 +33,13 @@ def pyro_track_resource(resource):

class TrackedResource:
"""Implements 'close' method that clears the underlying object.
This class is not exposed by the Pyro and therefore its methods do
This class is not exposed by the Pyro and therefore its methods do
not appear on the client proxy.
"""
_obj: None

def close(self):

logging.debug('Close: %s', type(self).__name__)
try:
if issubclass(self._obj, TT.TimeTaggerBase):
Expand Down Expand Up @@ -91,7 +91,7 @@ def method_proxy(self, *args, **kwargs):


def make_iterator_adapter_class(class_name: str):
"""Generates adapter class for the given Time Tagger iterator class
"""Generates adapter class for the given Time Tagger iterator class
and exposes them with Pyro.
"""
iterator_class = getattr(TT, class_name)
Expand Down Expand Up @@ -119,14 +119,14 @@ def __init__(self, tagger_adapter, *args, **kwargs):
if attrib.kind == 'method':
# print('| --> ', attrib.name)
methods[attrib.name] = make_class_method_proxy(attrib)

# Expose class methods with Pyro
IteratorAdapter = Pyro5.api.expose(type(class_name, (TrackedResource,), methods))
return IteratorAdapter


def make_synchronized_measurements_adaptor_class():
"""Generates adapter class for the given Time Tagger iterator class
"""Generates adapter class for the given Time Tagger iterator class
and exposes them with Pyro.
"""
Cls = TT.SynchronizedMeasurements
Expand Down Expand Up @@ -177,7 +177,7 @@ def unregisterMeasurement(self, measurement_proxy):
if attrib.kind == 'method':
# print(' --> ', attrib.name)
methods[attrib.name] = make_class_method_proxy(attrib)

# Expose class methods with Pyro
IteratorAdapter = Pyro5.api.expose(type(class_name, (TrackedResource,), methods))
return IteratorAdapter
Expand Down Expand Up @@ -221,13 +221,13 @@ def __init__(self, *args, **kwargs):

def make_iterator_constructor(iterator_name: str):
"""Generates a method that constructs the Time Tagger Iterator object and its adaptor.
The constructor method will be exposed via Pyro and allows creation of the measurements
The constructor method will be exposed via Pyro and allows creation of the measurements
and virtual channels via the TimeTaggerRPC interface.
"""

AdapterClass = make_iterator_adapter_class(iterator_name)

def constructor(self, tagger_proxy, *args, **kwargs):
def constructor(self, tagger_proxy, *args, **kwargs):
tagger_adapter = self._pyroDaemon.proxy2object(tagger_proxy)
pyro_obj = AdapterClass(tagger_adapter, *args, **kwargs)
self._pyroDaemon.register(pyro_obj)
Expand All @@ -240,13 +240,13 @@ def constructor(self, tagger_proxy, *args, **kwargs):

def make_synchronized_measurement_constructor():
"""Generates a method that constructs the SynchronizedMeasurements object and its adaptor.
The constructor method will be exposed via Pyro and allows creation of the measurements
The constructor method will be exposed via Pyro and allows creation of the measurements
and virtual channels via the TimeTaggerRPC interface.
"""

AdapterClass = make_synchronized_measurements_adaptor_class()

def constructor(self, tagger_proxy):
def constructor(self, tagger_proxy):
tagger_adapter = self._pyroDaemon.proxy2object(tagger_proxy)
pyro_obj = AdapterClass(tagger_adapter)
self._pyroDaemon.register(pyro_obj)
Expand All @@ -259,7 +259,7 @@ def constructor(self, tagger_proxy):

def make_tagger_constructor(class_name: str):
"""Generates a method that constructs the Time Tagger object and its adaptor.
The constructor method will be exposed via Pyro and allows creation
The constructor method will be exposed via Pyro and allows creation
of time taggers via the TimeTaggerRPC interface.
"""
TimeTaggerAdaptor = make_timetagger_adapter_class(class_name)
Expand Down Expand Up @@ -389,27 +389,26 @@ def main():
)
)
parser.add_argument(
'--host', type=str, dest='host', metavar='localhost', default='localhost',
'--host', type=str, dest='host', metavar='localhost', default='localhost',
help='Hostname or IP on which the server will listen for connections.'
)
parser.add_argument(
'--port', type=int, dest='port', default=23000, metavar='23000',
'--port', type=int, dest='port', default=23000, metavar='23000',
help='Server port.'
)
parser.add_argument(
'--use_ns', dest='use_ns', action='store_true',
'--use_ns', dest='use_ns', action='store_true',
help='Use Pyro5 nameserver.'
)
parser.add_argument(
'--start_ns', dest='start_ns', action='store_true',
'--start_ns', dest='start_ns', action='store_true',
help='Start Pyro5 nameserver in a subprocess.'
)

args = parser.parse_args()

start_server(**vars(args))



if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions doc/_static/placeholder.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This file is needed to include this folder into the repository.
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# -- Project information -----------------------------------------------------

project = 'Time Tagger RPC'
copyright = '2021, Igor Shavrin <[email protected]>'
copyright = '2021 Swabian Instruments GmbH'
author = 'Igor Shavrin <[email protected]>'


Expand Down
28 changes: 17 additions & 11 deletions doc/cookbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ Serving Time Tagger to multiple clients


This section describes how to access the same Time Tagger object from multiple processes on one PC.
Access from multiple PCs is done the same way except you have to configure the server for providing access over the network.

In order to access the TimeTaggerRPC server from multiple PCs, you have to configure the server for providing access over the network.
This is done by starting the server with ``--host`` parameter and specifying explicit IP address ``<SERVER_IP>`` on which the server shall listen for connections.

.. code::
TimeTaggerRPC-server --host <SERVER_IP>
On the client you can connect to the server as follows:

.. code:: python
# Process 1
from TimeTaggerRPC import client
TT = client.createProxy()
TT = client.createProxy(host='<SERVER_IP>')
tagger_proxy = TT.createTimeTagger()
tagger_proxy.getSerial()
'1740000JG2'
# Get the URI of the Time Tagger object.
print(tagger_proxy._pyroUri)
'PYRO:obj_b2d2c3cc61b8460d921dccededff8274@localhost:23000'
'PYRO:obj_b2d2c3cc61b8460d921dccededff8274@<SERVER_IP>:23000'
Now you can do on another process / PC the following

Expand All @@ -32,10 +40,10 @@ Now you can do on another process / PC the following
# Access the Time Tagger library.
# It is always the same server object (singleton)
TT = client.createProxy()
TT = client.createProxy(host='<SERVER_IP>')
# Connect to the existing Time Tagger object by its URI
uri = 'PYRO:obj_b2d2c3cc61b8460d921dccededff8274@localhost:23000'
uri = 'PYRO:obj_b2d2c3cc61b8460d921dccededff8274@<SERVER_IP>:23000'
tagger_proxy = Proxy(uri)
tagger_proxy.getSerial()
'1740000JG2'
Expand All @@ -44,14 +52,12 @@ Now you can do on another process / PC the following
This demonstrates how one can use multiple clients or processes to access the same Time Tagger.
Warning, if one of the clients does something like

.. code::

TT.freeTimeTagger(tagger_proxy)
.. warning::

all of the clients using this object will be interrupted because the server received
a command to close the TimeTagger hardware connection.
If any of the clients executes the following command ``TT.freeTimeTagger(tagger_proxy)``,
all of the clients using this object will be interrupted because the server received
a command to close the TimeTagger hardware connection.

Currently, there is no intention to implement access management code in the TimeTaggerRPC package.
If you want to develop a common access infrastructure in your lab then you can follow one of the strategies
Expand Down
8 changes: 4 additions & 4 deletions examples/multiple_threads.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
This example demonstrates how to use Proxy objects in multiple Python threads.
Pyro5 does not allow access to Proxy objects from multiple threads.
However, one can transfer ownership of an existing Proxy object to another thread
However, one can transfer ownership of an existing Proxy object to another thread
if required.
For more information see:
For more information see:
https://pyro5.readthedocs.io/en/latest/clientcode.html#proxy-sharing-between-threads
"""
Expand Down Expand Up @@ -34,7 +34,7 @@ def thread_worker(crate, stop):
tagger.setTestSignal(2, True)

# Create Countrate measurements and return their Pyro5 proxies
crate1 = TT.Counter(tagger, [1], binwidth=int(1e12), n_values=2)
crate1 = TT.Counter(tagger, [1], binwidth=int(1e12), n_values=2)
crate2 = TT.Counter(tagger, [2], binwidth=int(1e11), n_values=5)

# Create threads
Expand All @@ -45,7 +45,7 @@ def thread_worker(crate, stop):
t1.start()
t2.start()
while t1.is_alive() or t2.is_alive():
time.sleep(0.1)
time.sleep(0.1)

except KeyboardInterrupt:
stop_evt.set()
Expand Down
2 changes: 1 addition & 1 deletion examples/simple_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@
TimeTagger.freeTimeTagger(tagger)
del hist
del tagger
del TimeTagger
del TimeTagger
2 changes: 1 addition & 1 deletion examples/synchronized_measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@

TimeTagger.freeTimeTagger(tagger)
del tagger
del TimeTagger
del TimeTagger
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ build-backend = "flit_core.buildapi"

[tool.flit.metadata]
module = "TimeTaggerRPC"
author = "Igor Shavrin"
author = "Igor Shavrin, Swabian Instruments GmbH"
author-email = "[email protected]"
home-page = "https://github.com/igor-shavrin/TimeTaggerRPC"
home-page = "https://github.com/swabianinstruments/TimeTaggerRPC"
description-file = "README.md"
requires = [
"Pyro5",
Expand All @@ -29,7 +29,7 @@ classifiers=[
]

[tool.flit.metadata.urls]
Documentation = "https://www.swabianinstruments.com/static/documentation/TimeTagger/index.html"
Documentation = "https://timetaggerrpc.readthedocs.io/"
Hardware = "https://www.swabianinstruments.com/time-tagger/"

[tool.flit.scripts]
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import setuptools

setuptools.setup()
setuptools.setup()
8 changes: 4 additions & 4 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import typing

import numpy as np
import matplotlib.pyplot as plt

Expand All @@ -25,14 +25,14 @@
print('hist ', hist._pyroUri)
print('hist2', hist2._pyroUri)

crate = TT.Countrate(tagger, [1,2])
crate = TT.Countrate(tagger, [1, 2])
crate.clear()

hist.startFor(int(10e12), clear=True)

fig, ax = plt.subplots()
h, = ax.plot([],[])
h2, = ax.plot([],[])
h, = ax.plot([], [])
h2, = ax.plot([], [])
# the time vector is fixed. No need to read it on every iteration
x = hist.getIndex()
x2 = hist2.getIndex()
Expand Down
1 change: 0 additions & 1 deletion tests/test_enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
with createProxy() as TT:
print([v for v in dir(TT) if not v.startswith('_')])
print(list(TT.ChannelEdge))

5 changes: 2 additions & 3 deletions tests/test_remote_object_destruction.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import time
import typing

from TimeTaggerRPC.client import createProxy

Expand All @@ -25,12 +24,12 @@
hist_list = list()
for i in range(5):
h = TT.Correlation(tagger, 1, DELAYED_CH, binwidth=10, n_bins=2000)
print(f'hist_{i}', h._pyroUri)
print(f'hist_{i}', h._pyroUri)
hist_list.append(h)
sm.registerMeasurement(h)


crate = TT.Countrate(tagger, [1,2])
crate = TT.Countrate(tagger, [1, 2])
print('crate', crate._pyroUri)
crate.clear()

Expand Down

0 comments on commit 032cce3

Please sign in to comment.