diff --git a/etc/key_mapping b/etc/key_mapping
index e88fa11e1904bf47d4d11daa93f18a6f6321a8f0..31afa98b27cc8c13d771a5f14c13f613ad48bf27 100644
--- a/etc/key_mapping
+++ b/etc/key_mapping
@@ -1,9 +1,9 @@
 # CHADO (SO) database key mappings (used for writing out to file)
 #
 # CHADO                                    map to 	    qualifier (optional)
-pseudogenic_transcript                     mRNA            pseudo
-pseudogenic_exon                           CDS             pseudo
-pseudogene                                 gene            pseudo
+pseudogenic_transcript                     mRNA            pseudogene=unknown
+pseudogenic_exon                           CDS             pseudogene=unknown
+pseudogene                                 gene            pseudogene=unknown
 polypeptide_motif                          CDS_motif
 five_prime_UTR                             5'UTR
 three_prime_UTR                            3'UTR
diff --git a/etc/versions b/etc/versions
index e50dbf516da9221f82428901e0030e7fea89e49a..dc7637fca5ddf3c96f09454fa8381152472e4488 100644
--- a/etc/versions
+++ b/etc/versions
@@ -1,4 +1,4 @@
-Artemis Release 15.1.7
-ACT Release 12.1.7
+Artemis Release 15.1.8
+ACT Release 12.1.8
 DNAPlotter Release 1.11
 BamView 1.2.10
