From 2ffc7f547655e65697de34d1e6b71542e994cd51 Mon Sep 17 00:00:00 2001
From: jakubs <jakubs>
Date: Wed, 12 Dec 2012 12:18:46 +0000
Subject: [PATCH] SP-425 CCS-24 read cellomics metadata from mdb file

SVN: 27918
---
 screening/.classpath                          |   1 +
 .../cellomics-dropbox/cellomics-dropbox.py    |  24 +-
 .../shared/CellomicsMDBMetadataReader.java    | 323 ++++++++++++++++++
 3 files changed, 341 insertions(+), 7 deletions(-)
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/dss/shared/CellomicsMDBMetadataReader.java

diff --git a/screening/.classpath b/screening/.classpath
index 44da96f6b73..5f4716e68dc 100644
--- a/screening/.classpath
+++ b/screening/.classpath
@@ -75,5 +75,6 @@
 	<classpathentry kind="lib" path="/libraries/cisd-jhdf5/hdf5-macosx-intel.jar"/>
 	<classpathentry kind="lib" path="/libraries/cisd-jhdf5/hdf5-windows-intel.jar"/>
 	<classpathentry kind="lib" path="/libraries/commons-io/commons-io.jar" sourcepath="/libraries/commons-io/src.zip"/>
+	<classpathentry kind="lib" path="/libraries/jackcess/jackcess.jar"/>
 	<classpathentry kind="output" path="targets/www/WEB-INF/classes"/>
 </classpath>
diff --git a/screening/source/core-plugins/cellomics/1/dss/drop-boxes/cellomics-dropbox/cellomics-dropbox.py b/screening/source/core-plugins/cellomics/1/dss/drop-boxes/cellomics-dropbox/cellomics-dropbox.py
index 54d42dccb82..50c1c45901a 100644
--- a/screening/source/core-plugins/cellomics/1/dss/drop-boxes/cellomics-dropbox/cellomics-dropbox.py
+++ b/screening/source/core-plugins/cellomics/1/dss/drop-boxes/cellomics-dropbox/cellomics-dropbox.py
@@ -1,7 +1,9 @@
 import os
+import glob
 from ch.systemsx.cisd.openbis.dss.etl.dto.api.v1 import SimpleImageDataConfig
 from ch.systemsx.cisd.openbis.dss.etl.dto.api.v1 import ImageMetadata
 from ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto import Geometry
+from ch.systemsx.cisd.openbis.dss.shared import CellomicsMDBMetadataReader
 
 SPACE_CODE = "TEST"
 PROJECT_CODE = "TEST-PROJECT"
@@ -58,12 +60,12 @@ class MyImageDataSetConfig(SimpleImageDataConfig):
      
         basename = os.path.splitext(imagePath)[0]        
         value = basename.split("_")[2]
-	plate = basename.split("_")[1]
-	well = value[0:3]
-	tile = value[4:6]
-	tile = int(tile) + 1
-	channelCode = value[6:8]     
-         
+        plate = basename.split("_")[1]
+        well = value[0:3]
+        tile = value[4:6]
+        tile = int(tile) + 1
+        channelCode = value[6:8]     
+        
         image_tokens = ImageMetadata()
         image_tokens.well = well
         try:
@@ -76,8 +78,16 @@ class MyImageDataSetConfig(SimpleImageDataConfig):
     
     def getTileGeometry(self, imageTokens, maxTileNumber):
         return Geometry.createFromRowColDimensions((maxTileNumber - 1) / 3 + 1, 3)    
- 
+
+def extractMetadataFromMDBFile(incoming):
+    mdbFiles = glob.glob("%s/*.mdb" % incoming.getAbsoluteFile())
+    
+    if (len(mdbFiles) > 0):
+        mdbReader = CellomicsMDBMetadataReader(mdbFiles[0])
+        mdbReader.writeAllMetadata(incoming)
+
 if incoming.isDirectory():
+    extractMetadataFromMDBFile(incoming)
     imageDataset = MyImageDataSetConfig()
     imageDataset.setRawImageDatasetType()
     imageDataset.setGenerateThumbnails(True)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/shared/CellomicsMDBMetadataReader.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/shared/CellomicsMDBMetadataReader.java
