extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/Rna.java

Code
Comments
Other
Rev Date Author Line
1543 28 Feb 12 nicklas 1 package net.sf.basedb.reggie.dao;
1543 28 Feb 12 nicklas 2
1543 28 Feb 12 nicklas 3 import java.util.ArrayList;
3659 09 Dec 15 nicklas 4 import java.util.Arrays;
1865 19 Feb 13 nicklas 5 import java.util.Collection;
3764 22 Feb 16 nicklas 6 import java.util.Collections;
3651 07 Dec 15 nicklas 7 import java.util.Date;
3659 09 Dec 15 nicklas 8 import java.util.Iterator;
1543 28 Feb 12 nicklas 9 import java.util.List;
1543 28 Feb 12 nicklas 10
1573 19 Mar 12 nicklas 11 import org.json.simple.JSONObject;
1573 19 Mar 12 nicklas 12
1543 28 Feb 12 nicklas 13 import net.sf.basedb.core.DbControl;
1543 28 Feb 12 nicklas 14 import net.sf.basedb.core.Extract;
1543 28 Feb 12 nicklas 15 import net.sf.basedb.core.Include;
6341 29 Jun 21 nicklas 16 import net.sf.basedb.core.InvalidDataException;
3659 09 Dec 15 nicklas 17 import net.sf.basedb.core.ItemList;
1543 28 Feb 12 nicklas 18 import net.sf.basedb.core.ItemQuery;
3651 07 Dec 15 nicklas 19 import net.sf.basedb.core.ItemResultIterator;
3651 07 Dec 15 nicklas 20 import net.sf.basedb.core.Protocol;
1832 08 Feb 13 nicklas 21 import net.sf.basedb.core.Type;
3651 07 Dec 15 nicklas 22 import net.sf.basedb.core.query.Annotations;
1543 28 Feb 12 nicklas 23 import net.sf.basedb.core.query.Expressions;
1543 28 Feb 12 nicklas 24 import net.sf.basedb.core.query.Hql;
1543 28 Feb 12 nicklas 25 import net.sf.basedb.core.query.Orders;
1543 28 Feb 12 nicklas 26 import net.sf.basedb.core.query.Restrictions;
3166 05 Mar 15 nicklas 27 import net.sf.basedb.core.snapshot.SnapshotManager;
1826 07 Feb 13 nicklas 28 import net.sf.basedb.reggie.JsonUtil;
1560 14 Mar 12 nicklas 29 import net.sf.basedb.reggie.Reggie;
1543 28 Feb 12 nicklas 30
1543 28 Feb 12 nicklas 31 /**
1543 28 Feb 12 nicklas 32   Class for loading information that is related to RNA extracts.
1543 28 Feb 12 nicklas 33   
1543 28 Feb 12 nicklas 34   @author nicklas
1543 28 Feb 12 nicklas 35   @since 2.4
1543 28 Feb 12 nicklas 36 */
1543 28 Feb 12 nicklas 37 public class Rna 
1543 28 Feb 12 nicklas 38   extends ReggieItem<Extract>
1543 28 Feb 12 nicklas 39 {
1543 28 Feb 12 nicklas 40
1889 27 Feb 13 nicklas 41   /**
2902 06 Nov 14 nicklas 42     Value for the AutoProcessing annotation to indicate that the 
2902 06 Nov 14 nicklas 43     RNA item should be pre-normalized before put into freezer.
2902 06 Nov 14 nicklas 44     @since 2.18
2902 06 Nov 14 nicklas 45    */
2902 06 Nov 14 nicklas 46   public static final String AUTO_PROCESSING_PRE_NORMALIZE = "PreNormalizeRNA";
2902 06 Nov 14 nicklas 47   
2902 06 Nov 14 nicklas 48   /**
1889 27 Feb 13 nicklas 49     Flag value for the {@link Annotationtype#FLAG} annotation when a RNA doesn't have
1889 27 Feb 13 nicklas 50     enough remaining quantity to be auto-selected for library preparation. Additional
1889 27 Feb 13 nicklas 51     processing of backup lysate or speciman may be required.
1889 27 Feb 13 nicklas 52     @since 2.12
1889 27 Feb 13 nicklas 53   */
1889 27 Feb 13 nicklas 54   public static final String FLAG_NOT_ENOUGH_REMAINING_QUANTITY = "NotEnoughRemainingQuantity";
1940 18 Apr 13 nicklas 55
1940 18 Apr 13 nicklas 56   /**
1940 18 Apr 13 nicklas 57     Flag value for the {@link Annotationtype#FLAG} annotation when a RNA doesn't have
1940 18 Apr 13 nicklas 58     a high enough quality score (RQS or RIN) to be auto-selected for library preparation. 
1940 18 Apr 13 nicklas 59     Additional processing of backup lysate or speciman may be required.
1940 18 Apr 13 nicklas 60     @since 2.12
1940 18 Apr 13 nicklas 61   */
1940 18 Apr 13 nicklas 62   public static final String FLAG_LOW_QUALITY_SCORE = "LowQualityScore";
1946 19 Apr 13 nicklas 63
1946 19 Apr 13 nicklas 64   /**
1946 19 Apr 13 nicklas 65     Flag value for the {@link Annotationtype#FLAG} annotation when a RNA
1946 19 Apr 13 nicklas 66     has been manually flagged for some other reason. The desription of
1946 19 Apr 13 nicklas 67     the RNA item should contain more information.
1946 19 Apr 13 nicklas 68     @since 2.12
1946 19 Apr 13 nicklas 69   */
1946 19 Apr 13 nicklas 70   public static final String FLAG_MANUAL = "ManualFlag";
1543 28 Feb 12 nicklas 71   
1543 28 Feb 12 nicklas 72   /**
1889 27 Feb 13 nicklas 73     Flag value for the {@link Annotationtype#FLAG} annotation when the mRNA
1889 27 Feb 13 nicklas 74     processing failed. RNA on the failed plate need to be re-processed on a 
1889 27 Feb 13 nicklas 75     new plate.
1889 27 Feb 13 nicklas 76     @since 2.12
1889 27 Feb 13 nicklas 77   */
1890 01 Mar 13 nicklas 78   public static final String FLAG_MRNA_PLATE_FAILED = "mRNAPlateFailed";
1890 01 Mar 13 nicklas 79
1890 01 Mar 13 nicklas 80   /**
1890 01 Mar 13 nicklas 81     Flag value for the {@link Annotationtype#FLAG} annotation when the cDNA
1890 01 Mar 13 nicklas 82     processing failed. RNA on the failed plate need to be re-processed on a 
1890 01 Mar 13 nicklas 83     new plate.
1890 01 Mar 13 nicklas 84     @since 2.12
1890 01 Mar 13 nicklas 85   */
1890 01 Mar 13 nicklas 86   public static final String FLAG_CDNA_PLATE_FAILED = "cDNAPlateFailed";
1890 01 Mar 13 nicklas 87
1890 01 Mar 13 nicklas 88   /**
1908 19 Mar 13 nicklas 89     Flag value for the {@link Annotationtype#FLAG} annotation when the Library
1987 23 May 13 nicklas 90     processing failed (for an entire plate). RNA on the failed plate need to be 
1987 23 May 13 nicklas 91     re-processed on a new plate.
1908 19 Mar 13 nicklas 92     @since 2.12
1908 19 Mar 13 nicklas 93   */
1908 19 Mar 13 nicklas 94   public static final String FLAG_LIB_PLATE_FAILED = "LibPlateFailed";
1908 19 Mar 13 nicklas 95
1987 23 May 13 nicklas 96   /**
1987 23 May 13 nicklas 97     Flag value for the {@link Annotationtype#FLAG} annotation when a Library
1987 23 May 13 nicklas 98     item has been excluded from a pool. The parent RNA need to be
1987 23 May 13 nicklas 99     re-processed on a new plate.
1987 23 May 13 nicklas 100     @since 2.12
1987 23 May 13 nicklas 101   */
1987 23 May 13 nicklas 102   public static final String FLAG_EXCLUDED_FROM_POOL = "ExcludedFromPool";
2020 13 Sep 13 nicklas 103
2367 17 Apr 14 nicklas 104   /**
2367 17 Apr 14 nicklas 105     Flag value for the {@link Annotationtype#FLAG} annotation when
2367 17 Apr 14 nicklas 106     a library has been sequenced but the demux step failed. Eg.
2367 17 Apr 14 nicklas 107     not enough sequences for the library.
2367 17 Apr 14 nicklas 108     @since 2.16
2367 17 Apr 14 nicklas 109   */
2367 17 Apr 14 nicklas 110   public static final String FLAG_DEMUX_FAILED = "DemuxFailed";
2020 13 Sep 13 nicklas 111
1908 19 Mar 13 nicklas 112   /**
2404 06 May 14 nicklas 113     Flag value for the {@link Annotationtype#FLAG} annotation when
6187 26 Mar 21 nicklas 114     a library has been sequenced externally but the FASTQ import step
6187 26 Mar 21 nicklas 115     failed.
6187 26 Mar 21 nicklas 116     @since 4.32
6187 26 Mar 21 nicklas 117   */
6187 26 Mar 21 nicklas 118   public static final String FLAG_FASTQ_IMPORT_FAILED = "FASTQImportFailed";
6187 26 Mar 21 nicklas 119
6187 26 Mar 21 nicklas 120   /**
6187 26 Mar 21 nicklas 121     Flag value for the {@link Annotationtype#FLAG} annotation when
2404 06 May 14 nicklas 122     a library has been sequenced but the alignment step failed. Eg.
2404 06 May 14 nicklas 123     not enough sequences that matches the target genome.
2404 06 May 14 nicklas 124     @since 2.16
2404 06 May 14 nicklas 125   */
2404 06 May 14 nicklas 126   public static final String FLAG_ALIGN_FAILED = "AlignFailed";
2404 06 May 14 nicklas 127
2404 06 May 14 nicklas 128   /**
2826 16 Oct 14 nicklas 129     Flag value for the {@link Annotationtype#FLAG} annotation when
4658 26 Jan 18 nicklas 130     a library has been sequenced and the genotype QC has indicated
4658 26 Jan 18 nicklas 131     a high HET percentage. This may indiate contamination.
4658 26 Jan 18 nicklas 132     @since 4.15
4658 26 Jan 18 nicklas 133   */
4658 26 Jan 18 nicklas 134   public static final String FLAG_HIGH_HET = "HighHET";
4658 26 Jan 18 nicklas 135   
4658 26 Jan 18 nicklas 136   /**
4658 26 Jan 18 nicklas 137     Flag value for the {@link Annotationtype#FLAG} annotation when
2826 16 Oct 14 nicklas 138     a library has been sequenced but the cufflinks step failed.
2826 16 Oct 14 nicklas 139     @since 2.17
2826 16 Oct 14 nicklas 140   */
2826 16 Oct 14 nicklas 141   public static final String FLAG_CUFFLINKS_FAILED = "CufflinksFailed";
2826 16 Oct 14 nicklas 142
2826 16 Oct 14 nicklas 143   /**
4670 05 Feb 18 nicklas 144     Flag value for the {@link Annotationtype#FLAG} annotation when
4670 05 Feb 18 nicklas 145     a library has been sequenced but the StringTie step failed.
4670 05 Feb 18 nicklas 146     @since 4.15
4670 05 Feb 18 nicklas 147   */
4670 05 Feb 18 nicklas 148   public static final String FLAG_STRINGTIE_FAILED = "StringTieFailed";
4670 05 Feb 18 nicklas 149
4670 05 Feb 18 nicklas 150   /**
1938 17 Apr 13 nicklas 151     The name of the RNA item in BASE that represents Generic Stratagene.
1938 17 Apr 13 nicklas 152     Tracked Stratagene should use the pattern 'Stratagene.rNNN' where
1938 17 Apr 13 nicklas 153     'NNN' is a number.
1890 01 Mar 13 nicklas 154     @since 2.12
1890 01 Mar 13 nicklas 155   */
1890 01 Mar 13 nicklas 156   public static final String STRATAGENE = "Stratagene.r";
1890 01 Mar 13 nicklas 157
1890 01 Mar 13 nicklas 158   /**
1890 01 Mar 13 nicklas 159     The name of the RNA item in BASE that represents an external extract.
1890 01 Mar 13 nicklas 160     @since 2.12
1890 01 Mar 13 nicklas 161   */
1890 01 Mar 13 nicklas 162   public static final String EXTERNAL = "External.r";
1889 27 Feb 13 nicklas 163   
1889 27 Feb 13 nicklas 164   /**
1938 17 Apr 13 nicklas 165     Checks if an item with the given name is a Stratagene RNA or a 
1938 17 Apr 13 nicklas 166     derivative from a Stratagene RNA.
1938 17 Apr 13 nicklas 167     @since 2.12
1938 17 Apr 13 nicklas 168   */
1938 17 Apr 13 nicklas 169   public static boolean isStratagene(String name)
1938 17 Apr 13 nicklas 170   {
1938 17 Apr 13 nicklas 171     return name.startsWith(STRATAGENE);
1938 17 Apr 13 nicklas 172   }
1938 17 Apr 13 nicklas 173   
1938 17 Apr 13 nicklas 174   /**
1543 28 Feb 12 nicklas 175     Find RNA extracts that have not yet been quality controlled. The query will look for
1543 28 Feb 12 nicklas 176     extract with the {@link Subtype#RNA} subtype that has no child extract with
1543 28 Feb 12 nicklas 177     the {@link Subtype#RNAQC} subtype.
1543 28 Feb 12 nicklas 178   */
1543 28 Feb 12 nicklas 179   public static List<Rna> findRnaWithoutQc(DbControl dc)
1543 28 Feb 12 nicklas 180   {
1543 28 Feb 12 nicklas 181     // Create a query that load all RNA extracts that has at least one RNAQC child extract
1543 28 Feb 12 nicklas 182     ItemQuery<Extract> subquery = Extract.getQuery();
1560 14 Mar 12 nicklas 183     subquery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1543 28 Feb 12 nicklas 184     // Filter on RNA subtype
1543 28 Feb 12 nicklas 185     Subtype.RNA.addFilter(dc, subquery);
1543 28 Feb 12 nicklas 186     
1543 28 Feb 12 nicklas 187     // Join child items and filter on RNAQC subtype
1543 28 Feb 12 nicklas 188     subquery.join(Hql.innerJoin("childCreationEvents", "cce"));
1543 28 Feb 12 nicklas 189     subquery.join(Hql.innerJoin("cce", "event", "evt", null, false));
1543 28 Feb 12 nicklas 190     subquery.join(Hql.innerJoin("evt", "bioMaterial", "bm", null, false));
1543 28 Feb 12 nicklas 191     Subtype.RNAQC.addFilter(dc, subquery, "bm");
1543 28 Feb 12 nicklas 192     
1543 28 Feb 12 nicklas 193     ItemQuery<Extract> query = Extract.getQuery();
1560 14 Mar 12 nicklas 194     query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1543 28 Feb 12 nicklas 195     // Filter on RNA subtype
1543 28 Feb 12 nicklas 196     Subtype.RNA.addFilter(dc, query);
1543 28 Feb 12 nicklas 197     // Filter on id not equal to any that has a RNAQC child
1543 28 Feb 12 nicklas 198     query.restrict(Restrictions.neq(Hql.property("id"), Expressions.all(subquery)));
1938 17 Apr 13 nicklas 199     // Filter on creation date==null and parent != null (eg. to get rid of 'Stratagene')
1865 19 Feb 13 nicklas 200     query.join(Hql.innerJoin("creationEvent", "ce"));
1865 19 Feb 13 nicklas 201     query.restrict(Restrictions.neq(Hql.property("ce", "eventDate"), null));
1938 17 Apr 13 nicklas 202     query.restrict(Restrictions.neq(Hql.property("parent"), null));
1543 28 Feb 12 nicklas 203     
1560 14 Mar 12 nicklas 204     query.order(Orders.asc(Hql.property("id")));
1543 28 Feb 12 nicklas 205     
1865 19 Feb 13 nicklas 206     return toRna(query.list(dc));
1543 28 Feb 12 nicklas 207   }
1543 28 Feb 12 nicklas 208   
1543 28 Feb 12 nicklas 209   /**
1938 17 Apr 13 nicklas 210     Find all Stratagene RNA that is available for selection in the
1938 17 Apr 13 nicklas 211     mRNA wizards. This should include all 'Stratagene.rNNN' where
1938 17 Apr 13 nicklas 212     'NNN' is a number that has a registered location on a bioplate, and
1938 17 Apr 13 nicklas 213     the generic 'Stratagene.r' extract.
1938 17 Apr 13 nicklas 214   */
1938 17 Apr 13 nicklas 215   public static List<Rna> findStratagene(DbControl dc)
1938 17 Apr 13 nicklas 216   {
1938 17 Apr 13 nicklas 217     ItemQuery<Extract> query = Extract.getQuery();
1938 17 Apr 13 nicklas 218     query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1938 17 Apr 13 nicklas 219     // Join bioplate
1938 17 Apr 13 nicklas 220     query.join(Hql.leftJoin(null, "bioWell", "bw", null, true));
1938 17 Apr 13 nicklas 221     query.join(Hql.leftJoin("bw", "bioPlate", "bp", null, true));
1938 17 Apr 13 nicklas 222     
1938 17 Apr 13 nicklas 223     // Filter on RNA subtype
1938 17 Apr 13 nicklas 224     Subtype.RNA.addFilter(dc, query);
1938 17 Apr 13 nicklas 225     
1938 17 Apr 13 nicklas 226     // Filter on name='Stratagene.r' OR name ~ 'Stratagene.rNNN'
1938 17 Apr 13 nicklas 227     query.restrict(
1938 17 Apr 13 nicklas 228       Restrictions.or(
1938 17 Apr 13 nicklas 229         Restrictions.eq(Hql.property("name"), Expressions.string(Rna.STRATAGENE)),
1938 17 Apr 13 nicklas 230         Restrictions.and(
1938 17 Apr 13 nicklas 231           Restrictions.rlike(Hql.property("name"), Expressions.string("^"+ Rna.STRATAGENE + "[0-9]+$")),
1938 17 Apr 13 nicklas 232           Restrictions.neq(Hql.property("bioWell"), null)
1938 17 Apr 13 nicklas 233         )
1938 17 Apr 13 nicklas 234       )
1938 17 Apr 13 nicklas 235     );
1938 17 Apr 13 nicklas 236
1938 17 Apr 13 nicklas 237     // Sort by bioplate position -- those without plate are sorted last by name
1938 17 Apr 13 nicklas 238     query.order(Orders.asc(Hql.expression("coalesce(bp.name, 'zzzz')", null)));
1938 17 Apr 13 nicklas 239     query.order(Orders.asc(Hql.property("bw", "row")));
1938 17 Apr 13 nicklas 240     query.order(Orders.asc(Hql.property("bw", "column")));
1938 17 Apr 13 nicklas 241     query.order(Orders.asc(Hql.property("name")));
1938 17 Apr 13 nicklas 242     
1938 17 Apr 13 nicklas 243     return toRna(query.list(dc));
1938 17 Apr 13 nicklas 244   }
1938 17 Apr 13 nicklas 245   
1938 17 Apr 13 nicklas 246   /**
3651 07 Dec 15 nicklas 247     Find pre-normalized RNA that has not yet been used for library preparation.
3651 07 Dec 15 nicklas 248     
3651 07 Dec 15 nicklas 249     * Creation date must be set (or after RnaFilterOptions.startDate)
3651 07 Dec 15 nicklas 250     * Must be pre-normalized with the given protocol (RnaFilterOptions.normalizationProtocol)
3651 07 Dec 15 nicklas 251     * AutoProcessing must not be set (eg. to Disable)
3651 07 Dec 15 nicklas 252     * No child item of type mRNA or Library must exist
3651 07 Dec 15 nicklas 253     
3764 22 Feb 16 nicklas 254     No items are flagged by this method. This method return two lists. 
3764 22 Feb 16 nicklas 255
3764 22 Feb 16 nicklas 256      * The first contains YellowSpecimen RNA selected for library preparation.
3764 22 Feb 16 nicklas 257      * The second contains other RNA selected for library preparation
3764 22 Feb 16 nicklas 258      
3764 22 Feb 16 nicklas 259      The total number of RNA to process is less than or equal to the
3764 22 Feb 16 nicklas 260      'numToSelect' parameter. The selected RNA is sorted by storage
3764 22 Feb 16 nicklas 261      plate position. To be able to merge the list with YellowSpecimen RNA 
3764 22 Feb 16 nicklas 262      and other RNA and keep the plate order, use the 'startIndexOrder',
3764 22 Feb 16 nicklas 263      {@link Collections#sort(List, java.util.Comparator)} and 
3764 22 Feb 16 nicklas 264      {@link ReggieItem.IndexOrderComparator}.
3651 07 Dec 15 nicklas 265     
3764 22 Feb 16 nicklas 266     @since 4.0, 4.2
3651 07 Dec 15 nicklas 267   */
5415 09 May 19 nicklas 268   @SuppressWarnings({"unchecked", "rawtypes"})
3764 22 Feb 16 nicklas 269   public static List<Rna>[] findPreNormalizedForLibPrep(DbControl dc, SnapshotManager manager, RnaFilterOptions options, int numToSelect, int startIndexOrder)
3651 07 Dec 15 nicklas 270   {
3651 07 Dec 15 nicklas 271     // Start with loading pre-normalized RNA
3651 07 Dec 15 nicklas 272     ItemQuery<Extract> query = Extract.getQuery();
3651 07 Dec 15 nicklas 273     query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3651 07 Dec 15 nicklas 274     Subtype.RNA_NORMALIZED_ALIQUOT.addFilter(dc, query);
3651 07 Dec 15 nicklas 275     // Filters assume that 'creationEvent' is joined as 'ce' alias
3651 07 Dec 15 nicklas 276     query.join(Hql.innerJoin("creationEvent", "ce"));
3651 07 Dec 15 nicklas 277
3651 07 Dec 15 nicklas 278     // Filter for RNA already included on the plate
3651 07 Dec 15 nicklas 279     options.addIgnoreFilter(query);
3651 07 Dec 15 nicklas 280     
3651 07 Dec 15 nicklas 281     // Filter for non-empty creation date or creation date after startDate
3651 07 Dec 15 nicklas 282     options.addCreationDateFilter(query);
3651 07 Dec 15 nicklas 283
3651 07 Dec 15 nicklas 284     // Filter on Normalization protocol used
3651 07 Dec 15 nicklas 285     options.addProtocolFilter(query);
3651 07 Dec 15 nicklas 286     
3651 07 Dec 15 nicklas 287     // AUTO_PROCESSING annotation must be null
3651 07 Dec 15 nicklas 288     query.join(Annotations.leftJoin(null, Annotationtype.AUTO_PROCESSING.load(dc), "ap"));
3651 07 Dec 15 nicklas 289     query.restrict(Restrictions.eq(Hql.alias("ap"), null));
3651 07 Dec 15 nicklas 290     
3651 07 Dec 15 nicklas 291     // Create a subquery that load all prenormalized RNA extracts that has at least one mRNA/Library child extract
3651 07 Dec 15 nicklas 292     ItemQuery<Extract> childQuery = Extract.getQuery();
3651 07 Dec 15 nicklas 293     childQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3651 07 Dec 15 nicklas 294     Subtype.RNA_NORMALIZED_ALIQUOT.addFilter(dc, childQuery);
3651 07 Dec 15 nicklas 295   
3651 07 Dec 15 nicklas 296     // Join child items and filter on mRNA/Library subtype
3651 07 Dec 15 nicklas 297     childQuery.join(Hql.innerJoin("childCreationEvents", "cce"));
3651 07 Dec 15 nicklas 298     childQuery.join(Hql.innerJoin("cce", "event", "evt", null, false));
3651 07 Dec 15 nicklas 299     childQuery.join(Hql.innerJoin("evt", "bioMaterial", "bm", null, false));
3651 07 Dec 15 nicklas 300     childQuery.restrict(Restrictions.or(
3651 07 Dec 15 nicklas 301       Subtype.MRNA.restriction(dc, "bm"),
3651 07 Dec 15 nicklas 302       Subtype.LIBRARY.restriction(dc, "bm")
3651 07 Dec 15 nicklas 303     ));
3651 07 Dec 15 nicklas 304
3651 07 Dec 15 nicklas 305     // No mrna/library children
3651 07 Dec 15 nicklas 306     query.restrict(Restrictions.neq(Hql.property("id"), Expressions.all(childQuery)));
3651 07 Dec 15 nicklas 307     
3651 07 Dec 15 nicklas 308     // Order by RNA plate and location: plate - row - column
3651 07 Dec 15 nicklas 309     query.join(Hql.innerJoin(null, "parent", "rna", true));
3651 07 Dec 15 nicklas 310     query.join(Hql.innerJoin("rna", "bioWell", "w", true));
3651 07 Dec 15 nicklas 311     query.join(Hql.innerJoin("w", "bioPlate", "bp", true));
3651 07 Dec 15 nicklas 312     query.order(Orders.asc(Hql.property("bp", "name")));
3651 07 Dec 15 nicklas 313     query.order(Orders.asc(Hql.property("w", "row")));
3651 07 Dec 15 nicklas 314     query.order(Orders.asc(Hql.property("w", "column")));
3651 07 Dec 15 nicklas 315     
3764 22 Feb 16 nicklas 316     List<Rna> rnaYellow = new ArrayList<Rna>();
3764 22 Feb 16 nicklas 317     List<Rna> rnaNotYellow = new ArrayList<Rna>();
3651 07 Dec 15 nicklas 318     ItemResultIterator<Extract> it = query.iterate(dc);
3651 07 Dec 15 nicklas 319     try
3651 07 Dec 15 nicklas 320     {
3764 22 Feb 16 nicklas 321       int index = startIndexOrder;
3764 22 Feb 16 nicklas 322       while (it.hasNext() && rnaYellow.size() < numToSelect)
3651 07 Dec 15 nicklas 323       {
3651 07 Dec 15 nicklas 324         Extract e = it.next();
3651 07 Dec 15 nicklas 325         
3651 07 Dec 15 nicklas 326         Rna r = Rna.get(e);
3764 22 Feb 16 nicklas 327         JSONObject jsonSpecimen = r.loadYellowLabelInfo(dc, manager);
3764 22 Feb 16 nicklas 328         
3764 22 Feb 16 nicklas 329         boolean wasSelected = false;
3764 22 Feb 16 nicklas 330         if (jsonSpecimen.get("YellowLabel") != null)
3764 22 Feb 16 nicklas 331         {
3764 22 Feb 16 nicklas 332           wasSelected = rnaYellow.add(r);
3764 22 Feb 16 nicklas 333         }
3764 22 Feb 16 nicklas 334         else if (rnaNotYellow.size() < numToSelect)
3764 22 Feb 16 nicklas 335         {
3764 22 Feb 16 nicklas 336           wasSelected = rnaNotYellow.add(r);
3764 22 Feb 16 nicklas 337         }
3764 22 Feb 16 nicklas 338         if (wasSelected)
3764 22 Feb 16 nicklas 339         {
3764 22 Feb 16 nicklas 340           r.setIndexOrder(index++);
3764 22 Feb 16 nicklas 341           r.setAnnotation("preNormalized", true);
3764 22 Feb 16 nicklas 342           r.setAnnotation("remainingQuantity", e.getRemainingQuantity());
4983 27 Sep 18 nicklas 343           r.loadDoNotUseAnnotations(dc, manager);
3764 22 Feb 16 nicklas 344           r.loadAnnotations(dc, manager, "NDConc", Annotationtype.ND_CONC, null);
6218 20 Apr 21 nicklas 345           r.loadAnnotations(dc, manager, "QubitConc", Annotationtype.QUBIT_CONC, null);
6218 20 Apr 21 nicklas 346           r.coalesceInto("conc", "NDConc", "QubitConc");
3764 22 Feb 16 nicklas 347           r.loadAnnotations(dc, manager, "DilutionDate", Annotationtype.DILUTION_DATE, Reggie.CONVERTER_DATE_TO_STRING);
3764 22 Feb 16 nicklas 348         }
3651 07 Dec 15 nicklas 349       }
3651 07 Dec 15 nicklas 350     }
3651 07 Dec 15 nicklas 351     finally
3651 07 Dec 15 nicklas 352     {
3651 07 Dec 15 nicklas 353       it.close();
3651 07 Dec 15 nicklas 354     }
3651 07 Dec 15 nicklas 355     
3764 22 Feb 16 nicklas 356     // If we have selected too many RNA, decrease the size of the "not yellow" list
3764 22 Feb 16 nicklas 357     if (rnaYellow.size() + rnaNotYellow.size() > numToSelect)
3764 22 Feb 16 nicklas 358     {
3764 22 Feb 16 nicklas 359       rnaNotYellow = rnaNotYellow.subList(0, numToSelect - rnaYellow.size());
3764 22 Feb 16 nicklas 360     }
3764 22 Feb 16 nicklas 361     
3764 22 Feb 16 nicklas 362     return new List[] { rnaYellow, rnaNotYellow };
3651 07 Dec 15 nicklas 363   }
3651 07 Dec 15 nicklas 364   
3651 07 Dec 15 nicklas 365   /**
3651 07 Dec 15 nicklas 366     Find RNA items that has not yet been used for library preparation. 
3651 07 Dec 15 nicklas 367     
3651 07 Dec 15 nicklas 368     * Creation date must be set (or after RnaFilterOptions.startDate)
3651 07 Dec 15 nicklas 369     * The item must have a parent (to get rid of 'Stratagene')
3651 07 Dec 15 nicklas 370     * No child item of type mRNA or Library must exist unless:
3651 07 Dec 15 nicklas 371       - the RNA is marked for ReProcess and RnaFilterOptions.reProcess is set
3651 07 Dec 15 nicklas 372     
3764 22 Feb 16 nicklas 373      This method return three lists. 
3764 22 Feb 16 nicklas 374
3764 22 Feb 16 nicklas 375      * The first contains YellowSpecimen RNA selected for library preparation.
3764 22 Feb 16 nicklas 376      * The second contains other RNA selected for library preparation
3764 22 Feb 16 nicklas 377      *  The third contains RNA that should be flagged:
3764 22 Feb 16 nicklas 378        - Remaining quantity is lower than RnaFilterOptions.minRemainingQuantity
3764 22 Feb 16 nicklas 379        - RQS or RIN value is lower than RnaFilterOptions.minQualityScore
3651 07 Dec 15 nicklas 380      
3764 22 Feb 16 nicklas 381      The total number of RNA to process is less than or equal to the
3764 22 Feb 16 nicklas 382      'numToSelect' parameter. The selected RNA is sorted by storage
3764 22 Feb 16 nicklas 383      plate position. To be able to merge the list with YellowSpecimen RNA 
3764 22 Feb 16 nicklas 384      and other RNA and keep the plate order, use the 'startIndexOrder',
3764 22 Feb 16 nicklas 385      {@link Collections#sort(List, java.util.Comparator)} and 
3764 22 Feb 16 nicklas 386      {@link ReggieItem.IndexOrderComparator}.
3651 07 Dec 15 nicklas 387      
3764 22 Feb 16 nicklas 388     @since 4.0, 4.2
3651 07 Dec 15 nicklas 389   */
5415 09 May 19 nicklas 390   @SuppressWarnings({"unchecked", "rawtypes"})
3764 22 Feb 16 nicklas 391   public static List<Rna>[] findRnaForLibPrep(DbControl dc, SnapshotManager manager, RnaFilterOptions options, int numToSelect, int startIndexOrder)
3651 07 Dec 15 nicklas 392   {
3651 07 Dec 15 nicklas 393     ItemQuery<Extract> query = Extract.getQuery();
3651 07 Dec 15 nicklas 394     query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3651 07 Dec 15 nicklas 395     Subtype.RNA.addFilter(dc, query);
3651 07 Dec 15 nicklas 396     // Filters assume that 'creationEvent' is joined as 'ce' alias
3651 07 Dec 15 nicklas 397     query.join(Hql.innerJoin("creationEvent", "ce"));
3651 07 Dec 15 nicklas 398     
3651 07 Dec 15 nicklas 399     // Filter for RNA already included on the plate
3651 07 Dec 15 nicklas 400     options.addIgnoreFilter(query);
3651 07 Dec 15 nicklas 401     
3651 07 Dec 15 nicklas 402     // Filter for non-empty creation date or creation date after startDate
3651 07 Dec 15 nicklas 403     options.addCreationDateFilter(query);
3651 07 Dec 15 nicklas 404     
3651 07 Dec 15 nicklas 405     // Filter on parent != null (to get rid of 'Stratagene')
3651 07 Dec 15 nicklas 406     query.restrict(Restrictions.neq(Hql.property("parent"), null));
3651 07 Dec 15 nicklas 407     
3651 07 Dec 15 nicklas 408     // Create a subquery that load all RNA extracts that has at least one mRNA child extract
3651 07 Dec 15 nicklas 409     ItemQuery<Extract> mrnaQuery = Extract.getQuery();
3651 07 Dec 15 nicklas 410     mrnaQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3651 07 Dec 15 nicklas 411     Subtype.RNA.addFilter(dc, mrnaQuery);
3651 07 Dec 15 nicklas 412     // Join child items and filter on mRNA/Library subtype
3651 07 Dec 15 nicklas 413     mrnaQuery.join(Hql.innerJoin("childCreationEvents", "cce"));
3651 07 Dec 15 nicklas 414     mrnaQuery.join(Hql.innerJoin("cce", "event", "evt", null, false));
3651 07 Dec 15 nicklas 415     mrnaQuery.join(Hql.innerJoin("evt", "bioMaterial", "bm", null, false));
3651 07 Dec 15 nicklas 416     mrnaQuery.restrict(Restrictions.or(
3651 07 Dec 15 nicklas 417       Subtype.MRNA.restriction(dc, "bm"),
3651 07 Dec 15 nicklas 418       Subtype.LIBRARY.restriction(dc, "bm")
3651 07 Dec 15 nicklas 419     ));
3651 07 Dec 15 nicklas 420     
3651 07 Dec 15 nicklas 421     /* Create filter: AUTO_PROCESS==ReProcess OR (AUTO_PROCESS=null AND <no mrna/library children>) */
3651 07 Dec 15 nicklas 422     query.join(Annotations.leftJoin(null, Annotationtype.AUTO_PROCESSING.load(dc), "ap"));
3651 07 Dec 15 nicklas 423     query.restrict(
3651 07 Dec 15 nicklas 424       Restrictions.nullSafeOr(
3651 07 Dec 15 nicklas 425         options.reProcess ? Restrictions.eq(Hql.alias("ap"), Expressions.string("ReProcess")) : null,
3651 07 Dec 15 nicklas 426         Restrictions.and(
3651 07 Dec 15 nicklas 427           Restrictions.eq(Hql.alias("ap"), null),
3651 07 Dec 15 nicklas 428           Restrictions.neq(Hql.property("id"), Expressions.all(mrnaQuery))
3651 07 Dec 15 nicklas 429         )
3651 07 Dec 15 nicklas 430       )
3651 07 Dec 15 nicklas 431     );
3651 07 Dec 15 nicklas 432     
3651 07 Dec 15 nicklas 433     // Order by RNA plate and location: plate - row - column
3651 07 Dec 15 nicklas 434     query.join(Hql.innerJoin(null, "bioWell", "w", true));
3651 07 Dec 15 nicklas 435     query.join(Hql.innerJoin("w", "bioPlate", "bp", true));
3651 07 Dec 15 nicklas 436     query.order(Orders.asc(Hql.property("bp", "name")));
3651 07 Dec 15 nicklas 437     query.order(Orders.asc(Hql.property("w", "row")));
3651 07 Dec 15 nicklas 438     query.order(Orders.asc(Hql.property("w", "column")));
3651 07 Dec 15 nicklas 439
3764 22 Feb 16 nicklas 440     List<Rna> rnaYellow = new ArrayList<Rna>();
3764 22 Feb 16 nicklas 441     List<Rna> rnaNotYellow = new ArrayList<Rna>();
3651 07 Dec 15 nicklas 442     List<Rna> flagged = new ArrayList<Rna>();
3651 07 Dec 15 nicklas 443     
3651 07 Dec 15 nicklas 444     ItemResultIterator<Extract> it = query.iterate(dc);
3651 07 Dec 15 nicklas 445     try
3651 07 Dec 15 nicklas 446     {
3764 22 Feb 16 nicklas 447       int index = startIndexOrder;
3764 22 Feb 16 nicklas 448       while (it.hasNext() && rnaYellow.size() < numToSelect)
3651 07 Dec 15 nicklas 449       {
3651 07 Dec 15 nicklas 450         Extract e = it.next();
3651 07 Dec 15 nicklas 451         Rna r = Rna.get(e);
3651 07 Dec 15 nicklas 452         
3651 07 Dec 15 nicklas 453         // Check filtering/flagging options
3651 07 Dec 15 nicklas 454         boolean okToProcess = true;
3651 07 Dec 15 nicklas 455         String autoProcess = null;
3651 07 Dec 15 nicklas 456         if (options.reProcess)
3651 07 Dec 15 nicklas 457         {
3651 07 Dec 15 nicklas 458           // If the RNA has been marked for ReProcess it is always selected
3651 07 Dec 15 nicklas 459           autoProcess = (String)Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, manager, e);
3651 07 Dec 15 nicklas 460           r.setAnnotation("AutoProcessing", autoProcess);
3651 07 Dec 15 nicklas 461         }
3651 07 Dec 15 nicklas 462         
3763 22 Feb 16 nicklas 463         Float qualityScore = r.loadRnaQc(dc, manager);
3763 22 Feb 16 nicklas 464         Float remainingQuantity = e.getRemainingQuantity();
3763 22 Feb 16 nicklas 465
3651 07 Dec 15 nicklas 466         if (autoProcess == null)
3651 07 Dec 15 nicklas 467         {
3763 22 Feb 16 nicklas 468           if (qualityScore == null) continue; // QC has not been measuered; ignore
3763 22 Feb 16 nicklas 469           
3651 07 Dec 15 nicklas 470           if (options.minRemainingQuantity != null)
3651 07 Dec 15 nicklas 471           {
3651 07 Dec 15 nicklas 472             if (remainingQuantity == null || remainingQuantity < options.minRemainingQuantity)
3651 07 Dec 15 nicklas 473             {
3651 07 Dec 15 nicklas 474               okToProcess = false;
3651 07 Dec 15 nicklas 475               r.setAnnotation("flag", Rna.FLAG_NOT_ENOUGH_REMAINING_QUANTITY);
3651 07 Dec 15 nicklas 476             }
3651 07 Dec 15 nicklas 477           }
3651 07 Dec 15 nicklas 478           if (okToProcess && options.minQualityScore != null)
3651 07 Dec 15 nicklas 479           {
3651 07 Dec 15 nicklas 480             if (qualityScore < options.minQualityScore)
3651 07 Dec 15 nicklas 481             {
3651 07 Dec 15 nicklas 482               okToProcess = false;
3651 07 Dec 15 nicklas 483               r.setAnnotation("flag", Rna.FLAG_LOW_QUALITY_SCORE);
3651 07 Dec 15 nicklas 484             }
3651 07 Dec 15 nicklas 485           }
3651 07 Dec 15 nicklas 486         }
3763 22 Feb 16 nicklas 487         
3764 22 Feb 16 nicklas 488         JSONObject jsonSpecimen = r.loadYellowLabelInfo(dc, manager);
3651 07 Dec 15 nicklas 489
3764 22 Feb 16 nicklas 490         boolean wasSelected = false;
3651 07 Dec 15 nicklas 491         if (okToProcess)
3651 07 Dec 15 nicklas 492         {
3764 22 Feb 16 nicklas 493           r.setIndexOrder(index++);
3764 22 Feb 16 nicklas 494           if (jsonSpecimen.get("YellowLabel") != null)
3764 22 Feb 16 nicklas 495           {
3764 22 Feb 16 nicklas 496             wasSelected = rnaYellow.add(r);
3764 22 Feb 16 nicklas 497           }
3764 22 Feb 16 nicklas 498           else if (rnaNotYellow.size() < numToSelect)
3764 22 Feb 16 nicklas 499           {
3764 22 Feb 16 nicklas 500             wasSelected = rnaNotYellow.add(r);
3764 22 Feb 16 nicklas 501           }
3651 07 Dec 15 nicklas 502         }
3651 07 Dec 15 nicklas 503         else
3651 07 Dec 15 nicklas 504         {
3764 22 Feb 16 nicklas 505           if (rnaYellow.size() + rnaNotYellow.size() < numToSelect) 
3764 22 Feb 16 nicklas 506           {
3764 22 Feb 16 nicklas 507             wasSelected = flagged.add(r);
3764 22 Feb 16 nicklas 508           }
3651 07 Dec 15 nicklas 509         }
3764 22 Feb 16 nicklas 510         
3764 22 Feb 16 nicklas 511         if (wasSelected)
3764 22 Feb 16 nicklas 512         {
3764 22 Feb 16 nicklas 513           r.loadBioPlateLocation();
3764 22 Feb 16 nicklas 514           r.setAnnotation("preNormalized", false);
3764 22 Feb 16 nicklas 515           r.setAnnotation("remainingQuantity", remainingQuantity);
4983 27 Sep 18 nicklas 516           r.loadDoNotUseAnnotations(dc, manager);
3764 22 Feb 16 nicklas 517           r.loadAnnotations(dc, manager, "NDConc", Annotationtype.ND_CONC, null);
6218 20 Apr 21 nicklas 518           r.loadAnnotations(dc, manager, "QubitConc", Annotationtype.QUBIT_CONC, null);
6218 20 Apr 21 nicklas 519           r.coalesceInto("conc", "NDConc", "QubitConc");
3764 22 Feb 16 nicklas 520           r.loadAnnotations(dc, manager, "QiacubeDate", Annotationtype.QIACUBE_DATE, Reggie.CONVERTER_DATE_TO_STRING);
3764 22 Feb 16 nicklas 521         }
3651 07 Dec 15 nicklas 522       }
3651 07 Dec 15 nicklas 523     }
3651 07 Dec 15 nicklas 524     finally
3651 07 Dec 15 nicklas 525     {
3651 07 Dec 15 nicklas 526       it.close();
3651 07 Dec 15 nicklas 527     }
3651 07 Dec 15 nicklas 528     
3764 22 Feb 16 nicklas 529     // If we have selected too many RNA, decrease the size of the "not yellow" list
3764 22 Feb 16 nicklas 530     if (rnaYellow.size() + rnaNotYellow.size() > numToSelect)
3764 22 Feb 16 nicklas 531     {
3764 22 Feb 16 nicklas 532       rnaNotYellow = rnaNotYellow.subList(0, numToSelect - rnaYellow.size());
3764 22 Feb 16 nicklas 533     }
3764 22 Feb 16 nicklas 534     
3764 22 Feb 16 nicklas 535     return new List[] { rnaYellow, rnaNotYellow, flagged };
3651 07 Dec 15 nicklas 536   }
3651 07 Dec 15 nicklas 537   
3651 07 Dec 15 nicklas 538   /**
3659 09 Dec 15 nicklas 539     Find RNA from pre-defined item lists {@link BiomaterialList#RNA_AUTO_DESIGN_1} and
3659 09 Dec 15 nicklas 540     {@link BiomaterialList#RNA_AUTO_DESIGN_2}.
3659 09 Dec 15 nicklas 541   */
3659 09 Dec 15 nicklas 542   @SuppressWarnings("unchecked")
3659 09 Dec 15 nicklas 543   public static List<Rna> findMoreRnaForAutoDesignLibPrep(DbControl dc, SnapshotManager manager, int numToSelect)
3659 09 Dec 15 nicklas 544   {
3659 09 Dec 15 nicklas 545     List<Rna> rna = new ArrayList<Rna>();
3659 09 Dec 15 nicklas 546     List<BiomaterialList> lists = Arrays.asList(BiomaterialList.RNA_AUTO_DESIGN_1, BiomaterialList.RNA_AUTO_DESIGN_2);
3659 09 Dec 15 nicklas 547     Iterator<BiomaterialList> listIt = lists.iterator();
3659 09 Dec 15 nicklas 548     
3659 09 Dec 15 nicklas 549     while (rna.size() < numToSelect && listIt.hasNext())
3659 09 Dec 15 nicklas 550     {
3659 09 Dec 15 nicklas 551       BiomaterialList list = listIt.next();
3659 09 Dec 15 nicklas 552       ItemList l = list.load(dc);
3659 09 Dec 15 nicklas 553       JSONObject jsonList = new JSONObject();
3659 09 Dec 15 nicklas 554       jsonList.put("id", l.getId());
3659 09 Dec 15 nicklas 555       jsonList.put("name", l.getName());
3659 09 Dec 15 nicklas 556       
6183 26 Mar 21 nicklas 557       ItemQuery<Extract> query = list.load(dc).getMembers();
3659 09 Dec 15 nicklas 558       query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3659 09 Dec 15 nicklas 559       Subtype.RNA.addFilter(dc, query); // Just in case... the list should only contain RNA...
3659 09 Dec 15 nicklas 560       query.order(Orders.asc(Hql.property("id")));
3659 09 Dec 15 nicklas 561       Iterator<Extract> it = query.iterate(dc);
3659 09 Dec 15 nicklas 562       
3659 09 Dec 15 nicklas 563       while (rna.size() < numToSelect && it.hasNext())
3659 09 Dec 15 nicklas 564       {
3659 09 Dec 15 nicklas 565         Extract e = it.next();
3659 09 Dec 15 nicklas 566         
3659 09 Dec 15 nicklas 567         Rna r = Rna.get(e);
3659 09 Dec 15 nicklas 568         r.loadBioPlateLocation();
3659 09 Dec 15 nicklas 569         r.setAnnotation("preNormalized", false);
3659 09 Dec 15 nicklas 570         r.setAnnotation("list", jsonList);
3659 09 Dec 15 nicklas 571         r.setAnnotation("remainingQuantity", e.getRemainingQuantity());
3659 09 Dec 15 nicklas 572         r.loadAnnotations(dc, manager, "NDConc", Annotationtype.ND_CONC, null);
6218 20 Apr 21 nicklas 573         r.loadAnnotations(dc, manager, "QubitConc", Annotationtype.QUBIT_CONC, null);
6218 20 Apr 21 nicklas 574         r.coalesceInto("conc", "NDConc", "QubitConc");
4983 27 Sep 18 nicklas 575         r.loadDoNotUseAnnotations(dc, manager);
3659 09 Dec 15 nicklas 576         
3659 09 Dec 15 nicklas 577         r.loadRnaQc(dc, manager);
3659 09 Dec 15 nicklas 578         r.loadAnnotations(dc, manager, "QiacubeDate", Annotationtype.QIACUBE_DATE, Reggie.CONVERTER_DATE_TO_STRING);
3659 09 Dec 15 nicklas 579         rna.add(r);
3659 09 Dec 15 nicklas 580       }
3659 09 Dec 15 nicklas 581     }
3659 09 Dec 15 nicklas 582     
3659 09 Dec 15 nicklas 583     return rna;
3659 09 Dec 15 nicklas 584   }
3659 09 Dec 15 nicklas 585   
3659 09 Dec 15 nicklas 586   /**
1832 08 Feb 13 nicklas 587     Find all RNA items by case name. This method will check for {@link Subtype#RNA}
1832 08 Feb 13 nicklas 588     extracts with a name matching the case name (eg. xxx.r).
1832 08 Feb 13 nicklas 589     @since 2.11
1832 08 Feb 13 nicklas 590   */
1832 08 Feb 13 nicklas 591   public static List<Rna> findByCaseName(DbControl dc, String name)
1832 08 Feb 13 nicklas 592   {
1832 08 Feb 13 nicklas 593     // Get rid of suffixes in the name (eg. 'C' which is used for pre-neoadjuvant forms)
1832 08 Feb 13 nicklas 594     if (name.length() > 7) name = name.substring(0, 7);    
1832 08 Feb 13 nicklas 595     
1832 08 Feb 13 nicklas 596     // Look for a rna with the given name 
1832 08 Feb 13 nicklas 597     ItemQuery<Extract> rnaQuery = Extract.getQuery();
1832 08 Feb 13 nicklas 598     Subtype.RNA.addFilter(dc, rnaQuery);
2917 11 Nov 14 nicklas 599     rnaQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1832 08 Feb 13 nicklas 600     rnaQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("name", name+".%", Type.STRING)));
2917 11 Nov 14 nicklas 601     rnaQuery.order(Orders.asc(Hql.property("name")));
2917 11 Nov 14 nicklas 602
1832 08 Feb 13 nicklas 603     List<Extract> tmp = rnaQuery.list(dc);
1832 08 Feb 13 nicklas 604     List<Rna> rna = new ArrayList<Rna>(tmp.size());
1832 08 Feb 13 nicklas 605     for (Extract e : tmp)
1832 08 Feb 13 nicklas 606     {
1832 08 Feb 13 nicklas 607       rna.add(new Rna(e));
1832 08 Feb 13 nicklas 608     }
1832 08 Feb 13 nicklas 609     return rna;
1832 08 Feb 13 nicklas 610   }
1832 08 Feb 13 nicklas 611
6341 29 Jun 21 nicklas 612   /**
6341 29 Jun 21 nicklas 613      Find a RNA item with the given name.
6341 29 Jun 21 nicklas 614      @return A RNA, or null if not found
6341 29 Jun 21 nicklas 615      @since 4.32
6341 29 Jun 21 nicklas 616   */
6341 29 Jun 21 nicklas 617   public static Rna findByName(DbControl dc, String name, boolean allowPreNormalized)
6341 29 Jun 21 nicklas 618   {
6341 29 Jun 21 nicklas 619     Rna rna = null;
6341 29 Jun 21 nicklas 620     ItemQuery<Extract> query = Extract.getQuery();
6341 29 Jun 21 nicklas 621     if (allowPreNormalized)
6341 29 Jun 21 nicklas 622     {
6341 29 Jun 21 nicklas 623       query.restrict(Restrictions.or(
6341 29 Jun 21 nicklas 624         Subtype.RNA.restriction(dc, null),
6341 29 Jun 21 nicklas 625         Subtype.RNA_NORMALIZED_ALIQUOT.restriction(dc, null)
6341 29 Jun 21 nicklas 626       ));
6341 29 Jun 21 nicklas 627     }
6341 29 Jun 21 nicklas 628     else
6341 29 Jun 21 nicklas 629     {
6341 29 Jun 21 nicklas 630       Subtype.RNA.addFilter(dc, query);
6341 29 Jun 21 nicklas 631     }
6341 29 Jun 21 nicklas 632     
6341 29 Jun 21 nicklas 633     query.restrict(Restrictions.eq(Hql.property("name"), Expressions.string(name)));
6341 29 Jun 21 nicklas 634     query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
6341 29 Jun 21 nicklas 635     
6341 29 Jun 21 nicklas 636     List<Extract> items = query.list(dc);
6341 29 Jun 21 nicklas 637     if (items.size() > 1)
6341 29 Jun 21 nicklas 638     {
6341 29 Jun 21 nicklas 639       throw new InvalidDataException(
6341 29 Jun 21 nicklas 640           "More than one RNA with the name '" + name + "' was found. " +
6341 29 Jun 21 nicklas 641           "This wizard can't be used until that is corrected.");
6341 29 Jun 21 nicklas 642     }
6341 29 Jun 21 nicklas 643     if (items.size() == 1)
6341 29 Jun 21 nicklas 644     {
6341 29 Jun 21 nicklas 645       rna = new Rna(items.get(0));
6341 29 Jun 21 nicklas 646     }
6341 29 Jun 21 nicklas 647     return rna;
6341 29 Jun 21 nicklas 648   }
6341 29 Jun 21 nicklas 649
1832 08 Feb 13 nicklas 650   
1832 08 Feb 13 nicklas 651   /**
1543 28 Feb 12 nicklas 652     Get a RNA extract when the id is known.
1543 28 Feb 12 nicklas 653   */
1543 28 Feb 12 nicklas 654   public static Rna getById(DbControl dc, int id)
1543 28 Feb 12 nicklas 655   {
1543 28 Feb 12 nicklas 656     return new Rna(Extract.getById(dc, id));
1543 28 Feb 12 nicklas 657   }
1543 28 Feb 12 nicklas 658   
1865 19 Feb 13 nicklas 659   public static Rna get(Extract extract)
1865 19 Feb 13 nicklas 660   {
7142 04 May 23 nicklas 661     return extract == null ? null : new Rna(extract);
1865 19 Feb 13 nicklas 662   }
1573 19 Mar 12 nicklas 663   
1865 19 Feb 13 nicklas 664   public static List<Rna> toRna(Collection<Extract> extracts)
1865 19 Feb 13 nicklas 665   {
1865 19 Feb 13 nicklas 666     List<Rna> rna = new ArrayList<Rna>(extracts.size());
1865 19 Feb 13 nicklas 667     for (Extract e : extracts)
1865 19 Feb 13 nicklas 668     {
1865 19 Feb 13 nicklas 669       rna.add(new Rna(e));
1865 19 Feb 13 nicklas 670     }
1865 19 Feb 13 nicklas 671     return rna;
1865 19 Feb 13 nicklas 672   }
1865 19 Feb 13 nicklas 673   
1573 19 Mar 12 nicklas 674   private JSONObject jsonWell;
3757 18 Feb 16 nicklas 675   private JSONObject jsonSpecimen;
1573 19 Mar 12 nicklas 676   
1543 28 Feb 12 nicklas 677   private Rna(Extract extract)
1543 28 Feb 12 nicklas 678   {
1543 28 Feb 12 nicklas 679     super(extract);
1543 28 Feb 12 nicklas 680
1543 28 Feb 12 nicklas 681   }  
1543 28 Feb 12 nicklas 682   
2906 07 Nov 14 nicklas 683   /**
2906 07 Nov 14 nicklas 684     Checks if this RNA item is a Pre-normalized RNA.
2906 07 Nov 14 nicklas 685     @since 2.18
2906 07 Nov 14 nicklas 686   */
2906 07 Nov 14 nicklas 687   public boolean isPreNormalized(DbControl dc)
2906 07 Nov 14 nicklas 688   {
2906 07 Nov 14 nicklas 689     return Subtype.RNA_NORMALIZED_ALIQUOT.get(dc).equals(getExtract().getItemSubtype());
2906 07 Nov 14 nicklas 690   }
1543 28 Feb 12 nicklas 691   
1543 28 Feb 12 nicklas 692   /**
2906 07 Nov 14 nicklas 693     Return the parent RNA item if this is a pre-normalized
2906 07 Nov 14 nicklas 694     RNA, otherwise return itself.
2906 07 Nov 14 nicklas 695     @since 2.18
2906 07 Nov 14 nicklas 696   */
2906 07 Nov 14 nicklas 697   public Rna getRnaIfPrenormalized(DbControl dc)
2906 07 Nov 14 nicklas 698   {
2906 07 Nov 14 nicklas 699     Rna r = this;
2906 07 Nov 14 nicklas 700     if (isPreNormalized(dc))
2906 07 Nov 14 nicklas 701     {
2906 07 Nov 14 nicklas 702       r = new Rna((Extract)getItem().getParent());
2906 07 Nov 14 nicklas 703     }
2906 07 Nov 14 nicklas 704     return r;
2906 07 Nov 14 nicklas 705   }
2906 07 Nov 14 nicklas 706   
2906 07 Nov 14 nicklas 707   
2906 07 Nov 14 nicklas 708   /**
1543 28 Feb 12 nicklas 709     Get the real extract that represents this RNA in BASE.
1543 28 Feb 12 nicklas 710   */
1543 28 Feb 12 nicklas 711   public Extract getExtract()
1543 28 Feb 12 nicklas 712   {
1543 28 Feb 12 nicklas 713     return getItem();
1543 28 Feb 12 nicklas 714   }
3166 05 Mar 15 nicklas 715   
3166 05 Mar 15 nicklas 716   /**
3757 18 Feb 16 nicklas 717     NOTE! Assumes that the items is NOT a PreNormalizedRNA!
3166 05 Mar 15 nicklas 718     @since 3.2
3166 05 Mar 15 nicklas 719   */
3166 05 Mar 15 nicklas 720   public Lysate getLysate()
3166 05 Mar 15 nicklas 721   {
3166 05 Mar 15 nicklas 722     Extract rna = getItem();    
3166 05 Mar 15 nicklas 723     Extract lysate = (Extract)rna.getParent();
3760 19 Feb 16 nicklas 724     return lysate == null ? null : Lysate.get(lysate);
3166 05 Mar 15 nicklas 725   }
1543 28 Feb 12 nicklas 726
1543 28 Feb 12 nicklas 727   /**
1543 28 Feb 12 nicklas 728     Find the next name to give a RNAQC child item. This assumes that
1560 14 Mar 12 nicklas 729     all child items are using the naming convention. foo.qc, foo.qc2, and
1560 14 Mar 12 nicklas 730     so on. NOTE! The first child item have no number!
1543 28 Feb 12 nicklas 731     @return The next unused name
1543 28 Feb 12 nicklas 732   */
1543 28 Feb 12 nicklas 733   public String getNextRnaQcName(DbControl dc)
1543 28 Feb 12 nicklas 734   {
1543 28 Feb 12 nicklas 735     Extract rna = getItem();
6193 30 Mar 21 nicklas 736     ItemQuery<Extract> query = null;
6193 30 Mar 21 nicklas 737     if (rna.isInDatabase())
6193 30 Mar 21 nicklas 738     {
6193 30 Mar 21 nicklas 739       query = rna.getChildExtracts();
6193 30 Mar 21 nicklas 740       Subtype.RNAQC.addFilter(dc, query);
6193 30 Mar 21 nicklas 741       query.setIncludes(Include.ALL);
6193 30 Mar 21 nicklas 742     }
4891 09 Jul 18 nicklas 743     return getNextChildItemName(dc, query, Subtype.RNAQC.getItemSuffix(), false);
1543 28 Feb 12 nicklas 744   }
1543 28 Feb 12 nicklas 745   
1573 19 Mar 12 nicklas 746   /**
2903 06 Nov 14 nicklas 747     Find the next name to give a RNANormalizedAliquot child item. This assumes that
4905 11 Jul 18 nicklas 748     all child items are using the naming convention. foo.n, foo.n2, and
2903 06 Nov 14 nicklas 749     so on. NOTE! The first child item have no number!
2903 06 Nov 14 nicklas 750     @return The next unused name
2903 06 Nov 14 nicklas 751     @since 2.18
2903 06 Nov 14 nicklas 752   */
2903 06 Nov 14 nicklas 753   public String getNextNormalizedAliquotName(DbControl dc)
2903 06 Nov 14 nicklas 754   {
2903 06 Nov 14 nicklas 755     Extract rna = getItem();
6193 30 Mar 21 nicklas 756     ItemQuery<Extract> query = null;
6193 30 Mar 21 nicklas 757     if (rna.isInDatabase())
6193 30 Mar 21 nicklas 758     {
6193 30 Mar 21 nicklas 759       query = rna.getChildExtracts();
6193 30 Mar 21 nicklas 760       Subtype.RNA_NORMALIZED_ALIQUOT.addFilter(dc, query);
6193 30 Mar 21 nicklas 761       query.setIncludes(Include.ALL);
6193 30 Mar 21 nicklas 762     }
4905 11 Jul 18 nicklas 763     return getNextChildItemName(dc, query, Subtype.RNA_NORMALIZED_ALIQUOT.getItemSuffix(), false);
2903 06 Nov 14 nicklas 764   }
2903 06 Nov 14 nicklas 765
2903 06 Nov 14 nicklas 766   /**
4885 04 Jul 18 nicklas 767     Find the next name to give a "Library" or "mRNA" child item. This assumes that
4885 04 Jul 18 nicklas 768     all child items are using the naming convention. foo.m/lib, foo.m2/lib2, and
4885 04 Jul 18 nicklas 769     so on. NOTE! The first child item have no number!
4885 04 Jul 18 nicklas 770     @return The next unused name
4885 04 Jul 18 nicklas 771     @since 4.19
4885 04 Jul 18 nicklas 772   */
4885 04 Jul 18 nicklas 773   public String getNextLibOrMRnaName(DbControl dc, Subtype subtype)
4885 04 Jul 18 nicklas 774   {
4885 04 Jul 18 nicklas 775     Extract rna = getItem();
6193 30 Mar 21 nicklas 776     ItemQuery<Extract> query = null;
6193 30 Mar 21 nicklas 777     if (rna.isInDatabase())
6193 30 Mar 21 nicklas 778     {
6193 30 Mar 21 nicklas 779       query = rna.getChildExtracts();
6193 30 Mar 21 nicklas 780       subtype.addFilter(dc, query);
6193 30 Mar 21 nicklas 781       query.setIncludes(Include.ALL);
6193 30 Mar 21 nicklas 782     }
4885 04 Jul 18 nicklas 783     return getNextChildItemName(dc, query, subtype.getItemSuffix(), true);
4885 04 Jul 18 nicklas 784   }
4885 04 Jul 18 nicklas 785
4885 04 Jul 18 nicklas 786   
4885 04 Jul 18 nicklas 787   /**
1939 18 Apr 13 nicklas 788     Find the last RNAQC child item that contains either a BA_RIN or CA_RQS value.
1939 18 Apr 13 nicklas 789     @return The RNAQC item
1939 18 Apr 13 nicklas 790   */
3188 18 Mar 15 nicklas 791   public RnaQc findLastRnaQc(DbControl dc, SnapshotManager manager)
1939 18 Apr 13 nicklas 792   {
3188 18 Mar 15 nicklas 793     RnaQc lastQc = null;
3188 18 Mar 15 nicklas 794     List<RnaQc> rnaqc = RnaQc.findByRna(dc, this);
1939 18 Apr 13 nicklas 795     if (rnaqc.size() > 0)
1939 18 Apr 13 nicklas 796     {
3188 18 Mar 15 nicklas 797       lastQc = RnaQc.findLast(dc, manager, rnaqc);
1939 18 Apr 13 nicklas 798     }
1939 18 Apr 13 nicklas 799     return lastQc;
1939 18 Apr 13 nicklas 800   }
1939 18 Apr 13 nicklas 801   
1939 18 Apr 13 nicklas 802   
3166 05 Mar 15 nicklas 803   public Float loadRnaQc(DbControl dc, SnapshotManager manager)
1939 18 Apr 13 nicklas 804   {
1941 18 Apr 13 nicklas 805     Float rqs = null;
1941 18 Apr 13 nicklas 806     Float rin = null;
1941 18 Apr 13 nicklas 807     
3188 18 Mar 15 nicklas 808     RnaQc rnaqc = findLastRnaQc(dc, manager);
3188 18 Mar 15 nicklas 809     if (rnaqc != null)
1941 18 Apr 13 nicklas 810     {
3188 18 Mar 15 nicklas 811       Extract qc = rnaqc.getExtract();
3166 05 Mar 15 nicklas 812       rqs = (Float)Annotationtype.CA_RQS.getAnnotationValue(dc, manager, qc);
3166 05 Mar 15 nicklas 813       rin = (Float)Annotationtype.BA_RIN.getAnnotationValue(dc, manager, qc);
1941 18 Apr 13 nicklas 814       if (rqs != null) setAnnotation("rqs", rqs);
1941 18 Apr 13 nicklas 815       if (rin != null) setAnnotation("rin", rin);
1941 18 Apr 13 nicklas 816     }
1940 18 Apr 13 nicklas 817     return rqs != null ? rqs : rin;
1939 18 Apr 13 nicklas 818   }
1939 18 Apr 13 nicklas 819   
1939 18 Apr 13 nicklas 820   /**
1573 19 Mar 12 nicklas 821     Load information about the plate and location the current RNA
1573 19 Mar 12 nicklas 822     is located on.
1573 19 Mar 12 nicklas 823   */
1573 19 Mar 12 nicklas 824   public JSONObject loadBioPlateLocation()
1573 19 Mar 12 nicklas 825   {
1826 07 Feb 13 nicklas 826     if (jsonWell == null)
1573 19 Mar 12 nicklas 827     {
2134 11 Nov 13 nicklas 828       jsonWell = JsonUtil.getBioWellAsJSON(getItem().getBioWell(), true);
2906 07 Nov 14 nicklas 829       JSONObject json = asJSONObject();
2906 07 Nov 14 nicklas 830       json.put("bioWell", jsonWell);
1573 19 Mar 12 nicklas 831     }
1573 19 Mar 12 nicklas 832     return jsonWell;
1573 19 Mar 12 nicklas 833   }
1573 19 Mar 12 nicklas 834   
3651 07 Dec 15 nicklas 835   /**
3757 18 Feb 16 nicklas 836     Load the specimen this RNA/PreNormalizedRNA is derived from
3757 18 Feb 16 nicklas 837     and include YellowLabel annotation information.
3757 18 Feb 16 nicklas 838     @since 4.2
3757 18 Feb 16 nicklas 839   */
3757 18 Feb 16 nicklas 840   public JSONObject loadYellowLabelInfo(DbControl dc, SnapshotManager manager)
3757 18 Feb 16 nicklas 841   {
3757 18 Feb 16 nicklas 842     if (jsonSpecimen == null)
3757 18 Feb 16 nicklas 843     {
3757 18 Feb 16 nicklas 844       Lysate l = getRnaIfPrenormalized(dc).getLysate();
3757 18 Feb 16 nicklas 845       SpecimenTube sp = l != null ? l.getSpecimen() : null;
3757 18 Feb 16 nicklas 846       if (sp != null) 
3757 18 Feb 16 nicklas 847       {
3757 18 Feb 16 nicklas 848         sp.loadAnnotations(dc, manager, "YellowLabel", Annotationtype.YELLOW_LABEL, null);
3757 18 Feb 16 nicklas 849         jsonSpecimen = sp.asJSONObject();
3757 18 Feb 16 nicklas 850         setAnnotation("specimen", jsonSpecimen);
3757 18 Feb 16 nicklas 851       }
3757 18 Feb 16 nicklas 852       else
3757 18 Feb 16 nicklas 853       {
3757 18 Feb 16 nicklas 854         jsonSpecimen = new JSONObject();
3757 18 Feb 16 nicklas 855       }
3757 18 Feb 16 nicklas 856     }
3757 18 Feb 16 nicklas 857     return jsonSpecimen;
3757 18 Feb 16 nicklas 858   }
3757 18 Feb 16 nicklas 859   
3757 18 Feb 16 nicklas 860   /**
3651 07 Dec 15 nicklas 861     Class for keeping filtering options when finding RNA/PreNormalized RNA 
3651 07 Dec 15 nicklas 862     for library preparation. Note that not all filters are used in all cases.
3651 07 Dec 15 nicklas 863     Some options can be set as filters on the query that load extracts,
3651 07 Dec 15 nicklas 864     some options are checked after loading the information and may cause an item
3651 07 Dec 15 nicklas 865     to not be selected or be flagged.
3651 07 Dec 15 nicklas 866     @since 4.0
3651 07 Dec 15 nicklas 867   */
3651 07 Dec 15 nicklas 868   public static class RnaFilterOptions
3651 07 Dec 15 nicklas 869   {
3651 07 Dec 15 nicklas 870     // If set, filter on creation date > startDate
3651 07 Dec 15 nicklas 871     public Date startDate;
3651 07 Dec 15 nicklas 872     // If true, RNA marked for ReProcess are selected (only used for RNA)
3651 07 Dec 15 nicklas 873     public boolean reProcess;
3651 07 Dec 15 nicklas 874     // Do not include items with ID in this collection (used for both RNA and PreNormalized RNA)
3651 07 Dec 15 nicklas 875     public Collection<Long> ignore;
3651 07 Dec 15 nicklas 876     // Only select items pre-normalized with the given protocol (only used for PreNormalized RNA)
3651 07 Dec 15 nicklas 877     public Protocol normalizationProtocol;
3651 07 Dec 15 nicklas 878     
3651 07 Dec 15 nicklas 879     // Flag RNA having remaining quantity less than this value (only used for RNA)
3651 07 Dec 15 nicklas 880     public Float minRemainingQuantity;
3651 07 Dec 15 nicklas 881     // Flag RNA having a RQS/RIN lower than this value (only used for RNA)
3651 07 Dec 15 nicklas 882     public Float minQualityScore;
3651 07 Dec 15 nicklas 883     
3651 07 Dec 15 nicklas 884     public RnaFilterOptions()
3651 07 Dec 15 nicklas 885     {}
3651 07 Dec 15 nicklas 886     
3651 07 Dec 15 nicklas 887     /**
3651 07 Dec 15 nicklas 888       Add a filter removing all items in the 'ignore' collection.
3651 07 Dec 15 nicklas 889     */
3651 07 Dec 15 nicklas 890     void addIgnoreFilter(ItemQuery<?> query)
3651 07 Dec 15 nicklas 891     {
3651 07 Dec 15 nicklas 892       if (ignore != null && ignore.size() > 0)
3651 07 Dec 15 nicklas 893       {
3651 07 Dec 15 nicklas 894         query.restrict(Restrictions.not(Restrictions.in(Hql.property("id"), Expressions.parameter("ignore"))));
3651 07 Dec 15 nicklas 895         query.setParameter("ignore", ignore, Type.LONG);
3651 07 Dec 15 nicklas 896       }
3651 07 Dec 15 nicklas 897     }
3651 07 Dec 15 nicklas 898     
3651 07 Dec 15 nicklas 899     /**
3651 07 Dec 15 nicklas 900       Add a filter on creation date. It must be not-null or after the
3651 07 Dec 15 nicklas 901       given 'startDate'.
3651 07 Dec 15 nicklas 902     */
3651 07 Dec 15 nicklas 903     void addCreationDateFilter(ItemQuery<?> query)
3651 07 Dec 15 nicklas 904     {
3651 07 Dec 15 nicklas 905       if (startDate == null)
3651 07 Dec 15 nicklas 906       {
3651 07 Dec 15 nicklas 907         query.restrict(Restrictions.neq(Hql.property("ce", "eventDate"), null));
3651 07 Dec 15 nicklas 908       }
3651 07 Dec 15 nicklas 909       else
3651 07 Dec 15 nicklas 910       {
3651 07 Dec 15 nicklas 911         query.restrict(Restrictions.gteq(Hql.property("ce", "eventDate"), Expressions.parameter("startDate", startDate, Type.DATE)));
3651 07 Dec 15 nicklas 912       }
3651 07 Dec 15 nicklas 913     }
3651 07 Dec 15 nicklas 914     
3651 07 Dec 15 nicklas 915     /**
3651 07 Dec 15 nicklas 916       Add a filter on the creation protocol (normalized RNA only)
3651 07 Dec 15 nicklas 917     */
3651 07 Dec 15 nicklas 918     void addProtocolFilter(ItemQuery<?> query)
3651 07 Dec 15 nicklas 919     {
3651 07 Dec 15 nicklas 920       if (normalizationProtocol != null)
3651 07 Dec 15 nicklas 921       {
3651 07 Dec 15 nicklas 922         query.restrict(Restrictions.eq(Hql.property("ce", "protocol"), Hql.entity(normalizationProtocol)));
3651 07 Dec 15 nicklas 923       }
3651 07 Dec 15 nicklas 924     }
3651 07 Dec 15 nicklas 925   }
1543 28 Feb 12 nicklas 926 }