def update_sample_association(account_id, source_id, sample_id, body,
                              token_info):
    _validate_account_access(token_info, account_id)

    # TODO: API layer doesn't understand that BadRequest can be thrown,
    #  but that looks to be the right result if sample_site bad.
    #  Need to update the api layer if we want to specify 400s.
    #  (Or we leave api as is and say 400's can always be thrown if your
    #  request is bad)
    with Transaction() as t:
        sample_repo = SampleRepo(t)
        source_repo = SourceRepo(t)

        source = source_repo.get_source(account_id, source_id)
        if source is None:
            return jsonify(code=404, message="No such source"), 404

        needs_sample_site = source.source_type in [
            Source.SOURCE_TYPE_HUMAN, Source.SOURCE_TYPE_ANIMAL
        ]

        precludes_sample_site = source.source_type == \
            Source.SOURCE_TYPE_ENVIRONMENT

        sample_site_present = "sample_site" in body and \
                              body["sample_site"] is not None

        if needs_sample_site and not sample_site_present:
            # Human/Animal sources require sample_site to be set
            raise BadRequest("human/animal samples require sample_site")
        if precludes_sample_site and sample_site_present:
            raise BadRequest("environmental samples cannot specify "
                             "sample_site")

        sample_datetime = body['sample_datetime']
        try:
            sample_datetime = fromisotime(sample_datetime)
        except ValueError:
            raise BadRequest("Invalid sample_datetime")
        curdate = datetime.now(sample_datetime.tzinfo)
        lower_limit = curdate + relativedelta(years=-10)
        upper_limit = curdate + relativedelta(months=+1)
        if sample_datetime < lower_limit or sample_datetime > upper_limit:
            raise BadRequest('Invalid sample date')
        # sample_site will not be present if its environmental. this will
        # default to None if the key is not present
        sample_site = body.get('sample_site')
        sample_info = SampleInfo(sample_id, sample_datetime, sample_site,
                                 body["sample_notes"])

        is_admin = token_grants_admin_access(token_info)
        sample_repo.update_info(account_id,
                                source_id,
                                sample_info,
                                override_locked=is_admin)

        final_sample = sample_repo.get_sample(account_id, source_id, sample_id)
        t.commit()
    return jsonify(final_sample), 200
Example #2
0
def read_sample_association(account_id, source_id, sample_id, token_info):
    _validate_account_access(token_info, account_id)

    with Transaction() as t:
        sample_repo = SampleRepo(t)
        sample = sample_repo.get_sample(account_id, source_id, sample_id)
        if sample is None:
            return jsonify(code=404, message="Sample not found"), 404

        return jsonify(sample.to_api()), 200
    def dissociate_answered_survey_from_sample(self, account_id, source_id,
                                               sample_id, survey_id):
        sample_repo = SampleRepo(self._transaction)

        if not self._acct_source_owns_survey(account_id, source_id, survey_id):
            raise werkzeug.exceptions.NotFound("No survey ID: %s" % survey_id)

        s = sample_repo.get_sample(account_id, source_id, sample_id)

        if s is None:
            raise werkzeug.exceptions.NotFound("No sample ID: %s" % sample_id)

        with self._transaction.cursor() as cur:
            cur.execute(
                "DELETE FROM source_barcodes_surveys "
                "WHERE "
                "barcode = %s AND "
                "survey_id = %s", (s.barcode, survey_id))
            # Also delete from vioscreen, myfoodrepo and polyphenol registries
            cur.execute(
                "UPDATE vioscreen_registry "
                "SET deleted=true "
                "WHERE "
                "account_id = %s AND "
                "source_id = %s AND "
                "sample_id = %s AND "
                "vio_id = %s", (account_id, source_id, sample_id, survey_id))
            cur.execute(
                "UPDATE myfoodrepo_registry "
                "SET deleted=true "
                "WHERE "
                "account_id = %s AND "
                "source_id = %s AND "
                "myfoodrepo_id = %s", (account_id, source_id, survey_id))
            try:
                uuid.UUID(survey_id)
                cur.execute(
                    "UPDATE polyphenol_ffq_registry "
                    "SET deleted = true "
                    "WHERE "
                    "account_id = %s AND "
                    "source_id = %s AND "
                    "polyphenol_ffq_id = %s",
                    (account_id, source_id, survey_id))
            except ValueError:
                # Note: we don't care about the error, just means it's not
                # the Polyphenol FFQ
                pass
    def associate_answered_survey_with_sample(self, account_id, source_id,
                                              sample_id, survey_id):
        sample_repo = SampleRepo(self._transaction)

        if not self._acct_owns_survey(account_id, survey_id):
            raise werkzeug.exceptions.NotFound("No survey ID: %s" % survey_id)

        s = sample_repo.get_sample(account_id, source_id, sample_id)

        if s is None:
            raise werkzeug.exceptions.NotFound("No sample ID: %s" % sample_id)

        with self._transaction.cursor() as cur:
            cur.execute("INSERT INTO source_barcodes_surveys "
                        "(barcode, survey_id) "
                        "VALUES(%s, %s)", (s.barcode, survey_id))
    def dissociate_answered_survey_from_sample(self, account_id, source_id,
                                               sample_id, survey_id):
        sample_repo = SampleRepo(self._transaction)

        if not self._acct_source_owns_survey(account_id, source_id, survey_id):
            raise werkzeug.exceptions.NotFound("No survey ID: %s" % survey_id)

        s = sample_repo.get_sample(account_id, source_id, sample_id)

        if s is None:
            raise werkzeug.exceptions.NotFound("No sample ID: %s" % sample_id)

        with self._transaction.cursor() as cur:
            cur.execute(
                "DELETE FROM source_barcodes_surveys "
                "WHERE "
                "barcode = %s AND "
                "survey_id = %s", (s.barcode, survey_id))
