1 '''
2 Whole-cell knowledge base views
3
4 Author: Jonathan Karr, jkarr@stanford.edu
5 Affiliation: Covert Lab, Department of Bioengineering, Stanford University
6 Last updated: 2012-07-17
7 '''
8
9 from copy import deepcopy
10 from django.contrib.auth import login as auth_login, logout as auth_logout
11 from django.contrib.auth.decorators import login_required
12 from django.contrib.auth.forms import AuthenticationForm
13 from django.contrib.auth.models import User
14 from django.core.exceptions import ValidationError, ObjectDoesNotExist
15 from django.core.urlresolvers import reverse
16 from django.db.models import Count, Sum, Avg
17 from django.db.models.fields import BooleanField, NullBooleanField, AutoField, BigIntegerField, DecimalField, FloatField, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, SmallIntegerField
18 from django.db.models.fields.related import OneToOneField, RelatedObject, ManyToManyField, ForeignKey
19 from django.db.models.query import EmptyQuerySet
20 from django.http import Http404, HttpResponse, HttpResponseRedirect
21 from django.shortcuts import get_object_or_404
22 from django.utils.text import capfirst
23 from django.views.decorators.debug import sensitive_post_parameters
24 from django.views.decorators.cache import never_cache
25 from django.views.decorators.csrf import csrf_protect
26 from haystack.query import SearchQuerySet
27 from itertools import chain
28 from public import models
29 from public.forms import ExportDataForm, ImportDataForm
30 from public.helpers import getEntry, format_field_detail_view, objectToQuerySet, render_queryset_to_response, getObjectTypes, getModel, get_invalid_objects, get_edit_form_fields, get_edit_form_data
31 from public.helpers import validate_object_fields, validate_model_objects, validate_model_unique, save_object_data, batch_import_from_excel, readFasta
32 from public.helpers import PropertyDefinitionFilter, PygmentsStyle, PygmentsFormatter
33 from public.models import Entry, Parameter, Reference, Species, SpeciesComponent, ModelProperty, SimulationProperty
34 import pygments
35 from pygments.lexers import MatlabLexer
36 from pygments.token import Token
37 from urlparse import urlparse
38 import numpy
39 import os
40 import settings
41 import tempfile
42
43 MODEL_CODE_BASE_DIR = '/home/projects/WholeCell/simulation'
44
45 -def index(request, species_wid=None):
46 if species_wid is not None and species_wid != '':
47 species = Species.objects.get(wid=species_wid)
48 else:
49 species = Species.objects.all()
50 if len(species) > 0:
51 species = species[0]
52 else:
53 species = None
54 content = []
55 if species is not None:
56 content.append([
57 [0, 'Compartments', models.Compartment.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Compartment'})],
58 ])
59
60 chrs = models.Chromosome.objects.filter(species__id = species.id)
61 chrcontent = chrs.aggregate(length=Sum('length'));
62 try:
63 gc_content = sum([chr.get_gc_content() * chr.length for chr in chrs]) / chrcontent['length']
64 except TypeError, e:
65 gc_content = 0
66 content.append([
67 [0, 'Chromosomes', chrs.count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Chromosome'})],
68 [1, 'Length', chrcontent['length'], 'nt'],
69 [1, 'GC-content', ('%0.1f' % (gc_content * 100)), '%'],
70 ])
71
72 tus = models.TranscriptionUnit.objects.filter(species__id = species.id).annotate(num_genes = Count('genes'))
73 mons = tus.filter(num_genes__lte = 1)
74 nPolys = tus.filter(num_genes__gt = 1).count()
75 content.append([
76 [0, 'Transcription units', tus.count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'TranscriptionUnit'})],
77 [1, 'Monocistrons', tus.count() - nPolys],
78 [1, 'Polycistrons', nPolys],
79 ])
80
81 content.append([
82 [0, 'Genes', models.Gene.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Gene'})],
83 [1, 'mRNA', models.Gene.objects.filter(species__id = species.id, type__wid='mRNA').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Gene'}) + '?type=mRNA'],
84 [1, 'rRNA', models.Gene.objects.filter(species__id = species.id, type__wid='rRNA').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Gene'}) + '?type=rRNA'],
85 [1, 'sRNA', models.Gene.objects.filter(species__id = species.id, type__wid='sRNA').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Gene'}) + '?type=sRNA'],
86 [1, 'tRNA', models.Gene.objects.filter(species__id = species.id, type__wid='tRNA').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Gene'}) + '?type=tRNA'],
87 ])
88
89 content.append([
90 [0, 'Chromosome features',
91 models.ChromosomeFeature.objects.filter(species__id = species.id).count(),
92 None,
93 reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'ChromosomeFeature'}),
94 ],
95 [1, 'DnaA boxes',
96 models.ChromosomeFeature.objects.filter(species__id = species.id, type__parent__wid='ChromosomeFeature-DnaA_box').count(),
97 ],
98 [1, 'Short tandem repeats',
99 models.ChromosomeFeature.objects.filter(species__id = species.id, type__parent__wid='ChromosomeFeature-Short_Tandem_Repeat').count(),
100 ],
101 [1, 'Other',
102 models.ChromosomeFeature.objects.filter(species__id = species.id).exclude(type__parent__wid='ChromosomeFeature-DnaA_box').exclude(type__parent__wid='ChromosomeFeature-Short_Tandem_Repeat').count()],
103 ])
104
105 content.append([
106 [0, 'Metabolites', models.Metabolite.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Metabolite'})],
107 [1, 'Amino acids',
108 models.Metabolite.objects.filter(species__id = species.id, type__wid='amino_acid').count() +
109 models.Metabolite.objects.filter(species__id = species.id, type__wid='modified_amino_acid').count() +
110 models.Metabolite.objects.filter(species__id = species.id, type__wid='non-standard_amino_acid').count() +
111 models.Metabolite.objects.filter(species__id = species.id, type__wid='vitamin_non-standard_amino_acid').count()
112 ],
113 [1, 'Antibiotic',
114 models.Metabolite.objects.filter(species__id = species.id, type__wid='antibiotic').count() +
115 models.Metabolite.objects.filter(species__id = species.id, type__parent__wid='antibiotic').count()
116 ],
117 [1, 'Gases',
118 models.Metabolite.objects.filter(species__id = species.id, type__wid='gas').count() +
119 models.Metabolite.objects.filter(species__id = species.id, type__parent__wid='gas').count()
120 ],
121 [1, 'Ions',
122 models.Metabolite.objects.filter(species__id = species.id, type__wid='ion').count() +
123 models.Metabolite.objects.filter(species__id = species.id, type__parent__wid='ion').count()
124 ],
125 [1, 'Lipids',
126 models.Metabolite.objects.filter(species__id = species.id, type__wid='lipid').count() +
127 models.Metabolite.objects.filter(species__id = species.id, type__parent__wid='lipid').count() +
128 models.Metabolite.objects.filter(species__id = species.id, type__parent__parent__wid='lipid').count()
129 ],
130 [1, 'Vitamins',
131 models.Metabolite.objects.filter(species__id = species.id, type__wid='vitamin').count() +
132 models.Metabolite.objects.filter(species__id = species.id, type__parent__wid='vitamin').count()
133 ],
134 ])
135
136 mons = models.ProteinMonomer.objects.filter(species__id = species.id)
137 cpxs = models.ProteinComplex.objects.filter(species__id = species.id)
138 monDNABind = mons.filter(dna_footprint__length__gt=0).count()
139 monIntMem = mons.filter(localization__wid = 'm').exclude(signal_sequence__type = 'lipoprotein').count() + mons.filter(localization__wid = 'tm').exclude(signal_sequence__type = 'lipoprotein').count()
140 monLipo = mons.filter(signal_sequence__type = 'lipoprotein').count()
141 monSecreted = mons.filter(signal_sequence__type = 'secretory').count()
142 monTermOrg = mons.filter(localization__wid = 'tc').count() + mons.filter(localization__wid = 'tm').count()
143 cpxDNABind = cpxs.filter(dna_footprint__length__gt=0).count()
144 content.append([
145 [0, 'Proteins', mons.count() + cpxs.count()],
146 [1, 'Monomers', mons.count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'ProteinMonomer'})],
147 [2, 'DNA-binding', monDNABind],
148 [2, 'Integral membrane', monIntMem],
149 [2, 'Lipoprotein', monLipo, None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'ProteinMonomer'}) + '?signal_sequence__type=lipoprotein'],
150 [2, 'Secreted', monSecreted, None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'ProteinMonomer'}) + '?signal_sequence__type=secretory'],
151 [2, 'Terminal organelle', monTermOrg],
152 [1, 'Complexes', cpxs.count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'ProteinComplex'})],
153 [2, 'DNA-binding', cpxDNABind],
154 ])
155
156 rxns = models.Reaction.objects.filter(species__id = species.id)
157 content.append([
158 [0, 'Reactions', rxns.count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'})],
159 [1, 'DNA damage', rxns.filter(processes__wid='Process_DNADamage').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_DNADamage'],
160 [1, 'DNA repair', rxns.filter(processes__wid='Process_DNARepair').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_DNARepair'],
161 [1, 'Metabolic', rxns.filter(processes__wid='Process_Metabolism').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_Metabolism'],
162 [1, 'Protein decay', rxns.filter(processes__wid='Process_ProteinDecay').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_ProteinDecay'],
163 [1, 'Protein modification', rxns.filter(processes__wid='Process_ProteinModification').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_ProteinModification'],
164 [1, 'Replication Initiation', rxns.filter(processes__wid='Process_ReplicationInitiation').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_ReplicationInitiation'],
165 [1, 'RNA decay', rxns.filter(processes__wid='Process_RNADecay').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_RNADecay'],
166 [1, 'RNA modification', rxns.filter(processes__wid='Process_RNAModification').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_RNAModification'],
167 [1, 'RNA processing', rxns.filter(processes__wid='Process_RNAProcessing').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_RNAProcessing'],
168 [1, 'Transcription', rxns.filter(processes__wid='Process_Transcription').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_Transcription'],
169 [1, 'Translation', rxns.filter(processes__wid='Process_Translation').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_Translation'],
170 [1, 'tRNA aminoacylation', rxns.filter(processes__wid='Process_tRNAAminoacylation').count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Reaction'}) + '?processes=Process_tRNAAminoacylation'],
171 [1, 'Other', rxns.exclude(processes__wid='Process_DNADamage')
172 .exclude(processes__wid='Process_DNARepair')
173 .exclude(processes__wid='Process_Metabolism')
174 .exclude(processes__wid='Process_ProteinDecay')
175 .exclude(processes__wid='Process_ProteinModification')
176 .exclude(processes__wid='Process_ReplicationInitiation')
177 .exclude(processes__wid='Process_RNADecay')
178 .exclude(processes__wid='Process_RNAModification')
179 .exclude(processes__wid='Process_RNAProcessing')
180 .exclude(processes__wid='Process_Transcription')
181 .exclude(processes__wid='Process_Translation')
182 .exclude(processes__wid='Process_tRNAAminoacylation')
183 .count()],
184 ])
185
186 tr = models.TranscriptionalRegulation.objects.filter(species__id = species.id)
187 nTus = len(set([x[0] for x in tr.values_list('transcription_unit')]))
188 nTfs = len(set([x[0] for x in tr.values_list('transcription_factor')]))
189 content.append([
190 [0, 'Transcriptional regulation'],
191 [1, 'Interactions', tr.count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'TranscriptionalRegulation'})],
192 [1, 'Transcriptional regulators', nTfs],
193 [1, 'Regulated promoters', nTus],
194 ])
195
196 content.append([
197 [0, 'Pathways', models.Pathway.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Pathway'})],
198 ])
199 content.append([
200 [0, 'Stimuli', models.Stimulus.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Stimulus'})],
201 ])
202
203
204 nCellComp = models.Metabolite.objects.filter(species__id = species.id, biomass_composition__concentration__isnull=False).count()
205 nMediaComp = models.Metabolite.objects.filter(species__id = species.id, media_composition__concentration__isnull=False).count()
206 nKineticsKeq = models.Reaction.objects.filter(species__id = species.id, keq__isnull=False).count()
207 nKineticsKm = \
208 models.Reaction.objects.filter(species__id = species.id, kinetics_forward__km__isnull=False).count() + \
209 models.Reaction.objects.filter(species__id = species.id, kinetics_backward__km__isnull=False).count()
210 nKineticsVmax = \
211 models.Reaction.objects.filter(species__id = species.id, kinetics_forward__vmax__isnull=False).count() + \
212 models.Reaction.objects.filter(species__id = species.id, kinetics_backward__vmax__isnull=False).count()
213 nRnaExp = models.Gene.objects.filter(species__id = species.id, expression__isnull=False).count()
214 nRnaHl = models.Gene.objects.filter(species__id = species.id, half_life__isnull=False).count()
215 nStimuli = models.Stimulus.objects.filter(species__id = species.id, value__isnull=False).count()
216 nTrAffinity = models.TranscriptionalRegulation.objects.filter(species__id = species.id, affinity__isnull=False).count()
217 nTrActivity = models.TranscriptionalRegulation.objects.filter(species__id = species.id, activity__isnull=False).count()
218 nOther = models.Parameter.objects.filter(species__id = species.id).count()
219 nTotParameters = nCellComp + nMediaComp + nKineticsVmax + nRnaExp + nRnaHl + nStimuli + nTrAffinity + nTrActivity + nOther
220
221 content.append([
222 [0, 'Quantitative parameters', nTotParameters],
223 [1, 'Cell composition', nCellComp],
224 [1, 'Media composition', nMediaComp],
225 [1, 'Reaction K<sub>eq</sub>', nKineticsKeq],
226 [1, 'Reaction K<sub>m</sub>', nKineticsKm],
227 [1, 'Reaction V<sub>max</sub>', nKineticsVmax],
228 [1, 'RNA expression', nRnaExp],
229 [1, 'RNA half-lives', nRnaHl],
230 [1, 'Stimulus values', nStimuli],
231 [1, 'Transcr. reg. activity', nTrAffinity],
232 [1, 'Transcr. reg. affinity', nTrActivity],
233 [1, 'Other', nOther, None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Parameter'})],
234 ])
235
236 content.append([
237 [0, 'Processes', models.Process.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'Process'})],
238 ])
239
240 content.append([
241 [0, 'States', models.State.objects.filter(species__id = species.id).count(), None, reverse('public.views.list', kwargs={'species_wid': species.wid, 'model_type': 'State'})],
242 ])
243
244 nContent = [len(x) for x in content]
245 totContent = sum(nContent)
246 cum = 0
247 idx = 0
248 breakIdxs = [0, 0]
249 for x in nContent:
250 cum += x
251 idx += 1
252 if cum > totContent * 1/ 3 and breakIdxs[0] == 0:
253 breakIdxs[0] = idx
254 if cum > totContent * 2 / 3 and breakIdxs[1] == 0:
255 breakIdxs[1] = idx
256
257 contentCol1 = []
258 contentCol2 = []
259 contentCol3 = []
260 i = 0
261 for x in content[:breakIdxs[0]]:
262 i += 1
263 for y in x:
264 contentCol1.append([i] + y)
265 i = 0
266 for x in content[breakIdxs[0]:breakIdxs[1]]:
267 i += 1
268 for y in x:
269 contentCol2.append([i] + y)
270 i = 0
271 for x in content[breakIdxs[1]:]:
272 i += 1
273 for y in x:
274 contentCol3.append([i] + y)
275
276 sources = {
277 'total': 0,
278 'types': [],
279 'dates': [],
280 'evidence_parameters': [],
281 'evidence_species': [],
282 'evidence_media': [],
283 'evidence_pH': [],
284 'evidence_temperature': [],
285 }
286 if species is not None:
287 refs = models.Reference.objects.filter(species__id = species.id)
288 sources['total'] = refs.count()
289 sources['types'] = [
290 {'type': 'Articles', 'count': refs.filter(species__id = species.id, type__wid='article').count()},
291 {'type': 'Books', 'count': refs.filter(species__id = species.id, type__wid='book').count()},
292 {'type': 'Thesis', 'count': refs.filter(species__id = species.id, type__wid='thesis').count()},
293 {'type': 'Other', 'count': refs.filter(species__id = species.id, type__wid='misc').count()},
294 ]
295 sources['dates'] = refs.filter(year__isnull=False).order_by('year').values('year').annotate(count=Count('year'))
296
297
298 nEstimated = models.Parameter.objects.filter(species__id = species.id, value__evidence__is_experimentally_constrained=False).count()
299 nExpConstrained = nTotParameters - nEstimated
300 sources['evidence_parameters'] = [
301 {'type': 'Experimentally constrained', 'count': nExpConstrained},
302 {'type': 'Computationally estimated', 'count': nEstimated},
303 ]
304
305
306 sources['evidence_species'] = models.Evidence.objects.filter(species_component__species__id = species.id).values('species').annotate(count = Count('id'))
307 sources['evidence_media'] = models.Evidence.objects.filter(species_component__species__id = species.id).values('media').annotate(count = Count('id'))
308 sources['evidence_pH'] = models.Evidence.objects.filter(species_component__species__id = species.id).values('pH').annotate(count = Count('id'))
309 sources['evidence_temperature'] = models.Evidence.objects.filter(species_component__species__id = species.id).values('temperature').annotate(count = Count('id'))
310
311 return render_queryset_to_response(
312 request = request,
313 species_wid = species_wid,
314 data = {
315 'content': [contentCol1, contentCol2, contentCol3],
316 'contentRows': range(max(len(contentCol1), len(contentCol2), len(contentCol3))),
317 'sources': sources,
318 },
319 templateFile = 'public/index.html')
320
321 -def about(request, species_wid=None):
330
331 -def tutorial(request, species_wid=None):
336
337 @login_required
338 -def contributors(request, species_wid=None):
346
347 @login_required
348 -def contributor(request, username, species_wid=None):
356
357 -def search(request, species_wid = None):
365
367
368 if species_wid is None:
369 species_wid = Species.objects.all()[0].wid
370 results = SearchQuerySet().filter(species_wid=species_wid).filter(content=query)
371
372
373 facets = results.facet('model_type')
374 tmp = facets.facet_counts()['fields']['model_type']
375 modelNameFacet = []
376 objectTypes = getObjectTypes(is_public=request.user.is_anonymous())
377 models = []
378 for tmp2 in tmp:
379 modelName = objectTypes[objectTypes.index(tmp2[0])]
380 modelNameFacet.append({
381 'name':modelName,
382 'verbose_name': getModel(modelName)._meta.verbose_name,
383 'count':tmp2[1],
384 })
385 models.append(getModel(modelName))
386 modelNameFacet.sort(lambda x, y:cmp(x['verbose_name'], y['verbose_name']))
387
388
389 model_type = request.GET.get('model_type', '')
390 if model_type:
391 results = results.models(getModel(model_type))
392
393
394 results = results.order_by('wid')
395
396
397 queryset = EmptyQuerySet()
398 for object in results:
399 tmp = object.model.objects.none()
400 tmp._result_cache.append(object.object)
401 queryset = chain(queryset, tmp)
402
403
404 return render_queryset_to_response(
405 species_wid = species_wid,
406 request = request,
407 models = models,
408 queryset = queryset,
409 templateFile = 'public/search.html',
410 data = {
411 'query': query,
412 'engine': 'haystack',
413 'model_type': model_type,
414 'modelNameFacet': modelNameFacet,
415 })
416
426
427 -def list(request, species_wid, model_type):
428 try:
429 getObjectTypes(is_public=request.user.is_anonymous()).index(model_type)
430 except ValueError:
431 raise Http404
432
433 species = Species.objects.get(wid=species_wid)
434 model = getModel(model_type)
435 objects = model.objects.all().filter(species__id=species.id)
436
437 facet_fields = []
438 for field_full_name in model._meta.facet_fields:
439
440 field_names = str(field_full_name).split('__')
441 tmp_model = model
442 field_verbose_name = []
443 for field_name in field_names:
444 field = tmp_model._meta.get_field_by_name(field_name)[0]
445 field_verbose_name.append(field.verbose_name)
446 if isinstance(field, (ForeignKey, ManyToManyField)):
447 tmp_model = field.rel.to
448 field_verbose_name = ' › '.join(field_verbose_name)
449
450 if isinstance(field, (ForeignKey, ManyToManyField)) and not issubclass(field.rel.to, Entry):
451 continue
452
453 if isinstance(field, (ForeignKey, ManyToManyField)):
454 tmp = model.objects.filter(species__id=species.id).order_by(field_full_name + '__name').values(field_full_name).annotate(count=Count(field_full_name))
455 else:
456 tmp = model.objects.filter(species__id=species.id).order_by(field_full_name).values(field_full_name).annotate(count=Count(field_full_name))
457 facets = []
458 for facet in tmp:
459 value = facet[field_full_name]
460 if value is None or unicode(value) == '':
461 continue
462
463 if isinstance(field, (ForeignKey, ManyToManyField)):
464 tmp2 = tmp_model.objects.values('wid', 'name').get(id=value)
465 id = tmp2['wid']
466 name = capfirst(tmp2['name'])
467 elif (field.choices is not None) and (len(field.choices) > 0) and (not isinstance(field, (BooleanField, NullBooleanField))):
468 id = value
469 choices = [x[0] for x in field.choices]
470 if id in choices:
471 name = field.choices[choices.index(id)][1]
472 else:
473 name = capfirst(value)
474 else:
475 id = value
476 name = capfirst(value)
477 if value is not None and unicode(value) != '':
478 facets.append({
479 'id': unicode(id),
480 'name': unicode(name),
481 'count': facet['count']})
482 if len(facets) > 1:
483 facet_fields.append({
484 'name': field_full_name,
485 'verbose_name': field_verbose_name,
486 'facets': facets,
487 })
488
489
490 val = request.GET.get(field_full_name)
491 if val:
492 if isinstance(field, (ForeignKey, ManyToManyField)):
493 kwargs = {field_full_name + '__wid': val}
494 elif isinstance(field, (BooleanField, NullBooleanField)):
495 kwargs = {field_full_name: val == 'True'}
496 elif isinstance(field, (AutoField, BigIntegerField, DecimalField, FloatField, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, SmallIntegerField)):
497 kwargs = {field_full_name: float(val)}
498 else:
499 kwargs = {field_full_name: val}
500 objects = objects.filter(**kwargs)
501
502 return render_queryset_to_response(
503 species_wid = species_wid,
504 request = request,
505 models = [model],
506 queryset = objects,
507 templateFile = 'public/list.html',
508 data = {
509 'model_type': model_type,
510 'model_verbose_name': model._meta.verbose_name,
511 'model_verbose_name_plural': model._meta.verbose_name_plural,
512 'facet_fields': facet_fields,
513 })
514
515 -def detail(request, species_wid, wid):
516 obj = getEntry(species_wid = species_wid, wid = wid)
517 if obj is None:
518 raise Http404
519
520 model = obj.__class__
521 model_type = model.__name__
522 fieldsets = deepcopy(model._meta.fieldsets)
523
524
525 fieldset_names = [x[0] for x in fieldsets]
526 if 'Type' in fieldset_names:
527 idx = fieldset_names.index('Type')
528 del fieldsets[idx]
529
530
531 rmfieldsets = []
532 for idx in range(len(fieldsets)):
533 rmfields = []
534 for idx2 in range(len(fieldsets[idx][1]['fields'])):
535 if isinstance(fieldsets[idx][1]['fields'][idx2], dict):
536 field = fieldsets[idx][1]['fields'][idx2]
537 field_name = field['name']
538 verbose_name = field['verbose_name']
539 else:
540 field_name = fieldsets[idx][1]['fields'][idx2]
541 field = model._meta.get_field_by_name(field_name)[0]
542 if isinstance(field, RelatedObject):
543 verbose_name = capfirst(field.get_accessor_name())
544 else:
545 verbose_name = field.verbose_name
546
547 data = format_field_detail_view(obj, field_name, request.user.is_anonymous())
548 if (data is None) or (data == ''):
549 rmfields = [idx2] + rmfields
550
551 if issubclass(model, Parameter) and field_name == 'value':
552 is_modeled_url = reverse('public.views.viewParameterInSimulation', kwargs = {
553 'species_wid':species_wid,
554 'wid': wid,
555 })
556 elif (isinstance(field, (ForeignKey, ManyToManyField)) and issubclass(field.rel.to, Parameter)) or \
557 (isinstance(field, (RelatedObject)) and issubclass(field.model, Parameter)):
558 is_modeled_url = reverse('public.views.viewParametersInSimulation', kwargs = {
559 'species_wid':species_wid,
560 'wid': wid,
561 })
562 else:
563 try:
564 if ModelProperty.objects.get(species__wid = species_wid, class_name = model_type, property_name = field_name).simulation_properties.exists():
565 is_modeled_url = reverse('public.views.viewPropertyInSimulation', kwargs = {
566 'species_wid':species_wid,
567 'class_name': model_type,
568 'property_name': field_name,
569 })
570 except ObjectDoesNotExist:
571 is_modeled_url = ''
572
573 fieldsets[idx][1]['fields'][idx2] = {
574 'name': field_name,
575 'verbose_name': verbose_name.replace(" ", ' ').replace("-", "‑"),
576 'data': data,
577 'is_modeled_url': is_modeled_url,
578 }
579 for idx2 in rmfields:
580 del fieldsets[idx][1]['fields'][idx2]
581 if len(fieldsets[idx][1]['fields']) == 0:
582 rmfieldsets = [idx] + rmfieldsets
583 for idx in rmfieldsets:
584 del fieldsets[idx]
585
586
587 qs = objectToQuerySet(obj, model = model)
588
589
590 return render_queryset_to_response(
591 species_wid = species_wid,
592 request = request,
593 models = [model],
594 queryset = qs,
595 templateFile = 'public/detail.html',
596 data = {
597 'model_type': model_type,
598 'model': model,
599 'fieldsets': fieldsets,
600 'message': request.GET.get('message', ''),
601 })
602
604
605 model = getModel(class_name)
606
607
608 verbose_class_name = model._meta.verbose_name
609
610
611 verbose_property_name = property_name
612 for fieldset in model._meta.fieldsets:
613 for field in fieldset[1]['fields']:
614 if isinstance(field, (str, unicode)) and field == property_name:
615 tmp = model._meta.get_field_by_name(property_name)
616 if len(tmp) > 0:
617 verbose_property_name = tmp[0].verbose_name
618 if isinstance(field, dict) and field['name'] == property_name:
619 verbose_property_name = field['verbose_name']
620
621
622 qs = ModelProperty.objects.get(
623 species__wid = species_wid,
624 class_name = class_name,
625 property_name = property_name
626 ).simulation_properties.all().order_by('class_name', 'property_name')
627
628
629 classes = {}
630 for object in qs:
631 if not classes.has_key(object.class_name):
632 classes[object.class_name] = []
633 classes[object.class_name].append(object.property_name)
634
635
636 object_list = []
637 for sim_class_name in classes:
638 sim_property_names = classes[sim_class_name]
639 sim_property_names.sort()
640 pathParts = sim_class_name.split('.')
641 codePath = "%s/src/+%s/%s.m" % (MODEL_CODE_BASE_DIR, '/+'.join(pathParts[0:-1]), pathParts[-1])
642 if not os.path.isfile(codePath):
643 codePath = "%s/src/+%s/@%s/%s.m" % (MODEL_CODE_BASE_DIR, '/+'.join(pathParts[0:-1]), pathParts[-1], pathParts[-1])
644 if not os.path.isfile(codePath):
645 continue
646
647 with open (codePath, "r") as codeFile:
648 code = codeFile.read()
649
650 lexer = MatlabLexer()
651 lexer.add_filter(PropertyDefinitionFilter(property_names = sim_property_names, tokentype=Token.Name.Variable))
652
653 tokens = lexer.get_tokens(code)
654
655 object_list.append({
656 'class_name': sim_class_name,
657 'property_names': sim_property_names,
658 'code': pygments.format(tokens, PygmentsFormatter(linenos='inline', linenostep=1, style=PygmentsStyle, noclasses=True)),
659 })
660
661
662 return render_queryset_to_response(
663 species_wid = species_wid,
664 request = request,
665 models = [SimulationProperty],
666 queryset = qs,
667 templateFile = 'public/viewPropertyInSimulation.html',
668 data = {
669 'object_list': object_list,
670 'verbose_class_name': verbose_class_name,
671 'verbose_property_name': verbose_property_name,
672 })
673
675
676 qs = Parameter.objects.filter(species__wid = species_wid, wid=wid)
677 if not qs[0].state is None:
678 sim_class_name = 'edu.stanford.covert.cell.sim.state.%s' % qs[0].state.wid.replace('State_', '')
679 verbose_class_name = '%s: %s' % (wid, qs[0].state.name)
680 else:
681 sim_class_name = 'edu.stanford.covert.cell.sim.process.%s' % qs[0].process.wid.replace('Process_', '')
682 verbose_class_name = '%s: %s' % (wid, qs[0].process.name)
683 sim_property_name = qs[0].name
684 verbose_property_name = qs[0].name
685
686
687 pathParts = sim_class_name.split('.')
688 codePath = "%s/src/+%s/%s.m" % (MODEL_CODE_BASE_DIR, '/+'.join(pathParts[0:-1]), pathParts[-1])
689 if not os.path.isfile(codePath):
690 codePath = "%s/src/+%s/@%s/%s.m" % (MODEL_CODE_BASE_DIR, '/+'.join(pathParts[0:-1]), pathParts[-1], pathParts[-1])
691
692 if os.path.isfile(codePath):
693 with open (codePath, "r") as codeFile:
694 code = codeFile.read()
695
696 lexer = MatlabLexer()
697 lexer.add_filter(PropertyDefinitionFilter(property_names = [sim_property_name], tokentype=Token.Name.Variable))
698
699 tokens = lexer.get_tokens(code)
700
701 object = {
702 'class_name': sim_class_name,
703 'property_names': [sim_property_name],
704 'code': pygments.format(tokens, PygmentsFormatter(linenos='inline', linenostep=1, style=PygmentsStyle, noclasses=True)),
705 }
706 else:
707 raise Http404
708
709
710 return render_queryset_to_response(
711 species_wid = species_wid,
712 request = request,
713 models = [Parameter],
714 queryset = qs,
715 templateFile = 'public/viewPropertyInSimulation.html',
716 data = {
717 'object_list': [object],
718 'verbose_class_name': verbose_class_name,
719 'verbose_property_name': verbose_property_name,
720 })
721
723 obj = getEntry(species_wid = species_wid, wid = wid)
724 if obj is None:
725 raise Http404
726
727 model = obj.__class__
728 verbose_class_name = model._meta.verbose_name
729 verbose_property_name = '%s parameters' % obj.name
730
731
732 qs = EmptyQuerySet()
733 for field in model._meta.get_all_related_objects() + model._meta.get_all_related_many_to_many_objects():
734 accessor_name = field.get_accessor_name()
735 if accessor_name == '+':
736 continue
737
738 if isinstance(field, ForeignKey) and issubclass(field.rel.to, Parameter):
739 qs._result_cache.append(getattr(obj, accessor_name))
740 if (isinstance(field, ManyToManyField) and issubclass(field.rel.to, Parameter)) or \
741 (isinstance(field, RelatedObject) and issubclass(field.model, Parameter)):
742 qs2 = getattr(obj, accessor_name).all()
743 if len(qs2) > 0:
744 qs._result_cache.extend(qs2._result_cache)
745
746 classes = {}
747 for o in qs:
748 if not o.state is None:
749 sim_class_name = 'edu.stanford.covert.cell.sim.state.%s' % o.state.wid.replace('State_', '')
750 else:
751 sim_class_name = 'edu.stanford.covert.cell.sim.process.%s' % o.process.wid.replace('Process_', '')
752 if not classes.has_key(sim_class_name):
753 classes[sim_class_name] = []
754 classes[sim_class_name].append(o.name)
755
756
757 objects = []
758 for sim_class_name in classes:
759 sim_property_names = classes[sim_class_name]
760 sim_property_names.sort()
761 pathParts = sim_class_name.split('.')
762 codePath = "%s/src/+%s/%s.m" % (MODEL_CODE_BASE_DIR, '/+'.join(pathParts[0:-1]), pathParts[-1])
763 if not os.path.isfile(codePath):
764 codePath = "%s/src/+%s/@%s/%s.m" % (MODEL_CODE_BASE_DIR, '/+'.join(pathParts[0:-1]), pathParts[-1], pathParts[-1])
765 if not os.path.isfile(codePath):
766 continue
767 with open (codePath, "r") as codeFile:
768 code = codeFile.read()
769
770 lexer = MatlabLexer()
771 lexer.add_filter(PropertyDefinitionFilter(property_names = sim_property_names, tokentype=Token.Name.Variable))
772
773 tokens = lexer.get_tokens(code)
774
775 objects.append({
776 'class_name': sim_class_name,
777 'property_names': sim_property_names,
778 'code': pygments.format(tokens, PygmentsFormatter(linenos='inline', linenostep=1, style=PygmentsStyle, noclasses=True)),
779 })
780
781
782 return render_queryset_to_response(
783 species_wid = species_wid,
784 request = request,
785 models = [Parameter],
786 queryset = qs,
787 templateFile = 'public/viewPropertyInSimulation.html',
788 data = {
789 'object_list': objects,
790 'verbose_class_name': verbose_class_name,
791 'verbose_property_name': verbose_property_name,
792 })
793
794 @login_required
795 -def add(request, model_type, species_wid=None):
797
798 @login_required
799 -def edit(request, wid=None, model_type=None, species_wid=None, action='edit'):
800
801 if action == 'edit':
802 obj = getEntry(species_wid = species_wid, wid = wid)
803 if obj is None:
804 raise Http404
805 model = obj.__class__
806 else:
807 model = getModel(model_type)
808 obj = model()
809
810
811 error_messages = {}
812 if request.method == 'POST':
813 submitted_data = get_edit_form_data(model, request.POST)
814
815 data = submitted_data
816 data['id'] = obj.id
817 data['species'] = species_wid
818 data['model_type'] = model.__name__
819
820 try:
821
822 if issubclass(model, SpeciesComponent):
823 qs = SpeciesComponent.objects.values('wid', 'model_type').filter(species__wid=species_wid)
824 else:
825 qs = model.objects.values('wid', 'model_type').all()
826
827 if action == 'edit':
828 qs = qs.exclude(id=obj.id)
829
830 wids = {}
831 for x in qs:
832 wids[x['wid']] = x['model_type']
833
834 if data['wid'] in wids.keys():
835 raise ValidationError({'wid': 'Value must be unique'})
836
837 wids[data['wid']] = model.__name__
838
839
840 data = validate_object_fields(model, data, wids, species_wid, data['wid'])
841 validate_model_objects(model, data)
842 validate_model_unique(model, [data])
843
844
845 obj = save_object_data(species_wid, obj, data, {}, request.user, save=False, save_m2m=False)
846 obj = save_object_data(species_wid, obj, data, {data['wid']: obj}, request.user, save=True, save_m2m=False)
847 obj = save_object_data(species_wid, obj, data, {data['wid']: obj}, request.user, save=True, save_m2m=True)
848
849
850 return HttpResponseRedirect(obj.get_absolute_url())
851 except ValidationError as error:
852 error_messages = error.message_dict
853
854
855 if action == 'edit':
856 obj = getEntry(species_wid = species_wid, wid = wid)
857 if obj is None:
858 raise Http404
859 qs = objectToQuerySet(obj, model = model)
860 else:
861 obj = None
862 qs = model.objects.none()
863
864
865 fields, initial_values = get_edit_form_fields(species_wid, model, obj=obj)
866
867 if request.method == 'POST':
868 initial_values = submitted_data
869 return render_queryset_to_response(
870 species_wid = species_wid,
871 request = request,
872 models = [model],
873 queryset = qs,
874 templateFile = 'public/edit.html',
875 data = {
876 'model_verbose_name': model._meta.verbose_name,
877 'action': action,
878 'fields': fields,
879 'references_choices': Reference.objects.filter(species__wid = species_wid).values_list('wid'),
880 'initial_values': initial_values,
881 'error_messages': error_messages,
882 }
883 )
884
885 @login_required
886 -def delete(request, species_wid, wid):
910
912 getDict = request.GET.copy()
913 if getDict.get('format', ''):
914 getDict.__setitem__('species', getDict.get('species', species_wid))
915 form = ExportDataForm(request.user.is_anonymous(), getDict or None)
916 if not form.is_valid():
917 return render_queryset_to_response(
918 species_wid=species_wid,
919 request = request,
920 templateFile = 'public/exportDataForm.html',
921 data = {
922 'form': form
923 }
924 )
925 else:
926 species = Species.objects.get(wid = form.cleaned_data['species'])
927 queryset = EmptyQuerySet()
928 models = []
929 if form.cleaned_data['all_model_types'] == 'True':
930 model_types = getObjectTypes(superclass=Entry, is_public = request.user.is_anonymous())
931 else:
932 model_types = form.cleaned_data['model_type']
933
934 for model_type in model_types:
935 model = getModel(model_type)
936 if issubclass(model, SpeciesComponent):
937 queryset = chain(queryset, model.objects.filter(species__id=species.id).select_related(depth=2).all())
938 else:
939 queryset = chain(queryset, model.objects.select_related(depth=2).filter(id=species.id))
940 models.append(getModel(model_type))
941
942 return render_queryset_to_response(
943 species_wid = species_wid,
944 request = request,
945 queryset = queryset,
946 templateFile = 'public/exportDataResult.html',
947 models = models)
948
949 @login_required
950 -def importData(request, species_wid=None):
951 if request.method == 'POST':
952 form = ImportDataForm(request.POST or None, request.FILES)
953
954 if form.is_valid():
955 selected_species_wid = form.cleaned_data['species'] or form.cleaned_data['new_species']
956 if selected_species_wid == '' or selected_species_wid is None:
957 form.species.errors += ['Please select a specices']
958 else:
959
960 originalFileName, originalFileExtension = os.path.splitext(request.FILES['file'].name)
961 fid = tempfile.NamedTemporaryFile(suffix = originalFileExtension, delete = False)
962 filename = fid.name
963 for chunk in request.FILES['file'].chunks():
964 fid.write(chunk)
965 fid.close()
966
967
968 if originalFileExtension == '.xlsx':
969 try:
970 batch_import_from_excel(selected_species_wid, filename, request.user)
971 success = True
972 message = 'Data successfully saved!'
973 except ValidationError as error:
974 success = False
975 message = 'Unable to import data: ' + ' '.join(error.messages)
976 elif originalFileExtension == '.fna':
977 success, message = readFasta(selected_species_wid, filename, request.user)
978 else:
979 raise Http404
980
981
982 os.remove(filename)
983
984
985 return render_queryset_to_response(
986 species_wid = species_wid,
987 request = request,
988 templateFile = 'public/importDataResult.html',
989 data = {
990 'success': success,
991 'message': message,
992 })
993 else:
994 form = ImportDataForm(None)
995
996 return render_queryset_to_response(
997 species_wid = species_wid,
998 request = request,
999 templateFile = 'public/importDataForm.html',
1000 data = {
1001 'form': form},
1002 )
1003
1015
1016 @sensitive_post_parameters()
1017 @csrf_protect
1018 @never_cache
1019 -def login(request, species_wid=None):
1020 next = request.REQUEST.get('next', '')
1021
1022 if request.method == "POST":
1023 form = AuthenticationForm(data=request.POST)
1024 if form.is_valid():
1025 auth_login(request, form.get_user())
1026
1027 if request.session.test_cookie_worked():
1028 request.session.delete_test_cookie()
1029
1030 return HttpResponseRedirect(next)
1031 else:
1032 form = AuthenticationForm(request)
1033
1034 request.session.set_test_cookie()
1035
1036 return render_queryset_to_response(
1037 species_wid = species_wid,
1038 request = request,
1039 templateFile = 'public/login.html',
1040 data = {
1041 'form': form,
1042 'next': next,
1043 })
1044
1045 -def logout(request, species_wid=None):
1052
1054 return render_queryset_to_response(
1055 request = request,
1056 templateFile = 'public/sitemap.xml',
1057 data = {
1058 'ROOT_URL': settings.ROOT_URL,
1059 'qs_species': Species.objects.all(),
1060 }
1061 )
1062
1064 return render_queryset_to_response(
1065 request = request,
1066 templateFile = 'public/sitemap_toplevel.xml',
1067 data = {
1068 'ROOT_URL': settings.ROOT_URL,
1069 }
1070 )
1071
1083