new file mode 100644
index 00000000000..1ec8a861ddb
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/shared/CellomicsMDBMetadataReader.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.shared;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.csvreader.CsvWriter;
+import com.healthmarketscience.jackcess.Database;
+import com.healthmarketscience.jackcess.Table;
+
+/**
+ * @author Jakub Straszewski
+ */
+public class CellomicsMDBMetadataReader
+{
+    private final Database database;
+
+    private HashMap<String, FeatureDefinition> featureTypesDescription;
+
+    public CellomicsMDBMetadataReader(String mdbPath) throws IOException
+    {
+        database = Database.open(new File(mdbPath));
+        initializeFeatureDescriptions();
+    }
+
+    public void writeAllMetadata(String dir) throws IOException
+    {
+        writeAllMetadata(new File(dir));
+    }
+
+    public void writeAllMetadata(File dir) throws IOException
+    {
+        writeEntities("asnPlate", new File(dir, "Plate.tsv"));
+        writeFeatures("asnPlateFeature", "PlateID", new File(dir, "PlateFeature.tsv"));
+        writeEntities("asnWell", new File(dir, "Well.tsv"));
+        writeFeatures("asnWellFeature", "WellID", new File(dir, "WellFeature.tsv"));
+        writeEntities("WField", new File(dir, "Field.tsv"));
+        writeFeatures("WFieldFeature", "WFieldID", new File(dir, "FieldFeature.tsv"));
+        writeEntities("Cell", new File(dir, "Cell.tsv"));
+        writeFeatures("CellFeature", "CellID", new File(dir, "CellFeature.tsv"));
+        writeFeatureDefinitions(new File(dir, "FeatureDefinitions.tsv"));
+    }
+
+    private class CellomicsWriter
+    {
+        int indexesCount = 0;
+
+        final HashMap<String, Integer> indexes = new HashMap<String, Integer>();
+
+        final CsvWriter csvWriter;
+
+        final Writer outputStream;
+
+        public CellomicsWriter(File f) throws IOException
+        {
+            this.outputStream = new FileWriter(f);
+            csvWriter = new CsvWriter(outputStream, '\t');
+        }
+
+        void addIndexedField(String fieldName)
+        {
+            if (!indexes.containsKey(fieldName))
+            {
+                indexes.put(fieldName, indexesCount++);
+            }
+        }
+
+        void writeHeaders() throws IOException
+        {
+            int n = indexes.size();
+            String[] headers = new String[n];
+            for (Map.Entry<String, Integer> entry : indexes.entrySet())
+            {
+                headers[entry.getValue()] = entry.getKey();
+            }
+            csvWriter.writeRecord(headers);
+        }
+
+        void writeEntity(Entity entity) throws IOException
+        {
+            int n = indexes.size();
+            String[] row = new String[n];
+            for (Map.Entry<String, String> entry : entity.fields)
+            {
+                int index = indexes.get(entry.getKey());
+                row[index] = entry.getValue();
+            }
+            csvWriter.writeRecord(row);
+        }
+
+        void writeFeature(Feature feature) throws IOException
+        {
+            String[] row = new String[]
+                { feature.entityId, feature.getFeatureDescription(), feature.value.toString() };
+            csvWriter.writeRecord(row);
+        }
+
+        public void writeFeatureDefinition(FeatureDefinition fd) throws IOException
+        {
+            String[] row = new String[]
+                { fd.description, fd.notes };
+            csvWriter.writeRecord(row);
+        }
+
+        void close() throws IOException
+        {
+            outputStream.close();
+        }
+
+    }
+
+    private void initializeFeatureDescriptions() throws IOException
+    {
+        featureTypesDescription = new HashMap<String, FeatureDefinition>();
+
+        Table featureTypes = database.getTable("asnFeatureType");
+        for (Map<String, Object> row : featureTypes)
+        {
+            String id = getIDValue(row, "ID");
+            featureTypesDescription.put(id, new FeatureDefinition(row));
+        }
+    }
+
+    void writeEntities(String entityType, File f) throws IOException
+    {
+        CellomicsWriter cw = null;
+
+        try
+        {
+            cw = new CellomicsWriter(f);
+
+            Table entityTable = database.getTable(entityType);
+
+            boolean firstRow = true;
+
+            for (Map<String, Object> row : entityTable)
+            {
+                if (firstRow)
+                {
+                    for (String key : row.keySet())
+                    {
+                        cw.addIndexedField(key);
+                    }
+                    cw.writeHeaders();
+                    firstRow = false;
+                }
+                Entity entity = new Entity(row);
+                cw.writeEntity(entity);
+            }
+        } finally
+        {
+            try
+            {
+                if (cw != null)
+                {
+                    cw.close();
+                }
+            } catch (IOException ioe)
+            {
+                // ignore
+            }
+        }
+    }
+
+    void writeFeatures(String featureType, String entityForeignKey, File file) throws IOException
+    {
+        CellomicsWriter cw = null;
+        try
+        {
+            cw = new CellomicsWriter(file);
+
+            Table features = database.getTable(featureType);
+
+            cw.addIndexedField(entityForeignKey);
+            cw.addIndexedField("Feature");
+            cw.addIndexedField("Value");
+
+            cw.writeHeaders();
+
+            for (Map<String, Object> row : features)
+            {
+                Feature f = new Feature(row, entityForeignKey);
+                cw.writeFeature(f);
+            }
+        } finally
+        {
+            try
+            {
+                if (cw != null)
+                {
+                    cw.close();
+                }
+            } catch (IOException ioe)
+            {
+                // ignore
+            }
+        }
+    }
+
+    void writeFeatureDefinitions(File file) throws IOException
+    {
+        CellomicsWriter cw = null;
+        try
+        {
+            cw = new CellomicsWriter(file);
+
+            cw.addIndexedField("Definition");
+            cw.addIndexedField("Note");
+
+            cw.writeHeaders();
+
+            for (FeatureDefinition fd : featureTypesDescription.values())
+            {
+                cw.writeFeatureDefinition(fd);
+            }
+        } finally
+        {
+            try
+            {
+                if (cw != null)
+                {
+                    cw.close();
+                }
+            } catch (IOException ioe)
+            {
+                // ignore
+            }
+        }
+    }
+
+    private class FeatureDefinition
+    {
+        private String description;
+
+        private String notes;
+
+        public FeatureDefinition(Map<String, Object> row)
+        {
+            this.description = row.get("Description").toString();
+            this.notes = row.get("Notes").toString();
+        }
+
+    }
+
+    private class Feature
+    {
+        private final Double value;
+
+        private final String entityId;
+
+        private final String featureTypeId;
+
+        public Feature(Map<String, Object> row, String entityForeignKey)
+        {
+            featureTypeId = getIDValue(row, "TypeID");
+            entityId = getIDValue(row, entityForeignKey);
+            value = getFeatureValue(row);
+        }
+
+        String getFeatureDescription()
+        {
+            return featureTypesDescription.get(featureTypeId).description;
+        }
+    }
+
+    private static class Entity
+    {
+        private final String id;
+
+        private final List<Map.Entry<String, String>> fields =
+                new LinkedList<Map.Entry<String, String>>();
+
+        Entity(Map<String, Object> row)
+        {
+            for (Map.Entry<String, Object> o : row.entrySet())
+            {
+                put(o.getKey(), o.getValue() == null ? "" : o.getValue().toString());
+            }
+            id = getIDValue(row, "ID");
+        }
+
+        /**
+         * Add feature with the given key and value
+         */
+        void put(String key, String value)
+        {
+            fields.add(new AbstractMap.SimpleEntry<String, String>(key, value));
+        }
+
+    }
+
+    private static String getIDValue(Map<String, Object> row, String idField)
+    {
+        return row.get(idField).toString();
+    }
+
+    private static Double getFeatureValue(Map<String, Object> feature)
+    {
+        return (Double) feature.get("valdbl");
+    }
+}
-- 
GitLab