diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java
index 31e5069afa5a9f3b680208a3c8a5356040650203..9dc994cc37ad6880ec22344578b3ffa8dca8005b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseHelper.java
@@ -23,6 +23,8 @@ import java.util.Map;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.etl.dataaccess.IImagingQueryDAO;
 import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.Channel;
+import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColor;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgChannelDTO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgContainerDTO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgExperimentDTO;
@@ -92,8 +94,7 @@ public class ImagingDatabaseHelper
      * in the DB.
      */
     public static ExperimentWithChannelsAndContainer getOrCreateExperimentWithChannelsAndContainer(
-            IImagingQueryDAO dao, HCSContainerDatasetInfo info,
-            List<Channel> channels)
+            IImagingQueryDAO dao, HCSContainerDatasetInfo info, List<Channel> channels)
     {
         ImagingDatabaseHelper helper = new ImagingDatabaseHelper(dao);
         synchronized (IImagingQueryDAO.class)
@@ -289,9 +290,16 @@ public class ImagingDatabaseHelper
 
         private Map<String, Long> createChannels(ChannelOwner channelOwner, List<Channel> channels)
         {
+            int colorIndex = 0;
             Map<String, Long> map = new HashMap<String, Long>();
             for (Channel channel : channels)
             {
+                if (channel.tryGetChannelColor() == null)
+                {
+                    ChannelColor channelColor = ChannelColor.createFromIndex(colorIndex);
+                    channel.setChannelColor(channelColor);
+                    colorIndex++;
+                }
                 ImgChannelDTO channelDTO = createChannel(channel, channelOwner);
                 addChannel(map, channelDTO);
             }
@@ -313,8 +321,8 @@ public class ImagingDatabaseHelper
             return nameMap;
         }
 
-        private ImgChannelDTO updateExperimentChannel(Channel channel,
-                long expId, Map<String, ImgChannelDTO> existingChannels)
+        private ImgChannelDTO updateExperimentChannel(Channel channel, long expId,
+                Map<String, ImgChannelDTO> existingChannels)
         {
             ImgChannelDTO channelDTO =
                     makeChannelDTO(channel, ChannelOwner.createExperiment(expId));
@@ -358,8 +366,7 @@ public class ImagingDatabaseHelper
                     channelName, existingChannels.keySet());
         }
 
-        private ImgChannelDTO createChannel(Channel channel,
-                ChannelOwner channelOwner)
+        private ImgChannelDTO createChannel(Channel channel, ChannelOwner channelOwner)
         {
             ImgChannelDTO channelDTO = makeChannelDTO(channel, channelOwner);
             long channelId = dao.addChannel(channelDTO);
@@ -367,12 +374,15 @@ public class ImagingDatabaseHelper
             return channelDTO;
         }
 
-        private static ImgChannelDTO makeChannelDTO(Channel channel,
-                ChannelOwner channelOwner)
+        private static ImgChannelDTO makeChannelDTO(Channel channel, ChannelOwner channelOwner)
         {
+            ChannelColor channelColor = channel.tryGetChannelColor();
+            assert channelColor != null : "channel color should be specified at this point";
+            ImageChannelColor imageChannelColor = ImageChannelColor.valueOf(channelColor.name());
+
             return new ImgChannelDTO(channel.getCode(), channel.tryGetDescription(),
                     channel.tryGetWavelength(), channelOwner.tryGetDatasetId(),
-                    channelOwner.tryGetExperimentId(), channel.getLabel());
+                    channelOwner.tryGetExperimentId(), channel.getLabel(), imageChannelColor);
         }
     }
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseVersionHolder.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseVersionHolder.java
index c3522838478e6a338d98b54773de3e945f99393d..0601f6bdab0774a72b4407b73cb86c9ec58ce84e 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseVersionHolder.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/ImagingDatabaseVersionHolder.java
@@ -28,7 +28,7 @@ public class ImagingDatabaseVersionHolder implements IDatabaseVersionHolder
 
     public String getDatabaseVersion()
     {
-        return "011"; // changed in S105
+        return "012"; // changed in S106
     }
 
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java
index ae5b3d5b9be7175068fe289d9ae31b4c0c8e17e5..7e5fd32086497b5900dca6bab4781b268296c691 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java
@@ -69,8 +69,8 @@ public interface IImagingQueryDAO extends TransactionQuery, IImagingReadonlyQuer
     @Select("insert into EXPERIMENTS (PERM_ID) values (?{1}) returning ID")
     public long addExperiment(String experimentPermId);
 
-    @Select("insert into CHANNELS (LABEL, CODE, DESCRIPTION, WAVELENGTH, DS_ID, EXP_ID) values "
-            + "(?{1.label}, ?{1.code}, ?{1.description}, ?{1.wavelength}, ?{1.datasetId}, ?{1.experimentId}) returning ID")
+    @Select("insert into CHANNELS (LABEL, CODE, DESCRIPTION, WAVELENGTH, DS_ID, EXP_ID, COLOR) values "
+            + "(?{1.label}, ?{1.code}, ?{1.description}, ?{1.wavelength}, ?{1.datasetId}, ?{1.experimentId}, ?{1.dbChannelColor}) returning ID")
     public long addChannel(ImgChannelDTO channel);
 
     @Select("insert into CONTAINERS (PERM_ID, SPOTS_WIDTH, SPOTS_HEIGHT, EXPE_ID) values "
@@ -105,7 +105,7 @@ public interface IImagingQueryDAO extends TransactionQuery, IImagingReadonlyQuer
     // updates
 
     @Update("update CHANNELS "
-            + "set DESCRIPTION = ?{1.description}, WAVELENGTH = ?{1.wavelength} "
+            + "set DESCRIPTION = ?{1.description}, WAVELENGTH = ?{1.wavelength}, COLOR = ?{1.dbChannelColor} "
             + "where ID = ?{1.id}")
     public void updateChannel(ImgChannelDTO channel);
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java
index 845f51b144947cf3754b2426896f42835f9bfb0d..189ff38116c6bfef83c3b2738de970be3f971140 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/Channel.java
@@ -20,13 +20,28 @@ public final class Channel extends AbstractHashable
 
     private Integer wavelength;
 
-    /** Constructs a channel with a specified code and label. */
+    private ChannelColor channelColorOrNull;
+
+    /**
+     * Constructs a channel with a specified code and label. The channel will be presented in a
+     * default color.
+     */
     public Channel(String code, String label)
+    {
+        this(code, label, null);
+    }
+
+    /**
+     * Constructs a channel with a specified code and label. The channel will be presented in a
+     * specified color.
+     */
+    public Channel(String code, String label, ChannelColor channelColorOrNull)
     {
         assert code != null : "code is null";
         assert label != null : "label is null";
         this.label = label;
         this.code = code;
+        this.channelColorOrNull = channelColorOrNull;
     }
 
     public String getCode()
@@ -49,6 +64,16 @@ public final class Channel extends AbstractHashable
         return label;
     }
 
