Example #1
0
def study_get_tags_request(user_id, study_id):
    """Retrieve available study tags for study_id

    Parameters
    ----------
    user_id : int
        The id of the user performing the operation
    study_id : int
        The id of the study on which we will be performing the operation

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
        - tags: [value, ..., ...]
    """

    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error
    study = Study(study_id)

    return {'status': 'success', 'message': '', 'tags': study.tags}
Example #2
0
def study_delete_req(study_id, user_id):
    """Delete a given study

    Parameters
    ----------
    study_id : int
        Study id to delete
    user_id : str
        User requesting the deletion

    Returns
    -------
    dict
        Status of deletion, in the format
        {status: status,
         message: message}
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error

    status = 'success'
    try:
        Study.delete(int(study_id))
        msg = ''
    except Exception as e:
        status = 'error'
        msg = 'Unable to delete study: %s' % str(e)
    return {'status': status, 'message': msg}
Example #3
0
def artifact_delete_req(artifact_id, user_id):
    """Deletes the artifact

    Parameters
    ----------
    artifact_id : int
        Artifact being acted on
    user_id : str
        The user requesting the action

    Returns
    -------
    dict
        Status of action, in the form {'status': status, 'message': msg}
        status: status of the action, either success or error
        message: Human readable message for status
    """
    pd = Artifact(int(artifact_id))
    pt_id = pd.prep_templates[0].id
    access_error = check_access(pd.study.id, user_id)
    if access_error:
        return access_error

    job_id = safe_submit(user_id, delete_artifact, artifact_id)
    r_client.set(PREP_TEMPLATE_KEY_FORMAT % pt_id,
                 dumps({'job_id': job_id}))

    return {'status': 'success',
            'message': ''}
Example #4
0
def artifact_delete_req(artifact_id, user_id):
    """Deletes the artifact

    Parameters
    ----------
    artifact_id : int
        Artifact being acted on
    user_id : str
        The user requesting the action

    Returns
    -------
    dict
        Status of action, in the form {'status': status, 'message': msg}
        status: status of the action, either success or error
        message: Human readable message for status
    """
    pd = Artifact(int(artifact_id))
    pt_id = pd.prep_templates[0].id
    access_error = check_access(pd.study.id, user_id)
    if access_error:
        return access_error

    job_id = safe_submit(user_id, delete_artifact, artifact_id)
    r_client.set(PREP_TEMPLATE_KEY_FORMAT % pt_id, dumps({'job_id': job_id}))

    return {'status': 'success', 'message': ''}
Example #5
0
def sample_template_meta_cats_get_req(samp_id, user_id):
    """Returns list of metadata categories in the sample template

    Parameters
    ----------
    samp_id : int or str typecastable to int
        SampleTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict
        Returns information in the form
        {'status': str,
         'message': str,
         'categories': list of str}
         samples is list of metadata categories in the template
    """
    exists = _check_sample_template_exists(int(samp_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(samp_id, user_id)
    if access_error:
        return access_error

    return {
        'status': 'success',
        'message': '',
        'categories': sorted(SampleTemplate(int(samp_id)).categories())
    }
Example #6
0
def artifact_get_prep_req(user_id, artifact_ids):
    """Returns all prep info sample ids for the given artifact_ids

    Parameters
    ----------
    user_id : str
        user making the request
    artifact_ids : list of int
        list of artifact ids

    Returns
    -------
    dict of objects
        A dictionary containing the artifact information
        {'status': status,
         'message': message,
         'data': {artifact_id: [prep info sample ids]}
    """
    samples = {}

    for aid in sorted(artifact_ids):
        artifact = Artifact(aid)
        access_error = check_access(artifact.study.id, user_id)
        if access_error:
            return access_error

        samples[aid] = list(chain(
            *[sorted(pt.keys()) for pt in Artifact(aid).prep_templates]))

    return {'status': 'success', 'msg': '', 'data': samples}
Example #7
0
 def _check_permissions(self, sid):
     # Check general access to study
     study_info = check_access(sid, self.current_user.id)
     if study_info:
         raise HTTPError(405, reason="%s: %s, %s" % (
             study_info['message'], self.current_user.email, sid))
     return Study(sid)
Example #8
0
 def _check_permissions(self, sid):
     # Check general access to study
     study_info = check_access(sid, self.current_user.id)
     if study_info:
         raise HTTPError(405, reason="%s: %s, %s" % (
             study_info['message'], self.current_user.email, sid))
     return Study(sid)
Example #9
0
def sample_template_samples_get_req(samp_id, user_id):
    """Returns list of samples in the sample template

    Parameters
    ----------
    samp_id : int or str typecastable to int
        SampleTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict
        Returns summary information in the form
        {'status': str,
         'message': str,
         'samples': list of str}
         samples is list of samples in the template
    """
    exists = _check_sample_template_exists(int(samp_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(samp_id, user_id)
    if access_error:
        return access_error

    return {'status': 'success',
            'message': '',
            'samples': sorted(x for x in SampleTemplate(int(samp_id)))
            }
Example #10
0
def sample_template_patch_request(user_id,
                                  req_op,
                                  req_path,
                                  req_value=None,
                                  req_from=None):
    """Modifies an attribute of the artifact

    Parameters
    ----------
    user_id : str
        The id of the user performing the patch operation
    req_op : str
        The operation to perform on the artifact
    req_path : str
        The prep information and attribute to patch
    req_value : str, optional
        The value that needs to be modified
    req_from : str, optional
        The original path of the element

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
    """
    if req_op == 'remove':
        req_path = [v for v in req_path.split('/') if v]

        if len(req_path) != 3:
            return {'status': 'error', 'message': 'Incorrect path parameter'}

        st_id = req_path[0]
        attribute = req_path[1]
        attr_id = req_path[2]

        # Check if the user actually has access to the template
        st = SampleTemplate(st_id)
        access_error = check_access(st.study_id, user_id)
        if access_error:
            return access_error

        # Offload the deletion of the sample or column to the cluster
        job_id = safe_submit(user_id, delete_sample_or_column, SampleTemplate,
                             int(st_id), attribute, attr_id)
        # Store the job id attaching it to the sample template id
        r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % st_id,
                     dumps({'job_id': job_id}))

        return {'status': 'success', 'message': ''}

    else:
        return {
            'status':
            'error',
            'message':
            'Operation "%s" not supported. '
            'Current supported operations: remove' % req_op
        }
Example #11
0
def study_get_tags_request(user_id, study_id):
    """Retrieve available study tags for study_id

    Parameters
    ----------
    user_id : int
        The id of the user performing the operation
    study_id : int
        The id of the study on which we will be performing the operation

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
        - tags: [value, ..., ...]
    """

    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error
    study = Study(study_id)

    return {'status': 'success',
            'message': '',
            'tags': study.tags}
Example #12
0
def prep_template_filepaths_get_req(prep_id, user_id):
    """Returns all filepaths attached to a prep template

    Parameters
    ----------
    prep_id : int
        The current prep template id
    user_id : int
        The current user object id

    Returns
    -------
    dict of objects
        {'status': status,
         'message': message,
         'filepaths': [(filepath_id, filepath), ...]}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    return {'status': 'success',
            'message': '',
            'filepaths': prep.get_filepaths()
            }
Example #13
0
def prep_template_delete_req(prep_id, user_id):
    """Delete the prep template

    Parameters
    ----------
    prep_id : int
        The prep template to update
    user_id : str
        The current user object id

    Returns
    -------
    dict of str
        {'status': status,
         'message': message}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    msg = ''
    status = 'success'
    try:
        PrepTemplate.delete(prep.id)
    except Exception as e:
        msg = ("Couldn't remove prep template: %s" % str(e))
        status = 'error'

    return {'status': status,
            'message': msg}
Example #14
0
 def test_check_access_no_access(self):
     obs = check_access(1, '*****@*****.**')
     exp = {
         'status': 'error',
         'message': 'User does not have access to study'
     }
     self.assertEqual(obs, exp)
Example #15
0
def prep_template_get_req(prep_id, user_id):
    """Gets the json of the full prep template

    Parameters
    ----------
    prep_id : int
        PrepTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict of objects
    {'status': status,
     'message': message,
     'template': {sample: {column: value, ...}, ...}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    df = prep.to_dataframe()
    return {'status': 'success',
            'message': '',
            'template': df.to_dict(orient='index')}
Example #16
0
def prep_template_jobs_get_req(prep_id, user_id):
    """Returns graph of all artifacts created from the prep base artifact

    Parameters
    ----------
    prep_id : int
        Prep template ID to get graph for
    user_id : str
        User making the request

    Returns
    -------
    dict with the jobs information

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    job_info = r_client.get(PREP_TEMPLATE_KEY_FORMAT % prep_id)
    result = {}
    if job_info:
        job_info = defaultdict(lambda: '', loads(job_info))
        job_id = job_info['job_id']
        job = ProcessingJob(job_id)
        result[job.id] = {'status': job.status, 'step': job.step,
                          'error': job.log.msg if job.log else ""}

    return result
Example #17
0
def study_delete_req(study_id, user_id):
    """Delete a given study

    Parameters
    ----------
    study_id : int
        Study id to delete
    user_id : str
        User requesting the deletion

    Returns
    -------
    dict
        Status of deletion, in the format
        {status: status,
         message: message}
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error

    qiita_plugin = Software.from_name_and_version('Qiita', 'alpha')
    cmd = qiita_plugin.get_command('delete_study')
    params = Parameters.load(cmd, values_dict={'study': study_id})
    job = ProcessingJob.create(User(user_id), params, True)
    # Store the job id attaching it to the sample template id
    r_client.set(STUDY_KEY_FORMAT % study_id,
                 dumps({'job_id': job.id}))

    job.submit()

    return {'status': 'success', 'message': ''}
Example #18
0
def prep_template_filepaths_get_req(prep_id, user_id):
    """Returns all filepaths attached to a prep template

    Parameters
    ----------
    prep_id : int
        The current prep template id
    user_id : int
        The current user object id

    Returns
    -------
    dict of objects
        {'status': status,
         'message': message,
         'filepaths': [(filepath_id, filepath), ...]}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    return {'status': 'success',
            'message': '',
            'filepaths': prep.get_filepaths()
            }
Example #19
0
def study_delete_req(study_id, user_id):
    """Delete a given study

    Parameters
    ----------
    study_id : int
        Study id to delete
    user_id : str
        User requesting the deletion

    Returns
    -------
    dict
        Status of deletion, in the format
        {status: status,
         message: message}
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error

    status = 'success'
    try:
        Study.delete(int(study_id))
        msg = ''
    except Exception as e:
        status = 'error'
        msg = 'Unable to delete study: %s' % str(e)
    return {
        'status': status,
        'message': msg
    }
Example #20
0
def prep_template_delete_req(prep_id, user_id):
    """Delete the prep template

    Parameters
    ----------
    prep_id : int
        The prep template to update
    user_id : str
        The current user object id

    Returns
    -------
    dict of str
        {'status': status,
         'message': message}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    msg = ''
    status = 'success'
    try:
        PrepTemplate.delete(prep.id)
    except Exception as e:
        msg = str(e)
        status = 'error'

    return {'status': status,
            'message': msg}
Example #21
0
def sample_template_delete_req(study_id, user_id):
    """Deletes the sample template attached to the study

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    """
    exists = _check_sample_template_exists(int(study_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error

    # Offload the deletion of the sample template to the cluster
    job_id = safe_submit(user_id, delete_sample_template, int(study_id))
    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id,
                 dumps({'job_id': job_id}))

    return {'status': 'success', 'message': ''}
Example #22
0
def prep_template_get_req(prep_id, user_id):
    """Gets the json of the full prep template

    Parameters
    ----------
    prep_id : int
        PrepTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict of objects
    {'status': status,
     'message': message,
     'template': {sample: {column: value, ...}, ...}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    df = prep.to_dataframe()
    return {'status': 'success',
            'message': '',
            'template': df.to_dict(orient='index')}
Example #23
0
def artifact_get_prep_req(user_id, artifact_ids):
    """Returns all prep info sample ids for the given artifact_ids

    Parameters
    ----------
    user_id : str
        user making the request
    artifact_ids : list of int
        list of artifact ids

    Returns
    -------
    dict of objects
        A dictionary containing the artifact information
        {'status': status,
         'message': message,
         'data': {artifact_id: [prep info sample ids]}
    """
    samples = {}

    for aid in sorted(artifact_ids):
        artifact = Artifact(aid)
        access_error = check_access(artifact.study.id, user_id)
        if access_error:
            return access_error

        samples[aid] = list(
            chain(*[sorted(pt.keys()) for pt in Artifact(aid).prep_templates]))

    return {'status': 'success', 'msg': '', 'data': samples}
Example #24
0
def study_get_req(study_id, user_id):
    """Returns information available for the given study

    Parameters
    ----------
    study_id : int
        Study id to get prep template info for
    user_id : str
        User requesting the info

    Returns
    -------
    dict
        Data types information in the form
        {'status': status,
         'message': message,
         'info': dict of objects
        status can be success, warning, or error depending on result
        message has the warnings or errors
        info contains study information seperated by data type, in the form
        {col_name: value, ...} with value being a string, int, or list of
        strings or ints
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error
    # Can only pass ids over API, so need to instantiate object
    study = Study(study_id)
    study_info = study.info
    # Add needed info that is not part of the initial info pull
    study_info['publications'] = study.publications
    study_info['study_id'] = study.id
    study_info['study_title'] = study.title
    study_info['shared_with'] = [s.id for s in study.shared_with]
    study_info['status'] = study.status
    study_info['ebi_study_accession'] = study.ebi_study_accession
    study_info['ebi_submission_status'] = study.ebi_submission_status

    # Clean up StudyPerson objects to string for display
    pi = study_info['principal_investigator']
    study_info['principal_investigator'] = {
        'name': pi.name,
        'email': pi.email,
        'affiliation': pi.affiliation}

    lab_person = study_info['lab_person']
    if lab_person:
        study_info['lab_person'] = {
            'name': lab_person.name,
            'email': lab_person.email,
            'affiliation': lab_person.affiliation}

    samples = study.sample_template
    study_info['num_samples'] = 0 if samples is None else len(list(samples))
    study_info['owner'] = study.owner.id

    return {'status': 'success',
            'message': '',
            'study_info': study_info,
            'editable': study.can_edit(User(user_id))}
Example #25
0
def prep_template_samples_get_req(prep_id, user_id):
    """Returns list of samples in the prep template

    Parameters
    ----------
    prep_id : int or str typecastable to int
        PrepTemplate id to get info for
    user_id : str
        User requesting the prep template info

    Returns
    -------
    dict
        Returns summary information in the form
        {'status': str,
         'message': str,
         'samples': list of str}
         samples is list of samples in the template
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists
    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error
    return {'status': 'success',
            'message': '',
            'samples': sorted(x for x in PrepTemplate(int(prep_id)))
            }
Example #26
0
def artifact_delete_req(artifact_id, user_id):
    """Deletes the artifact

    Parameters
    ----------
    artifact_id : int
        Artifact being acted on
    user_id : str
        The user requesting the action

    Returns
    -------
    dict
        Status of action, in the form {'status': status, 'message': msg}
        status: status of the action, either success or error
        message: Human readable message for status
    """
    pd = Artifact(int(artifact_id))
    access_error = check_access(pd.study.id, user_id)
    if access_error:
        return access_error
    try:
        Artifact.delete(int(artifact_id))
    except QiitaDBArtifactDeletionError as e:
        return {'status': 'error',
                'message': str(e)}
    return {'status': 'success',
            'message': ''}
Example #27
0
def analyses_associated_with_study(study_id, user_id):
    """Returns all available analyses in study_id

    Parameters
    ----------
    study_id : int or str typecastable to int
        Study id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict
        Returns information in the form
        {'status': str,
         'message': str,
         'values': list of [qiita_db.analysis.Analysis,
                            prep_ids for this study]}
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error

    values = generate_analyses_list_per_study(study_id)

    return {'status': 'success',
            'message': '',
            'values': values}
Example #28
0
def study_delete_req(study_id, user_id):
    """Delete a given study

    Parameters
    ----------
    study_id : int
        Study id to delete
    user_id : str
        User requesting the deletion

    Returns
    -------
    dict
        Status of deletion, in the format
        {status: status,
         message: message}
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error

    qiita_plugin = Software.from_name_and_version('Qiita', 'alpha')
    cmd = qiita_plugin.get_command('delete_study')
    params = Parameters.load(cmd, values_dict={'study': study_id})
    job = ProcessingJob.create(User(user_id), params, True)
    # Store the job id attaching it to the sample template id
    r_client.set(STUDY_KEY_FORMAT % study_id, dumps({'job_id': job.id}))

    job.submit()

    return {'status': 'success', 'message': ''}
def sample_template_delete_req(study_id, user_id):
    """Deletes the sample template attached to the study

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    """
    exists = _check_sample_template_exists(int(study_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error

    # Offload the deletion of the sample template to the cluster
    job_id = safe_submit(user_id, delete_sample_template, int(study_id))
    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id,
                 dumps({'job_id': job_id}))

    return {'status': 'success', 'message': ''}
Example #30
0
def prep_template_graph_get_req(prep_id, user_id):
    """Returns graph of all artifacts created from the prep base artifact

    Parameters
    ----------
    prep_id : int
        Prep template ID to get graph for
    user_id : str
        User making the request

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    # We should filter for only the public artifacts if the user
    # doesn't have full access to the study
    full_access = Study(prep.study_id).can_edit(User(user_id))

    artifact = prep.artifact

    if artifact is None:
        return {'edges': [], 'nodes': [],
                'status': 'success', 'message': ''}

    G = artifact.descendants_with_jobs

    nodes, edges, wf_id = get_network_nodes_edges(G, full_access)
    # nodes returns [node_type, node_name, element_id]; here we are looking
    # for the node_type == artifact, and check by the element/artifact_id if
    # it's being deleted
    artifacts_being_deleted = [a[2] for a in nodes if a[0] == 'artifact' and
                               Artifact(a[2]).being_deleted_by is not None]

    return {'edges': edges,
            'nodes': nodes,
            'workflow': wf_id,
            'status': 'success',
            'artifacts_being_deleted': artifacts_being_deleted,
            'message': ''}
Example #31
0
def sample_template_post_req(study_id, user_id, data_type,
                             sample_template):
    """Creates the sample template from the given file

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id
    data_type : str
        Data type for the sample template
    sample_template : str
        filename to use for creation

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg,
         'file': sample_template}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    file has the file name
    """
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error
    fp_rsp = check_fp(study_id, sample_template)
    if fp_rsp['status'] != 'success':
        # Unknown filepath, so return the error message
        return fp_rsp
    fp_rsp = fp_rsp['file']

    # Define here the message and message level in case of success
    msg = ''
    status = 'success'
    is_mapping_file = looks_like_qiime_mapping_file(fp_rsp)
    if is_mapping_file and not data_type:
        return {'status': 'error',
                'message': 'Please, choose a data type if uploading a '
                           'QIIME mapping file',
                'file': sample_template}

    study = Study(int(study_id))

    # Offload the creation of the sample template to the cluster
    job_id = safe_submit(user_id, create_sample_template, fp_rsp, study,
                         is_mapping_file, data_type)
    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study.id,
                 dumps({'job_id': job_id}))

    return {'status': status,
            'message': msg,
            'file': sample_template}
Example #32
0
def sample_template_put_req(study_id, user_id, sample_template):
    """Updates a sample template using the given file

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id
    sample_template : str
        filename to use for updating

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg,
         'file': sample_template}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    file has the file name
    """
    exists = _check_sample_template_exists(int(study_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error

    fp_rsp = check_fp(study_id, sample_template)
    if fp_rsp['status'] != 'success':
        # Unknown filepath, so return the error message
        return fp_rsp
    fp_rsp = fp_rsp['file']

    msg = ''
    status = 'success'

    # Offload the update of the sample template to the cluster
    qiita_plugin = Software.from_name_and_version('Qiita', 'alpha')
    cmd = qiita_plugin.get_command('update_sample_template')
    params = Parameters.load(cmd,
                             values_dict={
                                 'study': int(study_id),
                                 'template_fp': fp_rsp
                             })
    job = ProcessingJob.create(User(user_id), params)

    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id,
                 dumps({'job_id': job.id}))

    job.submit()

    return {'status': status, 'message': msg, 'file': sample_template}
def sample_template_post_req(study_id, user_id, data_type, sample_template):
    """Creates the sample template from the given file

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id
    data_type : str
        Data type for the sample template
    sample_template : str
        filename to use for creation

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg,
         'file': sample_template}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    file has the file name
    """
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error
    fp_rsp = check_fp(study_id, sample_template)
    if fp_rsp['status'] != 'success':
        # Unknown filepath, so return the error message
        return fp_rsp
    fp_rsp = fp_rsp['file']

    # Define here the message and message level in case of success
    msg = ''
    status = 'success'
    is_mapping_file = looks_like_qiime_mapping_file(fp_rsp)
    if is_mapping_file and not data_type:
        return {
            'status': 'error',
            'message': 'Please, choose a data type if uploading a '
            'QIIME mapping file',
            'file': sample_template
        }

    study = Study(int(study_id))

    # Offload the creation of the sample template to the cluster
    job_id = safe_submit(user_id, create_sample_template, fp_rsp, study,
                         is_mapping_file, data_type)
    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study.id,
                 dumps({'job_id': job_id}))

    return {'status': status, 'message': msg, 'file': sample_template}
Example #34
0
def artifact_patch_request(user_id, req_op, req_path, req_value=None,
                           req_from=None):
    """Modifies an attribute of the artifact

    Parameters
    ----------
    user_id : str
        The id of the user performing the patch operation
    req_op : str
        The operation to perform on the artifact
    req_path : str
        The prep information and attribute to patch
    req_value : str, optional
        The value that needs to be modified
    req_from : str, optional
        The original path of the element

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
    """
    if req_op == 'replace':
        req_path = [v for v in req_path.split('/') if v]
        if len(req_path) != 2:
            return {'status': 'error',
                    'message': 'Incorrect path parameter'}

        artifact_id = req_path[0]
        attribute = req_path[1]

        # Check if the user actually has access to the artifact
        artifact = Artifact(artifact_id)
        access_error = check_access(artifact.study.id, user_id)
        if access_error:
            return access_error

        if not req_value:
            return {'status': 'error',
                    'message': 'A value is required'}

        if attribute == 'name':
            artifact.name = req_value
            return {'status': 'success',
                    'message': ''}
        else:
            # We don't understand the attribute so return an error
            return {'status': 'error',
                    'message': 'Attribute "%s" not found. '
                               'Please, check the path parameter' % attribute}
    else:
        return {'status': 'error',
                'message': 'Operation "%s" not supported. '
                           'Current supported operations: replace' % req_op}
Example #35
0
def sample_template_patch_request(user_id, req_op, req_path, req_value=None,
                                  req_from=None):
    """Modifies an attribute of the artifact

    Parameters
    ----------
    user_id : str
        The id of the user performing the patch operation
    req_op : str
        The operation to perform on the artifact
    req_path : str
        The prep information and attribute to patch
    req_value : str, optional
        The value that needs to be modified
    req_from : str, optional
        The original path of the element

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
    """
    if req_op == 'remove':
        req_path = [v for v in req_path.split('/') if v]

        if len(req_path) != 3:
            return {'status': 'error',
                    'message': 'Incorrect path parameter'}

        st_id = req_path[0]
        attribute = req_path[1]
        attr_id = req_path[2]

        # Check if the user actually has access to the template
        st = SampleTemplate(st_id)
        access_error = check_access(st.study_id, user_id)
        if access_error:
            return access_error

        # Offload the deletion of the sample or column to the cluster
        job_id = safe_submit(user_id, delete_sample_or_column, SampleTemplate,
                             int(st_id), attribute, attr_id)
        # Store the job id attaching it to the sample template id
        r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % st_id,
                     dumps({'job_id': job_id}))

        return {'status': 'success', 'message': ''}

    else:
        return {'status': 'error',
                'message': 'Operation "%s" not supported. '
                           'Current supported operations: remove' % req_op}
Example #36
0
def study_tags_patch_request(user_id, study_id,
                             req_op, req_path, req_value=None, req_from=None):
    """Modifies an attribute of the artifact

    Parameters
    ----------
    user_id : int
        The id of the user performing the patch operation
    study_id : int
        The id of the study on which we will be performing the patch operation
    req_op : str
        The operation to perform on the study
    req_path : str
        The attribute to patch
    req_value : str, optional
        The value that needs to be modified
    req_from : str, optional
        The original path of the element

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
    """
    if req_op == 'replace':
        req_path = [v for v in req_path.split('/') if v]
        if len(req_path) != 1:
            return {'status': 'error',
                    'message': 'Incorrect path parameter'}

        attribute = req_path[0]

        # Check if the user actually has access to the study
        access_error = check_access(study_id, user_id)
        if access_error:
            return access_error
        study = Study(study_id)

        if attribute == 'tags':
            message = study.update_tags(User(user_id), req_value)
            return {'status': 'success',
                    'message': message}
        else:
            # We don't understand the attribute so return an error
            return {'status': 'error',
                    'message': 'Attribute "%s" not found. '
                               'Please, check the path parameter' % attribute}
    else:
        return {'status': 'error',
                'message': 'Operation "%s" not supported. '
                           'Current supported operations: replace' % req_op}
Example #37
0
def study_prep_get_req(study_id, user_id):
    """Gives a summary of each prep template attached to the study

    Parameters
    ----------
    study_id : int
        Study id to get prep template info for
    user_id : str
        User id requesting the prep templates

    Returns
    -------
    dict of list of dict
        prep template information seperated by data type, in the form
        {data_type: [{prep 1 info dict}, ....], ...}
    """
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error
    # Can only pass ids over API, so need to instantiate object
    study = Study(int(study_id))
    prep_info = defaultdict(list)
    editable = study.can_edit(User(user_id))
    for dtype in study.data_types:
        for prep in study.prep_templates(dtype):
            if prep.status != 'public' and not editable:
                continue
            start_artifact = prep.artifact
            info = {
                'name': 'PREP %d NAME' % prep.id,
                'id': prep.id,
                'status': prep.status,
            }
            if start_artifact is not None:
                youngest_artifact = prep.artifact.youngest_artifact
                info['start_artifact'] = start_artifact.artifact_type
                info['start_artifact_id'] = start_artifact.id
                info['youngest_artifact'] = '%s - %s' % (
                    youngest_artifact.name, youngest_artifact.artifact_type)
                info['ebi_experiment'] = bool(
                    [v for _, v in viewitems(prep.ebi_experiment_accessions)
                     if v is not None])
            else:
                info['start_artifact'] = None
                info['start_artifact_id'] = None
                info['youngest_artifact'] = None
                info['ebi_experiment'] = False

            prep_info[dtype].append(info)

    return {'status': 'success',
            'message': '',
            'info': prep_info}
Example #38
0
def study_tags_patch_request(user_id, study_id,
                             req_op, req_path, req_value=None, req_from=None):
    """Modifies an attribute of the artifact

    Parameters
    ----------
    user_id : int
        The id of the user performing the patch operation
    study_id : int
        The id of the study on which we will be performing the patch operation
    req_op : str
        The operation to perform on the study
    req_path : str
        The attribute to patch
    req_value : str, optional
        The value that needs to be modified
    req_from : str, optional
        The original path of the element

    Returns
    -------
    dict of {str, str}
        A dictionary with the following keys:
        - status: str, whether if the request is successful or not
        - message: str, if the request is unsuccessful, a human readable error
    """
    if req_op == 'replace':
        req_path = [v for v in req_path.split('/') if v]
        if len(req_path) != 1:
            return {'status': 'error',
                    'message': 'Incorrect path parameter'}

        attribute = req_path[0]

        # Check if the user actually has access to the study
        access_error = check_access(study_id, user_id)
        if access_error:
            return access_error
        study = Study(study_id)

        if attribute == 'tags':
            message = study.update_tags(User(user_id), req_value)
            return {'status': 'success',
                    'message': message}
        else:
            # We don't understand the attribute so return an error
            return {'status': 'error',
                    'message': 'Attribute "%s" not found. '
                               'Please, check the path parameter' % attribute}
    else:
        return {'status': 'error',
                'message': 'Operation "%s" not supported. '
                           'Current supported operations: replace' % req_op}
Example #39
0
def prep_template_graph_get_req(prep_id, user_id):
    """Returns graph of all artifacts created from the prep base artifact

    Parameters
    ----------
    prep_id : int
        Prep template ID to get graph for
    user_id : str
        User making the request

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    # We should filter for only the public artifacts if the user
    # doesn't have full access to the study
    full_access = Study(prep.study_id).can_edit(User(user_id))

    artifact = prep.artifact

    if artifact is None:
        return {'edges': [], 'nodes': [],
                'status': 'success', 'message': ''}

    G = artifact.descendants_with_jobs

    nodes, edges, wf_id = get_network_nodes_edges(G, full_access)

    return {'edges': edges,
            'nodes': nodes,
            'workflow': wf_id,
            'status': 'success',
            'message': ''}
Example #40
0
def sample_template_get_req(samp_id, user_id):
    """Gets the json of the full sample template

    Parameters
    ----------
    samp_id : int or int castable string
        SampleTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict of objects
        {'status': status,
         'message': msg,
         'template': dict of {str: {str: object, ...}, ...}

        template is dictionary where the keys access_error the metadata samples
        and the values are a dictionary of column and value.
        Format {sample: {column: value, ...}, ...}
    """
    exists = _check_sample_template_exists(int(samp_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(samp_id), user_id)
    if access_error:
        return access_error

    template = SampleTemplate(int(samp_id))
    access_error = check_access(template.study_id, user_id)
    if access_error:
        return access_error
    df = template.to_dataframe()
    return {
        'status': 'success',
        'message': '',
        'template': df.to_dict(orient='index')
    }
Example #41
0
def sample_template_put_req(study_id, user_id, sample_template):
    """Updates a sample template using the given file

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id
    sample_template : str
        filename to use for updating

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg,
         'file': sample_template}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    file has the file name
    """
    exists = _check_sample_template_exists(int(study_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error

    fp_rsp = check_fp(study_id, sample_template)
    if fp_rsp['status'] != 'success':
        # Unknown filepath, so return the error message
        return fp_rsp
    fp_rsp = fp_rsp['file']

    msg = ''
    status = 'success'

    # Offload the update of the sample template to the cluster
    job_id = safe_submit(user_id, update_sample_template, int(study_id),
                         fp_rsp)
    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id,
                 dumps({'job_id': job_id}))

    return {'status': status,
            'message': msg,
            'file': sample_template}
Example #42
0
def prep_template_graph_get_req(prep_id, user_id):
    """Returns graph of all artifacts created from the prep base artifact

    Parameters
    ----------
    prep_id : int
        Prep template ID to get graph for
    user_id : str
        User making the request

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    # We should filter for only the public artifacts if the user
    # doesn't have full access to the study
    full_access = Study(prep.study_id).can_edit(User(user_id))
    G = prep.artifact.descendants
    node_labels = [(n.id, ' - '.join([n.name, n.artifact_type]))
                   for n in G.nodes()
                   if full_access or n.visibility == 'public']
    node_ids = [id_ for id_, label in node_labels]
    edge_list = [(n.id, m.id) for n, m in G.edges()
                 if n.id in node_ids and m.id in node_ids]

    return {
        'status': 'success',
        'message': '',
        'edge_list': edge_list,
        'node_labels': node_labels
    }
Example #43
0
def artifact_status_put_req(artifact_id, user_id, visibility):
    """Set the status of the artifact given

    Parameters
    ----------
    artifact_id : int
        Artifact being acted on
    user_id : str
        The user requesting the action
    visibility : {'sandbox', 'awaiting_approval', 'private', 'public'}
        What to change the visibility to

    Returns
    -------
    dict
        Status of action, in the form {'status': status, 'message': msg}
        status: status of the action, either success or error
        message: Human readable message for status
    """
    if visibility not in get_visibilities():
        return {'status': 'error',
                'message': 'Unknown visibility value: %s' % visibility}

    pd = Artifact(int(artifact_id))
    sid = pd.study.id
    access_error = check_access(sid, user_id)
    if access_error:
        return access_error
    user = User(str(user_id))
    status = 'success'
    msg = 'Artifact visibility changed to %s' % visibility
    # Set the approval to private if needs approval and admin
    if visibility == 'private':
        if not qiita_config.require_approval:
            pd.visibility = 'private'
        # Set the approval to private if approval not required
        elif user.level == 'admin':
            pd.visibility = 'private'
        # Trying to set approval without admin privileges
        else:
            status = 'error'
            msg = 'User does not have permissions to approve change'
    else:
        pd.visibility = visibility

    LogEntry.create('Warning', '%s changed artifact %s (study %d) to %s' % (
        user_id, artifact_id, sid, visibility))

    return {'status': status,
            'message': msg}
Example #44
0
def sample_template_get_req(samp_id, user_id):
    """Gets the json of the full sample template

    Parameters
    ----------
    samp_id : int or int castable string
        SampleTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict of objects
        {'status': status,
         'message': msg,
         'template': dict of {str: {str: object, ...}, ...}

        template is dictionary where the keys access_error the metadata samples
        and the values are a dictionary of column and value.
        Format {sample: {column: value, ...}, ...}
    """
    exists = _check_sample_template_exists(int(samp_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(samp_id), user_id)
    if access_error:
        return access_error

    template = SampleTemplate(int(samp_id))
    access_error = check_access(template.study_id, user_id)
    if access_error:
        return access_error
    df = template.to_dataframe()
    return {'status': 'success',
            'message': '',
            'template': df.to_dict(orient='index')}
Example #45
0
def prep_template_graph_get_req(prep_id, user_id):
    """Returns graph of all artifacts created from the prep base artifact

    Parameters
    ----------
    prep_id : int
        Prep template ID to get graph for
    user_id : str
        User making the request

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    # We should filter for only the public artifacts if the user
    # doesn't have full access to the study
    full_access = Study(prep.study_id).can_edit(User(user_id))
    G = prep.artifact.descendants
    node_labels = [(n.id, ' - '.join([n.name, n.artifact_type]))
                   for n in G.nodes()
                   if full_access or n.visibility == 'public']
    node_ids = [id_ for id_, label in node_labels]
    edge_list = [(n.id, m.id) for n, m in G.edges()
                 if n.id in node_ids and m.id in node_ids]

    return {'status': 'success',
            'message': '',
            'edge_list': edge_list,
            'node_labels': node_labels}
def sample_template_put_req(study_id, user_id, sample_template):
    """Updates a sample template using the given file

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id
    sample_template : str
        filename to use for updating

    Returns
    -------
    dict
        results dictonary in the format
        {'status': status,
         'message': msg,
         'file': sample_template}

    status can be success, warning, or error depending on result
    message has the warnings or errors
    file has the file name
    """
    exists = _check_sample_template_exists(int(study_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(int(study_id), user_id)
    if access_error:
        return access_error

    fp_rsp = check_fp(study_id, sample_template)
    if fp_rsp['status'] != 'success':
        # Unknown filepath, so return the error message
        return fp_rsp
    fp_rsp = fp_rsp['file']

    msg = ''
    status = 'success'

    # Offload the update of the sample template to the cluster
    job_id = safe_submit(user_id, update_sample_template, int(study_id),
                         fp_rsp)
    # Store the job id attaching it to the sample template id
    r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % study_id,
                 dumps({'job_id': job_id}))

    return {'status': status, 'message': msg, 'file': sample_template}
Example #47
0
def prep_template_summary_get_req(prep_id, user_id):
    """Get the summarized prep template data for each metadata column

    Parameters
    ----------
    prep_id : int
        PrepTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict of objects
        Dictionary object where the keys are the metadata categories
        and the values are list of tuples. Each tuple is an observed value in
        the category and the number of times its seen.
        Format {'status': status,
                'message': message,
                'num_samples': value,
                'category': [(val1, count1), (val2, count2), ...],
                'editable': bool}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    editable = Study(prep.study_id).can_edit(User(user_id))
    df = prep.to_dataframe()
    out = {
        'num_samples': df.shape[0],
        'summary': [],
        'status': 'success',
        'message': '',
        'editable': editable
    }

    cols = sorted(list(df.columns))
    for column in cols:
        counts = df[column].value_counts(dropna=False)
        out['summary'].append(
            (str(column), [(str(key), counts[key])
                           for key in natsorted(counts.index)]))
    return out
Example #48
0
def artifact_get_req(user_id, artifact_id):
    """Returns all base information about an artifact

    Parameters
    ----------
    user_id : str
        user making the request
    artifact_id : int or str coercable to int
        Atrtifact to get information for

    Returns
    -------
    dict of objects
        A dictionary containing the artifact information
        {'status': status,
         'message': message,
         'artifact': {info key: val, ...}}
    """
    artifact_id = int(artifact_id)
    artifact = Artifact(artifact_id)

    access_error = check_access(artifact.study.id, user_id)
    if access_error:
        return access_error

    can_submit_ebi = artifact.can_be_submitted_to_ebi
    ebi_run_accessions = (artifact.ebi_run_accessions
                          if can_submit_ebi else None)
    can_submit_vamps = artifact.can_be_submitted_to_vamps
    is_submitted_vamps = (artifact.is_submitted_to_vamps
                          if can_submit_vamps else False)

    return {
        'id': artifact_id,
        'timestamp': artifact.timestamp,
        'processing_parameters': artifact.processing_parameters,
        'visibility': artifact.visibility,
        'type': artifact.artifact_type,
        'data_type': artifact.data_type,
        'filepaths': artifact.filepaths,
        'parents': [a.id for a in artifact.parents],
        'study': artifact.study.id if artifact.study else None,
        'can_submit_ebi': can_submit_ebi,
        'ebi_run_accessions': ebi_run_accessions,
        'can_submit_vamps': can_submit_vamps,
        'is_submitted_vamps': is_submitted_vamps
    }
Example #49
0
def artifact_summary_post_request(user_id, artifact_id):
    """Launches the HTML summary generation and returns the job information

    Parameters
    ----------
    user_id : str
        The user making the request
    artifact_id : int or str
        The artifact id

    Returns
    -------
    dict of objects
        A dictionary containing the artifact summary information
        {'status': str,
         'message': str,
         'job': list of [str, str, str]}
    """
    artifact_id = int(artifact_id)
    artifact = Artifact(artifact_id)

    access_error = check_access(artifact.study.id, user_id)
    if access_error:
        return access_error

    # Check if the summary is being generated or has been already generated
    command = Command.get_html_generator(artifact.artifact_type)
    jobs = artifact.jobs(cmd=command)
    jobs = [j for j in jobs if j.status in ['queued', 'running', 'success']]
    if jobs:
        # The HTML summary is either being generated or already generated.
        # Return the information of that job so we only generate the HTML
        # once
        job = jobs[0]
    else:
        # Create a new job to generate the HTML summary and return the newly
        # created job information
        job = ProcessingJob.create(
            User(user_id),
            Parameters.load(command, values_dict={'input_data': artifact_id}))
        job.submit()

    return {
        'status': 'success',
        'message': '',
        'job': [job.id, job.status, job.step]
    }
Example #50
0
def artifact_graph_get_req(artifact_id, direction, user_id):
    """Creates graphs of ancestor or descendant artifacts from given one

    Parameters
    ----------
    artifact_id : int
        Artifact ID to get graph for
    direction : {'ancestors', 'descendants'}
        What direction to get the graph in

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    access_error = check_access(Artifact(artifact_id).study.id, user_id)
    if access_error:
        return access_error

    if direction == 'descendants':
        G = Artifact(int(artifact_id)).descendants
    elif direction == 'ancestors':
        G = Artifact(int(artifact_id)).ancestors
    else:
        return {
            'status': 'error',
            'message': 'Unknown directon %s' % direction
        }

    node_labels = [(n.id, ' - '.join([n.name, n.artifact_type]))
                   for n in G.nodes()]
    return {
        'edge_list': [(n.id, m.id) for n, m in G.edges()],
        'node_labels': node_labels,
        'status': 'success',
        'message': ''
    }
Example #51
0
def prep_template_summary_get_req(prep_id, user_id):
    """Get the summarized prep template data for each metadata column

    Parameters
    ----------
    prep_id : int
        PrepTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict of objects
        Dictionary object where the keys are the metadata categories
        and the values are list of tuples. Each tuple is an observed value in
        the category and the number of times its seen.
        Format {'status': status,
                'message': message,
                'num_samples': value,
                'category': [(val1, count1), (val2, count2), ...],
                'editable': bool}
    """
    exists = _check_prep_template_exists(int(prep_id))
    if exists['status'] != 'success':
        return exists

    prep = PrepTemplate(int(prep_id))
    access_error = check_access(prep.study_id, user_id)
    if access_error:
        return access_error

    editable = Study(prep.study_id).can_edit(User(user_id))
    df = prep.to_dataframe()
    out = {'num_samples': df.shape[0],
           'summary': [],
           'status': 'success',
           'message': '',
           'editable': editable}

    cols = sorted(list(df.columns))
    for column in cols:
        counts = df[column].value_counts()
        out['summary'].append(
            (str(column), [(str(key), counts[key])
                           for key in natsorted(counts.index)]))
    return out
Example #52
0
def artifact_status_put_req(artifact_id, user_id, visibility):
    """Set the status of the artifact given

    Parameters
    ----------
    artifact_id : int
        Artifact being acted on
    user_id : str
        The user requesting the action
    visibility : {'sandbox', 'awaiting_approval', 'private', 'public'}
        What to change the visibility to

    Returns
    -------
    dict
        Status of action, in the form {'status': status, 'message': msg}
        status: status of the action, either success or error
        message: Human readable message for status
    """
    if visibility not in get_visibilities():
        return {'status': 'error',
                'message': 'Unknown visiblity value: %s' % visibility}

    pd = Artifact(int(artifact_id))
    access_error = check_access(pd.study.id, user_id)
    if access_error:
        return access_error
    user = User(str(user_id))
    status = 'success'
    msg = 'Artifact visibility changed to %s' % visibility
    # Set the approval to private if needs approval and admin
    if visibility == 'private':
        if not qiita_config.require_approval:
            pd.visibility = 'private'
        # Set the approval to private if approval not required
        elif user.level == 'admin':
            pd.visibility = 'private'
        # Trying to set approval without admin privileges
        else:
            status = 'error'
            msg = 'User does not have permissions to approve change'
    else:
        pd.visibility = visibility

    return {'status': status,
            'message': msg}
Example #53
0
def artifact_summary_post_request(user_id, artifact_id):
    """Launches the HTML summary generation and returns the job information

    Parameters
    ----------
    user_id : str
        The user making the request
    artifact_id : int or str
        The artifact id

    Returns
    -------
    dict of objects
        A dictionary containing the artifact summary information
        {'status': str,
         'message': str,
         'job': list of [str, str, str]}
    """
    artifact_id = int(artifact_id)
    artifact = Artifact(artifact_id)

    access_error = check_access(artifact.study.id, user_id)
    if access_error:
        return access_error

    # Check if the summary is being generated or has been already generated
    command = Command.get_html_generator(artifact.artifact_type)
    jobs = artifact.jobs(cmd=command)
    jobs = [j for j in jobs if j.status in ['queued', 'running', 'success']]
    if jobs:
        # The HTML summary is either being generated or already generated.
        # Return the information of that job so we only generate the HTML
        # once
        job = jobs[0]
    else:
        # Create a new job to generate the HTML summary and return the newly
        # created job information
        job = ProcessingJob.create(
            User(user_id),
            Parameters.load(command, values_dict={'input_data': artifact_id}))
        job.submit()

    return {'status': 'success',
            'message': '',
            'job': [job.id, job.status, job.step]}
Example #54
0
def artifact_get_req(user_id, artifact_id):
    """Returns all base information about an artifact

    Parameters
    ----------
    user_id : str
        user making the request
    artifact_id : int or str coercable to int
        Atrtifact to get information for

    Returns
    -------
    dict of objects
        A dictionary containing the artifact information
        {'status': status,
         'message': message,
         'artifact': {info key: val, ...}}
    """
    artifact_id = int(artifact_id)
    artifact = Artifact(artifact_id)

    access_error = check_access(artifact.study.id, user_id)
    if access_error:
        return access_error

    can_submit_ebi = artifact.can_be_submitted_to_ebi
    ebi_run_accessions = (artifact.ebi_run_accessions
                          if can_submit_ebi else None)
    can_submit_vamps = artifact.can_be_submitted_to_vamps
    is_submitted_vamps = (artifact.is_submitted_to_vamps
                          if can_submit_vamps else False)

    return {'id': artifact_id,
            'timestamp': artifact.timestamp,
            'processing_parameters': artifact.processing_parameters,
            'visibility': artifact.visibility,
            'type': artifact.artifact_type,
            'data_type': artifact.data_type,
            'filepaths': artifact.filepaths,
            'parents': [a.id for a in artifact.parents],
            'study': artifact.study.id if artifact.study else None,
            'can_submit_ebi': can_submit_ebi,
            'ebi_run_accessions': ebi_run_accessions,
            'can_submit_vamps': can_submit_vamps,
            'is_submitted_vamps': is_submitted_vamps}
Example #55
0
def artifact_graph_get_req(artifact_id, direction, user_id):
    """Creates graphs of ancestor or descendant artifacts from given one

    Parameters
    ----------
    artifact_id : int
        Artifact ID to get graph for
    direction : {'ancestors', 'descendants'}
        What direction to get the graph in

    Returns
    -------
    dict of lists of tuples
        A dictionary containing the edge list representation of the graph,
        and the node labels. Formatted as:
        {'status': status,
         'message': message,
         'edge_list': [(0, 1), (0, 2)...],
         'node_labels': [(0, 'label0'), (1, 'label1'), ...]}

    Notes
    -----
    Nodes are identified by the corresponding Artifact ID.
    """
    access_error = check_access(Artifact(artifact_id).study.id, user_id)
    if access_error:
        return access_error

    if direction == 'descendants':
        G = Artifact(int(artifact_id)).descendants
    elif direction == 'ancestors':
        G = Artifact(int(artifact_id)).ancestors
    else:
        return {
            'status': 'error',
            'message': 'Unknown directon %s' % direction
        }

    node_labels = [(n.id, ' - '.join([n.name, n.artifact_type]))
                   for n in G.nodes()]
    return {'edge_list': [(n.id, m.id) for n, m in G.edges()],
            'node_labels': node_labels,
            'status': 'success',
            'message': ''}
Example #56
0
def sample_template_filepaths_get_req(study_id, user_id):
    """Returns all the filepaths attached to the sample template

    Parameters
    ----------
    study_id : int
        The current study object id
    user_id : str
        The current user object id

    Returns
    -------
    dict
        Filepaths in the form
        {'status': status,
         'message': msg,
         'filepaths': filepaths}
        status can be success, warning, or error depending on result
        message has the warnings or errors
        filepaths is a list of tuple of int and str
        All files in the sample template, as [(id, URL), ...]
    """
    exists = _check_sample_template_exists(int(study_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(study_id, user_id)
    if access_error:
        return access_error

    try:
        template = SampleTemplate(int(study_id))
    except QiitaDBUnknownIDError as e:
        return {'status': 'error',
                'message': str(e)}

    return {'status': 'success',
            'message': '',
            'filepaths': template.get_filepaths()
            }
Example #57
0
def sample_template_category_get_req(category, samp_id, user_id):
    """Returns dict of values for each sample in the given category

    Parameters
    ----------
    category : str
        Metadata category to get values for
    samp_id : int or str typecastable to int
        SampleTemplate id to get info for
    user_id : str
        User requesting the sample template info

    Returns
    -------
    dict
        Returns information in the form
        {'status': str,
         'message': str,
         'values': dict of {str: object}}
    """
    exists = _check_sample_template_exists(int(samp_id))
    if exists['status'] != 'success':
        return exists
    access_error = check_access(samp_id, user_id)
    if access_error:
        return access_error

    st = SampleTemplate(int(samp_id))
    try:
        values = st.get_category(category)
    except QiitaDBColumnError:
        return {'status': 'error',
                'message': 'Category %s does not exist in sample template' %
                category}
    return {'status': 'success',
            'message': '',
            'values': values}