Esempio n. 1
0
def model_task(project,
               modeller,
               margs,
               trajectories=None,
               min_trajlength=0,
               resource_requirements=None,
               taskenv=None,
               rp_client=None):

    if not modeller:
        return []
    # model task goes last to ensure (on first one) that the
    # previous round of trajectories is done
    #print("Using these in the model:\n", list(project.trajectories))
    if trajectories is None:
        trajectories = filter(lambda tj: tj.length >= min_trajlength,
                              project.trajectories)

    #print(project, modeller, margs, trajectories, resource_requirements)

    kwargs = margs.copy()
    kwargs.update(resource_requirements)
    #kwargs.update({"est_exec_time": 7})
    mtask = modeller.execute(list(trajectories), **kwargs)
    mtask.setenv('PYEMMA_NJOBS', 16)
    mtask.setenv('OMP_NUM_THREADS', 16)

    ## taskenv = {
    ##            'environment'    : 'admdenv',#environment,
    ##            'activate_prefix': '$TASKCONDAPATH',#activate_prefix,
    ##            'virtualenv'     : None,#virtualenv,
    ##            'task_env'       : None,#task_env,
    ##            'pre'            : None,#pre_cmds,
    ##           }

    logger.info("TASKENV for MODELLER: ".format(taskenv))
    add_task_env(mtask, **taskenv)

    project.queue(mtask)

    logger.debug(formatline("\nModeller Pre-task:\n" + pformat(mtask.pre)))
    logger.debug(formatline("\nModeller Main-task:\n" + pformat(mtask.main)))
    logger.debug(formatline("\nModeller Post-task:\n" + pformat(mtask.post)))

    if mtask and rp_client:
        start_rp_client(rp_client)
    return [mtask]
Esempio n. 2
0
def print_last_model(project):
    try:
        mdat = project.models.last.data
        logger.info("Hopefully model prints below!")
        logger.info("Model created using modeller:".format(
            project.models.last.name))
        logger.info("attempted using n_microstates: {}".format(
            mdat['clustering']['k']))
        logger.info("length of cluster populations row: {}".format(
            len(mdat['msm']['C'][0])))
        logger.info(formatline(pformat(mdat['msm'])))
        logger.info(formatline(mdat['msm']))
        #logger.info(mdat['msm']['P'])
        #logger.info(mdat['msm']['C'])
    except:
        logger.info("tried to print model")
        pass
Esempio n. 3
0
def model_task(project,
               modeller,
               margs,
               trajectories=None,
               resource_requirements=None,
               taskenv=None):

    if not modeller:
        return []
    # model task goes last to ensure (on first one) that the
    # previous round of trajectories is done
    #print("Using these in the model:\n", list(project.trajectories))
    if trajectories is None:
        trajectories = project.trajectories

    #print(project, modeller, margs, trajectories, resource_requirements)

    kwargs = margs.copy()
    kwargs.update(resource_requirements)
    #kwargs.update({"est_exec_time": 7})
    mtask = modeller.execute(list(trajectories), **kwargs)

    ## taskenv = {
    ##            'environment'    : 'admdenv',#environment,
    ##            'activate_prefix': '$TASKCONDAPATH',#activate_prefix,
    ##            'virtualenv'     : None,#virtualenv,
    ##            'task_env'       : None,#task_env,
    ##            'pre'            : None,#pre_cmds,
    ##           }

    print("TASKENV for MODELLER: ", taskenv)
    add_task_env(mtask, **taskenv)

    project.queue(mtask)

    logger.info(formatline("\nModeller Pre-task:\n" + pformat(mtask.pre)))
    logger.info(formatline("\nModeller Main-task:\n" + pformat(mtask.main)))
    logger.info(formatline("\nModeller Post-task:\n" + pformat(mtask.post)))

    return [mtask]
Esempio n. 4
0
def queue_tasks(project,
                tasks,
                rp_client,
                wait=False,
                batchsize=9999999,
                sleeptime=5):
    logger.info("Arguments to task queueing function")
    logger.info("wait={w} batchsize={b} sleeptime={s}".format(w=wait,
                                                              b=batchsize,
                                                              s=sleeptime))
    if tasks and rp_client:
        start_rp_client(rp_client)
    for i in range(len(tasks) / batchsize + 1):
        waiting = False
        if wait:
            waiting = True
            if wait == 'any':
                waitfunc = any
            elif wait == 'all':
                waitfunc = all
            else:
                #print("Wait argument must be 'any' or 'all' if given")
                raise Exception

        _tasks = tasks[i * batchsize:(i + 1) * batchsize]
        if _tasks:
            #print("QUEUEING THESE GUYS: ", _tasks)
            logger.info(
                formatline("TIMER Queueing {0} Tasks {1:.5f}".format(
                    len(_tasks), time.time())))
            project.queue(_tasks)
            #print("QUEUEING")
            time.sleep(sleeptime)

            while waiting:
                #print("WAITING: ", waitfunc, _tasks)
                if waitfunc(
                        map(
                            lambda ta: ta.state in
                            {'running', 'cancelled', 'success'}, _tasks)):
                    #print("WAITING: {} running".format(waitfunc))
                    #print("DONE WAITING")
                    waiting = False
                else:
                    #print("WAITING")
                    #print(reduce(lambda s,ta: s+' '+ta.state, [' ']+list(_tasks)))
                    #print("SLEEPING FOR {} seconds".format(sleeptime))
                    #print(" - have {} tasks queued".format(len(project.tasks)))
                    time.sleep(sleeptime)