\ No newline at end of file
diff --git a/test/data/project.properties b/test/data/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5fb5c53e55030a80bfad144f9fa2260f2fe08147
--- /dev/null
+++ b/test/data/project.properties
@@ -0,0 +1,20 @@
+
+project.Styphi.sequence=ftp://ftp.sanger.ac.uk/pub/pathogens/Salmonella/typhi/St.dna
+project.Styphi.annotation=ftp://ftp.sanger.ac.uk/pub/pathogens/Salmonella/typhi/St.art
+project.Styphi.title=Styphi
+
+#
+project.PF3D7.sequence = ftp://ftp.sanger.ac.uk/pub4/pathogens/Plasmodium/falciparum/3D7/3D7.latest_version/version3/August_2013/Pf3D7_01_v3.embl.gz
+project.PF3D7.bam = \
+        http://www.genedb.org/artemis/NAR/Malaria_RNASeq/version2.1.4/MAL_0h.bam \
+        http://www.genedb.org/artemis/NAR/Malaria_RNASeq/version2.1.4/MAL_8h.bam \
+        http://www.genedb.org/artemis/NAR/Malaria_RNASeq/version2.1.4/MAL_16h.bam \
+        http://www.genedb.org/artemis/NAR/Malaria_RNASeq/version2.1.4/MAL_24h.bam \
+        http://www.genedb.org/artemis/NAR/Malaria_RNASeq/version2.1.4/MAL_48h.bam
+project.PF3D7.title = Plasmodium\\ falciparum
+        
+#
+project.Pberghei.sequence = Pberghei:berg01
+project.Pberghei.chado =  genedb-db.sanger.ac.uk:5432/snapshot?genedb_ro
+project.Pberghei.title = Pberghei
+
diff --git a/test/uk/ac/sanger/artemis/components/ProjectPropertyTest.java b/test/uk/ac/sanger/artemis/components/ProjectPropertyTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..79c5f5a505741a63bba41d658adc0ddc10de99be
--- /dev/null
+++ b/test/uk/ac/sanger/artemis/components/ProjectPropertyTest.java
@@ -0,0 +1,168 @@
+/* 
+ * This file is part of Artemis
+ *
+ * Copyright (C) 2013  Genome Research Limited
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+package uk.ac.sanger.artemis.components;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.awt.GraphicsEnvironment;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Properties;
+
+/**
+ * Tests for loading and writing project properties for
+ * Artemis.
+ */
+public class ProjectPropertyTest
+{
+  private HashMap<String, HashMap<String, String>> projects;
+  
+  /**
+   * Load the test properties
+   */
+  @Before
+  public void loadProperties()
+  {
+    InputStream ins = 
+        this.getClass().getClassLoader().getResourceAsStream("data/project.properties");
+    
+    try
+    {
+      final Properties projectProps = new Properties();
+      projectProps.load(ins);
+      ins.close();
+      projects = ProjectProperty.getProjectMap(projectProps);
+    }
+    catch (IOException e)
+    {
+      org.junit.Assert.fail(e.getMessage());
+    }
+  }
+  
+  /**
+   * Test contents of hash for Styphi
+   */
+  @Test
+  public void projectContent1()
+  {
+    // ignore if in headless mode with no x11
+    if(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadless())
+      return;
+
+    assertTrue("Styphi project",  projects.containsKey("Styphi"));
+    if(projects.containsKey("Styphi"))
+    {
+      HashMap<String, String> thisProject = projects.get("Styphi");
+      assertTrue("Styphi project sequence",  thisProject.containsKey("sequence"));
+      assertTrue("Styphi project annotation",  thisProject.containsKey("annotation"));
+    }
+  }
+  
+  /**
+   * Test contents of hash for PF3D7
+   */
+  @Test
+  public void projectContent2()
+  {
+    // ignore if in headless mode with no x11
+    if(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadless())
+      return;
+
+    assertTrue("PF3D7 project",  projects.containsKey("PF3D7"));
+    if(projects.containsKey("PF3D7"))
+    {
+      HashMap<String, String> thisProject = projects.get("PF3D7");
+      assertTrue("Styphi project sequence",  thisProject.containsKey("sequence"));
+      assertTrue("Styphi project bam",  thisProject.containsKey("bam"));
+    }
+  }
+
+  @Test
+  public void launch()
+  {
+    // ignore if in headless mode with no x11
+    if(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadless())
+      return;
+
+    try
+    {
+      ProjectProperty pp = new ProjectProperty();
+    }
+    catch(Exception e)
+    {
+      org.junit.Assert.fail(e.getMessage());
+    }
+  }
+  
+  /**
+   * Test writing and reading of the fields in the
+   * properties file
+   */
+  @Test
+  public void writeAndReadProperties()
+  {
+    // ignore if in headless mode with no x11
+    if(GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadless())
+      return;
+
+    try
+    {
+      final File tmpFile = File.createTempFile("artemis.props", ".tmp");
+      ProjectProperty.writeProperties(tmpFile, projects);
+      
+      final InputStream ins = new FileInputStream(tmpFile);
+      final Properties projectProps = new Properties();
+      projectProps.load(ins);
+      ins.close();
+      final HashMap<String, HashMap<String, String>>
+         tmpProjects = ProjectProperty.getProjectMap(projectProps);
+      
+      for (String p: projects.keySet())
+      {
+        assertTrue("Contains "+p,  tmpProjects.containsKey(p));
+        
+        HashMap<String, String> props = projects.get(p);
+        HashMap<String, String> tmpProps = tmpProjects.get(p);
+        for(final String key: props.keySet())
+        {
+          // test property key (e.g. title, sequence, bam)
+          assertTrue("Contains property "+key,  tmpProps.containsKey(key));
+          
+          // test values
+          assertTrue("Contains property "+key+" = "+props.get(key), 
+              props.get(key).equals(tmpProps.get(key)));
+        }
+      }
+    }
+    catch(IOException e)
+    {
+      org.junit.Assert.fail(e.getMessage());
+    }
+
+  }
+  
+}
diff --git a/uk/ac/sanger/artemis/components/EntryFileDialog.java b/uk/ac/sanger/artemis/components/EntryFileDialog.java
index d70d48d1bcd9a461a7a688e5827f1f97b26f7620..20896d1d2e23f4a6e48639bcd0bec44557c362d7 100644
--- a/uk/ac/sanger/artemis/components/EntryFileDialog.java
+++ b/uk/ac/sanger/artemis/components/EntryFileDialog.java
@@ -366,17 +366,21 @@ public class EntryFileDialog extends StickyFileChooser
         Box yBox = Box.createVerticalBox();
         boolean useAccessory = false;
 
