Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotation api #65

Merged
merged 20 commits into from Mar 3, 2017
Merged

Annotation api #65

merged 20 commits into from Mar 3, 2017

Conversation

ir4y
Copy link
Collaborator

@ir4y ir4y commented Feb 16, 2017

No description provided.

@ir4y ir4y requested a review from Suor February 16, 2017 05:51
samples = data['series'].samples.all()

gsm_to_id = {s.gsm_name.upper(): s.id for s in samples}
id_to_gsm = {v: k for k, v in gsm_to_id.iteritems()}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove support for ids, only work with gsms. Do not play with case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also funcy.flip() function for this. But you won't need this code at all )

raise serializers.ValidationError(unicode(err))

tagged_samples_ids = set(values.keys())
all_samples_ids = set(data['series'].samples.values_list('id', flat=True))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally unneeded query. Use samples from above. Or use .values_list() above.

@@ -2,24 +2,28 @@

from cacheops import cached_as
from django.http import JsonResponse, HttpResponse
from funcy import walk_keys
from django.db import transaction
from funcy import walk_keys, first
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return empty line.

series = serializer.validated_data['series']
tag = serializer.validated_data['tag']

series_tag = first(SeriesTag.objects.filter(series=series, tag=tag))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Django's QuerySet.first().

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also specify .order_by('id'), now this code is unstable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also MAJOR error not filtering by platform here. SeriesTag is defined by these 3 things: serie, platform, tag. And filter by is_active=True.

tags/models.py Outdated
@@ -83,6 +83,8 @@ class SeriesTag(models.Model):
# (with whatever previous one, not necessarily initial)
agreed = models.IntegerField(blank=True, null=True)
fleiss_kappa = models.FloatField(blank=True, null=True)
comment = models.CharField(max_length=512, blank=True, null=True)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be TextField. Never use CharField when you are not sure about max length.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And change "comment" -> "note".

data = serializer.validated_data

with transaction.atomic():
old_annotation = first(SeriesTag.objects.filter(series=data['series'], tag=data['tag']))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • use QuerySet.first() and .order_by('id').

Note that while we allow tag several platforms at once in UI, I don't want to allow that in API.

Also this code should be in save_annotation() not duplicated here.

tags/misc.py Outdated
@@ -0,0 +1,61 @@
from funcy import group_by
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to annotate_core.py

tags/misc.py Outdated
sa.fill_samples(sample_tags)


def save_validation(user_id, series_tag, data, from_api=False):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorporate user_id and series_tag_id into data, same with save_annotation().

Do not query series_tag. Use serie_id, platform_id and tag_id passed from user/API.

tags/misc.py Outdated
series_id=series_tag.series_id,
platform_id=series_tag.platform_id, tag_id=series_tag.tag_id,
from_api=from_api, comment=data['comment'],
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be simple project(data, [...]).

raise ValidationError(
{'non_field_errors': ["You can't validate your own annotation"]})

res, err = save_validation(user_id, series_tag, serializer.validated_data, True)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You get orphan ValidationJob here, clean it up.

ir4y added 8 commits March 2, 2017 12:55
Use GSM for consistency calculation.
Use id instead of objects as annotate_core functions params
Use exceptons instead of function pair result
on_demand_validate is now usung save_validation from annotate_core
@ir4y ir4y merged commit 576bcaa into master Mar 3, 2017
@ir4y
Copy link
Collaborator Author

ir4y commented Mar 3, 2017

Hi @iDrDex
We have released sample annotations API.

You can create sample annotations by POST query to the http://stargeo.org/api/sample_annotations/ endpoint.

Also, you need to sign your request with the token. You can find token at the header of swagger docs http://stargeo.org/docs/

The example of annotation

{
  "series": "GSE77818",
  "platform": "GPL10787",
  "tag": 22,
  "note": "This annotation was created bu API request",
  "annotations": {
    "GSM2060029": "1",
    "GSM2060030": "1",
    "GSM2060031": "1",
    "GSM2060032": "1",
    "GSM2060033": "1",
    "GSM2060034": "1",
    "GSM2060035": "1",
    "GSM2060036": "1"
  }
}

It is an example how you can send annotation with curl

curl -H "Content-Type: application/json" -H "Authorization: Token XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" -X POST -d '{
  "series": "GSE77818",
  "platform": "GPL10787",
  "tag": 22,
  "note": "This annotation was created bu API request",
  "annotations": {
    "GSM2060029": "1",
    "GSM2060030": "1",
    "GSM2060031": "1",
    "GSM2060032": "1",
    "GSM2060033": "1",
    "GSM2060034": "1",
    "GSM2060035": "1",
    "GSM2060036": "1"
  }
}'  http://stargeo.org/api/sample_annotations/

It is an example how you can send annotation with requests

In [1]: import requests

In [2]: data = {
   ...:   "series": "GSE77818",
   ...:   "platform": "GPL10787",
   ...:   "tag": 22,
   ...:   "note": "ololol",
   ...:   "annotations": {
   ...:     "GSM2060029": "1",
   ...:     "GSM2060030": "1",
   ...:     "GSM2060031": "1",
   ...:     "GSM2060032": "1",
   ...:     "GSM2060033": "1",
   ...:     "GSM2060034": "1",
   ...:     "GSM2060035": "1",
   ...:     "GSM2060036": "1"
   ...:   }
   ...: }

In [3]: headers = {'Content-Type': 'application/json', 'Authorization': 'Token XXXXXXXXXX
   ...: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'}

In [4]: requests.post('http://stargeo.org/api/sample_annotations/', data=data, header
   ...: s=headers)

@iDrDex
Copy link
Owner

iDrDex commented Mar 3, 2017

Awesome. Thx!

@iDrDex
Copy link
Owner

iDrDex commented Apr 30, 2017

@ir4y this code fails with <Response [400]>:

import requests

data = {
    "series": "GSE77818",
    "platform": "GPL10787",
    "tag": 22,
    "note": "ololol",
    "annotations": {
        "GSM2060029": "1",
        "GSM2060030": "1",
        "GSM2060031": "1",
        "GSM2060032": "1",
        "GSM2060033": "1",
        "GSM2060034": "1",
        "GSM2060035": "1",
        "GSM2060036": "1"
    }
}

headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Token XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}

print requests.post(
    'http://stargeo.org/api/sample_annotations/', 
    data=data,
    headers=headers
)

@ir4y
Copy link
Collaborator Author

ir4y commented Apr 30, 2017

Hi @iDrDex !

The token is a confidential information.
With this token anybody can perform actions from your name. Please don't share it at public posts anymore.
I have revoked it, so you need to get a new one from http://stargeo.org/docs/
Please don't share it at public posts, you can provide me a user name and I will get a token from the database.

@ir4y
Copy link
Collaborator Author

ir4y commented Apr 30, 2017

About the issue.

There was an issue with my code sample.
You need to dump python dict to JSON before sending a request.

res = requests.post(
    'http://stargeo.org/api/sample_annotations/', 
    data=json.dumps(data),
    headers=headers
)

FYI
The res object contains all information about response, including error message in case of error.

print(res.status_code, res.content)

@iDrDex
Copy link
Owner

iDrDex commented Apr 30, 2017

Awesome. Thx @ir4y. I can definitely push annotations now. However, the counter on the home page does not reflect the API pushes. Can we fix that?

@ir4y
Copy link
Collaborator Author

ir4y commented May 1, 2017

@iDrDex
You need to wait for a while.
Updating home page counters run periodically.

@ir4y ir4y deleted the annotation-api branch July 25, 2017 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants