extensions/net.sf.basedb.meludi/trunk/src/net/sf/basedb/meludi/dao/Histology.java

Code
Comments
Other
Rev Date Author Line
5093 14 Nov 18 olle 1 package net.sf.basedb.meludi.dao;
5093 14 Nov 18 olle 2
5093 14 Nov 18 olle 3 import java.util.ArrayList;
5093 14 Nov 18 olle 4 import java.util.List;
5093 14 Nov 18 olle 5
5093 14 Nov 18 olle 6 import org.json.simple.JSONObject;
5093 14 Nov 18 olle 7
5093 14 Nov 18 olle 8 import net.sf.basedb.core.AnnotationSimpleRestriction;
5093 14 Nov 18 olle 9 import net.sf.basedb.core.AnnotationType;
5093 14 Nov 18 olle 10 import net.sf.basedb.core.DbControl;
5093 14 Nov 18 olle 11 import net.sf.basedb.core.ItemQuery;
5093 14 Nov 18 olle 12 import net.sf.basedb.core.Operator;
5093 14 Nov 18 olle 13 import net.sf.basedb.core.Sample;
5093 14 Nov 18 olle 14 import net.sf.basedb.core.Type;
5093 14 Nov 18 olle 15 import net.sf.basedb.core.query.Expressions;
5093 14 Nov 18 olle 16 import net.sf.basedb.core.query.Hql;
5093 14 Nov 18 olle 17 import net.sf.basedb.core.query.Orders;
5093 14 Nov 18 olle 18 import net.sf.basedb.core.query.Restrictions;
5093 14 Nov 18 olle 19 import net.sf.basedb.meludi.JsonUtil;
5093 14 Nov 18 olle 20 import net.sf.basedb.meludi.Meludi;
5093 14 Nov 18 olle 21
5093 14 Nov 18 olle 22 /**
5093 14 Nov 18 olle 23   Class for loading information that is related to Histology samples.
5093 14 Nov 18 olle 24   
5093 14 Nov 18 olle 25   @author nicklas
5093 14 Nov 18 olle 26   @since 2.7
5093 14 Nov 18 olle 27 */
5093 14 Nov 18 olle 28 public class Histology 
5093 14 Nov 18 olle 29   extends MeludiItem<Sample>
5093 14 Nov 18 olle 30 {
5093 14 Nov 18 olle 31
5093 14 Nov 18 olle 32   /**
5093 14 Nov 18 olle 33     This ID is used on Histology work lists for the external ID attribute.
5093 14 Nov 18 olle 34   */
5093 14 Nov 18 olle 35   public static final String WORK_LIST_ID = "net.sf.basedb.meludi.histology.work-list";
5093 14 Nov 18 olle 36
5093 14 Nov 18 olle 37   /**
5093 14 Nov 18 olle 38     Flag value for the {@link Annotationtype#FLAG} annotation when a Histology item has failed
5093 14 Nov 18 olle 39     to get a GoodStain.
5093 14 Nov 18 olle 40     @since 2.15
5093 14 Nov 18 olle 41   */
5093 14 Nov 18 olle 42   public static final String FLAG_NO_GOOD_STAIN = "NoGoodStain";
5093 14 Nov 18 olle 43
5093 14 Nov 18 olle 44   /**
5093 14 Nov 18 olle 45     The number of samples per paraffin block.
5093 14 Nov 18 olle 46   */
5093 14 Nov 18 olle 47   public static final int SAMPLES_PER_BLOCK = 5;
5093 14 Nov 18 olle 48   
5093 14 Nov 18 olle 49   /**
5093 14 Nov 18 olle 50     Path on BASE file system to histology images.
5093 14 Nov 18 olle 51     @since 3.6
5093 14 Nov 18 olle 52   */
5093 14 Nov 18 olle 53   //public static final String IMAGE_DIR = "/home/SCANB/HistologyImages";
5093 14 Nov 18 olle 54   public static final String IMAGE_DIR = "/home/HistologyImages";
5093 14 Nov 18 olle 55   
5093 14 Nov 18 olle 56   
5093 14 Nov 18 olle 57   /**
5093 14 Nov 18 olle 58     Get the folder for storing image for the given sample name.
5093 14 Nov 18 olle 59     
5093 14 Nov 18 olle 60     We want to use a prefix in the BASE file system to prevent
5093 14 Nov 18 olle 61     several thousands of subfolders or files inside a single folder.
5093 14 Nov 18 olle 62     The prefix should only be used if the name folder starts with
5093 14 Nov 18 olle 63     digits. The first level is the first two digits and the second level is 
5093 14 Nov 18 olle 64     the first four digits.
5093 14 Nov 18 olle 65     
5093 14 Nov 18 olle 66     
5093 14 Nov 18 olle 67     Examples:
5093 14 Nov 18 olle 68       1234567.1.his.he1 --> /12/1234/
5093 14 Nov 18 olle 69     @since 3.6
5093 14 Nov 18 olle 70   */
5093 14 Nov 18 olle 71   public static String getImageFolder(String name)
5093 14 Nov 18 olle 72   {
5093 14 Nov 18 olle 73     // If the name starts with 7 digits+'.'+at least one more digit
5093 14 Nov 18 olle 74     // insert prefix based on first 2+4 digits
5093 14 Nov 18 olle 75     return name.replaceFirst("^((\\d{2})\\d{2})\\d{3}\\.\\d+.*", "/$2/$1/");
5093 14 Nov 18 olle 76   }
5093 14 Nov 18 olle 77
5093 14 Nov 18 olle 78   
5093 14 Nov 18 olle 79   /**
5093 14 Nov 18 olle 80     Find Histology samples that have not yet been embedded in paraffin blocks. 
5093 14 Nov 18 olle 81     The query will look for samples with the {@link Subtype#HISTOLOGY} subtype 
5093 14 Nov 18 olle 82     that has no 'created' date. Since the Histology items are currently stored
5093 14 Nov 18 olle 83     in temporary boxes, the list is sorted by bioplate and position.
5093 14 Nov 18 olle 84     @param excludeWorkLists TRUE to exclude Histology items that have been picked and saved in a work list
5093 14 Nov 18 olle 85   */
5093 14 Nov 18 olle 86   public static List<Histology> findUnembeddedHistologyItems(DbControl dc, boolean excludeWorkLists, int maxResults)
5093 14 Nov 18 olle 87   {
5093 14 Nov 18 olle 88     List<Histology> histology = new ArrayList<Histology>();
5093 14 Nov 18 olle 89     
5093 14 Nov 18 olle 90     // Create a query that load all Histology samples without created date
5093 14 Nov 18 olle 91     ItemQuery<Sample> query = Sample.getQuery();
5093 14 Nov 18 olle 92     query.setIncludes(Meludi.INCLUDE_IN_CURRENT_PROJECT);
5093 14 Nov 18 olle 93     // Filter on Lysate subtype
5093 14 Nov 18 olle 94     Subtype.HISTOLOGY.addFilter(dc, query);
5093 14 Nov 18 olle 95     // Filter on created date == null
5093 14 Nov 18 olle 96     query.restrict(Restrictions.eq(Hql.property("ce", "eventDate"), null));
5093 14 Nov 18 olle 97     // Filter on not present in a work list 
5093 14 Nov 18 olle 98     if (excludeWorkLists)
5093 14 Nov 18 olle 99     {
5093 14 Nov 18 olle 100       ItemQuery<Sample> workQuery = Sample.getQuery();
5093 14 Nov 18 olle 101       workQuery.setIncludes(Meludi.INCLUDE_IN_CURRENT_PROJECT);
5093 14 Nov 18 olle 102       String subquery = "select mmb from ItemListData lst INNER JOIN lst.members mmb where lst.externalId=:externalId and lst.removed=false";
5093 14 Nov 18 olle 103       workQuery.restrict(Hql.restriction("$id NOT IN ("+subquery+")", "$"));
5093 14 Nov 18 olle 104       workQuery.setParameter("externalId", WORK_LIST_ID, Type.STRING);
5093 14 Nov 18 olle 105     }
5093 14 Nov 18 olle 106     
5093 14 Nov 18 olle 107     // Join the creation event and bioplate
5093 14 Nov 18 olle 108     query.join(Hql.innerJoin(null, "creationEvent", "ce", true));
5093 14 Nov 18 olle 109     query.join(Hql.leftJoin(null, "bioWell", "bw", null, true));
5093 14 Nov 18 olle 110     query.join(Hql.leftJoin("bw", "bioPlate", "bp", null, true));
5093 14 Nov 18 olle 111     
5093 14 Nov 18 olle 112     // Sort by bioplate position -- those without plate are sorted last by id
5093 14 Nov 18 olle 113     query.order(Orders.asc(Hql.expression("coalesce(bp.name, 'zzzz')", null)));
5093 14 Nov 18 olle 114     query.order(Orders.asc(Hql.property("bw", "row")));
5093 14 Nov 18 olle 115     query.order(Orders.asc(Hql.property("bw", "column")));
5093 14 Nov 18 olle 116     query.order(Orders.asc(Hql.property("id")));
5093 14 Nov 18 olle 117     
5093 14 Nov 18 olle 118     query.setMaxResults(maxResults);
5093 14 Nov 18 olle 119         
5093 14 Nov 18 olle 120     List<Sample> samples = query.list(dc);
5093 14 Nov 18 olle 121     for (Sample s : samples)
5093 14 Nov 18 olle 122     {
5093 14 Nov 18 olle 123       histology.add(new Histology(s));
5093 14 Nov 18 olle 124     }
5093 14 Nov 18 olle 125     return histology;
5093 14 Nov 18 olle 126   }
5093 14 Nov 18 olle 127   
5848 02 Mar 20 olle 128
5093 14 Nov 18 olle 129   /**
5848 02 Mar 20 olle 130     Find all histology items by name. This method will check for {@link Subtype#HISTOLOGY} samples 
5848 02 Mar 20 olle 131     with a specific name (eg. xxx.his).
5848 02 Mar 20 olle 132     @since 2.11
5848 02 Mar 20 olle 133    */
5848 02 Mar 20 olle 134   public static List<Histology> findByName(DbControl dc, String name)
5848 02 Mar 20 olle 135   {
5848 02 Mar 20 olle 136     ItemQuery<Sample> histologyQuery = Sample.getQuery();
5848 02 Mar 20 olle 137     Subtype.HISTOLOGY.addFilter(dc, histologyQuery);
5848 02 Mar 20 olle 138     histologyQuery.setIncludes(Meludi.INCLUDE_IN_CURRENT_PROJECT);
5848 02 Mar 20 olle 139     //histologyQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("name", name+".%", Type.STRING)));
5848 02 Mar 20 olle 140     histologyQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("name", name+"%", Type.STRING)));
5848 02 Mar 20 olle 141     histologyQuery.order(Orders.asc(Hql.property("name")));
5848 02 Mar 20 olle 142
5848 02 Mar 20 olle 143     List<Sample> tmp = histologyQuery.list(dc);
5848 02 Mar 20 olle 144     List<Histology> histology = new ArrayList<Histology>(tmp.size());
5848 02 Mar 20 olle 145     for (Sample s : tmp)
5848 02 Mar 20 olle 146     {
5848 02 Mar 20 olle 147       histology.add(new Histology(s));
5848 02 Mar 20 olle 148     }
5848 02 Mar 20 olle 149     return histology;
5848 02 Mar 20 olle 150   }
5848 02 Mar 20 olle 151
5848 02 Mar 20 olle 152
5848 02 Mar 20 olle 153   /**
5093 14 Nov 18 olle 154     Find all histology items by case name. This method will check for {@link Subtype#HISTOLOGY} samples 
5093 14 Nov 18 olle 155     with a name matching the case name (eg. xxx.his).
5093 14 Nov 18 olle 156     @since 2.11
5093 14 Nov 18 olle 157   */
5093 14 Nov 18 olle 158   public static List<Histology> findByCaseName(DbControl dc, String name)
5093 14 Nov 18 olle 159   {
5093 14 Nov 18 olle 160 /*
5093 14 Nov 18 olle 161     // Get rid of suffixes in the name (eg. 'C' which is used for pre-neoadjuvant forms)
5093 14 Nov 18 olle 162     if (name.length() > 7) name = name.substring(0, 7);    
5093 14 Nov 18 olle 163     
5093 14 Nov 18 olle 164     // Look for a blood case with the given name 
5093 14 Nov 18 olle 165     ItemQuery<Sample> histologyQuery = Sample.getQuery();
5093 14 Nov 18 olle 166     Subtype.HISTOLOGY.addFilter(dc, histologyQuery);
5093 14 Nov 18 olle 167     histologyQuery.setIncludes(Meludi.INCLUDE_IN_CURRENT_PROJECT);
5093 14 Nov 18 olle 168     histologyQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("name", name+".%", Type.STRING)));
5093 14 Nov 18 olle 169     histologyQuery.order(Orders.asc(Hql.property("name")));
5093 14 Nov 18 olle 170
5093 14 Nov 18 olle 171     List<Sample> tmp = histologyQuery.list(dc);
5093 14 Nov 18 olle 172     List<Histology> histology = new ArrayList<Histology>(tmp.size());
5093 14 Nov 18 olle 173     for (Sample s : tmp)
5093 14 Nov 18 olle 174     {
5093 14 Nov 18 olle 175       histology.add(new Histology(s));
5093 14 Nov 18 olle 176     }
5093 14 Nov 18 olle 177     return histology;
5093 14 Nov 18 olle 178 */
5093 14 Nov 18 olle 179     // Look for a histology item with the given case ID as annotation.
5093 14 Nov 18 olle 180     String caseId = name;
5093 14 Nov 18 olle 181     AnnotationType caseIdType = Annotationtype.CASE_ID.load(dc);
5093 14 Nov 18 olle 182     ItemQuery<Sample> histologyQuery = Sample.getQuery();
5093 14 Nov 18 olle 183     Subtype.HISTOLOGY.addFilter(dc, histologyQuery);
5093 14 Nov 18 olle 184     histologyQuery.restrict(new AnnotationSimpleRestriction(null, caseIdType, Operator.EQ, caseId, true, false));
5093 14 Nov 18 olle 185     histologyQuery.setIncludes(Meludi.INCLUDE_IN_CURRENT_PROJECT);
5093 14 Nov 18 olle 186     histologyQuery.order(Orders.asc(Hql.property("name")));
5093 14 Nov 18 olle 187
5093 14 Nov 18 olle 188     List<Sample> tmp = histologyQuery.list(dc);
5093 14 Nov 18 olle 189     List<Histology> histologyList = new ArrayList<Histology>(tmp.size());
5093 14 Nov 18 olle 190     for (Sample s : tmp)
5093 14 Nov 18 olle 191     {
5093 14 Nov 18 olle 192       histologyList.add(new Histology(s));
5093 14 Nov 18 olle 193     }
5093 14 Nov 18 olle 194     return histologyList;
5093 14 Nov 18 olle 195   }
5093 14 Nov 18 olle 196
5093 14 Nov 18 olle 197   
5093 14 Nov 18 olle 198   /**
5093 14 Nov 18 olle 199     Get a Histology when the id is known.
5093 14 Nov 18 olle 200   */
5093 14 Nov 18 olle 201   public static Histology getById(DbControl dc, int id)
5093 14 Nov 18 olle 202   {
5093 14 Nov 18 olle 203     return new Histology(Sample.getById(dc, id));
5093 14 Nov 18 olle 204   }
5093 14 Nov 18 olle 205   
5093 14 Nov 18 olle 206   
5093 14 Nov 18 olle 207   private JSONObject jsonWell;
5093 14 Nov 18 olle 208   
5093 14 Nov 18 olle 209   private Histology(Sample sample)
5093 14 Nov 18 olle 210   {
5093 14 Nov 18 olle 211     super(sample);
5093 14 Nov 18 olle 212
5093 14 Nov 18 olle 213   }  
5093 14 Nov 18 olle 214   
5093 14 Nov 18 olle 215   
5093 14 Nov 18 olle 216   /**
5093 14 Nov 18 olle 217     Get the real sample that represents this Histology item in BASE.
5093 14 Nov 18 olle 218   */
5093 14 Nov 18 olle 219   public Sample getSample()
5093 14 Nov 18 olle 220   {
5093 14 Nov 18 olle 221     return getItem();
5093 14 Nov 18 olle 222   }
5093 14 Nov 18 olle 223
5093 14 Nov 18 olle 224   @SuppressWarnings("unchecked")
5093 14 Nov 18 olle 225   @Override
5093 14 Nov 18 olle 226   protected void initJSON(JSONObject json) 
5093 14 Nov 18 olle 227   {
5093 14 Nov 18 olle 228     super.initJSON(json);
5093 14 Nov 18 olle 229     if (jsonWell != null) json.put("bioWell", jsonWell);
5093 14 Nov 18 olle 230     
5093 14 Nov 18 olle 231   }
5093 14 Nov 18 olle 232
5093 14 Nov 18 olle 233   /**
5093 14 Nov 18 olle 234     Load information about the plate and location the current RNA
5093 14 Nov 18 olle 235     is located on.
5093 14 Nov 18 olle 236   */
5093 14 Nov 18 olle 237   public JSONObject loadBioPlateLocation()
5093 14 Nov 18 olle 238   {
5093 14 Nov 18 olle 239     if (jsonWell == null)
5093 14 Nov 18 olle 240     {
5093 14 Nov 18 olle 241       jsonWell = JsonUtil.getBioWellAsJSON(getItem().getBioWell(), true);
5093 14 Nov 18 olle 242     }
5093 14 Nov 18 olle 243     return jsonWell;
5093 14 Nov 18 olle 244   }
5093 14 Nov 18 olle 245
5093 14 Nov 18 olle 246   
5093 14 Nov 18 olle 247 }