Esempio n. 1
0
 def screenshot(
     task,
     url,
     width=settings.BASE_WEBPAGE_PREVIEW_WIDTH,
     height=settings.BASE_WEBPAGE_PREVIEW_HEIGHT,
     lifetime=settings.BASE_WEBPAGE_PREVIEW_LIFETIME,
 ):
     url_id = sha256()
     url_id.update(url.encode("utf-8"))
     url_id.update(bytes(width))
     url_id.update(bytes(height))
     key = url_id.hexdigest()
     logger.info(f"Screenshot for {url} @ {width}x{height}: {key}")
     if key in cache:
         logger.info(f"Found {key} in cache.")
         return key
     logger.info(f"Locking {key}")
     lock = cache.lock(key)
     lock.acquire()
     logger.info("Starting WebEngineScreenshot app")
     parent_conn, child_conn = Pipe()
     p = Process(target=WebpageTasks.worker, args=(url, width, height, child_conn))
     p.start()
     image = parent_conn.recv()
     p.join()
     if not image:
         logger.info("WebEngineScreenshot app returned nothing")
         return None
     logger.info("Writing WebEngineScreenshot app result to cache")
     cache.set(key, image, timeout=lifetime)
     logger.info("Removing WebEngineScreenshot app singleton")
     return key
Esempio n. 2
0
def main():
    # To assign camera by name: put string(s) in list

    # Parse command line arguments
    parser = argparse.ArgumentParser(description='GUI for gaze tracking and pupillometry')
    parser.add_argument('-eye', dest='eye_file', type=str, help="Work with existing video recording, instead of live feed", default='')
    parser.add_argument('-world', dest='world_file', type=str, help="Work with existing video recording, instead of live feed", default='')

    args = parser.parse_args()

    # to use a pre-recorded video.
    # Use a string to specify the path to your video file as demonstrated below
    if args.eye_file == '':
        eye_src = ["UI154xLE-M", "USB Camera-B4.09.24.1", "FaceTime Camera (Built-in)", "Microsoft", "6000","Integrated Camera"]
        # to assign cameras directly, using integers as demonstrated below
        # eye_src = 1
    else:
#        print "Using provide file: %s" % args.filename
        eye_src = args.eye_file

    if args.world_file == '':
        world_src = ["Logitech Camera","(046d:081d)","C510","B525", "C525","C615","C920","C930e"]
        # to assign cameras directly, using integers as demonstrated below
        # world_src = 0
    else:
        world_src = args.world_file

    # Camera video size in pixels (width,height)
    eye_size = (260,216) #(1280,1024)
    world_size = (640,480)


    # on MacOS we will not use os.fork, elsewhere this does nothing.
    forking_enable(0)

    # Create and initialize IPC
    g_pool = Temp()
    g_pool.pupil_queue = Queue()
    g_pool.eye_rx, g_pool.eye_tx = Pipe(False)
    g_pool.quit = RawValue(c_bool,0)
    # this value will be substracted form the capture timestamp
    g_pool.timebase = RawValue(c_double,0)
    # make some constants avaiable
    g_pool.user_dir = user_dir
    g_pool.rec_dir = rec_dir
    g_pool.version = version
    g_pool.app = 'capture'
    # set up subprocesses
    p_eye = Process(target=eye, args=(g_pool,eye_src,eye_size))

    # Spawn subprocess:
    p_eye.start()
    if platform.system() == 'Linux':
        # We need to give the camera driver some time before requesting another camera.
        sleep(0.5)

    world(g_pool,world_src,world_size)

    # Exit / clean-up
    p_eye.join()
