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

Code
Comments
Other
Rev Date Author Line
3834 11 Apr 16 nicklas 1 package net.sf.basedb.reggie.plugins;
3834 11 Apr 16 nicklas 2
3834 11 Apr 16 nicklas 3 import java.io.IOException;
3834 11 Apr 16 nicklas 4 import java.io.InputStream;
3834 11 Apr 16 nicklas 5 import java.util.HashMap;
3834 11 Apr 16 nicklas 6 import java.util.Map;
3834 11 Apr 16 nicklas 7 import java.util.regex.Pattern;
3834 11 Apr 16 nicklas 8
3834 11 Apr 16 nicklas 9 import net.sf.basedb.core.AnnotationSet;
3834 11 Apr 16 nicklas 10 import net.sf.basedb.core.AnnotationType;
3834 11 Apr 16 nicklas 11 import net.sf.basedb.core.BioPlate;
3834 11 Apr 16 nicklas 12 import net.sf.basedb.core.DbControl;
3834 11 Apr 16 nicklas 13 import net.sf.basedb.core.Extract;
3834 11 Apr 16 nicklas 14 import net.sf.basedb.core.Type;
3834 11 Apr 16 nicklas 15 import net.sf.basedb.reggie.converter.ValueConverter;
3834 11 Apr 16 nicklas 16 import net.sf.basedb.util.parser.FlatFileParser;
3834 11 Apr 16 nicklas 17 import net.sf.basedb.util.parser.FlatFileParser.LineType;
3834 11 Apr 16 nicklas 18 import net.sf.basedb.util.parser.Mapper;
3834 11 Apr 16 nicklas 19
3834 11 Apr 16 nicklas 20 /**
3834 11 Apr 16 nicklas 21   Plug-in for importing annotations to biomaterial on
3834 11 Apr 16 nicklas 22   bioplates that has been proccessed with the Qubit
3834 11 Apr 16 nicklas 23   machine.
3834 11 Apr 16 nicklas 24   @author nicklas
3834 11 Apr 16 nicklas 25   @since 4.3
3834 11 Apr 16 nicklas 26 */
3834 11 Apr 16 nicklas 27 public class QubitPlateImporter
3835 11 Apr 16 nicklas 28   extends AbstractPlateImporter
3834 11 Apr 16 nicklas 29 {
5372 16 Apr 19 nicklas 30
3834 11 Apr 16 nicklas 31   public QubitPlateImporter()
3835 11 Apr 16 nicklas 32   {}
3834 11 Apr 16 nicklas 33   
3835 11 Apr 16 nicklas 34
3834 11 Apr 16 nicklas 35   /**
3834 11 Apr 16 nicklas 36     Import data from the input stream.
3834 11 Apr 16 nicklas 37     @param in
3834 11 Apr 16 nicklas 38   */
3834 11 Apr 16 nicklas 39   public boolean doImport(DbControl dc, InputStream in, boolean validateOnly, String fileName)
3834 11 Apr 16 nicklas 40     throws IOException
3834 11 Apr 16 nicklas 41   {
3835 11 Apr 16 nicklas 42     reset();
3834 11 Apr 16 nicklas 43     Map<String,Integer> locations = new HashMap<String, Integer>();
3834 11 Apr 16 nicklas 44
3834 11 Apr 16 nicklas 45     FlatFileParser ffp = getFlatFileParser();
3834 11 Apr 16 nicklas 46     ffp.setInputStream(in, "UTF-8");
3834 11 Apr 16 nicklas 47     LineType headerLine = ffp.parseHeaders();
3834 11 Apr 16 nicklas 48     int lineNo = ffp.getParsedLines();
3834 11 Apr 16 nicklas 49     if (headerLine != LineType.DATA_HEADER)
3834 11 Apr 16 nicklas 50     {
3834 11 Apr 16 nicklas 51       addErrorMessage("File '" + fileName + "' line " + lineNo + ": Could not find header line starting with 'Well{tab}Library name{tab}Qubit ng/ml...'");
3834 11 Apr 16 nicklas 52       return false; // Can't continue if no data is found in the file
3834 11 Apr 16 nicklas 53     }
3834 11 Apr 16 nicklas 54     
3834 11 Apr 16 nicklas 55     boolean useComma = ffp.getLine(ffp.getLineCount()-1).line().startsWith("Well,");
3834 11 Apr 16 nicklas 56     ffp.setDataSplitterRegexp(Pattern.compile(useComma ? "," : "\t"));
3834 11 Apr 16 nicklas 57     
3834 11 Apr 16 nicklas 58     Mapper wellMapper = ffp.getMapper("\\Well\\");
3834 11 Apr 16 nicklas 59     Mapper nameMapper = ffp.getMapper("\\Library name\\");
3834 11 Apr 16 nicklas 60     
3834 11 Apr 16 nicklas 61     Map<String, Mapper> amap = new HashMap<String, Mapper>();
3834 11 Apr 16 nicklas 62     ffp.setIgnoreNonExistingColumns(true);
3834 11 Apr 16 nicklas 63     
3835 11 Apr 16 nicklas 64     for (String col : getAnnotationMappings().keySet())
3834 11 Apr 16 nicklas 65     {
3834 11 Apr 16 nicklas 66       if (ffp.getColumnHeaderIndex(col) != null)
3834 11 Apr 16 nicklas 67       {
3834 11 Apr 16 nicklas 68         Mapper m = ffp.getMapper("\\" + col + "\\");
3834 11 Apr 16 nicklas 69         amap.put(col, m);
3834 11 Apr 16 nicklas 70       }
3834 11 Apr 16 nicklas 71       else
3834 11 Apr 16 nicklas 72       {
3834 11 Apr 16 nicklas 73         addErrorMessage("File '" + fileName + "' line " + lineNo + ": Column '" + col + "' not found in column headers.");
3834 11 Apr 16 nicklas 74       }
3834 11 Apr 16 nicklas 75     }
3834 11 Apr 16 nicklas 76     
3834 11 Apr 16 nicklas 77     // Return if there are any errors so far
3834 11 Apr 16 nicklas 78     if (hasError()) return false;
3834 11 Apr 16 nicklas 79     
3834 11 Apr 16 nicklas 80     int numExtractsByName = 0;
3834 11 Apr 16 nicklas 81     int numExtractsByLocation = 0;
3835 11 Apr 16 nicklas 82     BioPlate plate = getBioPlate();
3835 11 Apr 16 nicklas 83     if (plate != null)
3834 11 Apr 16 nicklas 84     {
3835 11 Apr 16 nicklas 85       getMissingExtracts().addAll(loadExtractsOnPlate(dc, plate));
3834 11 Apr 16 nicklas 86     }
3834 11 Apr 16 nicklas 87     
3834 11 Apr 16 nicklas 88     while (ffp.hasMoreData())
3834 11 Apr 16 nicklas 89     {
3834 11 Apr 16 nicklas 90       FlatFileParser.Data data = ffp.nextData();
3834 11 Apr 16 nicklas 91       lineNo = ffp.getParsedLines();
3834 11 Apr 16 nicklas 92       String fileAndLine = "File '" + fileName + "' line " + lineNo + ": ";
3834 11 Apr 16 nicklas 93       boolean errorOnThisLine = false;
3834 11 Apr 16 nicklas 94             
3834 11 Apr 16 nicklas 95       // Check that the "Library name" column maps to a valid extract
5364 16 Apr 19 nicklas 96       String extractName = nameMapper.getString(data);
5364 16 Apr 19 nicklas 97       String location = wellMapper.getString(data);
3834 11 Apr 16 nicklas 98       
5301 14 Feb 19 nicklas 99       if (extractName == null)
5301 14 Feb 19 nicklas 100       {
5301 14 Feb 19 nicklas 101         addErrorMessage(fileAndLine + "Missing Library name.");
5301 14 Feb 19 nicklas 102         continue; // with the next line
5301 14 Feb 19 nicklas 103       }
5301 14 Feb 19 nicklas 104       if (location == null)
5301 14 Feb 19 nicklas 105       {
5301 14 Feb 19 nicklas 106         addErrorMessage(fileAndLine + "Missing Well coordinate.");
5301 14 Feb 19 nicklas 107         continue; // with the next line
5301 14 Feb 19 nicklas 108       }
5301 14 Feb 19 nicklas 109       
3834 11 Apr 16 nicklas 110       Extract extract = null;
3835 11 Apr 16 nicklas 111       if (allowMatchAgainstLocation() && extractName.matches("\\w\\d\\d?"))
3834 11 Apr 16 nicklas 112       {
3834 11 Apr 16 nicklas 113         extract = findExtractByLocation(dc, plate, extractName, fileAndLine);
3834 11 Apr 16 nicklas 114         if (extract != null) 
3834 11 Apr 16 nicklas 115         {
3834 11 Apr 16 nicklas 116           numExtractsByLocation++;
3834 11 Apr 16 nicklas 117           addWarningMessage(fileAndLine + "No library name, extract '" + extract.getName() + "' found using location '" + extractName + "'");
3834 11 Apr 16 nicklas 118           extractName = extract.getName();
3834 11 Apr 16 nicklas 119         }
3834 11 Apr 16 nicklas 120       }
3834 11 Apr 16 nicklas 121       else
3834 11 Apr 16 nicklas 122       {
3834 11 Apr 16 nicklas 123         extract = findExtractByName(dc, plate, extractName, location, fileAndLine);
3834 11 Apr 16 nicklas 124         if (extract != null) numExtractsByName++;
3834 11 Apr 16 nicklas 125       }
3834 11 Apr 16 nicklas 126
3834 11 Apr 16 nicklas 127       
3834 11 Apr 16 nicklas 128       if (extract == null) continue; // with the next line
3835 11 Apr 16 nicklas 129       getExtracts().add(extract);
3835 11 Apr 16 nicklas 130       getMissingExtracts().remove(extract);
3834 11 Apr 16 nicklas 131       
3834 11 Apr 16 nicklas 132       // Validate that the location is the same in BASE and the CSV
3834 11 Apr 16 nicklas 133       if (!checkLocation(dc, extract, location, fileAndLine)) continue; // with the next line
3834 11 Apr 16 nicklas 134       
3834 11 Apr 16 nicklas 135       // Check that the same location has not been seen before in this file
3834 11 Apr 16 nicklas 136       if (locations.containsKey(location))
3834 11 Apr 16 nicklas 137       {
3834 11 Apr 16 nicklas 138         addErrorMessage(fileAndLine + "Duplicate well '" + location + "' with extract '" + extractName + "'. Also found on line " + locations.get(location) + ".");
3834 11 Apr 16 nicklas 139         continue; // with the next line
3834 11 Apr 16 nicklas 140       }
3834 11 Apr 16 nicklas 141       locations.put(location, lineNo);
3834 11 Apr 16 nicklas 142       
3834 11 Apr 16 nicklas 143       // Load annotations
3834 11 Apr 16 nicklas 144       AnnotationSet as = extract.getAnnotationSet();
3835 11 Apr 16 nicklas 145       for (String col : getAnnotationMappings().keySet())
3834 11 Apr 16 nicklas 146       {
3834 11 Apr 16 nicklas 147         try
3834 11 Apr 16 nicklas 148         {
3834 11 Apr 16 nicklas 149           Mapper m = amap.get(col);
3835 11 Apr 16 nicklas 150           AnnotationType at = getAnnotationMappings().get(col);
3835 11 Apr 16 nicklas 151           ValueConverter<String, ?> vc = getColumnConverters().get(col);
3834 11 Apr 16 nicklas 152           
5364 16 Apr 19 nicklas 153           String sval = m.getString(data);
3834 11 Apr 16 nicklas 154           Object val = vc == null ? sval : vc.convert(sval);
3834 11 Apr 16 nicklas 155           Type valueType = at.getValueType();
3834 11 Apr 16 nicklas 156           if (!valueType.isCorrectType(val) && val != null)
3834 11 Apr 16 nicklas 157           {
3834 11 Apr 16 nicklas 158             // Parse string values into the correct type
3834 11 Apr 16 nicklas 159             val = valueType.parseString(val.toString());
3834 11 Apr 16 nicklas 160           }
3834 11 Apr 16 nicklas 161
3834 11 Apr 16 nicklas 162           if (!validateOnly)
3834 11 Apr 16 nicklas 163           {
3861 22 Apr 16 nicklas 164             if (val != null) as.getAnnotation(at).setValueIfDifferent(val, null);
3834 11 Apr 16 nicklas 165           }
3834 11 Apr 16 nicklas 166           
3834 11 Apr 16 nicklas 167           // For debugging
3834 11 Apr 16 nicklas 168           //addWarningMessage(extractName + ": " + at.getName() + "=" + sval);
3834 11 Apr 16 nicklas 169           
3834 11 Apr 16 nicklas 170         }
3834 11 Apr 16 nicklas 171         catch (RuntimeException ex)
3834 11 Apr 16 nicklas 172         {
3834 11 Apr 16 nicklas 173           addErrorMessage(fileAndLine + "Location '" + location + "' with extract '" + 
3834 11 Apr 16 nicklas 174               extractName + "' " + ex.getMessage());
3834 11 Apr 16 nicklas 175           errorOnThisLine = true;
3834 11 Apr 16 nicklas 176         }
3834 11 Apr 16 nicklas 177       }
3834 11 Apr 16 nicklas 178       
3834 11 Apr 16 nicklas 179       // External lookup
3835 11 Apr 16 nicklas 180       for (Map.Entry<ValueConverter<String, ?>, AnnotationType> entry : getExternalLookups().entrySet())
3834 11 Apr 16 nicklas 181       {
3834 11 Apr 16 nicklas 182         try
3834 11 Apr 16 nicklas 183         {
3834 11 Apr 16 nicklas 184           ValueConverter<String, ?> lookup = entry.getKey();
3834 11 Apr 16 nicklas 185           AnnotationType at = entry.getValue();
3834 11 Apr 16 nicklas 186           // Do not need to apply Caliper-specific parsing for external data!
3834 11 Apr 16 nicklas 187           Object val = lookup.convert(extractName);
3834 11 Apr 16 nicklas 188           Type valueType = at.getValueType();
3834 11 Apr 16 nicklas 189           if (!valueType.isCorrectType(val) && val != null)
3834 11 Apr 16 nicklas 190           {
3834 11 Apr 16 nicklas 191             // Parse string values into the correct type
3834 11 Apr 16 nicklas 192             val = valueType.parseString(val.toString());
3834 11 Apr 16 nicklas 193           }
3834 11 Apr 16 nicklas 194           
3834 11 Apr 16 nicklas 195           if (!validateOnly)
3834 11 Apr 16 nicklas 196           {
3861 22 Apr 16 nicklas 197             if (val != null) as.getAnnotation(at).setValueIfDifferent(val, null);
3834 11 Apr 16 nicklas 198           }
3834 11 Apr 16 nicklas 199
3834 11 Apr 16 nicklas 200           // For debugging
3834 11 Apr 16 nicklas 201           // addWarningMessage(extractName + ": " + at.getName() + "=" + val);
3834 11 Apr 16 nicklas 202         }
3834 11 Apr 16 nicklas 203         catch (RuntimeException ex)
3834 11 Apr 16 nicklas 204         {
3834 11 Apr 16 nicklas 205           addExternalErrorMessage(ex.getMessage());
3834 11 Apr 16 nicklas 206           errorOnThisLine = true;
3834 11 Apr 16 nicklas 207         }
3834 11 Apr 16 nicklas 208       }
3834 11 Apr 16 nicklas 209       
3834 11 Apr 16 nicklas 210       if (errorOnThisLine) continue; // with the next line
3835 11 Apr 16 nicklas 211       addImported();
3834 11 Apr 16 nicklas 212     }
3834 11 Apr 16 nicklas 213     
3834 11 Apr 16 nicklas 214     if (numExtractsByLocation > numExtractsByName)
3834 11 Apr 16 nicklas 215     {
3834 11 Apr 16 nicklas 216       addErrorMessage("File '" + fileName + "': Too many lines have location instead of 'Library name': " + numExtractsByLocation + " of " + (numExtractsByLocation+numExtractsByName));
3834 11 Apr 16 nicklas 217     }
3834 11 Apr 16 nicklas 218     
3835 11 Apr 16 nicklas 219     if (getMissingExtracts().size() > 0)
3834 11 Apr 16 nicklas 220     {
3835 11 Apr 16 nicklas 221       for (Extract e : getMissingExtracts())
3834 11 Apr 16 nicklas 222       {
3834 11 Apr 16 nicklas 223         addErrorMessage("File '" + fileName + "': Could not find any data for library '" + e.getName() + "'");
3834 11 Apr 16 nicklas 224       }
3834 11 Apr 16 nicklas 225     }
3834 11 Apr 16 nicklas 226
3834 11 Apr 16 nicklas 227     return !hasError() && !hasExternalError();
3834 11 Apr 16 nicklas 228   }
3834 11 Apr 16 nicklas 229   
3835 11 Apr 16 nicklas 230
3834 11 Apr 16 nicklas 231   protected FlatFileParser getFlatFileParser()
3834 11 Apr 16 nicklas 232   {
3834 11 Apr 16 nicklas 233     FlatFileParser ffp = new FlatFileParser();
3834 11 Apr 16 nicklas 234     
3834 11 Apr 16 nicklas 235     ffp.setDataHeaderRegexp(Pattern.compile(".*Well.*Library name.*Qubit ng/ml.*After SpeedVac.*"));
3834 11 Apr 16 nicklas 236     ffp.setIgnoreRegexp(Pattern.compile("^(\\\"?#.*|)\\s*")); // Ignore all lines starting with (#), ("#), or containing only whitespace
3834 11 Apr 16 nicklas 237     ffp.setDataSplitterRegexp(Pattern.compile("\t|,")); // Split on tab or comma
3834 11 Apr 16 nicklas 238     
3834 11 Apr 16 nicklas 239     return ffp;
3834 11 Apr 16 nicklas 240   }
3834 11 Apr 16 nicklas 241
3834 11 Apr 16 nicklas 242   
3834 11 Apr 16 nicklas 243 }