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

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

References #527: Implement manual pooled library selection

Re-factored the volume calculations. There are some additional cases that could not happen before that must be considered. One example is that libraries may have lower remaining quantity than 5 or 10 µl which may result that there is not enough material even if the molarity is higher than 2.0nM.

For all calculations to be reproducable when generating the protocol we need to store both the target molarity and target volume on the pool so PoolTargetMolarity has been added as an annotation.

File size: 21.3 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 i = 0; i < pools.length; i++)
251    {
252      var pool = pools[i];
253      var wellsInPool = POOL_CURRENT_SCHEMA ? Plate.getPool(i) : null;
254     
255      var html = '';
256      var tbody = document.getElementById('listview.'+pool.id+'.body');
257     
258      var wellIndex = 0;
259      for (var j = 0; j < pool.libraries.length; j++)
260      {
261        var lib = pool.libraries[j];
262        var well = lib.bioWell;
263       
264        var tr = document.createElement('tr');
265        if (POOL_CURRENT_SCHEMA)
266        {
267          wellIndex = createMissingRows(tbody, wellsInPool, wellIndex, well, barcodeVariant);
268          tr.className = well.column % 2 == 0 ? "evencol" : "oddcol";
269        }
270        else
271        {
272          tr.className = 'evencol';
273        }
274   
275        if (barcodeVariant)
276        {
277          var indexSet = barcodeVariant.indexSets[well.column];
278          if (indexSet)
279          {
280            tr.className = lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
281          }
282        }
283
284        addColumn(tr, 'lib', lib.name);
285        addColumn(tr, 'remain', Numbers.formatNumber((lib.remainingVolume), 1));
286        addColumn(tr, 'molarity', Numbers.formatNumber(lib.molarity, 2));
287        <%
288        if (libPlate==null)
289        {
290          %>
291          addColumn(tr, 'workplate', well.bioPlate.name + ' ' + well.location);
292          <%
293        }
294        else
295        {
296          %>
297          addColumn(tr, 'workplate', well.location);
298          <%
299        }
300        %>
301        var mixFactor = lib.mixFactor || 1.0;
302        addColumn(tr, 'volume', mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualVolume, 1));
303        addColumn(tr, 'eb', pool.mixingStrategy == 'dynamic' || mixFactor > 1.0 ? '—' : Numbers.formatNumber(lib.actualEb, 1));
304        addColumn(tr, "remarks", lib.remarks.join('; '));
305        tbody.appendChild(tr);
306      }
307      if (POOL_CURRENT_SCHEMA)
308      {
309        createMissingRows(tbody, wellsInPool, wellIndex, null, barcodeVariant);
310      }
311     
312      var poolData = '<div class="pool-data">';
313      poolData += pool.libraries.length + ' libs; ';
314      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM; ';
315      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
316      poolData += '</div>';
317      setInnerHTML('molarity.'+pool.id, poolData);
318      setInnerHTML('eb-volume.'+pool.id, Numbers.formatNumber(Math.max(0, pool.extra.ebVolumeExtra), 1));
319      Main.show('pool.'+pool.id);
320    }
321  }
322 
323  function createMissingRows(table, wellsInPool, wellIndex, well, barcodeVariant)
324  {
325    var wellAtIndex = wellsInPool[wellIndex]; // Empty??
326    if (!well) well = {'row': -1, 'column': -1};
327    while (wellAtIndex.row != well.row || wellAtIndex.column != well.column)
328    {
329      var tr = document.createElement('tr');
330      tr.className = 'empty';
331      if (barcodeVariant)
332      {
333        var indexSet = barcodeVariant.indexSets[wellAtIndex.column];
334        if (indexSet) tr.className += ' ' + indexSet.color;
335      }
336     
337      addColumn(tr, 'lib', 'not pooled');
338      addColumn(tr, 'remain', '');
339      addColumn(tr, 'molarity', '');
340      addColumn(tr, 'workplate', WELL_ALPHA[wellAtIndex.row] + (wellAtIndex.column+1));
341      addColumn(tr, 'volume', '');
342      addColumn(tr, 'eb', '');
343      addColumn(tr, 'remarks', '');
344      table.appendChild(tr);
345      wellIndex++;
346      if (wellIndex >= wellsInPool.length) break;
347      wellAtIndex = wellsInPool[wellIndex];
348    }
349    return wellIndex+1;
350  }
351 
352  function addColumn(tr, className, html)
353  {
354    var td = document.createElement('td');
355    td.className = className;
356    td.innerHTML = html;
357    tr.appendChild(td);
358  }
359 
360  function viewAsPlate(pools, schema, barcodeVariant)
361  {
362    for (var poolNo = 0; poolNo < pools.length; poolNo++)
363    {
364      var pool = pools[poolNo];
365      for (var libNo = 0; libNo < pool.libraries.length; libNo++)
366      {
367        var lib = pool.libraries[libNo];
368        var well = lib.bioWell;
369        Plate.getWell(well.row, well.column).setExtract(lib);
370      }
371    }
372
373    WellPainter.barcodeVariant = barcodeVariant;
374    WellPainter.mixingStrategy = pools[0].mixingStrategy;
375    Plate.paint(Plate.getWells());
376    PoolSchema.buildPoolTableRow(schema, 12);
377    Main.show('plateview');
378   
379    for (var poolNo = 0; poolNo < pools.length; poolNo++)
380    {
381      var pool = pools[poolNo];
382      var poolData = '<div class="pool-data">';
383      poolData += pool.libraries.length + ' libs  ';
384      poolData += Numbers.formatNumber(pool.molarity, 2)+'nM  ';
385      poolData += Numbers.formatNumber(pool.volume, 1) + 'µl';
386      if (pool.mixingStrategy == 'dynamic')
387      {
388        poolData += '  <span class="pool-eb">'+Numbers.formatNumber(pool.extra.ebVolumeExtra, 1, 'µl')+'</span>';
389      }
390      poolData += '<div class="comments">'+pool.comments+'</div>';
391      poolData += '</div>';
392     
393      var realPoolNo = schema.getPoolNumForColumn(pool.libraries[0].bioWell.column);
394      document.getElementById('pool.'+realPoolNo).innerHTML = pool.name + poolData;
395    }
396  }
397
398  var WellPainter = function()
399  {
400    var painter = {};
401   
402    painter.getClassNameForWell = function(well, schema)
403    {
404      var cls = '';
405      var indexSet = painter.barcodeVariant.indexSets[well.column];
406      if (indexSet)
407      {
408        var lib = well.extract;
409        cls += lib && lib.barcode.modified ? 'bg-modified' : indexSet.color;
410      }
411      return cls;
412    }
413   
414    painter.getWellText = function(well, schema)
415    {
416      var text = '';
417      var lib = well.extract;
418      if (lib)
419      {
420        var name = lib.name;
421        var mixFactor = lib.mixFactor || 1.0;
422        var i = name.indexOf('.m');
423        text += '<div class="lib">'+name.substring(0, i)+'.<br>&nbsp;'+name.substring(i)+'</div>';
424        text += '<div><span class="volume">'+Numbers.formatNumber(lib.actualVolume*mixFactor, 1)+'µl</span>';
425        if (painter.mixingStrategy == 'fixed' || lib.mixFactor > 1.001)
426        {
427          text += '<span class="eb">'+Numbers.formatNumber(lib.actualEb*mixFactor, 1)+'µl</span>';
428        }
429        else
430        {
431          text += '<span class="eb"></span>';
432        }
433        //text+=lib.eb+':'+lib.mixFactor;
434        text += '</div>';
435        text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
436      }
437      return text;
438    }
439
440    return painter;
441  }();
442  </script>
443  <style>
444  table.protocolheader
445  {
446    width: 100%;
447    border: 1px solid #000000;
448    margin-bottom: 1em;
449    border-collapse: collapse;
450  }
451
452  table.protocolheader > tbody > tr
453  {
454    vertical-align: top;
455    height: 1.25em;
456  }
457
458  table.protocolheader > tbody > tr > th
459  {
460    text-align: left;
461    font-size: 1em;
462    background-color: #F0F0F0;
463    padding: 2px;
464  }
465 
466  table.protocolheader > tbody > tr > td
467  {
468    text-align: left;
469    font-size: 1em;
470    padding: 2px;
471  }
472
473  .pool-section
474  {
475    page-break-inside: avoid;
476  }
477
478  table.poolheader
479  {
480    margin-top: 1em;
481    width: 100%;
482    border: 1px solid #000000;
483    border-bottom: 0px;
484    border-collapse: collapse;
485  }
486
487  table.poolheader > tbody > tr
488  {
489    height: 1.25em;
490  }
491
492  table.poolheader > tbody > tr > th
493  {
494    text-align: left;
495    font-size: 1.25em;
496    padding: 1px;
497  }
498 
499  .listview
500  {
501    width: 100%;
502    font-size: 85%;
503    border-collapse: collapse;
504    border: 1px solid #000000;
505  }
506 
507  .listview tr.oddcol
508  {
509    background-color: #F0F0F0;
510  }
511 
512  .listview thead
513  {
514    border: 1px solid #000000;
515    background-color: #F0F0F0;
516  }
517 
518  .listview th
519  {
520    border-left: 1px solid #000000;
521  }
522 
523  .listview td
524  {
525    border-left: 1px solid #000000;
526    border-top: 1px dotted #666666;
527    vertical-align: middle;
528    padding: 2px;
529  }
530 
531  .listview .summary
532  {
533    border-top: 1px solid #000000;
534  }
535 
536  .listview .col-num
537  {
538    width: 1.75em;
539    text-align: center;
540    font-size: 125%;
541    font-weight: bold;
542    vertical-align: top;
543  }
544 
545  .listview .lib
546  {
547    width: 15em;
548    text-align: center;
549  }
550 
551  .listview .empty .lib
552  {
553    font-style: italic;
554    color: #666666;
555    text-align: center;
556  }
557 
558  .listview .workplate
559  {
560 
561    width: <%=libPlate==null ? "14em" : "7em"%>;
562    text-align: center;
563  }
564 
565  .listview .pool
566  {
567    width: 7em;
568    text-align: center;
569  }
570 
571  .listview .remain, .listview .molarity
572  {
573    width: 4.5em;
574    padding-right: 0.5em;
575    text-align: right;
576  }
577
578  .listview .volume
579  {
580    width: 3.5em;
581    padding-right: 0.5em;
582    text-align: right;
583    color: #C80000;
584  }
585 
586  .listview .eb
587  {
588    width: 3.5em;
589    padding-right: 0.5em;
590    text-align: right;
591    color: #0000C8;
592  }
593 
594  .listview .remarks
595  {
596    vertical-align: top;
597    padding-left: 0.25em;
598  }
599 
600  .mix-remark .volume, .mix-remark .eb
601  {
602    padding: 0;
603    text-align: inherit;
604    width: inherit;
605    font-weight: bold;
606  }
607
608 
609 
610  /* Divide the 12 wells across the full page */
611  #plateview .well
612  {
613    width: 8.2%;
614    max-width: 8.2%;
615    min-width: 8.2%;
616    padding: 4px;
617  }
618 
619  #plateview .well:hover
620  {
621    padding: 3px;
622  }
623 
624  #plateview .rowheader
625  {
626    width: 2em;
627  }
628 
629  #plateview .lib
630  {
631    font-weight: bold;
632    margin-bottom: 0.25em;
633  }
634  #plateview .volume
635  {
636    color: #C80000;
637  }
638  #plateview .eb
639  {
640    color: #0000C8;
641    float: right;
642  }
643 
644  #plateview .remarks
645  {
646    color: #C80000;
647    font-style: italic;
648  }
649 
650  #plateview .mix-remark
651  {
652    display: none;
653  }
654 
655  .pool-eb
656  {
657    color: #0000C8;
658  }
659 
660  #pool-row
661  {
662    vertical-align: top;
663  }
664 
665  #plateview .pool-data
666  {
667    font-weight: normal;
668  }
669  #plateview .comments
670  {
671    font-style: italic;
672  }
673 
674 
675  </style>
676</head>
677<body onload="init()">
678  <div class="paper <%=view.equals("list") ? "" : "landscape"%>">
679  <div class="noprint fullwidth" style="border-bottom: 1px dashed #A0A0A0; padding-left: 1em; padding-bottom: 1em;">
680    <span class="button" onclick="window.print()" style="float: left; margin-right: 1em;">
681      <img src="../images/print.png">Print&hellip;
682    </span>
683    <b>Note!</b> 
684    <%
685    if (view.equals("list"))
686    {
687      %>
688      For better printing reduce margins to about <i>5mm</i> and set page orientation
689      to <i>portrait</i>. To fit everything on a single page, scale down to <i>60-70%</i>.
690      <%
691    }
692    else
693    {
694      %>
695      For better printing reduce margins to about <i>5mm</i> and set page orientation
696      to <i>landscape</i>. The recommended scale is <i>100%</i>.
697      <%
698    }
699    %>
700    <br clear="all">
701  </div>
702 
703  <h1>Lab protocol for library pooling <span class="reggie">Reggie <%=reggie.getAbout().getVersion() %></span></h1>
704
705  <table style="width: 100%;" class="protocolheader">
706  <tr style="border-bottom: 1px solid #000000;">
707    <th style="width: 15%;">Library plate</th>
708    <td style="width: 30%; border-right: 1px solid #000000;"><%=libPlate == null ? "Multiple" : HTML.encodeTags(libPlate.getName())%></td>
709    <th style="width: 15%;"></th>
710    <th style="width: 20%;">Date</th>
711    <th style="width: 20%;">Operator</th>
712  </tr>
713  <tr>
714    <td rowspan="1" colspan="2" style="width: 50%; border-right: 1px solid #000000;"><%=libPlate != null ? HTML.niceFormat(libPlate.getDescription()) : ""%></td>
715    <td style="border-right: 1px solid #000000;">Pooling</td>
716    <td style="border-right: 1px solid #000000;"></td>
717    <td></td>
718  </tr>
719  </table>
720
721  <%
722  if (view.equals("list"))
723  {
724    for (Integer poolId :pools)
725    {
726      Extract pool = Extract.getById(dc, poolId);
727      %>
728      <div id="pool.<%=poolId%>" style="display: none;" class="pool-section">
729      <table style="width: 100%;" class="poolheader">
730      <tr valign="top">
731        <th style="width: 25%;"><%=HTML.encodeTags(pool.getName())%></th>
732        <th style="width: 75%; border-left: 1px solid #000000;">Comments:</th>
733      </tr>
734      <tr valign="top">
735        <td style="width: 25%;"><span id="molarity.<%=poolId%>"></span></td>
736        <td style="border-left: 1px solid #000000;"><%=HTML.niceFormat(pool.getDescription()) %></td>
737      </tr>
738      </table>
739      <table style="width: 100%;" class="listview" id="listview.<%=poolId%>">
740      <thead>
741        <tr class="toprow">
742          <th class="lib"></th>
743          <th>Remain</th>
744          <th>DNA</th>
745          <th class="workplate">Work</th>
746          <th>Lib</th>
747          <th>EB</th>
748          <th></th>
749        </tr>
750        <tr>
751          <th class="lib">Library</th>
752          <th>(µl)</th>
753          <th>(nM)</th>
754          <th class="workplate">plate</th>
755          <th>(µl)</th>
756          <th>(µl)</th>
757          <th>Remarks</th>
758        </tr>
759      </thead>
760      <tbody id="listview.<%=poolId%>.body">
761      </tbody>
762      <tbody>
763        <tr class="summary">
764          <td colspan="5" style="text-align: right; font-weight: bold; padding-right: 0.5em; font-size: 120%;">EB volume to add</td>
765          <td id="eb-volume.<%=poolId%>" class="eb">eb</td>
766          <td></td>
767        </tr>
768      </tbody>
769      </table>
770      </div>
771      <%
772    }
773  }
774  %>
775
776  <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>
777  <div class="messagecontainer error" id="errorMessage" style="display: none;"></div>
778  <%
779
780  if (view.equals("plate"))
781  {
782    %>
783    <table class="plate" style="margin: 0em 0 0 0; width: 100%; display: none;" id="plateview">
784    <%
785    WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
786    WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
787    %>
788    <tr class="header">
789      <th></th>
790      <%
791      for (int c = 0; c < libPlate.getColumns(); ++c)
792      {
793        %>
794        <th id="col.<%=c%>"><%=colF.format(c)%></th>
795        <%
796      }
797      %>
798    </tr>
799    <tbody>
800    <%
801    for (int r = 0; r < libPlate.getRows(); ++r)
802    {
803      String row = rowF.format(r);
804      %>
805      <tr class="row-<%=r%>">
806        <th id="row.<%=r%>" class="rowheader"><%=row%></th>
807        <%
808        for (int c = 0; c < libPlate.getColumns(); ++c)
809        {
810          %>
811          <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"></td>
812          <%
813        }
814        %>
815      </tr>
816      <%
817    }
818    %>
819    </tbody>
820    <tr id="pool-row">
821      <th colspan="13">&nbsp;</th>
822    </tr>
823    </table>
824    <div style="margin: 1em;">
825      For each pool: <i>Number of libraries</i> • <i>Final molarity</i> • <i>Total volume</i> • <i>EB volume (dynamic mixing only)</i>
826    </div>
827    <%
828  }
829  %>
830  </div>
831</body>
832</html>
833<%
834}
835finally
836{
837  if (dc != null) dc.close();
838}
839%>
Note: See TracBrowser for help on using the repository browser.