Esempio n. 3
0
def main():

    # To assign camera by name: put string(s) in list
    eye_cam_names = [
        "USB 2.0 Camera", "Microsoft", "6000", "Integrated Camera",
        "HD USB Camera"
    ]
    world_src = [
        "Logitech Camera", "(046d:081d)", "C510", "B525", "C525", "C615",
        "C920", "C930e"
    ]
    eye_src = (eye_cam_names,
               0), (eye_cam_names, 1
                    )  #first match for eye0 and second match for eye1

    # to assign cameras directly, using integers as demonstrated below
    # eye_src =  4 , 5 #second arg will be ignored for monocular eye trackers
    # world_src = 1

    # to use a pre-recorded video.
    # Use a string to specify the path to your video file as demonstrated below
    # eye_src = '/Users/mkassner/Downloads/000/eye0.mkv' , '/Users/mkassner/Downloads/eye.avi'
    # world_src = "/Users/mkassner/Downloads/000/world.mkv"

    # Camera video size in pixels (width,height)
    eye_size = (640, 480)
    world_size = (1280, 720)

    # on MacOS we will not use os.fork, elsewhere this does nothing.
    forking_enable(0)

    #g_pool holds variables. Only if added here they are shared across processes.
    g_pool = Global_Container()

    # Create and initialize IPC
    g_pool.pupil_queue = Queue()
    g_pool.quit = Value(c_bool, 0)
    g_pool.timebase = Value(c_double, 0)
    g_pool.eye_tx = []
    # make some constants avaiable
    g_pool.user_dir = user_dir
    g_pool.version = get_version(version_file)
    g_pool.app = 'capture'
    g_pool.binocular = binocular

    p_eye = []
    for eye_id in range(1 + 1 * binocular):
        rx, tx = Pipe(False)
        p_eye += [
            Process(target=eye,
                    args=(g_pool, eye_src[eye_id], eye_size, rx, eye_id))
        ]
        g_pool.eye_tx += [tx]
        p_eye[-1].start()

    world(g_pool, world_src, world_size)

    # Exit / clean-up
    for p in p_eye:
        p.join()
Esempio n. 4
0
def main():
    timePipe, sigPipe = Pipe()
    q = Queue()
    clock = Process(target=tickTock, args=(timePipe, ))
    testSignal = Process(target=signal, args=(q, sigPipe, [1]))
    testSignal.start()
    while True:
        print(q.get())
Esempio n. 5
0
 def __init__(self, title='MAVProxy: console'):
     if platform.system() == 'Darwin':
         forking_enable(False)
     textconsole.SimpleConsole.__init__(self)
     self.title = title
     self.menu_callback = None
     self.parent_pipe_recv, self.child_pipe_send = Pipe(duplex=False)
     self.child_pipe_recv, self.parent_pipe_send = Pipe(duplex=False)
     self.close_event = Event()
     self.close_event.clear()
     self.child = Process(target=self.child_task)
     self.child.start()
     self.child_pipe_send.close()
     self.child_pipe_recv.close()
     t = threading.Thread(target=self.watch_thread)
     t.daemon = True
     t.start()
Esempio n. 6
0
    def _fork_and_submit_job(self, job):
        parent_pipe, child_pipe = Pipe()
        try:
            p = Process(target=self._submit_job_to_lsf,
                        args=(child_pipe, parent_pipe, job,))
            p.start()

        except:
            parent_pipe.close()
            raise
        finally:
            child_pipe.close()

        try:
            p.join()

            result = parent_pipe.recv()
            if isinstance(result, basestring):
                raise SubmitError(result)

        except EOFError:
            raise SubmitError('Unknown exception submitting job')
        finally:
            parent_pipe.close()

        return result
Esempio n. 7
0
    def __init__(self):
        self.input_queue = queue.Queue()
        self.rl = None
        self.console = wxconsole.MessageConsole(title='MAVExplorer')
        self.exit = False
        self.status = MEStatus()
        self.settings = MPSettings([
            MPSetting('marker', str, '+', 'data marker', tab='Graph'),
            MPSetting('condition', str, None, 'condition'),
            MPSetting('xaxis', str, None, 'xaxis'),
            MPSetting('linestyle', str, None, 'linestyle'),
            MPSetting('show_flightmode', bool, True, 'show flightmode'),
            MPSetting('legend', str, 'upper left', 'legend position'),
            MPSetting('legend2', str, 'upper right', 'legend2 position')
        ])

        self.mlog = None
        self.command_map = command_map
        self.completions = {
            "set": ["(SETTING)"],
            "condition": ["(VARIABLE)"],
            "graph": [
                '(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)'
            ],
            "map": ['(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)']
        }
        self.aliases = {}
        self.graphs = []
        self.flightmode_selections = []
        self.last_graph = GraphDefinition('Untitled', '', '', [], None)

        #pipe to the wxconsole for any child threads (such as the save dialog box)
        self.parent_pipe_recv_console, self.child_pipe_send_console = Pipe(
            duplex=False)
        #pipe for creating graphs (such as from the save dialog box)
        self.parent_pipe_recv_graph, self.child_pipe_send_graph = Pipe(
            duplex=False)

        tConsoleWrite = threading.Thread(target=self.pipeRecvConsole)
        tConsoleWrite.daemon = True
        tConsoleWrite.start()
        tGraphWrite = threading.Thread(target=self.pipeRecvGraph)
        tGraphWrite.daemon = True
        tGraphWrite.start()
