1 # some core functions of the exp tracker module
2 from datetime import datetime, timedelta
6 from django.http import HttpResponse
7 from htsworkflow.frontend import settings
8 from htsworkflow.frontend.experiments.models import FlowCell, DataRun
9 from htsworkflow.frontend.samples.models import Library
10 from django.core.exceptions import ObjectDoesNotExist
11 from django.core.mail import send_mail, mail_admins
13 def updStatus(request):
17 UpdatedStatus = 'unknown'
20 ClIP = request.META['REMOTE_ADDR']
22 if hasattr(request, 'user'):
25 #Check access permission
26 if not (user.is_superuser and settings.ALLOWED_IPS.has_key(ClIP)):
27 return HttpResponse("%s access denied from %s." % (user, ClIP))
29 # ~~~~~~Parameters for the job ~~~~
30 if request.REQUEST.has_key('fcid'):
31 fcid = request.REQUEST['fcid']
33 return HttpResponse('missing fcid')
35 if request.REQUEST.has_key('runf'):
36 runfolder = request.REQUEST['runf']
38 return HttpResponse('missing runf')
41 if request.REQUEST.has_key('updst'):
42 UpdatedStatus = request.REQUEST['updst']
44 return HttpResponse('missing status')
46 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 # Update Data Run status in DB
49 # Try get rec. If not found return 'entry not found + <fcid><runfolder>', if found try update and return updated
51 rec = DataRun.objects.get(run_folder=runfolder)
52 rec.run_status = UpdatedStatus
54 #if there's a message update that too
55 mytimestamp = datetime.now().__str__()
56 mytimestamp = re.sub(pattern=":[^:]*$",repl="",string=mytimestamp)
57 if request.REQUEST.has_key('msg'):
58 rec.run_note += ", "+request.REQUEST['msg']+" ("+mytimestamp+")"
60 if UpdatedStatus == '1':
61 rec.run_note = "Started ("+mytimestamp+")"
64 output = "Hello "+settings.ALLOWED_IPS[ClIP]+". Updated to:'"+DataRun.RUN_STATUS_CHOICES[int(UpdatedStatus)][1].__str__()+"'"
65 except ObjectDoesNotExist:
66 output = "entry not found: "+fcid+", "+runfolder
69 #Notify researcher by email
71 #send_mail('Exp Tracker', 'Data Run Status '+output, 'rrauch@stanford.edu', ['rrrami@gmail.com'], fail_silently=False)
72 #mail_admins("test subject", "testing , testing", fail_silently=False)
73 # gives error: (49, "Can't assign requested address")
74 return HttpResponse(output)
76 def generateConfile(request,fcid):
78 #ClIP = request.META['REMOTE_ADDR']
79 #if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
81 #if not granted: return HttpResponse("access denied.")
83 config = ['READ_LENGTH 25']
84 config += ['ANALYSIS eland']
85 config += ['GENOME_FILE all_chr.fa']
86 config += ['ELAND_MULTIPLE_INSTANCES 8']
87 genome_dir = 'GENOME_DIR /Volumes/Genomes/'
88 eland_genome = 'ELAND_GENOME /Volumes/Genomes/'
91 fc = FlowCell.objects.get(flowcell_id=fcid)
92 for lane in fc.lane_set.all():
93 print dir(lane.library.library_species)
94 config += [ str(lane.lane_number) +":" + \
95 genome_dir + lane.library.library_species.scientific_name ]
96 config += [ str(lane.lane_number) +":" + \
97 eland_genome + lane.library.library_species.scientific_name ]
99 except ObjectDoesNotExist:
100 config = 'Entry not found for fcid = '+fcid
102 return os.linesep.join(config)
106 ClIP = req.META['REMOTE_ADDR']
107 if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
109 if not granted: return HttpResponse("access denied. IP: "+ClIP)
112 cnfgfile = 'Nothing found'
113 runfolder = 'unknown'
114 request = req.REQUEST
115 print request, dir(request)
116 print request['fcid'], request.has_key('fcid')
117 print request['runf']
118 if request.has_key('fcid'):
119 fcid = request['fcid']
120 if request.has_key('runf'):
121 runfolder = request['runf']
123 rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
124 cnfgfile = rec.config_params
125 #match_str = re.compile(r"READ_LENGTH.+$")
126 match_str = re.compile('^READ_LENGTH.+')
127 if not match_str.search(cnfgfile):
128 cnfgfile = generateConfile(request,fcid)
129 if match_str.search(cnfgfile):
130 rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
131 rec.config_params = cnfgfile
134 cnfgfile = 'Failed generating config params for RunFolder = '+runfolder +', Flowcell id = '+ fcid+ ' Config Text:\n'+cnfgfile
136 except ObjectDoesNotExist:
137 cnfgfile = 'Entry not found for RunFolder = '+runfolder
139 return HttpResponse(cnfgfile, mimetype='text/plain')
141 def getLaneLibs(req):
143 ClIP = req.META['REMOTE_ADDR']
144 if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
146 if not granted: return HttpResponse("access denied.")
148 request = req.REQUEST
151 if request.has_key('fcid'):
152 fcid = request['fcid']
154 rec = FlowCell.objects.get(flowcell_id=fcid)
156 year = datetime.today().year.__str__()
157 year = replace(year,'20','')
158 month = datetime.today().month
159 if month < 10: month = "0"+month.__str__()
160 else: month = month.__str__()
161 day = datetime.today().day
162 if day < 10: day = "0"+day.__str__()
163 else: day = day.__str__()
164 mydate = year+month+day
165 outputfile = '<?xml version="1.0" ?>'
166 outputfile += '\n<SolexaResult Date="'+mydate+'" Flowcell="'+fcid+'" Client="'+settings.ALLOWED_IPS[ClIP]+'">'
167 outputfile += '\n<Lane Index="1" Name="'+rec.lane_1_library.library_name+'" Library="'+rec.lane_1_library.library_id+'" Genome="'+rec.lane_1_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
168 outputfile += '\n<Lane Index="2" Name="'+rec.lane_2_library.library_name+'" Library="'+rec.lane_2_library.library_id+'" Genome="'+rec.lane_2_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
169 outputfile += '\n<Lane Index="3" Name="'+rec.lane_3_library.library_name+'" Library="'+rec.lane_3_library.library_id+'" Genome="'+rec.lane_3_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
170 outputfile += '\n<Lane Index="4" Name="'+rec.lane_4_library.library_name+'" Library="'+rec.lane_4_library.library_id+'" Genome="'+rec.lane_4_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
171 outputfile += '\n<Lane Index="5" Name="'+rec.lane_5_library.library_name+'" Library="'+rec.lane_5_library.library_id+'" Genome="'+rec.lane_5_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
172 outputfile += '\n<Lane Index="6" Name="'+rec.lane_6_library.library_name+'" Library="'+rec.lane_6_library.library_id+'" Genome="'+rec.lane_6_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
173 outputfile += '\n<Lane Index="7" Name="'+rec.lane_7_library.library_name+'" Library="'+rec.lane_7_library.library_id+'" Genome="'+rec.lane_7_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
174 outputfile += '\n<Lane Index="8" Name="'+rec.lane_8_library.library_name+'" Library="'+rec.lane_8_library.library_id+'" Genome="'+rec.lane_8_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
175 outputfile += '\n</SolexaResult>'
176 except ObjectDoesNotExist:
177 outputfile = 'Flowcell entry not found for: '+fcid
178 else: outputfile = 'Missing input: flowcell id'
180 return HttpResponse(outputfile, mimetype='text/plain')
182 def estimateFlowcellDuration(flowcell):
184 Attempt to estimate how long it will take to run a flowcell
187 # (3600 seconds * 1.5 hours per cycle )
188 sequencing_seconds_per_cycle= 3600 * 1.5
189 # 800 is a rough guess
190 pipeline_seconds_per_cycle = 800
192 cycles = flowcell.read_length
193 if flowcell.paired_end:
195 sequencing_time = timedelta(0, cycles * sequencing_seconds_per_cycle)
196 analysis_time = timedelta(0, cycles * pipeline_seconds_per_cycle)
197 estimate_mid = sequencing_time + analysis_time
199 estimate_low = timedelta(estimate_mid.days, 0)
200 # floor estimate_mid and add a day
201 estimate_high = timedelta(estimate_mid.days+1, 0)
203 return (estimate_low, estimate_high)
206 def makeUserLaneMap(flowcell):
208 Given a flowcell return a mapping of users interested in
209 the libraries on those lanes.
213 for lane in flowcell.lane_set.all():
214 for affiliation in lane.library.affiliations.all():
215 for user in affiliation.users.all():
216 users.setdefault(user,[]).append(lane)
220 def getUsersForFlowcell(flowcell):
223 for lane in flowcell.lane_set.all():
224 for affiliation in lane.library.affiliations.all():
225 for user in affiliation.users.all():
230 def makeUserLibraryMap(libraries):
232 Given an interable set of libraries return a mapping or
233 users interested in those libraries.
237 for library in libraries:
238 for affiliation in library.affiliations.all():
239 for user in affiliation.users.all():
240 users.setdefault(user,[]).append(library)
244 def makeAffiliationLaneMap(flowcell):
247 for lane in flowcell.lane_set.all():
248 for affiliation in lane.library.affiliations.all():
249 affs.setdefault(affiliation,[]).append(lane)
253 def makeEmailLaneMap(flowcell):
255 Create a list of email addresses and the lanes associated with those users.
257 The email addresses can come from both the "users" table and the "affiliations" table.
260 for lane in flowcell.lane_set.all():
261 for affiliation in lane.library.affiliations.all():
262 if affiliation.email is not None and len(affiliation.email) > 0:
263 emails.setdefault(affiliation.email,set()).add(lane)
264 for user in affiliation.users.all():
265 if user.email is not None and len(user.email) > 0:
266 emails.setdefault(user.email,set()).add(lane)