+    /**
+     * @return color for the specified channel which will be used to display merged channels images.
+     *         null only during dataset registration wheb default color should be used, afterwards
+     *         never null.
+     */
+    public ChannelColor tryGetChannelColor()
+    {
+        return channelColorOrNull;
+    }
+
     /** Sets the description of the channel.Optional. */
     public void setDescription(String description)
     {
@@ -60,4 +85,11 @@ public final class Channel extends AbstractHashable
     {
         this.wavelength = wavelength;
     }
+
+    /** Sets the color in which this channel will be displayed. */
+    public void setChannelColor(ChannelColor channelColor)
+    {
+        this.channelColorOrNull = channelColor;
+    }
+
 }
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a10cf74204457afb80fbb0b4cc9d82472cf340e
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ChannelColor.java
@@ -0,0 +1,38 @@
+package ch.systemsx.cisd.openbis.dss.etl.dto.api.v1;
+
+/**
+ * Allowed colors in which channels can be presented.
+ * 
+ * @author Tomasz Pylak
+ */
+public enum ChannelColor
+{
+    BLUE(0), GREEN(1), RED(2), RED_GREEN(3), RED_BLUE(4), GREEN_BLUE(5);
+
+    // If no mapping between channels and colors has been provided then channels get consecutive
+    // colors. This field determines the order in which colors are assigned.
+    // It is important for backward compatibility as well.
+    private final int orderIndex;
+
+    private ChannelColor(int orderIndex)
+    {
+        this.orderIndex = orderIndex;
+    }
+
+    public int getColorOrderIndex()
+    {
+        return orderIndex;
+    }
+
+    public static ChannelColor createFromIndex(int colorIndex)
+    {
+        for (ChannelColor color : values())
+        {
+            if (color.getColorOrderIndex() == colorIndex)
+            {
+                return color;
+            }
+        }
+        throw new IllegalStateException("Invalid color index: " + colorIndex + "!");
+    }
+}
\ No newline at end of file
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java
index 7f92f26718906ca535cb6114d49e7a275f1ced2c..1ff5f95da8eb40b5b74ca83632315190fbb0775b 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java
@@ -76,12 +76,29 @@ abstract public class SimpleImageDataConfig
     }
 
     /**
-     * Creates channel description for a given code. The channel label will be equal to the code.
-     * Can be overridden in subclasses.
+     * <p>
+     * Creates channel description for a given code. Can be overridden in subclasses.
+     * </p>
+     * By default rhe channel label will be equal to the code. Channel color returned by
+     * {@link #getChannelColor(String)} will be used.
      */
     public Channel createChannel(String channelCode)
     {
-        return new Channel(channelCode, channelCode);
+        ChannelColor channelColor = getChannelColor(channelCode);
+        return new Channel(channelCode, channelCode, channelColor);
+    }
+
+    /**
+     * Returns color for the specified channel. It will be used to display merged channels images.
+     * <p>
+     * Can be overridden in subclasses. It is ignored if {@link #createChannel(String)} is
+     * overridden as well.
+     * </p>
+     * By default returns null (the arbitrary color will be set).
+     */
+    public ChannelColor getChannelColor(String channelCode)
+    {
+        return null;
     }
 
     // --- auxiliary structures ----------------------------------------------
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java
index f26648c429a4e0059b8435d5fecfaff4a7b3eb54..425a2d6faabf39648777073099d7ca70c45566d0 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java
@@ -172,7 +172,8 @@ public class SimpleImageDataSetRegistrator
         List<Channel> channels = new ArrayList<Channel>();
         for (String channelCode : channelCodes)
         {
-            channels.add(simpleImageConfig.createChannel(channelCode));
+            Channel channel = simpleImageConfig.createChannel(channelCode);
+            channels.add(channel);
         }
         return channels;
     }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java
index 460320b878eca1ea2c2a859971964bdb785eed8e..1dc3935f1472e1d011fa4d1733a6aa61bccb3a61 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/detailviewers/ChannelChooser.java
@@ -32,6 +32,7 @@ import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.d
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.detailviewers.dto.LogicalImageReference;
 import ch.systemsx.cisd.openbis.plugin.screening.client.web.client.application.utils.GuiUtils;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.DatasetImagesReference;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
 
 /**
@@ -148,12 +149,11 @@ class ChannelChooser
         for (DatasetImagesReference overlayDataset : overlayDatasets)
         {
             ImageDatasetParameters imageParams = overlayDataset.getImageParameters();
-            List<String> channelsCodes = imageParams.getChannelsCodes();
-            List<String> channelsLabels = imageParams.getChannelsLabels();
             for (int i = 0; i < imageParams.getChannelsNumber(); i++)
             {
-                String channelCode = channelsCodes.get(i);
-                String channelLabel = channelsLabels.get(i);
+                ImageChannel channel = imageParams.getChannels().get(i);
+                String channelCode = channel.getCode();
+                String channelLabel = channel.getLabel();
                 LabeledItem<ImageDatasetChannel> item =
                         createLabeledItem(overlayDataset, channelCode, channelLabel);
                 items.add(item);
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java
new file mode 100644
index 0000000000000000000000000000000000000000..e51a89aeb830e3bdc2983812ffe2771bd92471d8
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannel.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2011 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.plugin.screening.shared.basic.dto;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.ISerializable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ServiceVersionHolder;
+
+/**
+ * A channel in which the image has been acquired.
+ * <p>
+ * Each channel has its <code>code</code> which uniquely identifies it in one experiment or dataset.
+ * 
+ * @author Tomasz Pylak
+ */
+public class ImageChannel implements ISerializable
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private String code;
+
+    private String label;
+
+    private String description;
+
+    private Integer wavelength;
+
+    private ImageChannelColor channelColor;
+
+    // GWT only
+    @SuppressWarnings("unused")
+    private ImageChannel()
+    {
+    }
+
+    public ImageChannel(String code, String label, String description, Integer wavelength,
+            ImageChannelColor channelColor)
+    {
+        this.code = code;
+        this.label = label;
+        this.description = description;
+        this.wavelength = wavelength;
+        this.channelColor = channelColor;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public String tryGetDescription()
+    {
+        return description;
+    }
+
+    public Integer tryGetWavelength()
+    {
+        return wavelength;
+    }
+
+    public String getLabel()
+    {
+        return label;
+    }
+
+    /**
+     * @return color for the specified channel which will be used to display merged channels images.
+     */
+    public ImageChannelColor getChannelColor()
+    {
+        return channelColor;
+    }
+
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannelColor.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannelColor.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1fd8c8af465c1c59d06a8af262d42b39dbfb180
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageChannelColor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 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.plugin.screening.shared.basic.dto;
+
+/**
+ * Allowed colors in which channels can be presented.
+ * 
+ * @author Tomasz Pylak
+ */
+public enum ImageChannelColor
+{
+    BLUE, GREEN, RED, RED_GREEN, RED_BLUE, GREEN_BLUE;
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java
index dddc6de6a39aa526799f5399413eb1b2d75dbe8c..78b70ff5e6242f4568b353e30e32862dea2c6655 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/basic/dto/ImageDatasetParameters.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -44,9 +45,7 @@ public class ImageDatasetParameters implements ISerializable
 
     private int tileColsNum;
 
-    private List<String> channelsCodes;
-
-    private List<String> channelsLabels;
+    private List<ImageChannel> channels;
 
     private Map<String/* channel code */, String/* signature */> channelsTransformerFactorySignatures =
             new HashMap<String, String>();
@@ -104,19 +103,29 @@ public class ImageDatasetParameters implements ISerializable
         this.datasetCode = datasetCode;
     }
 
-    public void setChannelsCodes(List<String> channelsCodes)
+    public List<String> getChannelsCodes()
     {
-        this.channelsCodes = channelsCodes;
+        List<String> channelCodes = new ArrayList<String>();
+        for (ImageChannel channel : channels)
+        {
+            channelCodes.add(channel.getCode());
+        }
+        return channelCodes;
     }
 
-    public List<String> getChannelsCodes()
+    public List<String> getChannelsLabels()
     {
-        return channelsCodes;
+        List<String> channelLabels = new ArrayList<String>();
+        for (ImageChannel channel : channels)
+        {
+            channelLabels.add(channel.getLabel());
+        }
+        return channelLabels;
     }
 
     public int getChannelsNumber()
     {
-        return channelsCodes.size();
+        return channels.size();
     }
 
     public boolean isMultidimensional()
@@ -129,14 +138,14 @@ public class ImageDatasetParameters implements ISerializable
         this.isMultidimensional = isMultidimensional;
     }
 