Esempio n. 8
0
    def __init__(self):
        self.input_queue = Queue.Queue()
        self.rl = None
        self.console = wxconsole.MessageConsole(title='MAVExplorer')
        self.exit = False
        self.status = MEStatus()
        self.settings = MPSettings(
            [ MPSetting('marker', str, '+', 'data marker', tab='Graph'),
              MPSetting('condition', str, None, 'condition'),
              MPSetting('xaxis', str, None, 'xaxis'),
              MPSetting('linestyle', str, None, 'linestyle'),
              MPSetting('show_flightmode', bool, True, 'show flightmode'),
              MPSetting('legend', str, 'upper left', 'legend position'),
              MPSetting('legend2', str, 'upper right', 'legend2 position')
              ]
            )

        self.mlog = None
        self.command_map = command_map
        self.completions = {
            "set"       : ["(SETTING)"],
            "condition" : ["(VARIABLE)"],
            "graph"     : ['(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)'],
            "map"       : ['(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)']
            }
        self.aliases = {}
        self.graphs = []
        self.flightmode_selections = []
        self.last_graph = GraphDefinition('Untitled', '', '', [], None)
        
        #pipe to the wxconsole for any child threads (such as the save dialog box)
        self.parent_pipe_recv_console,self.child_pipe_send_console = Pipe(duplex=False)
        #pipe for creating graphs (such as from the save dialog box)
        self.parent_pipe_recv_graph,self.child_pipe_send_graph = Pipe(duplex=False)
        
        tConsoleWrite = threading.Thread(target=self.pipeRecvConsole)
        tConsoleWrite.daemon = True
        tConsoleWrite.start()
        tGraphWrite = threading.Thread(target=self.pipeRecvGraph)
        tGraphWrite.daemon = True
        tGraphWrite.start()
Esempio n. 9
0
def main():
    # To assign camera by name: put string(s) in list
    eye_src = ["Microsoft", "6000", "Integrated Camera"]
    world_src = [
        "Logitech Camera", "(046d:081d)", "C510", "B525", "C525", "C615",
        "C920", "C930e"
    ]

    # to assign cameras directly, using integers as demonstrated below
    # eye_src = 1
    # world_src = 0

    # to use a pre-recorded video.
    # Use a string to specify the path to your video file as demonstrated below
    # eye_src = '/Users/mkassner/Pupil/datasets/p1-left/frames/test.avi'
    # world_src = "/Users/mkassner/Desktop/2014_01_21/000/world.avi"

    # Camera video size in pixels (width,height)
    eye_size = (640, 360)
    world_size = (1280, 720)

    # on MacOS we will not use os.fork, elsewhere this does nothing.
    forking_enable(0)

    # Create and initialize IPC
    g_pool = Temp()
    g_pool.pupil_queue = Queue()
    g_pool.eye_rx, g_pool.eye_tx = Pipe(False)
    g_pool.quit = RawValue(c_bool, 0)
    # this value will be substracted form the capture timestamp
    g_pool.timebase = RawValue(c_double, 0)
    # make some constants avaiable
    g_pool.user_dir = user_dir
    g_pool.rec_dir = rec_dir
    g_pool.version = version
    g_pool.app = 'capture'
    # set up subprocesses
    p_eye = Process(target=eye, args=(g_pool, eye_src, eye_size))

    # Spawn subprocess:
    p_eye.start()
    if platform.system() == 'Linux':
        # We need to give the camera driver some time before requesting another camera.
        sleep(0.5)

    world(g_pool, world_src, world_size)

    # Exit / clean-up
    p_eye.join()
