Пример #1
0
def main():
    app = connexion.App(__name__, specification_dir='./openapi/')
    app.app.json_encoder = encoder.JSONEncoder
    app.add_api('openapi.yaml',
                arguments={'title': 'pathoLogic'},
                pythonic_params=True)

    # Serve results under /v1/result/PATH
    app.app.config['STATIC_URL_PATH'] = os.path.abspath(
        os.getenv('BASE_DIR', os.getcwd()))
    CORS(app.app)  # enable CORS everywhere

    # Use dictionary as DB
    with app.app.app_context():
        get_db()

    @app.app.teardown_appcontext
    def close_db(e=None):
        db = g.pop('db', None)

        if db is not None:
            pickle.dump(
                db,
                open(
                    os.path.join(os.getenv('BASE_DIR', os.getcwd()),
                                 'pathoLogic.db'), 'wb'))

    # Create route for nextflow weblog (assembly)
    @app.app.route('/v1/nf_assembly/<runid>', methods=['POST'])
    def nf_assembly(runid):
        req_data = request.get_json()
        db = get_db()
        db['status_hybridassembly'][runid] = req_data
        #print(json.dumps(db['status_assembly'][runid]))
        if req_data['event'] == 'process_completed':
            for sID in db['runs'][runid]:
                db['samples'][sID]['status'] = 'finished'
        return 'NF Request received'

    # Create route for nextflow weblog (plasmident)
    @app.app.route('/v1/nf_plasmident/<runid>', methods=['POST'])
    def nf_plasmident(runid):
        req_data = request.get_json()
        db = get_db()
        db['status_plasmident'][runid] = req_data
        #print(json.dumps(db['status_plasmident'][runid]))
        if req_data['event'] == 'process_completed':
            for sID in db['runs'][runid]:
                db['samples'][sID]['status'] = 'finished'
        return 'NF Request received'

    production = os.getenv('PRODUCTION', False)
    app.run(port=os.getenv('HTTP_PORT', 8080),
            debug=not production,
            use_debugger=not production,
            use_reloader=not production,
            passthrough_errors=not production)
Пример #2
0
 def nf_plasmident(runid):
     req_data = request.get_json()
     db = get_db()
     db['status_plasmident'][runid] = req_data
     #print(json.dumps(db['status_plasmident'][runid]))
     if req_data['event'] == 'process_completed':
         for sID in db['runs'][runid]:
             db['samples'][sID]['status'] = 'finished'
     return 'NF Request received'
Пример #3
0
def status_get():  # noqa: E501
    """Get list of all sample statuses

     # noqa: E501


    :rtype: List[object]
    """
    db = get_db()
    return [{
        'id': sample,
        'status': db['samples'][sample]['status']
    } for sample in db['samples'].keys()]
Пример #4
0
def samples_post(user, body=None):  # noqa: E501
    """Create new samples

     # noqa: E501

    :param body:
    :type body: dict | bytes

    :rtype: Sample
    """
    # Create samplepath
    samplepath = os.path.join(os.environ.get('BASE_DIR', os.getcwd()),
                              'samples')
    if not os.path.isdir(samplepath):
        os.mkdir(samplepath)

    # Save config and read files for each sample in new folder
    for s in body['samples']:
        conf = body['config']
        if os.path.isdir(os.path.join(samplepath, s['id'])):
            raise BadRequest("Sample with ID: {} exists already.".format(
                s['id']))
        os.mkdir(os.path.join(samplepath, s['id']))
        with open(os.path.join(samplepath, s['id'], "nf_config.json"),
                  'w') as outfile:
            json.dump(conf, outfile)
        with open(os.path.join(samplepath, s['id'], "read_locations.tsv"),
                  'w') as outfile:
            if not "path_lr" in s:
                raise BadRequest(
                    "Submitted incomplete sample {}, long run path is missing."
                    .format(s['id']))
            paths = [
                join_read_path_with_data_dir(read_path, user) for read_path in
                [s['path_lr'],
                 s.get('path_sr1', ""),
                 s.get('path_sr2', "")] if len(read_path)
            ]
            outfile.write(s['id'] + '\t' + "\t".join(paths) + '\n')

        db = get_db()
        db['samples'][s['id']] = {
            'user_id': user,
            'id': s['id'],
            'created': str(datetime.utcnow()),
            'last_updated': str(datetime.utcnow()),
            'status': "created",
            'zip': None
        }

    return body['samples']
Пример #5
0
def samples_sample_iddelete(sample_id, user):
    # Get current database
    db = get_db()

    samples = sample_id.split(',')
    if not all(map(lambda sample: db['samples'][sample]['user_id'] == user, samples)):
        raise BadRequest("You are trying to start a sample for a different user. I am afraid I can't do that, Dave.")

    for sID in samples:
        sample_folder_path = os.path.join(os.getenv('DATA_DIR', os.getcwd()), user)
        if os.path.exists(sample_folder_path):
            shutil.rmtree(sample_folder_path) # remove samples from FS
        db['samples'].pop(sID) # remove samples from database

    return jsonify([{'id': sID} for sID in samples])
