예제 #1
0
def sample_template_checks(study_id, user, check_exists=False):
    """Performs different checks and raises errors if any of the checks fail

    Parameters
    ----------
    study_id : int
        The study id
    user : qiita_db.user.User
        The user trying to access the study
    check_exists : bool, optional
        If true, check if the sample template exists

    Raises
    ------
    HTTPError
        404 if the study does not exist
        403 if the user does not have access to the study
        404 if check_exists == True and the sample template doesn't exist
    """
    try:
        study = Study(int(study_id))
    except QiitaDBUnknownIDError:
        raise HTTPError(404, reason='Study does not exist')
    if not study.has_access(user):
        raise HTTPError(403, reason='User does not have access to study')

    # Check if the sample template exists
    if check_exists and not SampleTemplate.exists(study_id):
        raise HTTPError(404,
                        reason="Study %s doesn't have sample information" %
                        study_id)
예제 #2
0
def sample_template_checks(study_id, user, check_exists=False):
    """Performs different checks and raises errors if any of the checks fail

    Parameters
    ----------
    study_id : int
        The study id
    user : qiita_db.user.User
        The user trying to access the study
    check_exists : bool, optional
        If true, check if the sample template exists

    Raises
    ------
    HTTPError
        404 if the study does not exist
        403 if the user does not have access to the study
        404 if check_exists == True and the sample template doesn't exist
    """
    try:
        study = Study(int(study_id))
    except QiitaDBUnknownIDError:
        raise HTTPError(404, reason='Study does not exist')
    if not study.has_access(user):
        raise HTTPError(403, reason='User does not have access to study')

    # Check if the sample template exists
    if check_exists and not SampleTemplate.exists(study_id):
        raise HTTPError(404, reason="Study %s doesn't have sample information"
                        % study_id)
예제 #3
0
def sample_template_overview_handler_get_request(study_id, user):
    # Check if the current user has access to the sample template
    sample_template_checks(study_id, user)

    # Check if the sample template exists
    exists = SampleTemplate.exists(study_id)

    # The following information should always be provided:
    # The files that have been uploaded to the system and can be a
    # sample template file
    files = [
        f for _, f in get_files_from_uploads_folders(study_id)
        if f.endswith(('txt', 'tsv'))
    ]
    # If there is a job associated with the sample information, the job id
    job = None
    job_info = r_client.get(SAMPLE_TEMPLATE_KEY_FORMAT % study_id)
    if job_info:
        job = loads(job_info)['job_id']

    # Specific information if it exists or not:
    data_types = []
    st_fp_id = None
    old_files = []
    num_samples = 0
    num_cols = 0
    if exists:
        # If it exists we need to provide:
        # The id of the sample template file so the user can download it and
        # the list of old filepaths
        st = SampleTemplate(study_id)
        all_st_files = st.get_filepaths()
        # The current sample template file is the first one in the list
        # (pop(0)) and we are interested only in the id ([0])
        st_fp_id = all_st_files.pop(0)[0]
        # For the old filepaths we are only interested in their basename
        old_files = [basename(fp) for _, fp in all_st_files]
        # The number of samples - this is a space efficient way of counting
        # the number of samples. Doing len(list(st.keys())) creates a list
        # that we are not using
        num_samples = sum(1 for _ in st.keys())
        # The number of columns
        num_cols = len(st.categories())
    else:
        # It doesn't exist, we also need to provide the data_types in case
        # the user uploads a QIIME mapping file
        data_types = sorted(data_types_get_req()['data_types'])

    return {
        'exists': exists,
        'uploaded_files': files,
        'data_types': data_types,
        'user_can_edit': Study(study_id).can_edit(user),
        'job': job,
        'download_id': st_fp_id,
        'old_files': old_files,
        'num_samples': num_samples,
        'num_columns': num_cols
    }