Esempio n. 10
0
def main():

    #IPC
    pupil_queue = Queue()
    timebase = Value(c_double, 0)

    cmd_world_end, cmd_launcher_end = Pipe()
    com0 = Pipe(True)
    eyes_are_alive = Value(c_bool, 0), Value(c_bool, 0)
    com1 = Pipe(True)
    com_world_ends = com0[0], com1[0]
    com_eye_ends = com0[1], com1[1]

    p_world = Process(target=world,
                      args=(pupil_queue, timebase, cmd_world_end,
                            com_world_ends, eyes_are_alive, user_dir,
                            app_version, video_sources['world']))
    p_world.start()

    while True:
        #block and listen for commands from world process.
        cmd = cmd_launcher_end.recv()
        if cmd == "Exit":
            break
        else:
            eye_id = cmd
            p_eye = Process(target=eye,
                            args=(pupil_queue, timebase, com_eye_ends[eye_id],
                                  eyes_are_alive[eye_id], user_dir,
                                  app_version, eye_id,
                                  video_sources['eye%s' % eye_id]))
            p_eye.start()

    for p in active_children():
        p.join()
    logger.debug('Laucher exit')
Esempio n. 11
0
 def __init__(self):
     (self.sender,self.receiver) = Pipe()
     self.alive = True
     self.pending = []
Esempio n. 12
0
class MEState(object):
    '''holds state of MAVExplorer'''
    def __init__(self):
        self.input_queue = queue.Queue()
        self.rl = None
        self.console = wxconsole.MessageConsole(title='MAVExplorer')
        self.exit = False
        self.status = MEStatus()
        self.settings = MPSettings([
            MPSetting('marker', str, '+', 'data marker', tab='Graph'),
            MPSetting('condition', str, None, 'condition'),
            MPSetting('xaxis', str, None, 'xaxis'),
            MPSetting('linestyle', str, None, 'linestyle'),
            MPSetting('show_flightmode', bool, True, 'show flightmode'),
            MPSetting('legend', str, 'upper left', 'legend position'),
            MPSetting('legend2', str, 'upper right', 'legend2 position')
        ])

        self.mlog = None
        self.command_map = command_map
        self.completions = {
            "set": ["(SETTING)"],
            "condition": ["(VARIABLE)"],
            "graph": [
                '(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)'
            ],
            "map": ['(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)']
        }
        self.aliases = {}
        self.graphs = []
        self.flightmode_selections = []
        self.last_graph = GraphDefinition('Untitled', '', '', [], None)

        #pipe to the wxconsole for any child threads (such as the save dialog box)
        self.parent_pipe_recv_console, self.child_pipe_send_console = Pipe(
            duplex=False)
        #pipe for creating graphs (such as from the save dialog box)
        self.parent_pipe_recv_graph, self.child_pipe_send_graph = Pipe(
            duplex=False)

        tConsoleWrite = threading.Thread(target=self.pipeRecvConsole)
        tConsoleWrite.daemon = True
        tConsoleWrite.start()
        tGraphWrite = threading.Thread(target=self.pipeRecvGraph)
        tGraphWrite.daemon = True
        tGraphWrite.start()

    def pipeRecvConsole(self):
        '''watch for piped data from save dialog'''
        try:
            while True:
                console_msg = self.parent_pipe_recv_console.recv()
                if console_msg is not None:
                    self.console.writeln(console_msg)
                time.sleep(0.1)
        except EOFError:
            pass

    def pipeRecvGraph(self):
        '''watch for piped data from save dialog'''
        try:
            while True:
                graph_rec = self.parent_pipe_recv_graph.recv()
                if graph_rec is not None:
                    mestate.input_queue.put(graph_rec)
                time.sleep(0.1)
        except EOFError:
            pass
