Browse Source

Updated documentation methods.

master
Carlos Reding 1 year ago
parent
commit
6a6428039b

+ 28
- 22
pupuicon/_corelib.py View File

@@ -7,13 +7,13 @@ def _get_response(Connection, BUFFER_SIZE):

class InitNetwork(object):
"""
Initialise server instance for L|MO control panel.
Initialise server instance for L|MO control panel.\n\n

:PORT.
:PORT.\n
Port used to accept incoming connections. Range 1-65355
(defaults to 10011).
(defaults to 10011).\n\n

:MAX_CONNECTIONS.
:MAX_CONNECTIONS.\n
Maximum number of connections accepted by the server.
It defaults to 1, as it makes no sense one box being
controlled by more than one user at any given time.
@@ -22,7 +22,7 @@ class InitNetwork(object):
"""
Detect available interfaces in the host computer. Defaults
to wlan (wireless) interface unless an ethernet cable is
plugged in.
plugged in.\n\n
TODO:
- Optional interface or favour wlan even with cable?
- Retrieve and keep client's hostname.
@@ -64,7 +64,7 @@ class InitNetwork(object):
Initialise server and await for incoming connections. The
`accept()' command will make the rest of the code stall until
a client connects. Which is okay... what's the box going to
do if no-one tells it what to do? Just wait for a connection.
do if no-one tells it what to do? Just wait for a connection.\n\n

SO_REUSEADDR makes possible to keep the server alive when
a client disconnects and avoids `TIME_WAIT' situations, where
@@ -119,7 +119,7 @@ class InitNetwork(object):
self._MAX_CONNECTIONS = MAX_CONNECTIONS
self.Socket, self.Connection, self.Curr_Interface = self._init_connection(BUFFER_SIZE)
# Before handing over the conection to the GUI, check if any data has
# not been transferred:
# not been transferred. TODO.

class NetworkOperator():
"""
@@ -127,33 +127,38 @@ class NetworkOperator():
the L|MO and the client. It will tell the user that a connection
has been established and the L|MO is awaiting a command. It also
receives a command from the user and redirects to the appropriate
routine.
routine.\n\n

LIST OF AVAILABLE COMMANDS:
LIST OF AVAILABLE COMMANDS:\n
- Run Protocol: Reads the protocol in Rob's LIF Format (.RLF?) sent
by the user. It then retrieves the information
needed by SetupDevice() and SetProtocol(), from the
puppeteer library, to run L|MO appropriately.
puppeteer library, to run L|MO appropriately.\n
- Abort Protocol: Self-explanatory, stops any on going experiment
running in L|MO.
running in L|MO.\n
- Report Progress: Reports experiment progress back to the user.
WORK IN PROGRESS. Reports current state by default
(STREAM) or as per client's request (say the user
goes home and wants to check how things are going).
goes home and wants to check how things are going).\n\n

More commands to be implemented (see commented code below).
"""
def _retrieve_data(self, Connection, BUFFER_SIZE):
""" Receive data sent from client and store it in the variable
`Stream'. """
"""
Receive data sent from client and store it in the variable `Stream'.
"""
Stream = Connection.recv(BUFFER_SIZE)
if len(Stream) < BUFFER_SIZE:
""" This snippet handles short packages (<BUFFER_SIZE) to allow
the handshake between server and client. """
"""
This snippet handles short packages (<BUFFER_SIZE) to allow the
handshake between server and client.
"""
return Stream
else:
""" This other snippet handles larger packages (>=BUFFER_SIZE) to
allow the transmission of actual data, like, say, a protocol. """
"""
This other snippet handles larger packages (>=BUFFER_SIZE) to
allow the transmission of actual data, like, say, a protocol.
"""
while Stream:
Buffer = Connection.recv(BUFFER_SIZE)
Stream += Buffer
@@ -161,6 +166,9 @@ class NetworkOperator():
return Stream