예제 #4
0
def sample_template_overview_handler_get_request(study_id, user):
    # Check if the current user has access to the sample template
    sample_template_checks(study_id, user)

    # Check if the sample template exists
    exists = SampleTemplate.exists(study_id)

    # The following information should always be provided:
    # The files that have been uploaded to the system and can be a
    # sample template file
    files = [f for _, f, _ in get_files_from_uploads_folders(study_id)
             if f.endswith(('txt', 'tsv', 'xlsx'))]
    # If there is a job associated with the sample information, the job id
    job = None
    job_info = r_client.get(SAMPLE_TEMPLATE_KEY_FORMAT % study_id)
    if job_info:
        job = loads(job_info)['job_id']

    # Specific information if it exists or not:
    data_types = []
    st_fp_id = None
    old_files = []
    num_samples = 0
    num_cols = 0
    if exists:
        # If it exists we need to provide:
        # The id of the sample template file so the user can download it and
        # the list of old filepaths
        st = SampleTemplate(study_id)
        all_st_files = st.get_filepaths()
        # The current sample template file is the first one in the list
        # (pop(0)) and we are interested only in the id ([0])
        st_fp_id = all_st_files.pop(0)[0]
        # For the old filepaths we are only interested in their basename
        old_files = [basename(fp) for _, fp in all_st_files]
        # The number of samples - this is a space efficient way of counting
        # the number of samples. Doing len(list(st.keys())) creates a list
        # that we are not using
        num_samples = sum(1 for _ in st.keys())
        # The number of columns
        num_cols = len(st.categories())
    else:
        # It doesn't exist, we also need to provide the data_types in case
        # the user uploads a QIIME mapping file
        data_types = sorted(data_types_get_req()['data_types'])

    return {'exists': exists,
            'uploaded_files': files,
            'data_types': data_types,
            'user_can_edit': Study(study_id).can_edit(user),
            'job': job,
            'download_id': st_fp_id,
            'old_files': old_files,
            'num_samples': num_samples,
            'num_columns': num_cols}
예제 #5
0
    def tearDown(self):
        for fp in self._clean_up_files:
            if exists(fp):
                remove(fp)

        study_id = self.new_study.id
        for pt in self.new_study.prep_templates():
            PrepTemplate.delete(pt.id)
        if SampleTemplate.exists(study_id):
            SampleTemplate.delete(study_id)
        Study.delete(study_id)
예제 #6
0
    def tearDown(self):
        for fp in self._clean_up_files:
            if exists(fp):
                remove(fp)

        study_id = self.new_study.id
        for pt in self.new_study.prep_templates():
            PrepTemplate.delete(pt.id)
        if SampleTemplate.exists(study_id):
            SampleTemplate.delete(study_id)
        Study.delete(study_id)
예제 #7
0
    def display_template(self,
                         study,
                         user,
                         msg,
                         msg_level,
                         full_access,
                         top_tab=None,
                         sub_tab=None,
                         prep_tab=None):
        """Simple function to avoid duplication of code"""
        study_status = study.status
        user_level = user.level
        sample_template_exists = SampleTemplate.exists(study.id)

        if sample_template_exists:
            st = SampleTemplate(study.id)
            missing_cols = st.check_restrictions(
                [SAMPLE_TEMPLATE_COLUMNS['qiita_main']])
            allow_approval = len(missing_cols) == 0
            approval_deny_msg = (
                "Processed data approval request is disabled due to missing "
                "columns in the sample template: %s" % ', '.join(missing_cols))
        else:
            allow_approval = False
            approval_deny_msg = ""

        # The general information of the study can be changed if the study is
        # not public or if the user is an admin, in which case they can always
        # modify the information of the study
        show_edit_btn = study_status != 'public' or user_level == 'admin'

        # Make the error message suitable for html
        msg = msg.replace('\n', "<br/>")

        self.render('study_description.html',
                    message=msg,
                    level=msg_level,
                    study=study,
                    study_title=study.title,
                    study_alias=study.info['study_alias'],
                    show_edit_btn=show_edit_btn,
                    show_data_tabs=sample_template_exists,
                    full_access=full_access,
                    allow_approval=allow_approval,
                    approval_deny_msg=approval_deny_msg,
                    top_tab=top_tab,
                    sub_tab=sub_tab,
                    prep_tab=prep_tab)
예제 #8
0
    def test_delete_sample_template(self):
        # Error case
        job = self._create_job('delete_sample_template', {'study': 1})
        private_task(job.id)
        self.assertEqual(job.status, 'error')
        self.assertIn(
            "Sample template cannot be erased because there are "
            "prep templates associated", job.log.msg)

        # Success case
        info = {
            "timeseries_type_id": '1',
            "metadata_complete": 'true',
            "mixs_compliant": 'true',
            "number_samples_collected": 25,
            "number_samples_promised": 28,
            "study_alias": "TDST",
            "study_description": "Test delete sample template",
            "study_abstract": "Test delete sample template",
            "principal_investigator_id": StudyPerson(1)
        }
        study = Study.create(User('*****@*****.**'),
                             "Delete Sample Template test", info)
        metadata = pd.DataFrame.from_dict(
            {
                'Sample1': {
                    'physical_specimen_location': 'location1',
                    'physical_specimen_remaining': 'true',
                    'dna_extracted': 'true',
                    'sample_type': 'type1',
                    'collection_timestamp': '2014-05-29 12:24:15',
                    'host_subject_id': 'NotIdentified',
                    'Description': 'Test Sample 1',
                    'latitude': '42.42',
                    'longitude': '41.41',
                    'taxon_id': '9606',
                    'scientific_name': 'h**o sapiens'
                }
            },
            orient='index',
            dtype=str)
        SampleTemplate.create(metadata, study)

        job = self._create_job('delete_sample_template', {'study': study.id})
        private_task(job.id)
        self.assertEqual(job.status, 'success')
        self.assertFalse(SampleTemplate.exists(study.id))