Example #6
0
    def list_answered_surveys_by_sample(self, account_id, source_id,
                                        sample_id):
        sample_repo = SampleRepo(self._transaction)

        # Note: Retrieving sample in this way validates permissions.
        sample = sample_repo.get_sample(account_id, source_id, sample_id)
        if sample is None:
            raise werkzeug.exceptions.NotFound("No sample ID: %s" % sample.id)

        with self._transaction.cursor() as cur:
            cur.execute(
                "SELECT "
                "survey_id "
                "FROM "
                "ag_kit_barcodes "
                "LEFT JOIN source_barcodes_surveys "
                "USING (barcode)"
                "WHERE "
                "ag_kit_barcode_id = %s", (sample_id, ))
            rows = cur.fetchall()
            answered_surveys = [r[0] for r in rows if r[0] is not None]
        return answered_surveys
def read_sample_association(account_id, source_id, sample_id, token_info):
    _validate_account_access(token_info, account_id)

    with Transaction() as t:
        sample_repo = SampleRepo(t)
        sample = sample_repo.get_sample(account_id, source_id, sample_id)
        if sample is None:
            return jsonify(code=404, message="Sample not found"), 404

    qiita_body = {'sample_ids': ["10317." + str(sample.barcode)]}

    try:
        qiita_data = qclient.post('/api/v1/study/10317/samples/status',
                                  json=qiita_body)
        accession_urls = []
        for barcode_info in qiita_data:
            experiment_accession = barcode_info.get("ebi_experiment_accession")
            if experiment_accession is None:
                continue
            accession_urls.append("https://www.ebi.ac.uk/ena/browser/view/" +
                                  experiment_accession + "?show=reads")
        sample.set_accession_urls(accession_urls)
    except NotFoundError:
        # I guess qiita doesn't know about this barcode,
        # so probably no ebi accession info
        pass
    except BadRequestError:
        # How do I log these to gunicorn??
        app.logger.warning("Couldn't communicate with qiita", exc_info=True)
    except ForbiddenError:
        # How do I log these to gunicorn??
        app.logger.warning("Couldn't communicate with qiita", exc_info=True)
    except RuntimeError:
        # How do I log these to gunicorn??
        app.logger.warning("Couldn't communicate with qiita", exc_info=True)
        raise

    return jsonify(sample.to_api()),
    def associate_answered_survey_with_sample(self, account_id, source_id,
                                              sample_id, survey_id):
        sample_repo = SampleRepo(self._transaction)

        if not self._acct_owns_survey(account_id, survey_id):
            raise werkzeug.exceptions.NotFound("No survey ID: %s" % survey_id)

        s = sample_repo.get_sample(account_id, source_id, sample_id)

        if s is None:
            raise werkzeug.exceptions.NotFound("No sample ID: %s" % sample_id)

        # Switching to insert if not exists semantics since vioscreen IDs will
        # be associated with samples prior to being filled out.
        with self._transaction.cursor() as cur:
            cur.execute(
                "SELECT * FROM source_barcodes_surveys "
                "WHERE barcode=%s AND survey_id=%s", (s.barcode, survey_id))
            if cur.fetchone() is None:
                cur.execute(
                    "INSERT INTO source_barcodes_surveys "
                    "(barcode, survey_id) "
                    "VALUES(%s, %s)", (s.barcode, survey_id))