From 3da6e95f920a0a00930e18d3929ec59f7bc3fee8 Mon Sep 17 00:00:00 2001
From: kohleman <kohleman>
Date: Tue, 11 Aug 2015 14:02:08 +0000
Subject: [PATCH] adopted for HiSeq3000 runs

SVN: 34436
---
 .../read-demultiplex-stats-nextseq.py         | 191 +++---
 .../read_demultiplex_stats.java               | 603 +++++++++---------
 2 files changed, 407 insertions(+), 387 deletions(-)

diff --git a/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read-demultiplex-stats-nextseq.py b/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read-demultiplex-stats-nextseq.py
index b66873933cb..787e008d89c 100755
--- a/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read-demultiplex-stats-nextseq.py
+++ b/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read-demultiplex-stats-nextseq.py
@@ -239,23 +239,99 @@ def process(transaction):
   ##########################################################
   
   def updateLane(transaction, codeSampleFlowCell, totalLaneStatistics):
-      
-      flowcell, lanes, numberOfLanes = sampleSearch(transaction, codeSampleFlowCell)
-      lane = lanes[0]
-      mutable_lane = transaction.getSampleForUpdate(lane.getSampleIdentifier())
-      print("Setting Complete Lanes Statistics For: " + lane.getSampleIdentifier())
-      
-      mutable_lane.setPropertyValue("YIELD_MBASES", str(int(totalLaneStatistics.Sum_PfYield)))
-      mutable_lane.setPropertyValue('RAW_YIELD_MBASES', str(int(totalLaneStatistics.Sum_RawYield)))
-      mutable_lane.setPropertyValue('PERCENTAGE_PASSED_FILTERING',str(int(totalLaneStatistics.Percentage_PfClusterCount_RawClusterCount)))
-      mutable_lane.setPropertyValue('PF_READS_SUM',str(int(totalLaneStatistics.Sum_PfClusterCount)))
-      mutable_lane.setPropertyValue('RAW_READS_SUM',str(int(totalLaneStatistics.Sum_RawClusterCount)))
-      mutable_lane.setPropertyValue('PFYIELDQ30PERCENTAGE', str(int(totalLaneStatistics.Percentage_PfYieldQ30_PfYield)))
-      mutable_lane.setPropertyValue('PFMEANQUALITYSCORE', str(totalLaneStatistics.Fraction_PfQualityScoreSum_PfYield))
-      mutable_lane.setPropertyValue('CLUSTERS_PF_WITHOUT_NOINDEX', str(int(totalLaneStatistics.Clusters_PfWithoutNoindex)))
+    
+    print("Setting Complete Lanes Statistics For: " + lane.getSampleIdentifier())
+    mutable_lane = transaction.getSampleForUpdate(lane.getSampleIdentifier())
+    mutable_lane.setPropertyValue("YIELD_MBASES", str(int(totalLaneStatistics.get(lane_in_int).Sum_PfYield)))
+    mutable_lane.setPropertyValue('RAW_YIELD_MBASES', str(int(totalLaneStatistics.get(lane_in_int).Sum_RawYield)))
+    mutable_lane.setPropertyValue('PERCENTAGE_PASSED_FILTERING',str(int(totalLaneStatistics.get(lane_in_int).Percentage_PfClusterCount_RawClusterCount)))
+    mutable_lane.setPropertyValue('PF_READS_SUM',str(int(totalLaneStatistics.get(lane_in_int).Sum_PfClusterCount)))
+    mutable_lane.setPropertyValue('RAW_READS_SUM',str(int(totalLaneStatistics.get(lane_in_int).Sum_RawClusterCount)))
+    mutable_lane.setPropertyValue('PFYIELDQ30PERCENTAGE', str(int(totalLaneStatistics.get(lane_in_int).Percentage_PfYieldQ30_PfYield)))
+    mutable_lane.setPropertyValue('PFMEANQUALITYSCORE', str(totalLaneStatistics.get(lane_in_int).Fraction_PfQualityScoreSum_PfYield))
+    mutable_lane.setPropertyValue('CLUSTERS_PF_WITHOUT_NOINDEX', str(int(totalLaneStatistics.get(lane_in_int).Clusters_PfWithoutNoindex)))
 
   ##########################################################
 
