Changeset 2226


Ignore:
Timestamp:
Feb 13, 2014, 1:44:46 PM (9 years ago)
Author:
Nicklas Nordborg
Message:

References #546: Confirm sequencing as completed

First version of 'Confirm sequencing completed' wizard. It's really simple. After selecting if a sequencing failed or succeeded there is a field for comments and a possibility to mark individual lanes as failed (if the sequencing was otherwise successful).

Location:
extensions/net.sf.basedb.reggie/trunk
Files:
2 added
5 edited

Legend:

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

    r2215 r2226  
    224224      url = 'SequencingRun.servlet?ID=<%=ID%>&cmd=CountActiveSequencingRuns';
    225225    }
     226    else if (what == 'unconfirmed-sequencing-runs')
     227    {
     228      url = 'SequencingRun.servlet?ID=<%=ID%>&cmd=CountUncomfirmedSequencingRuns';
     229    }
    226230   
    227231    if (url)
     
    390394      var count = error ? -1 : response.count;
    391395      setCount('count.sequencing-run', count, 'sequencing runs', msg);
     396      startCounting('unconfirmed-sequencing-runs');
     397    }
     398    else if (currentCount == 'unconfirmed-sequencing-runs')
     399    {
     400      var msg = error || 'Number of ended but not confirmed sequencing runs';
     401      var count = error ? -1 : response.count;
     402      setCount('count.unconfirmed-sequencing-run', count, 'sequencing runs', msg);
    392403    }
    393404   
     
    687698          <dd>
    688699            <ul>
    689             <li><span class="require-permission" data-role="SecondaryAnalysis" data-link="analysis/sequencing_end.jsp?ID=<%=ID%>"
    690               >Confirm sequencing completed</span>
     700            <li><span class="require-permission" data-role="SecondaryAnalysis" data-link="analysis/sequencing_confirm.jsp?ID=<%=ID%>"
     701              >Confirm sequencing completed</span> <span class="counter" id="count.unconfirmed-sequencing-run" title="Counting..."><img src="images/loading-small.gif"></span>
     702           
    691703            <li><span class="require-permission" data-role="SecondaryAnalysis" data-link="analysis/demux_start.jsp?ID=<%=ID%>"
    692704              >Start demux and merge</span>
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Annotationtype.java

    r2225 r2226  
    674674    new Annotationtype("SequencingCycles", Type.STRING, Item.PHYSICALBIOASSAY, Item.DERIVEDBIOASSAY);
    675675
    676  
     676  /**
     677    The "FailedLanes" annotation, used for physical bioassays (FlowCell).
     678    It is a multi-valued annotation type representing the index numbers
     679    of lanes that failed during sequencing of a flow cell. The index numbers
     680    go from 1 to the size of the flow cell (eg. 1-8).
     681    @since 2.15
     682  */
     683  public static final Annotationtype FAILED_LANES =
     684    new Annotationtype("FailedLanes", Type.INT, Item.PHYSICALBIOASSAY);
     685
    677686  /**
    678687    The "HiSeqPosition" annotation, used for derived bioassays (SequencingRun).
     
    953962    }
    954963  }
     964 
     965  /**
     966    Set a multi-valued annotation on an item. If the values list is null or
     967    emtpy the annotation will be removed.
     968    @since 2.15
     969  */
     970  public void setAnnotationValues(DbControl dc, Annotatable item, List<?> values)
     971  {
     972    AnnotationType at = load(dc);
     973    if (values == null || values.isEmpty())
     974    {
     975      if (item.isAnnotated() && item.getAnnotationSet().hasAnnotation(at))
     976      {
     977        item.getAnnotationSet().removeAnnotation(at);
     978      }
     979    }
     980    else
     981    {
     982      item.getAnnotationSet().getAnnotation(at).setValues(values);
     983    }
     984  }
    955985
    956986  /**
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/FlowCellSampleSheetExporter.java

    r2187 r2226  
    197197        storeValue(job, request, ri.getParameter("Width"));
    198198        storeValue(job, request, ri.getParameter("Concentration"));
     199        storeValue(job, request, ri.getParameter("FailedLanes"));
    199200
    200201        if (request.getParameterValue(SAVE_AS) == null)
     
    301302      parameters);
    302303  }
     304  @SuppressWarnings("unchecked")
    303305  private RequestInformation getConfigureJobParameters(Boolean requireFile)
    304306  {
     
    346348        parameters.add(getWidthParameter());
    347349        parameters.add(getConcentrationParameter());
     350       
     351        if (currentBioAssay != null)
     352        {
     353          List<Integer> failedLanes = new ArrayList<Integer>((List<Integer>)Annotationtype.FAILED_LANES.getAnnotationValues(dc, currentBioAssay));
     354          Collections.sort(failedLanes);
     355          if (failedLanes.size() > 0)
     356          {
     357            parameters.add(getFailedLanesParameter(failedLanes));
     358          }
     359        }
    348360       
    349361      }
     
    417429    info[18] = flowCell.getName();  // Description
    418430   
     431    boolean includeFailedLanes = getParameter(parameters, "FailedLanes", "Exclude").equals("Include");
     432    List<Integer> failedLanes = (List<Integer>)(includeFailedLanes ? Collections.emptyList() : Annotationtype.FAILED_LANES.getAnnotationValues(dc, flowCell));
     433   
    419434    //Query to get all non-empty wells on the plate
    420435    SpecialQuery<BioMaterialEventSource> query = flowCell.getCreationEvent().getEventSources();
     
    425440      Extract poolA = (Extract)src.getBioMaterial(); // Aliquot from pool for current lane
    426441      int laneNo = src.getPosition();
     442     
     443      if (failedLanes.contains(laneNo))
     444      {
     445        if (progress != null)
     446        {
     447          progress.display(10 + 80 * laneNo/numLanes, "Skipping failed lane " + laneNo + " of " + flowCell.getSize());
     448        }
     449        continue; // Do not export failed lanes;
     450      }
    427451     
    428452      if (progress != null)
     
    608632  }
    609633 
     634  private PluginParameter<String> getFailedLanesParameter(List<Integer> failedLanes)
     635  {
     636    Integer lastLane = failedLanes.get(failedLanes.size()-1);
     637    String lanes;
     638    if (failedLanes.size() == 1)
     639    {
     640      lanes = "Lane <b>" + lastLane.toString() + "</b>";
     641    }
     642    else
     643    {
     644      lanes = "Lanes <b>" + Values.getString(failedLanes.subList(0, failedLanes.size()-1), ", ", true) + " and " + lastLane+"</b>";
     645    }
     646   
     647    PluginParameter<String> parameter = new PluginParameter<String>("FailedLanes", "Failed lanes",
     648        lanes + " failed during sequencing. " +
     649        "By default, the exporter <i>Exclude</i> sample information for those lanes.\n" +
     650        "Select <i>Include</i> to include sample information for all lanes.",
     651        new StringParameterType(255, "Exclude", false, 1, 0, 0, Arrays.asList("Exclude", "Include"))
     652        );
     653    return parameter;
     654  }
     655 
    610656  private String sequencingCycles2ReadString(String sequencingCycles)
    611657  {
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/InstallServlet.java

    r2225 r2226  
    331331        jsonChecks.add(checkAnnotationType(dc, Annotationtype.READ_STRING, 1, null, effectivePermissionsUse, createIfMissing));
    332332        jsonChecks.add(checkAnnotationType(dc, Annotationtype.SEQUENCING_CYCLES, 1, null, effectivePermissionsUse, createIfMissing));
     333        jsonChecks.add(checkAnnotationType(dc, Annotationtype.FAILED_LANES, 0, null, effectivePermissionsUse, createIfMissing));
    333334
    334335        jsonChecks.add(checkAnnotationType(dc, Annotationtype.SEQUENCING_START, 1, null, effectivePermissionsUse, createIfMissing));
     
    427428        jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.FLOW_CELL, createIfMissing,
    428429            Annotationtype.FLOWCELL_ID, Annotationtype.CLUSTER_START, Annotationtype.CLUSTER_OPERATOR,
    429             Annotationtype.SEQUENCING_CYCLES, Annotationtype.PLATE_PROCESS_RESULT, Annotationtype.SEQUENCING_RESULT));
     430
     431            Annotationtype.SEQUENCING_CYCLES, Annotationtype.FAILED_LANES,
     432            Annotationtype.PLATE_PROCESS_RESULT, Annotationtype.SEQUENCING_RESULT));
    430433       
    431434        jsonChecks.add(checkAnnotationTypeCategory(dc, Subtype.SEQUENCING_RUN, createIfMissing,
  • extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/SequencingRunServlet.java

    r2225 r2226  
    33import java.io.IOException;
    44import java.util.Date;
     5import java.util.HashSet;
    56import java.util.List;
     7import java.util.Set;
    68
    79import javax.servlet.ServletException;
     
    1517
    1618import net.sf.basedb.core.Application;
     19import net.sf.basedb.core.BioMaterialList;
    1720import net.sf.basedb.core.DbControl;
    1821import net.sf.basedb.core.DerivedBioAssay;
     22import net.sf.basedb.core.Extract;
    1923import net.sf.basedb.core.Hardware;
    2024import net.sf.basedb.core.ItemQuery;
     
    2731import net.sf.basedb.reggie.Reggie;
    2832import net.sf.basedb.reggie.dao.Annotationtype;
     33import net.sf.basedb.reggie.dao.BiomaterialList;
    2934import net.sf.basedb.reggie.dao.FlowCell;
     35import net.sf.basedb.reggie.dao.PooledLibrary;
    3036import net.sf.basedb.reggie.dao.ReggieRole;
    3137import net.sf.basedb.reggie.dao.SequencingRun;
     
    102108          fc.loadAnnotations(dc, "FlowCellID", Annotationtype.FLOWCELL_ID, null);
    103109          fc.setAnnotation("comments", fc.getItem().getDescription());
     110         
     111          run.setAnnotation("flowCell", fc.asJSONObject());
     112          jsonRuns.add(run.asJSONObject());
     113        }
     114       
     115        json.put("sequencingRuns", jsonRuns);
     116      }
     117      else if ("CountUncomfirmedSequencingRuns".equals(cmd))
     118      {
     119        dc = sc.newDbControl();
     120        ItemQuery<DerivedBioAssay> query = DerivedBioAssay.getQuery();
     121        query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     122        Subtype.SEQUENCING_RUN.addFilter(dc, query);
     123        // Must have a SEQUENCING_END annotation
     124        query.join(Annotations.leftJoin(null, Annotationtype.SEQUENCING_END.load(dc), "sse"));
     125        query.restrict(Restrictions.neq(Hql.alias("sse"), null));
     126        // Must NOT have a SEQUENCING_RESULT annotation
     127        query.join(Annotations.leftJoin(null, Annotationtype.SEQUENCING_RESULT.load(dc), "ssr"));
     128        query.restrict(Restrictions.eq(Hql.alias("ssr"), null));
     129        long count = query.count(dc);
     130        json.put("count", count);
     131      }
     132      else if ("GetUnconfirmedSequencingRuns".equals(cmd))
     133      {
     134        dc = sc.newDbControl();
     135        ItemQuery<DerivedBioAssay> query = DerivedBioAssay.getQuery();
     136        query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     137        Subtype.SEQUENCING_RUN.addFilter(dc, query);
     138        // Must have a SEQUENCING_END annotation
     139        query.join(Annotations.leftJoin(null, Annotationtype.SEQUENCING_END.load(dc), "sse"));
     140        query.restrict(Restrictions.neq(Hql.alias("sse"), null));
     141        // Must NOT have a SEQUENCING_RESULT annotation
     142        query.join(Annotations.leftJoin(null, Annotationtype.SEQUENCING_RESULT.load(dc), "ssr"));
     143        query.restrict(Restrictions.eq(Hql.alias("ssr"), null));
     144       
     145        JSONArray jsonRuns = new JSONArray();
     146        List<SequencingRun> runs = SequencingRun.toList(query.list(dc));
     147        for (SequencingRun run : runs)
     148        {
     149          run.loadAnnotations(dc, "SequencingStart", Annotationtype.SEQUENCING_START, Reggie.CONVERTER_DATE_TO_STRING);
     150          run.loadAnnotations(dc, "SequencingTurnAround", Annotationtype.SEQUENCING_TURN_AROUND, Reggie.CONVERTER_DATETIME_TO_STRING);
     151          run.loadAnnotations(dc, "SequencingEnd", Annotationtype.SEQUENCING_END, Reggie.CONVERTER_DATETIME_TO_STRING);
     152          run.loadAnnotations(dc, "HiSeqPosition", Annotationtype.HISEQ_POSITION, null);
     153          run.setAnnotation("comments", run.getDerivedBioAssay().getDescription());
     154         
     155          FlowCell fc = FlowCell.getBySequencingRun(dc, run);
     156          PhysicalBioAssay pba = fc.getItem();
     157          fc.loadAnnotations(dc, "FlowCellID", Annotationtype.FLOWCELL_ID, null);
     158          fc.setAnnotation("numLanes", pba.getSize());
     159          fc.setAnnotation("comments", pba.getDescription());
    104160         
    105161          run.setAnnotation("flowCell", fc.asJSONObject());
     
    243299        dc.commit();
    244300      }
     301      else if ("ConfirmSequencingEnded".equals(cmd))
     302      {
     303        dc = sc.newDbControl();
     304
     305        ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.SECONDARY_ANALYSIS, ReggieRole.ADMINISTRATOR);
     306
     307        JSONObject jsonReq = (JSONObject)new JSONParser().parse(req.getReader());
     308        JSONObject jsonSeq = (JSONObject)jsonReq.get("sequencingRun");
     309        JSONObject jsonFlowCell = (JSONObject)jsonSeq.get("flowCell");
     310        boolean failed = Boolean.TRUE.equals(jsonReq.get("failed"));
     311
     312        Number seqId = (Number)jsonSeq.get("id");
     313        DerivedBioAssay seqRun = DerivedBioAssay.getById(dc, seqId.intValue());
     314        seqRun.setDescription((String)jsonSeq.get("comments"));
     315       
     316        BioMaterialList flaggedPools = null;
     317        Set<Extract> pools = null;
     318        int numFlagged = 0;
     319        if (failed)
     320        {
     321          flaggedPools = BiomaterialList.FLAGGED_POOL.load(dc);
     322          pools = new HashSet<Extract>();
     323        }
     324       
     325        Number fcId = (Number)jsonFlowCell.get("id");
     326        PhysicalBioAssay flowCell = PhysicalBioAssay.getById(dc, fcId.intValue());
     327         
     328        if (failed)
     329        {
     330          // Load pool aliquots and pools for all lanes
     331          ItemQuery<Extract> aliquotQuery = flowCell.getExtracts(0);
     332          aliquotQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
     333          List<Extract> aliquots = aliquotQuery.list(dc);
     334
     335          // If sequencing failed, we flag the pools and add them to the 'Flagged pools' list.
     336          // Typically, most pools have enough material to try clustering again but that
     337          // the responsibility of another wizard
     338          for (Extract poolA : aliquots)
     339          {
     340            Extract pool = (Extract)poolA.getParent();
     341            if (!pools.contains(pool))
     342            {
     343              pools.add(pool);
     344              flaggedPools.add(pool);
     345              numFlagged++;
     346              Annotationtype.FLAG.setAnnotationValue(dc, pool, PooledLibrary.FLAG_SEQUENCING_FAILED);
     347              Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, pool, "Disable");
     348            }
     349          }
     350        }
     351        else
     352        {
     353          JSONArray jsonFailedLanes = (JSONArray)jsonFlowCell.get("failedLanes");
     354          Annotationtype.FAILED_LANES.setAnnotationValues(dc, flowCell, jsonFailedLanes);
     355          if (jsonFailedLanes.size() > 0)
     356          {
     357            Object lastLane = jsonFailedLanes.get(jsonFailedLanes.size()-1);
     358            String lanes;
     359            if (jsonFailedLanes.size() == 1)
     360            {
     361              lanes = "Lane " + lastLane.toString();
     362            }
     363            else
     364            {
     365              lanes = "Lanes " + Values.getString(jsonFailedLanes.subList(0, jsonFailedLanes.size()-1), ", ", true) + " and " + lastLane;
     366            }
     367
     368            jsonMessages.add(lanes + " registered as failed.");
     369          }
     370        }
     371       
     372        if (failed)
     373        {
     374          Annotationtype.SEQUENCING_RESULT.setAnnotationValue(dc, seqRun, SequencingRun.SEQUENCING_FAILED);
     375          jsonMessages.add(seqRun.getName() + " confirmed as failed.");
     376        }
     377        else
     378        {
     379          Annotationtype.SEQUENCING_RESULT.setAnnotationValue(dc, seqRun, SequencingRun.SEQUENCING_SUCCESSFUL);
     380          jsonMessages.add(seqRun.getName() + " confirmed as successful.");
     381        }
     382       
     383        if (numFlagged > 0)
     384        {
     385          jsonMessages.add("Added " + numFlagged + " pools to '" + flaggedPools.getName() + "' list.");
     386        }
     387
     388        dc.commit();
     389      }
    245390
    246391      json.put("messages", jsonMessages);
Note: See TracChangeset for help on using the changeset viewer.