Esempio n. 13
0
def main():

    # To assign camera by name: put string(s) in list
    world_src = [
        "Pupil Cam1 ID2", "Logitech Camera", "(046d:081d)", "C510", "B525",
        "C525", "C615", "C920", "C930e"
    ]
    eye0 = [
        "Pupil Cam1 ID0", "HD-6000", "Integrated Camera", "HD USB Camera",
        "USB 2.0 Camera"
    ]
    eye1 = ["Pupil Cam1 ID1", "HD-6000", "Integrated Camera"]
    eye_src = eye0, eye1

    # to assign cameras directly, using integers as demonstrated below
    # eye_src =  1 , 1 #second arg will be ignored for monocular eye trackers
    # world_src = 0

    # to use a pre-recorded video.
    # Use a string to specify the path to your video file as demonstrated below
    # eye_src = '/Users/mkassner/Downloads/eye0.mkv' , '/Users/mkassner/Downloads/eye.avi'
    # world_src = "/Users/mkassner/Downloads/000/world.mkv"

    # Default camera video size in pixels (width,height)
    eye_size = (640, 480)
    world_size = (1280, 720)

    # on MacOS we will not use os.fork, elsewhere this does nothing.
    forking_enable(0)

    #g_pool holds variables. Only if added here they are shared across processes.
    g_pool = Global_Container()

    # Create and initialize IPC
    g_pool.pupil_queue = Queue()
    g_pool.quit = Value(c_bool, 0)
    g_pool.timebase = Value(c_double, 0)
    g_pool.eye_tx = []
    # make some constants avaiable
    g_pool.user_dir = user_dir
    g_pool.version = get_version(version_file)
    g_pool.app = 'capture'
    g_pool.binocular = binocular

    p_eye = []
    for eye_id in range(1 + 1 * binocular):
        eye_end, world_end = Pipe(True)
        p_eye += [
            Process(target=eye,
                    args=(g_pool, eye_src[eye_id], eye_size, eye_end, eye_id))
        ]
        p_eye[-1].start()
        #wait for ready message from eye to sequentialize startup
        logger.debug(world_end.recv())
        g_pool.eye_tx += [world_end]

    world(g_pool, world_src, world_size)

    # Exit / clean-up
    for p in p_eye:
        p.join()
Esempio n. 14
0
class MEState(object):
    '''holds state of MAVExplorer'''
    def __init__(self):
        self.input_queue = Queue.Queue()
        self.rl = None
        self.console = wxconsole.MessageConsole(title='MAVExplorer')
        self.exit = False
        self.status = MEStatus()
        self.settings = MPSettings(
            [ MPSetting('marker', str, '+', 'data marker', tab='Graph'),
              MPSetting('condition', str, None, 'condition'),
              MPSetting('xaxis', str, None, 'xaxis'),
              MPSetting('linestyle', str, None, 'linestyle'),
              MPSetting('show_flightmode', bool, True, 'show flightmode'),
              MPSetting('legend', str, 'upper left', 'legend position'),
              MPSetting('legend2', str, 'upper right', 'legend2 position')
              ]
            )

        self.mlog = None
        self.command_map = command_map
        self.completions = {
            "set"       : ["(SETTING)"],
            "condition" : ["(VARIABLE)"],
            "graph"     : ['(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)'],
            "map"       : ['(VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE) (VARIABLE)']
            }
        self.aliases = {}
        self.graphs = []
        self.flightmode_selections = []
        self.last_graph = GraphDefinition('Untitled', '', '', [], None)
        
        #pipe to the wxconsole for any child threads (such as the save dialog box)
        self.parent_pipe_recv_console,self.child_pipe_send_console = Pipe(duplex=False)
        #pipe for creating graphs (such as from the save dialog box)
        self.parent_pipe_recv_graph,self.child_pipe_send_graph = Pipe(duplex=False)
        
        tConsoleWrite = threading.Thread(target=self.pipeRecvConsole)
        tConsoleWrite.daemon = True
        tConsoleWrite.start()
        tGraphWrite = threading.Thread(target=self.pipeRecvGraph)
        tGraphWrite.daemon = True
        tGraphWrite.start()
                
    def pipeRecvConsole(self):
        '''watch for piped data from save dialog'''
        try:
            while True:
                console_msg = self.parent_pipe_recv_console.recv()
                if console_msg is not None:
                    self.console.writeln(console_msg)
                time.sleep(0.1)
        except EOFError:
            pass

    def pipeRecvGraph(self):
        '''watch for piped data from save dialog'''
        try:
            while True:
                graph_rec = self.parent_pipe_recv_graph.recv()
                if graph_rec is not None:
                    mestate.input_queue.put(graph_rec)
                time.sleep(0.1)
        except EOFError:
            pass
