extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/ExternalSpecimenImporter.java

Code
Comments
Other
Rev Date Author Line
6194 30 Mar 21 nicklas 1 package net.sf.basedb.reggie.plugins;
6194 30 Mar 21 nicklas 2
6209 13 Apr 21 nicklas 3 import java.util.Arrays;
6209 13 Apr 21 nicklas 4
7025 08 Feb 23 nicklas 5 import org.apache.commons.lang3.time.FastDateFormat;
7025 08 Feb 23 nicklas 6
7226 01 Jun 23 nicklas 7 import net.sf.basedb.core.AnyToAny;
7226 01 Jun 23 nicklas 8 import net.sf.basedb.core.BasicItem;
6194 30 Mar 21 nicklas 9 import net.sf.basedb.core.BioMaterialEvent;
6207 12 Apr 21 nicklas 10 import net.sf.basedb.core.BioMaterialEventSource;
6195 31 Mar 21 nicklas 11 import net.sf.basedb.core.BioPlate;
6195 31 Mar 21 nicklas 12 import net.sf.basedb.core.BioWell;
7050 17 Feb 23 nicklas 13 import net.sf.basedb.core.DataFileType;
6194 30 Mar 21 nicklas 14 import net.sf.basedb.core.DbControl;
6194 30 Mar 21 nicklas 15 import net.sf.basedb.core.DerivedBioAssay;
7050 17 Feb 23 nicklas 16 import net.sf.basedb.core.Directory;
6194 30 Mar 21 nicklas 17 import net.sf.basedb.core.Extract;
7050 17 Feb 23 nicklas 18 import net.sf.basedb.core.File;
7050 17 Feb 23 nicklas 19 import net.sf.basedb.core.FileServer;
7050 17 Feb 23 nicklas 20 import net.sf.basedb.core.FileSet;
6341 29 Jun 21 nicklas 21 import net.sf.basedb.core.ItemSubtype;
6495 01 Dec 21 nicklas 22 import net.sf.basedb.core.Nameable;
7050 17 Feb 23 nicklas 23 import net.sf.basedb.core.Path;
6194 30 Mar 21 nicklas 24 import net.sf.basedb.core.PhysicalBioAssay;
6194 30 Mar 21 nicklas 25 import net.sf.basedb.core.Sample;
6887 24 Nov 22 nicklas 26 import net.sf.basedb.core.Tag;
6199 08 Apr 21 nicklas 27 import net.sf.basedb.core.data.PlateCoordinate;
7050 17 Feb 23 nicklas 28 import net.sf.basedb.reggie.Reggie;
6195 31 Mar 21 nicklas 29 import net.sf.basedb.reggie.dao.Annotationtype;
7231 02 Jun 23 nicklas 30 import net.sf.basedb.reggie.dao.BiomaterialList;
6195 31 Mar 21 nicklas 31 import net.sf.basedb.reggie.dao.BioplateType;
7050 17 Feb 23 nicklas 32 import net.sf.basedb.reggie.dao.Datafiletype;
6203 09 Apr 21 nicklas 33 import net.sf.basedb.reggie.dao.DemuxedSequences;
6207 12 Apr 21 nicklas 34 import net.sf.basedb.reggie.dao.Dna;
6194 30 Mar 21 nicklas 35 import net.sf.basedb.reggie.dao.FlowCell;
6207 12 Apr 21 nicklas 36 import net.sf.basedb.reggie.dao.FlowThrough;
6194 30 Mar 21 nicklas 37 import net.sf.basedb.reggie.dao.Library;
6194 30 Mar 21 nicklas 38 import net.sf.basedb.reggie.dao.Lysate;
6195 31 Mar 21 nicklas 39 import net.sf.basedb.reggie.dao.Pipeline;
6194 30 Mar 21 nicklas 40 import net.sf.basedb.reggie.dao.PooledLibrary;
6199 08 Apr 21 nicklas 41 import net.sf.basedb.reggie.dao.ReactionPlate;
6194 30 Mar 21 nicklas 42 import net.sf.basedb.reggie.dao.Rna;
6207 12 Apr 21 nicklas 43 import net.sf.basedb.reggie.dao.RnaQc;
6194 30 Mar 21 nicklas 44 import net.sf.basedb.reggie.dao.SequencingRun;
6194 30 Mar 21 nicklas 45 import net.sf.basedb.reggie.dao.SpecimenTube;
6194 30 Mar 21 nicklas 46 import net.sf.basedb.reggie.dao.Subtype;
6203 09 Apr 21 nicklas 47 import net.sf.basedb.reggie.plugins.cmd.DemuxInfo;
6207 12 Apr 21 nicklas 48 import net.sf.basedb.reggie.plugins.cmd.DnaInfo;
6734 09 May 22 nicklas 49 import net.sf.basedb.reggie.plugins.cmd.EndPoint;
6209 13 Apr 21 nicklas 50 import net.sf.basedb.reggie.plugins.cmd.FastqInfo;
7050 17 Feb 23 nicklas 51 import net.sf.basedb.reggie.plugins.cmd.FastqInfo.FastqFile;
6201 09 Apr 21 nicklas 52 import net.sf.basedb.reggie.plugins.cmd.FlowCellInfo;
6207 12 Apr 21 nicklas 53 import net.sf.basedb.reggie.plugins.cmd.FlowThroughInfo;
6199 08 Apr 21 nicklas 54 import net.sf.basedb.reggie.plugins.cmd.JsonFile;
6199 08 Apr 21 nicklas 55 import net.sf.basedb.reggie.plugins.cmd.LibraryInfo;
6887 24 Nov 22 nicklas 56 import net.sf.basedb.reggie.plugins.cmd.LibraryInfo.BarcodeInfo;
6207 12 Apr 21 nicklas 57 import net.sf.basedb.reggie.plugins.cmd.LysateInfo;
6495 01 Dec 21 nicklas 58 import net.sf.basedb.reggie.plugins.cmd.MainInfo;
6199 08 Apr 21 nicklas 59 import net.sf.basedb.reggie.plugins.cmd.PoolInfo;
6207 12 Apr 21 nicklas 60 import net.sf.basedb.reggie.plugins.cmd.RnaInfo;
6495 01 Dec 21 nicklas 61 import net.sf.basedb.reggie.plugins.cmd.ScanBIdRef;
6201 09 Apr 21 nicklas 62 import net.sf.basedb.reggie.plugins.cmd.SequencingRunInfo;
6217 19 Apr 21 nicklas 63 import net.sf.basedb.reggie.plugins.cmd.SpecimenInfo;
6495 01 Dec 21 nicklas 64 import net.sf.basedb.reggie.plugins.cmd.ScanBIdRef.SampleIdType;
6201 09 Apr 21 nicklas 65 import net.sf.basedb.util.MD5;
6194 30 Mar 21 nicklas 66
6194 30 Mar 21 nicklas 67 /**
6498 01 Dec 21 nicklas 68   Import data to new Specimen items and create all downstream items
6215 16 Apr 21 nicklas 69   needed (down to DemuxedSequences) before FASTQ files can be imported.
6194 30 Mar 21 nicklas 70   
6498 01 Dec 21 nicklas 71   It is also possible to start the import on an existing Specimen or
6194 30 Mar 21 nicklas 72   RNA item.
6194 30 Mar 21 nicklas 73   
6194 30 Mar 21 nicklas 74   @author nicklas
6194 30 Mar 21 nicklas 75   @since 4.32
6194 30 Mar 21 nicklas 76 */
6498 01 Dec 21 nicklas 77 public class ExternalSpecimenImporter 
6194 30 Mar 21 nicklas 78 {
6194 30 Mar 21 nicklas 79   
6198 07 Apr 21 nicklas 80
6198 07 Apr 21 nicklas 81   private JsonFile currentFile;
6198 07 Apr 21 nicklas 82   
6194 30 Mar 21 nicklas 83   
6498 01 Dec 21 nicklas 84   public ExternalSpecimenImporter()
6205 12 Apr 21 nicklas 85   {}
6198 07 Apr 21 nicklas 86
6198 07 Apr 21 nicklas 87
6198 07 Apr 21 nicklas 88   void addWarningMessage(String msg)
6198 07 Apr 21 nicklas 89   {
6199 08 Apr 21 nicklas 90     currentFile.addWarningMessage(msg);
6198 07 Apr 21 nicklas 91   }
6194 30 Mar 21 nicklas 92   
6198 07 Apr 21 nicklas 93   void addErrorMessage(String msg)
6194 30 Mar 21 nicklas 94   {
6199 08 Apr 21 nicklas 95     currentFile.addErrorMessage(msg);
6194 30 Mar 21 nicklas 96   }
6198 07 Apr 21 nicklas 97
6198 07 Apr 21 nicklas 98   void addDebugMessage(String msg)
6198 07 Apr 21 nicklas 99   {
6199 08 Apr 21 nicklas 100     currentFile.addDebugMessage(msg);
6198 07 Apr 21 nicklas 101   }
6194 30 Mar 21 nicklas 102   
6194 30 Mar 21 nicklas 103   /**
6495 01 Dec 21 nicklas 104     Import to a new Specimen. If the import is successful the 
6495 01 Dec 21 nicklas 105     imported items are returned, otherwise null.
6194 30 Mar 21 nicklas 106   */
7050 17 Feb 23 nicklas 107   public ImportedItems doImport(DbControl dc, JsonFile jsonFile, FileServer importGateway)
6194 30 Mar 21 nicklas 108   {
6198 07 Apr 21 nicklas 109     this.currentFile = jsonFile;
6194 30 Mar 21 nicklas 110     
6495 01 Dec 21 nicklas 111     MainInfo mainInfo = jsonFile.getMain();
6495 01 Dec 21 nicklas 112     ScanBIdRef idRef = mainInfo.idRef;
6734 09 May 22 nicklas 113     EndPoint endPoint = mainInfo.endPoint;
6734 09 May 22 nicklas 114     
6495 01 Dec 21 nicklas 115     ImportedItems items = new ImportedItems();
6495 01 Dec 21 nicklas 116     if (idRef.idType == SampleIdType.CASE || idRef.idType == SampleIdType.SPECIMEN)
6495 01 Dec 21 nicklas 117     {
6734 09 May 22 nicklas 118       // SPECIMEN
6495 01 Dec 21 nicklas 119       SpecimenInfo specimenInfo = jsonFile.getSpecimen();    
6495 01 Dec 21 nicklas 120       if (idRef.idType == SampleIdType.CASE)
6495 01 Dec 21 nicklas 121       {
6495 01 Dec 21 nicklas 122         if (!specimenInfo.valid) return null;
6738 10 May 22 nicklas 123         items.specimen = createSpecimen(dc,endPoint, mainInfo, specimenInfo);
6495 01 Dec 21 nicklas 124         items.importedTo = items.specimen.getItem();
6495 01 Dec 21 nicklas 125       }
6495 01 Dec 21 nicklas 126       else if (idRef.idType == SampleIdType.SPECIMEN)
6495 01 Dec 21 nicklas 127       {
6495 01 Dec 21 nicklas 128         // TODO -- is this ok?
6495 01 Dec 21 nicklas 129         items.specimen = idRef.specimen;
6495 01 Dec 21 nicklas 130         items.importedTo = items.specimen.getItem();
6495 01 Dec 21 nicklas 131       }
6910 30 Nov 22 nicklas 132       if (jsonFile.hasWarning())
6910 30 Nov 22 nicklas 133       {
6910 30 Nov 22 nicklas 134         Annotationtype.IMPORT_WARNINGS.setAnnotationValues(dc, items.specimen.getItem(), jsonFile.getWarningMessages());
6910 30 Nov 22 nicklas 135       }
6910 30 Nov 22 nicklas 136       
6734 09 May 22 nicklas 137       if (endPoint == EndPoint.SPECIMEN) return items;
6495 01 Dec 21 nicklas 138
6734 09 May 22 nicklas 139       // LYSATE
6734 09 May 22 nicklas 140       LysateInfo lysateInfo = jsonFile.getLysate();
6734 09 May 22 nicklas 141       if (!lysateInfo.valid) return null;
6738 10 May 22 nicklas 142       items.lysate = createLysate(dc, endPoint, items.specimen, lysateInfo);
6734 09 May 22 nicklas 143       if (endPoint == EndPoint.LYSATE) return items;
6495 01 Dec 21 nicklas 144     
6734 09 May 22 nicklas 145       // RNA, DNA and FlowThrough
6734 09 May 22 nicklas 146       RnaInfo rnaInfo = jsonFile.getRna();
6734 09 May 22 nicklas 147       DnaInfo dnaInfo = jsonFile.getDna();
6734 09 May 22 nicklas 148       FlowThroughInfo ftInfo = jsonFile.getFlowThroughInfo();
6734 09 May 22 nicklas 149       if (!rnaInfo.valid || !dnaInfo.valid || !ftInfo.valid) return null;
6738 10 May 22 nicklas 150       items.rna = createRna(dc, endPoint, items.lysate, rnaInfo);
6738 10 May 22 nicklas 151       items.rnaQc = createRnaQc(dc, endPoint, items.rna, rnaInfo);
6738 10 May 22 nicklas 152       items.dna = createDna(dc, endPoint, items.lysate, dnaInfo);
6738 10 May 22 nicklas 153       items.flowThrough = createFlowThrough(dc, endPoint, items.lysate, ftInfo);
6734 09 May 22 nicklas 154       if (endPoint == EndPoint.RNA) return items;
6495 01 Dec 21 nicklas 155     }
6495 01 Dec 21 nicklas 156     else if (idRef.idType == SampleIdType.PRENORMALISED_RNA)
6495 01 Dec 21 nicklas 157     {
6495 01 Dec 21 nicklas 158       items.rna = idRef.rna;
6495 01 Dec 21 nicklas 159       items.importedTo = items.rna.getItem();
6910 30 Nov 22 nicklas 160       if (jsonFile.hasWarning())
6910 30 Nov 22 nicklas 161       {
6910 30 Nov 22 nicklas 162         Annotationtype.IMPORT_WARNINGS.setAnnotationValues(dc, items.rna.getItem(), jsonFile.getWarningMessages());
6910 30 Nov 22 nicklas 163       }
6495 01 Dec 21 nicklas 164     }
6495 01 Dec 21 nicklas 165     else
6495 01 Dec 21 nicklas 166     {
6495 01 Dec 21 nicklas 167       return null;
6495 01 Dec 21 nicklas 168     }
6495 01 Dec 21 nicklas 169     
6734 09 May 22 nicklas 170     // LIBRARY  
6199 08 Apr 21 nicklas 171     LibraryInfo libInfo = jsonFile.getLibrary();
6734 09 May 22 nicklas 172     if (!libInfo.valid) return null;
6737 10 May 22 nicklas 173     items.lib = createLibrary(dc, endPoint, items.rna, libInfo);
6734 09 May 22 nicklas 174     if (endPoint == EndPoint.LIBRARY) return items;
6194 30 Mar 21 nicklas 175     
6734 09 May 22 nicklas 176     // POOL
6734 09 May 22 nicklas 177     PoolInfo poolInfo = jsonFile.getPool();
6734 09 May 22 nicklas 178     if (!poolInfo.valid) return null;
6737 10 May 22 nicklas 179     items.pool = getOrCreatePool(dc, endPoint, items.lib, poolInfo);
6734 09 May 22 nicklas 180     if (endPoint == EndPoint.POOL) return items;
6194 30 Mar 21 nicklas 181     
6734 09 May 22 nicklas 182     // SEQUENCING
6734 09 May 22 nicklas 183     FlowCellInfo flowCellInfo = jsonFile.getFlowCell();
6734 09 May 22 nicklas 184     SequencingRunInfo seqRunInfo = jsonFile.getSequencingRun();
6734 09 May 22 nicklas 185     if (!flowCellInfo.valid || !seqRunInfo.valid) return null;
6736 10 May 22 nicklas 186     items.flowCell = getOrCreateFlowCell(dc, endPoint, items.pool, flowCellInfo, seqRunInfo);
6736 10 May 22 nicklas 187     items.sequencingRun = getOrCreateSequencingRun(dc, endPoint, items.flowCell, flowCellInfo, seqRunInfo);
6734 09 May 22 nicklas 188     if (endPoint == EndPoint.SEQUENCING) return items;
6201 09 Apr 21 nicklas 189     
6734 09 May 22 nicklas 190     // FASTQ
6734 09 May 22 nicklas 191     DemuxInfo demuxInfo = jsonFile.getDemuxInfo();
6734 09 May 22 nicklas 192     FastqInfo fastqInfo = jsonFile.getFastqInfo();
6734 09 May 22 nicklas 193     if (!demuxInfo.valid || !fastqInfo.valid) return null;
6215 16 Apr 21 nicklas 194     items.demux = createDemuxedSequences(dc, items.lib, items.sequencingRun, flowCellInfo, seqRunInfo, demuxInfo, fastqInfo);
7050 17 Feb 23 nicklas 195     items.rawFastq = createRawFastqFiles(dc, items.demux, fastqInfo, importGateway);
6203 09 Apr 21 nicklas 196     
6734 09 May 22 nicklas 197     return jsonFile.hasError() ? null : items;
6194 30 Mar 21 nicklas 198   }
6194 30 Mar 21 nicklas 199   
7226 01 Jun 23 nicklas 200   /**
7226 01 Jun 23 nicklas 201     Create a file item reprsenting the JSON file and link it to the given item. 
7226 01 Jun 23 nicklas 202     The link is named "Imported from".
7226 01 Jun 23 nicklas 203     @since 4.48
7226 01 Jun 23 nicklas 204   */
7226 01 Jun 23 nicklas 205   public void createJsonLink(DbControl dc, JsonFile jsonFile, Nameable item, FileServer archive, String archiveFolder)
7226 01 Jun 23 nicklas 206   {
7226 01 Jun 23 nicklas 207     // Create a link betweem the specimen and archived JSON file
7226 01 Jun 23 nicklas 208     Directory jsonDir = Directory.getNew(dc, new Path(Reggie.EXTERNAL_JSON_IMPORT_DIR+archiveFolder, Path.Type.DIRECTORY));
7226 01 Jun 23 nicklas 209     File jsonInBase = File.getFile(dc, jsonDir, jsonFile.getName(), true);
7226 01 Jun 23 nicklas 210     jsonInBase.setFileServer(archive);
7226 01 Jun 23 nicklas 211     jsonInBase.setProjectKey(null);
7226 01 Jun 23 nicklas 212     jsonInBase.setMimeType("application/json");
7226 01 Jun 23 nicklas 213     jsonInBase.setCharacterSet("UTF-8");
7226 01 Jun 23 nicklas 214     jsonInBase.setDescription("Imported to "+item.getName());
7226 01 Jun 23 nicklas 215     String fileUrl = "sftp://" + archive.getHost() + archiveFolder + "/" + jsonFile.getName();
7226 01 Jun 23 nicklas 216     try
7226 01 Jun 23 nicklas 217     {
7226 01 Jun 23 nicklas 218       jsonInBase.setUrl(fileUrl, true);
7226 01 Jun 23 nicklas 219     }
7226 01 Jun 23 nicklas 220     catch (RuntimeException ex)
7226 01 Jun 23 nicklas 221     {
7226 01 Jun 23 nicklas 222       jsonInBase.setUrl(fileUrl, false);
7226 01 Jun 23 nicklas 223     }
7226 01 Jun 23 nicklas 224     if (!jsonInBase.isInDatabase()) dc.saveItem(jsonInBase);
7226 01 Jun 23 nicklas 225     
7226 01 Jun 23 nicklas 226     AnyToAny link = AnyToAny.getNewOrExisting(dc, (BasicItem)item, "Imported from", jsonInBase, true);
7226 01 Jun 23 nicklas 227     if (!link.isInDatabase()) dc.saveItem(link);
7226 01 Jun 23 nicklas 228   }
7226 01 Jun 23 nicklas 229   
6738 10 May 22 nicklas 230   private SpecimenTube createSpecimen(DbControl dc, EndPoint endPoint, MainInfo mainInfo, SpecimenInfo specimenInfo)
6194 30 Mar 21 nicklas 231   {
6572 07 Feb 22 nicklas 232     Sample specimen = null;
7231 02 Jun 23 nicklas 233     boolean isMerge = false;
7231 02 Jun 23 nicklas 234     boolean isConvert = false;
7232 02 Jun 23 nicklas 235     if (specimenInfo.mergeWith != null)
6572 07 Feb 22 nicklas 236     {
7232 02 Jun 23 nicklas 237       specimen = Sample.getById(dc, specimenInfo.mergeWith.getId());
7231 02 Jun 23 nicklas 238       // Remove the specimen from the Flagged External Specimen list
7231 02 Jun 23 nicklas 239       BiomaterialList.FLAGGED_EXERNAL_SPECIMEN.get(dc).removeItem(specimen);
7231 02 Jun 23 nicklas 240       isMerge = true;
7231 02 Jun 23 nicklas 241     }
7231 02 Jun 23 nicklas 242     else if (mainInfo.idRef.noSpecimen != null)
7231 02 Jun 23 nicklas 243     {
6572 07 Feb 22 nicklas 244       specimen = Sample.getById(dc, mainInfo.idRef.noSpecimen.getId());
7233 02 Jun 23 nicklas 245       specimen.setItemSubtype(Subtype.SPECIMEN.get(dc));
7231 02 Jun 23 nicklas 246       isConvert = true;
6572 07 Feb 22 nicklas 247     }
6572 07 Feb 22 nicklas 248     else
6572 07 Feb 22 nicklas 249     {
6572 07 Feb 22 nicklas 250       specimen = Sample.getNew(dc);
7000 20 Jan 23 nicklas 251       specimen.setName(SpecimenTube.getNextSpecimenName(dc, mainInfo.idRef.id, true));
6572 07 Feb 22 nicklas 252       specimen.setExternalId(SpecimenTube.getNextExternalId(dc, Subtype.SPECIMEN));
7233 02 Jun 23 nicklas 253       specimen.setItemSubtype(Subtype.SPECIMEN.get(dc));
6572 07 Feb 22 nicklas 254     }
6714 29 Apr 22 nicklas 255     specimen.setOriginalQuantity(multiply(specimenInfo.originalQuantity_mg, 1000));
6341 29 Jun 21 nicklas 256     
7231 02 Jun 23 nicklas 257     if (!isConvert)
6194 30 Mar 21 nicklas 258     {
7231 02 Jun 23 nicklas 259       Annotationtype.ALTERNATE_PAD.setAnnotationValue(dc, specimen, specimenInfo.alternatePad);
6194 30 Mar 21 nicklas 260     }
7231 02 Jun 23 nicklas 261     if (!isMerge)
7231 02 Jun 23 nicklas 262     {
7231 02 Jun 23 nicklas 263       // Do not overwrite annotations that have been set by transport box importer
7231 02 Jun 23 nicklas 264       Annotationtype.EXTERNAL_SPECIMEN_EXISTS.setAnnotationValue(dc, specimen, "Yes");
7231 02 Jun 23 nicklas 265       Annotationtype.EXTERNAL_STORAGE.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.storageLocation);
7231 02 Jun 23 nicklas 266     }
6928 02 Dec 22 nicklas 267     Annotationtype.PAD.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.pad);
6994 20 Jan 23 nicklas 268     Annotationtype.EXTERNAL_OPERATOR.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.operator);
6928 02 Dec 22 nicklas 269     Annotationtype.EXTERNAL_REF.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.clarityId);
6928 02 Dec 22 nicklas 270     Annotationtype.TUBE_LABEL.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.tubeLabel);
6928 02 Dec 22 nicklas 271     Annotationtype.NOF_DELIVERED_TUBES.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.numberOfTubes);
6928 02 Dec 22 nicklas 272     Annotationtype.NOF_PIECES.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.numberOfPieces);
6928 02 Dec 22 nicklas 273     Annotationtype.LATERALITY.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.laterality);
6928 02 Dec 22 nicklas 274     Annotationtype.OTHER_PATH_NOTE.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.pathologyNote);
6928 02 Dec 22 nicklas 275     Annotationtype.SPECIMEN_TYPE.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.specimenType);
6928 02 Dec 22 nicklas 276     Annotationtype.BIOPSY_TYPE.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.biopsyType);
6928 02 Dec 22 nicklas 277     Annotationtype.OPERATOR_DELIVERY_COMMENT.addOrUpdateAnnotationValue(dc, specimen, specimenInfo.deliveryComment);
6495 01 Dec 21 nicklas 278     
6572 07 Feb 22 nicklas 279     if (!specimen.isInDatabase()) 
6572 07 Feb 22 nicklas 280     {
7231 02 Jun 23 nicklas 281       if (mainInfo.idRef.theCase != null) 
7231 02 Jun 23 nicklas 282       {
7231 02 Jun 23 nicklas 283         Sample cse = mainInfo.idRef.theCase.getItem();
7231 02 Jun 23 nicklas 284         // We should only link Specimen->Case if the the
7231 02 Jun 23 nicklas 285         // Case already has Patient. If not, the Case is
7231 02 Jun 23 nicklas 286         // a free-floating consent registration only 
7231 02 Jun 23 nicklas 287         // which may have to be merged with another Case 
7231 02 Jun 23 nicklas 288         // of the same Patient and we don't know that yet
7231 02 Jun 23 nicklas 289         if (cse.hasSingleParent()) 
7231 02 Jun 23 nicklas 290         {
7231 02 Jun 23 nicklas 291           BioMaterialEvent creationEvent = specimen.getCreationEvent();
7231 02 Jun 23 nicklas 292           creationEvent.setSource(cse);
7231 02 Jun 23 nicklas 293         }
7231 02 Jun 23 nicklas 294       }
6572 07 Feb 22 nicklas 295       dc.saveItem(specimen);
6888 24 Nov 22 nicklas 296       addDebugMessage("Created Specimen: "+ specimen.getName());
6572 07 Feb 22 nicklas 297     }
7231 02 Jun 23 nicklas 298     else if (isMerge)
7231 02 Jun 23 nicklas 299     {
7231 02 Jun 23 nicklas 300       addDebugMessage("Merged with Specimen: "+ specimen.getName());
7231 02 Jun 23 nicklas 301     }
6572 07 Feb 22 nicklas 302     else
6572 07 Feb 22 nicklas 303     {
6572 07 Feb 22 nicklas 304       addDebugMessage("Converted NoSpecimen to Specimen: "+ specimen.getName());
6572 07 Feb 22 nicklas 305     }
6194 30 Mar 21 nicklas 306     return SpecimenTube.get(specimen);
6194 30 Mar 21 nicklas 307   }
6194 30 Mar 21 nicklas 308   
6738 10 May 22 nicklas 309   private Lysate createLysate(DbControl dc, EndPoint endPoint, SpecimenTube specimen, LysateInfo lysateInfo)
6194 30 Mar 21 nicklas 310   {
7233 02 Jun 23 nicklas 311     Extract lysate = null;
7233 02 Jun 23 nicklas 312     boolean isMerge = false;
7233 02 Jun 23 nicklas 313     if (lysateInfo.mergeWith != null)
7233 02 Jun 23 nicklas 314     {
7233 02 Jun 23 nicklas 315       lysate = Extract.getById(dc, lysateInfo.mergeWith.getId());
7233 02 Jun 23 nicklas 316       isMerge = true;
7233 02 Jun 23 nicklas 317     }
7233 02 Jun 23 nicklas 318     else
7233 02 Jun 23 nicklas 319     {
7233 02 Jun 23 nicklas 320       lysate = Extract.getNew(dc);
7233 02 Jun 23 nicklas 321       lysate.setItemSubtype(Subtype.LYSATE.get(dc));
7233 02 Jun 23 nicklas 322       lysate.setName(specimen.getNextLysateName(dc));
7233 02 Jun 23 nicklas 323     }
6207 12 Apr 21 nicklas 324
6194 30 Mar 21 nicklas 325     BioMaterialEvent creationEvent = lysate.getCreationEvent();
6207 12 Apr 21 nicklas 326     BioMaterialEventSource specSrc = creationEvent.setSource(specimen.getItem());
6207 12 Apr 21 nicklas 327     creationEvent.setEventDate(lysateInfo.lysateDate);
6888 24 Nov 22 nicklas 328     if (lysateInfo.protocol != null) addDebugMessage("Found Protocol: " + lysateInfo.protocol.getName());
6207 12 Apr 21 nicklas 329     creationEvent.setProtocol(lysateInfo.protocol);
6207 12 Apr 21 nicklas 330     creationEvent.setHardware(null);
6207 12 Apr 21 nicklas 331     
6207 12 Apr 21 nicklas 332     Annotationtype.PARTITION_DATE.setAnnotationValue(dc, lysate, lysateInfo.partitionDate);
6711 27 Apr 22 nicklas 333     Annotationtype.TUBE_LABEL.setAnnotationValue(dc, lysate, lysateInfo.tubeLabel);
6715 29 Apr 22 nicklas 334     if (lysateInfo.usedNumberOfPieces != null && lysateInfo.usedNumberOfPieces > 1)
6715 29 Apr 22 nicklas 335     {
6715 29 Apr 22 nicklas 336       Annotationtype.MULTIPLE_PIECES.setAnnotationValue(dc, lysate, true);
6715 29 Apr 22 nicklas 337     }
6738 10 May 22 nicklas 338     Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, lysate, "Disable");
6711 27 Apr 22 nicklas 339     
6714 29 Apr 22 nicklas 340     lysate.setOriginalQuantity(lysateInfo.originalVolume_ul);
6916 01 Dec 22 nicklas 341     // TODO -- should we auto-correct if the used quantity > specimen.original quantity?
6714 29 Apr 22 nicklas 342     specSrc.setUsedQuantity(multiply(lysateInfo.usedFromSpecimen_mg, 1000));
6207 12 Apr 21 nicklas 343     
7233 02 Jun 23 nicklas 344     if (!isMerge)
7233 02 Jun 23 nicklas 345     {
7233 02 Jun 23 nicklas 346       Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, lysate, lysateInfo.storageLocation);
7233 02 Jun 23 nicklas 347       dc.saveItem(lysate);
7233 02 Jun 23 nicklas 348       addDebugMessage("Created Lysate: "+ lysate.getName());
7233 02 Jun 23 nicklas 349     }
7233 02 Jun 23 nicklas 350     else
7233 02 Jun 23 nicklas 351     {
7233 02 Jun 23 nicklas 352       addDebugMessage("Merged with Lysate: "+ lysate.getName());
7233 02 Jun 23 nicklas 353     }
6194 30 Mar 21 nicklas 354     return Lysate.get(lysate);
6194 30 Mar 21 nicklas 355   }
6194 30 Mar 21 nicklas 356   
6738 10 May 22 nicklas 357   private Rna createRna(DbControl dc, EndPoint endPoint, Lysate lysate, RnaInfo rnaInfo)
6194 30 Mar 21 nicklas 358   {
7233 02 Jun 23 nicklas 359     Extract rna = null;
7233 02 Jun 23 nicklas 360     boolean isMerge = false;
7233 02 Jun 23 nicklas 361     if (rnaInfo.mergeWith != null)
7233 02 Jun 23 nicklas 362     {
7233 02 Jun 23 nicklas 363       rna = Extract.getById(dc, rnaInfo.mergeWith.getId());
7233 02 Jun 23 nicklas 364       isMerge = true;
7233 02 Jun 23 nicklas 365     }
7233 02 Jun 23 nicklas 366     else
7233 02 Jun 23 nicklas 367     {
7233 02 Jun 23 nicklas 368       rna = Extract.getNew(dc);
7233 02 Jun 23 nicklas 369       rna.setItemSubtype(Subtype.RNA.get(dc));
7233 02 Jun 23 nicklas 370       rna.setName(lysate.getNextChildName(dc, Subtype.RNA));
7233 02 Jun 23 nicklas 371     }
6207 12 Apr 21 nicklas 372
6194 30 Mar 21 nicklas 373     BioMaterialEvent creationEvent = rna.getCreationEvent();
6207 12 Apr 21 nicklas 374     BioMaterialEventSource lysSrc = creationEvent.setSource(lysate.getItem());
6207 12 Apr 21 nicklas 375     creationEvent.setEventDate(rnaInfo.qiacubeDate);
6888 24 Nov 22 nicklas 376     if (rnaInfo.protocol != null) addDebugMessage("Found Protocol: " + rnaInfo.protocol.getName());
6207 12 Apr 21 nicklas 377     creationEvent.setProtocol(rnaInfo.protocol);
6207 12 Apr 21 nicklas 378     creationEvent.setHardware(null);
6194 30 Mar 21 nicklas 379
6207 12 Apr 21 nicklas 380     Annotationtype.QIACUBE_DATE.setAnnotationValue(dc, rna, rnaInfo.qiacubeDate);
6207 12 Apr 21 nicklas 381     Annotationtype.QIACUBE_RUN_NO.setAnnotationValue(dc, rna, rnaInfo.qiacubeRunNumber);
6481 22 Nov 21 nicklas 382     Annotationtype.QIACUBE_RUN_ID.setAnnotationValue(dc, rna, rnaInfo.qiacubeRunId);
6207 12 Apr 21 nicklas 383     Annotationtype.QIACUBE_POSITION.setAnnotationValue(dc, rna, rnaInfo.qiacubePos);
6207 12 Apr 21 nicklas 384     Annotationtype.QIACUBE_OPERATOR.setAnnotationValue(dc, rna, rnaInfo.operator);
6711 27 Apr 22 nicklas 385     Annotationtype.TUBE_LABEL.setAnnotationValue(dc, rna, rnaInfo.tubeLabel);
6207 12 Apr 21 nicklas 386     Annotationtype.QUBIT_CONC.setAnnotationValue(dc, rna, rnaInfo.qubitConc);
6738 10 May 22 nicklas 387     Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, rna, "Disable");
6714 29 Apr 22 nicklas 388     rna.setOriginalQuantity(divide(rnaInfo.originalQuantity_ng, 1000));
6714 29 Apr 22 nicklas 389     lysSrc.setUsedQuantity(rnaInfo.usedVolumeFromLysate_ul);
7233 02 Jun 23 nicklas 390     if (!isMerge)
7233 02 Jun 23 nicklas 391     {
7233 02 Jun 23 nicklas 392       Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, rna, rnaInfo.storageLocation);
7233 02 Jun 23 nicklas 393       dc.saveItem(rna);
7233 02 Jun 23 nicklas 394       addDebugMessage("Created RNA: "+ rna.getName());
7233 02 Jun 23 nicklas 395     }
7233 02 Jun 23 nicklas 396     else
7233 02 Jun 23 nicklas 397     {
7233 02 Jun 23 nicklas 398       addDebugMessage("Merged with RNA: "+ rna.getName());
7233 02 Jun 23 nicklas 399     }
6194 30 Mar 21 nicklas 400     return Rna.get(rna);
6194 30 Mar 21 nicklas 401   }
6194 30 Mar 21 nicklas 402   
6738 10 May 22 nicklas 403   private Dna createDna(DbControl dc, EndPoint endPoint, Lysate lysate, DnaInfo dnaInfo)
6207 12 Apr 21 nicklas 404   {
7233 02 Jun 23 nicklas 405     Extract dna = null;
7233 02 Jun 23 nicklas 406     boolean isMerge = false;
7233 02 Jun 23 nicklas 407     if (dnaInfo.mergeWith != null)
7233 02 Jun 23 nicklas 408     {
7233 02 Jun 23 nicklas 409       dna = Extract.getById(dc, dnaInfo.mergeWith.getId());
7233 02 Jun 23 nicklas 410       isMerge = true;
7233 02 Jun 23 nicklas 411     }
7233 02 Jun 23 nicklas 412     else
7233 02 Jun 23 nicklas 413     {
7233 02 Jun 23 nicklas 414       dna = Extract.getNew(dc);
7233 02 Jun 23 nicklas 415       dna.setItemSubtype(Subtype.DNA.get(dc));
7233 02 Jun 23 nicklas 416       dna.setName(lysate.getNextChildName(dc, Subtype.DNA));
7233 02 Jun 23 nicklas 417     }
6207 12 Apr 21 nicklas 418
6207 12 Apr 21 nicklas 419     BioMaterialEvent creationEvent = dna.getCreationEvent();
6207 12 Apr 21 nicklas 420     BioMaterialEventSource lysSrc = creationEvent.setSource(lysate.getItem());
6207 12 Apr 21 nicklas 421     creationEvent.setEventDate(dnaInfo.qiacubeDate);
6888 24 Nov 22 nicklas 422     if (dnaInfo.protocol != null) addDebugMessage("Found Protocol: " + dnaInfo.protocol.getName());
6207 12 Apr 21 nicklas 423     creationEvent.setProtocol(dnaInfo.protocol);
6207 12 Apr 21 nicklas 424     creationEvent.setHardware(null);
6207 12 Apr 21 nicklas 425
6207 12 Apr 21 nicklas 426     Annotationtype.QIACUBE_DATE.setAnnotationValue(dc, dna, dnaInfo.qiacubeDate);
6207 12 Apr 21 nicklas 427     Annotationtype.QIACUBE_RUN_NO.setAnnotationValue(dc, dna, dnaInfo.qiacubeRunNumber);
6481 22 Nov 21 nicklas 428     Annotationtype.QIACUBE_RUN_ID.setAnnotationValue(dc, dna, dnaInfo.qiacubeRunId);
6207 12 Apr 21 nicklas 429     Annotationtype.QIACUBE_POSITION.setAnnotationValue(dc, dna, dnaInfo.qiacubePos);
6207 12 Apr 21 nicklas 430     Annotationtype.QIACUBE_OPERATOR.setAnnotationValue(dc, dna, dnaInfo.operator);
6711 27 Apr 22 nicklas 431     Annotationtype.TUBE_LABEL.setAnnotationValue(dc, dna, dnaInfo.tubeLabel);
6207 12 Apr 21 nicklas 432     Annotationtype.QUBIT_CONC.setAnnotationValue(dc, dna, dnaInfo.qubitConc);
6714 29 Apr 22 nicklas 433     dna.setOriginalQuantity(divide(dnaInfo.originalQuantity_ng, 1000));
6714 29 Apr 22 nicklas 434     lysSrc.setUsedQuantity(dnaInfo.usedVolumeFromLysate_ul);
7233 02 Jun 23 nicklas 435     if (!isMerge)
7233 02 Jun 23 nicklas 436     {
7233 02 Jun 23 nicklas 437       Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, dna, dnaInfo.storageLocation);
7233 02 Jun 23 nicklas 438       dc.saveItem(dna);
7233 02 Jun 23 nicklas 439       addDebugMessage("Created DNA: "+ dna.getName());
7233 02 Jun 23 nicklas 440     }
7233 02 Jun 23 nicklas 441     else
7233 02 Jun 23 nicklas 442     {
7233 02 Jun 23 nicklas 443       addDebugMessage("Merged with DNA: "+ dna.getName());
7233 02 Jun 23 nicklas 444     }
6207 12 Apr 21 nicklas 445     return Dna.get(dna);
6207 12 Apr 21 nicklas 446   }
6207 12 Apr 21 nicklas 447
6738 10 May 22 nicklas 448   private FlowThrough createFlowThrough(DbControl dc, EndPoint endPoint, Lysate lysate, FlowThroughInfo ftInfo)
6207 12 Apr 21 nicklas 449   {
7233 02 Jun 23 nicklas 450     Extract ft = null;
7233 02 Jun 23 nicklas 451     boolean isMerge = false;
7233 02 Jun 23 nicklas 452     if (ftInfo.mergeWith != null)
7233 02 Jun 23 nicklas 453     {
7233 02 Jun 23 nicklas 454       ft = Extract.getById(dc, ftInfo.mergeWith.getId());
7233 02 Jun 23 nicklas 455       isMerge = true;
7233 02 Jun 23 nicklas 456     }
7233 02 Jun 23 nicklas 457     else
7233 02 Jun 23 nicklas 458     {
7233 02 Jun 23 nicklas 459       ft = Extract.getNew(dc);
7233 02 Jun 23 nicklas 460       ft.setItemSubtype(Subtype.FLOW_THROUGH.get(dc));
7233 02 Jun 23 nicklas 461       ft.setName(lysate.getNextChildName(dc, Subtype.FLOW_THROUGH));
7233 02 Jun 23 nicklas 462     }
7233 02 Jun 23 nicklas 463     
6207 12 Apr 21 nicklas 464     BioMaterialEvent creationEvent = ft.getCreationEvent();
6207 12 Apr 21 nicklas 465     BioMaterialEventSource lysSrc = creationEvent.setSource(lysate.getItem());
6207 12 Apr 21 nicklas 466     creationEvent.setEventDate(ftInfo.qiacubeDate);
6888 24 Nov 22 nicklas 467     if (ftInfo.protocol != null) addDebugMessage("Found Protocol: " + ftInfo.protocol.getName());
6207 12 Apr 21 nicklas 468     creationEvent.setProtocol(ftInfo.protocol);
6207 12 Apr 21 nicklas 469     creationEvent.setHardware(null);
6207 12 Apr 21 nicklas 470
6207 12 Apr 21 nicklas 471     Annotationtype.QIACUBE_DATE.setAnnotationValue(dc, ft, ftInfo.qiacubeDate);
6207 12 Apr 21 nicklas 472     Annotationtype.QIACUBE_RUN_NO.setAnnotationValue(dc, ft, ftInfo.qiacubeRunNumber);
6481 22 Nov 21 nicklas 473     Annotationtype.QIACUBE_RUN_ID.setAnnotationValue(dc, ft, ftInfo.qiacubeRunId);
6207 12 Apr 21 nicklas 474     Annotationtype.QIACUBE_POSITION.setAnnotationValue(dc, ft, ftInfo.qiacubePos);
6207 12 Apr 21 nicklas 475     Annotationtype.QIACUBE_OPERATOR.setAnnotationValue(dc, ft, ftInfo.operator);
6711 27 Apr 22 nicklas 476     Annotationtype.TUBE_LABEL.setAnnotationValue(dc, ft, ftInfo.tubeLabel);
6714 29 Apr 22 nicklas 477     ft.setOriginalQuantity(ftInfo.originalVolume_ul);
6714 29 Apr 22 nicklas 478     lysSrc.setUsedQuantity(ftInfo.usedVolumeFromLysate_ul);
7233 02 Jun 23 nicklas 479     if (!isMerge)
7233 02 Jun 23 nicklas 480     {
7233 02 Jun 23 nicklas 481       Annotationtype.EXTERNAL_STORAGE.setAnnotationValue(dc, ft, ftInfo.storageLocation);
7233 02 Jun 23 nicklas 482       dc.saveItem(ft);
7233 02 Jun 23 nicklas 483       addDebugMessage("Created FlowThrough: "+ ft.getName());
7233 02 Jun 23 nicklas 484     }
7233 02 Jun 23 nicklas 485     else
7233 02 Jun 23 nicklas 486     {
7233 02 Jun 23 nicklas 487       addDebugMessage("Merged with FlowThroguh: "+ ft.getName());
7233 02 Jun 23 nicklas 488     }
6207 12 Apr 21 nicklas 489     return FlowThrough.get(ft);
6207 12 Apr 21 nicklas 490   }
6207 12 Apr 21 nicklas 491
6738 10 May 22 nicklas 492   private RnaQc createRnaQc(DbControl dc, EndPoint endPoint, Rna rna, RnaInfo rnaInfo)
6207 12 Apr 21 nicklas 493   {
6207 12 Apr 21 nicklas 494     Extract rnaQc = Extract.getNew(dc);
6207 12 Apr 21 nicklas 495     rnaQc.setItemSubtype(Subtype.RNAQC.get(dc));
6207 12 Apr 21 nicklas 496     rnaQc.setName(rna.getNextRnaQcName(dc));
6207 12 Apr 21 nicklas 497     
6207 12 Apr 21 nicklas 498     BioMaterialEvent creationEvent = rnaQc.getCreationEvent();
6207 12 Apr 21 nicklas 499     creationEvent.setSource(rna.getItem());
6207 12 Apr 21 nicklas 500     creationEvent.setEventDate(rnaInfo.qiacubeDate);
6209 13 Apr 21 nicklas 501     creationEvent.setProtocol(null);
6209 13 Apr 21 nicklas 502     creationEvent.setHardware(null);
6207 12 Apr 21 nicklas 503     
6482 22 Nov 21 nicklas 504     Annotationtype.BA_RIN.setAnnotationValue(dc, rnaQc, rnaInfo.rin);
6207 12 Apr 21 nicklas 505     
6207 12 Apr 21 nicklas 506     dc.saveItem(rnaQc);
6888 24 Nov 22 nicklas 507     addDebugMessage("Created RNAQC: "+ rnaQc.getName());
6207 12 Apr 21 nicklas 508     return RnaQc.get(rnaQc);
6207 12 Apr 21 nicklas 509   }
6207 12 Apr 21 nicklas 510   
6737 10 May 22 nicklas 511   private Library createLibrary(DbControl dc, EndPoint endPoint, Rna rna, LibraryInfo info)
6194 30 Mar 21 nicklas 512   {
6341 29 Jun 21 nicklas 513     ItemSubtype rnaType = rna.getItem().getItemSubtype();
6194 30 Mar 21 nicklas 514     Extract lib = Extract.getNew(dc);
6194 30 Mar 21 nicklas 515     lib.setItemSubtype(Subtype.LIBRARY.get(dc));
6194 30 Mar 21 nicklas 516     lib.setName(rna.getNextLibOrMRnaName(dc, Subtype.LIBRARY));
6205 12 Apr 21 nicklas 517     Pipeline.RNA_SEQ.setAnnotation(dc, lib);
6194 30 Mar 21 nicklas 518     BioMaterialEvent creationEvent = lib.getCreationEvent();
6207 12 Apr 21 nicklas 519     BioMaterialEventSource rnaSrc = creationEvent.setSource(rna.getItem());
6341 29 Jun 21 nicklas 520     if (Subtype.RNA_NORMALIZED_ALIQUOT.get(dc).equals(rnaType))
6341 29 Jun 21 nicklas 521     {
6341 29 Jun 21 nicklas 522       rnaSrc.setUsedQuantity(rna.getItem().getRemainingQuantity());
6341 29 Jun 21 nicklas 523     }
6341 29 Jun 21 nicklas 524     else
6341 29 Jun 21 nicklas 525     {
6714 29 Apr 22 nicklas 526       rnaSrc.setUsedQuantity(divide(info.usedQuantityFromRna_ng, 1000));
6341 29 Jun 21 nicklas 527     }
6194 30 Mar 21 nicklas 528
6199 08 Apr 21 nicklas 529     // Library annotations
6887 24 Nov 22 nicklas 530     lib.setTag(getOrCreateBarcode(dc, endPoint, info.barcodeInfo));
6205 12 Apr 21 nicklas 531     creationEvent.setEventDate(info.libDate);
6888 24 Nov 22 nicklas 532     if (info.protocol != null) addDebugMessage("Found Protocol: " + info.protocol.getName());
6205 12 Apr 21 nicklas 533     creationEvent.setProtocol(info.protocol);
6199 08 Apr 21 nicklas 534     creationEvent.setHardware(null);
6199 08 Apr 21 nicklas 535     
6199 08 Apr 21 nicklas 536     Annotationtype.QUBIT_CONC.setAnnotationValue(dc, lib, info.qubitConc);
7286 15 Aug 23 nicklas 537     Annotationtype.QUANTIT_CONC.setAnnotationValue(dc, lib, info.quantItConc);
6199 08 Apr 21 nicklas 538     Annotationtype.LIBRARY_SIZE_EST.setAnnotationValue(dc, lib, info.libSize);
6199 08 Apr 21 nicklas 539     Annotationtype.LIBRARY_MOLARITY_EST.setAnnotationValue(dc, lib, info.libMolarity);
6199 08 Apr 21 nicklas 540     Annotationtype.EXTERNAL_OPERATOR.setAnnotationValue(dc, lib, info.operator);
6194 30 Mar 21 nicklas 541     dc.saveItem(lib);
6194 30 Mar 21 nicklas 542     
6199 08 Apr 21 nicklas 543     // Library plate
6737 10 May 22 nicklas 544     BioPlate libPlate = getOrCreateLibPlate(dc, endPoint, info);
6199 08 Apr 21 nicklas 545     if (libPlate != null)
6195 31 Mar 21 nicklas 546     {
6199 08 Apr 21 nicklas 547       PlateCoordinate pos = info.well;
6199 08 Apr 21 nicklas 548       if (pos != null)
6195 31 Mar 21 nicklas 549       {
6199 08 Apr 21 nicklas 550         BioWell well = libPlate.getBioWell(pos);
6205 12 Apr 21 nicklas 551         lib.setBioWell(well);
6240 19 May 21 nicklas 552         addDebugMessage("Using well: "+libPlate.getName()+"["+ well.getCoordinate()+"; ExternalRef="+info.plateId+"]");
6195 31 Mar 21 nicklas 553       }
6195 31 Mar 21 nicklas 554     }
6195 31 Mar 21 nicklas 555     
6888 24 Nov 22 nicklas 556     addDebugMessage("Created Library: "+ lib.getName());
6194 30 Mar 21 nicklas 557     return Library.get(lib);
6194 30 Mar 21 nicklas 558   }
6194 30 Mar 21 nicklas 559   
6887 24 Nov 22 nicklas 560   private Tag getOrCreateBarcode(DbControl dc, EndPoint endPoint, BarcodeInfo info)
6887 24 Nov 22 nicklas 561   {
6887 24 Nov 22 nicklas 562     String tagName = info.name;
6887 24 Nov 22 nicklas 563     if (tagName == null) return null;
6887 24 Nov 22 nicklas 564     
6887 24 Nov 22 nicklas 565     Tag tag = info.tag;
6887 24 Nov 22 nicklas 566     if (tag != null)
6887 24 Nov 22 nicklas 567     {
7228 01 Jun 23 nicklas 568       tag = Tag.getById(dc, tag.getId());
6888 24 Nov 22 nicklas 569       addDebugMessage("Found Tag: "+tagName);
6887 24 Nov 22 nicklas 570     }
6887 24 Nov 22 nicklas 571     else
6887 24 Nov 22 nicklas 572     {
6887 24 Nov 22 nicklas 573       tag = Tag.getNew(dc);
6887 24 Nov 22 nicklas 574       tag.setName(tagName);
6887 24 Nov 22 nicklas 575       tag.setItemSubtype(Subtype.BARCODE.get(dc));
6887 24 Nov 22 nicklas 576       Pipeline.RNA_SEQ.setAnnotation(dc, tag);
6887 24 Nov 22 nicklas 577       
6887 24 Nov 22 nicklas 578       Annotationtype.BARCODE_SET.setAnnotationValue(dc, tag, info.barcodeSet);
6887 24 Nov 22 nicklas 579       Annotationtype.BARCODE_SEQUENCE.setAnnotationValue(dc, tag, info.seq1);
6887 24 Nov 22 nicklas 580       Annotationtype.BARCODE_SEQUENCE_2.setAnnotationValue(dc, tag, info.seq2);
6887 24 Nov 22 nicklas 581       
6887 24 Nov 22 nicklas 582       dc.saveItem(tag);
6888 24 Nov 22 nicklas 583       addDebugMessage("Created Tag: "+tagName);
6887 24 Nov 22 nicklas 584     }
6887 24 Nov 22 nicklas 585     return tag;
6887 24 Nov 22 nicklas 586   }
6887 24 Nov 22 nicklas 587   
6737 10 May 22 nicklas 588   private BioPlate getOrCreateLibPlate(DbControl dc, EndPoint endPoint, LibraryInfo info)
6195 31 Mar 21 nicklas 589   {
6199 08 Apr 21 nicklas 590     String plateId = info.plateId;
6199 08 Apr 21 nicklas 591     if (plateId == null) return null;
6195 31 Mar 21 nicklas 592     
6205 12 Apr 21 nicklas 593     BioPlate plate = info.libPlate;
6205 12 Apr 21 nicklas 594     if (plate != null)
6195 31 Mar 21 nicklas 595     {
7228 01 Jun 23 nicklas 596       plate = BioPlate.getById(dc, plate.getId());
6888 24 Nov 22 nicklas 597       addDebugMessage("Found LibPlate: "+plate.getName()+"[ExternalRef="+plateId+"]");
6194 30 Mar 21 nicklas 598     }
6194 30 Mar 21 nicklas 599     else
6194 30 Mar 21 nicklas 600     {
6465 03 Nov 21 nicklas 601       BioplateType plateType = info.libPlateType;
6465 03 Nov 21 nicklas 602       if (plateType == null) plateType = BioplateType.EXTERNAL_LIBRARY; // Should not happen if LibraryInfo.valid==TRUE
6205 12 Apr 21 nicklas 603       plate = BioPlate.getNew(dc, plateType.getPlateGeometry(dc), plateType.get(dc));
6205 12 Apr 21 nicklas 604       plate.setName(plateType.getNextPlateName(dc, true));
6205 12 Apr 21 nicklas 605       Annotationtype.EXTERNAL_REF.setAnnotationValue(dc, plate, plateId);
6205 12 Apr 21 nicklas 606       plate.setEventDate(info.libDate);
6737 10 May 22 nicklas 607       plate.setDestroyed(true); // Since we don't have access to it
6205 12 Apr 21 nicklas 608
6205 12 Apr 21 nicklas 609       Annotationtype.EXTERNAL_OPERATOR.setAnnotationValue(dc, plate, info.operator);
6205 12 Apr 21 nicklas 610       Annotationtype.PLATE_PROCESS_RESULT.setAnnotationValue(dc, plate, ReactionPlate.PROCESS_SUCCESSFUL);
6737 10 May 22 nicklas 611       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, plate, "Disable");
6205 12 Apr 21 nicklas 612       // TODO -- more libplate annotations?
6205 12 Apr 21 nicklas 613       
6205 12 Apr 21 nicklas 614       dc.saveItem(plate);
6888 24 Nov 22 nicklas 615       addDebugMessage("Created LibPlate: "+plate.getName()+"[ExternalRef="+plateId+"]");
6194 30 Mar 21 nicklas 616     }
6199 08 Apr 21 nicklas 617     return plate;
6205 12 Apr 21 nicklas 618   }  
6194 30 Mar 21 nicklas 619   
6737 10 May 22 nicklas 620   private PooledLibrary getOrCreatePool(DbControl dc, EndPoint endPoint, Library lib, PoolInfo info)
6194 30 Mar 21 nicklas 621   {
6199 08 Apr 21 nicklas 622     String poolId = info.poolId;
6199 08 Apr 21 nicklas 623     if (poolId == null) return null;
6199 08 Apr 21 nicklas 624
6205 12 Apr 21 nicklas 625     Extract pool = info.pool;
6205 12 Apr 21 nicklas 626     if (pool != null)
6194 30 Mar 21 nicklas 627     {
7228 01 Jun 23 nicklas 628       pool = Extract.getById(dc, pool.getId());
6888 24 Nov 22 nicklas 629       addDebugMessage("Found Pool: "+pool.getName()+"[ExternalRef="+poolId+"]");
6194 30 Mar 21 nicklas 630     }
6199 08 Apr 21 nicklas 631     else
6199 08 Apr 21 nicklas 632     {
6205 12 Apr 21 nicklas 633       pool = Extract.getNew(dc);
6205 12 Apr 21 nicklas 634       pool.setItemSubtype(Subtype.POOLED_LIBRARY.get(dc));
6205 12 Apr 21 nicklas 635       pool.setName(PooledLibrary.getNextNames(dc, 1).get(0));
6205 12 Apr 21 nicklas 636       Pipeline.RNA_SEQ.setAnnotation(dc, pool);
6205 12 Apr 21 nicklas 637       Annotationtype.EXTERNAL_REF.setAnnotationValue(dc, pool, poolId);
6205 12 Apr 21 nicklas 638       Annotationtype.POOL_DATE.setAnnotationValue(dc, pool, info.poolDate);
6205 12 Apr 21 nicklas 639       Annotationtype.POOL_OPERATOR.setAnnotationValue(dc, pool, info.operator);
6737 10 May 22 nicklas 640       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, pool, "Disable");
6205 12 Apr 21 nicklas 641       BioMaterialEvent poolEvent = pool.getCreationEvent();
6205 12 Apr 21 nicklas 642       poolEvent.setEventDate(info.poolDate);
6205 12 Apr 21 nicklas 643       poolEvent.setProtocol(null); // To avoid that a 'project default' is used
6205 12 Apr 21 nicklas 644       poolEvent.setHardware(null);
6205 12 Apr 21 nicklas 645       
6205 12 Apr 21 nicklas 646       dc.saveItem(pool);
6888 24 Nov 22 nicklas 647       addDebugMessage("Created Pool: "+pool.getName()+"[ExternalRef="+poolId+"]");
6199 08 Apr 21 nicklas 648     }
6205 12 Apr 21 nicklas 649     
6199 08 Apr 21 nicklas 650     pool.getCreationEvent().addSource(lib.getItem());
6199 08 Apr 21 nicklas 651     return PooledLibrary.get(pool);
6194 30 Mar 21 nicklas 652   }
6194 30 Mar 21 nicklas 653   
6201 09 Apr 21 nicklas 654   
6736 10 May 22 nicklas 655   private FlowCell getOrCreateFlowCell(DbControl dc, EndPoint endPoint, PooledLibrary pool, FlowCellInfo flowCellInfo, SequencingRunInfo seqRunInfo)
6201 09 Apr 21 nicklas 656   {
6201 09 Apr 21 nicklas 657     String flowCellId = flowCellInfo.flowCellId;
6201 09 Apr 21 nicklas 658     if (flowCellId == null) return null;
6199 08 Apr 21 nicklas 659
6205 12 Apr 21 nicklas 660     PhysicalBioAssay flowCell = flowCellInfo.flowCell;
6205 12 Apr 21 nicklas 661     if (flowCell != null)
6201 09 Apr 21 nicklas 662     {
7228 01 Jun 23 nicklas 663       flowCell = PhysicalBioAssay.getById(dc, flowCell.getId());
6888 24 Nov 22 nicklas 664       addDebugMessage("Found FlowCell: "+flowCell.getName()+"[FlowCellID="+flowCellId+"]");
6205 12 Apr 21 nicklas 665     }
6205 12 Apr 21 nicklas 666     else
6205 12 Apr 21 nicklas 667     {      
6205 12 Apr 21 nicklas 668       flowCell = PhysicalBioAssay.getNew(dc);
6205 12 Apr 21 nicklas 669       flowCell.setItemSubtype(Subtype.FLOW_CELL.get(dc));
6205 12 Apr 21 nicklas 670       flowCell.setName(FlowCell.getNextNames(dc, 1).get(0));
6205 12 Apr 21 nicklas 671       Pipeline.RNA_SEQ.setAnnotation(dc, flowCell);
6205 12 Apr 21 nicklas 672       flowCell.setSize(flowCellInfo.size);
6205 12 Apr 21 nicklas 673       Annotationtype.FLOWCELL_ID.setAnnotationValue(dc, flowCell, flowCellId);
6205 12 Apr 21 nicklas 674       Annotationtype.SEQUENCING_CYCLES.setAnnotationValue(dc, flowCell, flowCellInfo.sequencingCycles);
6205 12 Apr 21 nicklas 675       Annotationtype.FLOWCELL_TYPE.setAnnotationValue(dc, flowCell, seqRunInfo.sequencer.flowCellType);
6205 12 Apr 21 nicklas 676       Annotationtype.CLUSTER_OPERATOR.setAnnotationValue(dc, flowCell, flowCellInfo.operator);
6209 13 Apr 21 nicklas 677       Annotationtype.CLUSTER_START.setAnnotationValue(dc, flowCell, seqRunInfo.startDate);
6736 10 May 22 nicklas 678       if (endPoint == EndPoint.SEQUENCING)
6736 10 May 22 nicklas 679       {
6736 10 May 22 nicklas 680         Annotationtype.PLATE_PROCESS_RESULT.setAnnotationValue(dc, flowCell, ReactionPlate.PROCESS_FAILED);
6736 10 May 22 nicklas 681         Annotationtype.SEQUENCING_RESULT.setAnnotationValue(dc, flowCell, SequencingRun.SEQUENCING_FAILED);
6736 10 May 22 nicklas 682       }
6736 10 May 22 nicklas 683       else
6736 10 May 22 nicklas 684       {
6736 10 May 22 nicklas 685         Annotationtype.PLATE_PROCESS_RESULT.setAnnotationValue(dc, flowCell, ReactionPlate.PROCESS_SUCCESSFUL);
6736 10 May 22 nicklas 686         Annotationtype.SEQUENCING_RESULT.setAnnotationValue(dc, flowCell, SequencingRun.SEQUENCING_SUCCESSFUL);
6736 10 May 22 nicklas 687       }
6205 12 Apr 21 nicklas 688       dc.saveItem(flowCell);
6205 12 Apr 21 nicklas 689       
6205 12 Apr 21 nicklas 690       BioMaterialEvent createEvent = flowCell.getCreationEvent();
6209 13 Apr 21 nicklas 691       createEvent.setEventDate(seqRunInfo.startDate);
6205 12 Apr 21 nicklas 692       createEvent.setProtocol(null); // To avoid that a 'project default' is used
6205 12 Apr 21 nicklas 693       createEvent.setHardware(seqRunInfo.sequencer.sequencer);
6205 12 Apr 21 nicklas 694       
6205 12 Apr 21 nicklas 695       // Link with pool
6205 12 Apr 21 nicklas 696       for (int laneNo = 1; laneNo <= flowCell.getSize(); laneNo++)
6201 09 Apr 21 nicklas 697       {
6205 12 Apr 21 nicklas 698         Extract poolA = Extract.getNew(dc);
6205 12 Apr 21 nicklas 699         poolA.setItemSubtype(Subtype.POOLED_LIBRARY_ALIQUOT.get(dc));
6205 12 Apr 21 nicklas 700         poolA.setName(pool.getNextAliquotName(dc));
6209 13 Apr 21 nicklas 701         BioMaterialEvent poolEvent = poolA.getCreationEvent();
6209 13 Apr 21 nicklas 702         poolEvent.setSource(pool.getItem());
6209 13 Apr 21 nicklas 703         poolEvent.setEventDate(seqRunInfo.startDate);
6205 12 Apr 21 nicklas 704         createEvent.addSource(poolA).setPosition(laneNo);
6205 12 Apr 21 nicklas 705         dc.saveItem(poolA);
6888 24 Nov 22 nicklas 706         addDebugMessage("Created PoolAliquot: "+ poolA.getName());
6201 09 Apr 21 nicklas 707       }
6205 12 Apr 21 nicklas 708       
6888 24 Nov 22 nicklas 709       addDebugMessage("Created FlowCell: "+flowCell.getName()+"[FlowCellID="+flowCellId+"]");
6201 09 Apr 21 nicklas 710     }
6201 09 Apr 21 nicklas 711         
6201 09 Apr 21 nicklas 712     return FlowCell.get(flowCell);
6201 09 Apr 21 nicklas 713   }
6201 09 Apr 21 nicklas 714
6736 10 May 22 nicklas 715   private SequencingRun getOrCreateSequencingRun(DbControl dc, EndPoint endPoint, FlowCell flowCell, FlowCellInfo flowCellInfo, SequencingRunInfo seqRunInfo)
6201 09 Apr 21 nicklas 716   {
6201 09 Apr 21 nicklas 717     String flowCellId = flowCellInfo.flowCellId;
6201 09 Apr 21 nicklas 718     if (flowCellId == null) return null;
6201 09 Apr 21 nicklas 719
6205 12 Apr 21 nicklas 720     DerivedBioAssay seqRun = seqRunInfo.sequencingRun;
6205 12 Apr 21 nicklas 721     if (seqRun != null)
6201 09 Apr 21 nicklas 722     {
7228 01 Jun 23 nicklas 723       seqRun = DerivedBioAssay.getById(dc, seqRun.getId());
6888 24 Nov 22 nicklas 724       addDebugMessage("Found SequencingRun: "+seqRun.getName()+"[FlowCellID="+flowCellId+"]");
6205 12 Apr 21 nicklas 725     }
6205 12 Apr 21 nicklas 726     else
6205 12 Apr 21 nicklas 727     {
6205 12 Apr 21 nicklas 728       seqRun = DerivedBioAssay.getNew(dc, flowCell.getItem(), null);
6205 12 Apr 21 nicklas 729       seqRun.setItemSubtype(Subtype.SEQUENCING_RUN.get(dc));
6205 12 Apr 21 nicklas 730       seqRun.setName(SequencingRun.getNextName(dc));
6205 12 Apr 21 nicklas 731       Pipeline.RNA_SEQ.setAnnotation(dc, seqRun);
6205 12 Apr 21 nicklas 732       seqRun.setHardware(seqRunInfo.sequencer.sequencer);
6205 12 Apr 21 nicklas 733       seqRun.setSoftware(null);
6205 12 Apr 21 nicklas 734       seqRun.setProtocol(null);
6205 12 Apr 21 nicklas 735       Annotationtype.HISEQ_POSITION.setAnnotationValue(dc, seqRun, seqRunInfo.position);
6205 12 Apr 21 nicklas 736       Annotationtype.SEQUENCING_RUN_NUMBER.setAnnotationValue(dc, seqRun, seqRunInfo.runNumber);
6205 12 Apr 21 nicklas 737       Annotationtype.SEQUENCING_START.setAnnotationValue(dc, seqRun, seqRunInfo.startDate);
6205 12 Apr 21 nicklas 738       Annotationtype.SEQUENCING_END.setAnnotationValue(dc, seqRun, seqRunInfo.endDate);
6205 12 Apr 21 nicklas 739       Annotationtype.SEQUENCING_OPERATOR.setAnnotationValue(dc, seqRun, seqRunInfo.operator);
6205 12 Apr 21 nicklas 740       Annotationtype.SEQUENCING_CYCLES.setAnnotationValue(dc, seqRun, flowCellInfo.sequencingCycles);
6205 12 Apr 21 nicklas 741       Annotationtype.SEQUENCING_CONFIRMED.setAnnotationValue(dc, seqRun, true);
6736 10 May 22 nicklas 742       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, seqRun, "Disable");
6736 10 May 22 nicklas 743       if (endPoint == EndPoint.SEQUENCING)
6736 10 May 22 nicklas 744       {
6736 10 May 22 nicklas 745         Annotationtype.SEQUENCING_RESULT.setAnnotationValue(dc, seqRun, SequencingRun.SEQUENCING_FAILED);
6736 10 May 22 nicklas 746       }
6736 10 May 22 nicklas 747       else
6736 10 May 22 nicklas 748       {
6736 10 May 22 nicklas 749         Annotationtype.SEQUENCING_RESULT.setAnnotationValue(dc, seqRun, SequencingRun.SEQUENCING_SUCCESSFUL);
6736 10 May 22 nicklas 750       }
6205 12 Apr 21 nicklas 751       dc.saveItem(seqRun);
6205 12 Apr 21 nicklas 752       
6888 24 Nov 22 nicklas 753       addDebugMessage("Created SequencingRun: "+ seqRun.getName());
6201 09 Apr 21 nicklas 754     }
6201 09 Apr 21 nicklas 755     return SequencingRun.get(seqRun);
6201 09 Apr 21 nicklas 756   }
6201 09 Apr 21 nicklas 757   
6203 09 Apr 21 nicklas 758   
6215 16 Apr 21 nicklas 759   private DemuxedSequences createDemuxedSequences(DbControl dc, Library lib, SequencingRun seqRun, FlowCellInfo flowCellInfo, SequencingRunInfo seqRunInfo, DemuxInfo demuxInfo, FastqInfo fastqInfo)
6194 30 Mar 21 nicklas 760   {
6194 30 Mar 21 nicklas 761
6215 16 Apr 21 nicklas 762     DerivedBioAssay demux = DerivedBioAssay.getNew(dc, seqRun.getItem(), null);
6215 16 Apr 21 nicklas 763     demux.setItemSubtype(Subtype.DEMUXED_SEQUENCES.get(dc));
6215 16 Apr 21 nicklas 764     demux.setName(lib.getNextDemuxedSequencesName(dc));
6215 16 Apr 21 nicklas 765     Pipeline.RNA_SEQ.setAnnotation(dc, demux);
6215 16 Apr 21 nicklas 766     demux.setExtract(lib.getItem());
6215 16 Apr 21 nicklas 767     demux.setHardware(null);
6215 16 Apr 21 nicklas 768     demux.setSoftware(demuxInfo.software);
6215 16 Apr 21 nicklas 769     demux.setProtocol(null);
6215 16 Apr 21 nicklas 770     Annotationtype.ANALYSIS_RESULT.setAnnotationValue(dc, demux, DemuxedSequences.DEMUX_SUCCESSFUL);
6215 16 Apr 21 nicklas 771     Annotationtype.READ_STRING.setAnnotationValue(dc, demux, demuxInfo.readString);    
6215 16 Apr 21 nicklas 772     Annotationtype.READS.setAnnotationValue(dc, demux, demuxInfo.reads);
6215 16 Apr 21 nicklas 773     Annotationtype.PF_READS.setAnnotationValue(dc, demux, demuxInfo.pfReads);
6215 16 Apr 21 nicklas 774     Annotationtype.RAW_FASTQ.setAnnotationValues(dc, demux, Arrays.asList(fastqInfo.R1.name, fastqInfo.R2.name));
6209 13 Apr 21 nicklas 775     
7025 08 Feb 23 nicklas 776     FastDateFormat df = FastDateFormat.getInstance("/yyyy/yyMMdd");
6215 16 Apr 21 nicklas 777     String dataFilesFolder = df.format(seqRunInfo.startDate)+
6215 16 Apr 21 nicklas 778       "_"+seqRunInfo.sequencer.serialNo+
6215 16 Apr 21 nicklas 779       "_"+MD5.leftPad(Integer.toString(seqRunInfo.runNumber), '0', 4)+
6215 16 Apr 21 nicklas 780       "_"+seqRunInfo.position+flowCellInfo.flowCellId;
6215 16 Apr 21 nicklas 781     addDebugMessage("DataFilesFolder: "+dataFilesFolder);
6215 16 Apr 21 nicklas 782     Annotationtype.DATA_FILES_FOLDER.setAnnotationValue(dc, demux, dataFilesFolder);
6209 13 Apr 21 nicklas 783     
6215 16 Apr 21 nicklas 784     dc.saveItem(demux);
6203 09 Apr 21 nicklas 785     
6888 24 Nov 22 nicklas 786     addDebugMessage("Created DemuxedSequences: "+ demux.getName());
6215 16 Apr 21 nicklas 787     return DemuxedSequences.get(demux);
6194 30 Mar 21 nicklas 788   }
6194 30 Mar 21 nicklas 789
7050 17 Feb 23 nicklas 790   private File[] createRawFastqFiles(DbControl dc, DemuxedSequences demux, FastqInfo fastqInfo, FileServer importGateway)
7050 17 Feb 23 nicklas 791   {
7050 17 Feb 23 nicklas 792     String dataFilesFolder = (String)Annotationtype.DATA_FILES_FOLDER.getAnnotationValue(dc, demux.getItem());
7050 17 Feb 23 nicklas 793     String baseFolder = Reggie.EXTERNAL_JSON_IMPORT_DIR+dataFilesFolder;
7050 17 Feb 23 nicklas 794     Directory baseDir = Directory.getNew(dc, new Path(baseFolder, Path.Type.DIRECTORY));
7050 17 Feb 23 nicklas 795     FileSet fileSet = demux.getItem().getFileSet();
7050 17 Feb 23 nicklas 796     DataFileType fastqData = Datafiletype.FASTQ.load(dc);
7050 17 Feb 23 nicklas 797     ItemSubtype fastqType = fastqData.getGenericType();
7050 17 Feb 23 nicklas 798     
7050 17 Feb 23 nicklas 799     File[] files = new File[2];
7050 17 Feb 23 nicklas 800     FastqFile[] fq = new FastqFile[] { fastqInfo.R1, fastqInfo.R2 };
7050 17 Feb 23 nicklas 801     for (int i = 0; i<2; i++)
7050 17 Feb 23 nicklas 802     {
7050 17 Feb 23 nicklas 803       File fastq = File.getFile(dc, baseDir, fq[i].name, true);
7050 17 Feb 23 nicklas 804       fastq.setFileServer(importGateway);
7050 17 Feb 23 nicklas 805       fastq.setItemSubtype(fastqType);
7050 17 Feb 23 nicklas 806       String fileUrl = "sftp://" + importGateway.getHost()+"/"+fastq.getName();
7050 17 Feb 23 nicklas 807       fastq.setUrl(fileUrl, fq[i].asUriMetadata());
7050 17 Feb 23 nicklas 808       fastq.setDescription("DemuxedSequences: "+ demux.getName());
7050 17 Feb 23 nicklas 809       dc.saveItem(fastq);
7050 17 Feb 23 nicklas 810       
7050 17 Feb 23 nicklas 811       fileSet.addMember(fastq, fastqData);      
7050 17 Feb 23 nicklas 812       addDebugMessage("Created FASTQ: "+fastq.getUrl());
7050 17 Feb 23 nicklas 813       files[i] = fastq;
7050 17 Feb 23 nicklas 814     }
7050 17 Feb 23 nicklas 815     return files;
7050 17 Feb 23 nicklas 816   }
7050 17 Feb 23 nicklas 817   
6210 14 Apr 21 nicklas 818   /**
6714 29 Apr 22 nicklas 819     Multiply the value with the factor, unless null.
6714 29 Apr 22 nicklas 820   */
6714 29 Apr 22 nicklas 821   private Float multiply(Float value, float factor)
6714 29 Apr 22 nicklas 822   {
6714 29 Apr 22 nicklas 823     return value == null ? null : value * factor;
6714 29 Apr 22 nicklas 824   }
6714 29 Apr 22 nicklas 825
6714 29 Apr 22 nicklas 826   /**
6714 29 Apr 22 nicklas 827     Divide the value with the divisor, unless null.
6714 29 Apr 22 nicklas 828   */
6714 29 Apr 22 nicklas 829   private Float divide(Float value, float divisor)
6714 29 Apr 22 nicklas 830   {
6714 29 Apr 22 nicklas 831     return value == null ? null : value / divisor;
6714 29 Apr 22 nicklas 832   }
6714 29 Apr 22 nicklas 833
6714 29 Apr 22 nicklas 834   
6714 29 Apr 22 nicklas 835   /**
6210 14 Apr 21 nicklas 836     Hold all imported items.
6210 14 Apr 21 nicklas 837   */
6210 14 Apr 21 nicklas 838   public static class ImportedItems
6210 14 Apr 21 nicklas 839   {
6495 01 Dec 21 nicklas 840     public Nameable importedTo; // The top item that was used in the import. Typically a Specimen or RNA
6217 19 Apr 21 nicklas 841     public SpecimenTube specimen;
6210 14 Apr 21 nicklas 842     public Lysate lysate;
6210 14 Apr 21 nicklas 843     public FlowThrough flowThrough;
6210 14 Apr 21 nicklas 844     public Dna dna;
6210 14 Apr 21 nicklas 845     public Rna rna;
6210 14 Apr 21 nicklas 846     public RnaQc rnaQc;
6210 14 Apr 21 nicklas 847     public Library lib;
6210 14 Apr 21 nicklas 848     public PooledLibrary pool;
6210 14 Apr 21 nicklas 849     public FlowCell flowCell;
6210 14 Apr 21 nicklas 850     public SequencingRun sequencingRun;
6210 14 Apr 21 nicklas 851     public DemuxedSequences demux;
7050 17 Feb 23 nicklas 852     public File[] rawFastq;
6210 14 Apr 21 nicklas 853   }
6210 14 Apr 21 nicklas 854   
6194 30 Mar 21 nicklas 855 }