Пример #6
0
def samples_get(user):  # noqa: E501
    """List all samples

     # noqa: E501


    :rtype: List[Sample]
    """

    db = get_db()
    # filter samples without user id
    samples = [
        sample for sample in db['samples'].keys()
        if 'user_id' in db['samples'][sample]
    ]
    return [
        format_sample(db['samples'][sample]) for sample in samples
        if db['samples'][sample]['user_id'] == user
    ]
Пример #7
0
def result_sample_idget(sample_id):  # noqa: E501
    """Lists results for given sample

     # noqa: E501

    :param sample_id: Comma seperated list of results to return
    :type sample_id: List[str]

    :rtype: InlineResponse2002
    """
    db = get_db()
    samples = sample_id.split(',')
    sample = [db['samples'][sample] for sample in db['samples'].keys() if sample in samples][0]

    return {'id':sample['id'],
                'result': {
                    'statistics_path': 'mystats',
                    'zip_path': os.path.basename(sample['zip'])
                }
            }
Пример #8
0
def samples_sample_idput(sample_id, user):  # noqa: E501
    """Starts one or multiple sample via ID

     # noqa: E501

    :param sample_id:
    :type sample_id: List[str]

    :rtype: jsonify
    """

    # Get current database
    db = get_db()

    samples = sample_id.split(',')

    if not all(map(lambda sample: db['samples'][sample]['user_id'] == user, samples)):
        raise BadRequest("You are trying to start a sample for a different user. I am afraid I can't do that, Dave.")

    # Set sample status to started
    for sID in samples:
        db['samples'][sID]['status'] = 'started'

    #Try to run all this stuff
    # Create run folder
    runspath = os.path.join(os.environ.get('BASE_DIR', os.getcwd()), 'runs')
    if not os.path.isdir(runspath):
        os.mkdir(runspath)
    runid = str(uuid.uuid4())
    runpath = os.path.join(runspath, runid)
    if not os.path.isdir(runpath):
        os.mkdir(runpath)

    # Get nextflow paths
    nfexecutable = os.path.join(os.environ.get('BASE_DIR', os.getcwd()), 'nextflow')
    nf_hybridassembly = os.path.join(os.environ.get('BASE_DIR', os.getcwd()), 'hybridassembly', 'main.nf')
    nf_plasmident = os.path.join(os.environ.get('BASE_DIR', os.getcwd()), 'plasmIDent', 'main.nf')

    # Set sample status to started
    for sID in samples:
        db['samples'][sID]['status'] = 'started'

    # Assign samples to run
    db['runs'][runid] = samples

    # Copy input and config files to run folder
    status = 0

    status += os.system("cat " + " ".join([os.path.join(os.environ.get('BASE_DIR', os.getcwd()),
            'samples', sID, 'read_locations.tsv') for sID in samples]) +
            " >> " + os.path.join(runpath, "read_locations.tsv"))
    status += os.system("cp " + os.path.join(os.environ.get('BASE_DIR', os.getcwd()),
            'samples', sample_id, "nf_config.json") + " " + os.path.join(runpath,
            "nf_config.json"))

    # Run Hybrid assembly
    
    call_ha = ("cd " + runpath + " && " + nfexecutable +
             " run " + nf_hybridassembly + "  -profile app " +
             " --outDir " + runpath +
             " --input read_locations.tsv " +
             "-params-file nf_config.json -with-weblog " +
             "http://localhost:"+os.environ.get('HTTP_PORT',"8080")+"/v1/nf_assembly/" + runid)
    print(call_ha)
    status += os.system("cd " + runpath + " && " + call_ha)

    # Run plasmident
    call_pi =  (nfexecutable + " run " + nf_plasmident + " -profile app " +
              " --outDir " + runpath +
              " --input file_paths_plasmident.tsv " +
              "-params-file nf_config.json -with-weblog "+
              "http://localhost:"+os.environ.get('HTTP_PORT',"8080")+"/v1/nf_plasmident/" + runid)
    print(call_pi)
    status += os.system("cd " + runpath + " && " + call_pi)

    if status == 0:
        for sID in samples:
            # Zip output folders
            zip_path = os.path.join(runpath,  sID)
            zip_name = os.path.join(zip_path, sID + '_pathoLogic_results')
            shutil.make_archive(zip_name, 'zip', root_dir=zip_path, base_dir=zip_path)
            db['samples'][sID]['zip'] = zip_name + '.zip'
            
            # Store ref to summary statistics file in db
            stats_file = os.path.join(runpath, sID, "qc", "qc_summary_" + sID + '.json')
            db['samples'][sID]['assembly_stats'] = stats_file
    else:
        # Set sample status to errored
        for sID in samples:
            db['samples'][sID]['status'] = 'error'

        return jsonify([{'id': sID, 'status': 'error'} for sID in samples])

    return jsonify([{'id': sID, 'status': 'started'} for sID in samples])