def list_fragments(request): """Return metadata of all fragments owned by a user""" try: frags = Gene.objects.filter(owner=request.user) except ObjectDoesNotExist: return JsonResponse('Could not read fragments', ERROR) ret = [] for f in frags: ret.append(read_meta(f)) return JsonResponse(ret)
def part_import(request): """API to import a part via AJAX""" if request.method == 'GET' and 'part' in request.GET: name = request.GET.get('part', '') try: part = Part(name) record = part.to_seq_record() Gene.add(record, 'BB', request.user) except Exception, e: return JsonResponse(e.message, ERROR) return JsonResponse('ok')
def set_features(request, fid): """Save a fragment's features""" if request.method == 'POST': try: g = get_gene(request.user, fid) feats = request.POST.get('features') if feats: write_features(g, feats) return JsonResponse('Done') return JsonResponse('No features provided', ERROR) except ObjectDoesNotExist: JsonResponse("Fragment with ID='%s' does not exist" % fid, ERROR) raise Http404
def get_fragment(request, fid): """Return a small amount of information about the fragment""" try: fid = int(fid) except ValueError: return JsonResponse("Invalid fragment id: %s" % fid, ERROR) g = get_gene(request.user, fid) return JsonResponse({ 'id': fid, 'name': g.name, 'desc': g.description, 'length': g.length(), })
def get_sequence(request, fid): """Stream the sequence in blocks of 1kB by default""" try: chunk_size = int(request.GET.get('chunk_size', 1024)) except ValueError: return JsonResponse("ERROR: Invalid chunk_size '%s'." % request.GET.get('chunk_size', 1024), ERROR) pad_char = request.GET.get('pad_char', ' ') g = get_gene(request.user, fid) if g: resp = HttpResponse(chunk_sequence(g, chunk_size, pad_char), mimetype="text/plain") return resp return JsonResponse('Could Not Stream Sequence', ERROR)
def entrez_summary(request): """ Handle JSON Entrez summary request""" if request.method == 'GET' and 'id' in request.GET: id = request.GET['id'] db = request.GET.get('database', 'nucleotide') #assume nucleotide by default #fetch summary information for the id handle = Entrez.esummary(db=db, id=id) record = Entrez.read(handle) if record is None or len(record) < 1: return JsonResponse("Error: Could not get summary information for id '%s'" % id, ERROR) return JsonResponse(record[0]); raise Http404
def fragment_remove(request, cid): con = get_construct(request.user, cid) #post = json.loads(request.raw_post_data) cfid = request.POST.get('cfid') if not cfid: return JsonResponse('No ConstructFragment ID specified', ERROR) if con: try: con.delete_cfragment(cfid) except ObjectDoesNotExist as e: return JsonResponse('No such fragment "%s" associated with construct "%s".' % (cfid, cid)) return JsonResponse('OK'); else: return JsonResponse('No such Construct ' + cid, ERROR)
def fragment_clipping(request, cid, cfid): con = get_construct(request.user, cid) if con: try: cf = con.cf.get(id=cfid) except: return JsonResponse('Could not find ConstructFragment(%s)' % cfid, ERROR) t = loader.get_template('gibson/fragment_clipping.html') d = { 'feature_list': cf.fragment.features.all(), 'cfid': cfid, 'from_absolute': not cf.start_is_relative(), 'to_absolute': not cf.end_is_relative(), 'length': cf.fragment.length(), 'max': cf.fragment.length() - 1, } if cf.start_is_relative(): d['start_feat'] = cf.start_feature.id d['start_offset'] = cf.start_offset if cf.end_is_relative(): d['end_feat'] = cf.end_feature.id d['end_offset'] = cf.end_offset c = RequestContext(request, d) return HttpResponse(t.render(c)) raise Http404
def manual_add(request): """Add a fragment manually""" if request.method == 'GET': meta = MetaForm(request.GET) seq = SequenceForm(request.GET) if meta.is_valid() and seq.is_valid(): record = SeqRecord( seq.cleaned_data['seq'], name=meta.cleaned_data['name'], id=meta.cleaned_data['name'], description=meta.cleaned_data['desc']) Gene.add(record, 'MN', request.user) return JsonResponse('OK'); #figure out what the errors where errors = meta.errors errors.update(seq.errors) return JsonResponse(errors, ERROR) raise Http404
def get_features(request, fid): """Get a fragment's features""" g = get_gene(request.user, fid) return JsonResponse({ 'feats': read_features(g), 'alpha': get_alphabet(), 'length': len(g.sequence), })
def construct_delete(request, cid): con = get_construct(request.user, cid) if con: con.delete() if request.is_ajax(): return JsonResponse('/gibthon') return HttpResponseRedirect('/gibthon') else: return HttpResponseNotFound()
def entrez_search(request): """ Handle JSON Entrez search request""" if request.method == 'GET':# and request.is_ajax(): query = request.GET.get('query', ''); db = request.GET.get('database', 'nucleotide') #assume nucleotide by default if query != '' and query != None: #fetch a list of Ids which match handle = Entrez.esearch(db=db, term=query) record = Entrez.read(handle) ids = record['IdList'] if len(ids) == 0: return JsonResponse("No results for search '%s' on database '%s'." % (query, db), ERROR) else: return JsonResponse(ids) else: return JsonResponse("Error: Blank search query", ERROR); raise Http404
def save_settings(request, cid): print 'update_settings request.method = %s' % request.method if request.method == 'POST': con = get_construct(request.user, cid) if not con: return JsonResponse({ 'errors': { 'all':"Construct with id '%s' not found", },} % cid, ERROR) form = SettingsForm(request.POST, instance=con.settings) if form.is_valid(): form.save() con.reset() data = {} for key,value in form.cleaned_data.items(): data[key] = str(value); return JsonResponse({'modified': con.last_modified(), 'fields': data}) return JsonResponse({'errors': form.errors,}, ERROR) raise Http404
def construct_add(request): if request.method == 'POST': rp = fix_request(request.POST) form = ConstructForm(rp) if form.is_valid(): c = form.save() c.owner = request.user c.save() return JsonResponse({ 'url': '/gibthon/%s/' % c.id, }) t = loader.get_template('gibson/constructform.html') con = Construct.objects.all().filter(owner=request.user) c = RequestContext(request, { 'construct_form': form, }) return JsonResponse({ 'html': t.render(c), }, ERROR) else: return HttpResponseNotFound()
def set_meta(request, fid): """Update a fragment's metadata""" if request.method == 'POST': try: g = get_gene(request.user, fid) meta = {'name': request.POST.get('name'), 'desc': request.POST.get('desc'), } meta['annots'] = [] for i in range(0, len(request.POST) -2): m = request.POST.getlist('annots[%s][]'%i) if m: meta['annots'].append(m) print 'meta = %s' % meta if meta: write_meta(g, meta) return get_meta(request, fid) return JsonResponse("No metadata supplied.", ERROR) except ObjectDoesNotExist: return JsonResponse("Fragment with ID='%s' does not exist." % fid, ERROR) raise Http404
def entrez_import(request): """Handle a request to import an ID""" if request.method == 'GET' and 'id' in request.GET: id = request.GET['id'] db = request.GET.get('database', 'nucleotide') #assume nucleotide by default handle = Entrez.efetch(db=db, id=id, rettype="gb") records = SeqIO.parse(handle, 'gb') for r in records: if len(Gene.objects.filter(name=r.name, owner=request.user)) == 0: Gene.add(r, 'NT', request.user) return JsonResponse("Imported id '%s' from Entrez." % id) raise Http404
def save_order(request, cid): con = get_construct(request.user, cid) cfid = request.POST.getlist('cfid[]') direction = request.POST.getlist('direction[]') if not cfid: return JsonResponse('No cfids provided.', ERROR) if not direction: return JsonResponse('No directions provided', ERROR) if len(cfid) != len(con.cf.all()): return JsonResponse('Only %s ConstructFragments provided, %s required.' % (len(cfid), len(con.cf.all())), ERROR) if len(direction) != len(con.cf.all()): return JsonResponse('Only %s directions provided, %s required.' % (len(direction), len(con.cf.all())), ERROR) if con: dirs = [] for d in direction: dirs.append(directions.get(d, ' ')) con.reorder_cfragments(cfid, dirs) return JsonResponse({'modified': con.last_modified(),}); else: return HttpResponseNotFound()
def get_info(request, cid): """Get information about a construct""" try: c = get_construct(request.user, cid) cfs = [] fs = [] for cf in c.cf.all(): cfs.append(cf2dict(cf)); g = get_gene(request.user, cf.fragment.id) fs.append(read_meta(g)) ret = { 'id': cid, 'name': c.name, 'desc': c.description, 'length': c.length(), 'cfs': cfs, 'fs': fs, 'created': c.last_modified(), } return JsonResponse(ret) except ObjectDoesNotExist: return JsonResponse('Construct %s not found.' % s, ERROR) raise Http404
def save_meta(request, cid): """ Save a construct's metadata Post Data, all optional name, desc """ if request.method == 'POST': con = get_construct(request.user, cid) if not con: return JsonResponse({'errors': {'all': "Construct with id '%s' not found" % cid,}}, ERROR) name = request.POST.get('name', con.name) desc = request.POST.get('desc', con.description) if (name != con.name) or (desc != con.description): con.name = name con.description = desc try: con.save() except Exception as e: return JsonResponse('One or more fields are too long.', ERROR) return JsonResponse({'modified': con.last_modified(), 'fields': {'name': con.name, 'desc': con.description}}); raise Http404
def construct_fragment(request, cid): con = get_construct(request.user, cid) if con and not request.is_ajax(): t = loader.get_template('gibson/constructfragment.html') cf_list = con.cf.all() feature_list = [FeatureListForm(cf, con) for cf in cf_list] list = zip(cf_list, feature_list) c = RequestContext(request, {'list': list}) return HttpResponse(t.render(c)) if con and request.is_ajax(): cf_list = con.cf.all() frag_list = [{ 'fid': cf.fragment.id, 'cfid': cf.id, 'name': cf.fragment.name, 'desc': cf.fragment.description, 'length': abs(cf.end() - cf.start()), } for cf in cf_list] return JsonResponse(frag_list) return HttpResponseNotFound()
def fragment_add(request, cid): con = get_construct(request.user, cid) if con: fid = request.POST.get('fid') if not fid: return JsonResponse("No fragment id provided", ERROR) f = get_fragment(request.user, fid) pos = request.POST.get('pos', 0); strand = request.POST.get('dir', 1); try: pos = int(pos) except ValueError as e: return JsonResponse('Position must be an integer, not "%s"' % pos, ERROR) try: strand = int(strand) except ValueError as e: return JsonResponse('Direction must be an integer, not "%s"' % strand, ERROR) if strand not in [-1, 1]: return JsonResponse('Strand must be 1 or -1, not "%s"' %strand, ERROR) direction = 'f' if strand == -1: direction = 'r' if f: cf = con.add_fragment(f, pos, direction) if cf: return JsonResponse(cf2dict(cf)) else: return JsonResponse('Could not add fragment %s to construct %s' % (fid, cid), ERROR) else: if request.is_ajax(): return JsonResponse('Could not find fragment "%s"' % fid, ERROR) return HttpResponseNotFound() else: return HttpResponseNotFound()
def apply_clipping(request, cid, cfid): con = get_construct(request.user, cid) if con: try: cf = con.cf.get(id=cfid) except: return JsonResponse('Could not find ConstructFragment(%s)' % cfid, ERROR) try: f_type = request.POST['from_type'].lower() t_type = request.POST['to_type'].lower() if f_type == 'absolute': start = int(request.POST['from_abs']) if start < 0 or start > cf.fragment.length() - 1: raise ValueError('"start" must be within range [0:%i]' % cf.fragment.length() - 1) if cf.start_offset != start or cf.start_feature != None: cf.start_offset = start cf.start_feature = None con.processed = False elif f_type == 'relative': start = int(request.POST['from_rel']) start_fid = int(request.POST['start_feat']) print "available ids are %s" % [ feat.id for feat in cf.fragment.features.all() ] start_feature = cf.fragment.features.get(id=start_fid) if cf.start_offset != start or cf.start_feature != start_feature: cf.start_offset = start cf.start_feature = start_feature con.processed = False else: raise ValueError('"f_type" must be "absolute" or "relative"') if t_type == 'absolute': end = int(request.POST['to_abs']) if end < 0 or end > cf.fragment.length() - 1: raise ValueError('"end" must be within range [0:%i]' % cf.fragment.length() - 1) if cf.end_offset != end or cf.end_feature != None: cf.end_offset = end cf.end_feature = None con.processed = False elif t_type == 'relative': end = int(request.POST['to_rel']) end_fid = int(request.POST['end_feat']) end_feature = cf.fragment.features.get(id=end_fid) if cf.end_offset != end or cf.end_feature != end_feature: cf.end_offset = end cf.end_feature = end_feature con.processed = False else: raise ValueError('"t_type" must be "absolute" or "relative"') except KeyError as e: return JsonResponse('Value required for "%s"' % e.message, ERROR) except ValueError as e: return JsonResponse('ValueError: %s' % e.message, ERROR) except ObjectDoesNotExist as e: return JsonResponse( 'DoesNotExist: %s (%s)' % (e.message, start_fid), ERROR) cf.save() con.save() return JsonResponse('OK') raise Http404
def get_meta(request, fid): """get a particular fragment's metadata""" g = get_gene(request.user, fid) return JsonResponse( read_meta(g))
def crop(request, fid): """crop the fragment as specified""" try: fid = int(fid) except ValueError: return JsonResponse("Invalid fragment id: %s" % fid, ERROR) g = get_gene(request.user, fid) if not g: return JsonResponse('Could not get fragment %s'%fid, ERROR) try: start = int(request.POST.get('start')) end = int(request.POST.get('end')) except ValueError: return JsonResponse('Start and end must be valid integers', ERROR) try: f_internal = bool(int(request.POST.get('f_internal', 1))) f_all = bool(int(request.POST.get('f_all', 0))) except ValueError: return JsonResponse('f_internal and f_all must be 1 or 0', ERROR) if f_all and not f_internal: return JsonResponse( 'Cannot keep all features without keeping internal ones', ERROR) result = request.POST.get('result', 'new') if result not in ['new', 'overwrite']: return JsonResponse( 'Result type must be \'new\' or \'overwrite\', not %s' % result, ERROR) new_name = request.POST.get('new_name') new_desc = request.POST.get('new_desc') if (result == 'new') and not new_name: return JsonResponse( 'Must specify non-empty new_name when result type is new', ERROR) #build a list of features we want to keep feats = [] if f_internal: for f in g.features.all(): #internal features if (f.start >= start) and (f.end <= end): feats.append(f) elif f_all: if ( ((f.start > start) and (f.start < end)) or #starts in selection ((f.end < end) and (f.end > start)) or #ends in selection ((f.start < start) and (f.end > end)) ): #selection is subset feats.append(f) #get or make the target gene if result == 'new': target = Gene(owner=request.user, name=new_name, description=new_desc, sequence=g.sequence[start:end]) target.save() #copy references for r in g.references.all(): nr = Reference(gene=target, title=r.title, authors=r.authors, journal=r.journal, medline_id=r.medline_id, pubmed_id=r.pubmed_id) nr.save() #copy annotations for a in g.annotations.all(): na = Annotation(gene=target, key=a.key, value=a.value) na.save() elif result == 'overwrite': target = g g.sequence = g.sequence[start:end] #clear out old features Feature.remove(g) #copy the features for adding onto the new fragment for f in feats: nf = Feature(gene=target, type=f.type, direction=f.direction, start=max(f.start - start, 0), end=min(f.end - start, end - start)) nf.save() target.save() return JsonResponse(target.id)