source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/create_pools.jsp @ 2150

Last change on this file since 2150 was 2150, checked in by Nicklas Nordborg, 10 years ago

Fixes #537: Allow 10µl as max volume in Create pooled libraries wizard

File size: 26.8 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.util.formatter.WellCoordinateFormatter"
9  import="net.sf.basedb.clients.web.Base" 
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<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
15<%
16final SessionControl sc = Base.getExistingSessionControl(request, true);
17final String ID = sc.getId();
18final float scale = Base.getScale(sc);
19final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
20DbControl dc = null;
21try
22{
23  dc = sc.newDbControl();
24  final User user = User.getById(dc, sc.getLoggedInUserId());
25%>
26<base:page type="default" >
27<base:head scripts="ajax.js" styles="path.css,toolbar.css">
28  <link rel="stylesheet" type="text/css" href="../css/reggie.css">
29  <link rel="stylesheet" type="text/css" href="../css/plate.css">
30  <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script>
31  <script language="JavaScript" src="pools.js" type="text/javascript" charset="UTF-8"></script>
32  <script language="JavaScript" src="plate.js" type="text/javascript" charset="UTF-8"></script>
33
34<script language="JavaScript">
35var debug = 0;
36var currentStep = 1;
37
38var targetVolumePerLibIsValid = false;
39var POOL_DATA = [];
40
41// Loaded from servlet when getting Library information
42var TARGET_MOLARITY_IN_POOL;
43var LIMIT_FOR_AUTO_EXCLUDE = 0.25;
44var LIMIT_FOR_EXTRA_LARGE_MIX;
45var EXTRA_LARGE_MIX_FACTOR;
46
47function init()
48{
49  var frm = document.forms['reggie'];
50  var bioplates = getLibraryBioPlates();
51 
52  var plates = frm.bioplate;
53  if (bioplates != null && bioplates.length > 0)
54  {
55    for (var i=0; i < bioplates.length; i++)
56    {
57      var bioplate = bioplates[i];
58      var option = new Option(bioplate.name, bioplate.id);
59      option.bioplate = bioplate;
60      plates.options[plates.length] = option;
61    }
62    bioplateIsValid = true;
63    setInputStatus('bioplate', '', 'valid');
64  }
65  else
66  {
67    var msg = 'No Library bioplates available for processing.';
68    setFatalError(msg);
69    return;
70  }
71}
72
73
74function getLibraryBioPlates()
75{
76  var frm = document.forms['reggie']; 
77 
78  var request = Ajax.getXmlHttpRequest();
79  try
80  {
81    showLoadingAnimation('Loading Library bioplates...');
82    var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibraryPlatesForPooling';
83    request.open("GET", url, false); 
84    request.send(null);
85  }
86  finally
87  {
88    hideLoadingAnimation();
89  }
90 
91  if (debug) Main.debug(request.responseText);
92  var response = JSON.parse(request.responseText); 
93  if (response.status != 'ok')
94  {
95    setFatalError(response.message);
96    return false;
97  }
98  return response.bioplates;
99}
100
101function createManualPool()
102{
103  location.replace('create_manual_pool.jsp?ID=<%=ID%>');
104}
105
106function goNext(manual)
107{
108  setInnerHTML('gonext.message', '');
109  if (currentStep == 1)
110  {   
111    gotoStep2();
112  }
113  setCurrentStep(currentStep);
114}
115
116function gotoStep2()
117{
118  var frm = document.forms['reggie'];
119  frm.bioplate.disabled = true;
120  Main.addClass(document.getElementById('step.1.section'), 'disabled');
121 
122  loadPoolNames();
123  loadLibraryInformation();
124
125  currentStep = 2;
126  Main.hide('step.1.section');
127  Main.show('step.2.section');
128  Main.hide('gonext');
129  Main.show('gocancel');
130  Main.show('gocreate');
131}
132
133function goCreate()
134{
135  if (!targetVolumePerLibIsValid) return;
136 
137  var submitInfo = {};
138  submitInfo.pools = [];
139  submitInfo.flagged = [];
140  var frm = document.forms['reggie'];
141  var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
142  submitInfo.targetVolumeInPoolPerLib = parseFloat(frm.target_volume.value);
143  submitInfo.targetPoolMolarity = TARGET_MOLARITY_IN_POOL;
144  submitInfo.mixingStrategy = Forms.getCheckedRadio(frm.mixing_strategy).value;
145
146  var numPools = Plate.getPools();
147  for (var poolNo = 0; poolNo < numPools; poolNo++)
148  {
149    var wells = Plate.getPool(poolNo);
150   
151    var poolInfo = {};
152    poolInfo.name = POOL_NAMES[poolNo];
153    poolInfo.comment = frm['comment.'+poolNo].value;
154    poolInfo.ebVolumeExtra = POOL_DATA[poolNo].ebVolumeExtra;
155    poolInfo.libPlate = libPlate.id;
156    poolInfo.libs = [];
157    poolInfo.excluded = [];
158   
159    for (var wellNo = 0; wellNo < wells.length; wellNo++)
160    {
161      var lib = wells[wellNo].extract;
162      if (lib)
163      {
164        // We send library id, name and mixin volumes
165        var tmp = {};
166        tmp.id = lib.id;
167        tmp.name = lib.name;
168        tmp.volume = lib.actualVolume; 
169        tmp.eb = lib.actualEb;
170        tmp.mixFactor = lib.mixFactor;
171        tmp.comment = lib.comment;
172       
173        if (lib.excludeFromPool)
174        {
175          poolInfo.excluded[poolInfo.excluded.length] = tmp;
176        }
177        else
178        {
179          poolInfo.libs[poolInfo.libs.length] = tmp;
180        }
181       
182        if (lib.flag)
183        {
184          tmp.flag = lib.flag;
185          submitInfo.flagged[submitInfo.flagged.length] = tmp;
186        }
187      }
188    }
189   
190    submitInfo.pools[submitInfo.pools.length] = poolInfo;
191  }
192 
193  Main.addClass(document.getElementById('step.2.section'), 'disabled');
194  Main.hide('gocancel');
195  Main.hide('gocreate');
196
197  if (debug) Main.debug(JSON.stringify(submitInfo));
198  var request = Ajax.getXmlHttpRequest();
199  try
200  {
201    showLoadingAnimation('Creating pools...');
202    var url = '../Pool.servlet?ID=<%=ID%>';
203    url += '&cmd=CreatePools';
204    request.open("POST", url, false);
205    request.setRequestHeader("Content-Type", "application/json");
206    request.send(JSON.stringify(submitInfo));
207  }
208  finally
209  {
210    hideLoadingAnimation();
211  }
212
213  if (debug) Main.debug(request.responseText);
214
215  var response = JSON.parse(request.responseText);
216  if (response.status != 'ok')
217  {
218    setFatalError(response.message);
219    return false;
220  }
221
222  var msg = '<ul>';
223  for (var i = 0; i < response.messages.length; i++)
224  {
225    msg += '<li>' + response.messages[i];
226  }
227  msg += '</ul>';
228  setInnerHTML('done', msg);
229  Main.show('done');
230  Main.show('gorestart');
231  scrollToBottom(document.getElementById('content'));
232
233}
234
235function loadLibraryInformation()
236{
237  var frm = document.forms['reggie'];
238  var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
239
240  // Load Libraries and related info from the selected bioplate
241  var request = Ajax.getXmlHttpRequest();
242  try
243  {
244    showLoadingAnimation('Loading information about libraries...');
245    var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetLibraryInfoForPlate&bioplate='+libPlate.id;   
246    request.open("GET", url, false);
247    request.send(null);
248  }
249  finally
250  {
251    hideLoadingAnimation();
252  }
253 
254  if (debug) Main.debug(request.responseText);
255  var response = JSON.parse(request.responseText);
256  if (response.status != 'ok')
257  {
258    setFatalError(response.message);
259    return false;
260  }
261
262 
263  var schema = PoolSchema.getById(libPlate.poolSchema);
264  var barcodeVariant = PoolSchema.getBarcodeVariantByName(schema, libPlate.barcodeVariant);
265  Plate.setPoolSchema(schema);
266  WellPainter.barcodeVariant = barcodeVariant;
267  Plate.init(8, 12, schema, WellPainter);
268
269  var poolInfo = response.poolInfo;
270  TARGET_MOLARITY_IN_POOL = poolInfo.targetMolarity;
271  EXTRA_LARGE_MIX_FACTOR = poolInfo.extraLargeMixFactor;
272  LIMIT_FOR_EXTRA_LARGE_MIX = poolInfo.limitForExtraLargeMix;
273 
274  setInnerHTML('pool_schema', schema.name);
275  setInnerHTML('barcode_variant', barcodeVariant.name);
276  setInnerHTML('target_molarity', Numbers.formatNumber(TARGET_MOLARITY_IN_POOL, 1, ' nM'));
277
278  var libs = response.libraries;
279  var molarityLimit = TARGET_MOLARITY_IN_POOL * LIMIT_FOR_AUTO_EXCLUDE;
280  for (var i = 0; i < libs.length; i++)
281  {
282    var lib = libs[i];
283    var well = lib.bioWell;
284    lib.excludeFromPool = false;
285   
286    if (lib.molarity != null && lib.molarity < molarityLimit)
287    {
288      lib.excludeFromPool = true;
289      lib.flag = 'ExcludedFromPool';
290      lib.comment = 'Not enough DNA';
291    }
292
293    Plate.getWell(well.row, well.column).setExtract(lib);
294  }
295
296  PoolSchema.buildPoolTableRow(schema, 12);
297  setTargetVolumePerLib(poolInfo.targetVolumePerLib);
298}
299
300function loadPoolNames()
301{
302  var frm = document.forms['reggie'];
303  var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
304
305  var schema = PoolSchema.getById(libPlate.poolSchema);
306
307  // Load Libraries and related info from the selected bioplate
308  var request = Ajax.getXmlHttpRequest();
309  try
310  {
311    showLoadingAnimation('Loading Library bioplate information...');
312    var url = '../Pool.servlet?ID=<%=ID%>&cmd=GetNextAutoGeneratedPoolNames&numNames='+schema.numPools;   
313    request.open("GET", url, false);
314    request.send(null);
315  }
316  finally
317  {
318    hideLoadingAnimation();
319  }
320 
321  if (debug) Main.debug(request.responseText);
322  var response = JSON.parse(request.responseText);
323  if (response.status != 'ok')
324  {
325    setFatalError(response.message);
326    return false;
327  }
328 
329  var list = response.names;
330  for (var i = 0; i < list.length; i++)
331  {
332    POOL_NAMES[i] = list[i];
333  }
334
335}
336
337function setTargetVolumePerLib(targetVolumePerLib)
338{
339  var frm = document.forms['reggie'];
340  frm.target_volume.value = targetVolumePerLib;
341 
342  targetVolumePerLibIsValid = false;
343  if (targetVolumePerLib < 2 || targetVolumePerLib > 10)
344  {
345    setInputStatus('target_volume', 'Must be between 2 and 10µl', 'invalid');
346    return;
347  }
348  setInputStatus('target_volume', '', 'valid');
349  targetVolumePerLibIsValid = true;
350
351  // Pre-process the Library items
352  var mixingStrategy = Forms.getCheckedRadio(frm.mixing_strategy).value;
353  var wells = Plate.getWells();
354  for (var i = 0; i < wells.length; i++)
355  {
356    var lib = wells[i].extract;
357    if (lib)
358    {
359      if (lib.remainingQuantity == null)
360      {
361        lib.excludeFromPool = true;
362      }
363      else
364      {
365        PoolMix.calculateLibVolume(lib, TARGET_MOLARITY_IN_POOL, targetVolumePerLib, mixingStrategy);
366        PoolMix.calculateEbVolume(lib, TARGET_MOLARITY_IN_POOL, targetVolumePerLib, mixingStrategy);
367      }
368    }
369  }
370 
371  updatePoolData();
372  WellPainter.mixingStrategy = mixingStrategy;
373  Plate.paint(Plate.getWells());
374}
375
376function calculateRemarks(lib, schema, barcodeVariant)
377{
378  var well = lib.bioWell;
379  var remarks = [];
380
381  // Check if default barcode has been modified
382  var indexSet = barcodeVariant.indexSets[well.column];
383  if (indexSet)
384  {
385    var defaultBarcode = indexSet.barcodes[well.row];
386    if (defaultBarcode && lib.barcode.name != defaultBarcode)
387    {
388      remarks[remarks.length] = 'Modified barcode';
389      lib.barcode.modified = true;
390    }
391  }
392 
393  if (lib.molarity != null)
394  {
395    if (lib.volume != lib.actualVolume)
396    {
397      if (lib.volume > lib.remainingVolume)
398      {
399        remarks[remarks.length] = 'Low quantity';
400      }
401      else
402      {
403        remarks[remarks.length] = 'Low molarity';
404      }
405    }
406
407    if (lib.speedVacConc != null)
408    {
409      remarks[remarks.length] = 'SpeedVac';
410    }
411   
412    if (lib.mixFactor > 1)
413    {
414      // Larger mix than default
415      remarks[remarks.length] = 'Use ' + Numbers.formatNumber(lib.actualVolume+lib.actualEb, 1, 'µl') + ' in pool';
416    }
417   
418  }
419  lib.stratagene = lib.name.indexOf(GENERIC_STRATAGENE_NAME) == 0;
420  lib.external = lib.name.indexOf(EXTERNAL_RNA_NAME) == 0;
421  lib.remarks = remarks;
422}
423
424
425function updatePoolData()
426{
427  var frm = document.forms['reggie'];
428  var targetVolumePerLib = parseFloat(frm.target_volume.value);
429  var mixingStrategy = Forms.getCheckedRadio(frm.mixing_strategy).value;
430
431  var libPlate = frm.bioplate[frm.bioplate.selectedIndex].bioplate;
432  var schema = PoolSchema.getById(libPlate.poolSchema);
433  var barcodeVariant = PoolSchema.getBarcodeVariantByName(schema, libPlate.barcodeVariant);
434 
435  for (var poolNo = 0; poolNo < Plate.getPools(); poolNo++)
436  {
437    // Get all libs into an array
438    var libs = [];
439    var wells = Plate.getPool(poolNo);
440    for (var wellNo = 0; wellNo < wells.length; wellNo++)
441    {
442      var well = wells[wellNo];
443      var lib = well.extract;
444      if (lib && !lib.excludeFromPool)
445      {
446        libs[libs.length] = lib;
447      }
448    }
449   
450    // Calculate final pool volumes, molarity, etc.
451    var poolInfo = PoolMix.calculateFinalPoolInfo(libs, TARGET_MOLARITY_IN_POOL, targetVolumePerLib, mixingStrategy);
452    POOL_DATA[poolNo] = poolInfo;
453   
454    // Make remarks for each lib
455    for (var libNo = 0; libNo < libs.length; libNo++)
456    {
457      var lib = libs[libNo];
458      calculateRemarks(lib, schema, barcodeVariant);
459    }
460   
461    var warnMsg = null;
462    if (poolInfo.ebVolumeExtra < 0) 
463    {
464      warnMsg = 'Too many libs with low molarity';
465    }
466   
467    var poolDiv = document.getElementById('pool.'+poolNo);
468    var poolData = '<div class="pool-data">';
469    poolData += libs.length + ' libs  ';
470    poolData += Numbers.formatNumber(poolInfo.molarity, 2, 'nM')+'  ';
471    poolData += Numbers.formatNumber(poolInfo.totalVolume, 1, 'µl');
472    if (mixingStrategy == 'dynamic')
473    {
474      poolData += '  <span class="pool-eb">'+Numbers.formatNumber(poolInfo.ebVolumeExtra, 1, 'µl')+'</span>';
475    }
476    if (warnMsg)
477    {
478      Main.addClass(poolDiv, 'warning');
479      poolData += '<div class="warning-message">'+warnMsg+'</div>';
480    }
481    else
482    {
483      Main.removeClass(poolDiv, 'warning');
484    }
485    poolData += '</div>';
486    var poolComments = frm['comment.'+poolNo];
487    var comments = poolComments ? poolComments.value : '';
488    poolData += '<textarea name="comment.'+poolNo+'"></textarea>';
489    poolDiv.innerHTML = POOL_NAMES[poolNo] + poolData;
490    frm['comment.'+poolNo].value = comments;
491  }
492}
493
494function targetVolumeOnBlur()
495{
496  var frm = document.forms['reggie'];
497  var targetVolumePerLib = parseFloat(frm.target_volume.value);
498  setTargetVolumePerLib(targetVolumePerLib);
499}
500
501function mixingStrategyOnChange()
502{
503  targetVolumeOnBlur();
504}
505
506var WellPainter = function()
507{
508  var painter = {};
509 
510  painter.getClassNameForWell = function(well, schema)
511  {
512    var indexSet = painter.barcodeVariant.indexSets[well.column];
513    var cls = '';
514    var lib = well.extract;
515   
516    if (lib)
517    {
518      if (lib.excludeFromPool)
519      {
520        cls += ' exclude-from-pool';
521      }
522      else if (indexSet)
523      {
524        cls += ' ' + (lib && lib.barcode.modified ? 'bg-modified' : indexSet.color);
525      }
526      if (lib.flag)
527      {
528        cls += ' flagged';
529      }
530      if (!lib.flag && lib.actualVolume < lib.volume)
531      {
532        cls += ' low-volume';
533      }
534    }
535    else if (indexSet)
536    {
537      cls += indexSet.color;
538    }
539    return cls;
540  }
541 
542  painter.getWellText = function(well, schema)
543  {
544    var text = '';
545    var lib = well.extract;
546    if (lib)
547    {
548      var name = lib.name;
549      var i = name.indexOf('.m');
550      var mixFactor = lib.mixFactor;
551      var displayName = name.substring(0, i)+'.<br>&nbsp;'+name.substring(i);
552      text += '<div class="lib">'+displayName+'</div>';
553      text += '<div>';
554      text += '<span class="barcode">'+lib.barcode.name+'</span>';
555      if (lib.molarity != null)
556      {
557        text += '<span class="molarity">'+Numbers.formatNumber(lib.molarity, 2, 'nM')+'</span>';
558      }
559      text += '</div>';
560      if (!lib.excludeFromPool)
561      {
562        mark = (lib.volume > lib.actualVolume) ? '*' : '';
563        text += '<div>';
564        text += '<span class="volume">'+(isFinite(lib.volume) ? Numbers.formatNumber(lib.volume*mixFactor, 1, 'µl'+mark) : '∞')+'</span>';
565        if (painter.mixingStrategy == 'fixed' || lib.mixFactor > 1)
566        {
567          text += '<span class="eb">'+(isFinite(lib.eb) ? Numbers.formatNumber(lib.eb*mixFactor, 1, 'µl') : '-∞')+'</span>';
568        }
569        else
570        {
571          text += '<span class="eb"></span>';
572        }
573        text += '</div>';
574      }
575      if (lib.remarks) text += '<div class="remarks">'+ lib.remarks.join('; ') + '</div>';
576      if (lib.comment)
577      {
578        text += '<div class="remarks">'+ lib.comment + '</div>';
579      }
580    }
581    return text;
582  }
583
584  return painter;
585}();
586
587//Toggle the selected status of a single well
588function toggleWell(row, column)
589{
590  var well = Plate.getWell(row, column);
591  Plate.toggleSelected([well]);
592}
593
594var lastComment = '';
595function excludeSelected()
596{
597  var wells = Plate.getSelected();
598 
599  if (wells.length == 0)
600  {
601    alert('No wells have been selected');
602    return;
603  }
604
605  // See if there is an existing comment
606  var comment;
607  for (var i = 0; i < wells.length; i++)
608  {
609    var lib = wells[i].extract;
610    if (lib && lib.comment) 
611    {
612      comment = lib.comment;
613    }
614  }
615
616  comment = prompt('Comment on reason for exclusion', comment || lastComment);
617  if (comment == null) return;
618  lastComment = comment;
619 
620  if (comment == '') comment = null;
621 
622  for (var i = 0; i < wells.length; i++)
623  {
624    var well = wells[i];
625    var lib = well.extract;
626    if (lib)
627    {
628      lib.excludeFromPool = true;
629      if (!lib.stratagene && !lib.external)
630      {
631        lib.flag = 'ExcludedFromPool';
632        lib.comment = comment;
633      }
634    }
635    well.selected = false;
636  }
637 
638  updatePoolData();
639  Plate.paint(Plate.getWells());
640}
641
642function includeSelected()
643{
644  var wells = Plate.getSelected();
645 
646  if (wells.length == 0)
647  {
648    alert('No wells have been selected');
649    return;
650  }
651
652  for (var i = 0; i < wells.length; i++)
653  {
654    var well = wells[i];
655    var lib = well.extract;
656    if (lib)
657    {
658      lib.excludeFromPool = false;
659      lib.flag = null;
660      lib.oldComment = lib.comment;
661      lib.comment = null;
662    }
663    well.selected = false;
664  }
665 
666  updatePoolData();
667  Plate.paint(Plate.getWells());
668}
669
670//Flag the selected RNA
671function toggleFlag()
672{
673  var wells = Plate.getSelected();
674 
675  if (wells.length == 0)
676  {
677    alert('No wells have been selected');
678    return;
679  }
680
681  var flag = null;
682  var firstLib = true;
683  for (var i = 0; i < wells.length; i++)
684  {
685    var well = wells[i];
686    var lib = well.extract;
687    if (lib)
688    {
689      if (firstLib && !lib.excludeFromPool)
690      {
691        flag = lib.flag ? null : 'ManualFlag';
692        firstLib = false;
693      }
694      lib.flag = lib.excludeFromPool ? 'ExcludedFromPool' : flag;
695    }
696    //well.selected = false;
697  }
698 
699  Plate.paint(wells);
700}
701
702//Set a comment on the selected wells
703function commentSelected(comment)
704{
705  var wells = Plate.getSelected();
706 
707  if (comment == undefined)
708  {
709    if (wells.length == 0)
710    {
711      alert('No wells have been selected');
712      return;
713    }
714   
715    var count = 0;
716    for (var i = 0; i < wells.length; i++)
717    {
718      var well = wells[i];
719      if (well.extract) 
720      {
721        if (well.extract.comment) comment = well.extract.comment;
722        count++;
723      }
724    }
725   
726    if (count == 0)
727    {
728      alert('Only empty wells have been selected');
729      return;
730    }
731   
732    comment = prompt('Comment', comment || lastComment);
733    if (comment == null) return;
734  }
735 
736  lastComment = comment;
737 
738  if (comment == '') comment = null;
739  for (var i = 0; i < wells.length; i++)
740  {
741    var well = wells[i];
742    if (well.extract) 
743    {
744      well.extract.comment = comment;
745    }
746    well.selected = false;
747  }
748  Plate.paint(wells);
749}
750
751
752</script>
753<style>
754.lib
755{
756  font-weight: bold;
757  margin-bottom: 0.25em;
758  overflow: hidden;
759  text-overflow: ellipsis;
760}
761.barcode
762{}
763.molarity
764{
765  float: right;
766}
767
768.volume
769{
770  color: #C80000;
771}
772.eb
773{
774  color: #0000C8;
775  float: right;
776}
777.pool-eb
778{
779  color: #0000C8;
780}
781.remarks
782{
783  color: #C80000;
784  font-style: italic;
785}
786.pool-data
787{
788  font-weight: normal;
789}
790.pool.warning
791{
792  background-image: url('../images/warning.png');
793  background-position: 98% 5%;
794  background-repeat: no-repeat;
795}
796
797.pool-data .warning-message
798{
799  color: #C80000;
800  font-style: italic;
801}
802
803.well.exclude-from-pool
804{
805  background-color: #FFFFFF !important;
806}
807
808.well.exclude-from-pool.selected
809{
810  background-color: #D8D8D8 !important;
811}
812
813.well.exclude-from-pool *
814{
815  color: #999999 !important;
816}
817.well.flagged
818{
819  background-image: url('../images/flag.png');
820  background-position: 98% 5%;
821  background-repeat: no-repeat;
822}
823
824.well.low-volume
825{
826  background-image: url('../images/warning.png') !important;
827  background-position: 98% 5%;
828  background-repeat: no-repeat;
829}
830.pool textarea
831{
832  width: 95%;
833  height: 3.5em;
834}
835</style>
836</base:head>
837<base:body onload="init()">
838
839  <p:path><p:pathelement 
840    title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
841    /><p:pathelement title="Create pooled libraries" 
842    /></p:path>
843
844  <div class="content" id="content">
845  <%
846  if (sc.getActiveProjectId() == 0)
847  {
848    %>
849    <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
850      No project has been selected. You may proceed with the registration but
851      created items will not be shared.
852    </div>
853    <%
854  }
855  %>
856
857  <div class="allsteps">
858    <div class="step current" id="step.1">1</div>
859    ›
860    <div class="step future" id="step.2">2</div>
861  </div>
862
863  <form name="reggie" onsubmit="return false;">
864 
865  <div id="step.1.section">
866  <table class="stepform">
867  <tr>
868    <td rowspan="3" class="stepno">1</td>
869    <td class="steptitle">Select source for pool</td>
870  </tr>
871  <tr>
872    <td class="stepfields">
873      <table>
874      <tr valign="top">
875        <td class="prompt">Library bioplate</td>
876        <td class="input"><select style="width:90%" 
877            name="bioplate" id="bioplate" onchange="bioPlateOnChange()"></select>
878        </td>
879        <td class="status" id="bioplate.status"></td>
880        <td class="help"><span id="bioplate.message" class="message" style="display: none;"></span>
881          Select an existing Library bioplate. The list contain all Library bioplates that
882          contain libraries with no child items.
883        </td>
884      </tr>
885      <tr valign="top">
886        <td class="prompt"></td>
887        <td class="input"> - or -</td>
888        <td class="status"></td>
889        <td class="help"></td>
890      </tr>
891      <tr valign="top">
892        <td class="prompt"></td>
893        <td class="input">
894          <table><tr><td>
895            <base:button title="Create manual pool" onclick="createManualPool()" image="<%=home+"/images/gonext.png"%>" />
896          </td></tr></table>
897       
898        </td>
899        <td class="status"></td>
900        <td class="help"></td>
901      </tr>
902      </table>
903    </td>
904  </tr>
905  </table>
906  </div>
907 
908  <div id="step.2.section" style="display: none;">
909  <table class="stepform" style="width: auto;">
910  <tr>
911    <td rowspan="2" class="stepno">2</td>
912    <td class="steptitle">Confirm pool layout</td>
913  </tr>
914  <tr>
915    <td class="stepfields">
916
917      <table class="bottomborder" style="width: 100%;">
918      <tr valign="top">
919        <td class="prompt">Pool layout</td>
920        <td class="input">
921          <span id="pool_schema"></span>; <span id="barcode_variant"></span>
922        </td>
923        <td class="status"></td>
924        <td class="help"></td>
925      </tr>
926      <tr valign="top">
927        <td class="prompt">Target molarity</td>
928        <td class="input">
929          <span id="target_molarity"></span>
930        </td>
931        <td class="status"></td>
932        <td class="help"></td>
933      </tr>
934      <tr valign="top">
935        <td class="prompt">Average volume / lib</td>
936        <td class="input">
937          <input type="text" class="text" name="target_volume" 
938            value="5" style="width: 4em;"
939            onblur="targetVolumeOnBlur()"
940            onkeypress="doOnEnter(event, targetVolumeOnBlur); return Numbers.numberOnly(event)"> µl (2--10)
941        </td>
942        <td class="status" id="target_volume.status"></td>
943        <td class="help" rowspan="2"><span id="target_volume.message" class="message" style="display: none;"></span>
944          Select a target volume when mixing each lib to 2nM before pooling.
945          Use the <b>Dynamic</b> strategy to prioritize final pool molarity by mixing
946          different volume for each library. Use the <b>Fixed</b> strategy to mix all
947          libraries to the given volume.
948        </td>
949      </tr>
950      <tr valign="top">
951        <td class="prompt">Mixing strategy</td>
952        <td class="input">
953          <label><input type="radio" name="mixing_strategy" value="dynamic" checked
954            onclick="mixingStrategyOnChange()"
955            >Dynamic</label>
956          <label><input type="radio" name="mixing_strategy" value="fixed"
957            onclick="mixingStrategyOnChange()"
958            >Fixed</label>
959        </td>
960        <td class="status" id="mixing_strategy.status"></td>
961      </tr>
962      </table>
963      <tbl:toolbar subclass="bottomborder">
964        <tbl:button 
965          title="Exclude from pool&hellip;" 
966          image="<%=home+"/images/delete.png"%>" 
967          onclick="excludeSelected()" 
968          tooltip="Exclude the selected libraries from the pool"
969        />
970        <tbl:button 
971          title="Include in pool" 
972          image="<%=home+"/images/new.png"%>" 
973          onclick="includeSelected()" 
974          tooltip="Include the selected libraries in the pool"
975        />
976        <tbl:button 
977          title="Toggle flag" 
978          image="<%=home+"/images/flag.png"%>" 
979          onclick="toggleFlag()" 
980          tooltip="Flag the parent RNA for the selected libraries"
981        />
982        <tbl:button 
983          title="Comments&hellip;" 
984          image="<%=home+"/images/comment.png"%>" 
985          onclick="commentSelected()" 
986          tooltip="Add a comment to the selected libraries" 
987        />
988      </tbl:toolbar>
989     
990      <table class="plate" style="margin: 1em 1em 1em 1em;" id="plate">
991      <%
992      int columns = 12;
993      int rows = 8;
994      WellCoordinateFormatter rowF = new WellCoordinateFormatter(true);
995      WellCoordinateFormatter colF = new WellCoordinateFormatter(false);
996      %>
997      <tr class="header">
998        <th></th>
999        <%
1000        for (int c = 0; c < columns; ++c)
1001        {
1002          %>
1003          <th id="col.<%=c%>"><%=colF.format(c)%></th>
1004          <%
1005        }
1006        %>
1007      </tr>
1008      <tbody>
1009      <%
1010      for (int r = 0; r < rows; ++r)
1011      {
1012        String row = rowF.format(r);
1013        %>
1014        <tr class="row-<%=r%>">
1015          <th id="row.<%=r%>" class="rowheader"><%=row%></th>
1016          <%
1017          for (int c = 0; c < columns; ++c)
1018          {
1019            %>
1020            <td class="well col-<%=c%>" id="well.<%=r%>.<%=c%>"
1021              onclick="toggleWell(<%=r%>,<%=c%>)"
1022              title="Select/deselect this well"
1023              ></td>
1024            <%
1025          }
1026          %>
1027        </tr>
1028        <%
1029      }
1030      %>
1031      </tbody>
1032      <tr id="pool-row">
1033        <th colspan="13">&nbsp;</th>
1034      </tr>
1035      </table>
1036      <div style="margin: 1em;">
1037      Low molarity = The concentration of this library too low to mix to target molarity for the pool.<br>
1038      For each pool: <i>Number of libraries</i> • <i>Final molarity</i> • <i>Total volume</i> • <i>EB volume (dynamic mixing only)</i>
1039      </div>
1040    </td>
1041  </tr>
1042  </table>
1043  </div>
1044 
1045  <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>
1046 
1047  <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>
1048 
1049  <div id="done" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div>
1050 
1051  <table style="margin-left: 20px; margin-top: 10px; margin-bottom: 3em;" class="navigation">
1052    <tr>
1053      <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" /></td>
1054      <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)"/></td>
1055      <td><base:button id="gocreate" title="Create" image="<%=home+"/images/gonext.png"%>" onclick="goCreate()" style="display: none;"/></td>
1056      <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
1057      <td id="gonext.message" class="message"></td>
1058    </tr>
1059  </table>
1060 
1061 
1062  </form>
1063  </div>
1064 
1065</base:body>
1066</base:page>
1067<%
1068}
1069finally
1070{
1071  if (dc != null) dc.close();
1072}
1073%>
Note: See TracBrowser for help on using the repository browser.