+  def update_datatsets(transaction, samplestatisticslist, codeSampleFlowLane, codeSampleFlowCell):
+    # Prepare links between XML and openBIS w.r.t to indexes in DataSet (openBIS):
+    print(codeSampleFlowLane)
+    index1list, index2list = getIndexesOfDataSetsOfSample(codeSampleFlowLane)
+    print(index1list)
+    
+    propertiesCode, propertiesCodeValue = getInfoSampleProperties(codeSampleFlowCell)
+    index1length = int(propertiesCodeValue[CODE_INDEX1LENGTH])
+    index2length = int(propertiesCodeValue[CODE_INDEX2LENGTH])
+    
+    nprocessedDataSets = 0
+    for s in samplestatisticslist:
+        print "\nContent in XML file:\n", s
+    
+        # Prepare link between XML and openBIS w.r.t to indexes in Barcode (XML):
+        indexes = s.Barcode.split(BARCODE_SPLIT_CHAR)
+        if len(indexes) == 1: # only first part in Barcode
+            index1search = indexes[0].upper()
+            index2search = INDEX_EMPTY
+        elif len(indexes) == 2: # both parts in Barcode
+            index1search = indexes[0].upper()
+            index2search = indexes[1].upper()
+        else:
+            index1search = INDEX_EMPTY
+            index2search = INDEX_EMPTY
+    
+        # Set link between XML and openBIS w.r.t to indexes in DataSet (openBIS):
+        if index1search == INDEX_EMPTY or index1search == INDEX_UNKNOWN: 
+            index1 = INDEX_NO
+        else: # Hint: just two cases were known about index1length, that is 8 or 6
+            if index1length > 7:
+                index1 = [ index1 for index1 in index1list if index1search == index1 ]
+            else: # for smaller indexlength, the index is by 1 shorter in XML-file than in openBIS
+                index1 = [ index1 for index1 in index1list if index1search == index1[:index1length] ]
+            try:
+                index1 = index1[0]
+            except: 
+                print '\nOCCURRED EXCEPTION: First index \"' + index1search + '\" of Barcode in XML file has no corresponding DataSet in openBIS!'
+                index1 = 'MISSING'
+        if index2search == INDEX_EMPTY or index2search == INDEX_UNKNOWN:
+            index2 = INDEX_NO
+        else: # Hint: just one case was known about index2length, that is 8
+            if index2length > 7: # second and larger index must be reversed and complemented in contrast to first or smaller index
+                index2 = [ index2 for index2 in index2list if reversecomplement(index2search) == index2 ]
+            else: # second and smaller index is unknown how to handle
+                index2 = [ index2 for index2 in index2list if reversecomplement(index2search) == index2 ]
+            try:
+                index2 = index2[0]
+            except: 
+                print '\nOCCURRED EXCEPTION: Second index \"' + index2search + '\" of Barcode in XML file has no corresponding DataSet in openBIS!'
+                index2 = 'MISSING'
+    
+        # Get DataSet of openBIS corresponding to Project/Sample/Barcode of XML file:
+        correspondingDataSet = searchDataSetsOfSample(codeSampleFlowLane, index1, index2)
+        try:
+            assert correspondingDataSet.size() == 1
+        except AssertionError: 
+            print ('\nOCCURRED EXCEPTION: ' + str(correspondingDataSet.size()) + ' DataSets found which Sample match the criteria index1 \"' + str(index1) + '\" and index2 \"' + str(index2) + '\" and code \"' + codeSampleFlowLane + '\" and type \"' + TYPE_DATASET + '\".')
+            continue 
+        
+        # Modify Properties of corresponding DataSet:
+        # (method setPropertyValue requires Strings as Input, but Number format must fit to Properties already defined in openBIS)
+        ds = transaction.getDataSetForUpdate(correspondingDataSet[0].getDataSetCode())
+        ds.setPropertyValue('YIELD_MBASES', str(int(s.Mega_PfYield)))
+        ds.setPropertyValue('RAW_YIELD_MBASES', str(int(s.Mega_RawYield)))
+        ds.setPropertyValue('PERCENTAGE_PASSED_FILTERING',str(s.Percentage_PfClusterCount_RawClusterCount))
+        ds.setPropertyValue('PF_READS_SUM',str(int(s.Sum_PfClusterCount))) # convert first to Integer, then to String
+        ds.setPropertyValue('RAW_READS_SUM',str(int(s.Sum_RawClusterCount))) # convert first to Integer, then to String
+        ds.setPropertyValue('PERCENTAGE_RAW_CLUSTERS_PER_LANE', str(s.Percentage_RawClusterCount_AllRawClusterCounts))
+        ds.setPropertyValue('PFYIELDQ30PERCENTAGE', str(s.Percentage_PfYieldQ30_PfYield))
+        ds.setPropertyValue('PFMEANQUALITYSCORE', str(s.Fraction_PfQualityScoreSum_PfYield))
+        print "Properties in DataSet \"" + correspondingDataSet[0].getDataSetCode() + "\" are modified."
+        nprocessedDataSets += 1
+        
+    return nprocessedDataSets
+
+
+  ##########################################################
+  
   print('\nPROCESS RUNNING '+time.ctime())
   incomingPath = transaction.getIncoming().getPath()  
   FileGenerator= locate(XML_FILENAME, incomingPath)
@@ -264,89 +340,24 @@ def process(transaction):
   
   # Import data of XML file (independent of openBIS data):
   JavaClassToProcessXML = read_demultiplex_stats() # this function is implemented as Class in Java:
-  samplestatisticslist = JavaClassToProcessXML.importXMLdata_and_calculateStatistics(xmlfile)
+  samplestatisticslist = JavaClassToProcessXML.importXmlAndCalculateStatistics(xmlfile)
   totalLaneStatistics = JavaClassToProcessXML.calculateTotalLaneStatistics(samplestatisticslist)
   
   if len(samplestatisticslist) == 0:
     print "\nNo Projects/Samples/Barcodes are contained in XML-file " + xmlfile + "!"
     return
 
-  # Prepare links between XML and openBIS w.r.t. Samples:
-  codeSampleFlowCell = samplestatisticslist[0].Flowcell # expect just one equal FlowCell of all imported datasets
-  codeSampleFlowLane = samplestatisticslist[0].Flowcell + ":1" # expect just one equal FlowLane of all imported datasets
+  print(samplestatisticslist[0].Flowcell)
+  codeSampleFlowCell = samplestatisticslist[0].Flowcell # expect just one equal FlowCell
+  flowcell, lanes, numberOfLanes = sampleSearch(transaction, codeSampleFlowCell)
   