Esempio n. 5
0
    def model_extend(modeller, randbreak, mtask=None, c=None):
        #print("c_ext is ", c_ext, "({0})".format(n_ext))
        #print("length of extended is: ", len(extended))

        # FIRST workload including a model this execution
        if c_ext == 0:
            if len(tasks) == 0:
                if not randbreak and not fixedlength:
                    randbreak += randlength(n_run, longest, n_steps)
                    lengtharg = randbreak

                else:
                    # this may already be set if new project
                    # was created in this run of adaptivemd
                    #locals()['randbreak'] = [n_steps]*n_run
                    lengtharg = n_steps

                #trajectories = [project.new_trajectory(engine['pdb_file'], lengtharg, engine) for _ in range(n_run)]
                #trajectories = project.new_ml_trajectory(engine, lengtharg, n_run)
                trajectories = sampling_function(project, engine, lengtharg,
                                                 n_run)

                logger.info(
                    formatline("TIMER Brain fresh tasks define {0:.5f}".format(
                        time.time())))
                logger.info(
                    formatline(
                        "TIMER Brain fresh tasks defined {0:.5f}".format(
                            time.time())))

                if not n_rounds or not c.done:
                    logger.info("ENTERING task queuer")
                    #[tasks.append(t.run(export_path=export_path)) for t in trajectories]
                    [
                        tasks.append(t.run(**resource_requirements))
                        for t in trajectories
                    ]
                    #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                    add_task_env(tasks, **taskenv)

                    logger.info(
                        formatline(
                            "TIMER Brain fresh tasks queue {0:.5f}".format(
                                time.time())))
                    queue_tasks(project,
                                tasks,
                                rp_client,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()
                    logger.info(
                        formatline(
                            "TIMER Brain fresh tasks queued {0:.5f}".format(
                                time.time())))

                # wait for all initial trajs to finish
                waiting = True
                while waiting:
                    # OK condition because we're in first
                    #    extension, as long as its a fresh
                    #    project.
                    logger.info(
                        "len(project.trajectories), n_run: {0} {1}".format(
                            len(project.trajectories), n_run))

                    if notfirsttime or len(
                            project.trajectories) >= n_run - len(
                                filter(
                                    lambda ta: ta.state in
                                    {'fail', 'cancelled'}, project.tasks)):
                        logger.info("adding first/next modeller task")
                        mtask = model_task(
                            project,
                            modeller,
                            margs,
                            taskenv=taskenv,
                            rp_client=rp_client,
                            min_trajlength=min_model_trajlength,
                            resource_requirements=resource_requirements)

                        logger.info(
                            formatline(
                                "\nQueued Modelling Task\nUsing these modeller arguments:\n"
                                + pformat(margs)))

                        tasks.extend(mtask)
                        waiting = False
                    else:
                        time.sleep(3)

            #print(tasks)
            #print("First Extensions' status':\n", [ta.state for ta in tasks])

            return lambda: progress(tasks)
            #return any([ta.is_done() for ta in tasks[:-1]])
            #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
            #return all([ta.is_done() for ta in tasks[:-1]])

        # LAST workload in this execution
        elif c_ext == n_ext:
            if len(tasks) < n_run:
                if mtask:
                    # breaking convention of mtask last
                    # is OK because not looking for mtask
                    # after last round, only task.done
                    if mtask.is_done() and continuing:
                        mtask = model_task(
                            project,
                            modeller,
                            margs,
                            taskenv=taskenv,
                            rp_client=rp_client,
                            min_trajlength=min_model_trajlength,
                            resource_requirements=resource_requirements)

                        tasks.extend(mtask)
                        logger.info(
                            formatline(
                                "\nQueued Modelling Task\nUsing these modeller arguments:\n"
                                + pformat(margs)))

                logger.info(
                    formatline("TIMER Brain last tasks define {0:.5f}".format(
                        time.time())))
                logger.info("Queueing final extensions after modelling done")
                logger.info(
                    formatline(
                        "\nFirst MD Task Lengths: \n".format(randbreak)))
                unrandbreak = [2 * n_steps - rb for rb in randbreak]
                unrandbreak.sort()
                unrandbreak.reverse()
                logger.info(
                    formatline(
                        "\nFinal MD Task Lengths: \n".format(unrandbreak)))

                trajectories = sampling_function(project, engine, unrandbreak,
                                                 n_run)
                #trajectories = project.new_ml_trajectory(engine, unrandbreak, n_run)
                #trajectories = [project.new_trajectory(engine['pdb_file'], urb, engine) for urb in unrandbreak]

                [
                    tasks.append(t.run(**resource_requirements))
                    for t in trajectories
                ]
                #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                add_task_env(tasks, **taskenv)

                logger.info(
                    formatline("TIMER Brain last tasks queue {0:.5f}".format(
                        time.time())))
                if not n_rounds or not c.done:

                    logger.info("Queueing these: ")
                    logger.info(tasks)
                    queue_tasks(project,
                                tasks,
                                rp_client,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()

                logger.info(
                    formatline("TIMER Brain last tasks queued {0:.5f}".format(
                        time.time())))

            return lambda: progress(tasks)
            #return any([ta.is_done() for ta in tasks])
            #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
            #return all([ta.is_done() for ta in tasks])

        else:
            # MODEL TASK MAY NOT BE CREATED
            #  - timing is different
            #  - just running trajectories until
            #    prior model finishes, then starting
            #    round of modelled trajs along
            #    with mtask
            if len(tasks) == 0:
                logger.info("Queueing new round of modelled trajectories")
                logger.info(
                    formatline("TIMER Brain new tasks define {0:.5f}".format(
                        time.time())))

                trajectories = sampling_function(project, engine, n_steps,
                                                 n_run)
                #trajectories = project.new_ml_trajectory(engine, n_steps, n_run)
                #trajectories = [project.new_trajectory(engine['pdb_file'], n_steps, engine) for _ in range(n_run)]

                if not n_rounds or not c.done:
                    [
                        tasks.append(t.run(**resource_requirements))
                        for t in trajectories
                    ]
                    #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                    add_task_env(tasks, **taskenv)
                    logger.info(
                        formatline(
                            "TIMER Brain new tasks queue {0:.5f}".format(
                                time.time())))

                    queue_tasks(project,
                                tasks,
                                rp_client,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()
                    logger.info(
                        formatline(
                            "TIMER Brain new tasks queued {0:.5f}".format(
                                time.time())))

                    if mtask:
                        if mtask.is_done():
                            mtask = model_task(
                                project,
                                modeller,
                                margs,
                                taskenv=taskenv,
                                rp_client=rp_client,
                                min_trajlength=min_model_trajlength,
                                resource_requirements=resource_requirements)

                            tasks.extend(mtask)

                    return lambda: progress(tasks)
                    #return any([ta.is_done() for ta in tasks[:-1]])
                    #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                    #return all([ta.is_done() for ta in tasks[:-1]])

                else:
                    return lambda: progress(tasks)
                    #return any([ta.is_done() for ta in tasks])
                    #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                    #return all([ta.is_done() for ta in tasks])

            else:
                return lambda: progress(tasks)
Esempio n. 6
0
def strategy_function(project,
                      engine,
                      n_run,
                      n_ext,
                      n_steps,
                      round_n,
                      modeller=None,
                      fixedlength=True,
                      longest=5000,
                      continuing=True,
                      minlength=None,
                      randomly=False,
                      n_rounds=0,
                      environment=None,
                      activate_prefix=None,
                      virtualenv=None,
                      cpu_threads=8,
                      gpu_contexts=1,
                      mpi_rank=0,
                      batchsize=999999,
                      batchsleep=5,
                      progression='any',
                      batchwait=False,
                      read_margs=True,
                      sampling_method='explore_macrostates',
                      min_model_trajlength=0,
                      sfkwargs=dict(),
                      rp_client=None,
                      startontraj=0,
                      **kwargs):

    sampling_function = sampling_interface.get_one(sampling_method, **sfkwargs)

    def printem(tasks, progressfunc):
        tasksstring = ''
        tasksstring += str(progressfunc([ta.is_done() for ta in tasks]))
        for ta in tasks:
            tasksstring += ' done' if ta.is_done() else ' notdone'

        return progressfunc([ta.is_done() for ta in tasks])

    if progression == 'all':
        # Printout on each check
        #progress = lambda tasks: printem(tasks, all)
        progress = lambda tasks: all([ta.is_done() for ta in tasks])
    else:
        #progress = lambda tasks: printem(tasks, any)
        progress = lambda tasks: any([ta.is_done() for ta in tasks])

    logger.info(formatline("TIMER Brain enter {0:.5f}".format(time.time())))

    taskenv = dict()
    resource_requirements = dict()
    if rp_client:
        logger.info("Building environment for RP")
        task_env = {
            'OPENMM_CPU_THREADS': cpu_threads,
        }

        #gpu_load = 'module load cudatoolkit/7.5.18-1.0502.10743.2.1'
        gpu_load = 'module load cudatoolkit/7.5.18-1.0502.10743.2.1'
        gpu_find = 'export OPENMM_CUDA_COMPILER=`which nvcc`'
        gpu_cmds = [gpu_load, gpu_find, 'echo $OPENMM_CUDA_COMPILER']
        pre_cmds = gpu_cmds + [
            'module load python', 'which python',
            'echo \"   >>>  TIMER Task start \"`date +%s.%3N`'
        ]
        post_cmd = [
            'module unload python',
            'echo \"   >>>  TIMER Task stop \"`date +%s.%3N`'
        ]

        taskenv = {
            'environment': environment,
            'activate_prefix': activate_prefix,
            'virtualenv': virtualenv,
            'task_env': task_env,
            'pre': pre_cmds,
            'post': post_cmd,
        }

        resource_requirements = {
            'resource_name': project._current_configuration.resource_name,
            'cpu_threads': cpu_threads,
            'gpu_contexts': gpu_contexts,
            'mpi_rank': mpi_rank
        }

    logger.info("Got {0} for `cpu_threads`".format(cpu_threads))

    c = counter(n_rounds)
    tasks = list()

    if n_rounds:
        assert (n_rounds > 0)
        logger.info("Going to do n_rounds:  {}".format(c.n))

    # PREPARATION - Preprocess task setups
    logger.info("Using MD Engine: {0} {1}".format(
        engine, engine.name))  #, project.generators[engine.name].__dict__)
    logger.info("Using fixed length? {}".format(fixedlength))

    lengthvariance = 0.2

    if fixedlength:
        randbreak = [n_steps] * n_run

    else:
        randbreak = randlength(n_run, longest, n_steps, lengthvariance)

    if minlength is None:
        minlength = n_steps

    logger.info(
        formatline("\nProject models\n - Number: {n_model}".format(
            n_model=len(project.models))))

    logger.info(
        formatline("\nProject trajectories\n - Number: {n_traj}".format(
            n_traj=len(project.trajectories))))

    logger.debug(
        formatline("\nProject trajectories\n - Lengths:\n{lengths}".format(
            lengths=[t.length for t in project.trajectories])))

    # ROUND 1 - No pre-existing data
    #         - will skip if revisiting project
    if len(project.trajectories) == 0:

        notfirsttime = False

        logger.info(
            formatline("TIMER Brain first tasks define {0:.5f}".format(
                time.time())))
        [
            tasks.append(
                project.new_trajectory(engine['pdb_file'], rb,
                                       engine).run(**resource_requirements))
            for rb in randbreak
        ]

        #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
        add_task_env(tasks, **taskenv)

        logger.info(
            formatline("TIMER Brain first tasks queue {0:.5f}".format(
                time.time())))
        if not n_rounds or not c.done:
            queue_tasks(project,
                        tasks,
                        rp_client,
                        sleeptime=batchsleep,
                        batchsize=batchsize,
                        wait=batchwait)
            c.increment()

        #print("Number of tasks: ", len(tasks))
        logger.info(
            formatline("TIMER Brain first tasks queued {0:.5f}".format(
                time.time())))
        logger.info("Queued First Tasks in new project")
        #logger.info(formatline("\nTrajectory lengths were: \n{0}".format(randbreak)))

        yield lambda: progress(tasks)
        #yield lambda: any([ta.is_done() for ta in tasks])
        #yield lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
        #yield lambda: all([ta.is_done() for ta in tasks])

        logger.info("First Tasks are done")
        logger.info(
            formatline("TIMER Brain first tasks done {0:.5f}".format(
                time.time())))

    else:
        notfirsttime = True

    logger.info("Starting Trajectory Extensions")
    logger.info(
        formatline("TIMER Brain main loop enter {0:.5f}".format(time.time())))

    def model_extend(modeller, randbreak, mtask=None, c=None):
        #print("c_ext is ", c_ext, "({0})".format(n_ext))
        #print("length of extended is: ", len(extended))

        # FIRST workload including a model this execution
        if c_ext == 0:
            if len(tasks) == 0:
                if not randbreak and not fixedlength:
                    randbreak += randlength(n_run, longest, n_steps)
                    lengtharg = randbreak

                else:
                    # this may already be set if new project
                    # was created in this run of adaptivemd
                    #locals()['randbreak'] = [n_steps]*n_run
                    lengtharg = n_steps

                #trajectories = [project.new_trajectory(engine['pdb_file'], lengtharg, engine) for _ in range(n_run)]
                #trajectories = project.new_ml_trajectory(engine, lengtharg, n_run)
                trajectories = sampling_function(project, engine, lengtharg,
                                                 n_run)

                logger.info(
                    formatline("TIMER Brain fresh tasks define {0:.5f}".format(
                        time.time())))
                logger.info(
                    formatline(
                        "TIMER Brain fresh tasks defined {0:.5f}".format(
                            time.time())))

                if not n_rounds or not c.done:
                    logger.info("ENTERING task queuer")
                    #[tasks.append(t.run(export_path=export_path)) for t in trajectories]
                    [
                        tasks.append(t.run(**resource_requirements))
                        for t in trajectories
                    ]
                    #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                    add_task_env(tasks, **taskenv)

                    logger.info(
                        formatline(
                            "TIMER Brain fresh tasks queue {0:.5f}".format(
                                time.time())))
                    queue_tasks(project,
                                tasks,
                                rp_client,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()
                    logger.info(
                        formatline(
                            "TIMER Brain fresh tasks queued {0:.5f}".format(
                                time.time())))

                # wait for all initial trajs to finish
                waiting = True
                while waiting:
                    # OK condition because we're in first
                    #    extension, as long as its a fresh
                    #    project.
                    logger.info(
                        "len(project.trajectories), n_run: {0} {1}".format(
                            len(project.trajectories), n_run))

                    if notfirsttime or len(
                            project.trajectories) >= n_run - len(
                                filter(
                                    lambda ta: ta.state in
                                    {'fail', 'cancelled'}, project.tasks)):
                        logger.info("adding first/next modeller task")
                        mtask = model_task(
                            project,
                            modeller,
                            margs,
                            taskenv=taskenv,
                            rp_client=rp_client,
                            min_trajlength=min_model_trajlength,
                            resource_requirements=resource_requirements)

                        logger.info(
                            formatline(
                                "\nQueued Modelling Task\nUsing these modeller arguments:\n"
                                + pformat(margs)))

                        tasks.extend(mtask)
                        waiting = False
                    else:
                        time.sleep(3)

            #print(tasks)
            #print("First Extensions' status':\n", [ta.state for ta in tasks])

            return lambda: progress(tasks)
            #return any([ta.is_done() for ta in tasks[:-1]])
            #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
            #return all([ta.is_done() for ta in tasks[:-1]])

        # LAST workload in this execution
        elif c_ext == n_ext:
            if len(tasks) < n_run:
                if mtask:
                    # breaking convention of mtask last
                    # is OK because not looking for mtask
                    # after last round, only task.done
                    if mtask.is_done() and continuing:
                        mtask = model_task(
                            project,
                            modeller,
                            margs,
                            taskenv=taskenv,
                            rp_client=rp_client,
                            min_trajlength=min_model_trajlength,
                            resource_requirements=resource_requirements)

                        tasks.extend(mtask)
                        logger.info(
                            formatline(
                                "\nQueued Modelling Task\nUsing these modeller arguments:\n"
                                + pformat(margs)))

                logger.info(
                    formatline("TIMER Brain last tasks define {0:.5f}".format(
                        time.time())))
                logger.info("Queueing final extensions after modelling done")
                logger.info(
                    formatline(
                        "\nFirst MD Task Lengths: \n".format(randbreak)))
                unrandbreak = [2 * n_steps - rb for rb in randbreak]
                unrandbreak.sort()
                unrandbreak.reverse()
                logger.info(
                    formatline(
                        "\nFinal MD Task Lengths: \n".format(unrandbreak)))

                trajectories = sampling_function(project, engine, unrandbreak,
                                                 n_run)
                #trajectories = project.new_ml_trajectory(engine, unrandbreak, n_run)
                #trajectories = [project.new_trajectory(engine['pdb_file'], urb, engine) for urb in unrandbreak]

                [
                    tasks.append(t.run(**resource_requirements))
                    for t in trajectories
                ]
                #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                add_task_env(tasks, **taskenv)

                logger.info(
                    formatline("TIMER Brain last tasks queue {0:.5f}".format(
                        time.time())))
                if not n_rounds or not c.done:

                    logger.info("Queueing these: ")
                    logger.info(tasks)
                    queue_tasks(project,
                                tasks,
                                rp_client,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()

                logger.info(
                    formatline("TIMER Brain last tasks queued {0:.5f}".format(
                        time.time())))

            return lambda: progress(tasks)
            #return any([ta.is_done() for ta in tasks])
            #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
            #return all([ta.is_done() for ta in tasks])

        else:
            # MODEL TASK MAY NOT BE CREATED
            #  - timing is different
            #  - just running trajectories until
            #    prior model finishes, then starting
            #    round of modelled trajs along
            #    with mtask
            if len(tasks) == 0:
                logger.info("Queueing new round of modelled trajectories")
                logger.info(
                    formatline("TIMER Brain new tasks define {0:.5f}".format(
                        time.time())))

                trajectories = sampling_function(project, engine, n_steps,
                                                 n_run)
                #trajectories = project.new_ml_trajectory(engine, n_steps, n_run)
                #trajectories = [project.new_trajectory(engine['pdb_file'], n_steps, engine) for _ in range(n_run)]

                if not n_rounds or not c.done:
                    [
                        tasks.append(t.run(**resource_requirements))
                        for t in trajectories
                    ]
                    #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                    add_task_env(tasks, **taskenv)
                    logger.info(
                        formatline(
                            "TIMER Brain new tasks queue {0:.5f}".format(
                                time.time())))

                    queue_tasks(project,
                                tasks,
                                rp_client,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()
                    logger.info(
                        formatline(
                            "TIMER Brain new tasks queued {0:.5f}".format(
                                time.time())))

                    if mtask:
                        if mtask.is_done():
                            mtask = model_task(
                                project,
                                modeller,
                                margs,
                                taskenv=taskenv,
                                rp_client=rp_client,
                                min_trajlength=min_model_trajlength,
                                resource_requirements=resource_requirements)

                            tasks.extend(mtask)

                    return lambda: progress(tasks)
                    #return any([ta.is_done() for ta in tasks[:-1]])
                    #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                    #return all([ta.is_done() for ta in tasks[:-1]])

                else:
                    return lambda: progress(tasks)
                    #return any([ta.is_done() for ta in tasks])
                    #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                    #return all([ta.is_done() for ta in tasks])

            else:
                return lambda: progress(tasks)
                #return any([ta.is_done() for ta in tasks])
                #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                #return all([ta.is_done() for ta in tasks])

    c_ext = 0
    mtask = None
    frac_ext_final_margs = 0.75

    if not read_margs:
        start_margs = dict(tica_stride=2,
                           tica_lag=20,
                           tica_dim=2,
                           clust_stride=1,
                           msm_states=50,
                           msm_lag=20)

        final_margs = dict(tica_stride=2,
                           tica_lag=20,
                           tica_dim=2,
                           clust_stride=1,
                           msm_states=50,
                           msm_lag=20)

    # def update_margs():
    #     margs=dict()
    #     progress = c_ext/float(n_ext)

    #     if c_ext == 1:
    #         progress_margs = 0
    #     elif progress < frac_ext_final_margs:
    #         progress_margs = progress/frac_ext_final_margs
    #     else:
    #         progress_margs = 1

    #     for key,baseval in start_margs.items():
    #         if key in final_margs:
    #             finalval = final_margs[key]
    #             val = int( progress_margs*(finalval-baseval) + baseval )
    #         else:
    #             val = baseval

    #         margs.update({key: val})

    #     return margs

    else:
        # FIXME margs via main config
        _margs = parse_cfg_file('margs.cfg')
        logger.info(pformat(_margs))

        # def update_margs():
        #     margs    = dict()
        #     # How many rounds are done?
        #     for k in _margs:
        #         v = _margs[k]
        #         if isinstance(v,list): #TODO consider using afterntraj in calculation
        #             progress = math.ceil(len(project.trajectories)/float(n_run))
        #             for u in v:
        #                 # u is a 2-tuple
        #                 #  already prepped as ints
        #                 if progress >= u[1]:
        #                     margs[k] = u[0]
        #                 else:
        #                     if k not in margs:
        #                         margs[k] = u[0]
        #                     break
        #         else:
        #             # FIXME not good here, braoder solution to typing: typetemplate
        #             try:
        #                 margs[k] = int(v)
        #             except TypeError:
        #                 margs[k] = v
        #     return margs

        def update_margs(_margs, round_n=None):
            margs = dict()
            if round_n:
                logger.info("Choosing margs for round {}".format(round_n))
                _margs = _margs[str(
                    max(
                        filter(lambda i: i <= round_n,
                               map(lambda i: int(i), _margs))))]
                logger.info(pformat(_margs))
            # How many rounds are done?
            for k, v in _margs.items():
                if isinstance(
                        v,
                        list):  #TODO consider using afterntraj in calculation
                    progress = math.ceil(
                        len(project.trajectories) / float(n_run))
                    for u in v:
                        # u is a 2-tuple
                        #  already prepped as ints
                        if progress >= u[1]:
                            margs[k] = u[0]
                        else:
                            if k not in margs:
                                margs[k] = u[0]
                            break
                else:
                    # FIXME not good here, braoder solution to typing: typetemplate
                    try:
                        margs[k] = int(v)
                    except ValueError, TypeError:
                        margs[k] = v

            return margs
Esempio n. 7
0
                    #logger.info(formatline("TIMER Brain ext tasks done {0:.5f}".format(time.time())))
                    done = True

            else:
                if not lastcheck:
                    lastcheck = True

                time.sleep(15)

        logger.info("----------- Extension #{0}".format(c_ext))

        # when c_ext == n_ext, we just wanted
        # to use check_trajectory_minlength above
        if c_ext < n_ext and not c.done:
            logger.info(
                formatline("TIMER Brain main loop enter {0:.5f}".format(
                    time.time())))
            tasks = list()
            if not modeller:
                c_ext += 1
                logger.info("Extending project without modeller")
                yield lambda: model_extend(modeller, randbreak, c=c)
                logger.info(
                    formatline(
                        "TIMER Brain main no modeller done {0:.5f}".format(
                            time.time())))
            else:
                margs = update_margs(_margs, round_n)

                logger.info("Extending project with modeller")
                logger.info("margs for this round will be: {}".format(
                    pformat(margs)))
Esempio n. 8
0
def strategy_function(project,
                      engine,
                      n_run,
                      n_ext,
                      n_steps,
                      modeller=None,
                      fixedlength=True,
                      longest=5000,
                      continuing=True,
                      minlength=None,
                      randomly=False,
                      n_rounds=0,
                      environment=None,
                      activate_prefix=None,
                      virtualenv=None,
                      cpu_threads=8,
                      gpu_contexts=1,
                      mpi_rank=0,
                      batchsize=999999,
                      batchsleep=5,
                      progression='any',
                      batchwait=False,
                      read_margs=True,
                      sampling_method='explore_macrostates',
                      sfkwargs=dict(),
                      **kwargs):

    sampling_function = sampling_interface.get_one(sampling_method, **sfkwargs)

    #virtualenv = ["$ADMDRP_ENV_ACTIVATE","deactivate"]
    #condaenv   = ["$TASKCONDAPATH admdenv","source $TASKCONDAPATH/deactivate"]

    def printem(tasks, progressfunc):
        tasksstring = ''
        tasksstring += str(progressfunc([ta.is_done() for ta in tasks]))
        for ta in tasks:
            tasksstring += ' done' if ta.is_done() else ' notdone'

        return progressfunc([ta.is_done() for ta in tasks])

    if progression == 'all':
        # Printout on each check
        #progress = lambda tasks: printem(tasks, all)
        progress = lambda tasks: all([ta.is_done() for ta in tasks])
    else:
        #progress = lambda tasks: printem(tasks, any)
        progress = lambda tasks: any([ta.is_done() for ta in tasks])

    logger.info(formatline("TIMER Brain enter {0:.5f}".format(time.time())))

    task_env = {
        'OPENMM_CPU_THREADS': cpu_threads,
        'OPENMM_CUDA_COMPILER': "`which nvcc`"
    }

    #gpu_load = 'module load cudatoolkit/7.5.18-1.0502.10743.2.1'
    gpu_load = 'module load cudatoolkit'
    gpu_find = 'export OPENMM_CUDA_COMPILER=`which nvcc`'
    gpu_cmds = [gpu_load, gpu_find, 'echo $OPENMM_CUDA_COMPILER']
    pre_cmds = gpu_cmds + ['module load python']
    #pre_cmds = gpu_cmds + ['module unload python', 'module unload python_anaconda']

    taskenv = {
        'environment': environment,
        'activate_prefix': activate_prefix,
        'virtualenv': virtualenv,
        'task_env': task_env,
        'pre': pre_cmds
    }

    logger.info("Got {0} for `cpu_threads`".format(cpu_threads))

    resource_name = project._current_configuration.resource_name

    resource_requirements = {
        'resource_name': resource_name,
        'cpu_threads': cpu_threads,
        'gpu_contexts': gpu_contexts,
        'mpi_rank': mpi_rank
    }

    c = counter(n_rounds)
    tasks = list()

    if n_rounds:
        assert (n_rounds > 0)
        logger.info("Going to do n_rounds:  {}".format(c.n))

    # PREPARATION - Preprocess task setups
    logger.info("Using MD Engine: {0} {1}".format(
        engine, engine.name))  #, project.generators[engine.name].__dict__)
    logger.info("Using fixed length? {}".format(fixedlength))

    lengthvariance = 0.2

    if fixedlength:
        randbreak = [n_steps] * n_run

    else:
        randbreak = randlength(n_run, longest, n_steps, lengthvariance)

    if minlength is None:
        minlength = n_steps

    logger.info(
        formatline("\nProject models\n - Number: {n_model}".format(
            n_model=len(project.models))))

    logger.info(
        formatline(
            "\nProject trajectories\n - Number: {n_traj}\n - Lengths:\n{lengths}"
            .format(n_traj=len(project.trajectories),
                    lengths=[t.length for t in project.trajectories])))

    # ROUND 1 - No pre-existing data
    #         - will skip if revisiting project
    if len(project.trajectories) == 0:

        notfirsttime = False

        logger.info(
            formatline("TIMER Brain first tasks define {0:.5f}".format(
                time.time())))
        [
            tasks.append(
                project.new_trajectory(engine['pdb_file'], rb,
                                       engine).run(**resource_requirements))
            for rb in randbreak
        ]

        #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
        add_task_env(tasks, **taskenv)

        logger.info(
            formatline("TIMER Brain first tasks queue {0:.5f}".format(
                time.time())))
        if not n_rounds or not c.done:
            queue_tasks(project,
                        tasks,
                        sleeptime=batchsleep,
                        batchsize=batchsize,
                        wait=batchwait)
            c.increment()

        #print("Number of tasks: ", len(tasks))
        logger.info(
            formatline("TIMER Brain first tasks queued {0:.5f}".format(
                time.time())))
        logger.info("Queued First Tasks in new project")
        #logger.info(formatline("\nTrajectory lengths were: \n{0}".format(randbreak)))

        yield lambda: progress(tasks)
        #yield lambda: any([ta.is_done() for ta in tasks])
        #yield lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
        #yield lambda: all([ta.is_done() for ta in tasks])

        logger.info("First Tasks are done")
        logger.info(
            formatline("TIMER Brain first tasks done {0:.5f}".format(
                time.time())))

    else:
        notfirsttime = True

    logger.info("Starting Trajectory Extensions")
    logger.info(
        formatline("TIMER Brain main loop enter {0:.5f}".format(time.time())))

    def model_extend(modeller, randbreak, mtask=None, c=None):
        #print("c_ext is ", c_ext, "({0})".format(n_ext))
        #print("length of extended is: ", len(extended))

        # FIRST workload including a model this execution
        if c_ext == 0:
            if len(tasks) == 0:
                if not randbreak and not fixedlength:
                    randbreak += randlength(n_run, longest, n_steps)
                    lengtharg = randbreak

                else:
                    # this may already be set if new project
                    # was created in this run of adaptivemd
                    #locals()['randbreak'] = [n_steps]*n_run
                    lengtharg = n_steps

                #trajectories = [project.new_trajectory(engine['pdb_file'], lengtharg, engine) for _ in range(n_run)]
                #trajectories = project.new_ml_trajectory(engine, lengtharg, n_run)
                trajectories = sampling_function(project, engine, lengtharg,
                                                 n_run)

                logger.info(
                    formatline("TIMER Brain fresh tasks define {0:.5f}".format(
                        time.time())))
                logger.info(
                    formatline(
                        "TIMER Brain fresh tasks defined {0:.5f}".format(
                            time.time())))

                if not n_rounds or not c.done:
                    logger.info("ENTERING task queuer")
                    #[tasks.append(t.run(export_path=export_path)) for t in trajectories]
                    [
                        tasks.append(t.run(**resource_requirements))
                        for t in trajectories
                    ]
                    #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                    add_task_env(tasks, **taskenv)

                    logger.info(
                        formatline(
                            "TIMER Brain fresh tasks queue {0:.5f}".format(
                                time.time())))
                    queue_tasks(project,
                                tasks,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()
                    logger.info(
                        formatline(
                            "TIMER Brain fresh tasks queued {0:.5f}".format(
                                time.time())))

                # wait for all initial trajs to finish
                waiting = True
                while waiting:
                    # OK condition because we're in first
                    #    extension, as long as its a fresh
                    #    project.
                    logger.info(
                        "len(project.trajectories), n_run: {0} {1}".format(
                            len(project.trajectories), n_run))

                    if notfirsttime or len(
                            project.trajectories) >= n_run - len(
                                filter(
                                    lambda ta: ta.state in
                                    {'fail', 'cancelled'}, project.tasks)):
                        logger.info("adding first/next modeller task")
                        mtask = model_task(
                            project,
                            modeller,
                            margs,
                            taskenv=taskenv,
                            resource_requirements=resource_requirements)

                        logger.info(
                            formatline(
                                "\nQueued Modelling Task\nUsing these modeller arguments:\n"
                                + pformat(margs)))

                        tasks.extend(mtask)
                        waiting = False
                    else:
                        time.sleep(3)

            #print(tasks)
            #print("First Extensions' status':\n", [ta.state for ta in tasks])

            return lambda: progress(tasks)
            #return any([ta.is_done() for ta in tasks[:-1]])
            #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
            #return all([ta.is_done() for ta in tasks[:-1]])

        # LAST workload in this execution
        elif c_ext == n_ext:
            if len(tasks) < n_run:
                if mtask:
                    # breaking convention of mtask last
                    # is OK because not looking for mtask
                    # after last round, only task.done
                    if mtask.is_done() and continuing:
                        mtask = model_task(
                            project,
                            modeller,
                            margs,
                            taskenv=taskenv,
                            resource_requirements=resource_requirements)

                        tasks.extend(mtask)
                        logger.info(
                            formatline(
                                "\nQueued Modelling Task\nUsing these modeller arguments:\n"
                                + pformat(margs)))

                logger.info(
                    formatline("TIMER Brain last tasks define {0:.5f}".format(
                        time.time())))
                logger.info("Queueing final extensions after modelling done")
                logger.info(
                    formatline(
                        "\nFirst MD Task Lengths: \n".format(randbreak)))
                unrandbreak = [2 * n_steps - rb for rb in randbreak]
                unrandbreak.sort()
                unrandbreak.reverse()
                logger.info(
                    formatline(
                        "\nFinal MD Task Lengths: \n".format(unrandbreak)))

                trajectories = sampling_function(project, engine, unrandbreak,
                                                 n_run)
                #trajectories = project.new_ml_trajectory(engine, unrandbreak, n_run)
                #trajectories = [project.new_trajectory(engine['pdb_file'], urb, engine) for urb in unrandbreak]

                [
                    tasks.append(t.run(**resource_requirements))
                    for t in trajectories
                ]
                #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                add_task_env(tasks, **taskenv)

                logger.info(
                    formatline("TIMER Brain last tasks queue {0:.5f}".format(
                        time.time())))
                if not n_rounds or not c.done:

                    print("Queueing these: ")
                    print(tasks)
                    queue_tasks(project,
                                tasks,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()

                logger.info(
                    formatline("TIMER Brain last tasks queued {0:.5f}".format(
                        time.time())))

            return lambda: progress(tasks)
            #return any([ta.is_done() for ta in tasks])
            #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
            #return all([ta.is_done() for ta in tasks])

        else:
            # MODEL TASK MAY NOT BE CREATED
            #  - timing is different
            #  - just running trajectories until
            #    prior model finishes, then starting
            #    round of modelled trajs along
            #    with mtask
            if len(tasks) == 0:
                logger.info("Queueing new round of modelled trajectories")
                logger.info(
                    formatline("TIMER Brain new tasks define {0:.5f}".format(
                        time.time())))

                trajectories = sampling_function(project, engine, n_steps,
                                                 n_run)
                #trajectories = project.new_ml_trajectory(engine, n_steps, n_run)
                #trajectories = [project.new_trajectory(engine['pdb_file'], n_steps, engine) for _ in range(n_run)]

                if not n_rounds or not c.done:
                    [
                        tasks.append(t.run(**resource_requirements))
                        for t in trajectories
                    ]
                    #add_task_env(tasks, environment, activate_prefix, virtualenv, task_env, pre=pre_cmds)
                    add_task_env(tasks, **taskenv)
                    logger.info(
                        formatline(
                            "TIMER Brain new tasks queue {0:.5f}".format(
                                time.time())))

                    queue_tasks(project,
                                tasks,
                                sleeptime=batchsleep,
                                batchsize=batchsize,
                                wait=batchwait)

                    c.increment()
                    logger.info(
                        formatline(
                            "TIMER Brain new tasks queued {0:.5f}".format(
                                time.time())))

                    if mtask:
                        if mtask.is_done():
                            mtask = model_task(
                                project,
                                modeller,
                                margs,
                                taskenv=taskenv,
                                resource_requirements=resource_requirements)

                            tasks.extend(mtask)

                    return lambda: progress(tasks)
                    #return any([ta.is_done() for ta in tasks[:-1]])
                    #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                    #return all([ta.is_done() for ta in tasks[:-1]])

                else:
                    return lambda: progress(tasks)
                    #return any([ta.is_done() for ta in tasks])
                    #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                    #return all([ta.is_done() for ta in tasks])

            else:
                return lambda: progress(tasks)
                #return any([ta.is_done() for ta in tasks])
                #return lambda: len(filter(lambda ta: ta.is_done(), tasks)) > len(tasks) / 2
                #return all([ta.is_done() for ta in tasks])

    c_ext = 0
    mtask = None
    frac_ext_final_margs = 0.75

    if not read_margs:
        start_margs = dict(tica_stride=2,
                           tica_lag=20,
                           tica_dim=2,
                           clust_stride=1,
                           msm_states=50,
                           msm_lag=20)

        final_margs = dict(tica_stride=2,
                           tica_lag=20,
                           tica_dim=2,
                           clust_stride=1,
                           msm_states=50,
                           msm_lag=20)

        def update_margs():
            margs = dict()
            progress = c_ext / float(n_ext)

            if c_ext == 1:
                progress_margs = 0
            elif progress < frac_ext_final_margs:
                progress_margs = progress / frac_ext_final_margs
            else:
                progress_margs = 1

            for key, baseval in start_margs.items():
                if key in final_margs:
                    finalval = final_margs[key]
                    val = int(progress_margs * (finalval - baseval) + baseval)
                else:
                    val = baseval

                margs.update({key: val})

            return margs

    else:
        _margs = parse_cfg_file('margs.cfg')

        def update_margs():
            margs = dict()
            # How many rounds are done?

            for k, v in _margs[project.name].items():
                if isinstance(v, list):
                    progress = math.ceil(
                        len(project.trajectories) / float(n_run))
                    for u in v:
                        # u is a 2-tuple
                        #  already prepped as ints
                        if progress >= u[1]:
                            margs[k] = u[0]
                        else:
                            if k not in margs:
                                margs[k] = u[0]
                            break
                else:
                    # FIXME not good here, braoder solution to typing: typetemplate
                    try:
                        margs[k] = int(v)
                    except ValueError:
                        margs[k] = v

            return margs

    # this will be used to update the models
    # into database after `mtask` completion
    scd = Scheduler(project.resources.one)
    scd.enter(project)

    mtime = 0
    mtimes = list()
    # Start of CONTROL LOOP
    # when on final c_ext ( == n_ext), will
    # grow trajs to minlength before
    # strategy terminates
    while c_ext <= n_ext and (not n_rounds or not c.done):

        logger.info("Checking Extension Lengths")

        done = False
        lastcheck = True
        priorext = 0
        # TODO fix, this isn't a consistent name "trajectories"
        trajectories = set()
        while not done and (not n_rounds or not c.done):

            #print("looking for too-short trajectories")
            if c.done:
                xtasks = list()
            else:
                #logger.info(formatline("TIMER Brain ext tasks define {0:.5f}".format(time.time())))
                xtasks = check_trajectory_minlength(
                    project,
                    minlength,
                    n_steps,
                    n_run,
                    resource_requirements=resource_requirements,
                    task_env=taskenv)
                # environment=environment,
                # activate_prefix=activate_prefix, virtualenv=virtualenv,
                # task_env=task_env, resource_requirements=resource_requirements)

            tnames = set()
            if len(trajectories) > 0:
                [tnames.add(_) for _ in set(zip(*trajectories)[0])]

            #if xtasks:
            #    logger.info(formatline("TIMER Brain ext tasks queue {0:.5f}".format(time.time())))
            for xta in xtasks:
                tname = xta.trajectory.basename

                if tname not in tnames:
                    tnames.add(tname)
                    trajectories.add((tname, xta))
                    project.queue(xta)

            #if xtasks:
            #    logger.info(formatline("TIMER Brain ext tasks queued {0:.5f}".format(time.time())))
            removals = list()
            for tname, xta in trajectories:
                if xta.state in {"fail", "halted", "success", "cancelled"}:
                    removals.append((tname, xta))

            for removal in removals:
                trajectories.remove(removal)

            if len(trajectories) == n_run and priorext < n_run:
                logger.info("Have full width of extensions")
                c.increment()

            # setting this to look at next round
            priorext = len(trajectories)

            if len(trajectories) == 0:
                if lastcheck:
                    logger.info("Extensions last check")
                    lastcheck = False
                    time.sleep(15)

                else:
                    logger.info("Extensions are done")
                    #logger.info(formatline("TIMER Brain ext tasks done {0:.5f}".format(time.time())))
                    done = True

            else:
                if not lastcheck:
                    lastcheck = True

                time.sleep(15)

        logger.info("----------- Extension #{0}".format(c_ext))

        # when c_ext == n_ext, we just wanted
        # to use check_trajectory_minlength above
        if c_ext < n_ext and not c.done:
            logger.info(
                formatline("TIMER Brain main loop enter {0:.5f}".format(
                    time.time())))
            tasks = list()
            if not modeller:
                c_ext += 1
                logger.info("Extending project without modeller")
                yield lambda: model_extend(modeller, randbreak, c=c)
                logger.info(
                    formatline(
                        "TIMER Brain main no modeller done {0:.5f}".format(
                            time.time())))
            else:
                margs = update_margs()

                logger.info("Extending project with modeller")
                logger.info("margs for this round will be: {}".format(
                    pformat(margs)))

                if mtask is None:

                    mtime -= time.time()
                    yield lambda: model_extend(modeller, randbreak, c=c)

                    logger.info(
                        formatline(
                            "TIMER Brain main loop1 done {0:.5f}".format(
                                time.time())))
                    logger.info("Set a current modelling task")
                    mtask = tasks[-1]
                    logger.info("First model task is: {}".format(mtask))

                # TODO don't assume mtask not None means it
                #      has is_done method. outer loop needs
                #      upgrade
                elif mtask.is_done():

                    mtime += time.time()
                    mtimes.append(mtime)
                    mtime = -time.time()
                    logger.info("Current modelling task is done")
                    logger.info("It took {0} seconds".format(mtimes[-1]))
                    c_ext += 1

                    yield lambda: model_extend(modeller, randbreak, mtask, c=c)
                    logger.info(
                        formatline(
                            "TIMER Brain main loop2 done {0:.5f}".format(
                                time.time())))

                    pythontask_callback(mtask, scd)
                    #mpath = os.path.expandvars(mtask.__dict__['post'][1].target.url.replace('project:///','$ADMDRP_DATA/projects/{}/'.format(project.name)))
                    #mtask._cb_success(scd, mpath)
                    logger.info(
                        "Added another model to project, now have: {}".format(
                            len(project.models)))

                    print_last_model(project)
                    mtask = tasks[-1]
                    logger.info("Set a new current modelling task")

                elif not mtask.is_done():
                    logger.info(
                        "Continuing trajectory tasks, waiting on model")
                    yield lambda: model_extend(modeller, randbreak, mtask, c=c)
                    logger.info(
                        formatline(
                            "TIMER Brain main loop3 done {0:.5f}".format(
                                time.time())))

                else:
                    logger.info("Not sure how we got here")
                    pass

        # End of CONTROL LOOP
        # need to increment c_ext to exit the loop
        else:
            c_ext += 1

    # we should not arrive here until the final round
    # of extensions are queued and at least one of them
    # is complete.
    def all_done(mtask):
        '''
        Need to make sure all tasks are in a final state, ie
        either cancelled or success.
        '''

        #print("Checking if all done")
        idle_time = 20

        if mtask:
            # First can check the mtask
            # - if it's not done, then we're not all_done anyway
            project.tasks._set.load(mtask.__uuid__, force_load=True)
            #print("MTASK IS::::::::", mtask, mtask.state)
            if mtask:
                _mtask = get_task_dbentry(project, mtask)

            #logger.info("mtask is {0} {1} {2}".format(mtask, mtask.state, mtask.is_done()))
            #logger.info("MTASK OUTPUT STORED::::: {}".format(mtask.output_stored))
            #logger.info(formatline("_MTASK OUTPUT STORED:::::\n"+pformat(_mtask['_dict'])))
            if mtask.is_done():
                if not _mtask['_dict']['output_stored']:
                    #print("ADDING FINAL MODEL TO PROJECT DATABASE")
                    logger.info("Adding final model to project database")
                    logger.info("Had {} models".format(len(project.models)))
                    #pprint(mtask.__dict__)
                    #pprint(_mtask)

                    pythontask_callback(mtask, scd)

                    logger.info("MTASK OUTPUT STORED::::: {}".format(
                        mtask.output_stored))

                    #print("NOW HAVE: ", len(project.models))
                    #pprint(mtask.__dict__)
                    #pprint(_mtask)
                    #mtask = None

            else:
                logger.info("Waiting on mtask first: {0}.state ~ {1}".format(
                    mtask, mtask.state))
                time.sleep(idle_time)
                return False

        n_waiting = len(project.tasks) - len(
            filter(
                # TODO establish / utilize FINAL_STATES
                lambda ta: ta.state in {'dummy', 'cancelled', 'success'},
                project.tasks))
        #lambda ta: ta['state'] in {'dummy','cancelled', 'success'},
        #project.storage.tasks._document.find())))

        if n_waiting > 0:
            #print(reduce(lambda s,ta: s+' '+ta.state, [' ']+list(project.tasks)))
            #[print(ta.state) for ta in project.tasks]
            logger.info("Waiting on {} tasks".format(n_waiting))
            time.sleep(idle_time)
            return False
        else:
            logger.info("All Tasks in Final States")
            return True

    #
    # It's really only imperative we have a PythonTask as mtask
    # when we get here, since above only check was the is_done
    # method
    #
    #
    # TODO TODO find out why sometimes mtask is wrong from above
    #
    mtasks = sorted(filter(lambda x: x.__class__ is PythonTask, tasks),
                    key=lambda x: x.__time__)

    if len(mtasks) > 0:
        if mtask != mtasks[-1]:
            # TODO TODO find out why sometimes mtask is wrong
            if not isinstance(mtask, PythonTask):
                logger.info("Changing mtask to last PythonTask of tasks list")
                logger.info(
                    "Changing mtask to last PythonTask of tasks list: was:: {}"
                    .format(mtask))
                mtask = mtasks[-1]
                logger.info(
                    "Changing mtask to last PythonTask of tasks list: is:: {}".
                    format(mtask))

    logger.info("Waiting for all done")
    logger.info(
        formatline("TIMER Brain finishing enter {0:.5f}".format(time.time())))
    yield lambda: all_done(mtask)
    logger.info(
        formatline("TIMER Brain finishing done {0:.5f}".format(time.time())))
    time.sleep(5)

    #print(reduce(lambda s,ta: s+' '+ta.state, [' ']+list(project.tasks)))
    logger.info("Simulation Event Finished")