-        JCheckBox emblHeader = new JCheckBox("Add EMBL Header",
-                                             false);
+        JCheckBox emblHeader = new JCheckBox("Add EMBL Header", false);
+        
+        JCheckBox removeProductForPseudo = new JCheckBox(
+            "Remove products from pseudogenes", false);
 
         setDialogTitle("Save to ...");
         setDialogType(JFileChooser.SAVE_DIALOG);
 
-        if( destination_type == DocumentEntryFactory.EMBL_FORMAT &&
-           (entry.getHeaderText() == null ||
-           !isHeaderEMBL(entry.getHeaderText())) )
+        if( destination_type == DocumentEntryFactory.EMBL_FORMAT )
         {
-          yBox.add(emblHeader);
+          if((entry.getHeaderText() == null || !isHeaderEMBL(entry.getHeaderText())))
+            yBox.add(emblHeader);
+          
+          if(!include_diana_extensions)
+            yBox.add(removeProductForPseudo);
           useAccessory = true;
         }
 
@@ -466,6 +470,7 @@ public class EntryFileDialog extends StickyFileChooser
                              false);
         try 
         {
+          DocumentEntryFactory.REMOVE_PRODUCT_FROM_PSEUDOGENE = removeProductForPseudo.isSelected();
           if(entry.getEMBLEntry() instanceof DatabaseDocumentEntry ||
              entry.getEMBLEntry() instanceof GFFDocumentEntry)
             ReadAndWriteEntry.writeDatabaseEntryToFile(entry, file, 
@@ -507,6 +512,7 @@ public class EntryFileDialog extends StickyFileChooser
         }
         finally 
         {
+          DocumentEntryFactory.REMOVE_PRODUCT_FROM_PSEUDOGENE = false;
           if(message != null) 
             message.dispose();
         }
diff --git a/uk/ac/sanger/artemis/io/DocumentEntryFactory.java b/uk/ac/sanger/artemis/io/DocumentEntryFactory.java
index ad713b701b0deeeda061fc196f8b143a20bbe40f..f530a0863f4df5fc36c3d39f742f54e27fa8c884 100644
--- a/uk/ac/sanger/artemis/io/DocumentEntryFactory.java
+++ b/uk/ac/sanger/artemis/io/DocumentEntryFactory.java
@@ -48,47 +48,18 @@ abstract public class DocumentEntryFactory
 
   /** use if format of the entry is not important */
   final public static int ANY_FORMAT = UNKNOWN_FORMAT;
-                                                                                                               
+
   /** use for an entry that is in EMBL format */
   final public static int EMBL_FORMAT = 1;
-                                                                                                               
+
   /** use for an entry that is in GENBANK format */
   final public static int GENBANK_FORMAT = 2;
-                                                                                                               
+
   /** use for an entry that is in GFF format  */
   final public static int GFF_FORMAT = 3;
-                                                                                                               
-  /** use for an entry that is in BSML format */
-  final public static int BSML_FORMAT = 4;
-                                                                                                               
-  /** use for an entry that is in GAME format */
-  final public static int GAME_FORMAT = 5;
-                                                                                                               
-  /** use for an entry that is in AVAGE format */
-  final public static int AVAGE_FORMAT = 5;
-
 
-  /**
-   *  Read a DocumentEntry object from the given Document with no restrictions
-   *  on the possible keys and qualifiers.
-   *  @param listener The object that will listen for ReadEvents.
-   **/
-/*  private static DocumentEntry makeDocumentEntry (final Document document,
-                                                 final ReadListener listener)
-      throws IOException 
-  {
-    try
-    {
-      final EntryInformation entry_information =
-        SimpleEntryInformation.getDefaultEntryInformation ();
+  public static boolean REMOVE_PRODUCT_FROM_PSEUDOGENE = false;
 
-      return makeDocumentEntry (entry_information, document, listener);
-    } 
-    catch (EntryInformationException e)
-    {
-      throw new Error ("internal error - unexpected exception: " + e);
-    }
-  }*/
 
   /**
    *  Read a DocumentEntry object from the given Document.
@@ -161,27 +132,6 @@ abstract public class DocumentEntryFactory
     }
   }
 
-  /**
-   *  Make a new (nameless) DocumentEntry from the given Entry.  The new Entry
-   *  will have a copy of the EntryInformation object of the argument Entry.
-   *  @param destination_type This parameter control the type of DocumentEntry
-   *    that is created.  It should be a DocumentEntry type that can be
-   *    constructed from any Entry eg. one of EMBL_FORMAT, GENBANK_FORMAT.
-   *  @exception EntryInformationException Thrown if the destination Entry
-   *    cannot contain the Key, Qualifier or Key/Qualifier combination of one
-   *    of the features in the source Entry.
-   **/
-/*  public static DocumentEntry makeDocumentEntry (final Entry entry,
-                                                 final int destination_type)
-      throws EntryInformationException
-  {
-    final EntryInformation entry_information =
-      new SimpleEntryInformation (entry.getEntryInformation ());
-
-    return makeDocumentEntry (entry_information, entry, destination_type,
-                              false);
-  }*/
-
   /**
    *  Make a new (nameless) DocumentEntry from the given Entry.
    *  @param entry_information The EntryInformation to use for the new object.
@@ -229,7 +179,12 @@ abstract public class DocumentEntryFactory
 
     switch (destination_type) {
     case EMBL_FORMAT:
-      return new EmblDocumentEntry (entry_information, entry, force);
+    {
+      EmblDocumentEntry ee = new EmblDocumentEntry (entry_information, entry, force);
+      if(force)
+        removeProductFromPseudogene(ee, destination_type);
+      return ee;
+    }
     case GENBANK_FORMAT:
       return new GenbankDocumentEntry (entry_information, entry, force);
     case GFF_FORMAT:
@@ -242,4 +197,31 @@ abstract public class DocumentEntryFactory
       throw new Error ("internal error - unknown DocumentEntry type");
     }
   }
+  
+  /**
+   * Remove product qualifier from CDS features with pseudogene qualifier
+   * @param document_entry
+   * @param destination_type
+   * @throws EntryInformationException
+   */
+  private static void removeProductFromPseudogene(final DocumentEntry entry,
+                                                  final int destination_type) 
+      throws EntryInformationException
+  {
+    if( !REMOVE_PRODUCT_FROM_PSEUDOGENE )
+      return;
+
+    final FeatureVector features = entry.getAllFeatures();
+    for(Feature f: features)
+    {
+      if(f.getKey().equals("CDS"))
+      {
+        Qualifier q = f.getQualifierByName("product");
+        if(  q != null && 
+            (f.getQualifierByName("pseudogene") != null || 
+             f.getQualifierByName("pseudo") != null))
+          f.getQualifiers().remove(q);
+      }
+    }
+  }
 }
