From af4c2c93a775a6a8a03fc06bc7c97c5ebc397009 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Tue, 8 Jun 2010 07:05:10 +0000
Subject: [PATCH] SE-256 MZ peaks now stored as text in metabol database

SVN: 16313
---
 .../db/MetabolDatabaseVersionHolder.java      |   2 +-
 .../systemsx/cisd/yeastx/mzxml/IMzXmlDAO.java |  15 +-
 .../cisd/yeastx/mzxml/MzXml2Database.java     |  44 +--
 .../cisd/yeastx/mzxml/dto/MzScanDTO.java      |  47 ++-
 .../source/sql/postgresql/005/schema-005.sql  | 340 ++++++++++++++++++
 .../migration/migration-004-005.sql           |   3 +
 .../cisd/yeastx/mzxml/MzXMLParserTest.java    |  18 +-
 .../cisd/yeastx/mzxml/MzXml2DatabaseTest.java |  34 --
 8 files changed, 405 insertions(+), 98 deletions(-)
 create mode 100644 rtd_yeastx/source/sql/postgresql/005/schema-005.sql
 create mode 100644 rtd_yeastx/source/sql/postgresql/migration/migration-004-005.sql

diff --git a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/db/MetabolDatabaseVersionHolder.java b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/db/MetabolDatabaseVersionHolder.java
index 6e4c4fb953e..d24e4ce2c28 100644
--- a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/db/MetabolDatabaseVersionHolder.java
+++ b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/db/MetabolDatabaseVersionHolder.java
@@ -26,7 +26,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.IDatabaseVersionHolder;
 public class MetabolDatabaseVersionHolder implements IDatabaseVersionHolder
 {
     /** Current version of the database. */
-    static final String DATABASE_VERSION = "004";
+    static final String DATABASE_VERSION = "005";
 
     public String getDatabaseVersion()
     {
diff --git a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/IMzXmlDAO.java b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/IMzXmlDAO.java
index ab62445fa22..0916c920ffc 100644
--- a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/IMzXmlDAO.java
+++ b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/IMzXmlDAO.java
@@ -40,23 +40,18 @@ public interface IMzXmlDAO extends IDMGenericDAO
             + "    returning ID")
     public long addRun(DMDataSetDTO dataSet, MzInstrumentDTO instrument);
 
-    @Select(sql = "insert into MZ_SCANS "
+    @Update(sql = "insert into MZ_SCANS "
             + "           ( MZ_MS_RUN_ID, NUMBER, LEVEL, PEAKS_COUNT, POLARITY, "
             + "             SCAN_TYPE, COLLISION_ENERGY, LOW_MZ, HIGH_MZ,       "
-            + "             RETENTION_TIME,                                     "
+            + "             MZ_PEAK_POSITIONS, MZ_PEAK_INTENSITIES, RETENTION_TIME,        "
             + "             PRECURSOR1_MZ, PRECURSOR1_INTENSITY, PRECURSOR1_CHARGE,        "
             + "             PRECURSOR2_MZ, PRECURSOR2_INTENSITY, PRECURSOR2_CHARGE )       "
             + "    values ( ?{1}, ?{2.number}, ?{2.level}, ?{2.peaksCount}, ?{2.polarity}, "
             + "             ?{2.scanType}, ?{2.collisionEnergy}, ?{2.lowMz}, ?{2.highMz},  "
-            + "             ?{2.retentionTimeInSeconds},                                   "
+            + "             ?{2.peakPositions}, ?{2.peakIntensities}, ?{2.retentionTimeInSeconds}, "
             + "             ?{3.mz}, ?{3.intensity}, ?{3.charge},                          "
-            + "             ?{4.mz}, ?{4.intensity}, ?{4.charge} )                         "
-            + "    returning ID")
-    public long addScan(long runId, MzScanDTO scan, MzPrecursorDTO precursor1,
+            + "             ?{4.mz}, ?{4.intensity}, ?{4.charge} )                         ")
+    public void addScan(long runId, MzScanDTO scan, MzPrecursorDTO precursor1,
             MzPrecursorDTO precursor2);
 
-    @Update(sql = "insert into MZ_PEAKS (MZ_SCAN_ID, MZ, INTENSITY) "
-            + "                  values (?{1}, ?{2}, ?{3})", batchUpdate = true)
-    public void addPeaks(long scanId, Iterable<Float> mzArray, Iterable<Float> intensityArray);
-
 }
diff --git a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2Database.java b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2Database.java
index 9af38d4413e..85ad6cb7558 100644
--- a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2Database.java
+++ b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2Database.java
@@ -18,13 +18,11 @@ package ch.systemsx.cisd.yeastx.mzxml;
 
 import java.io.File;
 import java.sql.SQLException;
-import java.util.Iterator;
 import java.util.List;
 
 import javax.sql.DataSource;
 
 import ch.rinn.restrictions.Private;
-import ch.systemsx.cisd.common.exceptions.NotImplementedException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.yeastx.db.AbstractDatasetLoader;
 import ch.systemsx.cisd.yeastx.db.generic.DMDataSetDTO;
@@ -108,47 +106,7 @@ public class MzXml2Database extends AbstractDatasetLoader<IMzXmlDAO>
                                 scan.getNumber(), precursors.size());
             }
         }