예제 #9
0
def _check_sample_template_exists(samp_id):
    """Make sure a sample template exists in the system

    Parameters
    ----------
    samp_id : int or str castable to int
        SampleTemplate id to check

    Returns
    -------
    dict
        {'status': status,
         'message': msg}
    """
    if not SampleTemplate.exists(int(samp_id)):
        return {'status': 'error',
                'message': 'Sample template %d does not exist' % int(samp_id)
                }
    return {'status': 'success',
            'message': ''}
예제 #10
0
def _check_sample_template_exists(samp_id):
    """Make sure a sample template exists in the system

    Parameters
    ----------
    samp_id : int or str castable to int
        SampleTemplate id to check

    Returns
    -------
    dict
        {'status': status,
         'message': msg}
    """
    if not SampleTemplate.exists(int(samp_id)):
        return {
            'status': 'error',
            'message': 'Sample template %d does not exist' % int(samp_id)
        }
    return {'status': 'success', 'message': ''}
예제 #11
0
    def display_template(self, study, user, msg, msg_level, full_access,
                         top_tab=None, sub_tab=None, prep_tab=None):
        """Simple function to avoid duplication of code"""
        study_status = study.status
        user_level = user.level
        sample_template_exists = SampleTemplate.exists(study.id)

        if sample_template_exists:
            st = SampleTemplate(study.id)
            missing_cols = st.check_restrictions(
                [SAMPLE_TEMPLATE_COLUMNS['qiita_main']])
            allow_approval = len(missing_cols) == 0
            approval_deny_msg = (
                "Processed data approval request is disabled due to missing "
                "columns in the sample template: %s" % ', '.join(missing_cols))
        else:
            allow_approval = False
            approval_deny_msg = ""

        # The general information of the study can be changed if the study is
        # not public or if the user is an admin, in which case they can always
        # modify the information of the study
        show_edit_btn = study_status != 'public' or user_level == 'admin'

        # Make the error message suitable for html
        msg = msg.replace('\n', "<br/>")

        self.render('study_description.html',
                    message=msg,
                    level=msg_level,
                    study=study,
                    study_title=study.title,
                    study_alias=study.info['study_alias'],
                    show_edit_btn=show_edit_btn,
                    show_data_tabs=sample_template_exists,
                    full_access=full_access,
                    allow_approval=allow_approval,
                    approval_deny_msg=approval_deny_msg,
                    top_tab=top_tab,
                    sub_tab=sub_tab,
                    prep_tab=prep_tab)
예제 #12
0
    def test_delete_sample_template(self):
        # Error case
        job = self._create_job('delete_sample_template', {'study': 1})
        private_task(job.id)
        self.assertEqual(job.status, 'error')
        self.assertIn("Sample template cannot be erased because there are "
                      "prep templates associated", job.log.msg)

        # Success case
        info = {"timeseries_type_id": '1',
                "metadata_complete": 'true',
                "mixs_compliant": 'true',
                "number_samples_collected": 25,
                "number_samples_promised": 28,
                "study_alias": "TDST",
                "study_description": "Test delete sample template",
                "study_abstract": "Test delete sample template",
                "principal_investigator_id": StudyPerson(1)}
        study = Study.create(User('*****@*****.**'),
                             "Delete Sample Template test", info)
        metadata = pd.DataFrame.from_dict(
            {'Sample1': {'physical_specimen_location': 'location1',
                         'physical_specimen_remaining': 'true',
                         'dna_extracted': 'true',
                         'sample_type': 'type1',
                         'collection_timestamp': '2014-05-29 12:24:15',
                         'host_subject_id': 'NotIdentified',
                         'Description': 'Test Sample 1',
                         'latitude': '42.42',
                         'longitude': '41.41',
                         'taxon_id': '9606',
                         'scientific_name': 'h**o sapiens'}},
            orient='index', dtype=str)
        SampleTemplate.create(metadata, study)

        job = self._create_job('delete_sample_template', {'study': study.id})
        private_task(job.id)
        self.assertEqual(job.status, 'success')
        self.assertFalse(SampleTemplate.exists(study.id))
