def __init__(self, refresh_time=30): super().__init__() uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'designer', 'MainWindow.ui'), self) self.logger = get_logger(name=__name__) self.central_layout = QHBoxLayout(self.centralwidget) self.widget_splitter = QSplitter() self.camera_viewer_widget = CameraViewerWidget() self.histogram_tracks_widget = HistogramTracksWidget(self) self.widget_splitter.addWidget(self.camera_viewer_widget) self.widget_splitter.addWidget(self.histogram_tracks_widget) self.widget_splitter.setSizes((750, 750)) self.central_layout.addWidget(self.widget_splitter) self.config_widget = ConfigWidget() self.config_tracking_widget = ConfigTrackingWidget() self.refresh_timer = QTimer() self.refresh_timer.timeout.connect(self.update_gui) self.refresh_timer.start(refresh_time) self.showMaximized() self.connect_actions() self.connect_buttons() self.connect_signals()
def main(): logger = get_logger( ) # 'nanoparticle_tracking.model.experiment.nanoparticle_tracking.saver' logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) parser = ArgumentParser(description='Start the pyNTA software') parser.add_argument("-c", dest="config_file", required=False, help="Path to the configuration file") args = parser.parse_args() if args.config_file is None: config_file = os.path.join(BASE_DIR, 'util', 'example_config.yml') else: config_file = args.config_file exp = NPTracking(config_file) exp.initialize_camera() app = QApplication([]) window = MainWindow(exp) window.show() app.exec()
def publisher(queue, event, port): """ Simple method that starts a publisher on the port 5555. :param multiprocessing.Queue queue: Queue of messages to be broadcasted :param multiprocessing.Event event: Event to stop the publisher :param int port: port in which to broadcast data .. TODO:: The publisher's port should be determined in a configuration file. """ logger = get_logger(name=__name__) port_pub = port context = zmq.Context() socket = context.socket(zmq.PUB) socket.bind("tcp://*:%s" % port_pub) sleep(1) # It takes a time for subscribers to propagate to the publisher. # Without this sleep the first packages may be lost logger.info('Bound socket on {}'.format(port_pub)) while not event.is_set(): while not queue.empty(): data = queue.get( ) # Should be a dictionary {'topic': topic, 'data': data} logger.debug('Sending {} on {}'.format(data['data'], data['topic'])) socket.send_string(data['topic'], zmq.SNDMORE) socket.send_pyobj(data['data']) if general_stop_event.is_set(): break sleep(0.05) # Sleeps 5 milliseconds to be polite with the CPU sleep(1) # Gives enough time to the subscribers to update their status socket.close() logger.info('Stopped the publisher')
def __init__(self, port=5555): self.logger = get_logger(name=__name__) self._port = port self._queue = Queue( ) # The publisher will grab and broadcast the messages from this queue self._event = Event() # This event is used to stop the process self._process = Process(target=publisher, args=[self._queue, self._event, self._port]) self.logger.info('Initialized published on port {}'.format(port))
def func_wrapper(*args, **kwargs): logger = get_logger(name=__name__) logger.info('Starting a new thread for {}'.format(func.__name__)) args[0]._processes.append( [func.__name__, Process(target=func, args=args, kwargs=kwargs)]) args[0]._processes[-1][1].start() logger.debug('In total there are {} processes'.format( len(args[0]._threads)))
def __init__(self, camera): self.camera = camera self.running = False self.max_width = 0 self.max_height = 0 self.exposure = 0 self.config = {} self.data_type = np.uint16 # The data type that the camera generates when acquiring images. It is very important to have it available in order to create the buffer and saving to disk. self.logger = get_logger(name=__name__)
def __init__(self, port=None): self.logger = get_logger(name=__name__) if not port: self._port = config.zmq_port else: self._port = port self._queue = Queue( ) # The publisher will grab and broadcast the messages from this queue self._event = Event() # This event is used to stop the process self._process = None self.logger.info('Initialized publisher on port {}'.format(self._port))
def __init__(self, camera): super().__init__(camera) self.running = False self.xsize = 1080 self.ysize = 720 self.sb = SimBrownian((self.xsize, self.ysize)) self.maxX = 1800 self.maxY = 720 self.exposure = Q_('10ms') self.X = [0, self.maxX-1] self.Y = [0, self.maxY-1] self.logger = get_logger(name=__name__)
def worker_listener(file_path, meta, topic, port=5555, max_memory=500): """ Function that listens on the specified port for new data and then saves it to disk. It is the same as :func:`worker_saver` but implementing a ZMQ socket instead of grabbing data from a queue. :param str file_path: the path to the file to use. :param str meta: Metadata. It is kept as a string in order to provide flexibility for other programs. :param int port: Port on which to listen for publisher data :param int max_memory: Maximum memory (in MB) to allocate """ logger = get_logger(name=__name__) logger.info('Starting worker saver for topic {} on port {}'.format( topic, port)) context = zmq.Context() socket = context.socket(zmq.SUB) socket.connect("tcp://localhost:{}".format(port)) topic_filter = topic.encode('ascii') socket.setsockopt(zmq.SUBSCRIBE, topic_filter) allocate_memory = max_memory # megabytes of memory to allocate on the hard drive. with h5py.File(file_path, "a") as f: now = str(datetime.now()) g = f.create_group(now) g.create_dataset('metadata', data=meta.encode("ascii", "ignore")) # Has to be submitted via the socket a string 'stop' i = 0 j = 0 first = True while True: topic = socket.recv_string() data = socket.recv_pyobj() logger.debug('Got data of type {} on the saver topic {}.'.format( type(data), topic)) if isinstance(data, str): logger.info('Got the signal to stop the saving') break data = data[1] if first: # First time it runs, creates the dataset x = data.shape[0] y = data.shape[1] logger.debug('Image size: {}x{}'.format(x, y)) allocate = int(allocate_memory / data.nbytes * 1024 * 1024) logger.debug('Allocating {}MB to stream to disk'.format( allocate_memory)) logger.debug('Allocate {} frames'.format(allocate)) d = np.zeros((x, y, allocate), dtype=data.dtype) dset = g.create_dataset( 'timelapse', (x, y, allocate), maxshape=(x, y, None), compression='gzip', compression_opts=1, dtype=data.dtype ) # The images are going to be stacked along the z-axis. d[:, :, i] = data i += 1 first = False else: if i == allocate: logger.debug('Allocating more memory') dset[:, :, j:j + allocate] = d dset.resize((x, y, j + 2 * allocate)) d = np.zeros((x, y, allocate), dtype=data.dtype) i = 0 j += allocate d[:, :, i] = data i += 1 if j > 0 or i > 0: logger.info('Saving last bits of data before stopping.') logger.debug('Missing values: {}'.format(i)) dset[:, :, j:j + i] = d[:, :, :i] # Last save before closing # This last bit is to avoid having a lot of zeros at the end of the timelapses dset.resize((x, y, j + i)) logger.info('Flushing file to disk...') f.flush() logger.info('Finished writing to disk')
def worker_saver(file_path, meta, q, max_memory=500): """Function that can be run in a separate thread for continuously save data to disk. :param str file_path: the path to the file to use. :param str meta: Metadata. It is kept as a string in order to provide flexibility for other programs. :param Queue q: Queue that will store all the images to be saved to disk. :param int max_memory: Maximum memory (in MB) to allocate """ logger = get_logger(name=__name__) logger.info('Appending data to {}'.format(file_path)) allocate_memory = max_memory # megabytes of memory to allocate on the hard drive. with h5py.File(file_path, "a") as f: now = str(datetime.now()) g = f.create_group(now) g.create_dataset('metadata', data=meta.encode("ascii", "ignore")) keep_saving = True # Flag that will stop the worker function if running in a separate thread. # Has to be submitted via the queue a string 'exit' i = 0 j = 0 first = True while keep_saving: while not q.empty() or q.qsize() > 0: img = q.get() if isinstance(img, str): keep_saving = False logger.info('Got the signal to stop the saving') continue if first: # First time it runs, creates the dataset x = img.shape[0] y = img.shape[1] logger.debug('Image size: {}x{}'.format(x, y)) allocate = int(allocate_memory / img.nbytes * 1024 * 1024) logger.debug('Allocating {}MB to stream to disk'.format( allocate_memory)) logger.debug('Allocate {} frames'.format(allocate)) d = np.zeros((x, y, allocate), dtype=img.dtype) dset = g.create_dataset( 'timelapse', (x, y, allocate), maxshape=(x, y, None), compression='gzip', compression_opts=1, dtype=img.dtype ) # The images are going to be stacked along the z-axis. d[:, :, i] = img i += 1 first = False else: if i == allocate: logger.debug('Allocating more memory') dset[:, :, j:j + allocate] = d dset.resize((x, y, j + 2 * allocate)) d = np.zeros((x, y, allocate), dtype=img.dtype) i = 0 j += allocate d[:, :, i] = img i += 1 if j > 0 or i > 0: logger.info('Saving last bits of data before stopping.') logger.debug('Missing values: {}'.format(i)) dset[:, :, j:j + i] = d[:, :, :i] # Last save before closing # This last bit is to avoid having a lot of zeros at the end of the timelapses dset.resize((x, y, j + i)) logger.info('Flushing file to disk...') f.flush() logger.info('Finished writing to disk')
is very important for the GUI, since after the first crop, if the user wants to crop even further, the information has to be referenced to the already cropped area. .. note:: **IMPORTANT** Whatever new function is implemented in a specific model, it should be first declared in the BaseCamera class. In this way the other models will have access to the method and the program will keep running (perhaps with non intended behavior though). :copyright: Aquiles Carattino <*****@*****.**> :license: GPLv3, see LICENSE for more details """ import numpy as np from pynta.model.cameras.decorators import not_implemented from pynta.util.log import get_logger from pynta import Q_ logger = get_logger(__name__) class BaseCamera: MODE_CONTINUOUS = 1 MODE_SINGLE_SHOT = 0 ACQUISITION_MODE = { MODE_CONTINUOUS: 'Continuous', MODE_SINGLE_SHOT: 'Single' } def __init__(self, camera): self.camera = camera self.running = False self.max_width = 0 self.max_height = 0
import logging from time import sleep from pynta.model.experiment.nanoparticle_tracking.np_tracking import NPTracking from pynta.util.log import get_logger logger = get_logger( ) # 'nanoparticle_tracking.model.experiment.nanoparticle_tracking.saver' logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) if __name__ == '__main__': with NPTracking('config/nanocet.yml') as exp: sleep(1) # exp.connect(calculate_positions_image, 'free_run', exp.publisher_queue, **exp.config['tracking']['locate']) # exp.connect(add_to_save_queue, 'free_run', exp.saver_queue) # exp.connect(add_linking_queue, 'trackpy_locations', exp.locations_queue) # exp.connect(add_links_to_queue, 'particle_links', exp.tracks_queue) exp.initialize_camera() # exp.link_particles() exp.save_stream() sleep(1) exp.start_free_run() logger.info('Going to sleep for 5 seconds') sleep(5) logger.info('Keep acquiring set to false')
Base model for communicating with Arduino devices. In principle, Arduino's can be programmed in very different ways, and therefore the flow of information may be very different. This model is thought to interface with an Arduino which is in control of two DC motors and which is able to read values from some devices, such as a DHT22, and a DS18B20. It relies on PyVisa with pyvisa-py as backend in order to establish the communication with the device. """ from time import sleep import pyvisa from pynta.util.log import get_logger # TODO: Make more flexible which backend will be used for PyVisa from pynta.model.exceptions import OutOfRange rm = pyvisa.ResourceManager('@py') logger = get_logger(name=__name__) class Arduino: def __init__(self, port=None): """ :param port: Serial port where the Arduino is connected, can be none and in order to look for devices automatically """ logger.info(f'Starting Arduino class on port {port}') self.rsc = None self.port = port if port: if not port.startswith('ASRL'): port = 'ASRL' + port
def update_tracking_config(self, config): self.logger.error('Update Tracking config method not defined') def update_config(self, config): self.logger.error('Update Config method not defined') def closeEvent(self, *args, **kwargs): self.config_widget.close() self.config_tracking_widget.close() super(MainWindowGUI, self).closeEvent(*args, **kwargs) if __name__ == "__main__": import sys import logging from PyQt5.QtWidgets import QApplication logger = get_logger(name=__name__) logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) app = QApplication([]) win = MainWindowGUI() win.show() sys.exit(app.exec_())
) # Should be a dictionary {'topic': topic, 'data': data} logger.debug('Sending {} on {}'.format(data['data'], data['topic'])) socket.send_string(data['topic'], zmq.SNDMORE) socket.send_pyobj(data['data']) if general_stop_event.is_set(): break sleep(0.05) # Sleeps 5 milliseconds to be polite with the CPU sleep(1) # Gives enough time to the subscribers to update their status socket.close() logger.info('Stopped the publisher') if __name__ == "__main__": logger = get_logger( name=__name__) # 'pynta.model.experiment.nano_cet.saver' logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) p = Publisher() p.start() p.publish('Testing', [1, 2, 3, 4]) sleep(1) p.stop() p.join()
import logging from time import sleep from pynta.model.experiment.nano_cet.win_nanocet import NanoCET from pynta.util.log import get_logger logger = get_logger() # 'pynta.model.experiment.nano_cet.saver' logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) if __name__ == '__main__': with NanoCET('config/nanocet.yml') as exp: sleep(1) # exp.connect(calculate_positions_image, 'free_run', exp.publisher_queue, **exp.config['tracking']['locate']) # exp.connect(add_to_save_queue, 'free_run', exp.saver_queue) # exp.connect(add_linking_queue, 'trackpy_locations', exp.locations_queue) # exp.connect(add_links_to_queue, 'particle_links', exp.tracks_queue) exp.initialize_camera() # exp.link_particles() exp.save_stream() sleep(1) exp.start_free_run() logger.info('Going to sleep for 5 seconds') sleep(5) logger.info('Keep acquiring set to false') exp.keep_acquiring = False