src/core/net/sf/basedb/util/importer/spotdata/BaseFileImporter.java

Code
Comments
Other
Rev Date Author Line
5093 10 Sep 09 nicklas 1 /**
5093 10 Sep 09 nicklas 2   $Id$
5093 10 Sep 09 nicklas 3
5093 10 Sep 09 nicklas 4   Copyright (C) 2009 Nicklas Nordborg
5093 10 Sep 09 nicklas 5
5093 10 Sep 09 nicklas 6   This file is part of BASE - BioArray Software Environment.
5093 10 Sep 09 nicklas 7   Available at http://base.thep.lu.se/
5093 10 Sep 09 nicklas 8
5093 10 Sep 09 nicklas 9   BASE is free software; you can redistribute it and/or
5093 10 Sep 09 nicklas 10   modify it under the terms of the GNU General Public License
5093 10 Sep 09 nicklas 11   as published by the Free Software Foundation; either version 3
5093 10 Sep 09 nicklas 12   of the License, or (at your option) any later version.
5093 10 Sep 09 nicklas 13
5093 10 Sep 09 nicklas 14   BASE is distributed in the hope that it will be useful,
5093 10 Sep 09 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
5093 10 Sep 09 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5093 10 Sep 09 nicklas 17   GNU General Public License for more details.
5093 10 Sep 09 nicklas 18
5093 10 Sep 09 nicklas 19   You should have received a copy of the GNU General Public License
5093 10 Sep 09 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
5093 10 Sep 09 nicklas 21 */
5093 10 Sep 09 nicklas 22 package net.sf.basedb.util.importer.spotdata;
5093 10 Sep 09 nicklas 23
5093 10 Sep 09 nicklas 24 import java.io.IOException;
6077 03 Aug 12 nicklas 25 import java.io.InputStream;
5093 10 Sep 09 nicklas 26 import java.sql.SQLException;
5093 10 Sep 09 nicklas 27 import java.util.ArrayList;
5093 10 Sep 09 nicklas 28 import java.util.Collection;
5093 10 Sep 09 nicklas 29 import java.util.Collections;
5093 10 Sep 09 nicklas 30 import java.util.List;
5093 10 Sep 09 nicklas 31 import java.util.Map;
5093 10 Sep 09 nicklas 32
5093 10 Sep 09 nicklas 33 import net.sf.basedb.core.BioAssay;
5093 10 Sep 09 nicklas 34 import net.sf.basedb.core.BioAssaySet;
5093 10 Sep 09 nicklas 35 import net.sf.basedb.core.DatabaseException;
5093 10 Sep 09 nicklas 36 import net.sf.basedb.core.DbControl;
5093 10 Sep 09 nicklas 37 import net.sf.basedb.core.DynamicResultIterator;
5093 10 Sep 09 nicklas 38 import net.sf.basedb.core.DynamicSpotQuery;
5093 10 Sep 09 nicklas 39 import net.sf.basedb.core.IntensityTransform;
5093 10 Sep 09 nicklas 40 import net.sf.basedb.core.InvalidUseOfNullException;
5093 10 Sep 09 nicklas 41 import net.sf.basedb.core.MappingBatcher;
5093 10 Sep 09 nicklas 42 import net.sf.basedb.core.PositionBatcher;
5093 10 Sep 09 nicklas 43 import net.sf.basedb.core.ProgressReporter;
5093 10 Sep 09 nicklas 44 import net.sf.basedb.core.SimpleAbsoluteProgressReporter;
5093 10 Sep 09 nicklas 45 import net.sf.basedb.core.Transformation;
5093 10 Sep 09 nicklas 46 import net.sf.basedb.core.VirtualColumn;
5093 10 Sep 09 nicklas 47 import net.sf.basedb.core.VirtualTable;
5093 10 Sep 09 nicklas 48 import net.sf.basedb.core.data.RawData;
5093 10 Sep 09 nicklas 49 import net.sf.basedb.core.data.ReporterData;
5093 10 Sep 09 nicklas 50 import net.sf.basedb.core.query.Dynamic;
5093 10 Sep 09 nicklas 51 import net.sf.basedb.core.query.JoinType;
5093 10 Sep 09 nicklas 52 import net.sf.basedb.core.query.SqlResult;
5405 10 Sep 10 nicklas 53 import net.sf.basedb.core.signal.ThreadSignalHandler;
5093 10 Sep 09 nicklas 54 import net.sf.basedb.util.ChainedProgressReporter;
6077 03 Aug 12 nicklas 55 import net.sf.basedb.util.FileUtil;
5093 10 Sep 09 nicklas 56 import net.sf.basedb.util.basefile.BaseFileParser;
5374 03 Aug 10 nicklas 57 import net.sf.basedb.util.importer.FileWrapper;
5093 10 Sep 09 nicklas 58 import net.sf.basedb.util.importer.spotdata.BaseFileInfo.ChildBioAssay;
5093 10 Sep 09 nicklas 59 import net.sf.basedb.util.parser.FlatFileParser;
5093 10 Sep 09 nicklas 60
5093 10 Sep 09 nicklas 61 /**
5093 10 Sep 09 nicklas 62   Imports spot data from a serial or matrix BASEfile. Before it
5093 10 Sep 09 nicklas 63   can be used various configuration properties must be set.
5093 10 Sep 09 nicklas 64   <ul>
5093 10 Sep 09 nicklas 65   <li>An open DbControl: {@link #setDbControl(DbControl)}
5590 16 Mar 11 nicklas 66   <li>The source file: {@link #setSourceFileWrapper(FileWrapper)}
5093 10 Sep 09 nicklas 67   <li>The destination transaction: {@link #setTransformation(Transformation)}
5093 10 Sep 09 nicklas 68   </ul>
5093 10 Sep 09 nicklas 69   
5093 10 Sep 09 nicklas 70   Optional are:
5093 10 Sep 09 nicklas 71   <ul>
5093 10 Sep 09 nicklas 72   <li>A progress reporter: {@link #setProgressReporter(ProgressReporter)}
5093 10 Sep 09 nicklas 73   <li>The intensity transform used by the data set: 
5093 10 Sep 09 nicklas 74     {@link #setIntensityTransform(IntensityTransform)}.
5093 10 Sep 09 nicklas 75     If not set, the same intensity transform as for the parent
5093 10 Sep 09 nicklas 76     bioassay set is used
5096 14 Sep 09 nicklas 77   <li>Redefine column names. By default, column names used by BASE 1 
5374 03 Aug 10 nicklas 78     are assumed. Call {@link #useBase2ColumnNames(int)} to configure
5374 03 Aug 10 nicklas 79     the parser to use BASE 2 column names.
5093 10 Sep 09 nicklas 80   </ul>
5093 10 Sep 09 nicklas 81   
5093 10 Sep 09 nicklas 82   <p>
5093 10 Sep 09 nicklas 83   The importer will create a new child bioassay set. Child bioassays are 
5093 10 Sep 09 nicklas 84   created according to the data found in the BASEfile. The importer will
5093 10 Sep 09 nicklas 85   create a new datacube if the reporter/position mapping has changed or
5093 10 Sep 09 nicklas 86   if the child/parent bioassay relationship is not 1:1. The importer
5093 10 Sep 09 nicklas 87   supports extra values (float) and will create missing extra value types
5093 10 Sep 09 nicklas 88   if needed.
5093 10 Sep 09 nicklas 89   
5093 10 Sep 09 nicklas 90   @author Nicklas
5093 10 Sep 09 nicklas 91   @version 2.14
5093 10 Sep 09 nicklas 92   @base.modified $Date$
5093 10 Sep 09 nicklas 93 */
5093 10 Sep 09 nicklas 94 public class BaseFileImporter
5093 10 Sep 09 nicklas 95 {
5093 10 Sep 09 nicklas 96
5096 14 Sep 09 nicklas 97   private final BaseFileParser parser;
5093 10 Sep 09 nicklas 98   private DbControl dc;
5093 10 Sep 09 nicklas 99   private ProgressReporter progress;
5093 10 Sep 09 nicklas 100
5374 03 Aug 10 nicklas 101   private FileWrapper sourceFile;
5093 10 Sep 09 nicklas 102   private Transformation transformation;
5093 10 Sep 09 nicklas 103   private IntensityTransform transform;
5384 13 Aug 10 nicklas 104
5093 10 Sep 09 nicklas 105   
5093 10 Sep 09 nicklas 106   /**
5093 10 Sep 09 nicklas 107     Create a new importer object.
5093 10 Sep 09 nicklas 108   */
5093 10 Sep 09 nicklas 109   public BaseFileImporter()
5096 14 Sep 09 nicklas 110   {
5096 14 Sep 09 nicklas 111     this.parser = new BaseFileParser();
5096 14 Sep 09 nicklas 112   }
5093 10 Sep 09 nicklas 113   
5093 10 Sep 09 nicklas 114   /*
5093 10 Sep 09 nicklas 115     public Configuration properties
5093 10 Sep 09 nicklas 116     -------------------------------
5093 10 Sep 09 nicklas 117   */
5093 10 Sep 09 nicklas 118   /**
5093 10 Sep 09 nicklas 119     Set's the DbControl that should be used to get data from the database.
5093 10 Sep 09 nicklas 120   */
5093 10 Sep 09 nicklas 121   public void setDbControl(DbControl dc)
5093 10 Sep 09 nicklas 122   {
5093 10 Sep 09 nicklas 123     this.dc = dc;
5093 10 Sep 09 nicklas 124   }
5093 10 Sep 09 nicklas 125   
5093 10 Sep 09 nicklas 126   /**
5093 10 Sep 09 nicklas 127     Get the current DbControl.
5093 10 Sep 09 nicklas 128   */
5093 10 Sep 09 nicklas 129   public DbControl getDbControl()
5093 10 Sep 09 nicklas 130   {
5093 10 Sep 09 nicklas 131     return dc;
5093 10 Sep 09 nicklas 132   }
5093 10 Sep 09 nicklas 133
5093 10 Sep 09 nicklas 134   /**
5093 10 Sep 09 nicklas 135     Set the progress reporter that is used to report progress. Call
5093 10 Sep 09 nicklas 136     {@link #setProgress(int, String)} to update the current status.
5093 10 Sep 09 nicklas 137   */
5093 10 Sep 09 nicklas 138   public void setProgressReporter(ProgressReporter progress)
5093 10 Sep 09 nicklas 139   {
5093 10 Sep 09 nicklas 140     this.progress = progress;
5093 10 Sep 09 nicklas 141   }
5093 10 Sep 09 nicklas 142   
5093 10 Sep 09 nicklas 143   /**
5093 10 Sep 09 nicklas 144     Get the progress reporter.
5093 10 Sep 09 nicklas 145   */
5093 10 Sep 09 nicklas 146   public ProgressReporter getProgressReporter()
5093 10 Sep 09 nicklas 147   {
5093 10 Sep 09 nicklas 148     return progress;
5093 10 Sep 09 nicklas 149   }
5093 10 Sep 09 nicklas 150   
5093 10 Sep 09 nicklas 151   /**
5093 10 Sep 09 nicklas 152     Set the source BASEfile to import data from.
5093 10 Sep 09 nicklas 153     @param source The file
5374 03 Aug 10 nicklas 154     @since 2.16
5374 03 Aug 10 nicklas 155   */
5374 03 Aug 10 nicklas 156   public void setSourceFileWrapper(FileWrapper source)
5374 03 Aug 10 nicklas 157   {
5374 03 Aug 10 nicklas 158     this.sourceFile = source;
5374 03 Aug 10 nicklas 159   }
5374 03 Aug 10 nicklas 160   
5374 03 Aug 10 nicklas 161   /**
5374 03 Aug 10 nicklas 162     Get the source file.
5374 03 Aug 10 nicklas 163   */
5374 03 Aug 10 nicklas 164   public FileWrapper getSourceFileWrapper()
5374 03 Aug 10 nicklas 165   {
5374 03 Aug 10 nicklas 166     return sourceFile;
5374 03 Aug 10 nicklas 167   }
5374 03 Aug 10 nicklas 168     
5374 03 Aug 10 nicklas 169   /**
5093 10 Sep 09 nicklas 170     Set the destination transformation. A child bioassay set is created.
5093 10 Sep 09 nicklas 171     @param transformation The transformation
5093 10 Sep 09 nicklas 172   */
5093 10 Sep 09 nicklas 173   public void setTransformation(Transformation transformation)
5093 10 Sep 09 nicklas 174   {
5093 10 Sep 09 nicklas 175     this.transformation = transformation;
5093 10 Sep 09 nicklas 176   }
5093 10 Sep 09 nicklas 177   
5093 10 Sep 09 nicklas 178   /**
5093 10 Sep 09 nicklas 179     Get the destination transformation.
5093 10 Sep 09 nicklas 180   */
5093 10 Sep 09 nicklas 181   public Transformation getTransformation()
5093 10 Sep 09 nicklas 182   {
5093 10 Sep 09 nicklas 183     return transformation;
5093 10 Sep 09 nicklas 184   }
5093 10 Sep 09 nicklas 185   
5093 10 Sep 09 nicklas 186   /**
5093 10 Sep 09 nicklas 187     Set the intensity transform that have been applied to the spot
5093 10 Sep 09 nicklas 188     data in the file. If not specified, the same transform as for
5093 10 Sep 09 nicklas 189     the parent bioassay set is used.
5093 10 Sep 09 nicklas 190     @param transform The intensity transform
5093 10 Sep 09 nicklas 191   */
5093 10 Sep 09 nicklas 192   public void setIntensityTransform(IntensityTransform transform)
5093 10 Sep 09 nicklas 193   {
5093 10 Sep 09 nicklas 194     this.transform = transform;
5093 10 Sep 09 nicklas 195   }
5093 10 Sep 09 nicklas 196   
5093 10 Sep 09 nicklas 197   /**
5093 10 Sep 09 nicklas 198     Get the intensity transform
5093 10 Sep 09 nicklas 199   */
5093 10 Sep 09 nicklas 200   public IntensityTransform getIntensityTransform()
5093 10 Sep 09 nicklas 201   {
5093 10 Sep 09 nicklas 202     return transform;
5093 10 Sep 09 nicklas 203   }
5096 14 Sep 09 nicklas 204   
5096 14 Sep 09 nicklas 205   /**
5096 14 Sep 09 nicklas 206     Get the underlying parser for the BASEfile. It is useful when
5096 14 Sep 09 nicklas 207     there is need to change for example, name of columns, 
5096 14 Sep 09 nicklas 208     add different spot intensity parsers, etc.
5096 14 Sep 09 nicklas 209     @return The BASEfile parser
5096 14 Sep 09 nicklas 210   */
5096 14 Sep 09 nicklas 211   public BaseFileParser getBaseFileParser()
5096 14 Sep 09 nicklas 212   {
5096 14 Sep 09 nicklas 213     return parser;
5374 03 Aug 10 nicklas 214   }
5374 03 Aug 10 nicklas 215   
5374 03 Aug 10 nicklas 216   /**
5374 03 Aug 10 nicklas 217     Reconfigure the parser to use BASE 2 column names instead of BASE 1
5374 03 Aug 10 nicklas 218     column names.
5374 03 Aug 10 nicklas 219     @param channels The expected number of data channels in the file
5374 03 Aug 10 nicklas 220     @since 2.16
5374 03 Aug 10 nicklas 221   */
5374 03 Aug 10 nicklas 222   public void useBase2ColumnNames(int channels)
5374 03 Aug 10 nicklas 223   {
5374 03 Aug 10 nicklas 224     parser.setRedefinedColumnName("spots", "position", "Position");
5374 03 Aug 10 nicklas 225     parser.setRedefinedColumnName("spots", "reporter", "Internal id");
5374 03 Aug 10 nicklas 226     for (int ch = 1; ch <= channels; ++ch)
5374 03 Aug 10 nicklas 227     {
5374 03 Aug 10 nicklas 228       parser.setRedefinedColumnName("spots", "intensity" + ch, "Ch " + ch);
5374 03 Aug 10 nicklas 229     }
5374 03 Aug 10 nicklas 230   }
5093 10 Sep 09 nicklas 231   // -------------------------------
5093 10 Sep 09 nicklas 232   
5093 10 Sep 09 nicklas 233   /*
5093 10 Sep 09 nicklas 234     Helper methods
5093 10 Sep 09 nicklas 235     --------------
5093 10 Sep 09 nicklas 236   */
5093 10 Sep 09 nicklas 237   /**
5093 10 Sep 09 nicklas 238     Update the progress of the export.
5093 10 Sep 09 nicklas 239     @see ProgressReporter
5093 10 Sep 09 nicklas 240   */
5093 10 Sep 09 nicklas 241   protected void setProgress(int percent, String message)
5093 10 Sep 09 nicklas 242   {
5093 10 Sep 09 nicklas 243     if (progress != null)
5093 10 Sep 09 nicklas 244     {
5093 10 Sep 09 nicklas 245       progress.display(percent, message);
5093 10 Sep 09 nicklas 246     }
5093 10 Sep 09 nicklas 247   }
5093 10 Sep 09 nicklas 248   // ----------------------------
5093 10 Sep 09 nicklas 249
5093 10 Sep 09 nicklas 250   /**
5093 10 Sep 09 nicklas 251     Start the import.
5096 14 Sep 09 nicklas 252     @return The created bioassay set or null if the BASEfile didn't contain
5096 14 Sep 09 nicklas 253       spot data
5093 10 Sep 09 nicklas 254   */
5096 14 Sep 09 nicklas 255   public BioAssaySet doImport()
5093 10 Sep 09 nicklas 256     throws IOException
5093 10 Sep 09 nicklas 257   {
5093 10 Sep 09 nicklas 258     // Check required configuration parameters
5374 03 Aug 10 nicklas 259     FileWrapper srcFile = getSourceFileWrapper();
5093 10 Sep 09 nicklas 260     DbControl dc = getDbControl();
5093 10 Sep 09 nicklas 261     Transformation t = getTransformation();
5093 10 Sep 09 nicklas 262     if (srcFile == null) throw new InvalidUseOfNullException("sourceFile");
5093 10 Sep 09 nicklas 263     if (dc == null) throw new InvalidUseOfNullException("dbControl");
5093 10 Sep 09 nicklas 264     if (t == null) throw new InvalidUseOfNullException("transformation");
5093 10 Sep 09 nicklas 265     
5093 10 Sep 09 nicklas 266     // Get optional and derived parameters
5093 10 Sep 09 nicklas 267     BioAssaySet parent = t.getSource();
5093 10 Sep 09 nicklas 268     IntensityTransform transform = getIntensityTransform();
5093 10 Sep 09 nicklas 269     if (transform == null) transform = parent.getIntensityTransform();
5093 10 Sep 09 nicklas 270     ChainedProgressReporter chainedProgress = progress == null ? 
5093 10 Sep 09 nicklas 271       null : new ChainedProgressReporter(progress);
5093 10 Sep 09 nicklas 272     BaseFileInfo info = new BaseFileInfo(srcFile);
5093 10 Sep 09 nicklas 273     
5689 11 Aug 11 nicklas 274     // First parser pass: progress=0--30%
5093 10 Sep 09 nicklas 275     SectionAssaysParser assaysParser = new SectionAssaysParser(dc, info);
5093 10 Sep 09 nicklas 276     FirstPassSectionSpotsParser spotParser = new FirstPassSectionSpotsParser(dc, info, parent);
5093 10 Sep 09 nicklas 277     SectionReporterListParser listParser = new SectionReporterListParser(dc, info, t);
5093 10 Sep 09 nicklas 278     parser.setSectionParser("assays", assaysParser);
5093 10 Sep 09 nicklas 279     parser.setSectionParser("spots", spotParser);
5093 10 Sep 09 nicklas 280     parser.setSectionParser("reporterlist", listParser);
5093 10 Sep 09 nicklas 281     if (chainedProgress != null)
5093 10 Sep 09 nicklas 282     {
5093 10 Sep 09 nicklas 283       chainedProgress.setRange(0, 30);
5093 10 Sep 09 nicklas 284       parser.setProgressReporter(new SimpleAbsoluteProgressReporter(chainedProgress, srcFile.getSize()));
5093 10 Sep 09 nicklas 285     }
6077 03 Aug 12 nicklas 286     InputStream srcIn = srcFile.getInputStream();
6077 03 Aug 12 nicklas 287     try
5093 10 Sep 09 nicklas 288     {
6077 03 Aug 12 nicklas 289       FlatFileParser ffp = parser.parse(srcIn, srcFile.getCharacterSet());
6077 03 Aug 12 nicklas 290       int totalLines = ffp.getParsedLines();
6077 03 Aug 12 nicklas 291       
6077 03 Aug 12 nicklas 292       // If the BASEfile didn't have any 'spots' sections we don't 
6077 03 Aug 12 nicklas 293       // create a child bioassay set
6077 03 Aug 12 nicklas 294       if (parser.getSectionCount("spots") == 0) return null;
6077 03 Aug 12 nicklas 295   
6077 03 Aug 12 nicklas 296       // Create the child bioassay set and bioassays
6077 03 Aug 12 nicklas 297       boolean useNewDataCube = info.getAssaysHaveParentAssaysMapping() 
6077 03 Aug 12 nicklas 298         || info.getChildHasDifferentReporterPositionMapping();
6077 03 Aug 12 nicklas 299       BioAssaySet child = createChildBioAssaySet(dc, info, t, useNewDataCube);
6077 03 Aug 12 nicklas 300       child.setIntensityTransform(transform);
6077 03 Aug 12 nicklas 301       createChildBioAssays(dc, child, info, useNewDataCube);
6077 03 Aug 12 nicklas 302       
6077 03 Aug 12 nicklas 303       // Create the position/reporter mapping if needed
6077 03 Aug 12 nicklas 304       if (useNewDataCube)
5093 10 Sep 09 nicklas 305       {
6077 03 Aug 12 nicklas 306         if (chainedProgress != null) chainedProgress.setRange(30, 40);
6077 03 Aug 12 nicklas 307         createChildPositionReporterMapping(child, info, chainedProgress);
6077 03 Aug 12 nicklas 308         if (!info.getChildHasDifferentReporterPositionMapping() && child.getRawDataType().isStoredInDb())
6077 03 Aug 12 nicklas 309         {
6077 03 Aug 12 nicklas 310           // If the child and parent has identical position/reporter mapping
6077 03 Aug 12 nicklas 311           // we can "calculate" new raw data mappings.
6077 03 Aug 12 nicklas 312           if (chainedProgress != null) chainedProgress.setRange(40, 50);
6077 03 Aug 12 nicklas 313           createChildRawDataMapping(child, parent, info, chainedProgress);
6077 03 Aug 12 nicklas 314         }
5093 10 Sep 09 nicklas 315       }
6077 03 Aug 12 nicklas 316       FileUtil.close(srcIn);
6077 03 Aug 12 nicklas 317       
6077 03 Aug 12 nicklas 318       // Second parser pass: progress=50-100%
6077 03 Aug 12 nicklas 319       SecondPassSectionSpotsParser spotParser2 = 
6077 03 Aug 12 nicklas 320         new SecondPassSectionSpotsParser(dc, info, child, totalLines);
6077 03 Aug 12 nicklas 321       BaseFileParser secondParser = new BaseFileParser();
6077 03 Aug 12 nicklas 322       secondParser.copyRedefinedColumnNames(parser);
6077 03 Aug 12 nicklas 323       secondParser.setSectionParser("spots", spotParser2);
6077 03 Aug 12 nicklas 324       if (chainedProgress != null)
6077 03 Aug 12 nicklas 325       {
6077 03 Aug 12 nicklas 326         chainedProgress.setRange(50, 100);
6077 03 Aug 12 nicklas 327         secondParser.setProgressReporter(new SimpleAbsoluteProgressReporter(chainedProgress, totalLines));
6077 03 Aug 12 nicklas 328       }
6077 03 Aug 12 nicklas 329       srcIn = srcFile.getInputStream();
6077 03 Aug 12 nicklas 330       secondParser.parse(srcIn, srcFile.getCharacterSet());
6077 03 Aug 12 nicklas 331       return child;
5093 10 Sep 09 nicklas 332     }
6077 03 Aug 12 nicklas 333     finally
5093 10 Sep 09 nicklas 334     {
6077 03 Aug 12 nicklas 335       FileUtil.close(srcIn);
5093 10 Sep 09 nicklas 336     }
5093 10 Sep 09 nicklas 337   }
5093 10 Sep 09 nicklas 338
5093 10 Sep 09 nicklas 339   /**
5093 10 Sep 09 nicklas 340     Helper method for creating a child bioassay set using the information in the
5093 10 Sep 09 nicklas 341     BaseFileInfo object. The created bioassay set is scheduled for saving to
5093 10 Sep 09 nicklas 342     the database.
5093 10 Sep 09 nicklas 343     
5093 10 Sep 09 nicklas 344     @param dc A DbControl to use for database access
5093 10 Sep 09 nicklas 345     @param info Information from the parsed BASEfile
5093 10 Sep 09 nicklas 346     @param t The parent transformation
5093 10 Sep 09 nicklas 347     @param useNewDataCube TRUE to create the child bioassay set in a new
5093 10 Sep 09 nicklas 348       datacube, FALSE to use the same as the parent bioassay set
5093 10 Sep 09 nicklas 349     @return The new child bioassay set
5093 10 Sep 09 nicklas 350   */
5093 10 Sep 09 nicklas 351   public BioAssaySet createChildBioAssaySet(DbControl dc, BaseFileInfo info, 
5093 10 Sep 09 nicklas 352     Transformation t, boolean useNewDataCube)
5093 10 Sep 09 nicklas 353   {
5093 10 Sep 09 nicklas 354     BioAssaySet child = null;
5093 10 Sep 09 nicklas 355     if (useNewDataCube)
5093 10 Sep 09 nicklas 356     {
5093 10 Sep 09 nicklas 357       child = t.newProduct("new", "new", false);
5093 10 Sep 09 nicklas 358     }
5093 10 Sep 09 nicklas 359     else
5093 10 Sep 09 nicklas 360     {
5093 10 Sep 09 nicklas 361       child = t.newProduct(null, "new", false);
5093 10 Sep 09 nicklas 362     }
5093 10 Sep 09 nicklas 363     dc.saveItem(child);
5093 10 Sep 09 nicklas 364     return child;
5093 10 Sep 09 nicklas 365   }
5093 10 Sep 09 nicklas 366   
5093 10 Sep 09 nicklas 367   
5093 10 Sep 09 nicklas 368   /**
5093 10 Sep 09 nicklas 369     Helper method for creating new child bioassays using the information 
5093 10 Sep 09 nicklas 370     found in the BaseFileInfo object.
5093 10 Sep 09 nicklas 371     @see BaseFileInfo#getChildAssays()
5093 10 Sep 09 nicklas 372   */
5093 10 Sep 09 nicklas 373   public void createChildBioAssays(DbControl dc, BioAssaySet childSet, 
5093 10 Sep 09 nicklas 374       BaseFileInfo info, boolean useNewDataCube)
5093 10 Sep 09 nicklas 375   {
5093 10 Sep 09 nicklas 376     for (ChildBioAssay childData : info.getChildAssays())
5093 10 Sep 09 nicklas 377     {
5093 10 Sep 09 nicklas 378       BioAssay childBa = null;
5093 10 Sep 09 nicklas 379       if (useNewDataCube)
5093 10 Sep 09 nicklas 380       {
5093 10 Sep 09 nicklas 381         Collection<Integer> parentIds = childData.getParents();
5093 10 Sep 09 nicklas 382         Collection<BioAssay> parents = null;
5093 10 Sep 09 nicklas 383         if (parentIds == null || parentIds.size() == 0)
5093 10 Sep 09 nicklas 384         {
5093 10 Sep 09 nicklas 385           parents = Collections.singletonList(BioAssay.getById(dc, childData.getFileId()));
5093 10 Sep 09 nicklas 386         }
5093 10 Sep 09 nicklas 387         else
5093 10 Sep 09 nicklas 388         {
5093 10 Sep 09 nicklas 389           parents = new ArrayList<BioAssay>(parentIds.size());
5093 10 Sep 09 nicklas 390           for (Integer parentId : parentIds)
5093 10 Sep 09 nicklas 391           {
5093 10 Sep 09 nicklas 392             parents.add(BioAssay.getById(dc, parentId));
5093 10 Sep 09 nicklas 393           }
5093 10 Sep 09 nicklas 394         }
5093 10 Sep 09 nicklas 395         childBa = childSet.newBioAssay(parents);
5093 10 Sep 09 nicklas 396
5093 10 Sep 09 nicklas 397         // Store column mappings for future use
5093 10 Sep 09 nicklas 398         short childColumn = childBa.getDataCubeColumnNo();
5093 10 Sep 09 nicklas 399         for (BioAssay parentBa : parents)
5093 10 Sep 09 nicklas 400         {
5093 10 Sep 09 nicklas 401           info.mapParentChildColumns(parentBa.getDataCubeColumnNo(), childColumn);
5093 10 Sep 09 nicklas 402         }
5093 10 Sep 09 nicklas 403       }
5093 10 Sep 09 nicklas 404       else
5093 10 Sep 09 nicklas 405       {
5093 10 Sep 09 nicklas 406         BioAssay parentBa = BioAssay.getById(dc, childData.getFileId());
5093 10 Sep 09 nicklas 407         childBa = childSet.newBioAssay(parentBa);
5093 10 Sep 09 nicklas 408         // Columns should be identical... put in the mapping just be be sure
5093 10 Sep 09 nicklas 409         info.mapParentChildColumns(parentBa.getDataCubeColumnNo(), childBa.getDataCubeColumnNo());
5093 10 Sep 09 nicklas 410       }
5093 10 Sep 09 nicklas 411       if (childData.getName() != null) childBa.setName(childData.getName());
5093 10 Sep 09 nicklas 412       dc.saveItem(childBa);
5093 10 Sep 09 nicklas 413       childData.setChild(childBa);
5093 10 Sep 09 nicklas 414     }
5093 10 Sep 09 nicklas 415   }
5093 10 Sep 09 nicklas 416
5093 10 Sep 09 nicklas 417   /**
5093 10 Sep 09 nicklas 418     Helper method for creating position/reporter mappings for the child 
5093 10 Sep 09 nicklas 419     bioassay set (which must be in a new datacube). 
5093 10 Sep 09 nicklas 420     @param child The new child bioassay set
5093 10 Sep 09 nicklas 421     @param info Information about the position/reporter mapping
5093 10 Sep 09 nicklas 422       is found in {@link BaseFileInfo#getChildReporterPositions()}
5093 10 Sep 09 nicklas 423     @param progress Optional progress reporter
5093 10 Sep 09 nicklas 424   */
5093 10 Sep 09 nicklas 425   public void createChildPositionReporterMapping(BioAssaySet child, BaseFileInfo info, 
5093 10 Sep 09 nicklas 426       ProgressReporter progress)
5093 10 Sep 09 nicklas 427   {
5093 10 Sep 09 nicklas 428     PositionBatcher batcher = child.getPositionBatcher();
5093 10 Sep 09 nicklas 429     ReporterProxy proxy = new ReporterProxy();
5093 10 Sep 09 nicklas 430     Map<Integer, Integer> mapping = info.getChildReporterPositions();
5093 10 Sep 09 nicklas 431     int total = mapping.size();
5093 10 Sep 09 nicklas 432     int done = 0;
5093 10 Sep 09 nicklas 433     int delta = Math.max(total / 20, 50);
5093 10 Sep 09 nicklas 434     
5093 10 Sep 09 nicklas 435     for (Map.Entry<Integer, Integer> entry : mapping.entrySet())
5093 10 Sep 09 nicklas 436     {
5590 16 Mar 11 nicklas 437       ThreadSignalHandler.checkInterrupted();
5093 10 Sep 09 nicklas 438       if (progress != null && done % delta == 0)
5093 10 Sep 09 nicklas 439       {
5093 10 Sep 09 nicklas 440         int percent = (100 * done) / total;
5093 10 Sep 09 nicklas 441         progress.display(percent, "Mapping new reporter positions; " + 
5093 10 Sep 09 nicklas 442             done + " of " + total);
5093 10 Sep 09 nicklas 443       }
5093 10 Sep 09 nicklas 444       int position = entry.getKey();
5093 10 Sep 09 nicklas 445       Integer reporterId = entry.getValue();
5093 10 Sep 09 nicklas 446       if (reporterId == null)
5093 10 Sep 09 nicklas 447       {
5093 10 Sep 09 nicklas 448         batcher.insert(position, null);
5093 10 Sep 09 nicklas 449       }
5093 10 Sep 09 nicklas 450       else
5093 10 Sep 09 nicklas 451       {
5093 10 Sep 09 nicklas 452         proxy.setTheId(reporterId);
5093 10 Sep 09 nicklas 453         batcher.insert(position, proxy);
5093 10 Sep 09 nicklas 454       }
5093 10 Sep 09 nicklas 455       ++done;
5093 10 Sep 09 nicklas 456     }
5093 10 Sep 09 nicklas 457     batcher.flush();
5093 10 Sep 09 nicklas 458     batcher.close();
5093 10 Sep 09 nicklas 459   }
5093 10 Sep 09 nicklas 460   
5093 10 Sep 09 nicklas 461   /**
5093 10 Sep 09 nicklas 462     Helper method for creating a rawdata mapping for the child bioassay set.
5093 10 Sep 09 nicklas 463     This can only be done if the child is in a new data cube and if the
5093 10 Sep 09 nicklas 464     position/reporter mapping hasn't change. Since we know the child/parent
5093 10 Sep 09 nicklas 465     bioassay set mapping, the raw data mapping for a spot in the child is the 
5093 10 Sep 09 nicklas 466     same as the raw data mapping for the spots at the same position among the
5093 10 Sep 09 nicklas 467     parents.
5093 10 Sep 09 nicklas 468     <p>
5093 10 Sep 09 nicklas 469     Child/parent mapping is taken from the BaseFileInfo object. See
5093 10 Sep 09 nicklas 470     {@link BaseFileInfo#getChildColumns(short)}. This mapping automatically
5093 10 Sep 09 nicklas 471     created by {@link #createChildBioAssays(DbControl, BioAssaySet, BaseFileInfo, boolean)}.
5093 10 Sep 09 nicklas 472     
5093 10 Sep 09 nicklas 473     @param child The new child bioassay set
5093 10 Sep 09 nicklas 474     @param parent The parent bioassay set
5093 10 Sep 09 nicklas 475     @param info Information about the child/parent mapping
5093 10 Sep 09 nicklas 476       is found in {@link BaseFileInfo#getChildColumns(short)} 
5093 10 Sep 09 nicklas 477     @param progress Optional progress reporter
5093 10 Sep 09 nicklas 478   */
5093 10 Sep 09 nicklas 479   public void createChildRawDataMapping(BioAssaySet child, BioAssaySet parent, 
5093 10 Sep 09 nicklas 480     BaseFileInfo info, ProgressReporter progress)
5093 10 Sep 09 nicklas 481   {
5093 10 Sep 09 nicklas 482     MappingBatcher mapBatcher = child.getMappingBatcher();
5093 10 Sep 09 nicklas 483     DynamicSpotQuery spotQuery = parent.getSpotData();
5093 10 Sep 09 nicklas 484     spotQuery.joinRawData(JoinType.INNER);
5093 10 Sep 09 nicklas 485     spotQuery.select(Dynamic.select(VirtualColumn.COLUMN));
5093 10 Sep 09 nicklas 486     spotQuery.select(Dynamic.select(VirtualColumn.POSITION));
5093 10 Sep 09 nicklas 487     spotQuery.select(Dynamic.select(VirtualTable.RAWPARENTS, VirtualColumn.RAWDATA_ID));
5093 10 Sep 09 nicklas 488     
5093 10 Sep 09 nicklas 489     int total = parent.getNumSpots();
5093 10 Sep 09 nicklas 490     int done = 0;
5093 10 Sep 09 nicklas 491     int delta = Math.max(total / 20, 50);
5093 10 Sep 09 nicklas 492     
5093 10 Sep 09 nicklas 493     DynamicResultIterator spotIterator = spotQuery.iterate(dc);
5093 10 Sep 09 nicklas 494     RawDataProxy rawProxy = new RawDataProxy();
5093 10 Sep 09 nicklas 495     try
5093 10 Sep 09 nicklas 496     {
5093 10 Sep 09 nicklas 497       while (spotIterator.hasNext())
5093 10 Sep 09 nicklas 498       {
5590 16 Mar 11 nicklas 499         ThreadSignalHandler.checkInterrupted();
5093 10 Sep 09 nicklas 500         if (progress != null && done % delta == 0)
5093 10 Sep 09 nicklas 501         {
5093 10 Sep 09 nicklas 502           int percent = (100 * done) / total;
5093 10 Sep 09 nicklas 503           progress.display(percent, "Mapping new raw data positions; " + 
5093 10 Sep 09 nicklas 504               done + " of " + total);
5093 10 Sep 09 nicklas 505         }
5093 10 Sep 09 nicklas 506         SqlResult result = spotIterator.next();
5093 10 Sep 09 nicklas 507         short parentColumn = result.getShort(1);
5093 10 Sep 09 nicklas 508         int position = result.getInt(2);
5093 10 Sep 09 nicklas 509         int rawDataId = result.getInt(3);
5093 10 Sep 09 nicklas 510         List<Short> childColumns = info.getChildColumns(parentColumn);
5093 10 Sep 09 nicklas 511         if (childColumns != null)
5093 10 Sep 09 nicklas 512         {
5093 10 Sep 09 nicklas 513           rawProxy.setTheId(rawDataId);
5093 10 Sep 09 nicklas 514           for (short childColumn : childColumns)
5093 10 Sep 09 nicklas 515           {
5093 10 Sep 09 nicklas 516             mapBatcher.insert(childColumn, position, rawProxy);
5093 10 Sep 09 nicklas 517           }
5093 10 Sep 09 nicklas 518         }
5093 10 Sep 09 nicklas 519         ++done;
5093 10 Sep 09 nicklas 520       }
5093 10 Sep 09 nicklas 521     }
5093 10 Sep 09 nicklas 522     catch (SQLException ex)
5093 10 Sep 09 nicklas 523     {
5093 10 Sep 09 nicklas 524       throw new DatabaseException(ex);
5093 10 Sep 09 nicklas 525     }
5093 10 Sep 09 nicklas 526     mapBatcher.flush();
5093 10 Sep 09 nicklas 527     mapBatcher.close();
5093 10 Sep 09 nicklas 528   }
5093 10 Sep 09 nicklas 529   
5093 10 Sep 09 nicklas 530   static class ReporterProxy
5093 10 Sep 09 nicklas 531     extends ReporterData
5093 10 Sep 09 nicklas 532   {
5093 10 Sep 09 nicklas 533     private int id;
5093 10 Sep 09 nicklas 534     ReporterProxy()
5093 10 Sep 09 nicklas 535     {}
5093 10 Sep 09 nicklas 536     public void setTheId(int id)
5093 10 Sep 09 nicklas 537     {
5093 10 Sep 09 nicklas 538       this.id = id;
5093 10 Sep 09 nicklas 539     }
5093 10 Sep 09 nicklas 540     @Override
5093 10 Sep 09 nicklas 541     public int getId()
5093 10 Sep 09 nicklas 542     {
5093 10 Sep 09 nicklas 543       return id;
5093 10 Sep 09 nicklas 544     }
5093 10 Sep 09 nicklas 545   }
5093 10 Sep 09 nicklas 546
5093 10 Sep 09 nicklas 547   static class RawDataProxy
5093 10 Sep 09 nicklas 548     extends RawData
5093 10 Sep 09 nicklas 549   {
5093 10 Sep 09 nicklas 550     private int id;
5093 10 Sep 09 nicklas 551     RawDataProxy()
5093 10 Sep 09 nicklas 552     {}
5093 10 Sep 09 nicklas 553     public void setTheId(int id)
5093 10 Sep 09 nicklas 554     {
5093 10 Sep 09 nicklas 555       this.id = id;
5093 10 Sep 09 nicklas 556     }
5093 10 Sep 09 nicklas 557     @Override
5093 10 Sep 09 nicklas 558     public int getId()
5093 10 Sep 09 nicklas 559     {
5093 10 Sep 09 nicklas 560       return id;
5093 10 Sep 09 nicklas 561     }
5093 10 Sep 09 nicklas 562   }  
5093 10 Sep 09 nicklas 563   
5093 10 Sep 09 nicklas 564 }