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

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

References #548: Register Demux and Merge as ended

Remove job folder input field since it doens't do anything.

File size: 17.4 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      html += '<td class="dottedleft"><input type="checkbox" name="flag.'+merged.id+'"></td>';
266    }
267   
268    html += '<td class="dottedleft"><input type="checkbox" name="align.'+merged.id+'" '+alignChecked+'></td>';
269    html += '<td class="dottedleft"><input type="text" name="comment.'+merged.id+'" style="width: 20em;"></td>';
270    html += '</tr>';
271  }
272  html += '</tbody>';
273  html += '</table>';
274  setInnerHTML('mergedSequences', html);
275 
276  if (job.status == 'ERROR')
277  {
278    Doc.element('outcomeFailed').checked = true;
279    outcomeOnChange();
280  }
281
282}
283
284
285function getMergedSequences()
286{
287  var frm = document.forms['reggie'];
288  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
289 
290  var request = Ajax.getXmlHttpRequest();
291  try
292  {
293    showLoadingAnimation('Loading merged sequences...');
294    var url = '../DemuxMerge.servlet?ID=<%=ID%>&cmd=GetMergedSequences&job='+job.id;   
295    request.open("GET", url, false); 
296    request.send(null);
297  }
298  finally
299  {
300    hideLoadingAnimation();
301  }
302 
303  if (debug) Main.debug(request.responseText);
304  var response = JSON.parse(request.responseText); 
305  if (response.status != 'ok')
306  {
307    setFatalError(response.message);
308    return false;
309  }
310  return response.mergedSequences;
311
312}
313
314function outcomeOnChange()
315{
316  var frm = document.forms['reggie'];
317  var failed = document.getElementById('outcomeFailed').checked;
318  frm.flagPools.disabled = !failed;
319 
320  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
321  var mergedSequences = job.mergedSequences;
322 
323  for (var mergeNo = 0; mergeNo < mergedSequences.length; mergeNo++)
324  {
325    var merge = mergedSequences[mergeNo];
326    if (frm['flag.'+merge.id])
327    {
328      frm['flag.'+merge.id].disabled = failed;
329    }
330    frm['align.'+merge.id].disabled = failed;
331  }
332 
333}
334
335
336function goRegister()
337{
338  if (!step2IsValid()) return;
339  var failed = document.getElementById('outcomeFailed').checked;
340
341  var frm = document.forms['reggie'];
342  Main.addClass(document.getElementById('step.2.section'), 'disabled');
343 
344 
345  Main.hide('goregister');
346  Main.hide('gocancel');
347  Main.hide('gonext.message');
348 
349  var submitInfo = {};
350 
351  submitInfo.failed = failed;
352  submitInfo.flagPools = !frm.flagPools.disabled && frm.flagPools.checked ? true : false;
353 
354  var job = frm.demuxJobs[frm.demuxJobs.selectedIndex].job;
355  var demuxedSequences = job.demuxedSequences;
356  var mergedSequences = job.mergedSequences;
357 
358  var demux = [];
359  submitInfo.demuxedSequences = demux;
360  for (var demuxNo = 0; demuxNo < demuxedSequences.length; demuxNo++)
361  {
362    var dx = demuxedSequences[demuxNo];
363    var tmp = {};
364    tmp.id = dx.id;
365    demux[demux.length] = tmp;
366  }
367 
368  var merged = [];
369  submitInfo.mergedSequences = merged;
370  for (var mergeNo = 0; mergeNo < mergedSequences.length; mergeNo++)
371  {
372    var merge = mergedSequences[mergeNo];
373    var tmp = {};
374    tmp.id = merge.id;
375    tmp.flag = frm['flag.'+merge.id] && frm['flag.'+merge.id].checked;
376    tmp.align = frm['align.'+merge.id].checked;
377    tmp.comment = frm['comment.'+merge.id].value;
378    merged[merged.length] = tmp;
379  }
380 
381  if (debug) Main.debug(JSON.stringify(submitInfo));
382  var url = '../DemuxMerge.servlet?ID=<%=ID%>&cmd=RegisterDemuxAndMerge';
383  var request = Ajax.getXmlHttpRequest();
384  try
385  {
386    showLoadingAnimation('Performing registration...');
387    request.open("POST", url, false);
388    request.send(JSON.stringify(submitInfo));
389  }
390  finally
391  {
392    hideLoadingAnimation();
393  }
394 
395  if (debug) Main.debug(request.responseText);
396  var response = JSON.parse(request.responseText);
397 
398  if (response.messages && response.messages.length > 0)
399  {
400    var msg = '<ul>';
401    for (var i = 0; i < response.messages.length; i++)
402    {
403      var msgLine = response.messages[i];
404      if (msgLine.indexOf('[Warning]') >= 0)
405      {
406        msg += '<li class="warning">' + msgLine.replace('[Warning]', '');
407      }
408      else
409      {
410        msg += '<li>' + msgLine;
411      }
412    }
413    msg += '</ul>';
414    setInnerHTML('messages', msg);
415    Main.show('messages');
416  }
417 
418  if (response.status != 'ok')
419  {
420    Main.addClass(document.getElementById('messages'), 'failure');
421    setFatalError(response.message);
422    return false;
423  }
424
425  Main.show('gorestart');
426
427 
428}
429
430
431
432</script>
433<style>
434.fc-info
435{
436  background-color: #F4F4F4;
437  border-top: 1em solid transparent;
438}
439
440.fc-info .subprompt
441{
442  font-weight: normal;
443  padding-left: 2em;
444  text-align: left;
445}
446
447.fc-info .input
448{
449  font-style: italic;
450}
451
452#fc-info-table
453{
454  border-collapse: collapse;
455  background-color: #FFFFFF;
456  border: 1px solid #A0A0A0;
457}
458
459#fc-info-table td, #fc-info-table th
460{
461  padding: 1px 4px 1px 4px;
462  text-align: center;
463  border-left: 1px dotted #A0A0A0;
464  border-right: 1px dotted #A0A0A0;
465}
466
467tr.highlight
468{
469  border-top: 1px dotted #A0A0A0;
470}
471
472.dottedleft
473{
474  border-left: 1px dotted #A0A0A0;
475}
476
477#mergedSequencesTable
478{
479  width: 100%;
480  border-collapse: collapse;
481}
482
483#mergedSequencesTable td
484{
485  text-align: center;
486  min-width: 4.5em;
487}
488
489#mergedSequencesTable tbody td
490{
491  padding-top: 1px;
492  padding-bottom: 1px;
493}
494
495#mergedSequencesTable .italic
496{
497  font-style: italic;
498}
499
500</style>
501</base:head>
502<base:body onload="init()">
503
504  <p:path><p:pathelement 
505    title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
506    /><p:pathelement title="Confirm demux and merge ended" 
507    /></p:path>
508
509  <div class="content">
510  <%
511  if (sc.getActiveProjectId() == 0)
512  {
513    %>
514    <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
515      No project has been selected. You may proceed with the registration but
516      created items will not be shared.
517    </div>
518    <%
519  }
520  %>
521 
522  <div class="allsteps">
523    <div class="step current" id="step.1">1</div>
524    ›
525    <div class="step future" id="step.2">2</div>
526  </div>
527
528  <form name="reggie" onsubmit="return false;">
529 
530  <div id="step.1.section">
531  <table id="step.1.section" class="stepform">
532  <tr>
533    <td rowspan="3" class="stepno">1</td>
534    <td class="steptitle">Select demux job</td>
535  </tr>
536  <tr>
537    <td class="stepfields">
538      <table style="border-collapse: collapse;">
539      <tr valign="top">
540        <td class="prompt">Demux jobs</td>
541        <td class="input"><select class="required" style="width:90%;" 
542            name="seqRuns" id="demuxJobs" onchange="demuxJobOnChange()"></select>
543        </td>
544        <td class="status" id="demuxJobs.status"></td>
545        <td class="help"><span id="demuxJobs.message" class="message" style="display: none;"></span>
546          Select a demux job. The list contains all demux jobs that has
547          ended but has not been confirmed (determined by the absense of AnalysisResult
548          annotation on demuxed sequences items).
549        </td>
550      </tr>
551      <tbody class="fc-info">
552      <tr valign="top">
553        <td class="subprompt">Start date</td>
554        <td class="input" id="startDate" colspan="3"></td>
555      </tr>
556      <tr valign="top">
557        <td class="subprompt">End date</td>
558        <td class="input" id="endDate" colspan="3"></td>
559      </tr>
560      <tr valign="top">
561        <td class="subprompt">Status</td>
562        <td class="input" id="jobStatus" colspan="3"></td>
563      </tr>
564      <tr valign="top">
565        <td class="subprompt">Flow cells</td>
566        <td class="input" id="flowCellsInDemux" colspan="3"></td>
567      </tr>
568      <tr valign="top">
569        <td class="subprompt">Pools</td>
570        <td class="input" id="pools" colspan="3"></td>
571      </tr>
572      <tr valign="top">
573        <td class="subprompt">LibPlates</td>
574        <td class="input" id="libPlates" colspan="3"></td>
575      </tr>
576      <tr valign="top">
577        <td class="subprompt">Comments</td>
578        <td class="input" id="comments" colspan="3"></td>
579      </tr>
580      <tr valign="top">
581        <td class="subprompt">Warnings</td>
582        <td class="input" id="warnings" colspan="3">-</td>
583      </tr>
584      </tbody>
585      </table>
586    </td>
587  </tr>
588  </table>
589  </div>
590 
591  <div id="step.2.section" style="display: none;">
592  <table class="stepform">
593  <tr>
594    <td rowspan="3" class="stepno">2</td>
595    <td class="steptitle" id="step.2.title">Demux job</td>
596  </tr>
597  <tr>
598    <td class="stepfields">
599      <table>
600      <tr valign="top">
601        <td class="prompt">Outcome</td>
602        <td class="input">
603          <label><input type="radio" name="outcome" id="outcomeSuccessful" 
604            onclick="outcomeOnChange()" checked>Success</label> - continue with alignment<br>
605          <label><input type="radio" name="outcome" id="outcomeFailed" 
606            onclick="outcomeOnChange()">Failure</label> - no alignment<br>
607          <img src="../images/joinbottom.gif"><label><input type="checkbox" name="flagPools" value="1" disabled checked>Flag pools for re-clustering</label>
608        </td>
609        <td class="status" id="outcome.status"></td>
610        <td class="help"><span id="outcome.message" class="message" style="display: none;"></span>
611          Select the <b>Success</b> option if the demux was successful and it is possible to continue
612          with filtering and alignment of the sequences.
613          Select the <b>Failure</b> option if it not possible to continue.
614          Existing pooled libraries can optionally
615          be flagged for re-clustering and re-sequencing.
616        </td>
617      </tr>
618      </table>
619     
620      <div id="mergedSequences">
621       
622      </div>
623     
624    </td>
625  </tr>
626  </table>
627  </div>
628   
629  <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>
630 
631  <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>
632 
633  <div id="messages" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div>
634 
635  <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
636    <tr>
637      <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
638      <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)"/></td>
639      <td><base:button id="goregister" title="Register" image="<%=home+"/images/import.png"%>" onclick="goRegister()" style="display: none;"/></td>
640      <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
641      <td id="gonext.message" class="message"></td>
642    </tr>
643  </table>
644 
645  </form>
646  </div>
647 
648</base:body>
649</base:page>
650<%
651}
652finally
653{
654  if (dc != null) dc.close();
655}
656%>
Note: See TracBrowser for help on using the repository browser.