extensions/net.sf.basedb.reggie/trunk/resources/libprep/create_manual_pool.js

Code
Comments
Other
Rev Date Author Line
2805 15 Oct 14 nicklas 1 var CreatePool = function()
2805 15 Oct 14 nicklas 2 {
2805 15 Oct 14 nicklas 3   var createpool = {};
2805 15 Oct 14 nicklas 4   var debug = 0;
2805 15 Oct 14 nicklas 5
2805 15 Oct 14 nicklas 6   var subtypeLibrary;
5436 17 May 19 nicklas 7   var annotationTypePipeline;
5436 17 May 19 nicklas 8   
2805 15 Oct 14 nicklas 9   var selectedLibraries = [];
2805 15 Oct 14 nicklas 10   var newLibraries;
2805 15 Oct 14 nicklas 11   
2805 15 Oct 14 nicklas 12   var LIMIT_FOR_AUTO_EXCLUDE = 0.25;
2805 15 Oct 14 nicklas 13   var LIMIT_FOR_EXTRA_LARGE_MIX;
2805 15 Oct 14 nicklas 14   var MAX_TARGET_VOLUME = 20;
2805 15 Oct 14 nicklas 15   var MIN_TARGET_VOLUME = 2;
2805 15 Oct 14 nicklas 16   var LIBRARY_FRAC_ADPT_LIMIT = 10; // percent
2805 15 Oct 14 nicklas 17
2805 15 Oct 14 nicklas 18   var targetVolumePerLibIsValid = true;
2805 15 Oct 14 nicklas 19   var lastTargetVolume = null;
2805 15 Oct 14 nicklas 20   var lastComment = '';
2805 15 Oct 14 nicklas 21   
2805 15 Oct 14 nicklas 22   // Page initialization
2805 15 Oct 14 nicklas 23   createpool.initPage = function()
2805 15 Oct 14 nicklas 24   {
2805 15 Oct 14 nicklas 25     // Step 1
2805 15 Oct 14 nicklas 26     Events.addEventHandler('step-1', 'wizard-validate', createpool.validateStep1);
3107 27 Jan 15 nicklas 27     Events.addEventHandler('target_molarity', 'change', createpool.updatePoolData);
2805 15 Oct 14 nicklas 28     Events.addEventHandler('target_volume', 'change', createpool.targetVolumeOnChange);
2805 15 Oct 14 nicklas 29     Events.doOnEnter('target_volume', createpool.targetVolumeOnChange);
2805 15 Oct 14 nicklas 30     Events.addEventHandler('target_volume', 'keypress', Events.numberOnly);
2805 15 Oct 14 nicklas 31     
2805 15 Oct 14 nicklas 32     Events.addEventHandler('mixing_strategy_dynamic', 'change', createpool.updatePoolData);
2805 15 Oct 14 nicklas 33     Events.addEventHandler('mixing_strategy_fixed', 'change', createpool.updatePoolData);
2805 15 Oct 14 nicklas 34     
2805 15 Oct 14 nicklas 35     Buttons.addClickHandler('btnSelectLibraries', createpool.selectLibraries);
2805 15 Oct 14 nicklas 36     Events.addEventHandler('lib-table', 'base-selected', createpool.librarySelected);
2805 15 Oct 14 nicklas 37     Buttons.addClickHandler('btnRemove', createpool.removeSelected);
2805 15 Oct 14 nicklas 38     Buttons.addClickHandler('btnTargetVolume', createpool.setTargetVolume);
2805 15 Oct 14 nicklas 39     Buttons.addClickHandler('btnComment', createpool.commentChecked);
2805 15 Oct 14 nicklas 40     
2805 15 Oct 14 nicklas 41     Events.addEventHandler('checkAll', 'click', createpool.checkAll);
2805 15 Oct 14 nicklas 42     
2805 15 Oct 14 nicklas 43     // Navigation
2805 15 Oct 14 nicklas 44     Buttons.addClickHandler('gocancel', createpool.cancelWizard);
2805 15 Oct 14 nicklas 45     Buttons.addClickHandler('gorestart', createpool.cancelWizard);
2805 15 Oct 14 nicklas 46     Buttons.addClickHandler('gonext', Wizard.goNextOnClick);
2805 15 Oct 14 nicklas 47     Buttons.addClickHandler('goregister', Wizard.goRegister);
2805 15 Oct 14 nicklas 48     
2805 15 Oct 14 nicklas 49     // Final registration
2805 15 Oct 14 nicklas 50     Events.addEventHandler('wizard', 'wizard-submit', createpool.submit);
2805 15 Oct 14 nicklas 51
2805 15 Oct 14 nicklas 52     var url = '../Pool.servlet?ID='+App.getSessionId();
2805 15 Oct 14 nicklas 53     url += '&cmd=GetNextAutoGeneratedPoolNames&numNames=1';
2805 15 Oct 14 nicklas 54     Wizard.showLoadingAnimation('Loading pool information...');
2805 15 Oct 14 nicklas 55     Wizard.asyncJsonRequest(url, createpool.poolInfoLoaded);
2805 15 Oct 14 nicklas 56   }
2805 15 Oct 14 nicklas 57   
2805 15 Oct 14 nicklas 58   createpool.poolInfoLoaded = function(response)
2805 15 Oct 14 nicklas 59   {
2805 15 Oct 14 nicklas 60     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 61
2805 15 Oct 14 nicklas 62     // Load some default pooling options and the auto-generated name for the next pool
2805 15 Oct 14 nicklas 63     var poolInfo = response.poolInfo;
2805 15 Oct 14 nicklas 64     LIMIT_FOR_EXTRA_LARGE_MIX = poolInfo.limitForExtraLargeMix;
2805 15 Oct 14 nicklas 65     Doc.element('pool-name').innerHTML = Strings.encodeTags(response.names[0]);
2805 15 Oct 14 nicklas 66     
2805 15 Oct 14 nicklas 67     frm.target_volume.value = poolInfo.targetVolumePerLib;
2805 15 Oct 14 nicklas 68     frm.poolName.value = response.names[0];
2805 15 Oct 14 nicklas 69     
2805 15 Oct 14 nicklas 70     Doc.show('step-1');
2805 15 Oct 14 nicklas 71     Doc.show('gocancel');
2805 15 Oct 14 nicklas 72     Doc.show('goregister');
2805 15 Oct 14 nicklas 73     Wizard.setNoConfirmOnFirstStep(false);
2805 15 Oct 14 nicklas 74   }
2805 15 Oct 14 nicklas 75   
2805 15 Oct 14 nicklas 76   createpool.cancelWizard = function()
2805 15 Oct 14 nicklas 77   {
2805 15 Oct 14 nicklas 78     location.href = 'create_pools.jsp?ID='+App.getSessionId();
2805 15 Oct 14 nicklas 79   }
2805 15 Oct 14 nicklas 80
2805 15 Oct 14 nicklas 81   createpool.selectLibraries = function()
2805 15 Oct 14 nicklas 82   {
2805 15 Oct 14 nicklas 83     if (subtypeLibrary == null) subtypeLibrary = Reggie.getSubtypeInfo('LIBRARY');
5436 17 May 19 nicklas 84     if (annotationTypePipeline == null) annotationTypePipeline = Reggie.getAnnotationTypeInfo('PIPELINE');
2805 15 Oct 14 nicklas 85     
2805 15 Oct 14 nicklas 86     var url = '&resetTemporary=1';
2805 15 Oct 14 nicklas 87     url += '&tmpfilter:INT:itemSubtype='+subtypeLibrary.id;
2805 15 Oct 14 nicklas 88     url += '&tmpfilter:DATE:creationEvent.eventDate='+encodeURIComponent('<>');
2805 15 Oct 14 nicklas 89     url += '&tmpfilter:STRING:bioWell.bioPlate.name='+encodeURIComponent('<>');;
5436 17 May 19 nicklas 90     url += '&tmpfilter:STRING:'+encodeURIComponent('#')+annotationTypePipeline.id+'=RNAseq';
2805 15 Oct 14 nicklas 91     
2805 15 Oct 14 nicklas 92     var exclude = [];
2805 15 Oct 14 nicklas 93     for (var libNo = 0; libNo < selectedLibraries.length; libNo++)
2805 15 Oct 14 nicklas 94     {
2805 15 Oct 14 nicklas 95       exclude[exclude.length] = selectedLibraries[libNo].id;
2805 15 Oct 14 nicklas 96     }
2805 15 Oct 14 nicklas 97     if (exclude.length > 0) url += '&exclude='+exclude.join(',');
2805 15 Oct 14 nicklas 98
2805 15 Oct 14 nicklas 99     newLibraries = [];
2805 15 Oct 14 nicklas 100     Dialogs.selectItem('EXTRACT', 'lib-table', 1, url);
2805 15 Oct 14 nicklas 101   }
2805 15 Oct 14 nicklas 102
2805 15 Oct 14 nicklas 103   createpool.librarySelected = function(event)
2805 15 Oct 14 nicklas 104   {
2805 15 Oct 14 nicklas 105     var id = event.detail.id;
2805 15 Oct 14 nicklas 106
2805 15 Oct 14 nicklas 107     // Check if this library has already been selected
2805 15 Oct 14 nicklas 108     var isNew = true;
2805 15 Oct 14 nicklas 109     for (var i = 0; i < selectedLibraries.length; i++)
2805 15 Oct 14 nicklas 110     {
2805 15 Oct 14 nicklas 111       if (selectedLibraries[i].id == id) 
2805 15 Oct 14 nicklas 112       {
2805 15 Oct 14 nicklas 113         isNew = false;
2805 15 Oct 14 nicklas 114         break;
2805 15 Oct 14 nicklas 115       }
2805 15 Oct 14 nicklas 116     }
2805 15 Oct 14 nicklas 117     if (isNew) newLibraries[newLibraries.length] = id;
2805 15 Oct 14 nicklas 118     
2808 15 Oct 14 nicklas 119     if (event.detail.remaining == 0 && newLibraries.length > 0)
2805 15 Oct 14 nicklas 120     {
2805 15 Oct 14 nicklas 121       // Get more information about the selected library
2805 15 Oct 14 nicklas 122       var url = '../Pool.servlet?ID='+App.getSessionId();
2805 15 Oct 14 nicklas 123       url += '&cmd=GetLibraryInfo&libraries=' + newLibraries.join(',');
2805 15 Oct 14 nicklas 124       Wizard.asyncJsonRequest(url, createpool.libraryInfoLoaded);
2805 15 Oct 14 nicklas 125     }
2805 15 Oct 14 nicklas 126   }
2805 15 Oct 14 nicklas 127   
2805 15 Oct 14 nicklas 128   createpool.removeSelected = function()
2805 15 Oct 14 nicklas 129   {
2805 15 Oct 14 nicklas 130     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 131     var tbody = Doc.element('lib-table-rows');
2805 15 Oct 14 nicklas 132     var numRemoved = 0;
2805 15 Oct 14 nicklas 133     for (var libNo = selectedLibraries.length-1; libNo >= 0; libNo--)
2805 15 Oct 14 nicklas 134     {
2805 15 Oct 14 nicklas 135       var lib = selectedLibraries[libNo];
2805 15 Oct 14 nicklas 136       if (frm['check.'+lib.id].checked)
2805 15 Oct 14 nicklas 137       {
2805 15 Oct 14 nicklas 138         var tr = document.getElementById('lib.'+lib.id);
2805 15 Oct 14 nicklas 139         tbody.removeChild(tr);
2805 15 Oct 14 nicklas 140         selectedLibraries.splice(libNo, 1);
2805 15 Oct 14 nicklas 141         numRemoved++;
2805 15 Oct 14 nicklas 142       }
2805 15 Oct 14 nicklas 143     }
2805 15 Oct 14 nicklas 144     
2805 15 Oct 14 nicklas 145     if (numRemoved > 0)
2805 15 Oct 14 nicklas 146     {
2805 15 Oct 14 nicklas 147       createpool.updatePoolData();
2805 15 Oct 14 nicklas 148     }
2805 15 Oct 14 nicklas 149     
2805 15 Oct 14 nicklas 150     if (selectedLibraries.length == 0)
2805 15 Oct 14 nicklas 151     {  
2805 15 Oct 14 nicklas 152       Doc.show('not-selected');
2805 15 Oct 14 nicklas 153       Doc.hide('lib-table');
2805 15 Oct 14 nicklas 154     }
2805 15 Oct 14 nicklas 155   }
2805 15 Oct 14 nicklas 156   
2805 15 Oct 14 nicklas 157   createpool.checkAll = function()
2805 15 Oct 14 nicklas 158   {
2805 15 Oct 14 nicklas 159     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 160     var check = null;
2805 15 Oct 14 nicklas 161     for (var i = 0; i < frm.elements.length; i++)
2805 15 Oct 14 nicklas 162     {
2805 15 Oct 14 nicklas 163       var e = frm.elements[i];
2805 15 Oct 14 nicklas 164       if (e.type == 'checkbox')
2805 15 Oct 14 nicklas 165       {
2805 15 Oct 14 nicklas 166         if (check == null) check = !e.checked;
2805 15 Oct 14 nicklas 167         e.checked = check;
2805 15 Oct 14 nicklas 168       }
2805 15 Oct 14 nicklas 169     }
2805 15 Oct 14 nicklas 170   }
2805 15 Oct 14 nicklas 171   
2805 15 Oct 14 nicklas 172   createpool.libraryInfoLoaded = function(response)
2805 15 Oct 14 nicklas 173   {
2805 15 Oct 14 nicklas 174     var libraries = response.libraries;
2805 15 Oct 14 nicklas 175     for (var libNo = 0; libNo < libraries.length; libNo++)
2805 15 Oct 14 nicklas 176     {
2805 15 Oct 14 nicklas 177       var lib = libraries[libNo];
2805 15 Oct 14 nicklas 178       selectedLibraries[selectedLibraries.length] = lib;
5436 17 May 19 nicklas 179       if (lib.pipeline == 'RNAseq') 
5436 17 May 19 nicklas 180       {
5436 17 May 19 nicklas 181         // We do not make this check if the pipeline is not RNAseq since we will catch that as an error in updatePoolData()
5436 17 May 19 nicklas 182         lib.excludeFromPool = lib.molarity > 0 && lib.remainingQuantity > 0 ? false : true;
5436 17 May 19 nicklas 183       }
2805 15 Oct 14 nicklas 184       createpool.addLibraryToTable(lib);
2805 15 Oct 14 nicklas 185     }
2805 15 Oct 14 nicklas 186     
2805 15 Oct 14 nicklas 187     createpool.updatePoolData();
2805 15 Oct 14 nicklas 188     
2805 15 Oct 14 nicklas 189     Doc.hide('not-selected');
2805 15 Oct 14 nicklas 190     Doc.show('lib-table');
2805 15 Oct 14 nicklas 191   }
2805 15 Oct 14 nicklas 192
2805 15 Oct 14 nicklas 193   createpool.addLibraryToTable = function(lib)
2805 15 Oct 14 nicklas 194   {
2805 15 Oct 14 nicklas 195     var tr = document.createElement('tr');
2805 15 Oct 14 nicklas 196     tr.id = 'lib.'+lib.id;
2805 15 Oct 14 nicklas 197     var className = 'highlight';
2805 15 Oct 14 nicklas 198     if (lib.excludeFromPool) className += ' excluded';
2805 15 Oct 14 nicklas 199     createpool.addColumn(tr, 'check', '<input type="checkbox" name="check.'+lib.id+'" value="'+lib.id+'">');
2805 15 Oct 14 nicklas 200     createpool.addColumn(tr, 'name', Strings.encodeTags(lib.name));
2805 15 Oct 14 nicklas 201     createpool.addColumn(tr, 'barcode', lib.barcode ? Strings.encodeTags(lib.barcode.name) : '-');
2805 15 Oct 14 nicklas 202     createpool.addColumn(tr, 'location', lib.bioWell ? Strings.encodeTags(lib.bioWell.bioPlate.name + ' ' + lib.bioWell.location) : '-');
2805 15 Oct 14 nicklas 203     createpool.addColumn(tr, 'remain', lib.remainingVolume ? Numbers.formatNumber(lib.remainingVolume, 1) : '-');
2805 15 Oct 14 nicklas 204     createpool.addColumn(tr, 'adapter', lib.libraryFracAdpt != null ? lib.libraryFracAdpt + '%' : '-');
2805 15 Oct 14 nicklas 205     createpool.addColumn(tr, 'molarity', lib.molarity ? Numbers.formatNumber(lib.molarity, 2) : '-');
2805 15 Oct 14 nicklas 206     createpool.addColumn(tr, 'volume', '');
2805 15 Oct 14 nicklas 207     createpool.addColumn(tr, 'eb', '');
2805 15 Oct 14 nicklas 208     createpool.addColumn(tr, 'status', '');
2805 15 Oct 14 nicklas 209     createpool.addColumn(tr, 'remarks', '');
2805 15 Oct 14 nicklas 210     tr.className = className;
2805 15 Oct 14 nicklas 211
2805 15 Oct 14 nicklas 212     // Rows should be sorted by barcode
2805 15 Oct 14 nicklas 213     // Locate existing row 
2805 15 Oct 14 nicklas 214     tr.sortBy = lib.barcode ? lib.barcode.name : lib.name;
2805 15 Oct 14 nicklas 215     var tbody = Doc.element('lib-table-rows');
2805 15 Oct 14 nicklas 216     
2805 15 Oct 14 nicklas 217     var target = null;
2805 15 Oct 14 nicklas 218     for (var i = 0; i < tbody.childNodes.length; i++)
2805 15 Oct 14 nicklas 219     {
2805 15 Oct 14 nicklas 220       var row = tbody.childNodes[i];
2805 15 Oct 14 nicklas 221       if (row.sortBy && (row.sortBy > tr.sortBy))
2805 15 Oct 14 nicklas 222       {
2805 15 Oct 14 nicklas 223         // Found it!
2805 15 Oct 14 nicklas 224         target = row;
2805 15 Oct 14 nicklas 225         break;
2805 15 Oct 14 nicklas 226       };
2805 15 Oct 14 nicklas 227     }
2805 15 Oct 14 nicklas 228     
2805 15 Oct 14 nicklas 229     tbody.insertBefore(tr, target);
2805 15 Oct 14 nicklas 230   }
2805 15 Oct 14 nicklas 231
2805 15 Oct 14 nicklas 232   createpool.addColumn = function(tr, idSuffix, text)
2805 15 Oct 14 nicklas 233   {
2805 15 Oct 14 nicklas 234     var td = document.createElement('td');
2805 15 Oct 14 nicklas 235     td.id = tr.id+'.'+idSuffix;
2805 15 Oct 14 nicklas 236     td.className = idSuffix;
2805 15 Oct 14 nicklas 237     td.innerHTML = text;
2805 15 Oct 14 nicklas 238     tr.appendChild(td);
2805 15 Oct 14 nicklas 239   }
2805 15 Oct 14 nicklas 240
2805 15 Oct 14 nicklas 241   
2805 15 Oct 14 nicklas 242   createpool.updatePoolData = function()
2805 15 Oct 14 nicklas 243   {
2805 15 Oct 14 nicklas 244     if (!targetVolumePerLibIsValid || selectedLibraries.length == 0) return;
2805 15 Oct 14 nicklas 245     
2805 15 Oct 14 nicklas 246     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 247     var targetVolumePerLib = parseFloat(frm.target_volume.value);
2805 15 Oct 14 nicklas 248     var mixingStrategy = Forms.getCheckedRadio(frm.mixing_strategy).value;
3107 27 Jan 15 nicklas 249     var targetMolarityInPool = parseFloat(frm.target_molarity.value);
2805 15 Oct 14 nicklas 250
2805 15 Oct 14 nicklas 251     var numSeparateMix = 0;
2805 15 Oct 14 nicklas 252     var numLowQuantity = 0;
2805 15 Oct 14 nicklas 253     var numExcluded = 0;
2805 15 Oct 14 nicklas 254
2805 15 Oct 14 nicklas 255     // Get all libs into an array
2805 15 Oct 14 nicklas 256     var libs = [];
2805 15 Oct 14 nicklas 257     var usedBarcodes = [];
2805 15 Oct 14 nicklas 258     var duplicateBarcodes = [];
2805 15 Oct 14 nicklas 259     for (var selectedNo = 0; selectedNo < selectedLibraries.length; selectedNo++)
2805 15 Oct 14 nicklas 260     {
2805 15 Oct 14 nicklas 261       var lib = selectedLibraries[selectedNo];
2805 15 Oct 14 nicklas 262       if (!lib.excludeFromPool)
2805 15 Oct 14 nicklas 263       {
2805 15 Oct 14 nicklas 264         libs[libs.length] = lib;
2805 15 Oct 14 nicklas 265         if (usedBarcodes[lib.barcode.name])
2805 15 Oct 14 nicklas 266         {
2805 15 Oct 14 nicklas 267           duplicateBarcodes[lib.barcode.name] = 1;
2805 15 Oct 14 nicklas 268         }
2805 15 Oct 14 nicklas 269         else
2805 15 Oct 14 nicklas 270         {
2805 15 Oct 14 nicklas 271           usedBarcodes[lib.barcode.name] = 1;
2805 15 Oct 14 nicklas 272         }
3107 27 Jan 15 nicklas 273         PoolMix.calculateLibVolume(lib, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
3107 27 Jan 15 nicklas 274         PoolMix.calculateEbVolume(lib, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
2805 15 Oct 14 nicklas 275       }
2805 15 Oct 14 nicklas 276       else
2805 15 Oct 14 nicklas 277       {
2805 15 Oct 14 nicklas 278         numExcluded++;
2805 15 Oct 14 nicklas 279       }
2805 15 Oct 14 nicklas 280     }
2805 15 Oct 14 nicklas 281       
2805 15 Oct 14 nicklas 282     // Calculate final pool volumes, molarity, etc.
3107 27 Jan 15 nicklas 283     poolInfo = PoolMix.calculateFinalPoolInfo(libs, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
2805 15 Oct 14 nicklas 284     
2805 15 Oct 14 nicklas 285     // Make remarks for each lib
2805 15 Oct 14 nicklas 286     for (var libNo = 0; libNo < selectedLibraries.length; libNo++)
2805 15 Oct 14 nicklas 287     {
2805 15 Oct 14 nicklas 288       var lib = selectedLibraries[libNo];
2805 15 Oct 14 nicklas 289       if (!lib.excludeFromPool)
2805 15 Oct 14 nicklas 290       {
2805 15 Oct 14 nicklas 291         var mark = '';
2805 15 Oct 14 nicklas 292         var tr = Doc.element('lib.'+lib.id);
5436 17 May 19 nicklas 293         if (duplicateBarcodes[lib.barcode.name] || lib.pipeline != 'RNAseq')
2805 15 Oct 14 nicklas 294         {
2805 15 Oct 14 nicklas 295           Doc.addClass(tr, 'lib-error');
2805 15 Oct 14 nicklas 296           lib.hasError = true;
2805 15 Oct 14 nicklas 297         }
2805 15 Oct 14 nicklas 298         else
2805 15 Oct 14 nicklas 299         {
2805 15 Oct 14 nicklas 300           Doc.removeClass(tr, 'lib-error');
2805 15 Oct 14 nicklas 301           lib.hasError = false;
2805 15 Oct 14 nicklas 302         }
2805 15 Oct 14 nicklas 303         Doc.removeClass(tr, 'warning');
2805 15 Oct 14 nicklas 304         if (lib.volume != lib.actualVolume)
2805 15 Oct 14 nicklas 305         {
2805 15 Oct 14 nicklas 306           mark = '*';
2805 15 Oct 14 nicklas 307           Doc.addClass(tr, 'warning');
2805 15 Oct 14 nicklas 308         }
2805 15 Oct 14 nicklas 309         if (lib.libraryFracAdpt == null || lib.libraryFracAdpt > LIBRARY_FRAC_ADPT_LIMIT)
2805 15 Oct 14 nicklas 310         {
2805 15 Oct 14 nicklas 311           Doc.addClass(tr, 'warning');
2805 15 Oct 14 nicklas 312         }
2805 15 Oct 14 nicklas 313         
2805 15 Oct 14 nicklas 314         Doc.element('lib.'+lib.id+'.volume').innerHTML = lib.mixFactor > 1 ? '-' : Numbers.formatNumber(lib.volume, 1)+mark;
2805 15 Oct 14 nicklas 315         if (mixingStrategy == 'fixed' && lib.mixFactor < 1.001)
2805 15 Oct 14 nicklas 316         {
2805 15 Oct 14 nicklas 317           Doc.element('lib.'+lib.id+'.eb').innerHTML = Numbers.formatNumber(lib.eb, 1);
2805 15 Oct 14 nicklas 318         }
2805 15 Oct 14 nicklas 319         else
2805 15 Oct 14 nicklas 320         {
2805 15 Oct 14 nicklas 321           Doc.element('lib.'+lib.id+'.eb').innerHTML = '-';
2805 15 Oct 14 nicklas 322         }
2805 15 Oct 14 nicklas 323         if (lib.eb != 0 || mixingStrategy == 'fixed') numSeparateMix++;
2805 15 Oct 14 nicklas 324         if (lib.volume > lib.actualVolume) numLowQuantity++;
2805 15 Oct 14 nicklas 325       }
2805 15 Oct 14 nicklas 326       
2805 15 Oct 14 nicklas 327       createpool.calculateRemarks(lib, mixingStrategy, duplicateBarcodes);
2805 15 Oct 14 nicklas 328       Doc.element('lib.'+lib.id+'.remarks').innerHTML = lib.remarks.join('; ');
2805 15 Oct 14 nicklas 329     }
2805 15 Oct 14 nicklas 330     
2805 15 Oct 14 nicklas 331     var warnMsg = null;
2805 15 Oct 14 nicklas 332     if (poolInfo.ebVolumeExtra < 0) 
2805 15 Oct 14 nicklas 333     {
2805 15 Oct 14 nicklas 334       warnMsg = 'Too many libs with low molarity';
2805 15 Oct 14 nicklas 335     }
2805 15 Oct 14 nicklas 336     
2805 15 Oct 14 nicklas 337     Doc.element('pool.eb').innerHTML = Numbers.formatNumber(poolInfo.ebVolumeExtra, 1);
2805 15 Oct 14 nicklas 338
2805 15 Oct 14 nicklas 339     var poolDiv = Doc.element('pool-summary');
2805 15 Oct 14 nicklas 340     var poolRow = Doc.element('lib-table-pool-summary');
2805 15 Oct 14 nicklas 341     var poolData = '<div class="pool-data">';
2805 15 Oct 14 nicklas 342     poolData += libs.length + ' libs • ';
2805 15 Oct 14 nicklas 343     poolData += Numbers.formatNumber(poolInfo.molarity, 2, 'nM')+' • ';
2805 15 Oct 14 nicklas 344     poolData += Numbers.formatNumber(poolInfo.totalVolume, 1, 'µl');
2805 15 Oct 14 nicklas 345     if (mixingStrategy == 'dynamic')
2805 15 Oct 14 nicklas 346     {
2805 15 Oct 14 nicklas 347       poolData += ' • <span class="eb">'+Numbers.formatNumber(Math.max(0, poolInfo.ebVolumeExtra), 1, 'µl')+'</span>';
2805 15 Oct 14 nicklas 348     }
2805 15 Oct 14 nicklas 349     if (warnMsg)
2805 15 Oct 14 nicklas 350     {
2805 15 Oct 14 nicklas 351       Doc.addClass(poolRow, 'warning');
2805 15 Oct 14 nicklas 352       Doc.element('pool.remarks').innerHTML = warnMsg;
2805 15 Oct 14 nicklas 353     }
2805 15 Oct 14 nicklas 354     else
2805 15 Oct 14 nicklas 355     {
2805 15 Oct 14 nicklas 356       Doc.removeClass(poolRow, 'warning');
2805 15 Oct 14 nicklas 357       Doc.element('pool.remarks').innerHTML = '';
2805 15 Oct 14 nicklas 358     }
2805 15 Oct 14 nicklas 359     
2805 15 Oct 14 nicklas 360     poolData += '</div>';
2805 15 Oct 14 nicklas 361     poolDiv.innerHTML = poolData;
2805 15 Oct 14 nicklas 362     
2805 15 Oct 14 nicklas 363     Doc.element('num_separate_mix').innerHTML = numSeparateMix;
2805 15 Oct 14 nicklas 364     Doc.element('num_low_quantity').innerHTML = numLowQuantity;
2805 15 Oct 14 nicklas 365     Doc.element('num_excluded').innerHTML = numExcluded;
2805 15 Oct 14 nicklas 366   }
2805 15 Oct 14 nicklas 367
2805 15 Oct 14 nicklas 368   createpool.calculateRemarks = function(lib, mixingStrategy, duplicateBarcodes)
2805 15 Oct 14 nicklas 369   {
2805 15 Oct 14 nicklas 370     var remarks = [];
2805 15 Oct 14 nicklas 371
4984 27 Sep 18 nicklas 372     if (lib.DO_NOT_USE)
4984 27 Sep 18 nicklas 373     {
4984 27 Sep 18 nicklas 374       remarks[remarks.length] = 'DoNotUse-'+Strings.encodeTags(lib.DO_NOT_USE + ': ' + lib.DO_NOT_USE_COMMENT);
4984 27 Sep 18 nicklas 375     }
4984 27 Sep 18 nicklas 376     
5436 17 May 19 nicklas 377     if (lib.pipeline != 'RNAseq')
5436 17 May 19 nicklas 378     {
5436 17 May 19 nicklas 379       remarks[remarks.length] = 'Invalid pipeline: ' + Strings.encodeTags(lib.pipeline);
5436 17 May 19 nicklas 380     }
5436 17 May 19 nicklas 381     
2805 15 Oct 14 nicklas 382     // Check if default barcode has been modified
2805 15 Oct 14 nicklas 383     if (lib.molarity != null)
2805 15 Oct 14 nicklas 384     {
2805 15 Oct 14 nicklas 385       if (duplicateBarcodes[lib.barcode.name])
2805 15 Oct 14 nicklas 386       {
2805 15 Oct 14 nicklas 387         remarks[remarks.length] = 'Duplicate barcode: ' + Strings.encodeTags(lib.barcode.name);
2805 15 Oct 14 nicklas 388       }
2805 15 Oct 14 nicklas 389       
2805 15 Oct 14 nicklas 390       if (lib.volume != lib.actualVolume)
2805 15 Oct 14 nicklas 391       {
2805 15 Oct 14 nicklas 392         if (lib.volume > lib.remainingVolume)
2805 15 Oct 14 nicklas 393         {
2805 15 Oct 14 nicklas 394           remarks[remarks.length] = 'Low quantity';
2805 15 Oct 14 nicklas 395         }
2805 15 Oct 14 nicklas 396         else 
2805 15 Oct 14 nicklas 397         {
2805 15 Oct 14 nicklas 398           remarks[remarks.length] = 'Low molarity';
2805 15 Oct 14 nicklas 399         }
2805 15 Oct 14 nicklas 400         if (mixingStrategy == 'fixed')
2805 15 Oct 14 nicklas 401         {
2805 15 Oct 14 nicklas 402           remarks[remarks.length] = 'Mix <span class="volume">'+Numbers.formatNumber(lib.actualVolume, 1) + '</span>+<span class="eb">' + Numbers.formatNumber(lib.actualEb, 1)+'µl</span>';
2805 15 Oct 14 nicklas 403         }
2805 15 Oct 14 nicklas 404         else
2805 15 Oct 14 nicklas 405         {
2805 15 Oct 14 nicklas 406           remarks[remarks.length] = 'Use <span class="volume">'+Numbers.formatNumber(lib.actualVolume, 1) + 'µl</span>';
2805 15 Oct 14 nicklas 407         }
2805 15 Oct 14 nicklas 408       }
2805 15 Oct 14 nicklas 409       
2805 15 Oct 14 nicklas 410       if (lib.libraryFracAdpt == null)
2805 15 Oct 14 nicklas 411       {
2805 15 Oct 14 nicklas 412         remarks[remarks.length] = 'Unknown adapter fraction';
2805 15 Oct 14 nicklas 413       }
2805 15 Oct 14 nicklas 414       else if (lib.libraryFracAdpt > LIBRARY_FRAC_ADPT_LIMIT)
2805 15 Oct 14 nicklas 415       {
2805 15 Oct 14 nicklas 416         remarks[remarks.length] = 'High adapter fraction';
2805 15 Oct 14 nicklas 417       }
2805 15 Oct 14 nicklas 418       
2805 15 Oct 14 nicklas 419       if (lib.speedVacConc != null)
2805 15 Oct 14 nicklas 420       {
2805 15 Oct 14 nicklas 421         remarks[remarks.length] = 'SpeedVac';
2805 15 Oct 14 nicklas 422       }
2805 15 Oct 14 nicklas 423       
2805 15 Oct 14 nicklas 424       if (lib.mixFactor > 1)
2805 15 Oct 14 nicklas 425       {
2805 15 Oct 14 nicklas 426         // Larger mix than default
2805 15 Oct 14 nicklas 427         remarks[remarks.length] = 'Mix <span class="volume">'+Numbers.formatNumber(lib.volume*lib.mixFactor, 1) + '</span>+<span class="eb">' + Numbers.formatNumber(lib.eb*lib.mixFactor, 1)+'µl</span>';
2805 15 Oct 14 nicklas 428         remarks[remarks.length] = 'Use <b>' + Numbers.formatNumber(lib.volume+lib.eb, 1) + 'µl</b> in pool';
2805 15 Oct 14 nicklas 429       }
2805 15 Oct 14 nicklas 430     }
2805 15 Oct 14 nicklas 431     if (lib.excludeFromPool)
2805 15 Oct 14 nicklas 432     {
2805 15 Oct 14 nicklas 433       remarks[remarks.length] = 'Excluded';
2805 15 Oct 14 nicklas 434     }
2805 15 Oct 14 nicklas 435     if (lib.comment)
2805 15 Oct 14 nicklas 436     {
2805 15 Oct 14 nicklas 437       remarks[remarks.length] = Strings.encodeTags(lib.comment);
2805 15 Oct 14 nicklas 438     }
2805 15 Oct 14 nicklas 439     lib.stratagene = Reggie.isStratagene(lib.name);
2805 15 Oct 14 nicklas 440     lib.external = Reggie.isExternal(lib.name);
2805 15 Oct 14 nicklas 441     lib.remarks = remarks;
2805 15 Oct 14 nicklas 442   }
2805 15 Oct 14 nicklas 443
2805 15 Oct 14 nicklas 444   
2805 15 Oct 14 nicklas 445   createpool.targetVolumeOnChange = function()
2805 15 Oct 14 nicklas 446   {
2805 15 Oct 14 nicklas 447     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 448     var targetVolumePerLib = parseFloat(frm.target_volume.value);
2805 15 Oct 14 nicklas 449     
2805 15 Oct 14 nicklas 450     targetVolumePerLibIsValid = false;
2805 15 Oct 14 nicklas 451     if (targetVolumePerLib < MIN_TARGET_VOLUME || targetVolumePerLib > MAX_TARGET_VOLUME)
2805 15 Oct 14 nicklas 452     {
2805 15 Oct 14 nicklas 453       Wizard.setInputStatus('target_volume', 'invalid', 'Must be between '+MIN_TARGET_VOLUME+' and '+MAX_TARGET_VOLUME+'µl');
2805 15 Oct 14 nicklas 454       return;
2805 15 Oct 14 nicklas 455     }
2805 15 Oct 14 nicklas 456     
2805 15 Oct 14 nicklas 457     Wizard.setInputStatus('target_volume', 'valid');
2805 15 Oct 14 nicklas 458     targetVolumePerLibIsValid = true;
2805 15 Oct 14 nicklas 459     createpool.updatePoolData();
2805 15 Oct 14 nicklas 460   }
2805 15 Oct 14 nicklas 461   
2805 15 Oct 14 nicklas 462   //Set target volume on the selected wells
2805 15 Oct 14 nicklas 463   createpool.setTargetVolume = function(event)
2805 15 Oct 14 nicklas 464   {
2805 15 Oct 14 nicklas 465     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 466     var checked = [];
2805 15 Oct 14 nicklas 467     var targetVolume;
2805 15 Oct 14 nicklas 468     for (var libNo = 0; libNo < selectedLibraries.length; libNo++)
2805 15 Oct 14 nicklas 469     {
2805 15 Oct 14 nicklas 470       var lib = selectedLibraries[libNo];
2805 15 Oct 14 nicklas 471       if (frm['check.'+lib.id].checked && lib.mixFactor > 1)
2805 15 Oct 14 nicklas 472       {
2805 15 Oct 14 nicklas 473         checked[checked.length] = lib;
2805 15 Oct 14 nicklas 474         if (!targetVolume) targetVolume = lib.targetVolume;
2805 15 Oct 14 nicklas 475       }
2805 15 Oct 14 nicklas 476     }
2805 15 Oct 14 nicklas 477     
2805 15 Oct 14 nicklas 478     if (checked.length == 0)
2805 15 Oct 14 nicklas 479     {
2805 15 Oct 14 nicklas 480       Forms.showNotification(event.currentTarget, 'No libraries with separate mix have been selected');
2805 15 Oct 14 nicklas 481       return;
2805 15 Oct 14 nicklas 482     }
2805 15 Oct 14 nicklas 483
2805 15 Oct 14 nicklas 484     targetVolume = parseFloat(prompt('Volume to use in pool ('+LIMIT_FOR_EXTRA_LARGE_MIX+'--'+MAX_TARGET_VOLUME+' µl)', targetVolume || lastTargetVolume || frm.target_volume.value));
2805 15 Oct 14 nicklas 485     if (isNaN(targetVolume))
2805 15 Oct 14 nicklas 486     {
2805 15 Oct 14 nicklas 487       targetVolume = null;
2805 15 Oct 14 nicklas 488     }
2805 15 Oct 14 nicklas 489     else if (targetVolume > MAX_TARGET_VOLUME)
2805 15 Oct 14 nicklas 490     {
2805 15 Oct 14 nicklas 491       targetVolume = MAX_TARGET_VOLUME;
2805 15 Oct 14 nicklas 492     }
2805 15 Oct 14 nicklas 493     else if (targetVolume < LIMIT_FOR_EXTRA_LARGE_MIX)
2805 15 Oct 14 nicklas 494     {
2805 15 Oct 14 nicklas 495       targetVolume = LIMIT_FOR_EXTRA_LARGE_MIX
2805 15 Oct 14 nicklas 496     }
2805 15 Oct 14 nicklas 497     lastTargetVolume = targetVolume;
2805 15 Oct 14 nicklas 498     if (targetVolume == '') targetVolume = null;
2805 15 Oct 14 nicklas 499
2805 15 Oct 14 nicklas 500     var targetVolumePerLib = parseFloat(frm.target_volume.value);
2805 15 Oct 14 nicklas 501     var mixingStrategy = Forms.getCheckedRadio(frm.mixing_strategy).value;
3107 27 Jan 15 nicklas 502     var targetMolarityInPool = parseFloat(frm.target_molarity.value);
3107 27 Jan 15 nicklas 503     
2805 15 Oct 14 nicklas 504     for (var libNo = 0; libNo < checked.length; libNo++)
2805 15 Oct 14 nicklas 505     {
2805 15 Oct 14 nicklas 506       var lib = checked[libNo];
2805 15 Oct 14 nicklas 507       lib.targetVolume = targetVolume;
3107 27 Jan 15 nicklas 508       PoolMix.calculateEbVolume(lib, targetMolarityInPool, targetVolumePerLib, mixingStrategy);
2805 15 Oct 14 nicklas 509     }
2805 15 Oct 14 nicklas 510     
2805 15 Oct 14 nicklas 511     createpool.updatePoolData();
2805 15 Oct 14 nicklas 512   }
2805 15 Oct 14 nicklas 513
2805 15 Oct 14 nicklas 514   //Set a comment on the checked libraries
2805 15 Oct 14 nicklas 515   createpool.commentChecked = function(event)
2805 15 Oct 14 nicklas 516   {
2805 15 Oct 14 nicklas 517     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 518     
2805 15 Oct 14 nicklas 519     // Get array with checked libs
2805 15 Oct 14 nicklas 520     var checked = [];
2805 15 Oct 14 nicklas 521     var comment;
2805 15 Oct 14 nicklas 522     for (var libNo = 0; libNo < selectedLibraries.length; libNo++)
2805 15 Oct 14 nicklas 523     {
2805 15 Oct 14 nicklas 524       var lib = selectedLibraries[libNo];
2805 15 Oct 14 nicklas 525       if (frm['check.'+lib.id].checked)
2805 15 Oct 14 nicklas 526       {
2805 15 Oct 14 nicklas 527         checked[checked.length] = lib;
2805 15 Oct 14 nicklas 528         if (!comment) comment = lib.comment;
2805 15 Oct 14 nicklas 529       }
2805 15 Oct 14 nicklas 530     }
2805 15 Oct 14 nicklas 531     
2805 15 Oct 14 nicklas 532     if (checked.length == 0)
2805 15 Oct 14 nicklas 533     {
2805 15 Oct 14 nicklas 534       Forms.showNotification(event.currentTarget, 'No libraries have been selected');
2805 15 Oct 14 nicklas 535       return;
2805 15 Oct 14 nicklas 536     }
2805 15 Oct 14 nicklas 537           
2805 15 Oct 14 nicklas 538     comment = prompt('Comment', comment || lastComment);
2805 15 Oct 14 nicklas 539     if (comment == null) return;
2805 15 Oct 14 nicklas 540
2805 15 Oct 14 nicklas 541     lastComment = comment;
2805 15 Oct 14 nicklas 542     
2805 15 Oct 14 nicklas 543     if (comment == '') comment = null;
2805 15 Oct 14 nicklas 544     for (var libNo = 0; libNo < checked.length; libNo++)
2805 15 Oct 14 nicklas 545     {
2805 15 Oct 14 nicklas 546       var lib = checked[libNo];
2805 15 Oct 14 nicklas 547       lib.comment = comment;
2805 15 Oct 14 nicklas 548     }
2805 15 Oct 14 nicklas 549     
2805 15 Oct 14 nicklas 550     createpool.updatePoolData();
2805 15 Oct 14 nicklas 551   }
2805 15 Oct 14 nicklas 552   
2805 15 Oct 14 nicklas 553   createpool.validateStep1 = function(event)
2805 15 Oct 14 nicklas 554   {
2805 15 Oct 14 nicklas 555     var valid = true;
2805 15 Oct 14 nicklas 556     
2805 15 Oct 14 nicklas 557     valid &= targetVolumePerLibIsValid;
2805 15 Oct 14 nicklas 558     valid &= (selectedLibraries.length > 0);
2805 15 Oct 14 nicklas 559
5436 17 May 19 nicklas 560     var numIncluded = 0;
2805 15 Oct 14 nicklas 561     for (var libNo = 0; libNo < selectedLibraries.length; libNo++)
2805 15 Oct 14 nicklas 562     {
2805 15 Oct 14 nicklas 563       var lib = selectedLibraries[libNo];
2805 15 Oct 14 nicklas 564       valid &= !lib.hasError;
5436 17 May 19 nicklas 565       if (!lib.excludeFromPool) numIncluded++;
2805 15 Oct 14 nicklas 566     }
2805 15 Oct 14 nicklas 567
5436 17 May 19 nicklas 568     valid &= (numIncluded > 0);
5436 17 May 19 nicklas 569     
2805 15 Oct 14 nicklas 570     if (!valid) event.preventDefault();
2805 15 Oct 14 nicklas 571   }
2805 15 Oct 14 nicklas 572
2805 15 Oct 14 nicklas 573   createpool.submit = function()
2805 15 Oct 14 nicklas 574   {
2805 15 Oct 14 nicklas 575     var frm = document.forms['reggie'];
2805 15 Oct 14 nicklas 576
2805 15 Oct 14 nicklas 577     var submitInfo = {};
2805 15 Oct 14 nicklas 578     submitInfo.pools = [];
2805 15 Oct 14 nicklas 579     submitInfo.flagged = []; // Always empty
2805 15 Oct 14 nicklas 580     var mixingStrategy = Forms.getCheckedRadio(frm.mixing_strategy).value;
2805 15 Oct 14 nicklas 581     
2805 15 Oct 14 nicklas 582     var pool = {};
2805 15 Oct 14 nicklas 583     pool.name = frm.poolName.value;
2805 15 Oct 14 nicklas 584     pool.comment = frm.poolComments.value;
2805 15 Oct 14 nicklas 585     pool.ebVolumeExtra = Math.max(0, poolInfo.ebVolumeExtra);
2805 15 Oct 14 nicklas 586     pool.targetVolumeInPoolPerLib = parseFloat(frm.target_volume.value);
3107 27 Jan 15 nicklas 587     pool.targetPoolMolarity = parseFloat(frm.target_molarity.value);
2805 15 Oct 14 nicklas 588     pool.mixingStrategy = mixingStrategy;
2805 15 Oct 14 nicklas 589     pool.libs = [];
2805 15 Oct 14 nicklas 590     pool.excluded = [];
2805 15 Oct 14 nicklas 591     
2805 15 Oct 14 nicklas 592     for (var libNo = 0; libNo < selectedLibraries.length; libNo++)
2805 15 Oct 14 nicklas 593     {
2805 15 Oct 14 nicklas 594       var lib = selectedLibraries[libNo];
2805 15 Oct 14 nicklas 595       
2805 15 Oct 14 nicklas 596       // We send library id, name and mixing volumes
2805 15 Oct 14 nicklas 597       if (!lib.excludeFromPool)
2805 15 Oct 14 nicklas 598       {
2805 15 Oct 14 nicklas 599         var tmp = {};
2805 15 Oct 14 nicklas 600         tmp.id = lib.id;
2805 15 Oct 14 nicklas 601         tmp.name = lib.name;
2805 15 Oct 14 nicklas 602         tmp.volume = lib.actualVolume;
2805 15 Oct 14 nicklas 603         tmp.eb = lib.actualEb;
2805 15 Oct 14 nicklas 604         tmp.mixFactor = lib.mixFactor;
2805 15 Oct 14 nicklas 605         if (lib.mixFactor > 1 && lib.targetVolume && mixingStrategy == 'dynamic') 
2805 15 Oct 14 nicklas 606         {
2805 15 Oct 14 nicklas 607           tmp.targetVolume = lib.targetVolume;
2805 15 Oct 14 nicklas 608         }
2805 15 Oct 14 nicklas 609         tmp.comment = lib.comment;
2805 15 Oct 14 nicklas 610         pool.libs[pool.libs.length] = tmp;
2805 15 Oct 14 nicklas 611       }
2805 15 Oct 14 nicklas 612     }
2805 15 Oct 14 nicklas 613     submitInfo.pools[submitInfo.pools.length] = pool;
2805 15 Oct 14 nicklas 614     
2805 15 Oct 14 nicklas 615     var url = '../Pool.servlet?ID='+App.getSessionId();
2805 15 Oct 14 nicklas 616     url += '&cmd=CreatePools';
2805 15 Oct 14 nicklas 617     Wizard.showLoadingAnimation('Performing registration...');
2805 15 Oct 14 nicklas 618     Wizard.asyncJsonRequest(url, createpool.submissionResults, 'POST', JSON.stringify(submitInfo));
2805 15 Oct 14 nicklas 619   }
2805 15 Oct 14 nicklas 620   
2805 15 Oct 14 nicklas 621   createpool.submissionResults = function(response)
2805 15 Oct 14 nicklas 622   {
2805 15 Oct 14 nicklas 623     Wizard.showFinalMessage(response.messages);
2805 15 Oct 14 nicklas 624     Doc.show('gorestart');
2805 15 Oct 14 nicklas 625   }
2805 15 Oct 14 nicklas 626
2805 15 Oct 14 nicklas 627   return createpool;
2805 15 Oct 14 nicklas 628 }();
2805 15 Oct 14 nicklas 629
2805 15 Oct 14 nicklas 630 Doc.onLoad(CreatePool.initPage);
2805 15 Oct 14 nicklas 631