extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/LibPrepServlet.java

Code
Comments
Other
Rev Date Author Line
1806 22 Jan 13 nicklas 1 package net.sf.basedb.reggie.servlet;
1806 22 Jan 13 nicklas 2
5892 07 Apr 20 nicklas 3 import java.io.ByteArrayInputStream;
1806 22 Jan 13 nicklas 4 import java.io.IOException;
5301 14 Feb 19 nicklas 5 import java.io.InputStream;
5297 13 Feb 19 nicklas 6 import java.io.OutputStream;
2221 10 Feb 14 nicklas 7 import java.io.OutputStreamWriter;
5892 07 Apr 20 nicklas 8 import java.io.StringWriter;
1896 05 Mar 13 nicklas 9 import java.io.Writer;
5892 07 Apr 20 nicklas 10 import java.nio.charset.StandardCharsets;
1895 05 Mar 13 nicklas 11 import java.util.Date;
1810 28 Jan 13 nicklas 12 import java.util.HashMap;
2221 10 Feb 14 nicklas 13 import java.util.Iterator;
1806 22 Jan 13 nicklas 14 import java.util.List;
1810 28 Jan 13 nicklas 15 import java.util.Map;
1906 14 Mar 13 nicklas 16 import java.util.regex.Pattern;
1806 22 Jan 13 nicklas 17
1806 22 Jan 13 nicklas 18 import javax.servlet.ServletException;
1806 22 Jan 13 nicklas 19 import javax.servlet.http.HttpServlet;
1806 22 Jan 13 nicklas 20 import javax.servlet.http.HttpServletRequest;
1806 22 Jan 13 nicklas 21 import javax.servlet.http.HttpServletResponse;
1806 22 Jan 13 nicklas 22
7024 07 Feb 23 nicklas 23 import org.apache.commons.lang3.time.FastDateFormat;
5889 06 Apr 20 nicklas 24 import org.apache.poi.ss.usermodel.Cell;
5889 06 Apr 20 nicklas 25 import org.apache.poi.ss.usermodel.CellStyle;
5887 02 Apr 20 nicklas 26 import org.apache.poi.ss.usermodel.Row;
5887 02 Apr 20 nicklas 27 import org.apache.poi.ss.usermodel.Sheet;
5887 02 Apr 20 nicklas 28 import org.apache.poi.ss.usermodel.Workbook;
1806 22 Jan 13 nicklas 29 import org.json.simple.JSONArray;
1806 22 Jan 13 nicklas 30 import org.json.simple.JSONObject;
1806 22 Jan 13 nicklas 31
1906 14 Mar 13 nicklas 32 import net.sf.basedb.core.AnnotationType;
1895 05 Mar 13 nicklas 33 import net.sf.basedb.core.AnyToAny;
1806 22 Jan 13 nicklas 34 import net.sf.basedb.core.Application;
2221 10 Feb 14 nicklas 35 import net.sf.basedb.core.BioMaterial;
1908 19 Mar 13 nicklas 36 import net.sf.basedb.core.BioMaterialEvent;
1810 28 Jan 13 nicklas 37 import net.sf.basedb.core.BioMaterialEventSource;
3309 06 May 15 nicklas 38 import net.sf.basedb.core.BioPlateEvent;
3309 06 May 15 nicklas 39 import net.sf.basedb.core.BioPlateEventType;
3247 14 Apr 15 nicklas 40 import net.sf.basedb.core.ItemList;
5889 06 Apr 20 nicklas 41 import net.sf.basedb.core.ItemNotFoundException;
1806 22 Jan 13 nicklas 42 import net.sf.basedb.core.BioPlate;
1900 07 Mar 13 nicklas 43 import net.sf.basedb.core.BioWell;
1806 22 Jan 13 nicklas 44 import net.sf.basedb.core.DbControl;
1806 22 Jan 13 nicklas 45 import net.sf.basedb.core.Extract;
1895 05 Mar 13 nicklas 46 import net.sf.basedb.core.File;
1906 14 Mar 13 nicklas 47 import net.sf.basedb.core.InvalidDataException;
1986 21 May 13 nicklas 48 import net.sf.basedb.core.Item;
1806 22 Jan 13 nicklas 49 import net.sf.basedb.core.ItemQuery;
1810 28 Jan 13 nicklas 50 import net.sf.basedb.core.ItemSubtype;
1896 05 Mar 13 nicklas 51 import net.sf.basedb.core.Path;
2344 09 Apr 14 nicklas 52 import net.sf.basedb.core.Permission;
2221 10 Feb 14 nicklas 53 import net.sf.basedb.core.PermissionDeniedException;
1896 05 Mar 13 nicklas 54 import net.sf.basedb.core.PluginConfiguration;
1896 05 Mar 13 nicklas 55 import net.sf.basedb.core.PluginDefinition;
1908 19 Mar 13 nicklas 56 import net.sf.basedb.core.Protocol;
1806 22 Jan 13 nicklas 57 import net.sf.basedb.core.SessionControl;
1810 28 Jan 13 nicklas 58 import net.sf.basedb.core.Tag;
2454 23 May 14 nicklas 59 import net.sf.basedb.core.Type;
1896 05 Mar 13 nicklas 60 import net.sf.basedb.core.plugin.ParameterValues;
1893 04 Mar 13 nicklas 61 import net.sf.basedb.core.query.Annotations;
1986 21 May 13 nicklas 62 import net.sf.basedb.core.query.Expressions;
1806 22 Jan 13 nicklas 63 import net.sf.basedb.core.query.Hql;
1806 22 Jan 13 nicklas 64 import net.sf.basedb.core.query.Orders;
1806 22 Jan 13 nicklas 65 import net.sf.basedb.core.query.Restrictions;
3760 19 Feb 16 nicklas 66 import net.sf.basedb.core.snapshot.SnapshotManager;
2598 22 Aug 14 nicklas 67 import net.sf.basedb.reggie.JsonUtil;
1806 22 Jan 13 nicklas 68 import net.sf.basedb.reggie.Reggie;
5384 26 Apr 19 nicklas 69 import net.sf.basedb.reggie.activity.ActivityDef;
1895 05 Mar 13 nicklas 70 import net.sf.basedb.reggie.converter.DateToStringConverter;
1906 14 Mar 13 nicklas 71 import net.sf.basedb.reggie.converter.LookupConverter;
2960 19 Nov 14 nicklas 72 import net.sf.basedb.reggie.converter.RequiredValueConverter;
1900 07 Mar 13 nicklas 73 import net.sf.basedb.reggie.converter.ValueConverter;
1900 07 Mar 13 nicklas 74 import net.sf.basedb.reggie.converter.WellCoordinateConverter;
3059 19 Dec 14 nicklas 75 import net.sf.basedb.reggie.counter.CounterService;
1809 25 Jan 13 nicklas 76 import net.sf.basedb.reggie.dao.Annotationtype;
5866 13 Mar 20 nicklas 77 import net.sf.basedb.reggie.dao.BarcodeSet;
1908 19 Mar 13 nicklas 78 import net.sf.basedb.reggie.dao.BiomaterialList;
1806 22 Jan 13 nicklas 79 import net.sf.basedb.reggie.dao.BioplateType;
1806 22 Jan 13 nicklas 80 import net.sf.basedb.reggie.dao.CDna;
5791 16 Dec 19 nicklas 81 import net.sf.basedb.reggie.dao.DoNotUse;
1894 04 Mar 13 nicklas 82 import net.sf.basedb.reggie.dao.Library;
5436 17 May 19 nicklas 83 import net.sf.basedb.reggie.dao.Pipeline;
1908 19 Mar 13 nicklas 84 import net.sf.basedb.reggie.dao.ReactionPlate;
2161 09 Dec 13 nicklas 85 import net.sf.basedb.reggie.dao.ReggieRole;
1908 19 Mar 13 nicklas 86 import net.sf.basedb.reggie.dao.Rna;
1806 22 Jan 13 nicklas 87 import net.sf.basedb.reggie.dao.Subtype;
3835 11 Apr 16 nicklas 88 import net.sf.basedb.reggie.plugins.AbstractPlateImporter;
1896 05 Mar 13 nicklas 89 import net.sf.basedb.reggie.plugins.CaliperLibPrepParametersExporter;
1906 14 Mar 13 nicklas 90 import net.sf.basedb.reggie.plugins.CaliperPlateImporter;
1896 05 Mar 13 nicklas 91 import net.sf.basedb.reggie.plugins.CaliperSampleNameExporter;
2221 10 Feb 14 nicklas 92 import net.sf.basedb.reggie.plugins.CsvEncoderDecoder;
3834 11 Apr 16 nicklas 93 import net.sf.basedb.reggie.plugins.QubitPlateImporter;
1900 07 Mar 13 nicklas 94 import net.sf.basedb.reggie.plugins.QubitSampleNameExporter;
5303 15 Feb 19 nicklas 95 import net.sf.basedb.util.FileUtil;
1806 22 Jan 13 nicklas 96 import net.sf.basedb.util.Values;
1806 22 Jan 13 nicklas 97 import net.sf.basedb.util.error.ThrowableUtil;
5889 06 Apr 20 nicklas 98 import net.sf.basedb.util.excel.CellStyleCreator;
5888 03 Apr 20 nicklas 99 import net.sf.basedb.util.excel.XlsxTableWriter;
5371 16 Apr 19 nicklas 100 import net.sf.basedb.util.excel.XlsxToCsvUtil;
2221 10 Feb 14 nicklas 101 import net.sf.basedb.util.export.TableWriter;
1906 14 Mar 13 nicklas 102 import net.sf.basedb.util.parser.FlatFileParser;
1906 14 Mar 13 nicklas 103 import net.sf.basedb.util.parser.Mapper;
1906 14 Mar 13 nicklas 104 import net.sf.basedb.util.parser.FlatFileParser.LineType;
1806 22 Jan 13 nicklas 105
1806 22 Jan 13 nicklas 106
1806 22 Jan 13 nicklas 107 public class LibPrepServlet 
1806 22 Jan 13 nicklas 108   extends HttpServlet 
1806 22 Jan 13 nicklas 109 {
1806 22 Jan 13 nicklas 110
1806 22 Jan 13 nicklas 111   private static final long serialVersionUID = 2133738736983511172L;
1806 22 Jan 13 nicklas 112
1806 22 Jan 13 nicklas 113   public LibPrepServlet()
1806 22 Jan 13 nicklas 114   {}
1806 22 Jan 13 nicklas 115
1806 22 Jan 13 nicklas 116   @Override
1806 22 Jan 13 nicklas 117   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
1806 22 Jan 13 nicklas 118     throws ServletException, IOException 
1806 22 Jan 13 nicklas 119   {
1806 22 Jan 13 nicklas 120     String cmd = req.getParameter("cmd");
2598 22 Aug 14 nicklas 121     JsonUtil.setJsonResponseHeaders(resp);
1806 22 Jan 13 nicklas 122     
1806 22 Jan 13 nicklas 123     JSONObject json = new JSONObject();
1806 22 Jan 13 nicklas 124     json.put("status", "ok");
1806 22 Jan 13 nicklas 125     
3975 26 May 16 nicklas 126     final SessionControl sc = Reggie.getSessionControl(req);
1806 22 Jan 13 nicklas 127     DbControl dc = null;
1806 22 Jan 13 nicklas 128     try
1806 22 Jan 13 nicklas 129     {
3059 19 Dec 14 nicklas 130       if ("GetCDNAPlatesForBarcoding".equals(cmd))
1806 22 Jan 13 nicklas 131       {
1806 22 Jan 13 nicklas 132         /*
1893 04 Mar 13 nicklas 133           Find all cDNA bioplates that has not yet been assigned a
1893 04 Mar 13 nicklas 134           barcoding scheme.
1806 22 Jan 13 nicklas 135         */
6333 15 Jun 21 nicklas 136         dc = sc.newDbControl(":Assign barcodes to cDNA plate");
1893 04 Mar 13 nicklas 137         ItemQuery<BioPlate> query = BioPlate.getQuery();
1806 22 Jan 13 nicklas 138         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1893 04 Mar 13 nicklas 139         // Only cDNA bioplates that are not destroyed
1893 04 Mar 13 nicklas 140         BioplateType.CDNA.addFilter(dc, query, true);
1893 04 Mar 13 nicklas 141         // Must have a creation date
1893 04 Mar 13 nicklas 142         query.restrict(Restrictions.neq(Hql.property("eventDate"), null));
1893 04 Mar 13 nicklas 143         // Must not have a BARCODE_VARIANT annotation
1893 04 Mar 13 nicklas 144         query.join(Annotations.leftJoin(null, Annotationtype.BARCODE_VARIANT.load(dc), "bv"));
1893 04 Mar 13 nicklas 145         query.restrict(Restrictions.eq(Hql.alias("bv"), null));
1806 22 Jan 13 nicklas 146         
1893 04 Mar 13 nicklas 147         List<BioPlate> plates = query.list(dc);
1806 22 Jan 13 nicklas 148         
1806 22 Jan 13 nicklas 149         JSONArray jsonPlates = new JSONArray();
1806 22 Jan 13 nicklas 150         for (BioPlate plate : plates)
1806 22 Jan 13 nicklas 151         {
1806 22 Jan 13 nicklas 152           JSONObject jsonPlate = new JSONObject();
1806 22 Jan 13 nicklas 153           jsonPlate.put("id", plate.getId());
1806 22 Jan 13 nicklas 154           jsonPlate.put("name", plate.getName());
1814 30 Jan 13 nicklas 155           jsonPlate.put("comments", plate.getDescription());
1809 25 Jan 13 nicklas 156           jsonPlate.put("poolSchema", Annotationtype.POOL_SCHEMA.getAnnotationValue(dc, plate));
1814 30 Jan 13 nicklas 157           jsonPlate.put("barcodeVariant", Annotationtype.BARCODE_VARIANT.getAnnotationValue(dc, plate));
1806 22 Jan 13 nicklas 158           jsonPlates.add(jsonPlate);
1806 22 Jan 13 nicklas 159         }
1806 22 Jan 13 nicklas 160         json.put("bioplates", jsonPlates);
1806 22 Jan 13 nicklas 161       }
1894 04 Mar 13 nicklas 162       else if ("GetLibraryPlatesForLibPrep".equals(cmd))
1814 30 Jan 13 nicklas 163       {
1814 30 Jan 13 nicklas 164         /*
1894 04 Mar 13 nicklas 165           Find all Library bioplates without creation date.
1814 30 Jan 13 nicklas 166         */
6333 15 Jun 21 nicklas 167         dc = sc.newDbControl(":Library registration");
3308 06 May 15 nicklas 168         BioplateType plateType = BioplateType.getByCName(req.getParameter("plateType"));
3308 06 May 15 nicklas 169         if (plateType == null) plateType = BioplateType.LIBRARY;
3308 06 May 15 nicklas 170         
1894 04 Mar 13 nicklas 171         ItemQuery<BioPlate> query = BioPlate.getQuery();
1814 30 Jan 13 nicklas 172         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1894 04 Mar 13 nicklas 173         // Only Library bioplates that are not destroyed
3308 06 May 15 nicklas 174         plateType.addFilter(dc, query, true);
1894 04 Mar 13 nicklas 175         // Must NOT have a creation date
1993 23 May 13 nicklas 176         query.restrict(Restrictions.eq(Hql.property("eventDate"), null));
5887 02 Apr 20 nicklas 177         if (plateType != BioplateType.EXTERNAL_LIBRARY)
5887 02 Apr 20 nicklas 178         {
5887 02 Apr 20 nicklas 179           // Must have a BARCODE_VARIANT annotation
5887 02 Apr 20 nicklas 180           query.join(Annotations.leftJoin(null, Annotationtype.BARCODE_VARIANT.load(dc), "bv"));
5887 02 Apr 20 nicklas 181           query.restrict(Restrictions.neq(Hql.alias("bv"), null));
5887 02 Apr 20 nicklas 182         }
1814 30 Jan 13 nicklas 183         
1894 04 Mar 13 nicklas 184         List<BioPlate> plates = query.list(dc);
1814 30 Jan 13 nicklas 185         JSONArray jsonPlates = new JSONArray();
1814 30 Jan 13 nicklas 186         for (BioPlate plate : plates)
1814 30 Jan 13 nicklas 187         {
1986 21 May 13 nicklas 188           ItemQuery<AnyToAny> fileQuery = AnyToAny.getLinksFrom(plate);
1986 21 May 13 nicklas 189           Restrictions.eq(Hql.property("toType"), Expressions.integer(Item.FILE.getValue()));
1986 21 May 13 nicklas 190           long fileCount = fileQuery.count(dc);
1986 21 May 13 nicklas 191
1814 30 Jan 13 nicklas 192           JSONObject jsonPlate = new JSONObject();
1814 30 Jan 13 nicklas 193           jsonPlate.put("id", plate.getId());
1814 30 Jan 13 nicklas 194           jsonPlate.put("name", plate.getName());
1814 30 Jan 13 nicklas 195           jsonPlate.put("comments", plate.getDescription());
1986 21 May 13 nicklas 196           jsonPlate.put("numFiles", fileCount);
5887 02 Apr 20 nicklas 197           jsonPlate.put("usedWells", plate.getUsedWells());
3319 11 May 15 nicklas 198           jsonPlate.put("AutoProcessing", Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, plate));
3319 11 May 15 nicklas 199           jsonPlate.put("DilutionDate", Reggie.CONVERTER_DATE_TO_STRING.convert((Date)Annotationtype.DILUTION_DATE.getAnnotationValue(dc, plate)));
3319 11 May 15 nicklas 200           jsonPlate.put("DilutionOperator", Annotationtype.DILUTION_OPERATOR.getAnnotationValue(dc, plate));
1814 30 Jan 13 nicklas 201           jsonPlate.put("poolSchema", Annotationtype.POOL_SCHEMA.getAnnotationValue(dc, plate));
1814 30 Jan 13 nicklas 202           jsonPlate.put("barcodeVariant", Annotationtype.BARCODE_VARIANT.getAnnotationValue(dc, plate));
1814 30 Jan 13 nicklas 203           jsonPlates.add(jsonPlate);
1814 30 Jan 13 nicklas 204         }
1814 30 Jan 13 nicklas 205         json.put("bioplates", jsonPlates);
1814 30 Jan 13 nicklas 206       }
1810 28 Jan 13 nicklas 207       else if ("GetAllBarcodeInfo".equals(cmd))
1810 28 Jan 13 nicklas 208       {
6333 15 Jun 21 nicklas 209         dc = sc.newDbControl(":Assign barcodes to cDNA plate");
5866 13 Mar 20 nicklas 210         Pipeline pipeline = Pipeline.getByCName(req.getParameter("pipeline"));
5866 13 Mar 20 nicklas 211         BarcodeSet barcodeSet = BarcodeSet.getByCName(req.getParameter("barcodeSet"));
1810 28 Jan 13 nicklas 212         ItemQuery<Tag> query = Tag.getQuery();
1810 28 Jan 13 nicklas 213         Subtype.BARCODE.addFilter(dc, query);
5866 13 Mar 20 nicklas 214         if (pipeline != null) pipeline.addFilter(dc, query);
5866 13 Mar 20 nicklas 215         if (barcodeSet != null) barcodeSet.addFilter(dc, query);
1810 28 Jan 13 nicklas 216         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1810 28 Jan 13 nicklas 217         query.order(Orders.asc(Hql.property("name")));
1810 28 Jan 13 nicklas 218         
1810 28 Jan 13 nicklas 219         JSONArray jsonBarcodes = new JSONArray();
1810 28 Jan 13 nicklas 220         for (Tag t : query.list(dc))
1810 28 Jan 13 nicklas 221         {
1810 28 Jan 13 nicklas 222           JSONObject jsonTag = new JSONObject();
1810 28 Jan 13 nicklas 223           jsonTag.put("id", t.getId());
1810 28 Jan 13 nicklas 224           jsonTag.put("name", t.getName());
1810 28 Jan 13 nicklas 225           jsonBarcodes.add(jsonTag);
1810 28 Jan 13 nicklas 226         }
1810 28 Jan 13 nicklas 227         json.put("barcodes", jsonBarcodes);
1810 28 Jan 13 nicklas 228         
1810 28 Jan 13 nicklas 229       }
1806 22 Jan 13 nicklas 230       else if ("GetCDnaInfoForPlate".equals(cmd))
1806 22 Jan 13 nicklas 231       {
1806 22 Jan 13 nicklas 232         int cDnaPlateId = Values.getInt(req.getParameter("bioplate"));
6333 15 Jun 21 nicklas 233         dc = sc.newDbControl(":Assign barcodes to cDNA plate");
1806 22 Jan 13 nicklas 234
1806 22 Jan 13 nicklas 235         BioPlate cDnaPlate = BioPlate.getById(dc, cDnaPlateId);
1806 22 Jan 13 nicklas 236
1806 22 Jan 13 nicklas 237         ItemQuery<Extract> query = Extract.getQuery();
1806 22 Jan 13 nicklas 238         query.join(Hql.innerJoin(null, "bioWell", "bw", true));
1806 22 Jan 13 nicklas 239         query.join(Hql.innerJoin("bw", "bioPlate", "bp"));
1806 22 Jan 13 nicklas 240         query.restrict(Restrictions.eq(Hql.alias("bp"), Hql.entity(cDnaPlate)));
1806 22 Jan 13 nicklas 241         query.order(Orders.asc(Hql.property("bw", "column")));
1806 22 Jan 13 nicklas 242         query.order(Orders.asc(Hql.property("bw", "row")));
1806 22 Jan 13 nicklas 243
1806 22 Jan 13 nicklas 244         List<CDna> cdna = CDna.toList(query.list(dc));
1806 22 Jan 13 nicklas 245         JSONArray jsonCDna = new JSONArray();
3760 19 Feb 16 nicklas 246         SnapshotManager manager = new SnapshotManager();
1806 22 Jan 13 nicklas 247         for (CDna c : cdna)
1806 22 Jan 13 nicklas 248         {
1806 22 Jan 13 nicklas 249           c.loadBioPlateLocation();
3760 19 Feb 16 nicklas 250           c.setAnnotation("specimen", c.getMRna().getRna().loadYellowLabelInfo(dc, manager));
1806 22 Jan 13 nicklas 251           jsonCDna.add(c.asJSONObject());
1806 22 Jan 13 nicklas 252         }                
1806 22 Jan 13 nicklas 253         json.put("cdna", jsonCDna);
1806 22 Jan 13 nicklas 254       }
1814 30 Jan 13 nicklas 255       else if ("GetLibraryInfoForPlate".equals(cmd))
1814 30 Jan 13 nicklas 256       {
1894 04 Mar 13 nicklas 257         int libPlateId = Values.getInt(req.getParameter("bioplate"));
3308 06 May 15 nicklas 258         boolean loadDilutionInfo = Values.getBoolean(req.getParameter("loadDilutionInfo"));
6333 15 Jun 21 nicklas 259         dc = sc.newDbControl(":Create pooled libraries");
1806 22 Jan 13 nicklas 260
3760 19 Feb 16 nicklas 261         SnapshotManager manager = new SnapshotManager();
1894 04 Mar 13 nicklas 262         BioPlate libPlate = BioPlate.getById(dc, libPlateId);
3308 06 May 15 nicklas 263       
3308 06 May 15 nicklas 264         JSONObject jsonPlate = new JSONObject();
3308 06 May 15 nicklas 265         jsonPlate.put("id", libPlate.getId());
3308 06 May 15 nicklas 266         jsonPlate.put("name", libPlate.getName());
3308 06 May 15 nicklas 267         jsonPlate.put("columns", libPlate.getColumns());
3308 06 May 15 nicklas 268         jsonPlate.put("rows", libPlate.getRows());
3308 06 May 15 nicklas 269         jsonPlate.put("comments", libPlate.getDescription());
3319 11 May 15 nicklas 270         jsonPlate.put("DilutionDate", Reggie.CONVERTER_DATE_TO_STRING.convert((Date)Annotationtype.DILUTION_DATE.getAnnotationValue(dc, libPlate)));
3319 11 May 15 nicklas 271         jsonPlate.put("DilutionOperator", Annotationtype.DILUTION_OPERATOR.getAnnotationValue(dc, libPlate));
3308 06 May 15 nicklas 272         jsonPlate.put("poolSchema", Annotationtype.POOL_SCHEMA.getAnnotationValue(dc, libPlate));
3308 06 May 15 nicklas 273         jsonPlate.put("barcodeVariant", Annotationtype.BARCODE_VARIANT.getAnnotationValue(dc, libPlate));
3308 06 May 15 nicklas 274         
5891 07 Apr 20 nicklas 275         if (loadDilutionInfo)
5891 07 Apr 20 nicklas 276         {
5891 07 Apr 20 nicklas 277           JSONObject jsonProtocol = new JSONObject();
5891 07 Apr 20 nicklas 278           json.put("protocol", jsonProtocol);
5891 07 Apr 20 nicklas 279           jsonProtocol.put("RNATargetAmount", Annotationtype.RNA_TARGET_AMOUNT.getAnnotationValue(dc, libPlate));
5891 07 Apr 20 nicklas 280           jsonProtocol.put("RNATargetVolume", Annotationtype.RNA_TARGET_VOLUME.getAnnotationValue(dc, libPlate));
5891 07 Apr 20 nicklas 281           try
5891 07 Apr 20 nicklas 282           {
5891 07 Apr 20 nicklas 283             AnyToAny protocolLink = AnyToAny.getByName(dc, libPlate, "NormalizationProtocol");
5891 07 Apr 20 nicklas 284             Protocol protocol = (Protocol)protocolLink.getTo();
5891 07 Apr 20 nicklas 285             jsonProtocol.put("name", protocol.getName());
5891 07 Apr 20 nicklas 286           }
5891 07 Apr 20 nicklas 287           finally
5891 07 Apr 20 nicklas 288           {}
5891 07 Apr 20 nicklas 289         }
5891 07 Apr 20 nicklas 290         
1814 30 Jan 13 nicklas 291         ItemQuery<Extract> query = Extract.getQuery();
1894 04 Mar 13 nicklas 292         query.join(Hql.innerJoin(null, "bioWell", "bw", true));
1814 30 Jan 13 nicklas 293         query.join(Hql.innerJoin("bw", "bioPlate", "bp"));
1894 04 Mar 13 nicklas 294         query.restrict(Restrictions.eq(Hql.alias("bp"), Hql.entity(libPlate)));
1814 30 Jan 13 nicklas 295         query.order(Orders.asc(Hql.property("bw", "column")));
1814 30 Jan 13 nicklas 296         query.order(Orders.asc(Hql.property("bw", "row")));
1814 30 Jan 13 nicklas 297
1894 04 Mar 13 nicklas 298         List<Library> libs = Library.toList(query.list(dc));
1894 04 Mar 13 nicklas 299         
1894 04 Mar 13 nicklas 300         JSONArray jsonLibs = new JSONArray();
1894 04 Mar 13 nicklas 301         for (Library lib : libs)
1814 30 Jan 13 nicklas 302         {
1894 04 Mar 13 nicklas 303           lib.loadBioPlateLocation();
3760 19 Feb 16 nicklas 304           Rna rna = lib.getRna(dc, true);
3760 19 Feb 16 nicklas 305           lib.setAnnotation("specimen", rna.loadYellowLabelInfo(dc, manager));
3308 06 May 15 nicklas 306           if (loadDilutionInfo)
3308 06 May 15 nicklas 307           {
3308 06 May 15 nicklas 308             lib.loadAnnotations(dc, "DilutionConc", Annotationtype.DILUTION_CONC, null);
3832 07 Apr 16 nicklas 309             lib.loadAnnotations(dc, "DilutionVolume", Annotationtype.DILUTION_VOLUME, null);
3308 06 May 15 nicklas 310             lib.loadAnnotations(dc, "UseForQC", Annotationtype.USE_FOR_QC, null);
3308 06 May 15 nicklas 311             
3308 06 May 15 nicklas 312             boolean preNormalized = rna.isPreNormalized(dc);
3308 06 May 15 nicklas 313             rna.setAnnotation("preNormalized", preNormalized);
3308 06 May 15 nicklas 314             if (!preNormalized)
3308 06 May 15 nicklas 315             {
3308 06 May 15 nicklas 316               rna.loadBioPlateLocation();
3308 06 May 15 nicklas 317             }
6728 05 May 22 nicklas 318             rna.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
3308 06 May 15 nicklas 319             rna.loadAnnotations(dc, "NDConc", Annotationtype.ND_CONC, null);
6218 20 Apr 21 nicklas 320             rna.loadAnnotations(dc, "QubitConc", Annotationtype.QUBIT_CONC, null);
6218 20 Apr 21 nicklas 321             rna.coalesceInto("conc", "NDConc", "QubitConc");
3308 06 May 15 nicklas 322             
3308 06 May 15 nicklas 323             Float used = lib.getItem().getCreationEvent().getUsedQuantity(rna.getItem());
3308 06 May 15 nicklas 324             Float remain = rna.getItem().getRemainingQuantity();
3308 06 May 15 nicklas 325             rna.setAnnotation("usedQuantity", used);
3308 06 May 15 nicklas 326             if (used != null && remain != null)
3308 06 May 15 nicklas 327             {
3308 06 May 15 nicklas 328               rna.setAnnotation("remainingQuantity", remain+used);
3308 06 May 15 nicklas 329             }
3308 06 May 15 nicklas 330             lib.setAnnotation("rna", rna.asJSONObject());
3308 06 May 15 nicklas 331           }
3308 06 May 15 nicklas 332           
1894 04 Mar 13 nicklas 333           jsonLibs.add(lib.asJSONObject());
1814 30 Jan 13 nicklas 334         }
1894 04 Mar 13 nicklas 335
1894 04 Mar 13 nicklas 336         json.put("libraries", jsonLibs);
3308 06 May 15 nicklas 337         json.put("plate", jsonPlate);
1814 30 Jan 13 nicklas 338       }
1896 05 Mar 13 nicklas 339       else if ("GetConfigurationsForCaliperRunParametersExporter".equals(cmd))
1896 05 Mar 13 nicklas 340       {
1896 05 Mar 13 nicklas 341         /*
1896 05 Mar 13 nicklas 342           Get all configurations for the CaliperRunParametersExporter plugin
1896 05 Mar 13 nicklas 343         */
6333 15 Jun 21 nicklas 344         dc = sc.newDbControl(":Files for libprep");
1896 05 Mar 13 nicklas 345         PluginDefinition plugin = PluginDefinition.getByClassName(dc, CaliperLibPrepParametersExporter.class.getName());
1896 05 Mar 13 nicklas 346         ItemQuery<PluginConfiguration> query = plugin.getPluginConfigurations();
1896 05 Mar 13 nicklas 347         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
2344 09 Apr 14 nicklas 348         query.setItemPermission(Permission.USE);
1896 05 Mar 13 nicklas 349         query.order(Orders.asc(Hql.property("name")));
1896 05 Mar 13 nicklas 350         
1896 05 Mar 13 nicklas 351         JSONArray jsonConfigurations = new JSONArray();
1896 05 Mar 13 nicklas 352         for (PluginConfiguration p : query.list(dc))
1896 05 Mar 13 nicklas 353         {
1896 05 Mar 13 nicklas 354           JSONObject jsonConfiguration = new JSONObject();
1896 05 Mar 13 nicklas 355           jsonConfiguration.put("id", p.getId());
1896 05 Mar 13 nicklas 356           jsonConfiguration.put("name", p.getName());
1896 05 Mar 13 nicklas 357           jsonConfigurations.add(jsonConfiguration);
1896 05 Mar 13 nicklas 358         }
1896 05 Mar 13 nicklas 359         
1896 05 Mar 13 nicklas 360         json.put("configurations", jsonConfigurations);
1896 05 Mar 13 nicklas 361       }
1896 05 Mar 13 nicklas 362       else if ("ExportSampleNamesForCaliper".equals(cmd))
1896 05 Mar 13 nicklas 363       {
1896 05 Mar 13 nicklas 364         /*
1896 05 Mar 13 nicklas 365           Generate CSV file with sample names for the Caliper software
1896 05 Mar 13 nicklas 366         */
5887 02 Apr 20 nicklas 367         json = null; // No JSON output
1896 05 Mar 13 nicklas 368         int bioPlateId = Values.getInt(req.getParameter("bioPlateId"));
6333 15 Jun 21 nicklas 369         dc = sc.newDbControl(":Files for libprep");
1896 05 Mar 13 nicklas 370         BioPlate plate = BioPlate.getById(dc, bioPlateId);
1896 05 Mar 13 nicklas 371         
3665 14 Dec 15 nicklas 372         ValueConverter<BioWell, String> wellMapper = new WellCoordinateConverter();
1900 07 Mar 13 nicklas 373             
1896 05 Mar 13 nicklas 374         resp.setHeader("Content-Disposition", "attachment; filename=" + Path.makeSafeFilename(plate.getName(), "") + ".csv");
1896 05 Mar 13 nicklas 375         resp.setContentType("text/csv");
1896 05 Mar 13 nicklas 376         resp.setCharacterEncoding("UTF-8");
1896 05 Mar 13 nicklas 377         Writer out = resp.getWriter();
1896 05 Mar 13 nicklas 378         CaliperSampleNameExporter exporter = new CaliperSampleNameExporter();
1900 07 Mar 13 nicklas 379         exporter.exportSampleNames(dc, plate, wellMapper, out);
1900 07 Mar 13 nicklas 380   
1900 07 Mar 13 nicklas 381         out.flush();
1900 07 Mar 13 nicklas 382         out.close();
1900 07 Mar 13 nicklas 383       }
1900 07 Mar 13 nicklas 384       else if ("ExportSampleNamesForQubit".equals(cmd))
1900 07 Mar 13 nicklas 385       {
1900 07 Mar 13 nicklas 386         /*
1900 07 Mar 13 nicklas 387           Generate tab-separated file with sample names and locations
1900 07 Mar 13 nicklas 388         */
5887 02 Apr 20 nicklas 389         json = null; // No JSON output
1900 07 Mar 13 nicklas 390         int bioPlateId = Values.getInt(req.getParameter("bioPlateId"));
5297 13 Feb 19 nicklas 391         String fileFormat = Values.getString(req.getParameter("format"), "csv");
5297 13 Feb 19 nicklas 392         
6333 15 Jun 21 nicklas 393         dc = sc.newDbControl(":Files for libprep");
1900 07 Mar 13 nicklas 394         BioPlate plate = BioPlate.getById(dc, bioPlateId);
1900 07 Mar 13 nicklas 395         
5297 13 Feb 19 nicklas 396         if ("xlsx".equals(fileFormat))
5297 13 Feb 19 nicklas 397         {
5371 16 Apr 19 nicklas 398           resp.setContentType(XlsxToCsvUtil.XLSX_MIME_TYPE);
5297 13 Feb 19 nicklas 399         }
5297 13 Feb 19 nicklas 400         else
5297 13 Feb 19 nicklas 401         {
5298 13 Feb 19 nicklas 402           fileFormat = "csv";
5297 13 Feb 19 nicklas 403           resp.setContentType("text/csv");
5297 13 Feb 19 nicklas 404           resp.setCharacterEncoding("UTF-8");
5297 13 Feb 19 nicklas 405         }
5298 13 Feb 19 nicklas 406         resp.setHeader("Content-Disposition", "attachment; filename=" + Path.makeSafeFilename(plate.getName(), "") + "-qubit."+fileFormat);
5297 13 Feb 19 nicklas 407         
5297 13 Feb 19 nicklas 408         OutputStream out = resp.getOutputStream();
1900 07 Mar 13 nicklas 409         QubitSampleNameExporter exporter = new QubitSampleNameExporter();
5297 13 Feb 19 nicklas 410         exporter.exportSampleNames(dc, plate, out, fileFormat);
5297 13 Feb 19 nicklas 411                 
1896 05 Mar 13 nicklas 412         out.flush();
1896 05 Mar 13 nicklas 413         out.close();
1896 05 Mar 13 nicklas 414       }
1896 05 Mar 13 nicklas 415       else if ("ExportCaliperRunParameters".equals(cmd))
1896 05 Mar 13 nicklas 416       {
1896 05 Mar 13 nicklas 417         /*
1896 05 Mar 13 nicklas 418           Generate run parameter XML file for the Caliper software
1896 05 Mar 13 nicklas 419         */
5887 02 Apr 20 nicklas 420         json = null; // No JSON output
1896 05 Mar 13 nicklas 421         int bioPlateId = Values.getInt(req.getParameter("bioPlateId"));
1896 05 Mar 13 nicklas 422         int configurationId = Values.getInt(req.getParameter("configurationId"));
1896 05 Mar 13 nicklas 423         
6333 15 Jun 21 nicklas 424         dc = sc.newDbControl(":Files for libprep");
1896 05 Mar 13 nicklas 425         BioPlate plate = BioPlate.getById(dc, bioPlateId);
1896 05 Mar 13 nicklas 426         PluginConfiguration config = PluginConfiguration.getById(dc, configurationId);
1896 05 Mar 13 nicklas 427         ParameterValues parameters = config.getParameterValues(config.getParameterVersion());
3665 14 Dec 15 nicklas 428         ValueConverter<BioWell, String> wellMapper = new WellCoordinateConverter();        
1896 05 Mar 13 nicklas 429         resp.setHeader("Content-Disposition", "attachment; filename=" + Path.makeSafeFilename(plate.getName(), "") + ".xml");
1896 05 Mar 13 nicklas 430         resp.setContentType("application/xml");
1896 05 Mar 13 nicklas 431         resp.setCharacterEncoding("UTF-8");
1896 05 Mar 13 nicklas 432         Writer out = resp.getWriter();
1896 05 Mar 13 nicklas 433         
1896 05 Mar 13 nicklas 434         CaliperLibPrepParametersExporter exporter = new CaliperLibPrepParametersExporter();
1900 07 Mar 13 nicklas 435         exporter.exportRunParameters(dc, plate, wellMapper, parameters, out);
1896 05 Mar 13 nicklas 436         
1896 05 Mar 13 nicklas 437         out.flush();
1896 05 Mar 13 nicklas 438         out.close();
1896 05 Mar 13 nicklas 439       }
5888 03 Apr 20 nicklas 440       else if ("DownloadLabelsForExternalSequencing".equals(cmd))
5888 03 Apr 20 nicklas 441       {
5888 03 Apr 20 nicklas 442         json = null; // No JSON output
5888 03 Apr 20 nicklas 443         
5888 03 Apr 20 nicklas 444         int bioPlateId = Values.getInt(req.getParameter("bioPlateId"));
5888 03 Apr 20 nicklas 445         String format = Values.getString(req.getParameter("format"), "csv");
5888 03 Apr 20 nicklas 446         boolean includeAll = Values.getBoolean(req.getParameter("includeAll"));
5888 03 Apr 20 nicklas 447         
6333 15 Jun 21 nicklas 448         dc = sc.newDbControl(":Files for external sequencing");
5888 03 Apr 20 nicklas 449         BioPlate plate = BioPlate.getById(dc, bioPlateId);
5888 03 Apr 20 nicklas 450         
5888 03 Apr 20 nicklas 451         String baseFilename = plate.getName() + "-" + Reggie.CONVERTER_DATE_TO_STRING_WITH_SEPARATOR.convert(new Date());
5888 03 Apr 20 nicklas 452
5888 03 Apr 20 nicklas 453         TableWriter tw = null;
5888 03 Apr 20 nicklas 454         XlsxTableWriter xls = null;
5892 07 Apr 20 nicklas 455         StringWriter csv = null;
5888 03 Apr 20 nicklas 456         if ("xlsx".equals(format))
5888 03 Apr 20 nicklas 457         {
5888 03 Apr 20 nicklas 458           resp.setHeader("Content-Disposition", "attachment; filename="+baseFilename+".xlsx");
5888 03 Apr 20 nicklas 459           resp.setContentType(XlsxToCsvUtil.XLSX_MIME_TYPE);
5888 03 Apr 20 nicklas 460           xls = new XlsxTableWriter("Labels");
5888 03 Apr 20 nicklas 461           tw = xls;
5888 03 Apr 20 nicklas 462         }
5888 03 Apr 20 nicklas 463         else
5888 03 Apr 20 nicklas 464         {
5892 07 Apr 20 nicklas 465           format = "csv";
5888 03 Apr 20 nicklas 466           resp.setHeader("Content-Disposition", "attachment; filename="+baseFilename+".csv");
5888 03 Apr 20 nicklas 467           resp.setContentType("text/plain");
5888 03 Apr 20 nicklas 468           resp.setCharacterEncoding("UTF-8");
5892 07 Apr 20 nicklas 469           csv = new StringWriter();
5892 07 Apr 20 nicklas 470           tw = new TableWriter(csv);
5888 03 Apr 20 nicklas 471           // The LABEL header is only required in the CSV format
5888 03 Apr 20 nicklas 472           tw.tablePrintData("LABEL");
5888 03 Apr 20 nicklas 473         }
5892 07 Apr 20 nicklas 474         
5892 07 Apr 20 nicklas 475         File labelsFile = File.getByPath(dc, new Path(Reggie.EXTERNAL_LIB_PLATES_DIR+"/"+plate.getName()+"-Labels."+format, Path.Type.FILE), true);;
5892 07 Apr 20 nicklas 476         if (!labelsFile.isInDatabase()) dc.saveItem(labelsFile);
5892 07 Apr 20 nicklas 477         
5892 07 Apr 20 nicklas 478         AnyToAny labelsFileLink = AnyToAny.getNewOrExisting(dc, plate, "Labels", labelsFile, false);
5892 07 Apr 20 nicklas 479         if (!labelsFileLink.isInDatabase()) dc.saveItem(labelsFileLink);
5888 03 Apr 20 nicklas 480
5888 03 Apr 20 nicklas 481         ItemQuery<Extract> query = Extract.getQuery();
5888 03 Apr 20 nicklas 482         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
5888 03 Apr 20 nicklas 483         query.join(Hql.innerJoin(null, "bioWell", "bw", true));
5888 03 Apr 20 nicklas 484         query.join(Hql.innerJoin("bw", "bioPlate", "bp"));
5888 03 Apr 20 nicklas 485         query.restrict(Restrictions.eq(Hql.alias("bp"), Hql.entity(plate)));
5888 03 Apr 20 nicklas 486         query.order(Orders.asc(Hql.property("name")));
5888 03 Apr 20 nicklas 487
5888 03 Apr 20 nicklas 488         List<Library> libs = Library.toList(query.list(dc));
5888 03 Apr 20 nicklas 489         for (Library lib : libs)
5888 03 Apr 20 nicklas 490         {
5888 03 Apr 20 nicklas 491           Rna rna = lib.getRna(dc, true);
5888 03 Apr 20 nicklas 492           boolean preNorm = rna.isPreNormalized(dc);
5888 03 Apr 20 nicklas 493           if (!includeAll && preNorm) continue;
5888 03 Apr 20 nicklas 494           // We print the library name, unless the RNA is pre-normalized
5888 03 Apr 20 nicklas 495           tw.tablePrintData(preNorm ? rna.getName() : lib.getName());
5888 03 Apr 20 nicklas 496         }
5888 03 Apr 20 nicklas 497         tw.flush();
5888 03 Apr 20 nicklas 498
5892 07 Apr 20 nicklas 499         OutputStream out = labelsFile.getUploadStream(false);
5888 03 Apr 20 nicklas 500         if (xls != null) 
5888 03 Apr 20 nicklas 501         {
5892 07 Apr 20 nicklas 502           labelsFile.setMimeType(XlsxToCsvUtil.XLSX_MIME_TYPE);
5888 03 Apr 20 nicklas 503           xls.getSheet().setColumnWidth(0, 18*256);
5892 07 Apr 20 nicklas 504           xls.saveTo(out);
5888 03 Apr 20 nicklas 505           xls.close();
5888 03 Apr 20 nicklas 506         }
5892 07 Apr 20 nicklas 507         else if (csv != null)
5892 07 Apr 20 nicklas 508         {
5892 07 Apr 20 nicklas 509           labelsFile.setMimeType("text/plain");
5892 07 Apr 20 nicklas 510           labelsFile.setCharacterSet("UTF-8");
5892 07 Apr 20 nicklas 511           InputStream tmp = new ByteArrayInputStream(csv.toString().getBytes(StandardCharsets.UTF_8));
5892 07 Apr 20 nicklas 512           FileUtil.copy(tmp, out);
5892 07 Apr 20 nicklas 513         }
5892 07 Apr 20 nicklas 514         out.close();
5892 07 Apr 20 nicklas 515         dc.commit();
5892 07 Apr 20 nicklas 516         
5892 07 Apr 20 nicklas 517         out = resp.getOutputStream();
5892 07 Apr 20 nicklas 518         FileUtil.copy(labelsFile.getDownloadStream(0), out);
5892 07 Apr 20 nicklas 519         out.flush();
5892 07 Apr 20 nicklas 520         out.close();
5888 03 Apr 20 nicklas 521       }
5887 02 Apr 20 nicklas 522       else if ("GetExternalSequencingSampleSheet".equals(cmd))
5887 02 Apr 20 nicklas 523       {
5900 15 Apr 20 nicklas 524         json = null; // No JSON output
5900 15 Apr 20 nicklas 525         
5889 06 Apr 20 nicklas 526         int bioPlateId = Values.getInt(req.getParameter("bioPlateId"));
5889 06 Apr 20 nicklas 527         String templateName = req.getParameter("template");
5889 06 Apr 20 nicklas 528         String templateFile = null;
5892 07 Apr 20 nicklas 529         String templateSheet = null;
5889 06 Apr 20 nicklas 530         if ("ctg-rna".equals(templateName))
5889 06 Apr 20 nicklas 531         {
5889 06 Apr 20 nicklas 532           templateFile = "CTG_SampleSheet.xlsx";
5892 07 Apr 20 nicklas 533           templateSheet = "1";
5889 06 Apr 20 nicklas 534         }
5889 06 Apr 20 nicklas 535         
5889 06 Apr 20 nicklas 536         if (templateFile == null)
5889 06 Apr 20 nicklas 537         {
5900 15 Apr 20 nicklas 538           throw new ItemNotFoundException("Could not find a template file for template ID: " + templateName);
5889 06 Apr 20 nicklas 539         }
5889 06 Apr 20 nicklas 540         
6333 15 Jun 21 nicklas 541         dc = sc.newDbControl(":Files for external sequencing");
5887 02 Apr 20 nicklas 542         BioPlate plate = BioPlate.getById(dc, bioPlateId);
5897 15 Apr 20 nicklas 543         /*
5891 07 Apr 20 nicklas 544         Float targetAmount = (Float)Annotationtype.RNA_TARGET_AMOUNT.getAnnotationValue(dc, plate);
5891 07 Apr 20 nicklas 545         Float targetVolume = (Float)Annotationtype.RNA_TARGET_VOLUME.getAnnotationValue(dc, plate);
5891 07 Apr 20 nicklas 546         Float targetConc = targetAmount != null && targetVolume != null ?
5891 07 Apr 20 nicklas 547             targetAmount * 1000 / targetVolume : null;
5897 15 Apr 20 nicklas 548         */
5889 06 Apr 20 nicklas 549
5889 06 Apr 20 nicklas 550         File template = File.getByPath(dc, new Path(Reggie.TEMPLATES_DIR + "/" + templateFile, Path.Type.FILE), false);
5892 07 Apr 20 nicklas 551         File copy = File.getByPath(dc, new Path(Reggie.EXTERNAL_LIB_PLATES_DIR+"/"+plate.getName()+"-SampleSheet.xlsx", Path.Type.FILE), true);
5892 07 Apr 20 nicklas 552         copy.setMimeType(XlsxToCsvUtil.XLSX_MIME_TYPE);
5892 07 Apr 20 nicklas 553         if (!copy.isInDatabase()) dc.saveItem(copy);
5887 02 Apr 20 nicklas 554         
5892 07 Apr 20 nicklas 555         AnyToAny sampleSheetLink = AnyToAny.getNewOrExisting(dc, plate, "SampleSheet", copy, false);
5892 07 Apr 20 nicklas 556         if (!sampleSheetLink.isInDatabase()) dc.saveItem(sampleSheetLink);
5892 07 Apr 20 nicklas 557         
5887 02 Apr 20 nicklas 558         resp.setHeader("Content-Disposition", "attachment; filename=" + Path.makeSafeFilename(plate.getName(), "") + ".xlsx");
5887 02 Apr 20 nicklas 559         resp.setContentType(XlsxToCsvUtil.XLSX_MIME_TYPE);
5887 02 Apr 20 nicklas 560         
5887 02 Apr 20 nicklas 561         XlsxToCsvUtil util = new XlsxToCsvUtil();
5887 02 Apr 20 nicklas 562         util.readWorkbook(template.getDownloadStream(0));
5887 02 Apr 20 nicklas 563         Workbook xlsx = util.getWorkbook();
5889 06 Apr 20 nicklas 564         CellStyleCreator styleCreator = new CellStyleCreator(xlsx);
5889 06 Apr 20 nicklas 565         CellStyle oneDecimal = styleCreator.getCellStyle("0.0");
5887 02 Apr 20 nicklas 566         
5892 07 Apr 20 nicklas 567         Sheet sheet = xlsx.getSheet(templateSheet);
5887 02 Apr 20 nicklas 568         
5887 02 Apr 20 nicklas 569         ItemQuery<Extract> query = Extract.getQuery();
5887 02 Apr 20 nicklas 570         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
5887 02 Apr 20 nicklas 571         query.join(Hql.innerJoin(null, "bioWell", "bw", true));
5887 02 Apr 20 nicklas 572         query.join(Hql.innerJoin("bw", "bioPlate", "bp"));
5887 02 Apr 20 nicklas 573         query.restrict(Restrictions.eq(Hql.alias("bp"), Hql.entity(plate)));
5887 02 Apr 20 nicklas 574         query.order(Orders.asc(Hql.property("bw", "column")));
5887 02 Apr 20 nicklas 575         query.order(Orders.asc(Hql.property("bw", "row")));
5889 06 Apr 20 nicklas 576
5889 06 Apr 20 nicklas 577         List<Library> libs = Library.toList(query.list(dc));
5887 02 Apr 20 nicklas 578         int rowNum = 24;
5889 06 Apr 20 nicklas 579         for (Library lib : libs)
5887 02 Apr 20 nicklas 580         {
5889 06 Apr 20 nicklas 581           BioWell well = lib.getItem().getBioWell();
5889 06 Apr 20 nicklas 582           Rna rnaOrPreNorm = lib.getRna(dc, true);
5889 06 Apr 20 nicklas 583           boolean preNorm = rnaOrPreNorm.isPreNormalized(dc);
5889 06 Apr 20 nicklas 584           Rna rna = rnaOrPreNorm.getRnaIfPrenormalized(dc);
5889 06 Apr 20 nicklas 585           
5887 02 Apr 20 nicklas 586           Row row = sheet.getRow(rowNum);
5889 06 Apr 20 nicklas 587           row.getCell(1).setCellValue(Integer.toString(lib.getId()));  // Sample ID  (ID from the Library item; used by importer)
5889 06 Apr 20 nicklas 588           row.getCell(2).setCellValue(preNorm ? rnaOrPreNorm.getName() : lib.getName());  // Name (we try to set it to what is used on tube labels!)
5889 06 Apr 20 nicklas 589
5889 06 Apr 20 nicklas 590           row.getCell(5).setCellValue(well.getCoordinate());  // Plate position
5889 06 Apr 20 nicklas 591
6218 20 Apr 21 nicklas 592           // NanoDrop/Qubit measurements
5889 06 Apr 20 nicklas 593           Float ndConc = (Float)Annotationtype.ND_CONC.getAnnotationValue(dc, rna.getItem());
6218 20 Apr 21 nicklas 594           Float qubitConc = (Float)Annotationtype.QUBIT_CONC.getAnnotationValue(dc, rna.getItem());
6218 20 Apr 21 nicklas 595           setNumericCell(row.getCell(6), ndConc != null ? ndConc : qubitConc, oneDecimal); // ND Stock conc or Qubit
5889 06 Apr 20 nicklas 596           Float nd260by280 = (Float)Annotationtype.ND_260_BY_280.getAnnotationValue(dc, rna.getItem());
5889 06 Apr 20 nicklas 597           setNumericCell(row.getCell(7), nd260by280, oneDecimal);  // ND 260/280
5889 06 Apr 20 nicklas 598           Float nd260by230 = (Float)Annotationtype.ND_260_BY_230.getAnnotationValue(dc, rna.getItem());
5889 06 Apr 20 nicklas 599           setNumericCell(row.getCell(8), nd260by230, oneDecimal);  // ND 260/230
5889 06 Apr 20 nicklas 600
5889 06 Apr 20 nicklas 601           // RNAQC RIN or RQS
5889 06 Apr 20 nicklas 602           Float rinOrRqs = rna.loadRnaQc(dc, null);
5889 06 Apr 20 nicklas 603           setNumericCell(row.getCell(9), rinOrRqs, oneDecimal);  // RIN/RQN/RQS
5889 06 Apr 20 nicklas 604           
5897 15 Apr 20 nicklas 605           Float deliveryConc = (Float)Annotationtype.DILUTION_CONC.getAnnotationValue(dc, lib.getItem());
5897 15 Apr 20 nicklas 606           Float deliveryVolume = (Float)Annotationtype.DILUTION_VOLUME.getAnnotationValue(dc, lib.getItem());
5891 07 Apr 20 nicklas 607           
5897 15 Apr 20 nicklas 608           // NOTE! This should be the calculated values after applying the selected
5897 15 Apr 20 nicklas 609           // normalization protocol to the measured NanoDrop concencentation
5897 15 Apr 20 nicklas 610           // Calculatation are made by the design wizard and stored as DILUTION_* annotations
5897 15 Apr 20 nicklas 611           setNumericCell(row.getCell(11), deliveryConc, oneDecimal); // Qubit delivery conc. (ng/µl) 
5897 15 Apr 20 nicklas 612           setNumericCell(row.getCell(12), deliveryVolume, oneDecimal); // Delivery volume (µl)
5897 15 Apr 20 nicklas 613           
5887 02 Apr 20 nicklas 614           rowNum++;
5887 02 Apr 20 nicklas 615         }
5887 02 Apr 20 nicklas 616         
5892 07 Apr 20 nicklas 617         OutputStream out = copy.getUploadStream(false);
5887 02 Apr 20 nicklas 618         xlsx.write(out);
5887 02 Apr 20 nicklas 619         out.flush();
5887 02 Apr 20 nicklas 620         out.close();
5892 07 Apr 20 nicklas 621         dc.commit();
5892 07 Apr 20 nicklas 622         
5892 07 Apr 20 nicklas 623         out = resp.getOutputStream();
5892 07 Apr 20 nicklas 624         xlsx.write(out);
5892 07 Apr 20 nicklas 625         out.flush();
5892 07 Apr 20 nicklas 626         out.close();
5887 02 Apr 20 nicklas 627         xlsx.close();
5887 02 Apr 20 nicklas 628       }
5887 02 Apr 20 nicklas 629
1806 22 Jan 13 nicklas 630     }
1806 22 Jan 13 nicklas 631     catch (Throwable t)
1806 22 Jan 13 nicklas 632     {
1806 22 Jan 13 nicklas 633       t.printStackTrace();
5887 02 Apr 20 nicklas 634       if (json != null)
5887 02 Apr 20 nicklas 635       {
5887 02 Apr 20 nicklas 636         json.clear();
5887 02 Apr 20 nicklas 637         json.put("status", "error");
5887 02 Apr 20 nicklas 638         json.put("message", t.getMessage());
5887 02 Apr 20 nicklas 639         json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
5887 02 Apr 20 nicklas 640       }
5900 15 Apr 20 nicklas 641       else
5900 15 Apr 20 nicklas 642       {
5900 15 Apr 20 nicklas 643         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getMessage());
5900 15 Apr 20 nicklas 644       }
1806 22 Jan 13 nicklas 645     }
1806 22 Jan 13 nicklas 646     finally
1806 22 Jan 13 nicklas 647     {
1806 22 Jan 13 nicklas 648       if (dc != null) dc.close();
5887 02 Apr 20 nicklas 649       if (json != null)
5887 02 Apr 20 nicklas 650       {
5887 02 Apr 20 nicklas 651         json.writeJSONString(resp.getWriter());
5887 02 Apr 20 nicklas 652       }
1806 22 Jan 13 nicklas 653     }
1806 22 Jan 13 nicklas 654     
1806 22 Jan 13 nicklas 655   }
1806 22 Jan 13 nicklas 656
5889 06 Apr 20 nicklas 657   private void setNumericCell(Cell cell, Float f, CellStyle format)
5889 06 Apr 20 nicklas 658   {
5889 06 Apr 20 nicklas 659     if (f == null) return;
5889 06 Apr 20 nicklas 660     cell.setCellValue(f);
5889 06 Apr 20 nicklas 661     cell.getCellStyle().setDataFormat(format.getDataFormat());
5889 06 Apr 20 nicklas 662   }
5889 06 Apr 20 nicklas 663   
1806 22 Jan 13 nicklas 664   @Override
1806 22 Jan 13 nicklas 665   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
1806 22 Jan 13 nicklas 666     throws ServletException, IOException 
1806 22 Jan 13 nicklas 667   {
1806 22 Jan 13 nicklas 668     String cmd = req.getParameter("cmd");
2598 22 Aug 14 nicklas 669     JsonUtil.setJsonResponseHeaders(resp);
1806 22 Jan 13 nicklas 670     
1806 22 Jan 13 nicklas 671     JSONObject json = new JSONObject();
1806 22 Jan 13 nicklas 672     json.put("status", "ok");
1806 22 Jan 13 nicklas 673     
1806 22 Jan 13 nicklas 674     JSONArray jsonMessages = new JSONArray();
1806 22 Jan 13 nicklas 675   
3975 26 May 16 nicklas 676     final SessionControl sc = Reggie.getSessionControl(req);
1806 22 Jan 13 nicklas 677     DbControl dc = null;
1806 22 Jan 13 nicklas 678     try
1806 22 Jan 13 nicklas 679     {
1810 28 Jan 13 nicklas 680       if ("CreateBarcodedLibraries".equals(cmd))
1810 28 Jan 13 nicklas 681       {
6333 15 Jun 21 nicklas 682         dc = sc.newDbControl(":Assign barcodes to cDNA plate ");
2161 09 Dec 13 nicklas 683
2161 09 Dec 13 nicklas 684         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.LIBRARY_PREP, ReggieRole.ADMINISTRATOR);
2161 09 Dec 13 nicklas 685
3752 17 Feb 16 nicklas 686         JSONObject jsonReq = JsonUtil.parseRequest(req);
1810 28 Jan 13 nicklas 687         JSONObject jsonPlate = (JSONObject)jsonReq.get("bioplate");
1810 28 Jan 13 nicklas 688         JSONArray jsonWells = (JSONArray)jsonPlate.get("wells");
1810 28 Jan 13 nicklas 689         
1908 19 Mar 13 nicklas 690         // Load the CDNA bioplate and store comments and annotations
1810 28 Jan 13 nicklas 691         Number cdnaPlateId = (Number)jsonPlate.get("id");
4888 05 Jul 18 nicklas 692         ReactionPlate cdnaReactionPlate = ReactionPlate.getById(dc, cdnaPlateId.intValue(), BioplateType.CDNA);
4888 05 Jul 18 nicklas 693         BioPlate cDnaPlate = cdnaReactionPlate.getBioPlate();
1814 30 Jan 13 nicklas 694         Annotationtype.POOL_SCHEMA.setAnnotationValue(dc, cDnaPlate, jsonPlate.get("poolSchema"));
1814 30 Jan 13 nicklas 695         Annotationtype.BARCODE_VARIANT.setAnnotationValue(dc, cDnaPlate, jsonPlate.get("barcodeVariant"));
1810 28 Jan 13 nicklas 696         
1908 19 Mar 13 nicklas 697         // Create a child LibPlate -- copy pooling annotations to it
4888 05 Jul 18 nicklas 698         String libPlateName = cdnaReactionPlate.getChildPlateName(dc, BioplateType.LIBRARY);
1893 04 Mar 13 nicklas 699         BioPlate libPlate = BioPlate.getNew(dc, BioplateType.LIBRARY.getPlateGeometry(dc), BioplateType.LIBRARY.load(dc));
4888 05 Jul 18 nicklas 700         libPlate.setName(libPlateName);
1932 17 Apr 13 nicklas 701         libPlate.setDescription((String)jsonPlate.get("comments"));
1893 04 Mar 13 nicklas 702         Annotationtype.POOL_SCHEMA.setAnnotationValue(dc, libPlate, jsonPlate.get("poolSchema"));
1893 04 Mar 13 nicklas 703         Annotationtype.BARCODE_VARIANT.setAnnotationValue(dc, libPlate, jsonPlate.get("barcodeVariant"));
1893 04 Mar 13 nicklas 704         dc.saveItem(libPlate);
1893 04 Mar 13 nicklas 705         
1810 28 Jan 13 nicklas 706         ItemSubtype libType = Subtype.LIBRARY.load(dc);
1810 28 Jan 13 nicklas 707         Map<Extract, Integer> childCount = new HashMap<Extract, Integer>();
1810 28 Jan 13 nicklas 708         
1810 28 Jan 13 nicklas 709         for (int i = 0; i < jsonWells.size(); i++)
1810 28 Jan 13 nicklas 710         {
1810 28 Jan 13 nicklas 711           JSONObject jsonWell = (JSONObject)jsonWells.get(i);
1810 28 Jan 13 nicklas 712           JSONObject jsonCDna = (JSONObject)jsonWell.get("cdna");
1810 28 Jan 13 nicklas 713           JSONObject jsonBarcode = (JSONObject)jsonCDna.get("barcode");
1810 28 Jan 13 nicklas 714           
1810 28 Jan 13 nicklas 715           Number row = (Number)jsonWell.get("row");
1810 28 Jan 13 nicklas 716           Number col = (Number)jsonWell.get("column");
1908 19 Mar 13 nicklas 717           Number cdnaId = (Number)jsonCDna.get("id");
1810 28 Jan 13 nicklas 718           
1908 19 Mar 13 nicklas 719           // Load CDNA for each well and create a new child Library item
4885 04 Jul 18 nicklas 720           CDna cdna = CDna.getById(dc, cdnaId.intValue());
4885 04 Jul 18 nicklas 721           Extract c = cdna.getItem();
4885 04 Jul 18 nicklas 722
4885 04 Jul 18 nicklas 723           String libName = cdna.getNextLibraryName(dc);
1908 19 Mar 13 nicklas 724           Extract lib = Extract.getNew(dc);
1810 28 Jan 13 nicklas 725           lib.setItemSubtype(libType);
4885 04 Jul 18 nicklas 726           lib.setName(libName);
5436 17 May 19 nicklas 727           Pipeline.RNA_SEQ.setAnnotation(dc, lib);
1810 28 Jan 13 nicklas 728           lib.setTag(Tag.getById(dc, ((Number)jsonBarcode.get("id")).intValue()));
4885 04 Jul 18 nicklas 729           BioMaterialEventSource evtSrc = lib.getCreationEvent().setSource(c);
5791 16 Dec 19 nicklas 730           DoNotUse.copyDoNotUseAnnotations(dc, c, lib, false);
4885 04 Jul 18 nicklas 731           lib.setBioWell(libPlate.getBioWell(c.getBioWell().getPlateCoordinate()));
1810 28 Jan 13 nicklas 732           dc.saveItem(lib);
1810 28 Jan 13 nicklas 733         }
5384 26 Apr 19 nicklas 734
1810 28 Jan 13 nicklas 735         dc.commit();
1893 04 Mar 13 nicklas 736         jsonMessages.add("Created " + libPlate.getName() + " with " + jsonWells.size() + " barcoded libary child items");
5382 24 Apr 19 nicklas 737         
1810 28 Jan 13 nicklas 738       }
2221 10 Feb 14 nicklas 739       else if ("GenerateFakeQubitFile".equals(cmd))
2221 10 Feb 14 nicklas 740       {
2221 10 Feb 14 nicklas 741         int libPlateId = Values.getInt(req.getParameter("bioplate"));
2221 10 Feb 14 nicklas 742         String dir = req.getParameter("path");
2221 10 Feb 14 nicklas 743         
6333 15 Jun 21 nicklas 744         dc = sc.newDbControl(":Library registration");
2221 10 Feb 14 nicklas 745         BioPlate libPlate = BioPlate.getById(dc, libPlateId);
2221 10 Feb 14 nicklas 746         
2221 10 Feb 14 nicklas 747         String fileName = Path.makeSafeFilename(libPlate.getName(), "") + "-qubit-FAKE-" + Application.generateRandomId(3) +".csv";
2221 10 Feb 14 nicklas 748         
2221 10 Feb 14 nicklas 749         Path path = new Path(dir + "/"+fileName, Path.Type.FILE);
2221 10 Feb 14 nicklas 750         File qubitFile = File.getByPath(dc, path, true);
2221 10 Feb 14 nicklas 751         qubitFile.setItemSubtype(Subtype.QUBIT_CSV.get(dc));
2221 10 Feb 14 nicklas 752         qubitFile.setMimeType("text/csv");
2221 10 Feb 14 nicklas 753         dc.saveItem(qubitFile);
2221 10 Feb 14 nicklas 754         
2221 10 Feb 14 nicklas 755         TableWriter out = new TableWriter(new OutputStreamWriter(qubitFile.getUploadStream(false), "UTF-8"));
2221 10 Feb 14 nicklas 756         out.setDataSeparator("\t"); // Tab-separated file
2221 10 Feb 14 nicklas 757         out.setNullValue("");
2221 10 Feb 14 nicklas 758         // Get rid of "bad" characters (comma, tab, newline, etc.)
2221 10 Feb 14 nicklas 759         out.setEncoder(new CsvEncoderDecoder());
2221 10 Feb 14 nicklas 760         
2221 10 Feb 14 nicklas 761         // Header line
2221 10 Feb 14 nicklas 762         out.tablePrintData("Well", "Library name", "Qubit ng/ml", "After SpeedVac");
2221 10 Feb 14 nicklas 763         
2221 10 Feb 14 nicklas 764         //Query to get all non-empty wells on the plate
2221 10 Feb 14 nicklas 765         ItemQuery<BioWell> query = libPlate.getBioWells();
2221 10 Feb 14 nicklas 766         // Load only non-empty wells
2221 10 Feb 14 nicklas 767         query.join(Hql.innerJoin(null, "bioMaterial", "bm", true));
2825 16 Oct 14 nicklas 768         query.order(Orders.asc(Hql.property("column")));
2221 10 Feb 14 nicklas 769         query.order(Orders.asc(Hql.property("row")));
2221 10 Feb 14 nicklas 770
2221 10 Feb 14 nicklas 771         Object[] data = new Object[4];
2221 10 Feb 14 nicklas 772         Iterator<BioWell> it = query.iterate(dc);
2825 16 Oct 14 nicklas 773         int lastCol = -1;
2825 16 Oct 14 nicklas 774         int lastRow = libPlate.getRows() - 1;
2221 10 Feb 14 nicklas 775         while (it.hasNext())
2221 10 Feb 14 nicklas 776         {
2221 10 Feb 14 nicklas 777           BioWell well = it.next();
2221 10 Feb 14 nicklas 778           BioMaterial bm = null;
2825 16 Oct 14 nicklas 779           if (lastCol != -1 && lastCol != well.getColumn())
2825 16 Oct 14 nicklas 780           {
2825 16 Oct 14 nicklas 781             out.tablePrintData("#");
2825 16 Oct 14 nicklas 782           }
2825 16 Oct 14 nicklas 783           lastCol = well.getColumn();
2221 10 Feb 14 nicklas 784           try
2221 10 Feb 14 nicklas 785           {
2221 10 Feb 14 nicklas 786             bm = well.getBioMaterial();
2221 10 Feb 14 nicklas 787             data[0] = well.getCoordinate();
2221 10 Feb 14 nicklas 788             data[1] = bm.getName();
2825 16 Oct 14 nicklas 789             data[2] = well.getRow() == lastRow ? "" : (int)(50+Math.random()*3500); // Between 50 and 3500 ng/µl
2221 10 Feb 14 nicklas 790             out.tablePrintData(data);
2221 10 Feb 14 nicklas 791           }
2221 10 Feb 14 nicklas 792           catch (PermissionDeniedException ex)
2221 10 Feb 14 nicklas 793           {}
2221 10 Feb 14 nicklas 794         }
2221 10 Feb 14 nicklas 795         out.flush();
2221 10 Feb 14 nicklas 796         out.close();
2221 10 Feb 14 nicklas 797         
2221 10 Feb 14 nicklas 798         dc.commit();
2221 10 Feb 14 nicklas 799         
2221 10 Feb 14 nicklas 800         JSONObject jsonFile = new JSONObject();
2221 10 Feb 14 nicklas 801         jsonFile.put("id", qubitFile.getId());
2221 10 Feb 14 nicklas 802         jsonFile.put("path", path.toString());
2221 10 Feb 14 nicklas 803         json.put("file", jsonFile);
2221 10 Feb 14 nicklas 804       }
2221 10 Feb 14 nicklas 805       else if ("GenerateFakeCaliperFile".equals(cmd))
2221 10 Feb 14 nicklas 806       {
2221 10 Feb 14 nicklas 807         int libPlateId = Values.getInt(req.getParameter("bioplate"));
2221 10 Feb 14 nicklas 808         String dir = req.getParameter("path");
6333 15 Jun 21 nicklas 809         dc = sc.newDbControl(":Library registration");
2221 10 Feb 14 nicklas 810         
2221 10 Feb 14 nicklas 811         BioPlate libPlate = BioPlate.getById(dc, libPlateId);
2221 10 Feb 14 nicklas 812         
2221 10 Feb 14 nicklas 813         String fileName = Path.makeSafeFilename(libPlate.getName(), "") + "-WellTable-FAKE-" + Application.generateRandomId(3) +".csv";
2221 10 Feb 14 nicklas 814         
2221 10 Feb 14 nicklas 815         Path path = new Path(dir + "/"+fileName, Path.Type.FILE);
2221 10 Feb 14 nicklas 816         File caliperFile = File.getByPath(dc, path, true);
2221 10 Feb 14 nicklas 817         caliperFile.setItemSubtype(Subtype.CALIPER_WELL_TABLE.get(dc));
2221 10 Feb 14 nicklas 818         caliperFile.setMimeType("text/csv");
2221 10 Feb 14 nicklas 819         dc.saveItem(caliperFile);
2221 10 Feb 14 nicklas 820         
2221 10 Feb 14 nicklas 821         TableWriter out = new TableWriter(new OutputStreamWriter(caliperFile.getUploadStream(false), "UTF-8"));
2221 10 Feb 14 nicklas 822         out.setDataSeparator(","); // CSV file
2221 10 Feb 14 nicklas 823         out.setNullValue("");
2221 10 Feb 14 nicklas 824         // Get rid of "bad" characters (comma, tab, newline, etc.)
2221 10 Feb 14 nicklas 825         out.setEncoder(new CsvEncoderDecoder());
2221 10 Feb 14 nicklas 826         
2221 10 Feb 14 nicklas 827         // Header line
2454 23 May 14 nicklas 828         out.tablePrintData("Plate Name", "Well Label", "Sample Name", "Peak Count", "Total Conc. (ng/ul)", "Region[180-600] Size [BP]", "Region[180-600] Molarity (nmol/l)", "Region[120-140] Size [BP]", "Region[120-140] Molarity (nmol/l)");
2221 10 Feb 14 nicklas 829         
2221 10 Feb 14 nicklas 830         //Query to get all non-empty wells on the plate
2221 10 Feb 14 nicklas 831         ItemQuery<BioWell> query = libPlate.getBioWells();
2221 10 Feb 14 nicklas 832         // Load only non-empty wells
2221 10 Feb 14 nicklas 833         query.join(Hql.innerJoin(null, "bioMaterial", "bm", true));
2221 10 Feb 14 nicklas 834         query.order(Orders.asc(Hql.property("row")));
2221 10 Feb 14 nicklas 835         query.order(Orders.asc(Hql.property("column")));
2221 10 Feb 14 nicklas 836
2454 23 May 14 nicklas 837         Object[] data = new Object[9];
2221 10 Feb 14 nicklas 838         data[0] = libPlate.getName() + "_" + Reggie.CONVERTER_DATE_TO_STRING.convert(new Date());
2221 10 Feb 14 nicklas 839         Iterator<BioWell> it = query.iterate(dc);
2825 16 Oct 14 nicklas 840         int lastRow = libPlate.getRows() - 1;
2221 10 Feb 14 nicklas 841         while (it.hasNext())
2221 10 Feb 14 nicklas 842         {
2221 10 Feb 14 nicklas 843           BioWell well = it.next();
2221 10 Feb 14 nicklas 844           BioMaterial bm = null;
2825 16 Oct 14 nicklas 845           if (well.getRow() == lastRow) continue;
2221 10 Feb 14 nicklas 846           try
2221 10 Feb 14 nicklas 847           {
2221 10 Feb 14 nicklas 848             bm = well.getBioMaterial();
2221 10 Feb 14 nicklas 849             data[1] = well.getCoordinate();
2825 16 Oct 14 nicklas 850             data[2] = well.getCoordinate().equals("A11") ? well.getCoordinate() : bm.getName();
2221 10 Feb 14 nicklas 851             data[3] = 0;
2221 10 Feb 14 nicklas 852             data[4] = 0;
2454 23 May 14 nicklas 853             data[5] = (250+Math.random()*300); // Between 250 and 550 base pairs (CA_Size)
2454 23 May 14 nicklas 854             data[6] = (0.5+Math.random()*2.5); // Between 0.5 and 3.0  (CA_Molarity)
2454 23 May 14 nicklas 855             data[7] = (125+Math.random()*10); // Between 125 and 135 base pairs (CA_Size_Adpt)
2454 23 May 14 nicklas 856             data[8] = (0.2+Math.random()*1.3); // Between 0.2 and 1.5  (CA_Molarity_Adpt)
2221 10 Feb 14 nicklas 857             out.tablePrintData(data);
2221 10 Feb 14 nicklas 858           }
2221 10 Feb 14 nicklas 859           catch (PermissionDeniedException ex)
2221 10 Feb 14 nicklas 860           {}
2221 10 Feb 14 nicklas 861         }
2221 10 Feb 14 nicklas 862         out.flush();
2221 10 Feb 14 nicklas 863         out.close();
2221 10 Feb 14 nicklas 864         
2221 10 Feb 14 nicklas 865         dc.commit();
2221 10 Feb 14 nicklas 866         
2221 10 Feb 14 nicklas 867         JSONObject jsonFile = new JSONObject();
2221 10 Feb 14 nicklas 868         jsonFile.put("id", caliperFile.getId());
2221 10 Feb 14 nicklas 869         jsonFile.put("path", path.toString());
2221 10 Feb 14 nicklas 870         json.put("file", jsonFile);
2221 10 Feb 14 nicklas 871       }
3834 11 Apr 16 nicklas 872       else if ("PreValidateQubitCsv".equals(cmd))
3834 11 Apr 16 nicklas 873       {
3834 11 Apr 16 nicklas 874         int libPlateId = Values.getInt(req.getParameter("bioplate"));
3834 11 Apr 16 nicklas 875         String qubitPath = Values.getStringOrNull(req.getParameter("qubit"));
3834 11 Apr 16 nicklas 876         
6333 15 Jun 21 nicklas 877         dc = sc.newDbControl(":Library registration");
3834 11 Apr 16 nicklas 878         File qubitCsv = File.getByPath(dc, new Path(qubitPath, Path.Type.FILE), false);
3834 11 Apr 16 nicklas 879         AnnotationType qubitConcType = Annotationtype.QUBIT_CONC.load(dc);
3834 11 Apr 16 nicklas 880         
3834 11 Apr 16 nicklas 881         QubitPlateImporter qpi = new QubitPlateImporter();
3835 11 Apr 16 nicklas 882         qpi.setAnnotationMapping("Qubit ng/ml", qubitConcType, new FactorValueConverter(0.001f, new RequiredValueConverter<String>("is missing value for 'Qubit ng/µl'")));
3834 11 Apr 16 nicklas 883         qpi.setBioPlate(BioPlate.getById(dc, libPlateId));
3834 11 Apr 16 nicklas 884         qpi.setAllowMatchAgainstLocation(true); // Allow a few lines to have location coordinates instead of lib name
3834 11 Apr 16 nicklas 885         
3834 11 Apr 16 nicklas 886         JSONObject jsonQubit = new JSONObject();
5303 15 Feb 19 nicklas 887         InputStream csv = null;
5303 15 Feb 19 nicklas 888         boolean fileIsValid = false;
5303 15 Feb 19 nicklas 889         try
5303 15 Feb 19 nicklas 890         {
5372 16 Apr 19 nicklas 891           csv = qubitCsv.getDownloadStream(0);
5303 15 Feb 19 nicklas 892           fileIsValid = qpi.doImport(dc, csv, true, qubitCsv.getName());
5303 15 Feb 19 nicklas 893         }
5303 15 Feb 19 nicklas 894         finally
5303 15 Feb 19 nicklas 895         {
5303 15 Feb 19 nicklas 896           FileUtil.close(csv);
5303 15 Feb 19 nicklas 897         }
3834 11 Apr 16 nicklas 898         
3834 11 Apr 16 nicklas 899         jsonQubit.put("valid", fileIsValid);
3834 11 Apr 16 nicklas 900         jsonQubit.put("warnings", qpi.getWarningMessages().size());
3834 11 Apr 16 nicklas 901         jsonQubit.put("errors", qpi.getErrorMessages().size());
3834 11 Apr 16 nicklas 902         json.put("qubit", jsonQubit);
3834 11 Apr 16 nicklas 903         
3834 11 Apr 16 nicklas 904         if (fileIsValid)
3834 11 Apr 16 nicklas 905         {
3834 11 Apr 16 nicklas 906           // The validation was ok -- but there may be some warnings.
3834 11 Apr 16 nicklas 907           jsonMessages.add("Found " + qpi.getNumImported() + " libraries");
3834 11 Apr 16 nicklas 908           if (qpi.hasWarning())
3834 11 Apr 16 nicklas 909           {
3834 11 Apr 16 nicklas 910             jsonMessages.addAll(qpi.getWarningMessages());
3834 11 Apr 16 nicklas 911           }
3834 11 Apr 16 nicklas 912         }
3834 11 Apr 16 nicklas 913         else
3834 11 Apr 16 nicklas 914         {
3834 11 Apr 16 nicklas 915           jsonMessages.addAll(qpi.getErrorMessages());
3834 11 Apr 16 nicklas 916           jsonMessages.addAll(qpi.getExternalErrorMessages());
3834 11 Apr 16 nicklas 917           if (qpi.hasWarning())
3834 11 Apr 16 nicklas 918           {
3834 11 Apr 16 nicklas 919             jsonMessages.addAll(qpi.getWarningMessages());
3834 11 Apr 16 nicklas 920           }
3834 11 Apr 16 nicklas 921         }
3834 11 Apr 16 nicklas 922
3834 11 Apr 16 nicklas 923       }      
1908 19 Mar 13 nicklas 924       else if ("PreValidateCaliperWellTable".equals(cmd))
1908 19 Mar 13 nicklas 925       {
1963 07 May 13 nicklas 926         int libPlateId = Values.getInt(req.getParameter("bioplate"));
2675 17 Sep 14 nicklas 927         String csvPath = req.getParameter("csv");
2675 17 Sep 14 nicklas 928         String qubitPath = Values.getStringOrNull(req.getParameter("qubit"));
1908 19 Mar 13 nicklas 929         
6333 15 Jun 21 nicklas 930         dc = sc.newDbControl(":Library registration");
5303 15 Feb 19 nicklas 931         File wellTable = File.getByPath(dc, new Path(csvPath, Path.Type.FILE), false);
1966 08 May 13 nicklas 932         AnnotationType size = Annotationtype.CA_SIZE.load(dc);
2454 23 May 14 nicklas 933         AnnotationType molarity = Annotationtype.CA_MOLARITY.load(dc);
2454 23 May 14 nicklas 934         AnnotationType size_adpt = Annotationtype.CA_SIZE_ADPT.load(dc);
2454 23 May 14 nicklas 935         AnnotationType molarity_adpt = Annotationtype.CA_MOLARITY_ADPT.load(dc);
1908 19 Mar 13 nicklas 936         
5883 26 Mar 20 nicklas 937         CaliperPlateImporter cpi = new CaliperPlateImporter(BioplateType.LIBRARY.getPlateNamePrefix());
2960 19 Nov 14 nicklas 938         cpi.setAnnotationMapping("Region[180-600] Size [BP]", size, new RequiredValueConverter<String>("is missing value for Region[180-600] Size [BP]"));
3835 11 Apr 16 nicklas 939         cpi.setAnnotationMapping("Region[180-600] Molarity (nmol/l)", molarity, new FactorValueConverter(10f, new RequiredValueConverter<String>("is missing value for Region[180-600] Molarity (nmol/l)")));
2960 19 Nov 14 nicklas 940         cpi.setAnnotationMapping("Region[120-140] Size [BP]", size_adpt, new RequiredValueConverter<String>("is missing value for Region[120-140] Size [BP]"));
3835 11 Apr 16 nicklas 941         cpi.setAnnotationMapping("Region[120-140] Molarity (nmol/l)", molarity_adpt, new FactorValueConverter(10f, new RequiredValueConverter<String>("is missing value for Region[120-140] Molarity (nmol/l)")));
1963 07 May 13 nicklas 942         cpi.setBioPlate(BioPlate.getById(dc, libPlateId));
1963 07 May 13 nicklas 943         cpi.setAllowMatchAgainstLocation(true); // Allow a few lines to have location coordinates instead of lib name
1968 08 May 13 nicklas 944         
2675 17 Sep 14 nicklas 945         boolean fileIsValid = true;
2825 16 Oct 14 nicklas 946         JSONObject jsonQubit = new JSONObject();
2675 17 Sep 14 nicklas 947         if (qubitPath != null)
1968 08 May 13 nicklas 948         {
1968 08 May 13 nicklas 949           AnnotationType qubitConcType = Annotationtype.QUBIT_CONC.load(dc);
1968 08 May 13 nicklas 950           AnnotationType speedVacConcType = Annotationtype.QUBIT_CONC_AFTER_SPEEDVAC.load(dc);
2675 17 Sep 14 nicklas 951           File qubitCsv = File.getByPath(dc, new Path(qubitPath, Path.Type.FILE), false);
2675 17 Sep 14 nicklas 952           fileIsValid = addQubitFileLookups(cpi, qubitCsv, qubitConcType, speedVacConcType);
2675 17 Sep 14 nicklas 953           jsonQubit.put("valid", fileIsValid);
2675 17 Sep 14 nicklas 954           jsonQubit.put("warnings", cpi.getWarningMessages().size());
2675 17 Sep 14 nicklas 955           jsonQubit.put("errors", cpi.getErrorMessages().size());
2675 17 Sep 14 nicklas 956           json.put("qubit", jsonQubit);
1968 08 May 13 nicklas 957         }
1968 08 May 13 nicklas 958         
2675 17 Sep 14 nicklas 959         if (fileIsValid)
1908 19 Mar 13 nicklas 960         {
5303 15 Feb 19 nicklas 961           InputStream csv = null;
5303 15 Feb 19 nicklas 962           try
5303 15 Feb 19 nicklas 963           {
5303 15 Feb 19 nicklas 964             csv = wellTable.getDownloadStream(0);
5303 15 Feb 19 nicklas 965             fileIsValid = cpi.doImport(dc, csv, true, wellTable.getName());
5303 15 Feb 19 nicklas 966           }
5303 15 Feb 19 nicklas 967           finally
5303 15 Feb 19 nicklas 968           {
5303 15 Feb 19 nicklas 969             FileUtil.close(csv);
5303 15 Feb 19 nicklas 970           }
2675 17 Sep 14 nicklas 971           JSONObject jsonWelltable = new JSONObject();
2675 17 Sep 14 nicklas 972           jsonWelltable.put("valid", fileIsValid);
2675 17 Sep 14 nicklas 973           jsonWelltable.put("warnings", cpi.getWarningMessages().size());
2675 17 Sep 14 nicklas 974           jsonWelltable.put("errors", cpi.getErrorMessages().size());
2675 17 Sep 14 nicklas 975           json.put("welltable", jsonWelltable);
2825 16 Oct 14 nicklas 976           if (cpi.hasExternalError())
2825 16 Oct 14 nicklas 977           {
2825 16 Oct 14 nicklas 978             jsonQubit.put("valid", false);
2825 16 Oct 14 nicklas 979             jsonQubit.put("errors", cpi.getExternalErrorMessages().size());
2825 16 Oct 14 nicklas 980           }
2675 17 Sep 14 nicklas 981         }
2675 17 Sep 14 nicklas 982         
2675 17 Sep 14 nicklas 983         if (fileIsValid)
2675 17 Sep 14 nicklas 984         {
1963 07 May 13 nicklas 985           // The validation was ok -- but there may be some warnings.
2825 16 Oct 14 nicklas 986           jsonMessages.add("Found " + cpi.getNumImported() + " libraries");
1963 07 May 13 nicklas 987           if (cpi.hasWarning())
1963 07 May 13 nicklas 988           {
1963 07 May 13 nicklas 989             jsonMessages.addAll(cpi.getWarningMessages());
1963 07 May 13 nicklas 990           }
1908 19 Mar 13 nicklas 991         }
1908 19 Mar 13 nicklas 992         else
1908 19 Mar 13 nicklas 993         {
1908 19 Mar 13 nicklas 994           jsonMessages.addAll(cpi.getErrorMessages());
2825 16 Oct 14 nicklas 995           jsonMessages.addAll(cpi.getExternalErrorMessages());
2675 17 Sep 14 nicklas 996           if (cpi.hasWarning())
2675 17 Sep 14 nicklas 997           {
2675 17 Sep 14 nicklas 998             jsonMessages.addAll(cpi.getWarningMessages());
2675 17 Sep 14 nicklas 999           }
2675 17 Sep 14 nicklas 1000         }
1908 19 Mar 13 nicklas 1001       }      
1895 05 Mar 13 nicklas 1002       else if ("ImportLibPrepQcResults".equals(cmd))
1895 05 Mar 13 nicklas 1003       {
6333 15 Jun 21 nicklas 1004         dc = sc.newDbControl(":Library registration QC");
2161 09 Dec 13 nicklas 1005
2161 09 Dec 13 nicklas 1006         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.LIBRARY_PREP, ReggieRole.ADMINISTRATOR);
2161 09 Dec 13 nicklas 1007
3752 17 Feb 16 nicklas 1008         JSONObject jsonReq = JsonUtil.parseRequest(req);
1895 05 Mar 13 nicklas 1009         Number bioPlateId = (Number)jsonReq.get("bioplate");
2669 15 Sep 14 nicklas 1010         String pdfPath = (String)jsonReq.get("qcPdf");
1895 05 Mar 13 nicklas 1011         Date qcDate = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonReq.get("qcDate"));
2161 09 Dec 13 nicklas 1012                 
1895 05 Mar 13 nicklas 1013         BioPlate libPlate = BioPlate.getById(dc, bioPlateId.intValue());
1895 05 Mar 13 nicklas 1014
1895 05 Mar 13 nicklas 1015         // Link PDF file with the Library plate
2669 15 Sep 14 nicklas 1016         File pdf = File.getByPath(dc, new Path(pdfPath, Path.Type.FILE), false);
1895 05 Mar 13 nicklas 1017         
1895 05 Mar 13 nicklas 1018         ItemQuery<AnyToAny> query = AnyToAny.getLinksFrom(libPlate);
1895 05 Mar 13 nicklas 1019         List<AnyToAny> links = query.list(dc);
7024 07 Feb 23 nicklas 1020         DateToStringConverter d = new DateToStringConverter(FastDateFormat.getInstance("yyyy-MM-dd"));
1989 23 May 13 nicklas 1021
1989 23 May 13 nicklas 1022         if (pdf.getDescription() == null) pdf.setDescription("BioAnalyzer QC #" + (links.size()+1) + " for " + libPlate.getName());
1895 05 Mar 13 nicklas 1023         
1908 19 Mar 13 nicklas 1024         AnyToAny ata = AnyToAny.getNewOrExisting(dc, libPlate, (links.size() + 1) + ". " + d.convert(qcDate) + " (QC; PDF)", pdf, true);
1908 19 Mar 13 nicklas 1025         ata.setDescription((String)jsonReq.get("qcComments"));
1895 05 Mar 13 nicklas 1026         if (!ata.isInDatabase()) dc.saveItem(ata);
1895 05 Mar 13 nicklas 1027         
1895 05 Mar 13 nicklas 1028         jsonMessages.add("Attached file '" + pdf.getName() + "' to plate " + libPlate.getName());
1895 05 Mar 13 nicklas 1029
1895 05 Mar 13 nicklas 1030         dc.commit();        
1895 05 Mar 13 nicklas 1031       }
1906 14 Mar 13 nicklas 1032       else if ("ImportLibPrepResults".equals(cmd))
1906 14 Mar 13 nicklas 1033       {
6333 15 Jun 21 nicklas 1034         dc = sc.newDbControl(":Library registration");
2161 09 Dec 13 nicklas 1035
2161 09 Dec 13 nicklas 1036         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.LIBRARY_PREP, ReggieRole.ADMINISTRATOR);
2161 09 Dec 13 nicklas 1037
3752 17 Feb 16 nicklas 1038         JSONObject jsonReq = JsonUtil.parseRequest(req);
1906 14 Mar 13 nicklas 1039         Number bioPlateId = (Number)jsonReq.get("bioplate");
1906 14 Mar 13 nicklas 1040         Number libProtocolId = (Number)jsonReq.get("libProtocol");
1906 14 Mar 13 nicklas 1041         boolean failed = Boolean.TRUE.equals(jsonReq.get("failed"));
1906 14 Mar 13 nicklas 1042         
3835 11 Apr 16 nicklas 1043         Number libSize = (Number)jsonReq.get("libSize");
3835 11 Apr 16 nicklas 1044         
2675 17 Sep 14 nicklas 1045         String wellTableCsvPath = (String)jsonReq.get("wellTableCsv");
2675 17 Sep 14 nicklas 1046         String qubitCsvPath = (String)jsonReq.get("qubitCsv");
2675 17 Sep 14 nicklas 1047         String gxdPath = Values.getStringOrNull((String)jsonReq.get("caliperGxd"));
2675 17 Sep 14 nicklas 1048         String pdfPath = Values.getStringOrNull((String)jsonReq.get("caliperPdf"));
1906 14 Mar 13 nicklas 1049         
1906 14 Mar 13 nicklas 1050         BioPlate libPlate = BioPlate.getById(dc, bioPlateId.intValue());
5883 26 Mar 20 nicklas 1051         ReactionPlate reactionPlate = ReactionPlate.getById(dc, bioPlateId.intValue(), BioplateType.LIBRARY);
1908 19 Mar 13 nicklas 1052
3725 27 Jan 16 nicklas 1053         // Set date, protocol and comments for the event
2002 29 May 13 nicklas 1054         Date libDate = new Date();
3725 27 Jan 16 nicklas 1055         Protocol libProtocol = libProtocolId == null ? null : Protocol.getById(dc, libProtocolId.intValue());
3725 27 Jan 16 nicklas 1056         libPlate.setDescription((String)jsonReq.get("libComments"));
3725 27 Jan 16 nicklas 1057
5883 26 Mar 20 nicklas 1058         // Find the creation event for the plate
3725 27 Jan 16 nicklas 1059         List<BioPlateEvent> events = reactionPlate.findEvents(dc, BioPlateEventType.CREATE_BIOMATERIAL, "destination");
3725 27 Jan 16 nicklas 1060         if (events.size() > 1)
3725 27 Jan 16 nicklas 1061         {
3725 27 Jan 16 nicklas 1062           throw new InvalidDataException("Found > 1 creation event for plate: " + libPlate.getName());
3725 27 Jan 16 nicklas 1063         }
3725 27 Jan 16 nicklas 1064         // ...it may not exist if a plate has been created with a batch import...
3725 27 Jan 16 nicklas 1065         BioPlateEvent plateCreationEvent = events.size() == 0 ? null : events.get(0);
3725 27 Jan 16 nicklas 1066         if (plateCreationEvent != null)
3725 27 Jan 16 nicklas 1067         {
3725 27 Jan 16 nicklas 1068           // This automatically propagated to all Library items on the plate
3725 27 Jan 16 nicklas 1069           plateCreationEvent.setEventDate(libDate);
3725 27 Jan 16 nicklas 1070           plateCreationEvent.setProtocol(libProtocol);
3725 27 Jan 16 nicklas 1071         }
2002 29 May 13 nicklas 1072         
2002 29 May 13 nicklas 1073         Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonReq.get("libDate"));
1908 19 Mar 13 nicklas 1074         libPlate.setEventDate(libDate);
2002 29 May 13 nicklas 1075         
2002 29 May 13 nicklas 1076         // Dates and operators
5883 26 Mar 20 nicklas 1077         Annotationtype.AMPLIFICATION_DATE.setAnnotationValue(dc, libPlate, Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonReq.get("amplificationDate")));
5883 26 Mar 20 nicklas 1078         Annotationtype.AMPLIFICATION_OPERATOR.setAnnotationValue(dc, libPlate, Values.getStringOrNull((String)jsonReq.get("amplificationOperator")));
5883 26 Mar 20 nicklas 1079         Annotationtype.CLEANUP_DATE.setAnnotationValue(dc, libPlate, Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonReq.get("cleanupDate")));
5883 26 Mar 20 nicklas 1080         Annotationtype.CLEANUP_OPERATOR.setAnnotationValue(dc, libPlate, Values.getStringOrNull((String)jsonReq.get("cleanupOperator")));
2002 29 May 13 nicklas 1081         
1908 19 Mar 13 nicklas 1082         if (failed)
1906 14 Mar 13 nicklas 1083         {
1908 19 Mar 13 nicklas 1084           libPlate.setDestroyed(true);
1908 19 Mar 13 nicklas 1085           Annotationtype.PLATE_PROCESS_RESULT.setAnnotationValue(dc, libPlate, ReactionPlate.PROCESS_FAILED);
1908 19 Mar 13 nicklas 1086           
1908 19 Mar 13 nicklas 1087           // Flag the parent RNA items
3247 14 Apr 15 nicklas 1088           ItemList flaggedList = BiomaterialList.FLAGGED_RNA.load(dc);
1908 19 Mar 13 nicklas 1089           int numFlagged = 0;
1908 19 Mar 13 nicklas 1090           
1908 19 Mar 13 nicklas 1091           for (BioWell well : libPlate.getBioWells().list(dc))
1906 14 Mar 13 nicklas 1092           {
1908 19 Mar 13 nicklas 1093             if (!well.isEmpty())
1908 19 Mar 13 nicklas 1094             {
1908 19 Mar 13 nicklas 1095               Extract lib = (Extract)well.getBioMaterial();
2907 07 Nov 14 nicklas 1096               Library l = Library.get(lib);
3725 27 Jan 16 nicklas 1097               if (plateCreationEvent == null)
3725 27 Jan 16 nicklas 1098               {
3725 27 Jan 16 nicklas 1099                 // If no plate event existed, we must set protocol and date on all Library items
3725 27 Jan 16 nicklas 1100                 BioMaterialEvent evt = lib.getCreationEvent();
3725 27 Jan 16 nicklas 1101                 evt.setEventDate(libDate);
3725 27 Jan 16 nicklas 1102                 evt.setProtocol(libProtocol);
3725 27 Jan 16 nicklas 1103               }
1908 19 Mar 13 nicklas 1104               
5553 12 Aug 19 nicklas 1105               if (!Reggie.isExternalItem(lib.getName()))
1908 19 Mar 13 nicklas 1106               {
3309 06 May 15 nicklas 1107                 Rna r = l.getRna(dc, false);
2907 07 Nov 14 nicklas 1108                 Extract rna = r.getExtract();
1908 19 Mar 13 nicklas 1109                 Annotationtype.FLAG.setAnnotationValue(dc, rna, Rna.FLAG_LIB_PLATE_FAILED);
1908 19 Mar 13 nicklas 1110                 flaggedList.add(rna);
1908 19 Mar 13 nicklas 1111                 numFlagged++;
1908 19 Mar 13 nicklas 1112               }
1908 19 Mar 13 nicklas 1113             }
1906 14 Mar 13 nicklas 1114           }
1906 14 Mar 13 nicklas 1115           
1908 19 Mar 13 nicklas 1116           if (numFlagged > 0)
1906 14 Mar 13 nicklas 1117           {
1908 19 Mar 13 nicklas 1118             jsonMessages.add(numFlagged + " RNA items flagged for re-processing");
1906 14 Mar 13 nicklas 1119           }
1906 14 Mar 13 nicklas 1120           
1908 19 Mar 13 nicklas 1121           jsonMessages.add("Plate '" + libPlate.getName() + "' registered with status: " + (ReactionPlate.PROCESS_FAILED));
1906 14 Mar 13 nicklas 1122           dc.commit();
1906 14 Mar 13 nicklas 1123         }
1906 14 Mar 13 nicklas 1124         else
1906 14 Mar 13 nicklas 1125         {
3835 11 Apr 16 nicklas 1126           AbstractPlateImporter pi;
3835 11 Apr 16 nicklas 1127
1925 11 Apr 13 nicklas 1128           AnnotationType qubitConcType = Annotationtype.QUBIT_CONC.load(dc);
1925 11 Apr 13 nicklas 1129           AnnotationType speedVacConcType = Annotationtype.QUBIT_CONC_AFTER_SPEEDVAC.load(dc);
3835 11 Apr 16 nicklas 1130           File qubitCsv = File.getByPath(dc,new Path(qubitCsvPath, Path.Type.FILE), false);
3835 11 Apr 16 nicklas 1131           String qubitOrCaliperFile = qubitCsv.getName();
3835 11 Apr 16 nicklas 1132           boolean valid = true;
3835 11 Apr 16 nicklas 1133           boolean useCaliper = false;
1908 19 Mar 13 nicklas 1134           
3835 11 Apr 16 nicklas 1135           if (wellTableCsvPath != null)
3835 11 Apr 16 nicklas 1136           {
3835 11 Apr 16 nicklas 1137             useCaliper = true;
3835 11 Apr 16 nicklas 1138             File wellTableCsv = File.getByPath(dc, new Path(wellTableCsvPath, Path.Type.FILE), false);
3835 11 Apr 16 nicklas 1139             qubitOrCaliperFile = wellTableCsv.getName();
2675 17 Sep 14 nicklas 1140
3835 11 Apr 16 nicklas 1141             AnnotationType size = Annotationtype.CA_SIZE.load(dc);
3835 11 Apr 16 nicklas 1142             AnnotationType molarity = Annotationtype.CA_MOLARITY.load(dc);
3835 11 Apr 16 nicklas 1143             AnnotationType size_adpt = Annotationtype.CA_SIZE_ADPT.load(dc);
3835 11 Apr 16 nicklas 1144             AnnotationType molarity_adpt = Annotationtype.CA_MOLARITY_ADPT.load(dc);
3835 11 Apr 16 nicklas 1145             
5883 26 Mar 20 nicklas 1146             CaliperPlateImporter cpi = new CaliperPlateImporter(BioplateType.LIBRARY.getPlateNamePrefix());
3835 11 Apr 16 nicklas 1147             pi = cpi;
3835 11 Apr 16 nicklas 1148             cpi.setBioPlate(libPlate);
3835 11 Apr 16 nicklas 1149             cpi.setAllowMatchAgainstLocation(true); // Allow a few lines to have location coordinates instead of lib name
3835 11 Apr 16 nicklas 1150             cpi.setAnnotationMapping("Region[180-600] Size [BP]", size, new RequiredValueConverter<String>("is missing value for Region[180-600] Size [BP]"));
3835 11 Apr 16 nicklas 1151             cpi.setAnnotationMapping("Region[180-600] Molarity (nmol/l)", molarity, new FactorValueConverter(10f, new RequiredValueConverter<String>("is missing value for Region[180-600] Molarity (nmol/l)")));
3835 11 Apr 16 nicklas 1152             cpi.setAnnotationMapping("Region[120-140] Size [BP]", size_adpt, new RequiredValueConverter<String>("is missing value for Region[120-140] Size [BP]"));
3835 11 Apr 16 nicklas 1153             cpi.setAnnotationMapping("Region[120-140] Molarity (nmol/l)", molarity_adpt, new FactorValueConverter(10f, new RequiredValueConverter<String>("is missing value for Region[120-140] Molarity (nmol/l)")));
3835 11 Apr 16 nicklas 1154             
3835 11 Apr 16 nicklas 1155             valid = addQubitFileLookups(cpi, qubitCsv, qubitConcType, speedVacConcType);
3835 11 Apr 16 nicklas 1156             
3835 11 Apr 16 nicklas 1157             if (valid)
3835 11 Apr 16 nicklas 1158             {
5303 15 Feb 19 nicklas 1159               InputStream csv = null;
5303 15 Feb 19 nicklas 1160               try
5303 15 Feb 19 nicklas 1161               {
5303 15 Feb 19 nicklas 1162                 csv = wellTableCsv.getDownloadStream(0);
5303 15 Feb 19 nicklas 1163                 valid = cpi.doImport(dc, csv, false, wellTableCsv.getName());
5303 15 Feb 19 nicklas 1164               }
5303 15 Feb 19 nicklas 1165               finally
5303 15 Feb 19 nicklas 1166               {
5303 15 Feb 19 nicklas 1167                 FileUtil.close(csv);
5303 15 Feb 19 nicklas 1168               }
3835 11 Apr 16 nicklas 1169             }
3835 11 Apr 16 nicklas 1170           }
3835 11 Apr 16 nicklas 1171           else
3835 11 Apr 16 nicklas 1172           {
3835 11 Apr 16 nicklas 1173             QubitPlateImporter qpi = new QubitPlateImporter();
3835 11 Apr 16 nicklas 1174             pi = qpi;
3835 11 Apr 16 nicklas 1175             qpi.setBioPlate(libPlate);
3835 11 Apr 16 nicklas 1176             qpi.setAllowMatchAgainstLocation(true); // Allow a few lines to have location coordinates instead of lib name
3835 11 Apr 16 nicklas 1177             qpi.setAnnotationMapping("Qubit ng/ml", qubitConcType, new FactorValueConverter(0.001f, new RequiredValueConverter<String>("is missing value for 'Qubit ng/µl'")));
5303 15 Feb 19 nicklas 1178             InputStream csv = null;
5303 15 Feb 19 nicklas 1179             try
5303 15 Feb 19 nicklas 1180             {
5372 16 Apr 19 nicklas 1181               csv = qubitCsv.getDownloadStream(0);
5303 15 Feb 19 nicklas 1182               valid = qpi.doImport(dc, csv, false, qubitCsv.getName());
5303 15 Feb 19 nicklas 1183             }
5303 15 Feb 19 nicklas 1184             finally
5303 15 Feb 19 nicklas 1185             {
5303 15 Feb 19 nicklas 1186               FileUtil.close(csv);
5303 15 Feb 19 nicklas 1187             }
3835 11 Apr 16 nicklas 1188           }
2675 17 Sep 14 nicklas 1189           
3835 11 Apr 16 nicklas 1190           if (valid)
1908 19 Mar 13 nicklas 1191           {
1908 19 Mar 13 nicklas 1192             // The import was successful
3835 11 Apr 16 nicklas 1193             jsonMessages.add("Imported data to " + pi.getNumImported() + " libraries on plate " + libPlate.getName());
3835 11 Apr 16 nicklas 1194             if (pi.hasWarning())
1908 19 Mar 13 nicklas 1195             {
3835 11 Apr 16 nicklas 1196               jsonMessages.addAll(pi.getWarningMessages());
1908 19 Mar 13 nicklas 1197             }
3835 11 Apr 16 nicklas 1198
1908 19 Mar 13 nicklas 1199             // Attach the files we used to the bioplate
3835 11 Apr 16 nicklas 1200             pi.attachFile(dc, qubitCsv, "Qubit CSV");
1908 19 Mar 13 nicklas 1201             jsonMessages.add("Attached file '" + qubitCsv.getName() + "' to plate " + libPlate.getName());
1908 19 Mar 13 nicklas 1202             
3835 11 Apr 16 nicklas 1203             if (wellTableCsvPath != null)
3835 11 Apr 16 nicklas 1204             {
3835 11 Apr 16 nicklas 1205               File csv = File.getByPath(dc, new Path(wellTableCsvPath, Path.Type.FILE), false);
3835 11 Apr 16 nicklas 1206               pi.attachFile(dc, csv, "Well table CSV");
3835 11 Apr 16 nicklas 1207               jsonMessages.add("Attached file '" + csv.getName() + "' to plate " + libPlate.getName());
3835 11 Apr 16 nicklas 1208             }
2675 17 Sep 14 nicklas 1209             if (gxdPath != null)
1908 19 Mar 13 nicklas 1210             {
2675 17 Sep 14 nicklas 1211               File gxd = File.getByPath(dc, new Path(gxdPath, Path.Type.FILE), false);
3835 11 Apr 16 nicklas 1212               pi.attachFile(dc, gxd, "LabView GX raw data");
1908 19 Mar 13 nicklas 1213               jsonMessages.add("Attached file '" + gxd.getName() + "' to plate " + libPlate.getName());
1908 19 Mar 13 nicklas 1214             }
2675 17 Sep 14 nicklas 1215             if (pdfPath != null)
1908 19 Mar 13 nicklas 1216             {
2675 17 Sep 14 nicklas 1217               File pdf = File.getByPath(dc, new Path(pdfPath, Path.Type.FILE), false);
3835 11 Apr 16 nicklas 1218               pi.attachFile(dc, pdf, "Caliper PDF printout");
1908 19 Mar 13 nicklas 1219               jsonMessages.add("Attached file '" + pdf.getName() + "' to plate " + libPlate.getName());
1908 19 Mar 13 nicklas 1220             }
3835 11 Apr 16 nicklas 1221               
1908 19 Mar 13 nicklas 1222             // Calculate original quantity and molarity
1925 11 Apr 13 nicklas 1223             Float standardVolume = 10.0f; // Micro-liter -- NOTE! May be 11.0 when using 384-plate for Caliper
1925 11 Apr 13 nicklas 1224             Float speedVacVolume = 5.0f; // Less volume is left if SpeedVac has been done
1908 19 Mar 13 nicklas 1225             Float molFactor = 1000f * 1000f / 649f;
1908 19 Mar 13 nicklas 1226             
1908 19 Mar 13 nicklas 1227             int numExtracts = 0;
3835 11 Apr 16 nicklas 1228             for (Extract lib : pi.getExtracts())
1908 19 Mar 13 nicklas 1229             {
3725 27 Jan 16 nicklas 1230               if (plateCreationEvent == null)
3725 27 Jan 16 nicklas 1231               {
3725 27 Jan 16 nicklas 1232                 // If no plate event existed, we must set protocol and date on all Library items
3725 27 Jan 16 nicklas 1233                 BioMaterialEvent evt = lib.getCreationEvent();
3725 27 Jan 16 nicklas 1234                 evt.setEventDate(libDate);
3725 27 Jan 16 nicklas 1235                 evt.setProtocol(libProtocol);
3725 27 Jan 16 nicklas 1236               }
1908 19 Mar 13 nicklas 1237               
1925 11 Apr 13 nicklas 1238               // Use concentration and size value to calculate original quantity and molarity 
1925 11 Apr 13 nicklas 1239               Float originalConc = (Float)Annotationtype.QUBIT_CONC.getAnnotationValue(dc, lib);
1925 11 Apr 13 nicklas 1240               Float speedVacConc = (Float)Annotationtype.QUBIT_CONC_AFTER_SPEEDVAC.getAnnotationValue(dc, lib);
3835 11 Apr 16 nicklas 1241   
1925 11 Apr 13 nicklas 1242               Float libConc = speedVacConc != null ? speedVacConc : originalConc;
1925 11 Apr 13 nicklas 1243               Float libVolume = speedVacConc != null ? speedVacVolume : standardVolume;
1925 11 Apr 13 nicklas 1244               
3835 11 Apr 16 nicklas 1245               if (useCaliper)
3835 11 Apr 16 nicklas 1246               {
3835 11 Apr 16 nicklas 1247                 Float caSize = (Float)Annotationtype.CA_SIZE.getAnnotationValue(dc, lib);
3835 11 Apr 16 nicklas 1248                 Float caMolarity = (Float)Annotationtype.CA_MOLARITY.getAnnotationValue(dc, lib);
3835 11 Apr 16 nicklas 1249                 Float caSizeAdpt = (Float)Annotationtype.CA_SIZE_ADPT.getAnnotationValue(dc, lib);
3835 11 Apr 16 nicklas 1250                 Float caMolarityAdpt = (Float)Annotationtype.CA_MOLARITY_ADPT.getAnnotationValue(dc, lib);
3835 11 Apr 16 nicklas 1251               
3835 11 Apr 16 nicklas 1252                 if (caMolarity == null) caMolarity = 0f;
3835 11 Apr 16 nicklas 1253                 if (caMolarityAdpt == null) caMolarityAdpt = 0f;
3835 11 Apr 16 nicklas 1254                 libSize = calculateWeightedSize(caSize, caMolarity, caSizeAdpt, caMolarityAdpt);
3835 11 Apr 16 nicklas 1255                 Integer adptFraction = calculateAdapterFraction(caMolarity, caMolarityAdpt);
3835 11 Apr 16 nicklas 1256
3835 11 Apr 16 nicklas 1257                 Annotationtype.LIBRARY_FRAC_ADPT.setAnnotationValue(dc, lib, adptFraction);
3835 11 Apr 16 nicklas 1258               }
3835 11 Apr 16 nicklas 1259               
3835 11 Apr 16 nicklas 1260               Float libMolarity = libConc * molFactor / libSize.floatValue();
1925 11 Apr 13 nicklas 1261               lib.setOriginalQuantity(libConc * libVolume / 1000);
2454 23 May 14 nicklas 1262               Annotationtype.LIBRARY_MOLARITY_EST.setAnnotationValue(dc, lib, libMolarity);
2454 23 May 14 nicklas 1263               Annotationtype.LIBRARY_SIZE_EST.setAnnotationValue(dc, lib, libSize);
2454 23 May 14 nicklas 1264
3835 11 Apr 16 nicklas 1265               //jsonMessages.add(lib.getName() + ": " + libConc + " ng/µl: " + libMolarity + " nM: " + libSize + " BP");
3835 11 Apr 16 nicklas 1266               
1908 19 Mar 13 nicklas 1267               numExtracts++;
1908 19 Mar 13 nicklas 1268             }
1908 19 Mar 13 nicklas 1269                       
1908 19 Mar 13 nicklas 1270             // Register the plate as completely processed
1908 19 Mar 13 nicklas 1271             libPlate.setDestroyed(false);
1908 19 Mar 13 nicklas 1272             Annotationtype.PLATE_PROCESS_RESULT.setAnnotationValue(dc, libPlate, ReactionPlate.PROCESS_SUCCESSFUL);
1908 19 Mar 13 nicklas 1273             
5421 13 May 19 nicklas 1274             ActivityDef.COMPLETED_LIBPLATE.create(dc, libPlate.getName(), numExtracts);
5382 24 Apr 19 nicklas 1275
5382 24 Apr 19 nicklas 1276             dc.commit();
1908 19 Mar 13 nicklas 1277           }
1908 19 Mar 13 nicklas 1278           else
1908 19 Mar 13 nicklas 1279           {
3835 11 Apr 16 nicklas 1280             jsonMessages.addAll(pi.getErrorMessages());
3835 11 Apr 16 nicklas 1281             jsonMessages.addAll(pi.getExternalErrorMessages());
3835 11 Apr 16 nicklas 1282             jsonMessages.addAll(pi.getWarningMessages());
1908 19 Mar 13 nicklas 1283             json.put("status", "error");
3835 11 Apr 16 nicklas 1284             json.put("message", "Import failed from file: " + qubitOrCaliperFile);
1908 19 Mar 13 nicklas 1285           }
1908 19 Mar 13 nicklas 1286         }
1906 14 Mar 13 nicklas 1287       }
1806 22 Jan 13 nicklas 1288       json.put("messages", jsonMessages);
3059 19 Dec 14 nicklas 1289       CounterService.getInstance().setForceCount();
1806 22 Jan 13 nicklas 1290     }
1806 22 Jan 13 nicklas 1291     catch (Throwable t)
1806 22 Jan 13 nicklas 1292     {
1806 22 Jan 13 nicklas 1293       t.printStackTrace();
1806 22 Jan 13 nicklas 1294       json.clear();
1806 22 Jan 13 nicklas 1295       json.put("status", "error");
1806 22 Jan 13 nicklas 1296       json.put("message", t.getMessage());
1806 22 Jan 13 nicklas 1297       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
1806 22 Jan 13 nicklas 1298     }
1806 22 Jan 13 nicklas 1299     finally
1806 22 Jan 13 nicklas 1300     {
1806 22 Jan 13 nicklas 1301       if (dc != null) dc.close();
1806 22 Jan 13 nicklas 1302       json.writeJSONString(resp.getWriter());
1806 22 Jan 13 nicklas 1303     }
1806 22 Jan 13 nicklas 1304     
1806 22 Jan 13 nicklas 1305   }
1806 22 Jan 13 nicklas 1306   
1906 14 Mar 13 nicklas 1307   // Parse the Qubit file and return a map extract name -> concentration
2675 17 Sep 14 nicklas 1308   private boolean addQubitFileLookups(CaliperPlateImporter cpi, File qubitCsv, AnnotationType originalConcType, AnnotationType speedVacConcType)
1906 14 Mar 13 nicklas 1309   {
2454 23 May 14 nicklas 1310     int lineNo = 0;
5303 15 Feb 19 nicklas 1311     InputStream csv = null;
1968 08 May 13 nicklas 1312     try
1906 14 Mar 13 nicklas 1313     {
5372 16 Apr 19 nicklas 1314       csv = qubitCsv.getDownloadStream(0);
5303 15 Feb 19 nicklas 1315       
1968 08 May 13 nicklas 1316       // Parse the Qubit file and store concentration before and after speedvac in two maps
1968 08 May 13 nicklas 1317       FlatFileParser ffp = new FlatFileParser();
1968 08 May 13 nicklas 1318       ffp.setDataHeaderRegexp(Pattern.compile(".*Well.*Library name.*Qubit ng/ml.*After SpeedVac.*"));
2454 23 May 14 nicklas 1319       ffp.setIgnoreRegexp(Pattern.compile("^(\\\"?#.*|)\\s*")); // Ignore all lines starting with (#), ("#), or containing only whitespace
1968 08 May 13 nicklas 1320       ffp.setDataSplitterRegexp(Pattern.compile("\t|,")); // Split on tab or comma
5303 15 Feb 19 nicklas 1321       ffp.setInputStream(csv, "UTF-8");
1968 08 May 13 nicklas 1322       ffp.setTrimQuotes(true);
1968 08 May 13 nicklas 1323       if (ffp.parseHeaders() != LineType.DATA_HEADER)
1968 08 May 13 nicklas 1324       {
1968 08 May 13 nicklas 1325         throw new InvalidDataException("Could not find header line starting with 'Well{tab}Library name{tab}Qubit ng/ml...'");
1968 08 May 13 nicklas 1326       }
1968 08 May 13 nicklas 1327   
1968 08 May 13 nicklas 1328       Mapper nameMapper = ffp.getMapper("\\Library name\\");
1968 08 May 13 nicklas 1329       Mapper originalConcMapper = ffp.getMapper("\\Qubit ng/ml\\");
1968 08 May 13 nicklas 1330       Mapper speedVacConcMapper = ffp.getMapper("\\After SpeedVac\\");
1968 08 May 13 nicklas 1331   
1968 08 May 13 nicklas 1332       Map<String, Float> originalConc = new HashMap<String, Float>();
1968 08 May 13 nicklas 1333       Map<String, Float> speedVacConc = new HashMap<String, Float>();
2825 16 Oct 14 nicklas 1334       Map<String, String> errors = new HashMap<String, String>();
1968 08 May 13 nicklas 1335       while (ffp.hasMoreData())
1968 08 May 13 nicklas 1336       {
2454 23 May 14 nicklas 1337         lineNo = ffp.getParsedLines();
1968 08 May 13 nicklas 1338         FlatFileParser.Data data = ffp.nextData();
5364 16 Apr 19 nicklas 1339         String libName = nameMapper.getString(data);
2675 17 Sep 14 nicklas 1340         Float c = checkQubitConcentration(originalConcMapper.getFloat(data));
2675 17 Sep 14 nicklas 1341         if (c == null)
2675 17 Sep 14 nicklas 1342         {
2825 16 Oct 14 nicklas 1343           errors.put(libName, "File '" + qubitCsv.getName() + "' line " + lineNo + ": Missing concentration for extract '" + libName + "'");
2675 17 Sep 14 nicklas 1344         }
2675 17 Sep 14 nicklas 1345         originalConc.put(libName, c);
2675 17 Sep 14 nicklas 1346         speedVacConc.put(libName, checkQubitConcentration(speedVacConcMapper.getFloat(data)));
1968 08 May 13 nicklas 1347       }
1968 08 May 13 nicklas 1348       
1968 08 May 13 nicklas 1349       // An original concentration is required, but SpeedVac concentration is optional
3362 01 Jun 15 nicklas 1350       LookupConverter<String, Float> originalConcLookup = new LookupConverter<String, Float>(originalConc, errors, 
3362 01 Jun 15 nicklas 1351           "File '" + qubitCsv.getName() + "': Could not find any data for library '{KEY}'");
3362 01 Jun 15 nicklas 1352       LookupConverter<String, Float> speedVacConcLookup = new LookupConverter<String, Float>(speedVacConc, null, null);
1968 08 May 13 nicklas 1353   
1968 08 May 13 nicklas 1354       cpi.addExternalLookup(originalConcLookup, originalConcType);
1968 08 May 13 nicklas 1355       cpi.addExternalLookup(speedVacConcLookup, speedVacConcType);
1906 14 Mar 13 nicklas 1356     }
1968 08 May 13 nicklas 1357     catch (Exception ex)
1906 14 Mar 13 nicklas 1358     {
2675 17 Sep 14 nicklas 1359       cpi.addErrorMessage("File '" + qubitCsv.getName() + "' line " + lineNo + ": " + ex.getMessage());
1906 14 Mar 13 nicklas 1360     }
5303 15 Feb 19 nicklas 1361     finally
5303 15 Feb 19 nicklas 1362     {
5303 15 Feb 19 nicklas 1363       FileUtil.close(csv);
5303 15 Feb 19 nicklas 1364     }
2675 17 Sep 14 nicklas 1365     return !cpi.hasError();
1906 14 Mar 13 nicklas 1366   }
1930 16 Apr 13 nicklas 1367   
3834 11 Apr 16 nicklas 1368   
2675 17 Sep 14 nicklas 1369   private Float checkQubitConcentration(Float value)
1930 16 Apr 13 nicklas 1370   {
1930 16 Apr 13 nicklas 1371     return value == null ? null : value / 1000;
1930 16 Apr 13 nicklas 1372   }
2454 23 May 14 nicklas 1373   
2454 23 May 14 nicklas 1374   private Float calculateWeightedSize(Float libSize, Float libMolarity, Float adptSize, Float adptMolarity)
2454 23 May 14 nicklas 1375   {
2454 23 May 14 nicklas 1376     Float totalMolarity = libMolarity + adptMolarity;
2454 23 May 14 nicklas 1377     Float weightedSize = libSize;
2454 23 May 14 nicklas 1378     if (totalMolarity > 0)
2454 23 May 14 nicklas 1379     {
2454 23 May 14 nicklas 1380       weightedSize = (libSize * libMolarity + adptSize * adptMolarity) / totalMolarity;
2454 23 May 14 nicklas 1381     }
2454 23 May 14 nicklas 1382     return weightedSize;
2454 23 May 14 nicklas 1383   }
2454 23 May 14 nicklas 1384   
2454 23 May 14 nicklas 1385   private Integer calculateAdapterFraction(Float libMolarity, Float adptMolarity)
2454 23 May 14 nicklas 1386   {
2454 23 May 14 nicklas 1387     Float totalMolarity = libMolarity + adptMolarity;
2454 23 May 14 nicklas 1388     return totalMolarity > 0 ? (int)(100 * adptMolarity / totalMolarity) : null;
2454 23 May 14 nicklas 1389   }
2454 23 May 14 nicklas 1390   
3835 11 Apr 16 nicklas 1391   public static class FactorValueConverter
2454 23 May 14 nicklas 1392     implements ValueConverter<String, Float>
2454 23 May 14 nicklas 1393   {
2454 23 May 14 nicklas 1394
3835 11 Apr 16 nicklas 1395     private final Float factor;
2960 19 Nov 14 nicklas 1396     private final ValueConverter<String, String> parent;
2960 19 Nov 14 nicklas 1397     
3835 11 Apr 16 nicklas 1398     public FactorValueConverter(Float factor, ValueConverter<String, String> parent) 
2960 19 Nov 14 nicklas 1399     {
3835 11 Apr 16 nicklas 1400       this.factor = factor;
2960 19 Nov 14 nicklas 1401       this.parent = parent;
2960 19 Nov 14 nicklas 1402     }
2960 19 Nov 14 nicklas 1403     
2454 23 May 14 nicklas 1404     @Override
2454 23 May 14 nicklas 1405     public Float convert(String value) 
2454 23 May 14 nicklas 1406     {
2960 19 Nov 14 nicklas 1407       Float f = (Float)Type.FLOAT.parseString(parent.convert(value));
3835 11 Apr 16 nicklas 1408       if (f != null) f = f * factor;
2454 23 May 14 nicklas 1409       return f;
2454 23 May 14 nicklas 1410     }
2454 23 May 14 nicklas 1411     
2454 23 May 14 nicklas 1412   }
3835 11 Apr 16 nicklas 1413
1806 22 Jan 13 nicklas 1414 }