예제 #13
0
    def render(self, study):
        study_info = study.info
        id = study.id
        abstract = study_info['study_abstract']
        description = study_info['study_description']
        publications = []
        for doi, pmid in study.publications:
            if doi is not None:
                publications.append(doi_linkifier([doi]))
            if pmid is not None:
                publications.append(pubmed_linkifier([pmid]))
        publications = ", ".join(publications)
        princ_inv = StudyPerson(study_info['principal_investigator_id'])
        pi_link = study_person_linkifier((princ_inv.email, princ_inv.name))
        number_samples_promised = study_info['number_samples_promised']
        number_samples_collected = study_info['number_samples_collected']
        metadata_complete = study_info['metadata_complete']

        data_types = sorted(viewitems(get_data_types()), key=itemgetter(1))

        # Retrieve the files from the uploads folder, so the user can choose
        # the sample template of the study. Filter them to only include the
        # ones that ends with 'txt' or 'tsv'.
        files = [
            f for _, f in get_files_from_uploads_folders(str(study.id))
            if f.endswith(('txt', 'tsv'))
        ]

        # If the sample template exists, retrieve all its filepaths
        if SampleTemplate.exists(study.id):
            sample_templates = SampleTemplate(study.id).get_filepaths()
        else:
            # If the sample template does not exist, just pass an empty list
            sample_templates = []

        # Check if the request came from a local source
        is_local_request = is_localhost(self.request.headers['host'])

        # The user can choose the sample template only if the study is
        # sandboxed or the current user is an admin
        show_select_sample = (study.status == 'sandbox'
                              or self.current_user.level == 'admin')

        # EBI information
        ebi_status = study.ebi_submission_status
        ebi_accession = study.ebi_study_accession
        if ebi_accession:
            ebi_accession = (EBI_LINKIFIER.format(ebi_accession))

        return self.render_string(
            "study_description_templates/study_information_tab.html",
            abstract=abstract,
            description=description,
            id=id,
            publications=publications,
            principal_investigator=pi_link,
            number_samples_promised=number_samples_promised,
            number_samples_collected=number_samples_collected,
            metadata_complete=metadata_complete,
            show_select_sample=show_select_sample,
            files=files,
            study_id=study.id,
            sample_templates=sample_templates,
            is_local_request=is_local_request,
            data_types=data_types,
            ebi_status=ebi_status,
            ebi_accession=ebi_accession)
    def render(self, study):
        study_info = study.info
        id = study.id
        abstract = study_info['study_abstract']
        description = study_info['study_description']
        publications = []
        for doi, pmid in study.publications:
            if doi is not None:
                publications.append(doi_linkifier([doi]))
            if pmid is not None:
                publications.append(pubmed_linkifier([pmid]))
        publications = ", ".join(publications)
        princ_inv = StudyPerson(study_info['principal_investigator_id'])
        pi_link = study_person_linkifier((princ_inv.email, princ_inv.name))
        number_samples_promised = study_info['number_samples_promised']
        number_samples_collected = study_info['number_samples_collected']
        metadata_complete = study_info['metadata_complete']

        data_types = sorted(viewitems(get_data_types()), key=itemgetter(1))

        # Retrieve the files from the uploads folder, so the user can choose
        # the sample template of the study. Filter them to only include the
        # ones that ends with 'txt' or 'tsv'.
        files = [f for _, f in get_files_from_uploads_folders(str(study.id))
                 if f.endswith(('txt', 'tsv'))]

        # If the sample template exists, retrieve all its filepaths
        if SampleTemplate.exists(study.id):
            sample_templates = SampleTemplate(study.id).get_filepaths()
        else:
            # If the sample template does not exist, just pass an empty list
            sample_templates = []

        # Check if the request came from a local source
        is_local_request = is_localhost(self.request.headers['host'])

        # The user can choose the sample template only if the study is
        # sandboxed or the current user is an admin
        show_select_sample = (
            study.status == 'sandbox' or self.current_user.level == 'admin')

        # Ebi information
        ebi_status = study.ebi_submission_status
        ebi_accession = study.ebi_study_accession
        if ebi_accession:
            ebi_accession = (EBI_LINKIFIER.format(ebi_accession))

        return self.render_string(
            "study_description_templates/study_information_tab.html",
            abstract=abstract,
            description=description,
            id=id,
            publications=publications,
            principal_investigator=pi_link,
            number_samples_promised=number_samples_promised,
            number_samples_collected=number_samples_collected,
            metadata_complete=metadata_complete,
            show_select_sample=show_select_sample,
            files=files,
            study_id=study.id,
            sample_templates=sample_templates,
            is_local_request=is_local_request,
            data_types=data_types,
            ebi_status=ebi_status,
            ebi_accession=ebi_accession)