-  updateLane(transaction, codeSampleFlowCell, totalLaneStatistics)
-
-  # Prepare links between XML and openBIS w.r.t to indexes in DataSet (openBIS):
-  index1list, index2list = getIndexesOfDataSetsOfSample(codeSampleFlowLane)
-  propertiesCode, propertiesCodeValue = getInfoSampleProperties(codeSampleFlowCell)
-  index1length = int(propertiesCodeValue[CODE_INDEX1LENGTH])
-  index2length = int(propertiesCodeValue[CODE_INDEX2LENGTH])
-
-  nprocessedDataSets = 0
-  for s in samplestatisticslist:
-    print "\nContent in XML file:\n", s
-    print "Connection to openBIS:"
-
-    # Prepare link between XML and openBIS w.r.t to indexes in Barcode (XML):
-    indexes = s.Barcode.split(BARCODE_SPLIT_CHAR)
-    if len(indexes) == 1: # only first part in Barcode
-      index1search = indexes[0].upper()
-      index2search = INDEX_EMPTY
-    elif len(indexes) == 2: # both parts in Barcode
-      index1search = indexes[0].upper()
-      index2search = indexes[1].upper()
-    else:
-      index1search = INDEX_EMPTY
-      index2search = INDEX_EMPTY
-
-    # Set link between XML and openBIS w.r.t to indexes in DataSet (openBIS):
-    if index1search == INDEX_EMPTY or index1search == INDEX_UNKNOWN: 
-      index1 = INDEX_NO
-    else: # Hint: just two cases were known about index1length, that is 8 or 6
-      if index1length > 7:
-        index1 = [ index1 for index1 in index1list if index1search == index1 ]
-      else: # for smaller indexlength, the index is by 1 shorter in XML-file than in openBIS
-        index1 = [ index1 for index1 in index1list if index1search == index1[:index1length] ]
-      try:
-        index1 = index1[0]
-      except: 
-        print '\nOCCURRED EXCEPTION: First index \"' + index1search + '\" of Barcode in XML file has no corresponding DataSet in openBIS!'
-        index1 = 'MISSING'
-    if index2search == INDEX_EMPTY or index2search == INDEX_UNKNOWN:
-      index2 = INDEX_NO
-    else: # Hint: just one case was known about index2length, that is 8
-      if index2length > 7: # second and larger index must be reversed and complemented in contrast to first or smaller index
-        index2 = [ index2 for index2 in index2list if reversecomplement(index2search) == index2 ]
-      else: # second and smaller index is unknown how to handle
-        index2 = [ index2 for index2 in index2list if reversecomplement(index2search) == index2 ]
-      try:
-        index2 = index2[0]
-      except: 
-        print '\nOCCURRED EXCEPTION: Second index \"' + index2search + '\" of Barcode in XML file has no corresponding DataSet in openBIS!'
-        index2 = 'MISSING'
-
-    # Get DataSet of openBIS corresponding to Project/Sample/Barcode of XML file:
-    correspondingDataSet = searchDataSetsOfSample(codeSampleFlowLane, index1, index2)
-    try:
-      assert correspondingDataSet.size() == 1
-    except AssertionError: 
-      print ('\nOCCURRED EXCEPTION: ' + str(correspondingDataSet.size()) + ' DataSets found which Sample match the criteria index1 \"' + str(index1) + '\" and index2 \"' + str(index2) + '\" and code \"' + codeSampleFlowLane + '\" and type \"' + TYPE_DATASET + '\".')
-      continue 
-    
-    # Modify Properties of corresponding DataSet:
-    # (method setPropertyValue requires Strings as Input, but Number format must fit to Properties already defined in openBIS)
-    ds = transaction.getDataSetForUpdate(correspondingDataSet[0].getDataSetCode())
-    ds.setPropertyValue('YIELD_MBASES', str(int(s.Mega_PfYield)))
-    ds.setPropertyValue('RAW_YIELD_MBASES', str(int(s.Mega_RawYield)))
-    ds.setPropertyValue('PERCENTAGE_PASSED_FILTERING',str(s.Percentage_PfClusterCount_RawClusterCount))
-    ds.setPropertyValue('PF_READS_SUM',str(int(s.Sum_PfClusterCount))) # convert first to Integer, then to String
-    ds.setPropertyValue('RAW_READS_SUM',str(int(s.Sum_RawClusterCount))) # convert first to Integer, then to String
-    ds.setPropertyValue('PERCENTAGE_RAW_CLUSTERS_PER_LANE', str(s.Percentage_RawClusterCount_AllRawClusterCounts))
-    ds.setPropertyValue('PFYIELDQ30PERCENTAGE', str(s.Percentage_PfYieldQ30_PfYield))
-    ds.setPropertyValue('PFMEANQUALITYSCORE', str(s.Fraction_PfQualityScoreSum_PfYield))
-    print "Properties in DataSet \"" + correspondingDataSet[0].getDataSetCode() + "\" are modified."
-    nprocessedDataSets += 1
+  for lane in lanes:
+    lane_in_int = int(lane.getCode().split(":")[-1])
+    if (lane_in_int in totalLaneStatistics.keySet()):
+        updateLane(transaction, codeSampleFlowCell, totalLaneStatistics)
+        
+        codeSampleFlowLane = ":".join([codeSampleFlowCell, str(lane_in_int)])
+        nprocessedDataSets = update_datatsets(transaction, samplestatisticslist, codeSampleFlowLane, codeSampleFlowCell)
 
   print "\n", nprocessedDataSets, " openBIS-DataSets were processed." 
   print len(samplestatisticslist), " XML-Projects/-Samples/-Barcodes were processed."