Esempio n. 15
0
class MessageConsole(textconsole.SimpleConsole):
    '''
    a message console for MAVProxy
    '''
    def __init__(self, title='MAVProxy: console'):
        if platform.system() == 'Darwin':
            forking_enable(False)
        textconsole.SimpleConsole.__init__(self)
        self.title = title
        self.menu_callback = None
        self.parent_pipe_recv, self.child_pipe_send = Pipe(duplex=False)
        self.child_pipe_recv, self.parent_pipe_send = Pipe(duplex=False)
        self.close_event = Event()
        self.close_event.clear()
        self.child = Process(target=self.child_task)
        self.child.start()
        self.child_pipe_send.close()
        self.child_pipe_recv.close()
        t = threading.Thread(target=self.watch_thread)
        t.daemon = True
        t.start()

    def child_task(self):
        '''child process - this holds all the GUI elements'''
        self.parent_pipe_send.close()
        self.parent_pipe_recv.close()

        import wx_processguard
        from wx_loader import wx
        from wxconsole_ui import ConsoleFrame
        app = wx.App(False)
        app.frame = ConsoleFrame(state=self, title=self.title)
        app.frame.SetDoubleBuffered(True)
        app.frame.Show()
        app.MainLoop()

    def watch_thread(self):
        '''watch for menu events from child'''
        from mp_settings import MPSetting
        try:
            while True:
                msg = self.parent_pipe_recv.recv()
                if self.menu_callback is not None:
                    self.menu_callback(msg)
                time.sleep(0.1)
        except EOFError:
            pass

    def write(self, text, fg='black', bg='white'):
        '''write to the console'''
        try:
            self.parent_pipe_send.send(Text(text, fg, bg))
        except Exception:
            pass

    def set_status(self, name, text='', row=0, fg='black', bg='white'):
        '''set a status value'''
        if self.is_alive():
            self.parent_pipe_send.send(Value(name, text, row, fg, bg))

    def set_menu(self, menu, callback):
        if self.is_alive():
            self.parent_pipe_send.send(menu)
            self.menu_callback = callback

    def close(self):
        '''close the console'''
        self.close_event.set()
        if self.is_alive():
            self.child.join(2)

    def is_alive(self):
        '''check if child is still going'''
        return self.child.is_alive()