-        long scanId = getDao().addScan(runId, scan, precursor1, precursor2);
-        uploadPeaks(scanId, scan.getPeaks());
+        getDao().addScan(runId, scan, precursor1, precursor2);
     }
 
-    private void uploadPeaks(long scanId, float[] peaks)
-    {
-        Iterable<Float> mzArray = createEverySecondIterator(peaks, 0);
-        Iterable<Float> intensityArray = createEverySecondIterator(peaks, 1);
-        getDao().addPeaks(scanId, mzArray, intensityArray);
-    }
-
-    // iterates on every second element of an array starting from the specified initial index
-    private static Iterable<Float> createEverySecondIterator(final float[] bytes,
-            final int initialIndex)
-    {
-        return new Iterable<Float>()
-            {
-                public Iterator<Float> iterator()
-                {
-                    return new Iterator<Float>()
-                        {
-                            private int nextIx = initialIndex;
-
-                            public boolean hasNext()
-                            {
-                                return nextIx < bytes.length;
-                            }
-
-                            public Float next()
-                            {
-                                int ix = nextIx;
-                                nextIx += 2;
-                                return bytes[ix];
-                            }
-
-                            public void remove()
-                            {
-                                throw new NotImplementedException();
-                            }
-                        };
-                }
-            };
-    }
 }
diff --git a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/dto/MzScanDTO.java b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/dto/MzScanDTO.java
index 10102f8399f..e3e61535491 100644
--- a/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/dto/MzScanDTO.java
+++ b/rtd_yeastx/source/java/ch/systemsx/cisd/yeastx/mzxml/dto/MzScanDTO.java
@@ -33,6 +33,10 @@ public class MzScanDTO
     private int level;
 
     private int peaksCount;
+    
+    private String peakPositions;
+    
+    private String peakIntensities;
 
     private String polarity;
 
@@ -178,9 +182,46 @@ public class MzScanDTO
         return XmlUtils.tryAsSeconds(retentionTime);
     }
 
-    /** the array has mz on even positions and intensities on odd positions */
-    public float[] getPeaks()
+    public final String getPeakPositions()
     {
-        return XmlUtils.asFloats(peaks.getPeaks());
+        initPeaks();
+        return peakPositions;
+    }
+
+    public final String getPeakIntensities()
+    {
+        initPeaks();
+        return peakIntensities;
+    }
+    
+    private void initPeaks()
+    {
+        if (peakPositions == null)
+        {
+            float[] floats = XmlUtils.asFloats(peaks.getPeaks());
+            StringBuilder positions = new StringBuilder();
+            StringBuilder intensities = new StringBuilder();
+            for (int i = 0; i < floats.length; i++)
+            {
+                if (i % 2 == 0)
+                {
+                    addTo(positions, floats[i]);
+                } else
+                {
+                    addTo(intensities, floats[i]);
+                }
+            }
+            peakPositions = positions.toString();
+            peakIntensities = intensities.toString();
+        }
+    }
+    
+    private void addTo(StringBuilder builder, float value)
+    {
+        if (builder.length() > 0)
+        {
+            builder.append(", ");
+        }
+        builder.append(value);
     }
 }