-    public void setChannelsLabels(List<String> channelsLabels)
+    public void setChannels(List<ImageChannel> channels)
     {
-        this.channelsLabels = channelsLabels;
+        this.channels = channels;
     }
 
-    public List<String> getChannelsLabels()
+    public List<ImageChannel> getChannels()
     {
-        return channelsLabels;
+        return channels;
     }
 
     public void addTransformerFactorySignatureFor(String channelCode, String signatureOrNull)
@@ -148,5 +157,4 @@ public class ImageDatasetParameters implements ISerializable
     {
         return channelsTransformerFactorySignatures.get(channelCode);
     }
-
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java
index 72422a5d8f02c05efcecb393d72f2bc1b9550596..a127fd776492d681289777686c9e27e2da04c440 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/HCSDatasetLoader.java
@@ -20,6 +20,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 import ch.systemsx.cisd.common.utilities.MD5ChecksumCalculator;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelStack;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
@@ -160,21 +162,29 @@ public class HCSDatasetLoader implements IImageDatasetLoader
         params.setIsMultidimensional(dataset.getIsMultidimensional());
         params.addTransformerFactorySignatureFor(ScreeningConstants.MERGED_CHANNELS,
                 mergedChannelTransformerFactorySignatureOrNull);
-        List<String> channelsCodes = new ArrayList<String>();
-        List<String> channelsLabels = new ArrayList<String>();
-        for (ImgChannelDTO channel : channels)
+
+        List<ImageChannel> convertedChannels = new ArrayList<ImageChannel>();
+        for (ImgChannelDTO channelDTO : channels)
         {
-            String channelCode = channel.getCode();
-            channelsCodes.add(channelCode);
-            channelsLabels.add(channel.getLabel());
-            params.addTransformerFactorySignatureFor(channelCode,
-                    tryGetSignature(channel.getSerializedImageTransformerFactory()));
+            ImageChannel channel = convert(channelDTO);
+            convertedChannels.add(channel);
+
+            String transformationSignature =
+                    tryGetSignature(channelDTO.getSerializedImageTransformerFactory());
+            params.addTransformerFactorySignatureFor(channelDTO.getCode(), transformationSignature);
         }
-        params.setChannelsCodes(channelsCodes);
-        params.setChannelsLabels(channelsLabels);
+        params.setChannels(convertedChannels);
         return params;
     }
 
+    private static ImageChannel convert(ImgChannelDTO channelDTO)
+    {
+        ImageChannelColor imageChannelColor =
+                ImageChannelColor.valueOf(channelDTO.getDbChannelColor());
+        return new ImageChannel(channelDTO.getCode(), channelDTO.getLabel(),
+                channelDTO.getDescription(), channelDTO.getWavelength(), imageChannelColor);
+    }
+
     private String tryGetSignature(byte[] bytesOrNull)
     {
         if (bytesOrNull == null)
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java
index eaae5838b523ee5536a82afd1125cd0f6834c5a9..3393eabfa401566ef923f43aad9dda78f05dfde8 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgChannelDTO.java
@@ -18,6 +18,8 @@ package ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess;
 
 import net.lemnik.eodsql.ResultColumn;
 
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor;
+
 /**
  * @author Tomasz Pylak
  */
@@ -43,6 +45,10 @@ public class ImgChannelDTO extends AbstractImageTransformerFactoryHolder
     @ResultColumn("EXP_ID")
     private Long experimentIdOrNull;
 
+    /** Value for the {@link ImageChannelColor} enum. Not null. */
+    @ResultColumn("COLOR")
+    private String channelColor;
+
     // GWT only
     @SuppressWarnings("unused")
     private ImgChannelDTO()
@@ -51,7 +57,8 @@ public class ImgChannelDTO extends AbstractImageTransformerFactoryHolder
     }
 
     public ImgChannelDTO(String code, String descriptionOrNull, Integer wavelengthOrNull,
-            Long datasetIdOrNull, Long experimentIdOrNull, String label)
+            Long datasetIdOrNull, Long experimentIdOrNull, String label,
+            ImageChannelColor channelColor)
     {
         assert (datasetIdOrNull == null && experimentIdOrNull != null)
                 || (datasetIdOrNull != null && experimentIdOrNull == null);
@@ -61,6 +68,7 @@ public class ImgChannelDTO extends AbstractImageTransformerFactoryHolder
         this.wavelengthOrNull = wavelengthOrNull;
         this.datasetIdOrNull = datasetIdOrNull;
         this.experimentIdOrNull = experimentIdOrNull;
+        this.channelColor = channelColor.name();
     }
 
     public String getCode()
@@ -124,4 +132,14 @@ public class ImgChannelDTO extends AbstractImageTransformerFactoryHolder
         this.experimentIdOrNull = experimentId;
     }
 
+    /** Can be converted to {@link ImageChannelColor}. */
+    public String getDbChannelColor()
+    {
+        return channelColor;
+    }
+
+    public void setDbChannelColor(String channelColor)
+    {
+        this.channelColor = channelColor;
+    }
 }