def _retrieve_protocol(self, ProtocolSize, Connection, BUFFER_SIZE):
"""
Retrieve data for ProtocolDump.
"""
ProtocolDump = Connection.recv(BUFFER_SIZE)
if len(ProtocolDump) < ProtocolSize:
ProtocolDump += Connection.recv(BUFFER_SIZE)
@@ -170,7 +178,7 @@ class NetworkOperator():
"""
Retrieve user input and runs commands accordingly. Because each
option must return something ("command"), there is no point using
`while True' loops here. They always break.\n
`while True' loops here. They always break.\n\n
After the handshake has been processed, _nothing_ other than the
command must be sent back to the client. So, no
@@ -179,8 +187,6 @@ class NetworkOperator():
handshake = self._retrieve_data(Connection, BUFFER_SIZE) # Waits for client.
# Handshake, what do I do?
if handshake.decode() == "Run Protocol":
## .lif file opened in client side, then sent over. # THIS HAS
## The box keeps no hard copy of protocols files (.lif) # CHANGED!
InstructionSize = int(self._retrieve_data(Connection, BUFFER_SIZE).decode())
Connection.sendall(str("Acknowledged").encode()) # Unlock to proceed.
instructions_dump = self._retrieve_protocol(InstructionSize, Connection, BUFFER_SIZE**3)
@@ -202,7 +208,7 @@ class NetworkOperator():
stream of data, sent or received. Based on TCP protocol
whereby data is sent as a stream of bytes. This routine
decides when a transfer is complete or when the stream
is still pouring data in.
is still pouring data in.\n\n

BUFFER_SIZE defines the amount of data transferred at each
step and is given in BYTES.

+ 1
- 1
pupuicon/translator/__init__.py View File

@@ -1,4 +1,4 @@
"""
Treat translator thoughtfully.
Translate GUI's protocol and hardware settings implementation.
"""
from ._core import ProtocolHandler, HardwareHandler

+ 39
- 25
pupuicon/translator/_core.py View File

@@ -10,23 +10,30 @@ sys.modules['hardwareVariables'] = hardwareVariables

class ProtocolHandler:
"""
Rob's LIF format (RLF?) to Puppeteer translation layer.
Translator module from GUI's protocol implementetion to puppeteer's
implementation. The GUI's instructions are received as a `protocol_dump'
and then translated into a `UserProtocol' object.
"""
def _LIF_loader(self, protocol_dump):
"""
The user protocol (UserProtocol) is sent over the network to the
device as a pickle. This pickle, through ProtocolHandler, will
then be loaded in the device and translated from Rob's protocol
to what the library puppeteer actually requires. For testing
purposes, ProtocolHandler is a local pickle file with .lif (LIMO
File) extension. The real use will _NOT_ involve local files.
The user protocol (protocol_dump) is sent over the network to the
device as a pickle. Retrieve.
"""
return pickle.loads(protocol_dump)

def _translate(self, UserProtocol):
"""
Translate information contained in Rob's pickle into something that
can be implemented in puppeteer, the library controlling the device.
Translate information contained in Rob's pickle (UserProtocol) to
what puppeteer, the library controlling the device, actually
requires:\n\n
- Temperature.\n
- Selected filters.\n
- Selected wavelengths.\n
- Light Intensities.\n
- Duration of the protocotol.\n
- Read frequency.\n
- Delay in the initiation of the protocol.\n
"""
# Temperature
self.temperature = UserProtocol.temperature
@@ -116,10 +123,11 @@ class ProtocolHandler:
"""
Creates local queue to keep track of a) what steps have been
requested by the user, and b) what steps have been completed.
The user can then access the latter to keep track of progress.\n
The user can then access the latter to keep track of progress.
`QueueTime' _must_ be a datetime structure. `QueueSteps' is
provided in *MINUTES*.
`Delay' is provided in *SECONDS*.\n
`QueueTime' _must_ be a datetime structure.\n
`QueueSteps' is provided in *MINUTES*.
"""
# Create list of expected read times.
QueueInfo = list()
@@ -136,14 +144,11 @@ class ProtocolHandler:
QueueWait.insert(0, Delay) # Insert incubation time for job 1.
else:
QueueWait = QueueSteps # Do not insert otherwise (grabSettings)
# Generate Queue.
# Define QueueFile @ USR **home** directory.
# cwd = os.getcwd().split('/') # splits path into array of strings
cwd = os.getcwd() # splits path into array of strings
srv_dir = "/.srv"
fName = "/queue.q"
# QueueFile = '/'.join(cwd[:3]) + fName # [:3] ensures that path is /home/USR/fName. FIX: Do we want user to see this?
QueueFile = cwd + srv_dir + fName # Stored in path hidden from user.
# Generate Queue @ USR **home** directory.
cwd = os.getcwd()
srv_dir = "/.srv" # HARDCODED! Here it is a neccessary evil.
fName = "/queue.q" # HARDCODED! Here it is a neccessary evil.
QueueFile = cwd + srv_dir + fName
with open(QueueFile, "w") as fOut:
fOut.writelines("Date, Time, Status, Waiting time (min)\n")
for step, waiting_time in zip(QueueInfo, QueueWait):
@@ -152,6 +157,11 @@ class ProtocolHandler:
return QueueWait, QueueInfo, QueueFile

def __init__(self, protocol_dump):
"""
Translate GUI's protocol instructions (`protocol_dump') and generate
progress record (`Queue'). This record is stored locally in
QueueFile, to be sent back to the GUI on demand to report progress.
"""
# Load instructions
UserInstructions = self._LIF_loader(protocol_dump)
# Translate instructions as per L|MO.
@@ -165,17 +175,20 @@ class ProtocolHandler:

class HardwareHandler():
"""
Retrieve hardware settings given by user and implement them.
Retrieve hardware settings given by user and implement them into the
light modulator.
"""
def _Settings_loader(self, settings_dump):
"""
The hardware settings (hwSettings) is sent over the network to the
device as a pickle. This pickle, through HardwareHandler, will
save this settings into disk..
The hardware settings (`settings_dump') is sent over the network to
the device as a pickle. Retrieve.
"""
return pickle.loads(settings_dump)
def _Arrange_settings(self, Settings):
"""
Create dictionary with the settings mandated by the GUI.
"""
hwSettings = dict()
# GPIO information
hwSettings["GPIO_PIN_RGB"] = Settings.GPIO_PIN_RGB
@@ -207,12 +220,13 @@ class HardwareHandler():
# Set paths:
hw_fName = "/hwsettings.hws"
Path = os.getcwd() + "/.srv"
# Arrange settings from hws to something meaningful:
# Arrange settings from hws into something meaningful:
hwSettings = self._Arrange_settings(Settings)
# Save in disk:
pickle.dump(hwSettings, open(Path + hw_fName, "wb"))

def __init__(self, settings_dump):
""" Retrieve hardware settings. """
# Load settings
Settings = self._Settings_loader(settings_dump)
# Store in disk

+ 4
- 0
pupuicon/translator/handlers/__init__.py View File

@@ -1 +1,5 @@
"""
Given that whole classes are saved into disk instead of relevant
information on the GUI side, we need this stuff... the class itself.
"""
from . import translateUIToHardware

BIN
pupuicon/translator/rob/LiMOinstructionsFile.lif View File


BIN
pupuicon/translator/rob/LiMOinstructionsFile2.lif View File


BIN
pupuicon/translator/rob/LiMOinstructionsFile3.lif View File


+ 0
- 29
pupuicon/translator/rob/test.py View File

@@ -1,29 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 13 10:11:55 2018
@author: RobertBeardmore
"""
import translateUIToHardware as TTH
lif = TTH.LiMOinstructions.loadLiMOinstructionsFile('LiMOinstructionsFile.lif')
print(TTH.LiMOinstructions.LiMOinstructionsText(lif))
lif2 = TTH.LiMOinstructions.loadLiMOinstructionsFile('LiMOinstructionsFile2.lif')
print(TTH.LiMOinstructions.LiMOinstructionsText(lif2))
lif3 = TTH.LiMOinstructions.loadLiMOinstructionsFile('LiMOinstructionsFile3.lif')
print(TTH.LiMOinstructions.LiMOinstructionsText(lif3))
print('At most 3 reads are assumed with these pairs:')
print('-----------------')
print(lif.filterToLEDPairing)
print('This marker denotes when no read is to be made: ' + str(lif.noReadMarker))
print('\n')
print('LED-filter info:')
print('-----------------')
print(lif.filterName)
print(lif.LEDname)

Loading…
Cancel
Save