diff --git a/uk/ac/sanger/artemis/io/GFFStreamFeature.java b/uk/ac/sanger/artemis/io/GFFStreamFeature.java
index 9fa2cc0cf70f44bf965200d5c149b72800805678..3d4923b22341513667a1d294727d80a206de1f75 100644
--- a/uk/ac/sanger/artemis/io/GFFStreamFeature.java
+++ b/uk/ac/sanger/artemis/io/GFFStreamFeature.java
@@ -1320,6 +1320,36 @@ public class GFFStreamFeature extends SimpleDocumentFeature
     return false;
   }
   
+  /**
+   * Test if this is feature is marked as having a stop codon
+   * redefined as selenocysteine
+   * @param f
+   * @return
+   */
+  public static boolean isSelenocysteine(Feature f)
+  {
+    if(!(f instanceof GFFStreamFeature))
+      return false;
+    try
+    {
+      ChadoCanonicalGene gffGene = ((GFFStreamFeature)f).getChadoGene();
+      if(gffGene == null)
+        return false;
+      String transcript = gffGene.getTranscriptFromName(
+          GeneUtils.getUniqueName(f));
+      if(transcript == null)
+        return false;
+      Feature pep = gffGene.getProteinOfTranscript(transcript);
+      if(pep == null)
+        return false;
+      if(pep.getQualifierByName("stop_codon_redefined_as_selenocysteine") != null)
+        return true;
+    }
+    catch (Exception e){}
+
+    return false;
+  }
+  
   public static void main(String args[])
   {
     Key key = new Key("region");
diff --git a/uk/ac/sanger/artemis/io/ReadAndWriteEntry.java b/uk/ac/sanger/artemis/io/ReadAndWriteEntry.java
index bba78732434fcdef0d80cd06208bbb85254952bf..19cd5eab225c1c4c9a80d3ab7db232fce545e211 100644
--- a/uk/ac/sanger/artemis/io/ReadAndWriteEntry.java
+++ b/uk/ac/sanger/artemis/io/ReadAndWriteEntry.java
@@ -304,6 +304,7 @@ public class ReadAndWriteEntry
         System.out.println("-z\t[y|n] gzip output, default is y");
         System.out.println("-a\t[y|n] for EMBL submission format change to n, default is y");
         System.out.println("-pp\t[y|n] read polypeptide domain features, default is n");
+        System.out.println("-r\t[y|n] remove product qualifiers from pseudogene (only for EMBL submission format), default is n");
         System.out.println("-c\tthe URL for your Chado database e.g. db.genedb.org:5432/snapshot?genedb_ro (if not using default)");
         System.out.println("-u\t[swing|console|script] the UI mode : run in swing (with popup dialog boxes) mode, run in console mode (choices entered in the console window), or in script mode (all choices default to continue, all parameters passed on command line) ");
         System.out.println("-p\tthe password for connecting to the Chado database");
@@ -320,6 +321,7 @@ public class ReadAndWriteEntry
       String suffix = ".embl";
       boolean gzip = true;
       boolean noprivates = true;
+      boolean removeProductForPseudo = false;
       
       String filePath = "";
       
@@ -375,6 +377,11 @@ public class ReadAndWriteEntry
         {
         	System.setProperty("chado", args[i + 1]);
         }
+        else if (key.equals("-r"))
+        {
+          if(i + 1 < args.length && args[i + 1].toLowerCase().equals("y"))
+            removeProductForPseudo = true;
+        }
         else if (key.equals("-p"))
         {
         	System.setProperty("chadoPassword", args[i + 1]);
@@ -438,13 +445,12 @@ public class ReadAndWriteEntry
         logger4j.info("read :: "+names[i]+" write :: "+names[i]+suffix);
         
         Entry entry = ReadAndWriteEntry.readEntryFromDatabase(names[i], ENTRY_SOURCE);
-        
+        DocumentEntryFactory.REMOVE_PRODUCT_FROM_PSEUDOGENE = removeProductForPseudo;
         try
         {
           ReadAndWriteEntry.writeDatabaseEntryToFile(
             entry, new File(filePath + names[i]+suffix), flatten, ignoreObsolete, 
-            false, include_diana_extensions,
-            format, null);
+            false, include_diana_extensions, format, null);
           System.out.println("done");
           logger4j.info("done");
         }
diff --git a/uk/ac/sanger/artemis/io/ValidateFeature.java b/uk/ac/sanger/artemis/io/ValidateFeature.java
index d1dc8836d25054e5a3d4a069eeb0c1a360e39c49..f62ed79dbe2d4c883e1b398973a900ea6d4394e1 100644
--- a/uk/ac/sanger/artemis/io/ValidateFeature.java
+++ b/uk/ac/sanger/artemis/io/ValidateFeature.java
@@ -677,6 +677,9 @@ public class ValidateFeature
     if(!cds_predicate.testPredicate (f)) 
       return false;
 
+    if(feature instanceof GFFStreamFeature && GFFStreamFeature.isSelenocysteine(feature))
+      return false;
+
     final AminoAcidSequence aa = f.getTranslation ();
     return aa.containsStopCodon ();
   }