Changeset 6326


Ignore:
Timestamp:
Jun 14, 2021, 9:06:23 AM (12 months ago)
Author:
Nicklas Nordborg
Message:

Merge Reggie 4.31.3 to the trunk

Location:
extensions/net.sf.basedb.reggie/trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • extensions/net.sf.basedb.reggie/trunk

  • extensions/net.sf.basedb.reggie/trunk/README

    r6309 r6326  
    22
    33 1. BASE 3.18.1
    4  2. Open Grid Scheduler extension 1.2 must be installed
     4 2. Open Grid Scheduler extension 1.4 must be installed
    55 3. Thumbnails extension 1.2 must be installed
    66 
  • extensions/net.sf.basedb.reggie/trunk/resources/outtake/define.js

    r6220 r6326  
    44  var debug = 0;
    55 
    6   var subtypeRNA = null;
    7   var subtypeDNA = null;
     6  var subtypeSelected = null;
    87 
    98  var sourceList;
     
    1211  var targetAmountIsValid = false;
    1312  var targetVolumeIsValid = false;
     13
     14  var needTargetAmount = true;
     15  var needTargetVolume = true;
     16 
    1417 
    1518  // Page initialization
     
    1821    // Step 1
    1922    Events.addEventHandler('step-1', 'wizard-validate', outtake.validateStep1);
     23    Events.addEventHandler('outtakeType', 'change', outtake.outtakeTypeOnChange);
    2024    Buttons.addClickHandler('sourceList.select', outtake.selectSourceList);
    2125    Events.addEventHandler('sourceList', 'base-selected', outtake.sourceListSelected);
     
    4044  }
    4145
     46  outtake.outtakeTypeOnChange = function()
     47  {
     48    var frm = document.forms['reggie'];
     49
     50    subtypeSelected = null;
     51   
     52    var type = frm.outtakeType.value;
     53    if (type == 'RNA' || type == 'DNA')
     54    {
     55      needTargetAmount = true;
     56      needTargetVolume = true;
     57    }
     58    else
     59    {
     60      needTargetAmount = false;
     61      needTargetVolume = true;
     62    }
     63   
     64    Doc.showHide('targetAmountSection', needTargetAmount);
     65    Doc.showHide('targetVolumeSection', needTargetVolume);
     66    Doc.showHide('targetConcSection', needTargetVolume && needTargetAmount);
     67   
     68    if (frm.sourceList.value) outtake.sourceListSelected();
     69  }
     70
    4271  outtake.selectSourceList = function()
    4372  {
    4473    var frm = document.forms['reggie'];
    4574   
    46     if (subtypeDNA == null) subtypeDNA = Reggie.getSubtypeInfo('DNA');
    47     if (subtypeRNA == null) subtypeRNA = Reggie.getSubtypeInfo('RNA');
     75    if (subtypeSelected == null) subtypeSelected = Reggie.getSubtypeInfo(frm.outtakeType.value);
    4876   
    4977    var url = '&resetTemporary=1';
     
    5482    }
    5583    url += '&tmpfilter:INT:memberType='+Data.int('page-data', 'extract-type');
    56     url += '&tmpfilter:INT:itemSubtype='+encodeURIComponent(subtypeDNA.id+'|'+subtypeRNA.id);
     84    url += '&tmpfilter:INT:itemSubtype='+encodeURIComponent(subtypeSelected.id);
    5785    Dialogs.selectItem('ITEMLIST', 'sourceList', 0, url);
    5886  }
     
    6896    Doc.element('listConc').innerHTML = '';
    6997
    70     var list = event.detail;
    71     frm.sourceList[0] = new Option(list.name, list.id);
     98    if (event)
     99    {
     100      var list = event.detail;
     101      frm.sourceList[0] = new Option(list.name, list.id);
     102      frm.sourceList.selectedIndex = 0;
     103    }
    72104    Wizard.setInputStatus('sourceList', 'checking', 'Checking list...');
    73105   
    74106    var url = '../Outtake.servlet?ID='+App.getSessionId();
    75107    url += '&cmd=CheckSourceList';
    76     url += '&listId='+list.id;
     108    url += '&outtakeType='+frm.outtakeType.value;
     109    url += '&listId='+frm.sourceList.value;
    77110    Wizard.asyncJsonRequest(url, outtake.sourceListValidated);
    78 
    79111  }
    80112 
     
    98130      listType += ' (' + Strings.encodeTags(sourceList.subtype.name) + ')';
    99131    }
    100     else if (sourceList.numDifferentSubtypes > 1)
    101     {
    102       Wizard.setInputStatus('listType', 'warning', 'The list have items of ' + sourceList.numDifferentSubtypes + ' different types');
    103     }
    104    
    105132    Doc.element('listType').innerHTML = listType;
    106133    Doc.element('listSize').innerHTML = sourceList.size;
    107134   
    108     var remainingQuantity = sourceList.remainingQuantity;
    109     if (remainingQuantity)
    110     {
    111       Doc.element('listRemainingQuantity').innerHTML =
    112         Reggie.formatNumber(remainingQuantity.min, ' µg (min), ', 2) +
    113         Reggie.formatNumber(remainingQuantity.max, ' µg (max)', 2);
    114      
    115       if (remainingQuantity.nulls > 0)
    116       {
    117         Wizard.setInputStatus('listRemainingQuantity', 'warning', remainingQuantity.nulls + ' items have unknown remaining quantity');
    118       }
    119     }
    120     var conc = sourceList.conc;
    121     if (conc)
    122     {
    123       Doc.element('listConc').innerHTML =
    124         Reggie.formatNumber(conc.min, ' ng/µl (min), ', 2) +
    125         Reggie.formatNumber(conc.max, ' ng/µl (max)', 2);
    126      
    127       if (conc.nulls > 0)
    128       {
    129         Wizard.setInputStatus('listConc', 'warning', conc.nulls + ' items have unknown concentration');
    130       }
    131     }
     135    if (needTargetAmount || needTargetVolume)
     136    {
     137      var remainingQuantity = sourceList.remainingQuantity;
     138      if (remainingQuantity)
     139      {
     140        var remainingQuantityUnit = needTargetAmount ? ' µg' : ' µl';
     141        Doc.element('listRemainingQuantity').innerHTML =
     142          Reggie.formatNumber(remainingQuantity.min, remainingQuantityUnit+' (min), ', 2) +
     143          Reggie.formatNumber(remainingQuantity.max, remainingQuantityUnit+' (max)', 2);
     144       
     145        if (remainingQuantity.nulls > 0)
     146        {
     147          Wizard.setInputStatus('listRemainingQuantity', 'warning', remainingQuantity.nulls + ' items have unknown remaining quantity');
     148        }
     149      }
     150    }
     151    else
     152    {
     153      Doc.element('listRemainingQuantity').innerHTML = '';
     154    }
     155
     156    if (needTargetAmount && needTargetVolume)
     157    {
     158      var conc = sourceList.cnc;
     159      if (conc)
     160      {
     161        Doc.element('listConc').innerHTML =
     162          Reggie.formatNumber(conc.min, ' ng/µl (min), ', 2) +
     163          Reggie.formatNumber(conc.max, ' ng/µl (max)', 2);
     164       
     165        if (ndConc.nulls > 0)
     166        {
     167          Wizard.setInputStatus('listConc', 'warning', conc.nulls + ' items have unknown concentration');
     168        }
     169      }
     170    }
     171    else
     172    {
     173      Doc.element('listConc').innerHTML = '';
     174    }
     175
    132176
    133177    if (sourceList.size == 0)
     
    148192      Wizard.showGoNextConfirmation(true, 'Confirm using the list with ' + sourceList.numDoNotUse + ' items marked as DoNotUse');
    149193    }
    150     else if (sourceList.numDifferentSubtype > 0)
    151     {
    152       Wizard.setInputStatus('sourceList', 'warning', 'Items in the list are not of the same subtype');
     194    else if (sourceList.numIncorrectSubtype > 1)
     195    {
     196      Wizard.setInputStatus('sourceList', 'warning', 'The list have '+sourceList.numIncorrectSubtype+' items that are not '+frm.outtakeType.value);
    153197    }
    154198    else
     
    237281    var targetConc = 1000 * targetAmount / targetVolume;
    238282   
    239     if (!isNaN(targetConc))
    240     {
    241       Doc.element('targetConcentration').innerHTML = Reggie.formatNumber(targetConc, ' ng/µl', 2);
     283    if (needTargetAmount && needTargetVolume)
     284    {
     285      if (!isNaN(targetConc))
     286      {
     287        Doc.element('targetConcentration').innerHTML = Reggie.formatNumber(targetConc, ' ng/µl', 2);
     288      }
    242289    }
    243290   
    244291    if (sourceList)
    245292    {
    246       if (sourceList.remainingQuantity && sourceList.remainingQuantity.min < targetAmount)
    247       {
    248         Wizard.setInputStatus('targetAmount', 'warning', 'Some items in the list have less remaining quantity: '+ Reggie.formatNumber(sourceList.remainingQuantity.min, ' µg', 2));
     293      if (needTargetAmount)
     294      {
     295        if (sourceList.remainingQuantity && sourceList.remainingQuantity.min < targetAmount)
     296        {
     297          Wizard.setInputStatus('targetAmount', 'warning', 'Some items in the list have less remaining quantity: '+ Reggie.formatNumber(sourceList.remainingQuantity.min, ' µg', 2));
     298        }
    249299      }
    250300     
    251       if (sourceList.conc && sourceList.conc.min < targetConc)
    252       {
    253         Wizard.setInputStatus('targetVolume', 'warning', 'Some items in the list has too low concentration: '+ Reggie.formatNumber(sourceList.conc.min, ' ng/µl', 2));
    254       }
     301      if (needTargetAmount && needTargetVolume)
     302      {
     303        if (sourceList.conc && sourceList.conc.min < targetConc)
     304        {
     305          Wizard.setInputStatus('targetVolume', 'warning', 'Some items in the list has too low concentration: '+ Reggie.formatNumber(sourceList.ndConc.min, ' ng/µl', 2));
     306        }
     307      }
     308      else if (needTargetVolume)
     309      {
     310        if (sourceList.remainingQuantity && sourceList.remainingQuantity.min < targetVolume)
     311        {
     312          Wizard.setInputStatus('targetVolume', 'warning', 'Some items in the list have less remaining quantity: '+ Reggie.formatNumber(sourceList.remainingQuantity.min, ' µl', 2));
     313        }
     314      }
     315
    255316    }
    256317  }
     
    268329    valid &= sourceListIsValid;
    269330    valid &= nameIsValid;
    270     valid &= targetAmountIsValid;
    271     valid &= targetVolumeIsValid;
     331    if (needTargetAmount) valid &= targetAmountIsValid;
     332    if (needTargetVolume) valid &= targetVolumeIsValid;
    272333   
    273334    if (!valid) event.preventDefault();
     
    281342   
    282343    submitInfo.sourceList = parseInt(frm.sourceList.value);
     344    submitInfo.outtakeType = frm.outtakeType.value;
    283345    submitInfo.outtakeName = frm.outtakeName.value;
    284     submitInfo.targetAmount = parseFloat(frm.targetAmount.value);
    285     submitInfo.targetVolume = parseFloat(frm.targetVolume.value);
     346    if (needTargetAmount)
     347    {
     348      submitInfo.targetAmount = parseFloat(frm.targetAmount.value);
     349    }
     350    if (needTargetVolume)
     351    {
     352      submitInfo.targetVolume = parseFloat(frm.targetVolume.value);
     353    }
    286354    submitInfo.comments = frm.comments.value;
    287355
  • extensions/net.sf.basedb.reggie/trunk/resources/outtake/define.jsp

    r6220 r6326  
    5555        <td class="prompt">Outtake name</td>
    5656        <td class="input"><input type="text" name="outtakeName" id="outtakeName"
    57           class="auto-init required" data-auto-init="focus-on-enter" data-next-focus="sourceList.select"
     57          class="auto-init required" data-auto-init="focus-on-enter" data-next-focus="outtakeType"
    5858          maxlength="255"></td>
    5959        <td class="status" id="outtakeName.status"></td>
     
    6363          of the item list with aliquots.
    6464        </td>
     65      </tr>
     66      <tr>
     67        <td class="prompt">Outtake type</td>
     68        <td class="input">
     69          <select name="outtakeType" id="outtakeType" class="required auto-init"
     70            data-auto-init="focus-on-enter" data-next-focus="sourceList.select"
     71            style="width: 10em;">
     72            <option value="DNA">DNA
     73            <option value="RNA">RNA
     74            <option value="LYSATE">Lysate
     75            <option value="FLOWTHROUGH">FlowThrough
     76          </select>
     77        </td>
     78        <td class="status" id="outtakeType.status"></td>
     79        <td class="help">
     80          <span id="outtakeType.message" class="message"></span>
     81          Select the type of items in the outtake.
     82        </td>
     83       
    6584      </tr>
    6685      <tr class="align-top">
     
    7796        <td class="help">
    7897          <span id="sourceList.message" class="message"></span>
    79           Select a source item list that contains either RNA or DNA items.
     98          Select a source item list that contains items of the selected type.
    8099        </td>
    81100      </tr>
     
    106125      </tr>
    107126      </tbody>
    108       <tr>
     127      <tr id="targetAmountSection">
    109128        <td class="prompt">Target amount</td>
    110129        <td class="input"><input type="text" name="targetAmount" id="targetAmount"
     
    118137        </td>
    119138      </tr>
    120       <tr>
     139      <tr id="targetVolumeSection">
    121140        <td class="prompt">Target volume</td>
    122141        <td class="input"><input type="text" name="targetVolume" id="targetVolume"
     
    126145        <td class="help">
    127146          <span id="targetVolume.message" class="message"></span>
    128           Specify the target volume in µl of the normalized aliquots.
     147          Specify the target volume in µl of the aliquots.
    129148        </td>
    130149      </tr>
    131       <tbody class="info-section">
     150      <tbody class="info-section" id="targetConcSection">
    132151      <tr>
    133152        <td class="prompt">Target concentration</td>
  • extensions/net.sf.basedb.reggie/trunk/resources/outtake/delivery_export.js

    r4173 r6326  
    3838      {
    3939        var list = workLists[i];
    40         var name = list.name + ' (' + list.size + ')';
     40        var name = list.name + ' (' + list.size+(list.parentType?' '+list.parentType : '') + ')';
    4141        var option = new Option(name, list.id);
    4242        option.workList = list;
  • extensions/net.sf.basedb.reggie/trunk/resources/outtake/picklist.js

    r6220 r6326  
    4646      {
    4747        var list = workLists[i];
    48         var name = list.name + ' (' + list.size + ')';
     48        var name = list.name + ' (' + list.size+(list.parentType?' '+list.parentType : '') + ')';
    4949        var option = new Option(name, list.id);
    5050        option.workList = list;
     
    9898   
    9999    var list = response.list;
    100     Doc.element('targetAmount').innerHTML = Reggie.formatNumber(list.TargetAmount, ' µg', 1);
    101     Doc.element('targetVolume').innerHTML = Reggie.formatNumber(list.TargetVolume, ' µl', 1);
    102     Doc.element('targetConcentration').innerHTML = Reggie.formatNumber(1000 * list.TargetAmount / list.TargetVolume, ' ng/µl', 2);
     100    var needTargetAmount = list.TargetAmount > 0;
     101    var needTargetVolume = list.TargetVolume > 0;
     102   
     103    Doc.element('parentType').innerHTML = Strings.encodeTags(list.parentType);
     104    if (needTargetAmount)
     105    {
     106      Doc.element('targetAmount').innerHTML = Reggie.formatNumber(list.TargetAmount, ' µg', 1);
     107    }
     108    else
     109    {
     110      Doc.hide('targetAmountSection');
     111    }
     112    if (needTargetVolume)
     113    {
     114      Doc.element('targetVolume').innerHTML = Reggie.formatNumber(list.TargetVolume, ' µl', 1);
     115    }
     116    else
     117    {
     118      Doc.hide('targetVolumeSection');
     119    }
     120    if (needTargetAmount && needTargetVolume)
     121    {
     122      Doc.element('targetConcentration').innerHTML = Reggie.formatNumber(1000 * list.TargetAmount / list.TargetVolume, ' ng/µl', 2);
     123    }
     124    else
     125    {
     126      Doc.hide('targetConcentrationSection');
     127    }
    103128   
    104129    var aliquots = response.aliquots;
     
    108133    var lastStorageBox = -1;
    109134    var numRows = 0;
    110 
    111     var targetConc = 1000 * list.TargetAmount / list.TargetVolume; // ng/µl;
    112135   
    113136    for (var aliquotNo = 0; aliquotNo < aliquots.length; aliquotNo++)
     
    168191      {
    169192        dilution = a.dilution;
    170         if (dilution.amount < list.TargetAmount)
    171         {
    172           // Not enough remaining quantity -- take as much as possible
    173           remarks[remarks.length] = 'Remain: ' + Reggie.formatNumber(dilution.amount, ' µg', 1);
    174         }
    175         else if (dilution.amount > list.TargetAmount)
    176         {
    177           // Typically happens to avoid taking less than 1µl
    178           remarks[remarks.length] = 'Large mix: ' + Reggie.formatNumber(dilution.amount, ' µg', 1);
     193        if (needTargetAmount)
     194        {
     195          if (dilution.amount < list.TargetAmount)
     196          {
     197            // Not enough remaining quantity -- take as much as possible
     198            remarks[remarks.length] = 'Remain: ' + Reggie.formatNumber(dilution.amount, ' µg', 1);
     199          }
     200          else if (dilution.amount > list.TargetAmount)
     201          {
     202            // Typically happens to avoid taking less than 1µl
     203            remarks[remarks.length] = 'Large mix: ' + Reggie.formatNumber(dilution.amount, ' µg', 1);
     204          }
     205        }
     206        else if (needTargetVolume)
     207        {
     208          if (dilution.volume < list.TargetVolume)
     209          {
     210            // Not enough remaining quantity -- take as much as possible
     211            remarks[remarks.length] = 'Remain: ' + Reggie.formatNumber(dilution.volume, ' µl', 1);
     212          }
    179213        }
    180214        if (dilution.water < 0)
     
    183217          remarks[remarks.length] = 'Conc: ' + Reggie.formatNumber(p.conc, ' ng/µl', 2);
    184218          dilution.water = null;
     219        }
     220      }
     221      else
     222      {
     223        if (!p.remainingQuantity)
     224        {
     225          remarks[remarks.length] = 'Remain: unknown';
     226        }
     227        else if (!p.NdConc)
     228        {
     229          remarks[remarks.length] = 'Conc: unknown';
    185230        }
    186231      }
  • extensions/net.sf.basedb.reggie/trunk/resources/outtake/picklist2.jsp

    r4172 r6326  
    153153  </tr>
    154154  <tr>
     155    <th>Parent item type</th>
     156    <td><span id="parentType"></span></td>
     157  </tr>
     158  <tr id="targetAmountSection">
    155159    <th>Target amount</th>
    156160    <td><span id="targetAmount"></span></td>
    157161  </tr>
    158   <tr>
     162  <tr id="targetVolumeSection">
    159163    <th>Target volume</th>
    160164    <td><span id="targetVolume"></span></td>
    161165  </tr>
    162   <tr>
     166  <tr id="targetConcentrationSection">
    163167    <th>Target concentration</th>
    164168    <td><span id="targetConcentration"></span></td>
  • extensions/net.sf.basedb.reggie/trunk/resources/outtake/register.js

    r4179 r6326  
    4949      {
    5050        var list = workLists[i];
    51         var name = list.name + ' (' + list.size + ')';
     51        var name = list.name + ' (' + list.size+(list.parentType?' '+list.parentType : '') + ')';
    5252        var option = new Option(name, list.id);
    5353        option.workList = list;
     
    193193    {
    194194      submitInfo.sampleConsumed = Doc.element('sampleConsumedYes').checked;
    195       var except = [];
    196195      submitInfo.except = Link.getIdsInList(frm.except, workList.itemType);
    197196    }
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Annotationtype.java

    r6277 r6326  
    18561856  */
    18571857  public static final Annotationtype OUTTAKE_TARGET_VOLUME =
    1858       new Annotationtype("OuttakeTargetVolume", Type.FLOAT, false, Item.ITEMLIST);
    1859 
     1858    new Annotationtype("OuttakeTargetVolume", Type.FLOAT, false, Item.ITEMLIST);
     1859
     1860  /**
     1861    Subtype of the parent items for the outtake aliquots.
     1862    @since 4.31.3
     1863  */
     1864  public static final Annotationtype OUTTAKE_PARENT_TYPE =
     1865    new Annotationtype("OuttakeParentType", Type.STRING, false, Item.ITEMLIST);
     1866   
    18601867  /**
    18611868    INCA2 diagnosis date annotation (provtagningsdatum). We need this to
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/InstallServlet.java

    r6277 r6326  
    704704        jsonChecks.add(checkAnnotationType(dc, Annotationtype.OUTTAKE_TARGET_AMOUNT, 1, null, createIfMissing, effectivePermissionsUse));
    705705        jsonChecks.add(checkAnnotationType(dc, Annotationtype.OUTTAKE_TARGET_VOLUME, 1, null, createIfMissing, effectivePermissionsUse));
     706        jsonChecks.add(checkAnnotationType(dc, Annotationtype.OUTTAKE_PARENT_TYPE, 1,
     707            new ValueOptions("DNA", "RNA", "Lysate", "FlowThrough"), createIfMissing, effectivePermissionsUse));
    706708        jsonChecks.add(checkAnnotationType(dc, Annotationtype.OUTTAKE_RESULT, 1,
    707709            new ValueOptions("Successful", "Failed"),
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/OuttakeServlet.java

    r6220 r6326  
    1717import org.json.simple.JSONObject;
    1818
     19import net.sf.basedb.core.AnyToAny;
    1920import net.sf.basedb.core.BioMaterial;
    2021import net.sf.basedb.core.BioMaterialEvent;
     
    8990
    9091        int listId = Values.getInt(req.getParameter("listId"));
     92        ItemSubtype outtakeType = Subtype.getByCName(req.getParameter("outtakeType")).get(dc);
    9193       
    9294        ItemList list = ItemList.getById(dc, listId);
     
    9496        ItemSubtype memberSubtype = list.getItemSubtype();
    9597       
    96         Set<ItemSubtype> memberSubtypes = new HashSet<>();
    97         if (memberSubtype != null) memberSubtypes.add(memberSubtype);
    98 
    9998        JSONObject jsonList = new JSONObject();
    10099        jsonList.put("id", list.getId());
     
    106105        {
    107106          int numDoNotUse = 0;
     107          int numIncorrectSubtype = 0;
    108108          ItemQuery<Extract> memberQuery = list.getMembers();
    109109          memberQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     
    121121            conc.add(c);
    122122           
    123             ItemSubtype subtype = e.getItemSubtype();
    124             memberSubtypes.add(subtype);
     123            ItemSubtype subtype = e.getItemSubtype();         
     124            if (!outtakeType.equals(subtype))
     125            {
     126              numIncorrectSubtype++;
     127            }
    125128           
    126129            if (Annotationtype.DO_NOT_USE.getAnnotationValue(dc, e) != null)
     
    133136          jsonList.put("conc", conc.asJSONObject());
    134137          jsonList.put("numDoNotUse", numDoNotUse);
    135         }
    136        
    137         jsonList.put("numDifferentSubtypes", memberSubtypes.size());
    138         if (memberSubtypes.size() == 1)
    139         {
    140           memberSubtype = memberSubtypes.iterator().next();
     138          jsonList.put("numIncorrectSubtype", numIncorrectSubtype);
     139        }
     140       
     141        if (memberSubtype != null)
     142        {
    141143          jsonList.put("subtype", Subtype.get(memberSubtype).asJSONObject(dc));
    142144        }
     
    181183          jsonList.put("size", list.getSize());
    182184          jsonList.put("comments", list.getDescription());
     185          jsonList.put("parentType", Annotationtype.OUTTAKE_PARENT_TYPE.getAnnotationValue(dc, list));
    183186          jsonLists.add(jsonList);
    184187        }
     
    268271        jsonList.put("TargetAmount", targetAmount);
    269272        jsonList.put("TargetVolume", targetVolume);
     273        jsonList.put("parentType", Annotationtype.OUTTAKE_PARENT_TYPE.getAnnotationValue(dc, manager, list));
    270274       
    271275        ItemQuery<Extract> memberQuery = list.getMembers();
     
    298302          if (conc == null) conc = (Float)Annotationtype.QUBIT_CONC.getAnnotationValue(dc, parent);
    299303         
    300           if (remain != null && conc != null)
    301           {
    302             Dilution d = new Dilution(targetAmount, targetVolume, conc, remain);
    303             jsonA.put("dilution", d.asJSONObject());
     304          if (targetAmount != null && targetVolume != null)
     305          {
     306            // Aliquots should be normalized
     307            if (remain != null && conc != null)
     308            {
     309              Dilution d = new Dilution(targetAmount, targetVolume, conc, remain);
     310              jsonA.put("dilution", d.asJSONObject());
     311            }
     312          }
     313          else if (targetVolume != null)
     314          {
     315            if (remain != null)
     316            {
     317              // A specific volume is needed (remaining quantity is expcted to be µl)
     318              Dilution d = new Dilution(targetVolume, remain);
     319              jsonA.put("dilution", d.asJSONObject());
     320            }
    304321          }
    305322         
     
    328345       
    329346        ItemList workList = ItemList.getById(dc, workListId);
    330        
     347        Float targetAmount = (Float)Annotationtype.OUTTAKE_TARGET_AMOUNT.getAnnotationValue(dc, workList);
     348        Float targetVolume = (Float)Annotationtype.OUTTAKE_TARGET_VOLUME.getAnnotationValue(dc, workList);
     349     
    331350        ItemQuery<Extract> memberQuery = workList.getMembers();
    332351        memberQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     
    346365       
    347366        TableWriter tw = new TableWriter(out);
    348         tw.tablePrintData("Name", "Box", "Position", "Quantity (µg)", "Concentration (ng/µl)");
    349         Object[] data = new Object[5];
     367        Object[] data = null;
     368        if (targetAmount != null && targetVolume != null)
     369        {
     370          tw.tablePrintData("Name", "Box", "Position", "Quantity (µg)", "Concentration (ng/µl)");
     371          data = new Object[5];
     372        }
     373        else
     374        {
     375          tw.tablePrintData("Name", "Box", "Position", "Quantity (µl)");
     376          data = new Object[4];
     377        }
    350378       
    351379        Iterator<Extract> it = memberQuery.iterate(dc);
     
    363391          data[2] = well.getCoordinate();
    364392          data[3] = Values.formatNumber(aliquot.getRemainingQuantity(), 1);
    365           data[4] = Values.formatNumber((Float)Annotationtype.DILUTION_CONC.getAnnotationValue(dc, aliquot), 1);
     393          if (data.length > 4)
     394          {
     395            data[4] = Values.formatNumber((Float)Annotationtype.DILUTION_CONC.getAnnotationValue(dc, aliquot), 1);
     396          }
    366397          tw.tablePrintData(data);
    367398        }
     
    427458        String comments = (String)jsonReq.get("comments");
    428459       
    429         float targetAmount = ((Number)jsonReq.get("targetAmount")).floatValue();
    430         float targetVolume = ((Number)jsonReq.get("targetVolume")).floatValue();
     460        Number targetAmount = (Number)jsonReq.get("targetAmount");
     461        Number targetVolume = (Number)jsonReq.get("targetVolume");
     462        ItemSubtype outtakeType = Subtype.getByCName((String)jsonReq.get("outtakeType")).get(dc);
    431463       
    432464        ItemList aliquotList = ItemList.getNew(dc, sourceList.getMemberType());
     
    436468        dc.saveItem(aliquotList);
    437469       
     470        AnyToAny sourceLink = AnyToAny.getNew(dc, aliquotList, sourceList, "Source list", false);
     471        sourceLink.setDescription("This is the source list that contain parent items for the aliquots in this list");
     472        dc.saveItem(sourceLink);
     473       
    438474        Annotationtype.OUTTAKE_TARGET_AMOUNT.setAnnotationValue(dc, aliquotList, targetAmount);
    439475        Annotationtype.OUTTAKE_TARGET_VOLUME.setAnnotationValue(dc, aliquotList, targetVolume);
     476        Annotationtype.OUTTAKE_PARENT_TYPE.setAnnotationValue(dc, aliquotList, outtakeType.getName());
    440477       
    441478        // Query for finding existing child aliquots
     
    585622          if (conc == null) conc = (Float)Annotationtype.QUBIT_CONC.getAnnotationValue(dc, parent);
    586623         
    587           if (remain != null && conc != null)
    588           {
    589             boolean isException = except.contains(aliquot.getId());
    590             if (isException) numExceptions++;
    591            
    592             if (sampleConsumed != isException)
     624          if (targetAmount != null && targetVolume != null)
     625          {
     626            if (remain != null && conc != null)
    593627            {
    594               Dilution d = new Dilution(targetAmount, targetVolume, conc, remain);
    595               creationEvent.getEventSource(parent).setUsedQuantity(d.amount);
    596               aliquot.setOriginalQuantity(d.amount);
    597               Annotationtype.DILUTION_CONC.setAnnotationValue(dc, aliquot, d.getDilutedConc());
    598               //jsonMessages.add(aliquot.getId() + ":" + aliquot.getName() + ": " + ndConc + "--" + d.getDilutedConc() + ":"+isException);
     628              boolean isException = except.contains(aliquot.getId());
     629              if (isException) numExceptions++;
     630             
     631              if (sampleConsumed != isException)
     632              {
     633                Dilution d = new Dilution(targetAmount, targetVolume, conc, remain);
     634                creationEvent.getEventSource(parent).setUsedQuantity(d.amount);
     635                aliquot.setOriginalQuantity(d.amount);
     636                Annotationtype.DILUTION_CONC.setAnnotationValue(dc, aliquot, d.getDilutedConc());
     637                //jsonMessages.add(aliquot.getId() + ":" + aliquot.getName() + ": " + ndConc + "--" + d.getDilutedConc() + ":"+isException);
     638              }
     639              else
     640              {
     641                // jsonMessages.add(aliquot.getId() + ":" + aliquot.getName() + " not consumed: " + isException);
     642              }
    599643            }
    600             else
     644          }
     645          else if (targetVolume != null)
     646          {
     647            if (remain != null)
    601648            {
    602               // jsonMessages.add(aliquot.getId() + ":" + aliquot.getName() + " not consumed: " + isException);
     649              boolean isException = except.contains(aliquot.getId());
     650              if (isException) numExceptions++;
     651              if (sampleConsumed != isException)
     652              {
     653                Dilution d = new Dilution(targetVolume, remain);
     654                creationEvent.getEventSource(parent).setUsedQuantity(d.volume);
     655                aliquot.setOriginalQuantity(d.volume);
     656                //jsonMessages.add(aliquot.getId() + ":" + aliquot.getName() + ": " + d.volume + ":"+isException);
     657              }
     658              else
     659              {
     660                //jsonMessages.add(aliquot.getId() + ":" + aliquot.getName() + " not consumed: " + isException);
     661              }
    603662            }
    604663          }
     
    769828   
    770829    /**
     830      Use a fixed target volume. If remaining quantity is lower
     831      we can't take more of course.
     832      @since 4.31.3
     833    */
     834    Dilution(float targetVolume, float remainingQuantity)
     835    {
     836      this.remainingQuantity = remainingQuantity;
     837      this.conc = Float.NaN;
     838     
     839      this.volume = Math.min(targetVolume, remainingQuantity);
     840      this.water = Float.NaN;
     841      this.amount = Float.NaN;
     842    }
     843   
     844    /**
    771845      Create a new dilution calculation.
    772846      @param targetAmount The target amount (µg)
Note: See TracChangeset for help on using the changeset viewer.