def memory_usage(proc=-1,
                 interval=.1,
                 timeout=None,
                 timestamps=False,
                 include_children=False,
                 multiprocess=False,
                 max_usage=False,
                 retval=False,
                 stream=None,
                 backend=None):
    """
    Return the memory usage of a process or piece of code

    Parameters
    ----------
    proc : {int, string, tuple, subprocess.Popen}, optional
        The process to monitor. Can be given by an integer/string
        representing a PID, by a Popen object or by a tuple
        representing a Python function. The tuple contains three
        values (f, args, kw) and specifies to run the function
        f(*args, **kw).
        Set to -1 (default) for current process.

    interval : float, optional
        Interval at which measurements are collected.

    timeout : float, optional
        Maximum amount of time (in seconds) to wait before returning.

    max_usage : bool, optional
        Only return the maximum memory usage (default False)

    retval : bool, optional
        For profiling python functions. Save the return value of the profiled
        function. Return value of memory_usage becomes a tuple:
        (mem_usage, retval)

    timestamps : bool, optional
        if True, timestamps of memory usage measurement are collected as well.

    include_children : bool, optional
        if True, sum the memory of all forked processes as well

    multiprocess : bool, optional
        if True, track the memory usage of all forked processes.

    stream : File
        if stream is a File opened with write access, then results are written
        to this file instead of stored in memory and returned at the end of
        the subprocess. Useful for long-running processes.
        Implies timestamps=True.

    Returns
    -------
    mem_usage : list of floating-point values
        memory usage, in MiB. It's length is always < timeout / interval
        if max_usage is given, returns the two elements maximum memory and
        number of measurements effectuated
    ret : return value of the profiled function
        Only returned if retval is set to True
    """
    backend = choose_backend(backend)
    if stream is not None:
        timestamps = True

    if not max_usage:
        ret = []
    else:
        ret = -1

    if timeout is not None:
        max_iter = int(timeout / interval)
    elif isinstance(proc, int):
        # external process and no timeout
        max_iter = 1
    else:
        # for a Python function wait until it finishes
        max_iter = float('inf')

    if callable(proc):
        proc = (proc, (), {})
    if isinstance(proc, (list, tuple)):
        if len(proc) == 1:
            f, args, kw = (proc[0], (), {})
        elif len(proc) == 2:
            f, args, kw = (proc[0], proc[1], {})
        elif len(proc) == 3:
            f, args, kw = (proc[0], proc[1], proc[2])
        else:
            raise ValueError

        while True:
            child_conn, parent_conn = Pipe(
            )  # this will store MemTimer's results
            p = MemTimer(os.getpid(),
                         interval,
                         child_conn,
                         backend,
                         timestamps=timestamps,
                         max_usage=max_usage,
                         include_children=include_children)
            p.start()
            parent_conn.recv()  # wait until we start getting memory

            # When there is an exception in the "proc" - the (spawned) monitoring processes don't get killed.
            # Therefore, the whole process hangs indefinitely. Here, we are ensuring that the process gets killed!
            try:
                returned = f(*args, **kw)
                parent_conn.send(0)  # finish timing
                ret = parent_conn.recv()
                n_measurements = parent_conn.recv()
                if retval:
                    ret = ret, returned
            except Exception:
                if has_psutil:
                    parent = psutil.Process(os.getpid())
                    for child in parent.children(recursive=True):
                        os.kill(child.pid, SIGKILL)
                p.join(0)
                raise

            p.join(5 * interval)
            if n_measurements > 4 or interval < 1e-6:
                break
            interval /= 10.
    elif isinstance(proc, subprocess.Popen):
        # external process, launched from Python
        line_count = 0
        while True:
            if not max_usage:
                mem_usage = _get_memory(proc.pid,
                                        backend,
                                        timestamps=timestamps,
                                        include_children=include_children)

                if stream is not None:
                    stream.write("MEM {0:.6f} {1:.4f}\n".format(*mem_usage))

                    # Write children to the stream file
                    if multiprocess:
                        for idx, chldmem in enumerate(
                                _get_child_memory(proc.pid)):
                            stream.write("CHLD {0} {1:.6f} {2:.4f}\n".format(
                                idx, chldmem, time.time()))
                else:
                    # Create a nested list with the child memory
                    if multiprocess:
                        mem_usage = [mem_usage]
                        for chldmem in _get_child_memory(proc.pid):
                            mem_usage.append(chldmem)

                    # Append the memory usage to the return value
                    ret.append(mem_usage)
            else:
                ret = max(
                    ret,
                    _get_memory(proc.pid,
                                backend,
                                include_children=include_children))
            time.sleep(interval)
            line_count += 1
            # flush every 50 lines. Make 'tail -f' usable on profile file
            if line_count > 50:
                line_count = 0
                if stream is not None:
                    stream.flush()
            if timeout is not None:
                max_iter -= 1
                if max_iter == 0:
                    break
            if proc.poll() is not None:
                break
    else:
        # external process
        if max_iter == -1:
            max_iter = 1
        counter = 0
        while counter < max_iter:
            counter += 1
            if not max_usage:
                mem_usage = _get_memory(proc,
                                        backend,
                                        timestamps=timestamps,
                                        include_children=include_children)
                if stream is not None:
                    stream.write("MEM {0:.6f} {1:.4f}\n".format(*mem_usage))

                    # Write children to the stream file
                    if multiprocess:
                        for idx, chldmem in enumerate(
                                _get_child_memory(proc.pid)):
                            stream.write("CHLD {0} {1:.6f} {2:.4f}\n".format(
                                idx, chldmem, time.time()))
                else:
                    # Create a nested list with the child memory
                    if multiprocess:
                        mem_usage = [mem_usage]
                        for chldmem in _get_child_memory(proc.pid):
                            mem_usage.append(chldmem)

                    # Append the memory usage to the return value
                    ret.append(mem_usage)
            else:
                ret = max([
                    ret,
                    _get_memory(proc,
                                backend,
                                include_children=include_children)
                ])

            time.sleep(interval)
            # Flush every 50 lines.
            if counter % 50 == 0 and stream is not None:
                stream.flush()
    if stream:
        return None
    return ret