diff --git a/screening/source/sql/postgresql/012/data.sql b/screening/source/sql/postgresql/012/data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..f08222c48c2932180be40863f775e14dac5267bc
--- /dev/null
+++ b/screening/source/sql/postgresql/012/data.sql
@@ -0,0 +1,275 @@
+-- Note that these data has to be loaded manually into the openBIS Core database.
+
+-- TODO: this sql should be converted to a generic sql without refering to technical ids. 
+-- Now the ids should be updated if some new records will be added in the generic data.
+
+--
+-- PostgreSQL database dump
+--
+
+SET statement_timeout = 0;
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = off;
+SET check_function_bodies = false;
+SET client_min_messages = warning;
+SET escape_string_warning = off;
+
+SET search_path = public, pg_catalog;
+
+--
+-- Data for Name: controlled_vocabularies; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY controlled_vocabularies (id, code, description, registration_timestamp, pers_id_registerer, is_managed_internally, is_internal_namespace, dbin_id, modification_timestamp, is_chosen_from_list, source_uri) FROM stdin;
+2	PLATE_GEOMETRY	The geometry or dimensions of a plate	2008-06-17 16:38:30.723292+02	1	t	t	1	2009-11-27 16:02:26.451046+01	t	\N
+3	MICROSCOPE	Microscope used in an experiment.	2009-11-29 23:55:18.978884+01	1	f	f	1	2009-12-17 01:50:54.68+01	t	\N
+\.
+
+
+--
+-- Data for Name: controlled_vocabulary_terms; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY controlled_vocabulary_terms (id, code, registration_timestamp, covo_id, pers_id_registerer, label, description, ordinal) FROM stdin;
+3	384_WELLS_16X24	2008-06-17 16:38:30.723292+02	2	1	384 Wells, 16x24	\N	1
+4	96_WELLS_8X12	2008-06-17 16:38:31.101031+02	2	1	96 Wells, 8x12	\N	2
+5	1536_WELLS_32X48	2008-06-17 16:38:31.101031+02	2	1	1536 Wells, 32x48	\N	3
+6	BD_PATHWAY_855	2009-11-29 23:55:18.978884+01	3	1	\N	\N	1
+7	MD_IMAGEXPRESS_MICROLIVE	2009-11-29 23:55:18.978884+01	3	1	\N	\N	2
+8	MD_IMAGEXPRESS_MICRO_2	2009-11-29 23:55:18.978884+01	3	1	\N	\N	3
+\.
+
+
+--
+-- Data for Name: data_set_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY data_set_types (id, code, description, dbin_id, modification_timestamp) FROM stdin;
+3	HCS_IMAGE_ANALYSIS_DATA	Data derived from analysis of HCS images	1	2009-11-27 16:02:26.451046+01
+2	HCS_IMAGE	HCS raw images acquired by microscopes	1	2009-11-27 16:02:26.451046+01
+4	HCS_ANALYSIS_PER_GENE	Image analysis data aggregated per gene.	1	2009-12-16 16:59:50.743029+01
+\.
+
+
+--
+-- Data for Name: material_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY material_types (id, code, description, dbin_id, modification_timestamp) FROM stdin;
+1	VIRUS	Virus	1	2009-11-27 16:02:26.451046+01
+2	CELL_LINE	Cell Line or Cell Culture. The growing of cells under controlled conditions.	1	2009-11-27 16:02:26.451046+01
+3	GENE	Gene	1	2009-11-27 16:02:26.451046+01
+4	SIRNA	siRNA nucleotide	1	2009-11-27 16:02:26.451046+01
+5	CONTROL	Control of a control layout	1	2009-11-27 16:02:26.451046+01
+6	BACTERIUM	Bacterium	1	2009-11-27 16:02:26.451046+01
+7	COMPOUND	Compound	1	2009-11-27 16:02:26.451046+01
+\.
+
+
+--
+-- Data for Name: property_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY property_types (id, code, description, label, daty_id, registration_timestamp, pers_id_registerer, covo_id, is_managed_internally, is_internal_namespace, dbin_id, maty_prop_id) FROM stdin;
+3	NUCLEOTIDE_SEQUENCE	A sequence of nucleotides	Nucleotide Sequence	1	2008-02-28 13:03:03.358532+01	1	\N	f	f	1	\N
+4	REFSEQ	NCBI Reference Sequence code, applicable to sequences of type: DNA, RNA, protein	RefSeq	1	2008-02-28 13:03:03.358532+01	1	\N	f	f	1	\N
+13	MICROSCOPE	 	Microscope	7	2009-11-29 23:57:05.85618+01	1	3	f	f	1	\N
+7	INHIBITOR_OF	Inhibitor Of	Inhibitor Of	8	2009-11-27 16:02:45.060699+01	1	\N	f	f	1	3
+11	SIRNA	siRNA	siRNA	8	2009-11-29 23:56:19.39967+01	1	\N	f	f	1	4
+12	CONTROL	Control	Control	8	2009-11-29 23:56:37.355313+01	1	\N	f	f	1	5
+6	PLATE_GEOMETRY	Plate Geometry	Plate Geometry	7	2008-06-17 16:38:30.723292+02	1	2	t	t	1	\N
+15	NUMBER_OF_CHANNEL	 	Channels	3	2009-12-17 10:56:17.239319+01	1	\N	f	f	1	\N
+16	LIBRARY_ID	Library id	Id from the master plate library	1	2008-02-28 13:03:03.358532+01	1	\N	f	f	1	\N
+\.
+
+
+--
+-- Data for Name: data_set_type_property_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY data_set_type_property_types (id, dsty_id, prty_id, is_mandatory, is_managed_internally, pers_id_registerer, registration_timestamp, section, ordinal) FROM stdin;
+\.
+
+
+--
+-- Data for Name: experiment_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY experiment_types (id, code, description, dbin_id, modification_timestamp) FROM stdin;
+2	COMPOUND_HCS	Compound High Content Screening	1	2009-11-27 16:02:26.451046+01
+1	SIRNA_HCS	Small Interfering RNA High Content Screening	1	2009-11-27 16:02:26.451046+01
+\.
+
+
+--
+-- Data for Name: experiment_type_property_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY experiment_type_property_types (id, exty_id, prty_id, is_mandatory, is_managed_internally, pers_id_registerer, registration_timestamp, section, ordinal) FROM stdin;
+1	1	1	t	t	1	2008-06-17 16:38:49.023295+02	\N	1
+2	2	1	t	t	1	2008-06-17 16:38:49.301922+02	\N	1
+5	1	13	f	f	1	2009-12-17 10:54:01.261178+01	\N	2
+\.
+
+
+--
+-- Data for Name: file_format_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY file_format_types (id, code, description, dbin_id) FROM stdin;
+7	PNG	\N	1
+8	CSV	files with values separated by comma or semicolon	1
+9	JPG	\N	1
+\.
+
+
+--
+-- Data for Name: filters; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY filters (id, dbin_id, name, description, registration_timestamp, pers_id_registerer, modification_timestamp, expression, is_public, grid_id) FROM stdin;
+9	1	Infection index	\N	2009-12-16 21:19:19.012657+01	1	2009-12-16 22:41:56.863+01	float(row.col('colIndex_5')) > float(${threshold})	t	data-set-reporting-gridplate-image-analysis-merger
+8	1	Total number of cells	\N	2009-12-16 21:18:05.161964+01	1	2009-12-16 22:42:31.707+01	int(row.col('colIndex_3')) > int(${threshold})	t	data-set-reporting-gridplate-image-analysis-merger
+7	1	Number of infected cells	\N	2009-12-16 21:17:40.765083+01	1	2009-12-16 22:42:46.052+01	int(row.col('colIndex_4')) > int(${threshold})	t	data-set-reporting-gridplate-image-analysis-merger
+\.
+
+
+--
+-- Data for Name: material_type_property_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY material_type_property_types (id, maty_id, prty_id, is_mandatory, registration_timestamp, pers_id_registerer, is_managed_internally, section, ordinal) FROM stdin;
+10	4	7	t	2009-11-27 16:02:45.060699+01	1	f	\N	4
+9	5	1	f	2008-02-28 13:03:03.358532+01	1	f	\N	1
+8	4	1	f	2008-02-28 13:03:03.358532+01	1	f	\N	3
+6	4	3	t	2008-02-28 13:03:03.358532+01	1	f	\N	1
+12	4	16	f	2008-02-28 13:03:03.358532+01	1	f	\N	1
+5	3	1	f	2008-02-28 13:03:03.358532+01	1	f	\N	2
+3	7	1	t	2008-02-28 13:03:03.358532+01	1	f	\N	1
+2	6	1	t	2008-02-28 13:03:03.358532+01	1	f	\N	1
+1	1	1	t	2008-02-28 13:03:03.358532+01	1	f	\N	1
+\.
+
+
+--
+-- Data for Name: sample_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY sample_types (id, code, description, dbin_id, is_listable, generated_from_depth, part_of_depth, modification_timestamp, is_auto_generated_code, generated_code_prefix) FROM stdin;
+3	PLATE	Cell Plate	1	t	2	0	2009-11-27 16:02:26.451046+01	f	S
+7	SIRNA_WELL	\N	1	f	0	1	2009-11-27 19:42:03.483115+01	f	O
+8	CONTROL_WELL	\N	1	f	0	1	2009-11-27 19:42:25.791288+01	f	C
+9	LIBRARY	\N	1	f	0	0	2009-11-27 19:42:25.791288+01	f	L
+\.
+
+
+--
+-- Data for Name: sample_type_property_types; Type: TABLE DATA; Schema: public; Owner: -
+--
+
+COPY sample_type_property_types (id, saty_id, prty_id, is_mandatory, is_managed_internally, pers_id_registerer, registration_timestamp, is_displayed, section, ordinal) FROM stdin;
+8	7	11	f	f	1	2009-11-29 23:57:38.268212+01	t	\N	1
+9	8	12	f	f	1	2009-11-29 23:57:49.098187+01	t	\N	1
+10	3	6	f	f	1	2009-11-30 01:28:20.972263+01	t	\N	1
+\.
+
+--
+-- PostgreSQL database dump complete
+--
+
+--------------------------------------------------
+-- update sequences values
+--------------------------------------------------
+
+select setval('controlled_vocabulary_id_seq', 100);
+select setval('cvte_id_seq', 100);
+select setval('property_type_id_seq', 100);
+select setval('file_format_type_id_seq', 100);
+select setval('filter_id_seq', 100);
+select setval('experiment_type_id_seq', 100);
+select setval('sample_type_id_seq', 100);
+select setval('data_set_type_id_seq', 100);
+select setval('material_type_id_seq', 100);
+select setval('etpt_id_seq', 100);
+select setval('stpt_id_seq', 100);
+select setval('mtpt_id_seq', 100);
+
+
+--------------------------------------------------
+-- create a gene property and assign it to sirna well
+--------------------------------------------------
+
+insert into property_types(
+	id, 
+	code, description, label, 
+	daty_id,
+	pers_id_registerer,
+	dbin_id,
+	maty_prop_id) 
+values(
+		nextval('PROPERTY_TYPE_ID_SEQ'), 
+		'GENE','Inhibited gene','Gene',
+		(select id from data_types where code = 'MATERIAL'), 
+		(select id from persons where user_id ='system'), 
+		(select id from database_instances where is_original_source = 'T'), 
+		(select id from material_types where code = 'GENE')
+	);
+	
+insert into sample_type_property_types( 
+  id,
+  saty_id,
+  prty_id,
+  is_mandatory,
+  pers_id_registerer,
+  ordinal
+) values(
+		nextval('stpt_id_seq'), 
+		(select id from sample_types where code = 'SIRNA_WELL'),
+		(select id from property_types where code = 'GENE'),
+		false,
+		(select id from persons where user_id ='system'),
+		(select max(ordinal)+1 from sample_type_property_types 
+			where saty_id = (select id from sample_types where code = 'SIRNA_WELL'))
+	);
+
+
+--------------------------------------------------
+-- Create gene property: gene_symbols
+--------------------------------------------------
+
+
+	insert into property_types
+		(id
+		,code
+		,description
+		,label
+		,daty_id
+		,pers_id_registerer
+		,dbin_id)
+	values 
+		(nextval('PROPERTY_TYPE_ID_SEQ')
+		,'GENE_SYMBOLS'
+		,'Gene symbols'
+		,'Gene symbols'
+		,(select id from data_types where code ='VARCHAR')
+		,(select id from persons where user_id ='system')
+		,(select id from database_instances where is_original_source = 'T')
+	);
+		
+	insert into material_type_property_types( 
+	  id,
+	  maty_id,
+	  prty_id,
+	  is_mandatory,
+	  pers_id_registerer,
+	  ordinal
+	) values(
+			nextval('mtpt_id_seq'), 
+			(select id from material_types where code = 'GENE'),
+			(select id from property_types where code = 'GENE_SYMBOLS'),
+			false,
+			(select id from persons where user_id ='system'),
+			(select max(ordinal)+1 from material_type_property_types 
+				where maty_id = (select id from material_types where code = 'GENE'))
+		);
+
diff --git a/screening/source/sql/postgresql/012/schema-012.sql b/screening/source/sql/postgresql/012/schema-012.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c798e6d3ba6a294b6e578ac27d2d90bbc3cac884
--- /dev/null
+++ b/screening/source/sql/postgresql/012/schema-012.sql
@@ -0,0 +1,285 @@
+
+/* ---------------------------------------------------------------------- */
+/* Domains                                                                */
+/* ---------------------------------------------------------------------- */
+
+CREATE DOMAIN TECH_ID AS BIGINT;
+
+CREATE DOMAIN CODE AS VARCHAR(40);
+
+CREATE DOMAIN NAME AS VARCHAR(80);
+
+CREATE DOMAIN DESCRIPTION AS VARCHAR(200);
+
+CREATE DOMAIN FILE_PATH as VARCHAR(1000);
+
+CREATE DOMAIN COLOR_COMPONENT AS VARCHAR(40) CHECK (VALUE IN ('RED', 'GREEN', 'BLUE'));
+
+CREATE DOMAIN CHANNEL_COLOR AS VARCHAR(20) CHECK (VALUE IN ('BLUE', 'GREEN', 'RED', 'RED_GREEN', 'RED_BLUE', 'GREEN_BLUE'));
+ 
+CREATE DOMAIN BOOLEAN_CHAR AS BOOLEAN DEFAULT FALSE;
+
+/* ---------------------------------------------------------------------- */
+/* Tables                                                                 */
+/* ---------------------------------------------------------------------- */
+
+CREATE TABLE EXPERIMENTS (
+  ID BIGSERIAL NOT NULL,
+  PERM_ID CODE NOT NULL,
+  IMAGE_TRANSFORMER_FACTORY BYTEA,
+
+  PRIMARY KEY (ID),
+  UNIQUE (PERM_ID)
+);
+
+CREATE TABLE CONTAINERS (
+  ID BIGSERIAL NOT NULL,
+  PERM_ID CODE NOT NULL,
+
+  SPOTS_WIDTH INTEGER,
+  SPOTS_HEIGHT INTEGER,
+  
+  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
+);
+
+CREATE INDEX CONTAINERS_EXPE_IDX ON CONTAINERS(EXPE_ID);
+
+CREATE TABLE SPOTS (
+  ID BIGSERIAL NOT NULL,
+	
+	-- position in the container, one-based
+  X INTEGER, 
+  Y INTEGER, 
+  CONT_ID TECH_ID NOT NULL,
+  
+  PRIMARY KEY (ID),
+  CONSTRAINT FK_SPOT_1 FOREIGN KEY (CONT_ID) REFERENCES CONTAINERS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX SPOTS_CONT_IDX ON SPOTS(CONT_ID);
+-- allows to select one spot of the container quicker
+CREATE INDEX SPOTS_COORDS_IDX ON SPOTS(CONT_ID, X, Y);
+
+CREATE TABLE DATA_SETS (
+  ID BIGSERIAL NOT NULL,
+  PERM_ID CODE NOT NULL,
+
+  ---- image dataset specific fields (should be refactored) 
+	FIELDS_WIDTH INTEGER,
+	FIELDS_HEIGHT INTEGER,	
+  -- transformation for merged channels on the dataset level, overrides experiment level transformation
+  IMAGE_TRANSFORMER_FACTORY BYTEA,
+  -- a redundant information if there are timepoint or depth stack data for any spots in this dataset
+  IS_MULTIDIMENSIONAL BOOLEAN_CHAR NOT NULL,
+
+  -- Which image library should be used to read the image? 
+  -- If not specified, some heuristics are used, but it is slower and does not try with all the available libraries. 
+  IMAGE_LIBRARY_NAME NAME,
+  -- Which reader in the library should be used? Valid only if the library name is specified.
+  -- Should be specified when library name is specified.
+  IMAGE_LIBRARY_READER_NAME NAME,
+  ---- END image dataset specific fields
+  
+  CONT_ID TECH_ID,
+  
+  PRIMARY KEY (ID),
+  UNIQUE (PERM_ID),
+  CONSTRAINT FK_DATA_SET_1 FOREIGN KEY (CONT_ID) REFERENCES CONTAINERS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX DATA_SETS_CONT_IDX ON DATA_SETS(CONT_ID);
+
+CREATE TABLE CHANNELS (
+    ID BIGSERIAL  NOT NULL,
+    
+    CODE NAME NOT NULL,
+    LABEL NAME NOT NULL,
+    DESCRIPTION DESCRIPTION,
+    WAVELENGTH INTEGER,
+    IMAGE_TRANSFORMER_FACTORY BYTEA,
+    COLOR CHANNEL_COLOR NOT NULL,
+
+    DS_ID TECH_ID,
+    EXP_ID TECH_ID,
+    
+    PRIMARY KEY (ID),
+    CONSTRAINT FK_CHANNELS_1 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT FK_CHANNELS_2 FOREIGN KEY (EXP_ID) REFERENCES EXPERIMENTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT CHANNELS_DS_EXP_ARC_CK CHECK ((DS_ID IS NOT NULL AND EXP_ID IS NULL) OR (DS_ID IS NULL AND EXP_ID IS NOT NULL)),
+    
+    CONSTRAINT CHANNELS_UK_1 UNIQUE(CODE, DS_ID),
+    CONSTRAINT CHANNELS_UK_2 UNIQUE(CODE, EXP_ID)
+);
+
+CREATE INDEX CHANNELS_DS_IDX ON CHANNELS(DS_ID);
+
+CREATE TABLE CHANNEL_STACKS (
+    ID BIGSERIAL  NOT NULL,
+		
+		-- x and y are kind of a two dimensional sequence number, some use case may only use x and leave y alone
+		X INTEGER,
+		Y INTEGER,
+		-- We use the fixed dimension meters here.
+		Z_in_M REAL,
+		-- We use the fixed dimension seconds here.
+		T_in_SEC REAL,
+		SERIES_NUMBER INTEGER,
+		
+		-- For all channel stacks of a well (HCS) or image dataset (microscopy) there should be exactly 
+		-- one record with is_representative = true
+		is_representative BOOLEAN_CHAR NOT NULL DEFAULT 'F',
+    
+    DS_ID TECH_ID	NOT NULL,
+		SPOT_ID TECH_ID,
+
+    PRIMARY KEY (ID),
+    CONSTRAINT FK_CHANNEL_STACKS_1 FOREIGN KEY (SPOT_ID) REFERENCES SPOTS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT FK_CHANNEL_STACKS_2 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX CHANNEL_STACKS_DS_IDX ON CHANNEL_STACKS(DS_ID);
+CREATE INDEX CHANNEL_STACKS_SPOT_IDX ON CHANNEL_STACKS(SPOT_ID);
+CREATE INDEX CHANNEL_STACKS_DIM_IDX ON CHANNEL_STACKS(X, Y, Z_in_M, T_in_SEC);
+
+CREATE TABLE IMAGES (
+    ID BIGSERIAL  NOT NULL,
+   
+    PATH	FILE_PATH NOT NULL,
+    PAGE	INTEGER,
+    COLOR	COLOR_COMPONENT,
+    
+    PRIMARY KEY (ID)
+);
+
+CREATE TABLE ACQUIRED_IMAGES (
+    ID BIGSERIAL  NOT NULL,
+   
+		IMG_ID   TECH_ID NOT NULL,
+		THUMBNAIL_ID  TECH_ID,
+		IMAGE_TRANSFORMER_FACTORY BYTEA,
+
+    CHANNEL_STACK_ID  TECH_ID NOT NULL,
+    CHANNEL_ID  TECH_ID NOT NULL,
+
+    PRIMARY KEY (ID),
+    CONSTRAINT FK_IMAGES_1 FOREIGN KEY (CHANNEL_STACK_ID) REFERENCES CHANNEL_STACKS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT FK_IMAGES_2 FOREIGN KEY (CHANNEL_ID) REFERENCES CHANNELS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT FK_IMAGES_3 FOREIGN KEY (IMG_ID) REFERENCES IMAGES (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT FK_IMAGES_4 FOREIGN KEY (THUMBNAIL_ID) REFERENCES IMAGES (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX IMAGES_CHANNEL_STACK_IDX ON ACQUIRED_IMAGES(CHANNEL_STACK_ID);
+CREATE INDEX IMAGES_CHANNEL_IDX ON ACQUIRED_IMAGES(CHANNEL_ID);
+CREATE INDEX IMAGES_IMG_IDX ON ACQUIRED_IMAGES(IMG_ID);
+CREATE INDEX IMAGES_THUMBNAIL_IDX ON ACQUIRED_IMAGES(THUMBNAIL_ID);
+
+CREATE TABLE EVENTS (
+  LAST_SEEN_DELETION_EVENT_ID TECH_ID NOT NULL
+);
+
+/* ---------------------------------------------------------------------- */
+/* FEATURE VECTORS                                                        */
+/* ---------------------------------------------------------------------- */ 
+
+CREATE TABLE FEATURE_DEFS (
+    ID BIGSERIAL  NOT NULL,
+    
+    CODE NAME NOT NULL,
+    LABEL NAME NOT NULL,
+    DESCRIPTION DESCRIPTION,
+    
+    DS_ID  TECH_ID NOT NULL,
+    
+    PRIMARY KEY (ID),
+    CONSTRAINT FK_FEATURE_DEFS_1 FOREIGN KEY (DS_ID) REFERENCES DATA_SETS (ID) ON DELETE CASCADE ON UPDATE CASCADE,
+    CONSTRAINT FEATURE_DEFS_UK_1 UNIQUE(CODE, DS_ID)
+);
+
+CREATE INDEX FEATURE_DEFS_DS_IDX ON FEATURE_DEFS(DS_ID);
+
+CREATE TABLE FEATURE_VOCABULARY_TERMS (
+	ID BIGSERIAL  NOT NULL,
+
+  CODE NAME NOT NULL,
+  SEQUENCE_NUMBER INTEGER NOT NULL,
+	FD_ID  TECH_ID NOT NULL,
+
+	PRIMARY KEY (ID),
+	CONSTRAINT FK_FEATURE_VOCABULARY_TERMS_1 FOREIGN KEY (FD_ID) REFERENCES FEATURE_DEFS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+CREATE INDEX FEATURE_VOCABULARY_TERMS_FD_IDX ON FEATURE_VOCABULARY_TERMS(FD_ID);
+
+CREATE TABLE FEATURE_VALUES (
+    ID BIGSERIAL  NOT NULL,
+		
+		-- we use the fixed dimension meters here
+		Z_in_M REAL,
+		-- we use the fixed dimension seconds here
+		T_in_SEC REAL,
+		-- Serialized 2D matrix with values for each spot.
+		-- Contains floats which can be NaN. 
+		-- It is never a case that the whole matrix contains NaN - in such a case we save nothing.
+		-- If feature definition has some connected vocabulary terms then the matrix 
+		-- stores FEATURE_VOCABULARY_TERMS.SEQUENCE_NUMBER of the terms (should be casted from float to int).
+		-- If the term is null the Float.NaN is stored.
+		VALUES BYTEA NOT NULL,
+		
+		FD_ID  TECH_ID NOT NULL,
+		
+		PRIMARY KEY (ID),
+		CONSTRAINT FK_FEATURE_VALUES_1 FOREIGN KEY (FD_ID) REFERENCES FEATURE_DEFS (ID) ON DELETE CASCADE ON UPDATE CASCADE
+    -- This constaint does not make any sense. Leave it out for now.
+    -- CONSTRAINT FEATURE_VALUES_UK_1 UNIQUE(Z_in_M, T_in_SEC)
+);
+
+CREATE INDEX FEATURE_VALUES_FD_IDX ON FEATURE_VALUES(FD_ID);
+CREATE INDEX FEATURE_VALUES_Z_AND_T_IDX ON FEATURE_VALUES(Z_in_M, T_in_SEC);
+
+
+/* ---------------------------------------------------------------------- */
+/* FUNCTIONS AND TRIGGERS                                                 */
+/* ---------------------------------------------------------------------- */ 
+
+CREATE OR REPLACE FUNCTION DELETE_UNUSED_IMAGES() RETURNS trigger AS $$
+BEGIN
+   delete from images where id = OLD.img_id or id = OLD.thumbnail_id;
+   RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER UNUSED_IMAGES AFTER DELETE ON ACQUIRED_IMAGES
+    FOR EACH ROW EXECUTE PROCEDURE DELETE_UNUSED_IMAGES();
+    
+------------------------------------------------------------------------------------
+--  Purpose:  Create trigger CHANNEL_STACKS_CHECK which checks if both spot_id and dataset.cont_id 
+--            are both null or not null.
+------------------------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION CHANNEL_STACKS_CHECK() RETURNS trigger AS $$
+DECLARE
+   v_cont_id  CODE;
+BEGIN
+
+   select cont_id into v_cont_id from data_sets where id = NEW.ds_id;
+
+   -- Check that if there is no spot than there is no dataset container as well
+   if v_cont_id IS NULL then
+      if NEW.spot_id IS NOT NULL then
+         RAISE EXCEPTION 'Insert/Update of CHANNEL_STACKS failed, as the dataset container is not set, but spot is (spot id = %).',NEW.spot_id;
+      end if;
+	 else
+      if NEW.spot_id IS NULL then
+         RAISE EXCEPTION 'Insert/Update of CHANNEL_STACKS failed, as the dataset container is set (id = %), but spot is not set.',v_cont_id;
+      end if; 
+   end if;
+   RETURN NEW;
+END;
+$$ LANGUAGE 'plpgsql';
+
+CREATE TRIGGER CHANNEL_STACKS_CHECK BEFORE INSERT OR UPDATE ON CHANNEL_STACKS
+    FOR EACH ROW EXECUTE PROCEDURE CHANNEL_STACKS_CHECK();
\ No newline at end of file
diff --git a/screening/source/sql/postgresql/012/upload-screening-metadata.sh b/screening/source/sql/postgresql/012/upload-screening-metadata.sh
new file mode 100755
index 0000000000000000000000000000000000000000..1a8a1969f1ef9d83fafdeb766696b9c5eef14fe7
--- /dev/null
+++ b/screening/source/sql/postgresql/012/upload-screening-metadata.sh
@@ -0,0 +1,2 @@
+DB=$1
+psql -U postgres -d openbis_$DB -f data.sql
diff --git a/screening/source/sql/postgresql/migration/migration-011-012.sql b/screening/source/sql/postgresql/migration/migration-011-012.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4197da7db0dba79e3d371c83c5bcc9516c6d3cb0
--- /dev/null
+++ b/screening/source/sql/postgresql/migration/migration-011-012.sql
@@ -0,0 +1,22 @@
+-- Migration from 011 to 012
+CREATE DOMAIN CHANNEL_COLOR AS VARCHAR(20) CHECK (VALUE IN ('BLUE', 'GREEN', 'RED', 'RED_GREEN', 'RED_BLUE', 'GREEN_BLUE'));
+
+ALTER TABLE channels ADD COLUMN color CHANNEL_COLOR;
+  
+update channels upd_ch
+set color = 
+  (  select 
+  			CASE 
+  			  WHEN (upd_ch.id - min(id)) % 6 = 0 THEN 'BLUE'
+		 			WHEN (upd_ch.id - min(id)) % 6 = 1 THEN 'GREEN'
+		 			WHEN (upd_ch.id - min(id)) % 6 = 2 THEN 'RED'
+		 			WHEN (upd_ch.id - min(id)) % 6 = 3 THEN 'RED_GREEN'
+		 			WHEN (upd_ch.id - min(id)) % 6 = 4 THEN 'RED_BLUE'
+				  WHEN (upd_ch.id - min(id)) % 6 = 5 THEN 'GREEN_BLUE'
+		    END color
+         from channels cc
+         where upd_ch.exp_id = cc.exp_id or upd_ch.ds_id = cc.ds_id
+         group by cc.exp_id, cc.ds_id
+  );
+           
+ALTER TABLE channels ALTER COLUMN color SET NOT NULL;
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ChannelColorTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ChannelColorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f14f9af3b0a3748c5b107cb9ad7941f51e35b8c
--- /dev/null
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ChannelColorTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 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.etl.dataaccess;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.common.test.AssertionUtil;
+import ch.systemsx.cisd.openbis.dss.etl.dto.api.v1.ChannelColor;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor;
+
+/**
+ * @author Tomasz Pylak
+ */
+public class ChannelColorTest extends AssertJUnit
+{
+    @Test
+    public void testEnumsEqual()
+    {
+        List<ChannelColor> values1 = Arrays.asList(ChannelColor.values());
+        List<ImageChannelColor> values2 = Arrays.asList(ImageChannelColor.values());
+        AssertionUtil.assertEnumsEqual(values1, values2);
+    }
+}
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java
index f4702198da5d214f7a929fb4cb7447410ade5bc5..00ac1faf50d3d2f92d2c2ebd3d56a287f21f4c72 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/ImagingQueryDAOTest.java
@@ -31,6 +31,7 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.bds.hcs.Location;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.AbstractDBTest;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ColorComponent;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgAcquiredImageDTO;
@@ -54,6 +55,8 @@ public class ImagingQueryDAOTest extends AbstractDBTest
 
     private static final String CHANNEL_LABEL = "Channel Label";
 
+    private static final ImageChannelColor CHANNEL_COLOR = ImageChannelColor.RED;
+
     private static final int PAGE = 1;
 
     private static final int Y_TILE_ROW = 2;
@@ -299,6 +302,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest
 
         assertEquals("DSCHANNEL", datasetChannel.getCode());
         assertEquals(CHANNEL_LABEL, datasetChannel.getLabel());
+        assertEquals(CHANNEL_COLOR.name(), datasetChannel.getDbChannelColor());
         assertEquals(datasetChannelId, datasetChannel.getId());
 
         assertEquals(datasetChannel, dao.tryGetChannelForDataset(datasetId, "dsChannel"));
@@ -308,6 +312,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest
         ImgChannelDTO experimentChannel = experimentChannels.get(0);
         assertEquals("EXPCHANNEL", experimentChannel.getCode());
         assertEquals(CHANNEL_LABEL, experimentChannel.getLabel());
+        assertEquals(CHANNEL_COLOR.name(), experimentChannel.getDbChannelColor());
         assertEquals(experimentChannelId, experimentChannel.getId());
 
         assertEquals(experimentChannel, dao.tryGetChannelForExperiment(experimentId, "expChannel"));
@@ -400,7 +405,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest
     {
         final ImgChannelDTO channel =
                 new ImgChannelDTO(DS_CHANNEL, CHANNEL_DESCRIPTION, WAVELENGTH, datasetId, null,
-                        CHANNEL_LABEL);
+                        CHANNEL_LABEL, CHANNEL_COLOR);
         return dao.addChannel(channel);
     }
 
@@ -408,7 +413,7 @@ public class ImagingQueryDAOTest extends AbstractDBTest
     {
         final ImgChannelDTO channel =
                 new ImgChannelDTO(EXP_CHANNEL, CHANNEL_DESCRIPTION, WAVELENGTH, null, experimentId,
-                        CHANNEL_LABEL);
+                        CHANNEL_LABEL, CHANNEL_COLOR);
         return dao.addChannel(channel);
     }
 
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java
index 3306e9b6d49da7fc4607126ffb6b281278da5b0c..eb2a160d7cbf03b2cfae696c68449ef8f914a765 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/images/ImageChannelsUtilsTest.java
@@ -47,6 +47,7 @@ import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.ImageChannelStackR
 import ch.systemsx.cisd.openbis.dss.generic.server.images.dto.RequestedImageSize;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.Size;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtilTest;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
 
 /**
@@ -165,7 +166,8 @@ public class ImageChannelsUtilsTest extends AssertJUnit
                 {
                     one(loader).getImageParameters();
                     ImageDatasetParameters imgParams = new ImageDatasetParameters();
-                    imgParams.setChannelsCodes(Arrays.asList(CHANNEL));
+                    imgParams.setChannels(Arrays.asList(new ImageChannel(CHANNEL, CHANNEL, null,
+                            null, null)));
                     will(returnValue(imgParams));
 
                     RequestedImageSize requestedSize =
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java
index 55da96f177bbdf02f68d05bbf0596163cf87139f..cd6cb792052dee44963a18c47beeed4cf55b6fd4 100644
--- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/screening/server/DssServiceRpcScreeningTest.java
@@ -79,6 +79,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.IFeatureVecto
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ImageSize;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannel;
+import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageChannelColor;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ImageDatasetParameters;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.dto.PlateFeatureValues;
@@ -169,7 +171,8 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
         imageParameters.setTileRowsNum(1);
         imageParameters.setTileColsNum(2);
         imageParameters.setDatasetCode(DATASET_CODE);
-        imageParameters.setChannelsCodes(Arrays.asList(CHANNEL_CODE));
+        imageParameters.setChannels(Arrays.asList(new ImageChannel(CHANNEL_CODE, CHANNEL_CODE,
+                null, null, null)));
         context.checking(new Expectations()
             {
                 {
@@ -384,7 +387,8 @@ public class DssServiceRpcScreeningTest extends AssertJUnit
                 {
                     one(dao).tryGetChannelForExperimentPermId(EXPERIMENT_PERM_ID, channel);
                     ImgChannelDTO channelDTO =
-                            new ImgChannelDTO("dapi", null, null, new Long(42), null, "dapi");
+                            new ImgChannelDTO("dapi", null, null, new Long(42), null, "dapi",
+                                    ImageChannelColor.BLUE);
                     channelDTO.setSerializedImageTransformerFactory(SerializationUtils
                             .serialize(transformerFactory));
                     will(returnValue(channelDTO));