extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/pdf/PilotReportWorker.java

Code
Comments
Other
Rev Date Author Line
3506 23 Sep 15 nicklas 1 package net.sf.basedb.reggie.pdf;
3506 23 Sep 15 nicklas 2
3535 08 Oct 15 nicklas 3 import java.io.BufferedReader;
3506 23 Sep 15 nicklas 4 import java.io.File;
3506 23 Sep 15 nicklas 5 import java.io.FileInputStream;
3506 23 Sep 15 nicklas 6 import java.io.IOException;
3533 08 Oct 15 nicklas 7 import java.io.InputStream;
3542 14 Oct 15 nicklas 8 import java.io.InputStreamReader;
3506 23 Sep 15 nicklas 9 import java.io.OutputStream;
3525 05 Oct 15 nicklas 10 import java.text.DecimalFormat;
3525 05 Oct 15 nicklas 11 import java.text.DecimalFormatSymbols;
3525 05 Oct 15 nicklas 12 import java.text.NumberFormat;
3506 23 Sep 15 nicklas 13 import java.util.Date;
3525 05 Oct 15 nicklas 14 import java.util.HashMap;
3525 05 Oct 15 nicklas 15 import java.util.List;
3506 23 Sep 15 nicklas 16 import java.util.Map;
3533 08 Oct 15 nicklas 17 import java.util.regex.Pattern;
3506 23 Sep 15 nicklas 18
7024 07 Feb 23 nicklas 19 import org.apache.commons.lang3.time.FastDateFormat;
7024 07 Feb 23 nicklas 20
3506 23 Sep 15 nicklas 21 import net.sf.basedb.core.BioMaterial;
3506 23 Sep 15 nicklas 22 import net.sf.basedb.core.BioSource;
3506 23 Sep 15 nicklas 23 import net.sf.basedb.core.DbControl;
3525 05 Oct 15 nicklas 24 import net.sf.basedb.core.Extract;
4537 21 Jun 17 nicklas 25 import net.sf.basedb.core.RawBioAssay;
3506 23 Sep 15 nicklas 26 import net.sf.basedb.core.Sample;
6031 29 Oct 20 nicklas 27 import net.sf.basedb.core.plugin.ExportOutputStream;
3506 23 Sep 15 nicklas 28 import net.sf.basedb.reggie.Reggie;
3506 23 Sep 15 nicklas 29 import net.sf.basedb.reggie.Site;
3506 23 Sep 15 nicklas 30 import net.sf.basedb.reggie.converter.DateToStringConverter;
3506 23 Sep 15 nicklas 31 import net.sf.basedb.reggie.dao.Annotationtype;
3506 23 Sep 15 nicklas 32 import net.sf.basedb.reggie.dao.Rawbioassay;
3525 05 Oct 15 nicklas 33 import net.sf.basedb.reggie.dao.Rna;
3525 05 Oct 15 nicklas 34 import net.sf.basedb.reggie.dao.RnaQc;
3506 23 Sep 15 nicklas 35 import net.sf.basedb.reggie.dao.Subtype;
6060 17 Nov 20 nicklas 36 import net.sf.basedb.reggie.pdf.PdfUtil7.Align;
6070 20 Nov 20 nicklas 37 import net.sf.basedb.reggie.pdf.PdfUtil7.Options;
6035 29 Oct 20 nicklas 38 import net.sf.basedb.reggie.script.PilotReport;
6036 02 Nov 20 nicklas 39 import net.sf.basedb.reggie.script.ScriptResult;
3533 08 Oct 15 nicklas 40 import net.sf.basedb.util.FileUtil;
3525 05 Oct 15 nicklas 41 import net.sf.basedb.util.MD5;
3533 08 Oct 15 nicklas 42 import net.sf.basedb.util.parser.FlatFileParser;
3533 08 Oct 15 nicklas 43 import net.sf.basedb.util.parser.Mapper;
3506 23 Sep 15 nicklas 44
3506 23 Sep 15 nicklas 45 /**
3506 23 Sep 15 nicklas 46   Worker implementation that runs the 'PilotReport' R script and
3506 23 Sep 15 nicklas 47   generates a PDF document with the plots and other information.
3506 23 Sep 15 nicklas 48   
3506 23 Sep 15 nicklas 49   @author nicklas
3506 23 Sep 15 nicklas 50   @since 3.7
3506 23 Sep 15 nicklas 51 */
3506 23 Sep 15 nicklas 52 public class PilotReportWorker 
3506 23 Sep 15 nicklas 53   extends PdfReportWorker
3506 23 Sep 15 nicklas 54 {
3506 23 Sep 15 nicklas 55
3506 23 Sep 15 nicklas 56   /**
3506 23 Sep 15 nicklas 57     The default file name for the generated pdf.
3506 23 Sep 15 nicklas 58   */
3506 23 Sep 15 nicklas 59   public static final String DEFAULT_PDF_NAME = "pilotreport.pdf";
3506 23 Sep 15 nicklas 60   
3506 23 Sep 15 nicklas 61   public static final DateToStringConverter DATE_FORMAT = 
7024 07 Feb 23 nicklas 62       new DateToStringConverter(FastDateFormat.getInstance("yyyy-MM-dd"));
3506 23 Sep 15 nicklas 63
3525 05 Oct 15 nicklas 64   private static final float MARGIN_RIGHT = 579;
3525 05 Oct 15 nicklas 65   private static final float MARGIN_LEFT = 14;
3506 23 Sep 15 nicklas 66   
3525 05 Oct 15 nicklas 67   /* TEXT POSITIONS */
3525 05 Oct 15 nicklas 68   // Left X of text columns
3525 05 Oct 15 nicklas 69   private static final float TEXT_X1 = 99;
3525 05 Oct 15 nicklas 70   private static final float TEXT_X2 = 191;
3525 05 Oct 15 nicklas 71   private static final float TEXT_X3 = 283;
3525 05 Oct 15 nicklas 72   private static final float TEXT_X4 = 404;
3525 05 Oct 15 nicklas 73   private static final float TEXT_X5 = 495;
3506 23 Sep 15 nicklas 74   
3525 05 Oct 15 nicklas 75   // Bottom Y of text rows
3525 05 Oct 15 nicklas 76   private static final float TEXT_Y1 = 801;
3525 05 Oct 15 nicklas 77   private static final float TEXT_Y2 = 773;
3525 05 Oct 15 nicklas 78   private static final float TEXT_Y3 = 746;
3525 05 Oct 15 nicklas 79   private static final float TEXT_Y4 = 718;
3525 05 Oct 15 nicklas 80   private static final float TEXT_Y5 = 690;
3528 05 Oct 15 nicklas 81   
3528 05 Oct 15 nicklas 82   // Molecular subtype box
3528 05 Oct 15 nicklas 83   private static final float SUBTYPE_Y1 = 616;
3528 05 Oct 15 nicklas 84   private static final float SUBTYPE_Y2 = 608;
3528 05 Oct 15 nicklas 85   private static final float SUBTYPE_X1 = 156;
3528 05 Oct 15 nicklas 86   private static final float SUBTYPE_X2 = 330;
3528 05 Oct 15 nicklas 87   private static final float SUBTYPE_XX = 50;
3528 05 Oct 15 nicklas 88   
3528 05 Oct 15 nicklas 89   /* PLOT POSITIONS */
3528 05 Oct 15 nicklas 90   // Left X of plots
3528 05 Oct 15 nicklas 91   private static final float PLOT_X = 355;
3528 05 Oct 15 nicklas 92   // Bottom Y of first plot
3556 21 Oct 15 nicklas 93   private static final float PLOT_START_Y = 503f;
3528 05 Oct 15 nicklas 94   // Distance between plots
3556 21 Oct 15 nicklas 95   private static final float PLOT_DELTA_Y = 98.5f;
3528 05 Oct 15 nicklas 96   // Size of plots
3528 05 Oct 15 nicklas 97   private static final float PLOT_WIDTH = 160;
3528 05 Oct 15 nicklas 98   private static final float PLOT_HEIGHT = 80;
3528 05 Oct 15 nicklas 99   // Text releated to plot
3556 21 Oct 15 nicklas 100   private static final float PLOT_TEXT_X = 205;
3556 21 Oct 15 nicklas 101   private static final float PLOT_TEXT_START_Y = 540.5f;
3528 05 Oct 15 nicklas 102   
3506 23 Sep 15 nicklas 103   private PilotReport script;
3620 24 Nov 15 nicklas 104   private final String config;
3620 24 Nov 15 nicklas 105   private final String parameterSet;
3506 23 Sep 15 nicklas 106   private String pdfTemplatePath;
3525 05 Oct 15 nicklas 107   private Map<String, String> translations;
3525 05 Oct 15 nicklas 108   private NumberFormat oneDecimal;
3525 05 Oct 15 nicklas 109   private NumberFormat twoDecimals;
3506 23 Sep 15 nicklas 110
3620 24 Nov 15 nicklas 111   PilotReportWorker(PdfReportTemplate template, String config, String parameterSet)
3506 23 Sep 15 nicklas 112   {
3506 23 Sep 15 nicklas 113     super(template);
3506 23 Sep 15 nicklas 114     this.config = config;
3620 24 Nov 15 nicklas 115     this.parameterSet = parameterSet;
3506 23 Sep 15 nicklas 116   }
3506 23 Sep 15 nicklas 117
3506 23 Sep 15 nicklas 118   /**
3506 23 Sep 15 nicklas 119     Run the gene report script for the given raw bioassay and then
3506 23 Sep 15 nicklas 120     create the pdf.
3506 23 Sep 15 nicklas 121   */
3506 23 Sep 15 nicklas 122   @Override
6036 02 Nov 20 nicklas 123   public ScriptResult runAndCreatePdf(DbControl dc, Rawbioassay raw, ExportOutputStream out, ReportOptions options)
3506 23 Sep 15 nicklas 124     throws IOException
3506 23 Sep 15 nicklas 125   {
3506 23 Sep 15 nicklas 126     if (script == null) 
3506 23 Sep 15 nicklas 127     {
3506 23 Sep 15 nicklas 128       // Initialize script in the first call to this method
3620 24 Nov 15 nicklas 129       script = new PilotReport(config, parameterSet);
3620 24 Nov 15 nicklas 130       pdfTemplatePath = Reggie.getConfig().getConfig(config+"/template", parameterSet, script.getScriptDir() + "/template.pdf");
3506 23 Sep 15 nicklas 131       Reggie.checkFile(pdfTemplatePath, false);
3525 05 Oct 15 nicklas 132       oneDecimal = createNumberFormat(1);
3525 05 Oct 15 nicklas 133       twoDecimals = createNumberFormat(2);
3506 23 Sep 15 nicklas 134     }
3506 23 Sep 15 nicklas 135     PilotReport.Result result = script.run(dc, raw);
3506 23 Sep 15 nicklas 136     if (result.getExitStatus() == 0)
3506 23 Sep 15 nicklas 137     {
4537 21 Jun 17 nicklas 138       toPdf(dc, result, out, options);
3506 23 Sep 15 nicklas 139     }
3506 23 Sep 15 nicklas 140     return result;
3506 23 Sep 15 nicklas 141   }
3506 23 Sep 15 nicklas 142
3506 23 Sep 15 nicklas 143
4537 21 Jun 17 nicklas 144   private void toPdf(DbControl dc, PilotReport.Result result, OutputStream out, ReportOptions options)
3506 23 Sep 15 nicklas 145       throws IOException 
3506 23 Sep 15 nicklas 146   {
3506 23 Sep 15 nicklas 147     Rawbioassay raw = result.raw;
3506 23 Sep 15 nicklas 148     
3525 05 Oct 15 nicklas 149     Map<Subtype, BioMaterial> parents = raw.findParentBioMaterial(dc, Subtype.PATIENT, Subtype.SPECIMEN, Subtype.CASE, Subtype.RNA);
3525 05 Oct 15 nicklas 150     Extract rna = (Extract)parents.get(Subtype.RNA);
3506 23 Sep 15 nicklas 151     Sample specimen = (Sample)parents.get(Subtype.SPECIMEN);
3525 05 Oct 15 nicklas 152     Sample theCase = (Sample)parents.get(Subtype.CASE);
3506 23 Sep 15 nicklas 153     BioSource patient = (BioSource)parents.get(Subtype.PATIENT);
3525 05 Oct 15 nicklas 154     Site site = Site.findByCaseName(raw.getName());
4537 21 Jun 17 nicklas 155     RawBioAssay rba = raw.getRawBioAssay();
4537 21 Jun 17 nicklas 156     Map<String, String> translations = new HashMap<>();
4537 21 Jun 17 nicklas 157     translations.put("Hög", "High");
4537 21 Jun 17 nicklas 158     translations.put("Låg", "Low");
4537 21 Jun 17 nicklas 159     translations.put("Positiv", "Positive");
4537 21 Jun 17 nicklas 160     translations.put("Negativ", "Negative");
3506 23 Sep 15 nicklas 161     
6060 17 Nov 20 nicklas 162     PdfUtil7 pdfUtil = null;
3506 23 Sep 15 nicklas 163     try
3506 23 Sep 15 nicklas 164     {
6060 17 Nov 20 nicklas 165       pdfUtil = new PdfUtil7("Pilot report: " + raw.getName(), result.getScript());
3506 23 Sep 15 nicklas 166       pdfUtil.open(out);
3506 23 Sep 15 nicklas 167       
6061 18 Nov 20 nicklas 168       pdfUtil.importPdf(new FileInputStream(pdfTemplatePath), 1, 0, 0, Float.NaN, Float.NaN, Align.LEFT);
3506 23 Sep 15 nicklas 169       //pdfUtil.drawGrid();
3506 23 Sep 15 nicklas 170       
3506 23 Sep 15 nicklas 171       // Patient and sample information
3525 05 Oct 15 nicklas 172       // Row 2
6070 20 Nov 20 nicklas 173       if (patient != null) pdfUtil.addText(patient.getName(), 12, TEXT_X1, TEXT_Y2);
6070 20 Nov 20 nicklas 174       if (theCase != null) pdfUtil.addText(theCase.getName(), 12, TEXT_X2, TEXT_Y2);
6070 20 Nov 20 nicklas 175       if (specimen != null) pdfUtil.addText(specimen.getName(), 12, TEXT_X3, TEXT_Y2);
3525 05 Oct 15 nicklas 176
3525 05 Oct 15 nicklas 177       // Row 3
3525 05 Oct 15 nicklas 178       String consent = (String)Annotationtype.CONSENT.getAnnotationValue(dc, theCase);
3525 05 Oct 15 nicklas 179       Date consentDate = (Date)Annotationtype.CONSENT_DATE.getAnnotationValue(dc, theCase);
6070 20 Nov 20 nicklas 180       pdfUtil.addText(translate(consent), 12, TEXT_X1, TEXT_Y3);
6070 20 Nov 20 nicklas 181       pdfUtil.addText(DATE_FORMAT.convert(consentDate), 12, TEXT_X2, TEXT_Y3);
3525 05 Oct 15 nicklas 182       if (rna != null)
3506 23 Sep 15 nicklas 183       {
3525 05 Oct 15 nicklas 184         List<RnaQc> rnaqc = RnaQc.findByRna(dc, Rna.get(rna));
3525 05 Oct 15 nicklas 185         RnaQc lastRnaQc = RnaQc.findLast(dc, null, rnaqc);
3525 05 Oct 15 nicklas 186         if (lastRnaQc != null)
3525 05 Oct 15 nicklas 187         {
3525 05 Oct 15 nicklas 188           Float rqs = (Float)Annotationtype.CA_RQS.getAnnotationValue(dc, lastRnaQc.getItem());
3525 05 Oct 15 nicklas 189           Float rin = (Float)Annotationtype.BA_RIN.getAnnotationValue(dc, lastRnaQc.getItem());
3525 05 Oct 15 nicklas 190           if (rqs != null || rin != null)
3525 05 Oct 15 nicklas 191           {
6070 20 Nov 20 nicklas 192             pdfUtil.addText(oneDecimal.format((double)(rqs != null ? rqs : rin)), 12, TEXT_X3, TEXT_Y3);
3525 05 Oct 15 nicklas 193           }
3525 05 Oct 15 nicklas 194         }
3506 23 Sep 15 nicklas 195       }
3506 23 Sep 15 nicklas 196       
3525 05 Oct 15 nicklas 197       // Row 4
6070 20 Nov 20 nicklas 198       pdfUtil.addText(DATE_FORMAT.convert((Date)Annotationtype.SAMPLING_DATETIME.getAnnotationValue(dc, specimen)), 12, TEXT_X1, TEXT_Y4);
6070 20 Nov 20 nicklas 199       pdfUtil.addText(DATE_FORMAT.convert((Date)Annotationtype.ARRIVAL_DATE.getAnnotationValue(dc, specimen)), 12, TEXT_X2, TEXT_Y4);
6070 20 Nov 20 nicklas 200       pdfUtil.addText(DATE_FORMAT.convert(new Date()), 12, TEXT_X3, TEXT_Y4);
3525 05 Oct 15 nicklas 201       
3525 05 Oct 15 nicklas 202       // Row 5
3525 05 Oct 15 nicklas 203       String laterality = (String)Annotationtype.LATERALITY.getAnnotationValue(dc, specimen);
6070 20 Nov 20 nicklas 204       pdfUtil.addText(translate(laterality), 12, TEXT_X4, TEXT_Y5);
6070 20 Nov 20 nicklas 205       if (site != Site.UNKNOWN) pdfUtil.addText(site.getName(), 12, TEXT_X5, TEXT_Y5);
3525 05 Oct 15 nicklas 206       
3533 08 Oct 15 nicklas 207       // Molecular subtype information is found in the 'PAM50.txt' output file
3533 08 Oct 15 nicklas 208       File workDir = result.getWorkDir();
3533 08 Oct 15 nicklas 209       String[] subtypeNames = { "LumA", "LumB", "Her2", "Basal", "Normal" };
3533 08 Oct 15 nicklas 210       float[] subtypeScores = new float[subtypeNames.length];
4537 21 Jun 17 nicklas 211       Annotationtype[] scoreTypes = { Annotationtype.PILOT_SCORE_LUMA, Annotationtype.PILOT_SCORE_LUMB, 
4537 21 Jun 17 nicklas 212           Annotationtype.PILOT_SCORE_HER2, Annotationtype.PILOT_SCORE_BASAL, Annotationtype.PILOT_SCORE_NORMAL };
3533 08 Oct 15 nicklas 213       String subtypeClass = parsePam50(new File(workDir, "PAM50.txt"), subtypeNames, subtypeScores);
6070 20 Nov 20 nicklas 214       pdfUtil.addText(subtypeClass, 14, SUBTYPE_X1, SUBTYPE_Y1);
4537 21 Jun 17 nicklas 215
4537 21 Jun 17 nicklas 216       if (options.updateAnnotations())
4537 21 Jun 17 nicklas 217       {
4537 21 Jun 17 nicklas 218         Annotationtype.PILOT_SUBTYPE.setAnnotationValue(dc, rba, subtypeClass);
4537 21 Jun 17 nicklas 219       }
4537 21 Jun 17 nicklas 220       
3543 14 Oct 15 nicklas 221       // Find max score
3543 14 Oct 15 nicklas 222       float maxScore = subtypeScores[0];
3543 14 Oct 15 nicklas 223       for (int scoreNo = 1; scoreNo < subtypeScores.length; scoreNo++)
3543 14 Oct 15 nicklas 224       {
3543 14 Oct 15 nicklas 225         if (subtypeScores[scoreNo] > maxScore) maxScore = subtypeScores[scoreNo];
3543 14 Oct 15 nicklas 226       }
3543 14 Oct 15 nicklas 227       // Print scores
3533 08 Oct 15 nicklas 228       for (int scoreNo = 0; scoreNo < subtypeScores.length; scoreNo++)
3528 05 Oct 15 nicklas 229       {
4537 21 Jun 17 nicklas 230         if (options.updateAnnotations())
4537 21 Jun 17 nicklas 231         {
4537 21 Jun 17 nicklas 232           scoreTypes[scoreNo].setAnnotationValue(dc, rba, subtypeScores[scoreNo]);
4537 21 Jun 17 nicklas 233         }
4537 21 Jun 17 nicklas 234         
3543 14 Oct 15 nicklas 235         if (Float.compare(subtypeScores[scoreNo], maxScore) == 0)
3528 05 Oct 15 nicklas 236         {
6070 20 Nov 20 nicklas 237           pdfUtil.addText(twoDecimals.format(subtypeScores[scoreNo]), 12, SUBTYPE_X2+scoreNo*SUBTYPE_XX, SUBTYPE_Y2, new Options().bold());
3528 05 Oct 15 nicklas 238         }
3528 05 Oct 15 nicklas 239         else
3528 05 Oct 15 nicklas 240         {
6070 20 Nov 20 nicklas 241           pdfUtil.addText(twoDecimals.format(subtypeScores[scoreNo]), 12, SUBTYPE_X2+scoreNo*SUBTYPE_XX, SUBTYPE_Y2);
3528 05 Oct 15 nicklas 242         }
3528 05 Oct 15 nicklas 243       }
3528 05 Oct 15 nicklas 244       
3528 05 Oct 15 nicklas 245       // Plots
3535 08 Oct 15 nicklas 246       float yPlot = PLOT_START_Y;
3528 05 Oct 15 nicklas 247       float yText = PLOT_TEXT_START_Y;
3542 14 Oct 15 nicklas 248       String[] plots = { "GGI.pdf", "ER_validationClass.pdf", "PR_validationClass.pdf", "ERBB2_validationClass.pdf", "KI67_validationClass.pdf" };
3542 14 Oct 15 nicklas 249       String[] groups = { "GGI_group.txt", "ER_validationClass.txt", "PR_validationClass.txt", "ERBB2_validationClass.txt", "KI67_validationClass.txt" };
4537 21 Jun 17 nicklas 250       Annotationtype[] groupTypes = { Annotationtype.PILOT_GGI, Annotationtype.PILOT_ER, Annotationtype.PILOT_PGR, Annotationtype.PILOT_HER2, Annotationtype.PILOT_KI67 };
3533 08 Oct 15 nicklas 251       for (int plotNo = 0; plotNo < plots.length; plotNo++)
3528 05 Oct 15 nicklas 252       {
3542 14 Oct 15 nicklas 253         File groupTxt = new File(workDir, groups[plotNo]);
3542 14 Oct 15 nicklas 254         String group = parseGroupTxt(groupTxt);
4537 21 Jun 17 nicklas 255         String translatedGroup = translations.containsKey(group) ? translations.get(group) : group;
4537 21 Jun 17 nicklas 256         if (options.updateAnnotations())
4537 21 Jun 17 nicklas 257         {
4537 21 Jun 17 nicklas 258           groupTypes[plotNo].setAnnotationValue(dc, rba, translatedGroup);
4537 21 Jun 17 nicklas 259         }
6070 20 Nov 20 nicklas 260         pdfUtil.addText(group == null ? "N/A" : group, 14, PLOT_TEXT_X, yText);
3528 05 Oct 15 nicklas 261         yText -= PLOT_DELTA_Y;
3528 05 Oct 15 nicklas 262
3542 14 Oct 15 nicklas 263         File plotPdf = new File(workDir, plots[plotNo]);
3535 08 Oct 15 nicklas 264         if (plotPdf.exists())
3528 05 Oct 15 nicklas 265         {
6061 18 Nov 20 nicklas 266           pdfUtil.importPdf(new FileInputStream(plotPdf), 1, PLOT_X, yPlot, Float.NaN, Float.NaN, Align.LEFT);
3528 05 Oct 15 nicklas 267         }
3535 08 Oct 15 nicklas 268         yPlot -= PLOT_DELTA_Y;
3528 05 Oct 15 nicklas 269       }
3528 05 Oct 15 nicklas 270       
3506 23 Sep 15 nicklas 271       // Extra info at bottom
6070 20 Nov 20 nicklas 272       pdfUtil.addText(raw.getName(), 8, MARGIN_RIGHT, 10, Options.ALIGN_RIGHT);
3506 23 Sep 15 nicklas 273     }
3506 23 Sep 15 nicklas 274     finally
3506 23 Sep 15 nicklas 275     {
3506 23 Sep 15 nicklas 276       if (pdfUtil != null) pdfUtil.close();
3506 23 Sep 15 nicklas 277     }
3533 08 Oct 15 nicklas 278   }
3533 08 Oct 15 nicklas 279   
3533 08 Oct 15 nicklas 280   /**
3533 08 Oct 15 nicklas 281     The PAM50.txt file has one header line and one data line.
3506 23 Sep 15 nicklas 282     
3533 08 Oct 15 nicklas 283     @param pam50 The PAM50.txt file
3533 08 Oct 15 nicklas 284     @param subtypes Column headers in the file we are interested in
3533 08 Oct 15 nicklas 285     @param scores Output array for the scores found in the file. Must be
3533 08 Oct 15 nicklas 286       of same length as the subtypes array
3533 08 Oct 15 nicklas 287     @return The data value for the 'class' column
3533 08 Oct 15 nicklas 288   */
3533 08 Oct 15 nicklas 289   private String parsePam50(File pam50, String[] subtypes, float[] scores)
3533 08 Oct 15 nicklas 290     throws IOException
3533 08 Oct 15 nicklas 291   {
3533 08 Oct 15 nicklas 292     FlatFileParser ffp = new FlatFileParser();
3533 08 Oct 15 nicklas 293     ffp.setDataHeaderRegexp(Pattern.compile("class\\tnearest.*"));
3533 08 Oct 15 nicklas 294     ffp.setDataSplitterRegexp(Pattern.compile("\\t"));
3533 08 Oct 15 nicklas 295     InputStream in = null;
3533 08 Oct 15 nicklas 296     String subtypeClass = null;
3533 08 Oct 15 nicklas 297     try
3533 08 Oct 15 nicklas 298     {
3533 08 Oct 15 nicklas 299       in = new FileInputStream(pam50);
3533 08 Oct 15 nicklas 300       ffp.setInputStream(in, "UTF-8");
3533 08 Oct 15 nicklas 301       FlatFileParser.LineType line = ffp.parseHeaders();
3533 08 Oct 15 nicklas 302       // Check that we have found the header and has data
3533 08 Oct 15 nicklas 303       if (line != FlatFileParser.LineType.DATA_HEADER)
3533 08 Oct 15 nicklas 304       {
3533 08 Oct 15 nicklas 305         throw new IOException("Can't find data header in file: "+pam50);
3533 08 Oct 15 nicklas 306       }
3533 08 Oct 15 nicklas 307       FlatFileParser.Data data = ffp.nextData();
3533 08 Oct 15 nicklas 308       if (data == null)
3533 08 Oct 15 nicklas 309       {
3533 08 Oct 15 nicklas 310         throw new IOException("Can't find data line in file: "+pam50);
3533 08 Oct 15 nicklas 311       }
3533 08 Oct 15 nicklas 312       
3533 08 Oct 15 nicklas 313       // Get the subtype class
3533 08 Oct 15 nicklas 314       Mapper mapper = ffp.getMapper("\\class\\");
5364 16 Apr 19 nicklas 315       subtypeClass = mapper.getString(data);
3533 08 Oct 15 nicklas 316       // Get subtype scores
3533 08 Oct 15 nicklas 317       for (int subtypeNo = 0; subtypeNo < subtypes.length; subtypeNo++)
3533 08 Oct 15 nicklas 318       {
3533 08 Oct 15 nicklas 319         mapper = ffp.getMapper("\\"+subtypes[subtypeNo]+"\\");
3533 08 Oct 15 nicklas 320         scores[subtypeNo] = mapper.getFloat(data);
3533 08 Oct 15 nicklas 321       }
3533 08 Oct 15 nicklas 322     }
3533 08 Oct 15 nicklas 323     finally
3533 08 Oct 15 nicklas 324     {
3533 08 Oct 15 nicklas 325       FileUtil.close(in);
3533 08 Oct 15 nicklas 326     }
3533 08 Oct 15 nicklas 327     return subtypeClass;
3506 23 Sep 15 nicklas 328   }
3506 23 Sep 15 nicklas 329   
3542 14 Oct 15 nicklas 330   private String parseGroupTxt(File groupTxt)
3535 08 Oct 15 nicklas 331     throws IOException
3535 08 Oct 15 nicklas 332   {
3535 08 Oct 15 nicklas 333     BufferedReader reader = null;
3542 14 Oct 15 nicklas 334     String group = null;
3542 14 Oct 15 nicklas 335     if (groupTxt.exists())
3535 08 Oct 15 nicklas 336     {
3535 08 Oct 15 nicklas 337       try
3535 08 Oct 15 nicklas 338       {
3542 14 Oct 15 nicklas 339         reader = new BufferedReader(new InputStreamReader(new FileInputStream(groupTxt), "UTF-8"));
3542 14 Oct 15 nicklas 340         group = reader.readLine();
3535 08 Oct 15 nicklas 341       }
3535 08 Oct 15 nicklas 342       finally
3535 08 Oct 15 nicklas 343       {
3535 08 Oct 15 nicklas 344         FileUtil.close(reader);
3535 08 Oct 15 nicklas 345       }
3535 08 Oct 15 nicklas 346     }
3542 14 Oct 15 nicklas 347     return group;
3535 08 Oct 15 nicklas 348   }
3535 08 Oct 15 nicklas 349   
3506 23 Sep 15 nicklas 350   /**
3506 23 Sep 15 nicklas 351     Add personal information to the pilot report.
3506 23 Sep 15 nicklas 352   */
3506 23 Sep 15 nicklas 353   @Override
6060 17 Nov 20 nicklas 354   public void addPersonalInformation(DbControl dc, Rawbioassay raw, PdfUtil7 pdf) 
3506 23 Sep 15 nicklas 355     throws IOException 
3506 23 Sep 15 nicklas 356   {
3506 23 Sep 15 nicklas 357     Map<Subtype, BioMaterial> parents = raw.findParentBioMaterial(dc, Subtype.SPECIMEN, Subtype.PATIENT);
3506 23 Sep 15 nicklas 358     BioSource patient = (BioSource)parents.get(Subtype.PATIENT);
3525 05 Oct 15 nicklas 359     Sample specimen = (Sample)parents.get(Subtype.SPECIMEN);
3506 23 Sep 15 nicklas 360     
6070 20 Nov 20 nicklas 361     pdf.addText(DATE_FORMAT.convert(new Date()), 8, MARGIN_LEFT, 10);
3506 23 Sep 15 nicklas 362     
3506 23 Sep 15 nicklas 363     if (patient != null)
3506 23 Sep 15 nicklas 364     {
6070 20 Nov 20 nicklas 365       pdf.addText((String)Annotationtype.PERSONAL_NUMBER.getAnnotationValue(dc, patient), 12, TEXT_X4, TEXT_Y1);
6070 20 Nov 20 nicklas 366       pdf.addText((String)Annotationtype.FAMILY_NAME.getAnnotationValue(dc, patient), 12, TEXT_X4, TEXT_Y2);
6070 20 Nov 20 nicklas 367       pdf.addText((String)Annotationtype.ALL_FIRST_NAMES.getAnnotationValue(dc, patient), 12, TEXT_X4, TEXT_Y3);
6070 20 Nov 20 nicklas 368       pdf.addText((String)Annotationtype.PAD.getAnnotationValue(dc, specimen), 12, TEXT_X3, TEXT_Y5);
3506 23 Sep 15 nicklas 369     }
3506 23 Sep 15 nicklas 370     else
3506 23 Sep 15 nicklas 371     {
6070 20 Nov 20 nicklas 372       pdf.addText("No patient information", 12, TEXT_X4, TEXT_Y1);
3506 23 Sep 15 nicklas 373     }
3506 23 Sep 15 nicklas 374   }
3506 23 Sep 15 nicklas 375
3525 05 Oct 15 nicklas 376   private String translate(String word)
3525 05 Oct 15 nicklas 377   {
3525 05 Oct 15 nicklas 378     if (word == null) return null;
3525 05 Oct 15 nicklas 379     if (translations == null)
3525 05 Oct 15 nicklas 380     {
3525 05 Oct 15 nicklas 381       translations = new HashMap<String, String>();
3525 05 Oct 15 nicklas 382       translations.put("left", "Vänster");
3525 05 Oct 15 nicklas 383       translations.put("right", "Höger");
3525 05 Oct 15 nicklas 384       translations.put("yes", "Ja");
3525 05 Oct 15 nicklas 385       translations.put("no", "Nej");
3525 05 Oct 15 nicklas 386     }
3525 05 Oct 15 nicklas 387     
3525 05 Oct 15 nicklas 388     String translatedWord = translations.get(word.toLowerCase());
3525 05 Oct 15 nicklas 389     return translatedWord == null ? word : translatedWord;
3525 05 Oct 15 nicklas 390   }
3506 23 Sep 15 nicklas 391   
3525 05 Oct 15 nicklas 392   private NumberFormat createNumberFormat(int numDecimals)
3525 05 Oct 15 nicklas 393   {
3525 05 Oct 15 nicklas 394     DecimalFormatSymbols sym = new DecimalFormatSymbols();
3525 05 Oct 15 nicklas 395     sym.setDecimalSeparator(',');
3525 05 Oct 15 nicklas 396     String format = "0";
3525 05 Oct 15 nicklas 397     if (numDecimals > 0) format += "." + MD5.leftPad("", '0', numDecimals);
3525 05 Oct 15 nicklas 398     DecimalFormat df = new DecimalFormat(format, sym);
3525 05 Oct 15 nicklas 399     return df;
3525 05 Oct 15 nicklas 400   }
3525 05 Oct 15 nicklas 401   
3506 23 Sep 15 nicklas 402 }