diff --git a/rtd_yeastx/source/sql/postgresql/005/schema-005.sql b/rtd_yeastx/source/sql/postgresql/005/schema-005.sql
new file mode 100644
index 00000000000..c4cc7a4293f
--- /dev/null
+++ b/rtd_yeastx/source/sql/postgresql/005/schema-005.sql
@@ -0,0 +1,340 @@
+-----------------------------------
+-- Version 004
+-----------------------------------
+
+-- Create domain types section -------------------------------------------------
+
+CREATE DOMAIN TECH_ID AS BIGINT;
+
+CREATE DOMAIN CODE AS VARCHAR(40);
+
+CREATE DOMAIN FILE_NAME as VARCHAR(255);
+
+CREATE DOMAIN FILE_PATH as VARCHAR(1000);
+
+CREATE DOMAIN SHORT_LABEL as VARCHAR(20); 
+
+CREATE DOMAIN LONG_LABEL as VARCHAR(100); 
+
+CREATE DOMAIN CHAR as VARCHAR(1);
+
+CREATE DOMAIN ms_quantification_software_kind AS character varying(40)
+	CONSTRAINT ms_quantification_software_kind_check CHECK (((VALUE)::text = 
+		ANY ((ARRAY['msSoft'::character varying, 'Xcalibur'::character varying, 
+								'Analyst'::character varying, 'MassHunter'::character varying])::text[])));
+
+
+-- Create tables section -------------------------------------------------
+
+-- Table EXPERIMENTS
+
+CREATE TABLE EXPERIMENTS (
+  ID BIGSERIAL NOT NULL,
+  PERM_ID CODE NOT NULL,
+  NAME LONG_LABEL NOT NULL,
+  PRIMARY KEY (ID),
+  UNIQUE (PERM_ID)
+);
+
+-- Table SAMPLES
+
+CREATE TABLE SAMPLES (
+  ID BIGSERIAL NOT NULL,
+  PERM_ID CODE NOT NULL,
+  NAME LONG_LABEL NOT NULL,
+  EXPE_ID TECH_ID NOT NULL,
+  PRIMARY KEY (ID),
+  UNIQUE (PERM_ID),
+  CONSTRAINT FK_SAMPLE_1 FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- Table DATA_SETS
+
+CREATE TABLE DATA_SETS (
+  ID BIGSERIAL NOT NULL,
+  PERM_ID CODE NOT NULL,  
+  EXPE_ID TECH_ID NOT NULL,
+  SAMP_ID TECH_ID,
+  PRIMARY KEY (ID),
+  UNIQUE (PERM_ID),
+  CONSTRAINT FK_DATA_SET_1 FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_DATA_SET_2 FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- Table EIC_MS_RUNS
+
+CREATE TABLE EIC_MS_RUNS (
+  ID BIGSERIAL NOT NULL,
+  EXPE_ID TECH_ID NOT NULL,
+  SAMP_ID TECH_ID,
+  DS_ID TECH_ID NOT NULL,
+  RAW_DATA_FILE_NAME FILE_NAME NOT NULL,
+  RAW_DATA_FILE_PATH FILE_PATH DEFAULT NULL,
+  ACQUISITION_DATE TIMESTAMP DEFAULT NULL,
+  INSTRUMENT_TYPE SHORT_LABEL DEFAULT NULL,
+  INSTRUMENT_MANUFACTURER LONG_LABEL DEFAULT NULL,
+  INSTRUMENT_MODEL LONG_LABEL DEFAULT NULL,
+  METHOD_IONISATION SHORT_LABEL DEFAULT NULL,
+  METHOD_SEPARATION LONG_LABEL DEFAULT NULL,
+  OPERATOR SHORT_LABEL DEFAULT NULL,
+  MS_RUN_ID BIGINT DEFAULT NULL,
+  SET_ID TECH_ID DEFAULT NULL,
+  START_TIME REAL NOT NULL,
+  END_TIME REAL NOT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_EIC_MS_RUN_1 FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_EIC_MS_RUN_2 FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_EIC_MS_RUN_3 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX EIC_MS_RUNS_FK_DS_ID_IDX ON EIC_MS_RUNS(DS_ID);
+CREATE INDEX EIC_MS_RUNS_FK_SAMP_ID_IDX ON EIC_MS_RUNS(SAMP_ID);
+CREATE INDEX EIC_MS_RUNS_FK_EXPE_ID_IDX ON EIC_MS_RUNS(EXPE_ID);
+
+-- Table EIC_CHROMATOGRAMS
+
+CREATE TABLE EIC_CHROMATOGRAMS (
+  ID BIGSERIAL NOT NULL,
+  EIC_MS_RUN_ID TECH_ID NOT NULL,
+  Q1_MZ REAL NOT NULL,
+  Q3_LOW_MZ REAL NOT NULL,
+  Q3_HIGH_MZ REAL NOT NULL,
+  LABEL LONG_LABEL DEFAULT NULL,
+  POLARITY CHAR DEFAULT NULL,
+  RUN_TIMES TEXT NOT NULL,
+  INTENSITIES TEXT NOT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_EIC_CHROMATOGRAM_1 FOREIGN KEY (EIC_MS_RUN_ID) REFERENCES EIC_MS_RUNS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX EIC_CHROMATOGRAM_FK_IDX ON EIC_CHROMATOGRAMS(EIC_MS_RUN_ID);
+
+-- Table FIA_MS_RUNS
+
+CREATE TABLE FIA_MS_RUNS (
+  ID BIGSERIAL NOT NULL,
+  EXPE_ID TECH_ID NOT NULL,
+  SAMP_ID TECH_ID,
+  DS_ID TECH_ID NOT NULL,
+  RAW_DATA_FILE_NAME FILE_NAME NOT NULL,
+  RAW_DATA_FILE_PATH FILE_PATH DEFAULT NULL,
+  ACQUISITION_DATE TIMESTAMP DEFAULT NULL,
+  INSTRUMENT_TYPE SHORT_LABEL DEFAULT NULL,
+  INSTRUMENT_MANUFACTURER LONG_LABEL DEFAULT NULL,
+  INSTRUMENT_MODEL LONG_LABEL DEFAULT NULL,
+  METHOD_IONISATION SHORT_LABEL DEFAULT NULL,
+  METHOD_SEPARATION LONG_LABEL DEFAULT NULL,
+  POLARITY VARCHAR(1) DEFAULT NULL,
+  LOW_MZ REAL NOT NULL,
+  HIGH_MZ REAL NOT NULL,
+  INTERNAL_STANDARD REAL NOT NULL,
+  -- Is this a good name?
+  OD REAL NOT NULL,
+  OPERATOR SHORT_LABEL DEFAULT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_FIA_MS_RUN_1 FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_EIA_MS_RUN_2 FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_EIA_MS_RUN_3 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX FIA_MS_RUNS_FK_DS_ID_IDX ON FIA_MS_RUNS(DS_ID);
+CREATE INDEX FIA_MS_RUNS_FK_SAMP_ID_IDX ON FIA_MS_RUNS(SAMP_ID);
+CREATE INDEX FIA_MS_RUNS_FK_EXPE_ID_IDX ON FIA_MS_RUNS(EXPE_ID);
+
+-- Table FIA_PROFILES
+
+CREATE TABLE FIA_PROFILES (
+  ID BIGSERIAL NOT NULL,
+  FIA_MS_RUN_ID TECH_ID NOT NULL,
+  LOW_MZ REAL NOT NULL,
+  HIGH_MZ REAL NOT NULL,
+  MZ TEXT NOT NULL,
+  INTENSITIES TEXT NOT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_FIA_PROFILE_1 FOREIGN KEY (FIA_MS_RUN_ID) REFERENCES FIA_MS_RUNS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX FIA_PROFILE_I_ID on FIA_PROFILES(FIA_MS_RUN_ID);
+CREATE INDEX FIA_PROFILE_I_ID_MZ on FIA_PROFILES(FIA_MS_RUN_ID, LOW_MZ, HIGH_MZ);
+
+-- Table FIA_CENTROIDS
+
+CREATE TABLE FIA_CENTROIDS (
+  ID BIGSERIAL NOT NULL,
+  FIA_MS_RUN_ID TECH_ID NOT NULL,
+  MZ REAL NOT NULL,
+  INTENSITY REAL NOT NULL,
+  CORRELATION REAL NOT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_FIA_CENTROID_1 FOREIGN KEY (FIA_MS_RUN_ID) REFERENCES FIA_MS_RUNS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX FIA_CENTROID_I_ID ON FIA_CENTROIDS(FIA_MS_RUN_ID);
+CREATE INDEX FIA_CENTROID_I_ID_MZ ON FIA_CENTROIDS(FIA_MS_RUN_ID, MZ);
+ 
+-- Table MS_QUANTIFICATIONS
+
+CREATE TABLE MS_QUANTIFICATIONS (
+  ID BIGSERIAL NOT NULL,
+  DS_ID TECH_ID NOT NULL,
+  EXPE_ID TECH_ID NOT NULL,
+  SOURCE MS_QUANTIFICATION_SOFTWARE_KIND NOT NULL,
+  VALID BOOLEAN NOT NULL,
+  COMMENT TEXT,
+  REGISTRATOR SHORT_LABEL DEFAULT NULL,
+  REGISTRATION_DATE TIMESTAMP DEFAULT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT MS_QUANTIFICATION_1 FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT MS_QUANTIFICATION_3 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX MS_QUANTIFICATION_FK_DS_ID_IDX ON MS_QUANTIFICATIONS(DS_ID);
+CREATE INDEX MS_QUANTIFICATION_FK_EXPE_ID_IDX ON MS_QUANTIFICATIONS(EXPE_ID);
+
+-- Table MS_QUANT_CONCENTRATIONS
+
+CREATE TABLE MS_QUANT_CONCENTRATIONS (
+  ID BIGSERIAL NOT NULL,
+  MS_QUANTIFICATION_ID TECH_ID NOT NULL,
+  PARENT_DS_PERM_ID CODE NOT NULL,
+  AMOUNT REAL NOT NULL,
+  UNIT SHORT_LABEL NOT NULL,
+  VALID BOOLEAN NOT NULL,
+  COMMENT TEXT,
+  RETENTION_TIME REAL NOT NULL,
+  Q1 REAL NOT NULL,
+  Q3 REAL NOT NULL,
+  INTERNAL_STANDARD VARCHAR(30) NOT NULL,
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_QUANT_CONCENTRATIONS_1 FOREIGN KEY (MS_QUANTIFICATION_ID) REFERENCES MS_QUANTIFICATIONS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- Table MS_QUANT_COMPOUND
+
+CREATE TABLE MS_QUANT_COMPOUNDS (
+	ID BIGSERIAL NOT NULL,
+  MS_QUANT_CONCENTRATION_ID TECH_ID NOT NULL,
+  COMPOUND_ID TECH_ID NOT NULL,
+  CONSTRAINT FK_QUANT_COMPOUND_1 FOREIGN KEY (MS_QUANT_CONCENTRATION_ID) REFERENCES MS_QUANT_CONCENTRATIONS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+--------------- mzXML file content
+CREATE TABLE MZ_MS_RUNS (
+  ID BIGSERIAL NOT NULL,
+  EXPE_ID TECH_ID NOT NULL,
+  SAMP_ID TECH_ID,
+  DS_ID TECH_ID NOT NULL,
+
+  INSTRUMENT_TYPE SHORT_LABEL DEFAULT NULL,
+  INSTRUMENT_MANUFACTURER LONG_LABEL DEFAULT NULL,
+  INSTRUMENT_MODEL LONG_LABEL DEFAULT NULL,
+  METHOD_IONISATION SHORT_LABEL DEFAULT NULL,
+
+  PRIMARY KEY (ID), 
+  CONSTRAINT FK_MZ_MS_RUN_1 FOREIGN KEY (EXPE_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_MZ_MS_RUN_2 FOREIGN KEY (SAMP_ID) REFERENCES SAMPLES (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT FK_MZ_MS_RUN_3 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX MZ_MS_RUNS_FK_DS_ID_IDX ON MZ_MS_RUNS(DS_ID);
+CREATE INDEX MZ_MS_RUNS_FK_SAMP_ID_IDX ON MZ_MS_RUNS(SAMP_ID);
+CREATE INDEX MZ_MS_RUNS_FK_EXPE_ID_IDX ON MZ_MS_RUNS(EXPE_ID);
+
+
+CREATE TABLE MZ_SCANS (
+  ID BIGSERIAL NOT NULL,
+	MZ_MS_RUN_ID TECH_ID NOT NULL,
+
+	NUMBER INTEGER NOT NULL CHECK (NUMBER > 0),
+	LEVEL INTEGER NOT NULL CHECK (LEVEL > 0),
+	PEAKS_COUNT INTEGER NOT NULL CHECK (PEAKS_COUNT >= 0),
+	MZ_PEAK_POSITIONS TEXT,
+	MZ_PEAK_INTENSITIES TEXT,
+	POLARITY CHAR (1) CHECK (POLARITY = '+' OR POLARITY = '-'),
+	SCAN_TYPE VARCHAR(10),
+	COLLISION_ENERGY REAL, 
+	LOW_MZ REAL,
+	HIGH_MZ REAL,
+	RETENTION_TIME REAL,
+
+	PRECURSOR1_MZ REAL,
+	PRECURSOR1_INTENSITY REAL,
+	PRECURSOR1_CHARGE INTEGER CHECK (PRECURSOR1_CHARGE > 0),
+
+	PRECURSOR2_MZ REAL,
+	PRECURSOR2_INTENSITY REAL,
+	PRECURSOR2_CHARGE INTEGER CHECK (PRECURSOR2_CHARGE > 0),
+	
+	CHECK (
+			(PRECURSOR1_MZ IS NULL AND PRECURSOR1_INTENSITY IS NULL AND PRECURSOR1_CHARGE IS NULL) OR 
+			(PRECURSOR1_MZ IS NOT NULL AND PRECURSOR1_INTENSITY IS NOT NULL) 
+	),
+	CHECK (
+			(PRECURSOR2_MZ IS NULL AND PRECURSOR2_INTENSITY IS NULL AND PRECURSOR2_CHARGE IS NULL) OR 
+			(PRECURSOR2_MZ IS NOT NULL AND PRECURSOR2_INTENSITY IS NOT NULL) 
+	),
+	PRIMARY KEY (ID),
+	CONSTRAINT FK_MZ_MS_RUN FOREIGN KEY (MZ_MS_RUN_ID) REFERENCES MZ_MS_RUNS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+--------------- END mzXML
+
+-- Table EVENTS
+
+CREATE TABLE EVENTS (
+  LAST_SEEN_DELETION_EVENT_ID TECH_ID NOT NULL
+);
+
+GRANT SELECT ON TABLE EXPERIMENTS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE SAMPLES TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE DATA_SETS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE EIC_MS_RUNS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE EIC_CHROMATOGRAMS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE FIA_MS_RUNS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE FIA_PROFILES TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE FIA_CENTROIDS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE MS_QUANTIFICATIONS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE MS_QUANT_CONCENTRATIONS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE MS_QUANT_COMPOUNDS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE EVENTS TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE EXPERIMENTS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE SAMPLES_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE DATA_SETS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE EIC_MS_RUNS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE EIC_CHROMATOGRAMS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE FIA_MS_RUNS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE FIA_PROFILES_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE FIA_CENTROIDS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE MS_QUANTIFICATIONS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE MS_QUANT_CONCENTRATIONS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE MZ_MS_RUNS TO GROUP metabol_readonly;
+GRANT SELECT ON TABLE MZ_SCANS TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE MZ_MS_RUNS_ID_SEQ TO GROUP metabol_readonly;
+GRANT SELECT ON SEQUENCE MZ_SCANS_ID_SEQ TO GROUP metabol_readonly;
+
+GRANT ALL PRIVILEGES ON TABLE EXPERIMENTS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE SAMPLES TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE DATA_SETS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE EIC_MS_RUNS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE EIC_CHROMATOGRAMS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE FIA_MS_RUNS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE FIA_PROFILES TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE FIA_CENTROIDS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE MS_QUANTIFICATIONS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE MS_QUANT_CONCENTRATIONS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE MS_QUANT_COMPOUNDS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE EVENTS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE EXPERIMENTS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE SAMPLES_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE DATA_SETS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE EIC_MS_RUNS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE EIC_CHROMATOGRAMS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE FIA_MS_RUNS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE FIA_PROFILES_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE FIA_CENTROIDS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE MS_QUANTIFICATIONS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE MS_QUANT_CONCENTRATIONS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE MZ_MS_RUNS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON TABLE MZ_SCANS TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE MZ_MS_RUNS_ID_SEQ TO GROUP metabol_readwrite;
+GRANT ALL PRIVILEGES ON SEQUENCE MZ_SCANS_ID_SEQ TO GROUP metabol_readwrite;
diff --git a/rtd_yeastx/source/sql/postgresql/migration/migration-004-005.sql b/rtd_yeastx/source/sql/postgresql/migration/migration-004-005.sql
new file mode 100644
index 00000000000..f4fc3090b64
--- /dev/null
+++ b/rtd_yeastx/source/sql/postgresql/migration/migration-004-005.sql
@@ -0,0 +1,3 @@
+DROP TABLE MZ_PEAKS;
+ALTER TABLE MZ_SCANS ADD COLUMN MZ_PEAK_POSITIONS TEXT;
+ALTER TABLE MZ_SCANS ADD COLUMN MZ_PEAK_INTENSITIES TEXT;
\ No newline at end of file
diff --git a/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXMLParserTest.java b/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXMLParserTest.java
index 711d37d9d3a..acef5b8e7a5 100644
--- a/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXMLParserTest.java
+++ b/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXMLParserTest.java
@@ -74,12 +74,16 @@ public class MzXMLParserTest extends AssertJUnit
         assertEquals(32333300.0, precursor.getIntensity());
         assertNull(precursor.getCharge());
 
-        float[] peakFloats = scan.getPeaks();
-        assertEquals(scan.getPeaksCount() * 2, peakFloats.length);
-
-        assertEquals(174.6F, peakFloats[0]);
-        assertEquals(16666.666F, peakFloats[1]);
-        assertEquals(695.88F, peakFloats[peakFloats.length - 2]);
-        assertEquals(16666.666F, peakFloats[peakFloats.length - 1]);
+        assertNumbers("174.6", "695.88", scan.getPeaksCount(), scan.getPeakPositions());
+        assertNumbers("16666.666", "16666.666", scan.getPeaksCount(), scan.getPeakIntensities());
+    }
+    
+    private void assertNumbers(String firstNumber, String lastNumber, int count, String numbers)
+    {
+        String[] numberArray = numbers.split(",");
+        assertEquals(firstNumber, numberArray[0].trim());
+        assertEquals(lastNumber, numberArray[numberArray.length - 1].trim());
+        assertEquals(count, numberArray.length);
     }
+    
 }
diff --git a/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2DatabaseTest.java b/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2DatabaseTest.java
index 6b6f24028c9..99aed660af8 100644
--- a/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2DatabaseTest.java
+++ b/rtd_yeastx/sourceTest/java/ch/systemsx/cisd/yeastx/mzxml/MzXml2DatabaseTest.java
@@ -17,12 +17,8 @@
 package ch.systemsx.cisd.yeastx.mzxml;
 
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.List;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.testng.annotations.Test;
@@ -77,36 +73,6 @@ public class MzXml2DatabaseTest
                     will(returnValue(runId));
 
                     exactly(2).of(dao).addScan(runId, scan, precursor, precursor);
-                    long scanId = 333;
-                    will(returnValue(scanId));
-
-                    exactly(2).of(dao).addPeaks(with(scanId), with(createFloatIteratorMatcher(mz)),
-                            with(createFloatIteratorMatcher(intensity)));
-                }
-
-                // checks that iterator has exactly one value
-                private Matcher<Iterable<Float>> createFloatIteratorMatcher(final float value)
-                {
-                    return new BaseMatcher<Iterable<Float>>()
-                        {
-                            public boolean matches(Object item)
-                            {
-                                Iterator<Float> iterator = asIterator(item);
-                                Float number = iterator.next();
-                                return number.equals(value) && iterator.hasNext() == false;
-                            }
-
-                            @SuppressWarnings("unchecked")
-                            private Iterator<Float> asIterator(Object item)
-                            {
-                                return ((Iterable<Float>) item).iterator();
-                            }
-
-                            public void describeTo(Description description)
-                            {
-                                description.appendValue("iterator with one value '" + value + "'");
-                            }
-                        };
                 }
             });
 
-- 
GitLab