diff --git a/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read_demultiplex_stats.java b/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read_demultiplex_stats.java
index e10a38ce32f..385601962cd 100644
--- a/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read_demultiplex_stats.java
+++ b/deep_sequencing_unit/sourceTest/core-plugins/illumina-qgf/1/dss/drop-boxes/read-demultiplex-stats-nextseq/read_demultiplex_stats.java
@@ -25,29 +25,46 @@ limitations under the License.
        - read_demultiplex_stats$Statistics.class
  */
 
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
 
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 //##########################################################
 
 public final class read_demultiplex_stats
 {
 
-    public List<Statistics> importXMLdata_and_calculateStatistics(String XMLfile)
-    {
+    public static ArrayList<Statistics> importXmlAndCalculateStatistics(String XMLFile) throws Exception {
+
+        ArrayList<Statistics> stats = executeImportXmlAndCalculateStatistics(XMLFile);
+        HashMap<Integer, ArrayList<Statistics>> groupedList = groupByLane(stats);
 
-        ArrayList<Statistics> samplestatisticslist = new ArrayList<Statistics>();
+        for (Statistics s : stats)
+            s.adaptStatisticsWithRespectToAllSamples(stats, groupedList);
+        return stats;
+    }
+
+    /**
+     *
+     * Streams through a given XML file, parses the data and writes it into a Statistics object
+     *
+     * @param XMLfile: ConversionStats.xml
+     * @return a ArrayList of <Statistics>
+     */
+    private static  ArrayList<Statistics> executeImportXmlAndCalculateStatistics(String XMLfile) throws Exception {
+        ArrayList<Statistics> sampleStatisticsList = new ArrayList<>();
 
         /*Parse corresponding XML file, put all values into a memory structure, calculate statistics overall samples.
-          Output: samplestatisticslist (list of Sample-Statistics-Objects)
+          Output: sampleStatisticsList (list of Sample-Statistics-Objects)
           Input:  XMLfile having structure of file ConversionStats.xml (Example of 1.10.2014):
                   <?xml version="1.0" encoding="utf-8"?>                             => Assumptions about XML structure:
                   <Stats>                                                            => Element is singlechild
@@ -86,70 +103,77 @@ public final class read_demultiplex_stats
                               </Tile>
                               <Tile number="11102">
                               [...]
-        */
 
-        try
-        {
+                      </Project>
+                      <Lane number="2">
+                        <TopUnknownBarcodes>
+                          <Barcode count="150988002" sequence="NNNNNNN"/>
+                          <Barcode count="167095" sequence="CCCCCCC"/>
+                          <Barcode count="57859" sequence="CCCGTCC"/>
+                          <Barcode count="49993" sequence="CCGATGT"/>
+                          <Barcode count="42981" sequence="GTCCCGC"/>
+                          <Barcode count="40446" sequence="TAAAATT"/>
+                          <Barcode count="39962" sequence="CCAGATC"/>
+                          <Barcode count="34688" sequence="GATGTAT"/>
+                          <Barcode count="32013" sequence="AAAAAGT"/>
+                          <Barcode count="30501" sequence="AGATCAT"/>
+                        </TopUnknownBarcodes>
+                      </Lane>
+                      [...]
+        */
 
-            // temporary variables (frequently changing during XML-read-in):
-            String errormessage = "";
-            int event = 0;
-            int skip = 0;
-            String curflowcellname = "";
-            String curprojectname = "";
-            String cursamplename = "";
-            String curbarcodename = "";
-            double curlanenumber = Double.NaN; // obvious double, but could be turned into int
-            double curtilenumber = Double.NaN; // obvious double, but could be turned into int
-            Sample cursample = null;
-            Statistics curstatistics = null;
-            SampleItem currawitem = null;
-            SampleItem curpfitem = null;
-
-            InputStream xmlfile = new FileInputStream(XMLfile);
-            XMLInputFactory xmlfactory = XMLInputFactory.newInstance();
-            XMLStreamReader xmlparser = xmlfactory.createXMLStreamReader(xmlfile);
+//        Map<Integer, Map<String, Integer>> barcodesPerLane = null;
+
+        try {
+            String errorMessage;
+            int event;
+            int skip;
+            String flowcellName = "";
+            String projectName = "";
+            String sampleName = "";
+            String barcodeName = "";
+            int laneNumber = 0;
+            int tileNumber;
+            Sample currentSample = null;
+            Statistics statistics;
+            SampleItem rawItem;
+            SampleItem pfItem;
+            Map<String, Integer> barcodesMap = new HashMap<>();
+            Map<Integer, Map<String, Integer>> barcodesPerLane = new HashMap<>();
+
+                    InputStream xmlFile = new FileInputStream(XMLfile);
+            XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
+            XMLStreamReader xmlParser = xmlFactory.createXMLStreamReader(xmlFile);
 
             // Start-Tag "Stats":
-            event = xmlparser.nextTag(); // Assumption: just white space or comments are aside explicit start-tag
-            if (event != XMLStreamConstants.START_ELEMENT || !xmlparser.getLocalName().equals("Stats"))
-            {
-                errormessage =
-                        "STRANGE ERROR IN METHOD importXMLdata_and_calculateStatistics WHEN READING IN XMLFILE. => CHECK CODE AND XMLFILE-STRUCTURE! Got " + event;
-                throw new Exception(errormessage);
+            event = xmlParser.nextTag(); // Assumption: just white space or comments are aside explicit start-tag
+            if (event != XMLStreamConstants.START_ELEMENT || !xmlParser.getLocalName().equals("Stats")) {
+                errorMessage =
+                        "STRANGE ERROR IN METHOD importXmlAndCalculateStatistics WHEN READING IN XMLFILE. => CHECK CODE AND XMLFILE-STRUCTURE! Got " + event;
+                throw new Exception(errorMessage);
             }
-            //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
 
             // Loop over potential Tags "Flowcell":
-            event = xmlparser.nextTag(); // Assumption: just white spaces or comments are aside start- or end-tag
+            event = xmlParser.nextTag(); // Assumption: just white spaces or comments are aside start- or end-tag
             //            List<Statistics> samplestatistics = new ArrayList<Statistics>();
             boolean doimport = true;
-            while (doimport)
-            {
+            while (doimport) {
                 // concerning tag Flowcell:
-                if (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Flowcell"))
-                {
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                    curflowcellname = xmlparser.getAttributeValue(0); // Assumption: Flowcell-attribute flowcell-id is just string
-                    event = xmlparser.nextTag();
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Flowcell"))
-                {
-                    curflowcellname = "";
-                    event = xmlparser.nextTag();
+                if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Flowcell")) {
+                    flowcellName = xmlParser.getAttributeValue(0);
+                    event = xmlParser.nextTag();
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Flowcell")) {
+                    flowcellName = "";
+                    event = xmlParser.nextTag();
 
                     // concerning tag Project:
-                } else if (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Project"))
-                {
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                    if (xmlparser.getAttributeValue(0).equals("all"))
-                    {
-                        // skip the current XML element and all of its following subelements:
+                } else if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Project")) {
+                    if (xmlParser.getAttributeValue(0).equals("all")) {
+                        //skip the current XML element and all of its following subelements:
                         skip = 1;
-                        while (skip > 0)
-                        {
-                            event = xmlparser.next();
-                            switch (event)
-                            {
+                        while (skip > 0) {
+                            event = xmlParser.next();
+                            switch (event) {
                                 case XMLStreamConstants.END_ELEMENT:
                                     skip -= 1;
                                     break;
@@ -161,217 +185,239 @@ public final class read_demultiplex_stats
                                     break;
                             }
                         }
-                    } else
-                    {
-                        curprojectname = xmlparser.getAttributeValue(0); // Assumption: Project-attribute name is just string
+                    } else {
+                    projectName = xmlParser.getAttributeValue(0);
+
                     }
-                    event = xmlparser.nextTag();
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Project"))
-                {
-                    curprojectname = "";
-                    event = xmlparser.nextTag();
+                    event = xmlParser.nextTag();
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Project")) {
+                    projectName = "";
+                    event = xmlParser.nextTag();
 
                     // concerning tag Sample:
-                } else if (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Sample"))
-                {
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                    if (xmlparser.getAttributeValue(0).equals("all"))
-                    {
+                } else if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Sample")) {
+                    if (xmlParser.getAttributeValue(0).equals("all")) {
                         // skip the current XML element and all of its following subelements:
                         skip = 1;
-                        while (skip > 0)
-                        {
-                            event = xmlparser.next();
-                            switch (event)
-                            {
+                        while (skip > 0) {
+                            event = xmlParser.next();
+                            switch (event) {
                                 case XMLStreamConstants.END_ELEMENT:
                                     skip -= 1;
-                                    break; // break-command after each case is necessary in switch-statement
+                                    break;
                                 case XMLStreamConstants.START_ELEMENT:
                                     skip += 1;
-                                    break; // break-command after each case is necessary in switch-statement
+                                    break;
                                 default:
                                     skip += 0; // text elements, spaces, ...
-                                    break; // break-command after each case is necessary in switch-statement
+                                    break;
                             }
                         }
-                    } else
-                    {
-                        cursamplename = xmlparser.getAttributeValue(0); // Assumption: Sample-attribute name is just string
+                    } else {
+                        sampleName = xmlParser.getAttributeValue(0);
                     }
-                    event = xmlparser.nextTag();
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Sample"))
-                {
-                    cursamplename = "";
-                    event = xmlparser.nextTag();
+                    event = xmlParser.nextTag();
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Sample")) {
+                    sampleName = "";
+                    event = xmlParser.nextTag();
 
                     // concerning tag Barcode (which is as well the start/end of Project-/Sample-Entry):
-                } else if (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Barcode"))
-                {
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                    if (xmlparser.getAttributeValue(0).equals("all"))
-                    {
+                } else if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Barcode")) {
+                    if (xmlParser.getAttributeValue(0).equals("all")) {
                         // skip the current XML element and all of its following subelements:
                         skip = 1;
-                        while (skip > 0)
-                        {
-                            event = xmlparser.next();
-                            switch (event)
-                            {
+                        while (skip > 0) {
+                            event = xmlParser.next();
+                            switch (event) {
                                 case XMLStreamConstants.END_ELEMENT:
                                     skip -= 1;
-                                    break; // break-command after each case is necessary in switch-statement
+                                    break;
                                 case XMLStreamConstants.START_ELEMENT:
                                     skip += 1;
-                                    break; // break-command after each case is necessary in switch-statement
+                                    break;
                                 default:
                                     skip += 0; // text elements, spaces, ...
-                                    break; // break-command after each case is necessary in switch-statement
+                                    break;
                             }
                         }
-                    } else
-                    {
-                        curbarcodename = xmlparser.getAttributeValue(0); // Assumption: Barcode-attribute name is just string
-                        cursample = new Sample();
-                        cursample.Flowcell = curflowcellname;
-                        cursample.Project = curprojectname;
-                        cursample.Sample = cursamplename;
-                        cursample.Barcode = curbarcodename;
+                    } else {
+                        barcodeName = xmlParser.getAttributeValue(0);
                     }
-                    event = xmlparser.nextTag();
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Barcode"))
-                {
-                    // Statistics 1st step: calculate individual statistics per sample:
-                    curstatistics = new Statistics(cursample);
-                    samplestatisticslist.add(curstatistics);
-                    cursample = null;
-                    curstatistics = null;
-                    curbarcodename = "";
-                    event = xmlparser.nextTag();
+                    event = xmlParser.nextTag();
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Barcode")) {
+                    barcodeName = "";
+                    event = xmlParser.nextTag();
+
 
                     // concerning Lane:
-                } else if (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Lane"))
-                {
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                    curlanenumber = Double.parseDouble(xmlparser.getAttributeValue(0)); // Assumption:Lane-attribute number is always numeric
-                    event = xmlparser.nextTag();
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Lane"))
-                {
-                    curlanenumber = Double.NaN;
-                    event = xmlparser.nextTag();
+                } else if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Lane")) {
+//                    System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
+                    laneNumber = Integer.parseInt(xmlParser.getAttributeValue(0));
+
+                    // Now we have everything we need, we put it into a Sample
+                    currentSample = new Sample();
+
+                    if (sampleName.startsWith("Undetermined")) {
+                        currentSample.Sample = sampleName + "_" + flowcellName + "_" + laneNumber;
+                    } else {
+                        currentSample.Sample = sampleName;
+                    }
+
+                    currentSample.Flowcell = flowcellName;
+                    currentSample.Lane = laneNumber;
+                    currentSample.Project = projectName;
+                    currentSample.Barcode = barcodeName;
+                    event = xmlParser.nextTag();
+//                    System.out.println(currentSample.Sample);
+
+
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Lane")) {
+                    // Statistics 1st step: calculate individual statistics per sample:
+                    statistics = new Statistics(currentSample);
+                    if (!currentSample.Project.equals("")) {
+                        sampleStatisticsList.add(statistics);
+                    }
+                    currentSample = null;
+                    statistics = null;
+
+//                    laneNumber = Double.NaN;
+                    event = xmlParser.nextTag();
 
                     // concerning Tile with all its sub-elements:
-                } else if (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Tile"))
-                {
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                    curtilenumber = Double.parseDouble(xmlparser.getAttributeValue(0)); // Assumption: Tile-attribute number is always numeric
+                } else if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Tile")) {
+                    tileNumber = Integer.parseInt(xmlParser.getAttributeValue(0));
                     // concerning Raw with Assumption: Raw-element is singlechild:
-                    xmlparser.nextTag();
-                    //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName());
-                    currawitem = new SampleItem();
-                    currawitem.Type = "Raw";
-                    currawitem.Lane = curlanenumber;
-                    currawitem.Tile = curtilenumber;
-                    xmlparser.nextTag();
-                    currawitem.ClusterCount = Double.parseDouble(xmlparser.getElementText()); // Assumption: ClusterCount-element is numeric singlechild
-                    //System.out.println("\nValue: ClusterCount=" + currawitem.ClusterCount);
-                    xmlparser.nextTag();
-                    while (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Read"))
-                    { // Assumption: at least or more than 1 Read-element
-                      //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                        xmlparser.nextTag();
-                        currawitem.YieldList.add(Double.parseDouble(xmlparser.getElementText())); // Assumption: Yield-element is numeric singlechild
-                        xmlparser.nextTag();
-                        currawitem.YieldQ30List.add(Double.parseDouble(xmlparser.getElementText())); // Assumption: YieldQ30List-element is numeric singlechild
-                        xmlparser.nextTag();
-                        currawitem.QualityScoreSumList.add(Double.parseDouble(xmlparser.getElementText())); // Assumption: QualityScoreSumList-element is numeric singlechild
-                        xmlparser.nextTag();
-                        xmlparser.nextTag();
-                        //System.out.println("Values in Read: Yield=" + currawitem.YieldList.get(currawitem.YieldList.size()-1) + ", YieldQ30=" + currawitem.YieldQ30List.get(currawitem.YieldQ30List.size()-1) + ", QualityScoreSum=" + currawitem.QualityScoreSumList.get(currawitem.QualityScoreSumList.size()-1));
+                    xmlParser.nextTag();
+                    rawItem = new SampleItem();
+                    rawItem.Type = "Raw";
+                    rawItem.Lane = laneNumber;
+                    rawItem.Tile = tileNumber;
+                    xmlParser.nextTag();
+                    rawItem.ClusterCount = Integer.parseInt(xmlParser.getElementText()); // Assumption: ClusterCount-element is numeric singlechild
+                    //System.out.println("\nValue: ClusterCount=" + rawItem.ClusterCount);
+                    xmlParser.nextTag();
+                    while (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Read")) {
+                        //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
+                        xmlParser.nextTag();
+                        rawItem.YieldList.add(Double.parseDouble(xmlParser.getElementText()));
+                        xmlParser.nextTag();
+                        rawItem.YieldQ30List.add(Double.parseDouble(xmlParser.getElementText()));
+                        xmlParser.nextTag();
+                        rawItem.QualityScoreSumList.add(Double.parseDouble(xmlParser.getElementText()));
+                        xmlParser.nextTag();
+                        xmlParser.nextTag();
+                        //System.out.println("Values in Read: Yield=" + rawItem.YieldList.get(rawItem.YieldList.size()-1) + ", YieldQ30=" + rawItem.YieldQ30List.get(rawItem.YieldQ30List.size()-1) + ", QualityScoreSum=" + rawItem.QualityScoreSumList.get(rawItem.QualityScoreSumList.size()-1));
                     }
-                    //System.out.println("\nRaw-SampleItem  " + currawitem);
-                    cursample.RawList.add(currawitem);
-                    currawitem = null;
+                    //System.out.println("\nRaw-SampleItem  " + rawItem);
+                    currentSample.RawList.add(rawItem);
+
+
+                    rawItem = null;
                     // concerning Pf with Assumption that entire Pf-element is structured same as Raw:
-                    xmlparser.nextTag();
+                    xmlParser.nextTag();
                     //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName());
-                    curpfitem = new SampleItem();
-                    curpfitem.Type = "Pf";
-                    curpfitem.Lane = curlanenumber;
-                    curpfitem.Tile = curtilenumber;
-                    xmlparser.nextTag();
-                    curpfitem.ClusterCount = Double.parseDouble(xmlparser.getElementText());
-                    //System.out.println("\nValue: ClusterCount=" + curpfitem.ClusterCount);
-                    xmlparser.nextTag();
-                    while (event == XMLStreamConstants.START_ELEMENT && xmlparser.getLocalName().equals("Read"))
-                    {
+                    pfItem = new SampleItem();
+                    pfItem.Type = "Pf";
+                    pfItem.Lane = laneNumber;
+                    pfItem.Tile = tileNumber;
+                    xmlParser.nextTag();
+                    pfItem.ClusterCount = Integer.parseInt(xmlParser.getElementText());
+                    //System.out.println("\nValue: ClusterCount=" + pfItem.ClusterCount);
+                    xmlParser.nextTag();
+                    while (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Read")) {
                         //System.out.println("\nStart-Element with tag " + xmlparser.getLocalName() + " with " + xmlparser.getAttributeCount() + " attributes with first attribute: " + xmlparser.getAttributeLocalName(0) +" = " + xmlparser.getAttributeValue(0));
-                        xmlparser.nextTag();
-                        curpfitem.YieldList.add(Double.parseDouble(xmlparser.getElementText()));
-                        xmlparser.nextTag();
-                        curpfitem.YieldQ30List.add(Double.parseDouble(xmlparser.getElementText()));
-                        xmlparser.nextTag();
-                        curpfitem.QualityScoreSumList.add(Double.parseDouble(xmlparser.getElementText()));
-                        xmlparser.nextTag();
-                        xmlparser.nextTag();
-                        //System.out.println("Values in Read: Yield=" + curpfitem.YieldList.get(curpfitem.YieldList.size()-1) + ", YieldQ30=" + curpfitem.YieldQ30List.get(curpfitem.YieldQ30List.size()-1) + ", QualityScoreSum=" + curpfitem.QualityScoreSumList.get(curpfitem.QualityScoreSumList.size()-1));
+                        xmlParser.nextTag();
+                        pfItem.YieldList.add(Double.parseDouble(xmlParser.getElementText()));
+                        xmlParser.nextTag();
+                        pfItem.YieldQ30List.add(Double.parseDouble(xmlParser.getElementText()));
+                        xmlParser.nextTag();
+                        pfItem.QualityScoreSumList.add(Double.parseDouble(xmlParser.getElementText()));
+                        xmlParser.nextTag();
+                        xmlParser.nextTag();
+                        //System.out.println("Values in Read: Yield=" + pfItem.YieldList.get(pfItem.YieldList.size()-1) + ", YieldQ30=" + pfItem.YieldQ30List.get(pfItem.YieldQ30List.size()-1) + ", QualityScoreSum=" + pfItem.QualityScoreSumList.get(pfItem.QualityScoreSumList.size()-1));
                     }
-                    //System.out.println("\nPf-SampleItem  " + curpfitem);
-                    cursample.PfList.add(curpfitem);
-                    curpfitem = null;
+                    //System.out.println("\nPf-SampleItem  " + pfItem);
+                    currentSample.PfList.add(pfItem);
+                    pfItem = null;
                     // attain end of current Tile and afterwards continue in next Tile/Lane/Barcode/Sample/Project:
-                    event = xmlparser.nextTag();
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Tile"))
-                {
-                    curtilenumber = Double.NaN;
-                    event = xmlparser.nextTag();
+                    event = xmlParser.nextTag();
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Tile")) {
+                    tileNumber = 0;
+                    event = xmlParser.nextTag();
+
+
+                } else if (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("TopUnknownBarcodes")) {
+
+                    event = xmlParser.nextTag();
+                    while (event == XMLStreamConstants.START_ELEMENT && xmlParser.getLocalName().equals("Barcode")) {
+                        Integer numberOfBarcodes = Integer.valueOf((xmlParser.getAttributeValue(0)));
+                        String barcode = xmlParser.getAttributeValue(1);
+                        barcodesMap.put(barcode, numberOfBarcodes);
+                        xmlParser.nextTag();
+                        event = xmlParser.nextTag();
+                    }
+
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("TopUnknownBarcodes")) {
+
+                    barcodesPerLane.put(laneNumber, barcodesMap);
+                    event = xmlParser.nextTag();
 
                     //  concerning finish of reading in XML or hit upon error due XML content:
-                } else if (event == XMLStreamConstants.END_ELEMENT && xmlparser.getLocalName().equals("Stats"))
-                {
+                } else if (event == XMLStreamConstants.END_ELEMENT && xmlParser.getLocalName().equals("Stats")) {
                     // this final part of while loop is just for analyzing potential errors, but
                     // could be removed and changed in:  while xmlparser.getLocalName() != 'Stats'
                     doimport = false;
-                } else
-                {
+                } else {
                     doimport = false;
                     System.out.println("Warning: Different XML structure than expectet. Got event: " + event);
                 }
             }
-            xmlparser.close();
+            xmlParser.close();
 
-        } catch (FileNotFoundException | XMLStreamException e)
-        {
+        } catch (FileNotFoundException | XMLStreamException | IllegalArgumentException e) {
             System.out.println("OCCURRED EXCEPTION " + e.toString());
             e.printStackTrace();
-        } catch (IllegalArgumentException e)
-        {
-            System.out.println("OCCURRED EXCEPTION " + e.toString());
-            e.printStackTrace();
-        } catch (Exception e)
-        { // catch any other exception
-            System.out.println("OCCURRED EXCEPTION " + e.toString());
-            e.printStackTrace();
-        } finally
-        { // anyway adapt statistics and return output (It would be empty list due to constructor of this object)
-          // Statistics 2nd step: adapt single sample's statistics including entire list of samples
-            for (Statistics s : samplestatisticslist)
-                s.adaptStatisticsWithRespectToAllSamples(samplestatisticslist);
         }
-        return samplestatisticslist;
-
+        return sampleStatisticsList;
     }
 
-    public LaneStatistics calculateTotalLaneStatistics(ArrayList<Statistics> samplestatisticslist)
+    public static HashMap<Integer, LaneStatistics> calculateTotalLaneStatistics(ArrayList<Statistics> samplestatisticslist)
     {
-        LaneStatistics laneStats = new LaneStatistics(samplestatisticslist);
-        laneStats.calculateOverallStats();
-        return laneStats;
+        HashMap<Integer, LaneStatistics> listOfLaneStatistics= new HashMap<Integer, LaneStatistics>();
+
+        HashMap<Integer, ArrayList<Statistics>> groupedList = groupByLane(samplestatisticslist);
+
+        for (Integer key : groupedList.keySet()) {
+
+            LaneStatistics laneStats = new LaneStatistics(groupedList.get(key));
+            laneStats.calculateOverallStats(key);
+            listOfLaneStatistics.put(key, laneStats);
+        }
+        return listOfLaneStatistics;
     }
 
+
+    private static HashMap<Integer, ArrayList<Statistics>> groupByLane(ArrayList<Statistics> samplestatisticslist) {
+        // Group ArrayList by Lane
+        HashMap<Integer, ArrayList<Statistics>> groupedList = new HashMap <Integer, ArrayList<Statistics>>();
+        for (Statistics s : samplestatisticslist) {
+
+            if (groupedList.containsKey(s.Lane)) {
+                groupedList.get(s.Lane).add(s);
+            }
+            else {
+                ArrayList <Statistics> newEntry = new ArrayList<Statistics>();
+                newEntry.add(s);
+                groupedList.put(s.Lane, newEntry);
+            }
+        }
+        return groupedList;
+    }
+
+
     // ##########################################################
 
-    public class SampleItem
+    private static class SampleItem
     {
         /*
          * Object of an item in sample including - the corresponding type Raw or Pf - the index of corresponding Lane, Tile - measured value of
@@ -380,20 +426,19 @@ public final class read_demultiplex_stats
 
         public String Type = "";
 
-        // Define unknown numerical value. Type double could be exchanged with int, but double is necessary to initialize NaN-value.
-        public double Lane = Double.NaN;
+        public Integer Lane = 0;
 
-        public double Tile = Double.NaN;
+        public Integer Tile = 0;
 
-        public double ClusterCount = Double.NaN;
+        public Integer ClusterCount = 0;
 
         // Define unknown ArrayList of numerical values with changeable List size. Type Double(object) instead of double(primitive) is necessary in
         // Lists.
-        public List<Double> YieldList = new ArrayList<Double>();
+        public List<Double> YieldList = new ArrayList<>();
 
-        public List<Double> YieldQ30List = new ArrayList<Double>();
+        public List<Double> YieldQ30List = new ArrayList<>();
 
-        public List<Double> QualityScoreSumList = new ArrayList<Double>();
+        public List<Double> QualityScoreSumList = new ArrayList<>();
 
         public String toString()
         {
@@ -406,13 +451,15 @@ public final class read_demultiplex_stats
 
     // ##########################################################
 
-    public class Sample
+    public static class Sample
     {
         /*
          * Object of an entire sample including - the name of Flowcell, Project, Sample, Barcode - the list of Raw and Pf SampleItem-Objects
          */
 
         public String Flowcell = "";
+        
+        public Integer Lane = 0;
 
         public String Project = "";
 
@@ -421,13 +468,13 @@ public final class read_demultiplex_stats
         public String Barcode = "";
 
         // Define unknown ArrayList of SampleItems:
-        public List<SampleItem> RawList = new ArrayList<SampleItem>();
+        public List<SampleItem> RawList = new ArrayList<>();
 
-        public List<SampleItem> PfList = new ArrayList<SampleItem>();
+        public List<SampleItem> PfList = new ArrayList<>();
 
         public String toString()
         {
-            return "Flowcell: " + this.Flowcell + ", Project: " + this.Project + ", Sample: " + this.Sample + ", Barcode: " + this.Barcode
+            return "Flowcell: " + this.Flowcell + ", Lane: " + this.Lane + ", Project: " + this.Project + ", Sample: " + this.Sample + ", Barcode: " + this.Barcode
                     + ", RawList: " + this.RawList + ", PfList: " + this.PfList;
         }
 
@@ -435,15 +482,15 @@ public final class read_demultiplex_stats
 
     // ##########################################################
 
-    public class Statistics extends Sample
+    public static class Statistics extends Sample
     {
         /*
          * Object of Statistics within one single sample inherited from Sample-Object
          */
 
-        public double Sum_RawClusterCount = Double.NaN; // obvious double, but could be turned into int
+        public Integer Sum_RawClusterCount = 0;
 
-        public double Sum_PfClusterCount = Double.NaN; // obvious double, but could be turned into int
+        public Integer Sum_PfClusterCount = 0;
 
         public double Sum_RawYield = Double.NaN;
 
@@ -479,6 +526,7 @@ public final class read_demultiplex_stats
 
             super();
             Flowcell = sample.Flowcell;
+            Lane = sample.Lane;
             Project = sample.Project;
             Sample = sample.Sample;
             Barcode = sample.Barcode;
@@ -539,17 +587,17 @@ public final class read_demultiplex_stats
 
         public String toString()
         {
-            return "Flowcell: " + this.Flowcell + ", Project: " + this.Project + ", Sample: " + this.Sample + ", Barcode: " + this.Barcode
+            return "Flowcell: " + this.Flowcell + ", Lane: "+ this.Lane + ", Project: " + this.Project + ", Sample: " + this.Sample + ", Barcode: " + this.Barcode
                     + ", Raw Clusters: " + (long) this.Sum_RawClusterCount + ", Mbases Raw Yield: " + this.Mega_RawYield
                     + ", % Raw Clusters overall: " + this.Percentage_RawClusterCount_AllRawClusterCounts
                     + ", Pf Clusters: " + (long) this.Sum_PfClusterCount + ", Mbases Pf Yield: " + this.Mega_PfYield
                     + ", % PfYield/RawYield: " + this.Percentage_PfYield_RawYield
                     + ", % PfYieldQ30/PfYield: " + this.Percentage_PfYieldQ30_PfYield
                     + ", Mean Pf Quality Score: " + this.Fraction_PfQualityScoreSum_PfYield
-                    + ", % Passes Filtering: " + this.Percentage_PfClusterCount_RawClusterCount;
+                    + ", % Passes Filtering: " + this.Percentage_PfClusterCount_RawClusterCount + "\n";
         }
 
-        public void adaptStatisticsWithRespectToAllSamples(List<Statistics> statisticslist)
+        public void adaptStatisticsWithRespectToAllSamples(ArrayList<Statistics> statisticslist, HashMap<Integer, ArrayList<Statistics>>  groupedList)
         {
             /*
              * This Statistics-Object (corresponding to one sample) is adapted by employing a list of Statistics-Objects corresponding to all samples
@@ -559,34 +607,25 @@ public final class read_demultiplex_stats
             { // here it additionally should be checked, if calling object is included ...
                 Percentage_RawClusterCount_AllRawClusterCounts = Double.NaN;
                 String errormessage =
-                        "INPUT ARGUMENT statisticslist MUST BE LIST OF Statistics OBJECTS INCLUDING THE CALLING OBJECT IN METHOD adaptStatisticsWithRespectToAllSamples!";
-                // System.out.println(errormessage);
+                        "INPUT ARGUMENT statisticslist MUST BE LIST OF Statistics OBJECTS INCLUDING THE CALLING OBJECT" +
+                                " IN METHOD adaptStatisticsWithRespectToAllSamples!";
                 throw new IllegalArgumentException(errormessage); // Exception reasonable since otherwise wrong results.
             } else
             {
-                double sum_allrawclustercounts = 0;
-                for (Statistics s : statisticslist)
-                    sum_allrawclustercounts += s.Sum_RawClusterCount;
-                Percentage_RawClusterCount_AllRawClusterCounts = calculate_Percentage(Sum_RawClusterCount, sum_allrawclustercounts);
+                for (Integer key : groupedList.keySet()) {
+                    double sumAllRawClusterCounts = 0;
+                    ArrayList<Statistics> groupList = groupedList.get(key);
+                    for (Statistics element : groupList) {
+                        sumAllRawClusterCounts += element.Sum_RawClusterCount;
+                    }
+                    for (Statistics element : groupList) {
+                        element.Percentage_RawClusterCount_AllRawClusterCounts =
+                                calculate_Percentage(element.Sum_RawClusterCount, sumAllRawClusterCounts);
+                    }
+                }
             }
         }
 
-        public double calculate_MegaUnit(double x)
-        {
-            double z;
-            if (x == Double.POSITIVE_INFINITY || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))
-            {
-                z = Double.NaN;
-                String errormessage =
-                        "INPUT ARGUMENT WAS UNREASONABLE IN METHOD calculate_MegaUnit!  x = " + x + "  (Values were in Sample " + Sample + ")";
-                // System.out.println(errormessage);
-                // throw new IllegalArgumentException(errormessage);
-            } else
-            {
-                z = x / 1000000;
-            }
-            return z;
-        }
 
         public double calculate_Percentage(double x, double y)
         {
@@ -594,11 +633,6 @@ public final class read_demultiplex_stats
             if (z == Double.POSITIVE_INFINITY || z == Double.NEGATIVE_INFINITY || Double.isNaN(z))
             {
                 z = Double.NaN;
-                String errormessage =
-                        "INPUT ARGUMENT WAS UNREASONABLE IN METHOD calculate_Percentage!  x = " + x + ",  y = " + y + "  (Values were in Sample "
-                                + Sample + ")";
-                // System.out.println(errormessage);
-                // throw new IllegalArgumentException(errormessage);
             } else
             {
                 z = 100 * z;
@@ -612,47 +646,23 @@ public final class read_demultiplex_stats
             if (z == Double.POSITIVE_INFINITY || z == Double.NEGATIVE_INFINITY || Double.isNaN(z))
             {
                 z = Double.NaN;
-                String errormessage =
-                        "INPUT ARGUMENT WAS UNREASONABLE IN METHOD calculate_Fraction!  x = " + x + ",  y = " + y + "  (Values were in Sample "
-                                + Sample + ")";
-                // System.out.println(errormessage);
-                // throw new IllegalArgumentException(errormessage);
-            }
-            return z;
-        }
-
-        public double roundspecific(double x, int places)
-        {
-            double z;
-            if (places < 0 || places > 13 || x == Double.POSITIVE_INFINITY || x == Double.NEGATIVE_INFINITY || Double.isNaN(x))
-            {
-                z = Double.NaN;
-                String errormessage =
-                        "INPUT ARGUMENT WAS UNREASONABLE IN METHOD roundspecific!  x = " + x + ",  places = " + places + "  (Values were in Sample "
-                                + Sample + ")";
-                // System.out.println(errormessage);
-                // throw new IllegalArgumentException(errormessage);
-            } else
-            {
-                double factor = Math.pow(10, places);
-                z = Math.round(x * factor);
-                z = z / factor;
             }
             return z;
         }
-
     }
 
-    public class LaneStatistics
+    public static class LaneStatistics
     {
         /*
          * Total Lane Statistics
          */
         public ArrayList<Statistics> statisticsList;
 
+        public Integer Lane = 0;
+
         public double Sum_RawClusterCount = 0.0;
 
-        public double Sum_PfClusterCount = 0.0;
+        public Integer Sum_PfClusterCount = 0;
 
         public double Sum_RawYield = 0.0;
 
@@ -683,18 +693,12 @@ public final class read_demultiplex_stats
             this.statisticsList = statisticsList;
         }
 
-        public void calculateOverallStats()
+        public void calculateOverallStats(Integer key)
         {
-
             int sampleNumber = statisticsList.size();
-
-            for (Statistics s : statisticsList)
-            {
-                if (!s.Barcode.equals("unknown"))
-                {
-                    System.out.println("BARCODE " + s.Barcode);
+            for (Statistics s : statisticsList) {
+                if (!s.Barcode.equals("") || s.Barcode.equals("unknown")) {
                     this.Clusters_PfWithoutNoindex += s.Sum_PfClusterCount;
-                    System.out.println(s.Sum_PfClusterCount);
                 }
 
                 this.Sum_RawClusterCount += s.Sum_RawClusterCount;
@@ -706,10 +710,14 @@ public final class read_demultiplex_stats
                 this.Sum_RawQualityScoreSum += s.Sum_RawQualityScoreSum;
                 this.Sum_PfQualityScoreSum += s.Sum_PfQualityScoreSum;
                 this.Percentage_PfYield_RawYield += s.Percentage_PfYield_RawYield;
-                this.Percentage_PfYieldQ30_PfYield += s.Percentage_PfYieldQ30_PfYield;
+                if (!Double.isNaN(s.Percentage_PfYieldQ30_PfYield)) {
+                    this.Percentage_PfYieldQ30_PfYield += s.Percentage_PfYieldQ30_PfYield;
+                }
                 this.Percentage_PfClusterCount_RawClusterCount += s.Percentage_PfClusterCount_RawClusterCount;
                 this.Fraction_PfQualityScoreSum_PfYield += s.Fraction_PfQualityScoreSum_PfYield;
             }
+
+            this.Lane = key;
             this.Sum_RawQualityScoreSum = this.Sum_RawQualityScoreSum / sampleNumber;
             this.Sum_PfQualityScoreSum = this.Sum_PfQualityScoreSum / sampleNumber;
             this.Percentage_PfYield_RawYield = this.Percentage_PfYield_RawYield / sampleNumber;
@@ -720,8 +728,9 @@ public final class read_demultiplex_stats
 
         public String toString()
         {
-            return "Sum_RawClusterCount " + this.Sum_RawClusterCount + " Sum_PfClusterCount" + this.Sum_PfClusterCount +
-                    " Percentage_PfYieldQ30_PfYield " + this.Percentage_PfYieldQ30_PfYield;
+            return "Lane " + this.Lane + " Sum_RawClusterCount " + this.Sum_RawClusterCount + " Sum_PfClusterCount " + this.Sum_PfClusterCount +
+                    " Percentage_PfYieldQ30_PfYield " + this.Percentage_PfYieldQ30_PfYield +
+                    " Percentage_PfClusterCount_RawClusterCount " + this.Percentage_PfClusterCount_RawClusterCount;
         }
     }
 }
\ No newline at end of file
-- 
GitLab