source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/pool_protocol2.jsp @ 2184

Last change on this file since 2184 was 2184, checked in by Nicklas Nordborg, 8 years ago

Fixes #553: Set different volume and mixing strategy for pools on a plate

Added a section in the plate view so that the "Average volume/lib" and "Mixing strategy" can be selected for each pool. Only minor changes required in the protocol generation since most of it was already working per pool.

File size: 21.7 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.core.Extract"
9  import="net.sf.basedb.core.BioMaterial"
10  import="net.sf.basedb.core.MeasuredBioMaterial"
11  import="net.sf.basedb.core.BioMaterialEventSource"
12  import="net.sf.basedb.core.BioPlate"
13  import="net.sf.basedb.core.BioWell"
14  import="net.sf.basedb.core.PermissionDeniedException"
15  import="net.sf.basedb.core.ItemQuery"
16  import="net.sf.basedb.core.query.Restrictions"
17  import="net.sf.basedb.core.query.Hql"
18  import="net.sf.basedb.core.query.Orders"
19  import="net.sf.basedb.util.Values"
20  import="net.sf.basedb.util.formatter.WellCoordinateFormatter"
21  import="net.sf.basedb.util.extensions.Extension"
22  import="net.sf.basedb.clients.web.Base" 
23  import="net.sf.basedb.clients.web.util.HTML"
24  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
25  import="java.util.List"
26  import="java.util.ArrayList"
27%>
28<%
29final SessionControl sc = Base.getExistingSessionControl(request, true);
30final String ID = sc.getId();
31final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
32final String root = request.getContextPath();
33DbControl dc = null;
34try
35{
36  dc = sc.newDbControl();
37  final Extension reggie = ExtensionsControl.get(dc).getExtension("net.sf.basedb.reggie");
38  final User user = User.getById(dc, sc.getLoggedInUserId());
39 
40  Integer[] pools = Values.getInt(request.getParameterValues("pools"));
41 
42  int libPlateId = Values.getInt(request.getParameter("bioplate"));
43  BioPlate libPlate = libPlateId == 0 ? null : BioPlate.getById(dc, libPlateId);
44  String view = Values.getString(request.getParameter("view"), "list");
45%>
46<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
47<html>
48<head>
49  <%
50  if (libPlate != null)
51  {
52    %>
53    <title>Lab protocol for pooling <%=HTML.encodeTags(libPlate.getName())%> - <%=view.equals("list") ? "list" : "table"%></title>
54    <%
55  }
56  else
57  {
58    %>
59    <title>Lab protocol for library pooling - <%=view.equals("list") ? "list" : "table"%></title>
60    <%
61  }
62  %>
63  <link rel="SHORTCUT ICON" href="<%=home%>/images/flowcell.png">
64  <link rel="stylesheet" type="text/css" href="<%=home %>/css/printable.css">
65  <link rel="stylesheet" type="text/css" href="<%=home %>/css/plate.css">
66  <link rel="stylesheet" type="text/css" href="<%=home %>/css/reggie.css">
67  <script language="JavaScript" src="<%=root%>/include/scripts/main.js" type="text/javascript" charset="UTF-8"></script>
68  <script language="JavaScript" src="<%=root%>/include/scripts/ajax.js" type="text/javascript" charset="UTF-8"></script>
69  <script language="JavaScript" src="<%=home %>/reggie.js" type="text/javascript" charset="UTF-8"></script>
70  <script language="JavaScript" src="pools.js" type="text/javascript" charset="UTF-8"></script>
71  <script language="JavaScript" src="plate.js" type="text/javascript" charset="UTF-8"></script>
72 
73  <script language="JavaScript">
74  var debug = 0;
75  var currentStep = 1;
76 
77  // Loaded from servlet when getting Library information
78  var POOL_CURRENT_SCHEMA;
79  var POOL_CURRENT_BARCODE_VARIANT;
80 
81  function init()
82  {
83    // Load information about Library bioplate
84    var libPlate;
85    <%
86    if (libPlateId != 0)
87    {
88      %>
89      // Load Libraries and related info from the selected pools
90      var request = Ajax.getXmlHttpRequest();
91      try
92      {
93        showLoadingAnimation('Loading library bioplate information...');
94        var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibPlateInfo&bioplate=<%=libPlateId%>';   
95        request.open("GET", url, false);
96        request.send(null);
97      }
98      finally
99      {
100        hideLoadingAnimation();
101      }
102     
103      if (debug) Main.debug(request.responseText);
104      var response = JSON.parse(request.responseText);
105      if (response.status != 'ok')
106      {
107        setFatalError(response.message);
108        return false;
109      }
110     
111      libPlate = response.libPlate;
112      POOL_CURRENT_SCHEMA = PoolSchema.getById(libPlate.poolSchema);
113      POOL_CURRENT_BARCODE_VARIANT = PoolSchema.getBarcodeVariantByName(POOL_CURRENT_SCHEMA, libPlate.barcodeVariant);
114      Plate.init(8, 12, POOL_CURRENT_SCHEMA, WellPainter);
115      <%
116    }
117    %>
118   
119    var pools = [<%=Values.getString(java.util.Arrays.asList(pools), ",", true)%>];
120
121    // Load Libraries and related info from the selected pools
122    var request = Ajax.getXmlHttpRequest();
123    try
124    {
125      showLoadingAnimation('Loading pooled library information...');
126      var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibraryInfoForPools&pools='+pools.join(',')+'&bioplate=<%=libPlateId%>';   
127      request.open("GET", url, false);
128      request.send(null);
129    }
130    finally
131    {
132      hideLoadingAnimation();
133    }
134   
135    if (debug) Main.debug(request.responseText);
136    var response = JSON.parse(request.responseText);
137    if (response.status != 'ok')
138    {
139      setFatalError(response.message);
140      return false;
141    }
142   
143    var pools = response.pools;
144    var poolInfo = response.poolInfo;
145
146    var pageTitle = 'Lab protocol for pooling ';
147    // Pre-process the Library items
148    for (var i = 0; i < pools.length; i++)
149    {
150      var pool = pools[i];
151      if (i > 0) pageTitle += ','
152      pageTitle += ' ' + pool.name;
153     
154      // Calculate some pool quantities
155      pool.volume = 1000 * pool.originalQuantity / pool.conc;
156
157      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
158      {
159        var lib = pool.libraries[libNo];
160        PoolMix.calculateLibVolumeForProtocol(lib, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy, true);
161        PoolMix.calculateEbVolume(lib, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy);
162        checkAndPreProcessLibrary(lib, pool, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT, '<%=view%>');       
163      }
164
165      pool.extra = PoolMix.calculateFinalPoolInfo(pool.libraries, pool.targetPoolMolarity, pool.targetVolumePerLib, pool.mixingStrategy);
166    }
167   
168    if (!libPlate)
169    {
170      document.title = pageTitle + ' - <%=view%>';
171    }
172   
173    <%
174    if (view.equals("list"))
175    {
176      %>
177      viewAsList(pools, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT);
178      <%
179    }
180    else
181    {
182      %>
183      viewAsPlate(pools, POOL_CURRENT_SCHEMA, POOL_CURRENT_BARCODE_VARIANT);
184      <%
185    }
186    %>
187  }
188 
189  function checkAndPreProcessLibrary(lib, pool, schema, barcodeVariant, view)
190  {
191    var well = lib.bioWell;
192    var remarks = [];
193
194    // Check if default barcode has been modified
195    if (barcodeVariant)
196    {
197      var indexSet = barcodeVariant.indexSets[well.column];
198      if (indexSet)
199      {
200        var defaultBarcode = indexSet.barcodes[well.row];
201        if (defaultBarcode && lib.barcode.name != defaultBarcode)
202        {
203          remarks[remarks.length] = 'Modified barcode';
204          lib.barcode.modified = true;
205        }
206      }
207    }
208   
209    if (lib.molarity)
210    {
211      if (lib.speedVacConc != null)
212      {
213        remarks[remarks.length] = 'SpeedVac';
214      }
215 
216      if (lib.mixFactor > 1)
217      {
218        // Larger mix than default
219        if (view != 'plate')
220        {
221          remarks[remarks.length] = '<span class="mix-remark">Mix <span class="volume">'+Numbers.formatNumber(lib.actualVolume*lib.mixFactor, 1) + '</span>+<span class="eb">' + Numbers.formatNumber(lib.actualEb*lib.mixFactor, 1)+'µl</span></span>';
222        }
223        remarks[remarks.length] = 'Use <b>' + Numbers.formatNumber(lib.actualVolume+lib.actualEb, 1) + 'µl</b> in pool';
224      }
225
226      lib.remarks = remarks;
227    }
228   
229    if (lib.comment) remarks[remarks.length] = lib.comment;
230  }
231 
232  /**
233    Get the plate coordinate string for a well, optionally including the plate
234    name or not.
235  */
236  function getPlateCoordinate(well, includePlateName)
237  {
238    var c = '';
239    if (well)
240    {
241      if (includePlateName) c += well.bioPlate.name;
242      c += ' ' + WELL_ALPHA[well.row] + (well.column+1);
243    }
244    return c;
245  }
246 
247 
248  function viewAsList(pools, schema, barcodeVariant)
249  {
250    for (var poolNo = 0; poolNo < pools.length; poolNo++)
251    {
252      var pool = pools[poolNo];
253      var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
254
255      var wellsInPool = POOL_CURRENT_SCHEMA ? Plate.getPool(realPoolNo) : null;
256     
257      var html = '';
258      var tbody = document.getElementById('listview.'+pool.id+'.body');
259     
260      var wellIndex = 0;
261      for (var j = 0; j < pool.libraries.length; j++)
262      {
263        var lib = pool.libraries[j];
264        var well = lib.bioWell;
265       
266        var tr = document.createElement('tr');
267        if (POOL_CURRENT_SCHEMA)
268        {
269          wellIndex = createMissingRows(tbody, wellsInPool, wellIndex, well, barcodeVariant);
270          tr.className = well.column % 2 == 0 ? "evencol" : "oddcol";
271        }
272        else
273        {
274          tr.className = 'evencol';
275        }
276   
277        if (barcodeVariant)
278        {
279          var indexSet = barcodeVariant.indexSets[well.column];
280          if (indexSet)
281          {
282            tr.className = lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
283          }
284        }
285
286        addColumn(tr, 'lib', lib.name);
287        addColumn(tr, 'remain', Numbers.formatNumber((lib.remainingVolume), 1));
288        addColumn(tr, 'molarity', Numbers.formatNumber(lib.molarity, 2));
289        <%
290        if (libPlate==null)
291        {
292          %>
293          addColumn(tr, 'workplate', well.bioPlate.name + ' ' + well.location);
294          <%
295        }
296        else
297        {
298          %>
299          addColumn(tr, 'workplate', well.location);
300          <%
301        }
302        %>
303        var mixFactor = lib.mixFactor || 1.0;
304        addColumn(tr, 'volume', mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualVolume, 1));
305        addColumn(tr, 'eb', pool.mixingStrategy == 'dynamic' || mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualEb, 1));
306        addColumn(tr, "remarks", lib.remarks.join('; '));
307        tbody.appendChild(tr);
308      }
309      if (POOL_CURRENT_SCHEMA)
310      {
311        createMissingRows(tbody, wellsInPool, wellIndex, null, barcodeVariant);
312      }
313     
314      var poolData = '<div class="pool-data">';
315      poolData += pool.libraries.length + ' libs; ';
316      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM; ';
317      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
318      poolData += '<br>Mixing strategy: ' + pool.mixingStrategy;
319      poolData += '</div>';
320      setInnerHTML('molarity.'+pool.id, poolData);
321      setInnerHTML('eb-volume.'+pool.id, Numbers.formatNumber(Math.max(0, pool.extra.ebVolumeExtra), 1));
322      Main.show('pool.'+pool.id);
323    }
324  }
325 
326  function createMissingRows(table, wellsInPool, wellIndex, well, barcodeVariant)
327  {
328    var wellAtIndex = wellsInPool[wellIndex]; // Empty??
329    if (!well) well = {'row': -1, 'column': -1};
330    while (wellAtIndex.row != well.row || wellAtIndex.column != well.column)
331    {
332      var tr = document.createElement('tr');
333      tr.className = 'empty';
334      if (barcodeVariant)
335      {
336        var indexSet = barcodeVariant.indexSets[wellAtIndex.column];
337        if (indexSet) tr.className += ' ' + indexSet.color;
338      }
339     
340      addColumn(tr, 'lib', 'not pooled');
341      addColumn(tr, 'remain', '');
342      addColumn(tr, 'molarity', '');
343      addColumn(tr, 'workplate', WELL_ALPHA[wellAtIndex.row] + (wellAtIndex.column+1));
344      addColumn(tr, 'volume', '');
345      addColumn(tr, 'eb', '');
346      addColumn(tr, 'remarks', '');
347      table.appendChild(tr);
348      wellIndex++;
349      if (wellIndex >= wellsInPool.length) break;
350      wellAtIndex = wellsInPool[wellIndex];
351    }
352    return wellIndex+1;
353  }
354 
355  function addColumn(tr, className, html)
356  {
357    var td = document.createElement('td');
358    td.className = className;
359    td.innerHTML = html;
360    tr.appendChild(td);
361  }
362 
363  function viewAsPlate(pools, schema, barcodeVariant)
364  {
365    for (var poolNo = 0; poolNo < pools.length; poolNo++)
366    {
367      var pool = pools[poolNo];
368      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
369      {
370        var lib = pool.libraries[libNo];
371        var well = lib.bioWell;
372        Plate.getWell(well.row, well.column).setExtract(lib);
373      }
374    }
375
376    WellPainter.barcodeVariant = barcodeVariant;
377    PoolSchema.buildPoolTableRow(schema, 12);
378    Main.show('plateview');
379   
380    for (var poolNo = 0; poolNo < pools.length; poolNo++)
381    {
382      var pool = pools[poolNo];
383      var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
384      WellPainter.mixingStrategy = pool.mixingStrategy;
385      Plate.paint(Plate.getPool(realPoolNo));
386     
387      var poolData = '<div class="pool-data">';
388      poolData += pool.libraries.length + ' libs  ';
389      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM  ';
390      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
391      if (pool.mixingStrategy == 'dynamic')
392      {
393        poolData += '  <span class="pool-eb">'+Numbers.formatNumber(pool.extra.ebVolumeExtra, 1, 'µl')+'</span>';
394      }
395      poolData += '<br>Mixing strategy: ' + pool.mixingStrategy;
396      poolData += '<div class="comments">'+pool.comments+'</div>';
397      poolData += '</div>';
398     
399      document.getElementById('pool.'+realPoolNo).innerHTML = pool.name + poolData;
400    }
401  }
402
403  var WellPainter = function()
404  {
405    var painter = {};
406   
407    painter.getClassNameForWell = function(well, schema)
408    {
409      var cls = '';
410      var indexSet = painter.barcodeVariant.indexSets[well.column];
411      if (indexSet)
412      {
413        var lib = well.extract;
414        cls += lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
415      }
416      return cls;
417    }
418   
419    painter.getWellText = function(well, schema)
420    {
421      var text = '';
422      var lib = well.extract;
423      if (lib)
424      {
425        var name = lib.name;
426        var mixFactor = lib.mixFactor || 1.0;
427        var i = name.indexOf('.m');
428        text += '<div class="lib">'+name.substring(0, i)+'.<br>&nbsp;'+name.substring(i)+'</div>';
429        text += '<div><span class="volume">'+Numbers.formatNumber(lib.actualVolume*mixFactor, 1)+'µl</span>';
430        if (painter.mixingStrategy == 'fixed' || lib.mixFactor > 1.001)
431        {
432          text += '<span class="eb">'+Numbers.formatNumber(lib.actualEb*mixFactor, 1)+'µl</span>';
433        }
434        else
435        {
436          text += '<span class="eb"></span>';
437        }
438        //text+=lib.eb+':'+lib.mixFactor;
439        text += '</div>';
440        text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
441      }
442      return text;
443    }
444
445    return painter;
446  }();
447  </script>
448  <style>
449  table.protocolheader
450  {
451    width: 100%;
452    border: 1px solid #000000;
453    margin-bottom: 1em;
454    border-collapse: collapse;
455  }
456
457  table.protocolheader > tbody > tr
458  {
459    vertical-align: top;
460    height: 1.25em;
461  }
462
463  table.protocolheader > tbody > tr > th
464  {
465    text-align: left;
466    font-size: 1em;
467    background-color: #F0F0F0;
468    padding: 2px;
469  }
470 
471  table.protocolheader > tbody > tr > td
472  {
473    text-align: left;
474    font-size: 1em;
475    padding: 2px;
476  }
477
478  .pool-section
479  {
480    page-break-inside: avoid;
481  }
482
483  table.poolheader
484  {
485    margin-top: 1em;
486    width: 100%;
487    border: 1px solid #000000;
488    border-bottom: 0px;
489    border-collapse: collapse;
490  }
491
492  table.poolheader > tbody > tr
493  {
494    height: 1.25em;
495  }
496
497  table.poolheader > tbody > tr > th
498  {
499    text-align: left;
500    font-size: 1.25em;
501    padding: 1px;
502  }
503 
504  .listview
505  {
506    width: 100%;
507    font-size: 85%;
508    border-collapse: collapse;
509    border: 1px solid #000000;
510  }
511 
512  .listview tr.oddcol
513  {
514    background-color: #F0F0F0;
515  }
516 
517  .listview thead
518  {
519    border: 1px solid #000000;
520    background-color: #F0F0F0;
521  }
522 
523  .listview th
524  {
525    border-left: 1px solid #000000;
526  }
527 
528  .listview td
529  {
530    border-left: 1px solid #000000;
531    border-top: 1px dotted #666666;
532    vertical-align: middle;
533    padding: 2px;
534  }
535 
536  .listview .summary
537  {
538    border-top: 1px solid #000000;
539  }
540 
541  .listview .col-num
542  {
543    width: 1.75em;
544    text-align: center;
545    font-size: 125%;
546    font-weight: bold;
547    vertical-align: top;
548  }
549 
550  .listview .lib
551  {
552    width: 15em;
553    text-align: center;
554  }
555 
556  .listview .empty .lib
557  {
558    font-style: italic;
559    color: #666666;
560    text-align: center;
561  }
562 
563  .listview .workplate
564  {
565 
566    width: <%=libPlate==null ? "14em" : "7em"%>;
567    text-align: center;
568  }
569 
570  .listview .pool
571  {
572    width: 7em;
573    text-align: center;
574  }
575 
576  .listview .remain, .listview .molarity
577  {
578    width: 4.5em;
579    padding-right: 0.5em;
580    text-align: right;
581  }
582
583  .listview .volume
584  {
585    width: 3.5em;
586    padding-right: 0.5em;
587    text-align: right;
588    color: #C80000;
589  }
590 
591  .listview .eb
592  {
593    width: 3.5em;
594    padding-right: 0.5em;
595    text-align: right;
596    color: #0000C8;
597  }
598 
599  .listview .remarks
600  {
601    vertical-align: top;
602    padding-left: 0.25em;
603  }
604 
605  .mix-remark .volume, .mix-remark .eb
606  {
607    padding: 0;
608    text-align: inherit;
609    width: inherit;
610    font-weight: bold;
611  }
612
613 
614 
615  /* Divide the 12 wells across the full page */
616  #plateview .well
617  {
618    width: 8.2%;
619    max-width: 8.2%;
620    min-width: 8.2%;
621    padding: 4px;
622  }
623 
624  #plateview .well:hover
625  {
626    padding: 3px;
627  }
628 
629  #plateview .rowheader
630  {
631    width: 2em;
632  }
633 
634  #plateview .lib
635  {
636    font-weight: bold;
637    margin-bottom: 0.25em;
638  }
639  #plateview .volume
640  {
641    color: #C80000;
642  }
643  #plateview .eb
644  {
645    color: #0000C8;
646    float: right;
647  }
648 
649  #plateview .remarks
650  {
651    color: #C80000;
652    font-style: italic;
653  }
654 
655  #plateview .mix-remark
656  {
657    display: none;
658  }
659 
660  .pool-eb
661  {
662    color: #0000C8;
663  }
664 
665  #pool-row th
666  {
667    border-top: 0;
668    border-bottom: 1px solid #808080;
669    vertical-align: top;
670    padding: 0;
671  }
672 
673  #plateview .pool-data
674  {
675    font-weight: normal;
676  }
677  #plateview .comments
678  {
679    font-style: italic;
680  }
681 
682 
683  </style>
684</head>
685<body onload="init()">
686  <div class="paper <%=view.equals("list") ? "" : "landscape"%>">
687  <div class="noprint fullwidth" style="border-bottom: 1px dashed #A0A0A0; padding-left: 1em; padding-bottom: 1em;">
688    <span class="button" onclick="window.print()" style="float: left; margin-right: 1em;">
689      <img src="../images/print.png">Print&hellip;
690    </span>
691    <b>Note!</b> 
692    <%
693    if (view.equals("list"))
694    {
695      %>
696      For better printing reduce margins to about <i>5mm</i> and set page orientation
697      to <i>portrait</i>. To fit everything on a single page, scale down to <i>60-70%</i>.
698      <%
699    }
700    else
701    {
702      %>
703      For better printing reduce margins to about <i>5mm</i> and set page orientation
704      to <i>landscape</i>. The recommended scale is <i>100%</i>.
705      <%
706    }
707    %>
708    <br clear="all">
709  </div>
710 
711  <h1>Lab protocol for library pooling <span class="reggie">Reggie <%=reggie.getAbout().getVersion() %></span></h1>
712
713  <table style="width: 100%;" class="protocolheader">
714  <tr style="border-bottom: 1px solid #000000;">
715    <th style="width: 15%;">Library plate</th>
716    <td style="width: 30%; border-right: 1px solid #000000;"><%=libPlate == null ? "Multiple" : HTML.encodeTags(libPlate.getName())%></td>
717    <th style="width: 15%;"></th>
718    <th style="width: 20%;">Date</th>
719    <th style="width: 20%;">Operator</th>
720  </tr>
721  <tr>
722    <td rowspan="1" colspan="2" style="width: 50%; border-right: 1px solid #000000;"><%=libPlate != null ? HTML.niceFormat(libPlate.getDescription()) : ""%></td>
723    <td style="border-right: 1px solid #000000;">Pooling</td>
724    <td style="border-right: 1px solid #000000;"></td>
725    <td></td>
726  </tr>
727  </table>
728
729  <%
730  if (view.equals("list"))
731  {
732    for (Integer poolId :pools)
733    {
734      Extract pool = Extract.getById(dc, poolId);
735      %>
736      <div id="pool.<%=poolId%>" style="display: none;" class="pool-section">
737      <table style="width: 100%;" class="poolheader">
738      <tr valign="top">
739        <th style="width: 25%;"><%=HTML.encodeTags(pool.getName())%></th>
740        <th style="width: 75%; border-left: 1px solid #000000;">Comments:</th>
741      </tr>
742      <tr valign="top">
743        <td style="width: 25%;"><span id="molarity.<%=poolId%>"></span></td>
744        <td style="border-left: 1px solid #000000;"><%=HTML.niceFormat(pool.getDescription()) %></td>
745      </tr>
746      </table>
747      <table style="width: 100%;" class="listview" id="listview.<%=poolId%>">
748      <thead>
749        <tr class="toprow">
750          <th class="lib"></th>
751          <th>Remain</th>
752          <th>DNA</th>
753          <th class="workplate">Work</th>
754          <th>Lib</th>
755          <th>EB</th>
756          <th></th>
757        </tr>
758        <tr>
759          <th class="lib">Library</th>
760          <th>(µl)</th>
761          <th>(nM)</th>
762          <th class="workplate">plate</th>
763          <th>(µl)</th>
764          <th>(µl)</th>
765          <th>Remarks</th>
766        </tr>
767      </thead>
768      <tbody id="listview.<%=poolId%>.body">
769      </tbody>
770      <tbody>
771        <tr class="summary">
772          <td colspan="5" style="text-align: right; font-weight: bold; padding-right: 0.5em; font-size: 120%;">EB volume to add</td>
773          <td id="eb-volume.<%=poolId%>" class="eb">eb</td>
774          <td></td>
775        </tr>
776      </tbody>
777      </table>
778      </div>
779      <%
780    }
781  }
782  %>
783
784  <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>
785  <div class="messagecontainer error" id="errorMessage" style="display: none;"></div>
786  <%
787
788  if (view.equals("plate"))
789  {
790    %>
791    <table class="plate" style="margin: 0em 0 0 0; width: 100%; display: none;" id="plateview">
792    <tr id="pool-row">
793      <th colspan="13">&nbsp;</th>
794    </tr>
795    <%
796    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
797    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
798    %>
799    <tr class="header">
800      <th></th>
801      <%
802      for (int c = 0; c < libPlate.getColumns(); ++c)
803      {
804        %>
805        <th id="col.<%=c%>"><%=colF.format(c)%></th>
806        <%
807      }
808      %>
809    </tr>
810    <tbody>
811    <%
812    for (int r = 0; r < libPlate.getRows(); ++r)
813    {
814      String row = rowF.format(r);
815      %>
816      <tr class="row-<%=r%>">
817        <th id="row.<%=r%>" class="rowheader"><%=row%></th>
818        <%
819        for (int c = 0; c < libPlate.getColumns(); ++c)
820        {
821          %>
822          <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"></td>
823          <%
824        }
825        %>
826      </tr>
827      <%
828    }
829    %>
830    </tbody>
831    </table>
832    <div style="margin: 1em;">
833      For each pool: <i>Number of libraries</i> • <i>Final molarity</i> • <i>Total volume</i> • <i>EB volume (dynamic mixing only)</i>
834    </div>
835    <%
836  }
837  %>
838  </div>
839</body>
840</html>
841<%
842}
843finally
844{
845  if (dc != null) dc.close();
846}
847%>
Note: See TracBrowser for help on using the repository browser.