From d9678c723871f6cd258d099da3b86606b28cac14 Mon Sep 17 00:00:00 2001 From: Rami Rauch Date: Thu, 14 Aug 2008 16:54:47 +0000 Subject: [PATCH] here's the exp_tack again; hopefully updated this time --- gaworkflow/frontend/exp_track/__init__.py | 0 gaworkflow/frontend/exp_track/et_urls.py | 10 ++ gaworkflow/frontend/exp_track/exptrack.py | 194 ++++++++++++++++++++++ gaworkflow/frontend/exp_track/models.py | 144 ++++++++++++++++ gaworkflow/frontend/exp_track/views.py | 22 +++ 5 files changed, 370 insertions(+) create mode 100755 gaworkflow/frontend/exp_track/__init__.py create mode 100755 gaworkflow/frontend/exp_track/et_urls.py create mode 100755 gaworkflow/frontend/exp_track/exptrack.py create mode 100755 gaworkflow/frontend/exp_track/models.py create mode 100755 gaworkflow/frontend/exp_track/views.py diff --git a/gaworkflow/frontend/exp_track/__init__.py b/gaworkflow/frontend/exp_track/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/gaworkflow/frontend/exp_track/et_urls.py b/gaworkflow/frontend/exp_track/et_urls.py new file mode 100755 index 0000000..6acea12 --- /dev/null +++ b/gaworkflow/frontend/exp_track/et_urls.py @@ -0,0 +1,10 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', + + (r'^$', 'gaworkflow.frontend.exp_track.views.index'), + (r'^(?P.+)/$', 'gaworkflow.frontend.exp_track.views.detail'), + (r'^updStatus$', 'gaworkflow.frontend.exp_track.exptrack.updStatus'), + (r'^getConfile$', 'gaworkflow.frontend.exp_track.exptrack.getConfile'), + (r'^getLanesNames$', 'gaworkflow.frontend.exp_track.exptrack.getLaneLibs') +) diff --git a/gaworkflow/frontend/exp_track/exptrack.py b/gaworkflow/frontend/exp_track/exptrack.py new file mode 100755 index 0000000..8cd5d6d --- /dev/null +++ b/gaworkflow/frontend/exp_track/exptrack.py @@ -0,0 +1,194 @@ +# some core functions of the exp tracker module +from django.http import HttpResponse +from datetime import datetime +from string import * +import re +from gaworkflow.frontend import settings +from gaworkflow.frontend.exp_track.models import FlowCell, DataRun +from gaworkflow.frontend.fctracker.models import Library +from django.core.exceptions import ObjectDoesNotExist +from django.core.mail import send_mail, mail_admins + +def updStatus(request): + output='' + user = 'none' + pswd = '' + UpdatedStatus = 'unknown' + fcid = 'none' + runfolder = 'unknown' + ClIP = request.META['REMOTE_ADDR'] + granted = False + + if request.has_key('user'): + user = request['user'] + + #Check access permission + if (user == 'rami' and settings.ALLOWED_IPS.has_key(ClIP)): granted = True + if not granted: return HttpResponse("access denied.") + + + # ~~~~~~Parameters for the job ~~~~ + if request.has_key('fcid'): + fcid = request['fcid'] + else: + return HttpResponse('missing fcid') + + if request.has_key('runf'): + runfolder = request['runf'] + else: + return HttpResponse('missing runf') + + + if request.has_key('updst'): + UpdatedStatus = request['updst'] + else: + return HttpResponse('missing status') + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + # Update Data Run status in DB + # Try get rec. If not found return 'entry not found + ', if found try update and return updated + try: + rec = DataRun.objects.get(run_folder=runfolder) + rec.run_status = UpdatedStatus + + #if there's a message update that too + mytimestamp = datetime.now().__str__() + mytimestamp = re.sub(pattern=":[^:]*$",repl="",string=mytimestamp) + if request.has_key('msg'): + rec.run_note += ", "+request['msg']+" ("+mytimestamp+")" + else : + if UpdatedStatus == '1': + rec.run_note = "Started ("+mytimestamp+")" + + rec.save() + output = "Hello "+settings.ALLOWED_IPS[ClIP]+". Updated to:'"+DataRun.RUN_STATUS_CHOICES[int(UpdatedStatus)][1].__str__()+"'" + except ObjectDoesNotExist: + output = "entry not found: "+fcid+", "+runfolder + + + #Notify researcher by email + # Doesn't work + #send_mail('Exp Tracker', 'Data Run Status '+output, 'rrauch@stanford.edu', ['rrrami@gmail.com'], fail_silently=False) + #mail_admins("test subject", "testing , testing", fail_silently=False) + # gives error: (49, "Can't assign requested address") + return HttpResponse(output) + +def generateConfile(fcid): + granted = False + ClIP = request.META['REMOTE_ADDR'] + if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True + + if not granted: return HttpResponse("access denied.") + + cnfgfile = 'READ_LENGTH 25\n' + cnfgfile += 'ANALYSIS eland\n' + cnfgfile += 'GENOME_FILE all_chr.fa\n' + cnfgfile += 'ELAND_MULTIPLE_INSTANCES 8\n' + genome_dir = 'GENOME_DIR /Volumes/Genomes/' + eland_genome = 'ELAND_GENOME /Volumes/Genomes/' + + try: + rec = FlowCell.objects.get(flowcell_id=fcid) + + cnfgfile += '1:'+genome_dir+rec.lane_1_library.library_species.use_genome_build+'\n' + cnfgfile += '1:'+eland_genome+rec.lane_1_library.library_species.use_genome_build+'\n' + + cnfgfile += '2:'+genome_dir+rec.lane_2_library.library_species.use_genome_build+'\n' + cnfgfile += '2:'+eland_genome+rec.lane_2_library.library_species.use_genome_build+'\n' + + cnfgfile += '3:'+genome_dir+rec.lane_3_library.library_species.use_genome_build+'\n' + cnfgfile += '3:'+eland_genome+rec.lane_3_library.library_species.use_genome_build+'\n' + + cnfgfile += '4:'+genome_dir+rec.lane_4_library.library_species.use_genome_build+'\n' + cnfgfile += '4:'+eland_genome+rec.lane_4_library.library_species.use_genome_build+'\n' + + cnfgfile += '5:'+genome_dir+rec.lane_5_library.library_species.use_genome_build+'\n' + cnfgfile += '5:'+eland_genome+rec.lane_5_library.library_species.use_genome_build+'\n' + + cnfgfile += '6:'+genome_dir+rec.lane_6_library.library_species.use_genome_build+'\n' + cnfgfile += '6:'+eland_genome+rec.lane_6_library.library_species.use_genome_build+'\n' + + cnfgfile += '7:'+genome_dir+rec.lane_7_library.library_species.use_genome_build+'\n' + cnfgfile += '7:'+eland_genome+rec.lane_7_library.library_species.use_genome_build+'\n' + + cnfgfile += '8:'+genome_dir+rec.lane_8_library.library_species.use_genome_build+'\n' + cnfgfile += '8:'+eland_genome+rec.lane_8_library.library_species.use_genome_build + + except ObjectDoesNotExist: + cnfgfile = 'Entry not found for fcid = '+fcid + + return cnfgfile + +def getConfile(request): + granted = False + ClIP = request.META['REMOTE_ADDR'] + if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True + + if not granted: return HttpResponse("access denied.") + + fcid = 'none' + cnfgfile = '' + runfolder = 'unknown' + if request.has_key('fcid'): + fcid = request['fcid'] + if request.has_key('runf'): + runfolder = request['runf'] + try: + rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid) + cnfgfile = rec.config_params + #match_str = re.compile(r"READ_LENGTH.+$") + match_str = re.compile('^READ_LENGTH.+') + if not match_str.search(cnfgfile): + cnfgfile = generateConfile(fcid) + if match_str.search(cnfgfile): + rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid) + rec.config_params = cnfgfile + rec.save() + else: + cnfgfile = 'Failed generating config params for RunFolder = '+runfolder +', Flowcell id = '+ fcid+ ' Config Text:\n'+cnfgfile + + except ObjectDoesNotExist: + cnfgfile = 'Entry not found for RunFolder = '+runfolder + + return HttpResponse(cnfgfile) + +def getLaneLibs(request): + granted = False + ClIP = request.META['REMOTE_ADDR'] + if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True + + if not granted: return HttpResponse("access denied.") + + fcid = 'none' + outputfile = '' + if request.has_key('fcid'): + fcid = request['fcid'] + try: + rec = FlowCell.objects.get(flowcell_id=fcid) + #Ex: 071211 + year = datetime.today().year.__str__() + year = replace(year,'20','') + month = datetime.today().month + if month < 10: month = "0"+month.__str__() + else: month = month.__str__() + day = datetime.today().day + if day < 10: day = "0"+day.__str__() + else: day = day.__str__() + mydate = year+month+day + outputfile = '' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + outputfile += '\n' + except ObjectDoesNotExist: + outputfile = 'Flowcell entry not found for: '+fcid + else: outputfile = 'Missing input: flowcell id' + + return HttpResponse(outputfile) diff --git a/gaworkflow/frontend/exp_track/models.py b/gaworkflow/frontend/exp_track/models.py new file mode 100755 index 0000000..2096148 --- /dev/null +++ b/gaworkflow/frontend/exp_track/models.py @@ -0,0 +1,144 @@ +from django.db import models +from gaworkflow.frontend.fctracker.models import Library + +class FlowCell(models.Model): + + flowcell_id = models.CharField(max_length=20, unique=True, db_index=True, core=True) + run_date = models.DateTimeField(core=True) + advanced_run = models.BooleanField(default=False) + read_length = models.IntegerField(default=32) #Stanford is currenlty 25 + + lane_1_library = models.ForeignKey(Library, related_name="lane_1_library") + lane_2_library = models.ForeignKey(Library, related_name="lane_2_library") + lane_3_library = models.ForeignKey(Library, related_name="lane_3_library") + lane_4_library = models.ForeignKey(Library, related_name="lane_4_library") + lane_5_library = models.ForeignKey(Library, related_name="lane_5_library") + lane_6_library = models.ForeignKey(Library, related_name="lane_6_library") + lane_7_library = models.ForeignKey(Library, related_name="lane_7_library") + lane_8_library = models.ForeignKey(Library, related_name="lane_8_library") + + lane_1_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_2_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_3_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_4_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_5_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_6_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_7_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + lane_8_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=2.5) + + lane_1_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_2_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_3_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_4_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_5_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_6_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_7_cluster_estimate = models.IntegerField(blank=True, null=True) + lane_8_cluster_estimate = models.IntegerField(blank=True, null=True) + + # lane_1_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_1_primer") + # lane_2_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_2_primer") + # lane_3_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_3_primer") + # lane_4_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_4_primer") + # lane_5_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_5_primer") + # lane_6_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_6_primer") + # lane_7_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_7_primer") + # lane_8_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_8_primer") + + #Machine Names + CLUSTER_MAC = ( + ('M304','M304'), + ('R349','R349'), + ('Tinkerbell','Tinkerbell'), + ('BitBit','BitBit'), + ) + + SEQ_MAC = ( + ('EAS149','EAS149'), + ('EAS46','EAS46'), + ('EAS45','Paris'), + ('Britney','Britney'), + ) + + cluster_mac_id = models.CharField(max_length=50, choices=CLUSTER_MAC, default='BitBit') + seq_mac_id = models.CharField(max_length=50, choices=SEQ_MAC, verbose_name = 'Sequencer', default='Britney') + + notes = models.TextField(blank=True) + + def __str__(self): + #return '%s (%s)' % (self.flowcell_id, self.run_date) + return '%s' % (self.flowcell_id) + + + def Lanes(self): + return '
1)%s2)%s3)%s4)%s5)%s6)%s7)%s8)%s
' % (self.lane_1_library,self.lane_2_library,self.lane_3_library,self.lane_4_library,self.lane_5_library,self.lane_6_library,self.lane_7_library,self.lane_8_library) + Lanes.allow_tags = True + + class Meta: + ordering = ["-run_date"] + + class Admin: + save_on_top = True + date_hierarchy = "run_date" + save_on_top = True + search_fields = ['flowcell_id','seq_mac_id','cluster_mac_id','=lane_1_library__library_id','=lane_2_library__library_id','=lane_3_library__library_id','=lane_4_library__library_id','=lane_5_library__library_id','=lane_6_library__library_id','=lane_7_library__library_id','=lane_8_library__library_id'] + list_display = ('flowcell_id','seq_mac_id','run_date', 'Lanes') + list_filter = ('seq_mac_id','cluster_mac_id') + fields = ( + (None, { + 'fields': ('run_date', ('flowcell_id','cluster_mac_id','seq_mac_id'), ('read_length'),) + }), + ('Lanes:', { + ##'fields' : (('lane_1_library', 'lane_1_pM', 'lane_1_cluster_estimate', 'lane_1_primer'), ('lane_2_library', 'lane_2_pM', 'lane_2_cluster_estimate', 'lane_2_primer'), ('lane_3_library', 'lane_3_pM', 'lane_3_cluster_estimate', 'lane_3_primer'), ('lane_4_library', 'lane_4_pM', 'lane_4_cluster_estimate', 'lane_4_primer'), ('lane_5_library', 'lane_5_pM', 'lane_5_cluster_estimate', 'lane_5_primer'), ('lane_6_library', 'lane_6_pM', 'lane_6_cluster_estimate', 'lane_6_primer'), ('lane_7_library', 'lane_7_pM', 'lane_7_cluster_estimate', 'lane_7_primer'), ('lane_8_library', 'lane_8_pM', 'lane_8_cluster_estimate', 'lane_8_primer'),) + 'fields' : (('lane_1_library', 'lane_1_pM', 'lane_1_cluster_estimate'), ('lane_2_library', 'lane_2_pM', 'lane_2_cluster_estimate'), ('lane_3_library', 'lane_3_pM', 'lane_3_cluster_estimate'), ('lane_4_library', 'lane_4_pM', 'lane_4_cluster_estimate'), ('lane_5_library', 'lane_5_pM', 'lane_5_cluster_estimate'), ('lane_6_library', 'lane_6_pM', 'lane_6_cluster_estimate'), ('lane_7_library', 'lane_7_pM', 'lane_7_cluster_estimate'), ('lane_8_library', 'lane_8_pM', 'lane_8_cluster_estimate'),) + }), + (None, { + 'fields' : ('notes',) + }), + ) + + +### ----------------------- +class DataRun(models.Model): + ConfTemplate = "CONFIG PARAMS WILL BE GENERATED BY THE PIPELINE SCRIPT.\nYOU'LL BE ABLE TO EDIT AFTER IF NEEDED." + run_folder = models.CharField(max_length=50,unique=True, db_index=True) + fcid = models.ForeignKey(FlowCell,verbose_name="Flowcell Id") + config_params = models.TextField(default=ConfTemplate) + run_start_time = models.DateTimeField(core=True) + RUN_STATUS_CHOICES = ( + (0, 'Sequencer running'), ##Solexa Data Pipeline Not Yet Started'), + (1, 'Data Pipeline Started'), + (2, 'Data Pipeline Interrupted'), + (3, 'Data Pipeline Finished'), + (4, 'CollectReads Started'), + (5, 'CollectReads Finished'), + (6, 'QC Finished'), + (7, 'DONE'), + ) + run_status = models.IntegerField(choices=RUN_STATUS_CHOICES, default=0) + run_note = models.TextField(blank=True) + + + def main_status(self): + return self.run_status + + main_status.allow_tags = True + + def Flowcell_Info(self): + str = ''+self.fcid.__str__()+'' + str += ' (c: '+self.fcid.cluster_mac_id+', s: '+self.fcid.seq_mac_id+')' + str += '
' + str +='View/hide lanes' + str += '
' + LanesList = '1: '+self.fcid.lane_1_library.__str__()+' ('+self.fcid.lane_1_library.library_species.use_genome_build+')
2: '+self.fcid.lane_2_library.__str__()+' ('+self.fcid.lane_2_library.library_species.use_genome_build+')
3: '+self.fcid.lane_3_library.__str__()+' ('+self.fcid.lane_3_library.library_species.use_genome_build+')
4: '+self.fcid.lane_4_library.__str__()+' ('+self.fcid.lane_4_library.library_species.use_genome_build+')
5: '+self.fcid.lane_5_library.__str__()+' ('+self.fcid.lane_5_library.library_species.use_genome_build+')
6: '+self.fcid.lane_6_library.__str__()+' ('+self.fcid.lane_6_library.library_species.use_genome_build+')
7: '+self.fcid.lane_7_library.__str__()+' ('+self.fcid.lane_7_library.library_species.use_genome_build+')
8: '+self.fcid.lane_8_library.__str__()+' ('+self.fcid.lane_8_library.library_species.use_genome_build+')' + str += LanesList ## self.fcid.Lanes() + str += '
' + str += '' + str += '
' + return str + Flowcell_Info.allow_tags = True + + class Admin: + search_fields = ['run_folder','run_note','config_params','=fcid__lane_1_library__library_id','=fcid__lane_2_library__library_id','=fcid__lane_3_library__library_id','=fcid__lane_4_library__library_id','=fcid__lane_5_library__library_id','=fcid__lane_6_library__library_id','=fcid__lane_7_library__library_id','=fcid__lane_8_library__library_id'] + + list_display = ('run_folder','Flowcell_Info','run_start_time','run_status','run_note') + list_filter = ('run_status','run_start_time') diff --git a/gaworkflow/frontend/exp_track/views.py b/gaworkflow/frontend/exp_track/views.py new file mode 100755 index 0000000..1d9aa8d --- /dev/null +++ b/gaworkflow/frontend/exp_track/views.py @@ -0,0 +1,22 @@ +# Create your views here. +#from django.template import Context, loader +#shortcut to the above modules +from django.shortcuts import render_to_response, get_object_or_404 +from gaworkflow.frontend.exp_track.models import DataRun +from django.http import HttpResponse + +def index(request): + all_runs = DataRun.objects.all().order_by('-run_start_time') + #t = loader.get_template('exptrack/index.html') + #c = Context({ + # 'data_run_list': all_runs, + #}) + #return HttpResponse(t.render(c)) + # shortcut to the above module usage + return render_to_response('exptrack/index.html',{'data_run_list': all_runs}) + +def detail(request, run_folder): + html_str = '

Exp Track Details Page

' + html_str += 'Run Folder: '+run_folder + r = get_object_or_404(DataRun,run_folder=run_folder) + return render_to_response('exptrack/detail.html',{'run_f': r}) -- 2.30.2