source: extensions/net.sf.basedb.reggie/trunk/resources/analysis/demux_confirm.jsp @ 2458

Last change on this file since 2458 was 2458, checked in by Nicklas Nordborg, 9 years ago

References #548: Register Demux and Merge as ended

Display failed demux jobs in the confirmation wizard.

Do not check 'align' for libraries that have 0 PF_READS.

File size: 17.5 KB
Line 
1<%@ page
2  pageEncoding="UTF-8"
3  session="false"
4  import="net.sf.basedb.core.User"
5  import="net.sf.basedb.core.DbControl"
6  import="net.sf.basedb.core.SessionControl"
7  import="net.sf.basedb.core.Application"
8  import="net.sf.basedb.clients.web.Base" 
9  import="net.sf.basedb.clients.web.util.HTML" 
10  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
11%>
12<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
13<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
14<%
15final SessionControl sc = Base.getExistingSessionControl(request, true);
16final String ID = sc.getId();
17final float scale = Base.getScale(sc);
18final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
19DbControl dc = null;
20try
21{
22  dc = sc.newDbControl();
23  final User user = User.getById(dc, sc.getLoggedInUserId());
24%>
25<base:page type="default" >
26<base:head scripts="ajax.js" styles="path.css">
27  <link rel="stylesheet" type="text/css" href="../css/reggie.css">
28  <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script>
29
30<script language="JavaScript">
31
32var debug = 1;
33var currentStep = 1;
34
35
36function init()
37{
38  var frm = document.forms['reggie'];
39  var jobs = getDemuxJobs();
40
41  // Load existing Demux jobs
42  if (jobs != null && jobs.length > 0)
43  {
44    for (var jobNo=0; jobNo < jobs.length; jobNo++)
45    {
46      var job = jobs[jobNo];
47      var option = new Option(job.name, job.id);
48      //option.title = title;
49      option.job = job;
50      frm.demuxJobs.options[frm.demuxJobs.length] = option;
51    }
52    demuxJobOnChange();
53  }
54  else
55  {
56    var msg = 'No jobs available for processing.';
57    setFatalError(msg);
58    return;
59  }
60
61  // All is ok
62  frm.demuxJobs.focus();
63}
64
65function getPoolNum(poolName)
66{
67  var num = poolName.match(/Pool(\d+)/);
68  return num ? parseInt(num[1], 10) : null; 
69}
70
71function goNextAuto()
72{
73  goNext(false);
74}
75
76function goNext(manual)
77{
78  setInnerHTML('gonext.message', '');
79  if (currentStep == 1)
80  {
81    if (step1IsValid()) gotoStep2();
82  }
83  setCurrentStep(currentStep);
84}
85
86function step1IsValid()
87{
88  return true;
89}
90
91function step2IsValid()
92{
93  return true;
94}
95
96
97function getDemuxJobs()
98{
99  var frm = document.forms['reggie']; 
100 
101  var request = Ajax.getXmlHttpRequest();
102  try
103  {
104    showLoadingAnimation('Loading demux jobs...');
105    var url = '../DemuxMerge.servlet?ID=<%=ID%>&cmd=GetUnconfirmedDemuxJobs';   
106    request.open("GET", url, false); 
107    request.send(null);
108  }
109  finally
110  {
111    hideLoadingAnimation();
112  }
113 
114  if (debug) Main.debug(request.responseText);
115  var response = JSON.parse(request.responseText); 
116  if (response.status != 'ok')
117  {
118    setFatalError(response.message);
119    return false;
120  }
121  return response.jobs;
122}
123
124function demuxJobOnChange()
125{
126  var frm = document.forms['reggie']; 
127  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
128 
129  setInnerHTML('startDate', formatDate(job.started));
130  setInnerHTML('endDate', formatDate(job.ended));
131  setInnerHTML('jobStatus', job.status+'; '+Strings.encodeTags(job.statusMessage));
132 
133  var demuxedSequences = job.demuxedSequences;
134  var fcHtml = '<table id="fc-info-table"><tr><th>ID</th><th>PF_READS</th><th>PF_UNUSED_PCT</th><th>PF_NNNN_PCT</th><th>Warnings</th></tr>';
135  var poolHtml = '';
136  var libPlateHtml = '';
137  var warningsHtml = '';
138  for (var dxNo = 0; dxNo < demuxedSequences.length; dxNo++)
139  {
140    var dx = demuxedSequences[dxNo];
141    var fc = dx.seqRun.flowCell;
142   
143    //if (dxNo > 0) fcHtml += '<br>';
144    fcHtml += '<tr><td>'+Main.encodeTags(fc.FlowCellID)+'</td>';
145    fcHtml += '<td>' + formatNumber(dx.PF_READS/1000000, 'M', 2) + '</td>';
146    fcHtml += '<td>' + formatNumber(dx.PF_UNUSED_PCT, '%', 2)+' </td>';
147    fcHtml += '<td>'+formatNumber(dx.PF_NNNN_PCT, '%', 2) + '</td>';
148    fcHtml += '<td>'+dx.DEMUX_WARNING.length;
149    if (dx.DEMUX_WARNING.length > 0) fcHtml += ' (see below)';
150    fcHtml += '</td></tr>';
151   
152    var pools = fc.pools;
153    for (var poolNo = 0; poolNo < pools.length; poolNo++)
154    {
155      var pool = pools[poolNo];
156      if (poolHtml.indexOf(pool.name) == -1)
157      {
158        if (poolHtml.length > 0) poolHtml += ', ';
159        poolHtml += Main.encodeTags(pool.name);
160      }
161      if (pool.LibPlate && libPlateHtml.indexOf(pool.LibPlate.name) == -1)
162      {
163        if (libPlateHtml.length > 0) libPlateHtml += ', ';
164        libPlateHtml += Main.encodeTags(pool.LibPlate.name);
165      }
166    }
167   
168    if (dx.DEMUX_WARNING.length > 0)
169    {
170      for (var warnNo = 0; warnNo < dx.DEMUX_WARNING.length; warnNo++)
171      {
172        warningsHtml += '<li class="warning">'+Main.encodeTags(fc.FlowCellID)+': '+Main.encodeTags(dx.DEMUX_WARNING[warnNo]) + '<br>';
173      }
174    }
175  }
176  fcHtml += '</table>';
177
178  setInnerHTML('flowCellsInDemux', fcHtml);
179  setInnerHTML('pools', poolHtml);
180  setInnerHTML('libPlates', libPlateHtml || 'n/a');
181  setInnerHTML('comments', Main.encodeTags(job.comments));
182  setInnerHTML('warnings', warningsHtml);
183}
184
185
186function formatDate(value)
187{
188  if (!value) return '';
189  if (value.length == 8)
190  {
191    // YYYYMMDD
192    value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2);
193  }
194  else if (value.length == 13)
195  {
196    // YYYYMMDD HHMM
197    value = value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2) + ' ' + value.substr(9, 2) + ':' + value.substr(11, 2);
198  }
199  return value;
200}
201
202
203function gotoStep2()
204{
205  var frm = document.forms['reggie'];
206 
207  // Disable controls
208  frm.demuxJobs.disabled = true;
209
210  currentStep = 2;
211  Main.hide('step.1.section');
212  Main.show('step.2.section');
213  Main.addClass(document.getElementById('step.1.section'), 'disabled');
214  Main.show('gocancel');
215  Main.show('goregister');
216  Main.hide('gonext');
217 
218  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
219
220  var mergedSeq = getMergedSequences();
221  job.mergedSequences = mergedSeq;
222 
223  var html = '<table id="mergedSequencesTable">';
224  html += '<thead style="background-color: #E8E8E8; border-top: 1px solid #A0A0A0;">';
225  // Header row
226  html += '<tr>';
227  html += '<th>Library</th>';
228  html += '<th class="dottedleft">READS</th>';
229  html += '<th class="dottedleft">PF_READS</th>';
230  html += '<th class="dottedleft">Flag RNA</th>';
231  html += '<th class="dottedleft">Align</th>';
232  html += '<th class="dottedleft">Comment</th>';
233  html += '</tr>';
234  html += '<tr>';
235  html += '<th></th>';
236  html += '<th class="dottedleft">(millions)</th>';
237  html += '<th class="dottedleft">(millions)</th>';
238  html += '<th class="dottedleft"></th>';
239  html += '<th class="dottedleft"></th>';
240  html += '<th class="dottedleft"></th>';
241  html += '</tr>';
242  html += '</thead>';
243  html += '<tbody>';
244  for (var mergedNo = 0; mergedNo < mergedSeq.length; mergedNo++)
245  {
246    var merged = mergedSeq[mergedNo];
247    var lib = merged.lib;
248    lib.stratagene = lib.name.indexOf(GENERIC_STRATAGENE_NAME) == 0;
249    lib.external = lib.name.indexOf(EXTERNAL_RNA_NAME) == 0;
250   
251    html += '<tr class="highlight">';
252    html += '<td class="prompt">'+lib.name+'</td>';
253    html += '<td class="dottedleft">'+formatNumber(merged.READS/1000000, null, 2)+'</td>';
254    html += '<td class="dottedleft">'+formatNumber(merged.PF_READS/1000000, null, 2)+'</td>';
255
256    // Do not allow flagging external or stratagene
257    var alignChecked = 'checked';
258    if (lib.stratagene || lib.external)
259    {
260      html += '<td class="dottedleft">-</td>';
261      alignChecked = '';
262    }
263    else
264    {
265      if (!merged.PF_READS) alignChecked = '';
266      html += '<td class="dottedleft"><input type="checkbox" name="flag.'+merged.id+'"></td>';
267    }
268   
269    html += '<td class="dottedleft"><input type="checkbox" name="align.'+merged.id+'" '+alignChecked+'></td>';
270    html += '<td class="dottedleft"><input type="text" name="comment.'+merged.id+'" style="width: 20em;"></td>';
271    html += '</tr>';
272  }
273  html += '</tbody>';
274  html += '</table>';
275  setInnerHTML('mergedSequences', html);
276 
277  if (job.status == 'ERROR')
278  {
279    Doc.element('outcomeFailed').checked = true;
280    outcomeOnChange();
281  }
282
283}
284
285
286function getMergedSequences()
287{
288  var frm = document.forms['reggie'];
289  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
290 
291  var request = Ajax.getXmlHttpRequest();
292  try
293  {
294    showLoadingAnimation('Loading merged sequences...');
295    var url = '../DemuxMerge.servlet?ID=<%=ID%>&cmd=GetMergedSequences&job='+job.id;   
296    request.open("GET", url, false); 
297    request.send(null);
298  }
299  finally
300  {
301    hideLoadingAnimation();
302  }
303 
304  if (debug) Main.debug(request.responseText);
305  var response = JSON.parse(request.responseText); 
306  if (response.status != 'ok')
307  {
308    setFatalError(response.message);
309    return false;
310  }
311  return response.mergedSequences;
312
313}
314
315function outcomeOnChange()
316{
317  var frm = document.forms['reggie'];
318  var failed = document.getElementById('outcomeFailed').checked;
319  frm.flagPools.disabled = !failed;
320 
321  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
322  var mergedSequences = job.mergedSequences;
323 
324  for (var mergeNo = 0; mergeNo < mergedSequences.length; mergeNo++)
325  {
326    var merge = mergedSequences[mergeNo];
327    if (frm['flag.'+merge.id])
328    {
329      frm['flag.'+merge.id].disabled = failed;
330    }
331    frm['align.'+merge.id].disabled = failed;
332  }
333 
334}
335
336
337function goRegister()
338{
339  if (!step2IsValid()) return;
340  var failed = document.getElementById('outcomeFailed').checked;
341
342  var frm = document.forms['reggie'];
343  Main.addClass(document.getElementById('step.2.section'), 'disabled');
344 
345 
346  Main.hide('goregister');
347  Main.hide('gocancel');
348  Main.hide('gonext.message');
349 
350  var submitInfo = {};
351 
352  submitInfo.failed = failed;
353  submitInfo.flagPools = !frm.flagPools.disabled && frm.flagPools.checked ? true : false;
354 
355  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
356  var demuxedSequences = job.demuxedSequences;
357  var mergedSequences = job.mergedSequences;
358 
359  var demux = [];
360  submitInfo.demuxedSequences = demux;
361  for (var demuxNo = 0; demuxNo < demuxedSequences.length; demuxNo++)
362  {
363    var dx = demuxedSequences[demuxNo];
364    var tmp = {};
365    tmp.id = dx.id;
366    demux[demux.length] = tmp;
367  }
368 
369  var merged = [];
370  submitInfo.mergedSequences = merged;
371  for (var mergeNo = 0; mergeNo < mergedSequences.length; mergeNo++)
372  {
373    var merge = mergedSequences[mergeNo];
374    var tmp = {};
375    tmp.id = merge.id;
376    tmp.flag = frm['flag.'+merge.id] && frm['flag.'+merge.id].checked;
377    tmp.align = frm['align.'+merge.id].checked;
378    tmp.comment = frm['comment.'+merge.id].value;
379    merged[merged.length] = tmp;
380  }
381 
382  if (debug) Main.debug(JSON.stringify(submitInfo));
383  var url = '../DemuxMerge.servlet?ID=<%=ID%>&cmd=RegisterDemuxAndMerge';
384  var request = Ajax.getXmlHttpRequest();
385  try
386  {
387    showLoadingAnimation('Performing registration...');
388    request.open("POST", url, false);
389    request.send(JSON.stringify(submitInfo));
390  }
391  finally
392  {
393    hideLoadingAnimation();
394  }
395 
396  if (debug) Main.debug(request.responseText);
397  var response = JSON.parse(request.responseText);
398 
399  if (response.messages && response.messages.length > 0)
400  {
401    var msg = '<ul>';
402    for (var i = 0; i < response.messages.length; i++)
403    {
404      var msgLine = response.messages[i];
405      if (msgLine.indexOf('[Warning]') >= 0)
406      {
407        msg += '<li class="warning">' + msgLine.replace('[Warning]', '');
408      }
409      else
410      {
411        msg += '<li>' + msgLine;
412      }
413    }
414    msg += '</ul>';
415    setInnerHTML('messages', msg);
416    Main.show('messages');
417  }
418 
419  if (response.status != 'ok')
420  {
421    Main.addClass(document.getElementById('messages'), 'failure');
422    setFatalError(response.message);
423    return false;
424  }
425
426  Main.show('gorestart');
427
428 
429}
430
431
432
433</script>
434<style>
435.fc-info
436{
437  background-color: #F4F4F4;
438  border-top: 1em solid transparent;
439}
440
441.fc-info .subprompt
442{
443  font-weight: normal;
444  padding-left: 2em;
445  text-align: left;
446}
447
448.fc-info .input
449{
450  font-style: italic;
451}
452
453#fc-info-table
454{
455  border-collapse: collapse;
456  background-color: #FFFFFF;
457  border: 1px solid #A0A0A0;
458}
459
460#fc-info-table td, #fc-info-table th
461{
462  padding: 1px 4px 1px 4px;
463  text-align: center;
464  border-left: 1px dotted #A0A0A0;
465  border-right: 1px dotted #A0A0A0;
466}
467
468tr.highlight
469{
470  border-top: 1px dotted #A0A0A0;
471}
472
473.dottedleft
474{
475  border-left: 1px dotted #A0A0A0;
476}
477
478#mergedSequencesTable
479{
480  width: 100%;
481  border-collapse: collapse;
482}
483
484#mergedSequencesTable td
485{
486  text-align: center;
487  min-width: 4.5em;
488}
489
490#mergedSequencesTable tbody td
491{
492  padding-top: 1px;
493  padding-bottom: 1px;
494}
495
496#mergedSequencesTable .italic
497{
498  font-style: italic;
499}
500
501</style>
502</base:head>
503<base:body onload="init()">
504
505  <p:path><p:pathelement 
506    title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
507    /><p:pathelement title="Confirm demux and merge ended" 
508    /></p:path>
509
510  <div class="content">
511  <%
512  if (sc.getActiveProjectId() == 0)
513  {
514    %>
515    <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
516      No project has been selected. You may proceed with the registration but
517      created items will not be shared.
518    </div>
519    <%
520  }
521  %>
522 
523  <div class="allsteps">
524    <div class="step current" id="step.1">1</div>
525    ›
526    <div class="step future" id="step.2">2</div>
527  </div>
528
529  <form name="reggie" onsubmit="return false;">
530 
531  <div id="step.1.section">
532  <table id="step.1.section" class="stepform">
533  <tr>
534    <td rowspan="3" class="stepno">1</td>
535    <td class="steptitle">Select demux job</td>
536  </tr>
537  <tr>
538    <td class="stepfields">
539      <table style="border-collapse: collapse;">
540      <tr valign="top">
541        <td class="prompt">Demux jobs</td>
542        <td class="input"><select class="required" style="width:90%;" 
543            name="seqRuns" id="demuxJobs" onchange="demuxJobOnChange()"></select>
544        </td>
545        <td class="status" id="demuxJobs.status"></td>
546        <td class="help"><span id="demuxJobs.message" class="message" style="display: none;"></span>
547          Select a demux job. The list contains all demux jobs that has
548          ended but has not been confirmed (determined by the absense of AnalysisResult
549          annotation on demuxed sequences items).
550        </td>
551      </tr>
552      <tbody class="fc-info">
553      <tr valign="top">
554        <td class="subprompt">Start date</td>
555        <td class="input" id="startDate" colspan="3"></td>
556      </tr>
557      <tr valign="top">
558        <td class="subprompt">End date</td>
559        <td class="input" id="endDate" colspan="3"></td>
560      </tr>
561      <tr valign="top">
562        <td class="subprompt">Status</td>
563        <td class="input" id="jobStatus" colspan="3"></td>
564      </tr>
565      <tr valign="top">
566        <td class="subprompt">Flow cells</td>
567        <td class="input" id="flowCellsInDemux" colspan="3"></td>
568      </tr>
569      <tr valign="top">
570        <td class="subprompt">Pools</td>
571        <td class="input" id="pools" colspan="3"></td>
572      </tr>
573      <tr valign="top">
574        <td class="subprompt">LibPlates</td>
575        <td class="input" id="libPlates" colspan="3"></td>
576      </tr>
577      <tr valign="top">
578        <td class="subprompt">Comments</td>
579        <td class="input" id="comments" colspan="3"></td>
580      </tr>
581      <tr valign="top">
582        <td class="subprompt">Warnings</td>
583        <td class="input" id="warnings" colspan="3">-</td>
584      </tr>
585      </tbody>
586      </table>
587    </td>
588  </tr>
589  </table>
590  </div>
591 
592  <div id="step.2.section" style="display: none;">
593  <table class="stepform">
594  <tr>
595    <td rowspan="3" class="stepno">2</td>
596    <td class="steptitle" id="step.2.title">Demux job</td>
597  </tr>
598  <tr>
599    <td class="stepfields">
600      <table>
601      <tr valign="top">
602        <td class="prompt">Outcome</td>
603        <td class="input">
604          <label><input type="radio" name="outcome" id="outcomeSuccessful" 
605            onclick="outcomeOnChange()" checked>Success</label> - continue with alignment<br>
606          <label><input type="radio" name="outcome" id="outcomeFailed" 
607            onclick="outcomeOnChange()">Failure</label> - no alignment<br>
608          <img src="../images/joinbottom.gif"><label><input type="checkbox" name="flagPools" value="1" disabled checked>Flag pools for re-clustering</label>
609        </td>
610        <td class="status" id="outcome.status"></td>
611        <td class="help"><span id="outcome.message" class="message" style="display: none;"></span>
612          Select the <b>Success</b> option if the demux was successful and it is possible to continue
613          with filtering and alignment of the sequences.
614          Select the <b>Failure</b> option if it not possible to continue.
615          Existing pooled libraries can optionally
616          be flagged for re-clustering and re-sequencing.
617        </td>
618      </tr>
619      </table>
620     
621      <div id="mergedSequences">
622       
623      </div>
624     
625    </td>
626  </tr>
627  </table>
628  </div>
629   
630  <div class="loading" id="loading" style="display: none;"><table><tr><td><img src="../images/loading.gif"></td><td id="loading.msg">Please wait...</td></tr></table></div>
631 
632  <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>
633 
634  <div id="messages" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div>
635 
636  <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
637    <tr>
638      <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
639      <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)"/></td>
640      <td><base:button id="goregister" title="Register" image="<%=home+"/images/import.png"%>" onclick="goRegister()" style="display: none;"/></td>
641      <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
642      <td id="gonext.message" class="message"></td>
643    </tr>
644  </table>
645 
646  </form>
647  </div>
648 
649</base:body>
650</base:page>
651<%
652}
653finally
654{
655  if (dc != null) dc.close();
656}
657%>
Note: See TracBrowser for help on using the repository browser.