Index: cpp/frams/genetics/geno.cpp
===================================================================
--- cpp/frams/genetics/geno.cpp	(revision 969)
+++ cpp/frams/genetics/geno.cpp	(revision 972)
@@ -24,6 +24,32 @@
 }
 
+bool Geno::formatIsOneOf(const SString& format, const SString& format_list)
+{
+	if (strchr(format_list.c_str(), ',') == NULL)
+		return format == format_list;
+	else
+	{
+		SString item; int pos = 0;
+		while (format_list.getNextToken(pos, item, ','))
+			if (item == format)
+				return true;
+	}
+	return false;
+}
+
 const SString Geno::INVALID_FORMAT = "invalid";
 const SString Geno::UNKNOWN_FORMAT = "";
+const SString Geno::F0_FORMAT_LIST = "0,0s";
+
+bool Geno::isF0Format(const SString& format_list)
+{
+	if (strchr(format_list.c_str(), ',') == NULL)
+		return formatIsOneOf(format_list, F0_FORMAT_LIST);
+	SString item; int pos = 0;
+	while (format_list.getNextToken(pos, item, ','))
+		if (!formatIsOneOf(item, F0_FORMAT_LIST))
+			return false;
+	return true;
+}
 
 void Geno::init(const SString& genstring, const SString& genformat, const SString& genname, const SString& comment)
@@ -41,5 +67,5 @@
 {
 	SString format = trim(input);
-	if (format.len() == 0 || strContainsOneOf(format.c_str(), " \r\n\t"))
+	if (format.length() == 0 || strContainsOneOf(format.c_str(), " \r\n\t"))
 		return Geno::INVALID_FORMAT;
 	return format;
@@ -73,5 +99,5 @@
 					genformat = trimAndValidateFormat(genstring.substr(2));
 					gencopy = "";
-					mapinshift = genstring.len();
+					mapinshift = genstring.length();
 				}
 				break;
@@ -88,5 +114,5 @@
 					genformat = trimAndValidateFormat(genstring.substr(2));
 					gencopy = "";
-					mapinshift = genstring.len();
+					mapinshift = genstring.length();
 				}
 				break;
@@ -95,5 +121,5 @@
 			{
 				SString cut;
-				if (error_end < 0) error_end = genstring.len();
+				if (error_end < 0) error_end = genstring.length();
 				static const int MAX_ERROR = 20;
 				if (error_end > MAX_ERROR)
@@ -104,5 +130,5 @@
 				if (lf >= 0) { if ((lf > 0) && (cut[lf - 1] == '\r')) lf--; cut = cut.substr(0, lf); }
 				sstringQuote(cut);
-				logPrintf("Geno", "init", LOG_ERROR, "Invalid genotype format declaration: '%s'%s", cut.c_str(), name.len() ? SString::sprintf(" in '%s'", name.c_str()).c_str() : "");
+				logPrintf("Geno", "init", LOG_ERROR, "Invalid genotype format declaration: '%s'%s", cut.c_str(), name.length() ? SString::sprintf(" in '%s'", name.c_str()).c_str() : "");
 			}
 
@@ -212,5 +238,5 @@
 int Geno::mapGenToString(int genpos) const
 {
-	if (genpos > gen.len()) return -2;
+	if (genpos > gen.length()) return -2;
 	if (genpos < 0) return -1;
 	return mapinshift + genpos;
@@ -220,5 +246,5 @@
 {
 	stringpos -= mapinshift;
-	if (stringpos > gen.len()) return -2;
+	if (stringpos > gen.length()) return -2;
 	if (stringpos < 0) return -1;
 	return stringpos;
@@ -232,7 +258,7 @@
 int ModelGenoValidator::testGenoValidity(Geno& g)
 {
-	if (g.getFormat() == "0")
-	{
-		Model mod(g);
+	if (Geno::formatIsOneOf(g.getFormat(), Geno::F0_FORMAT_LIST))
+	{
+		Model mod(g, Model::SHAPE_UNKNOWN);
 		return mod.isValid();
 	}
@@ -240,5 +266,5 @@
 	{
 		bool converter_missing;
-		Geno f0geno = g.getConverted("0", NULL, false, &converter_missing);
+		Geno f0geno = g.getConverted(Geno::F0_FORMAT_LIST, NULL, false, &converter_missing);
 		if (converter_missing)
 			return -1;//no result
@@ -250,5 +276,5 @@
 {
 	if (isvalid >= 0) return;
-	if (gen.len() == 0) { isvalid = 0; return; }
+	if (gen.length() == 0) { isvalid = 0; return; }
 	if (format == INVALID_FORMAT) { isvalid = 0; return; }
 	Validators* vals = getValidators();
@@ -309,15 +335,15 @@
 }
 
-Geno Geno::getConverted(SString otherformat, MultiMap *m, bool using_checkpoints, bool *converter_missing)
-{
-	if (otherformat == getFormat()) { if (converter_missing) *converter_missing = false; return *this; }
+Geno Geno::getConverted(SString otherformat_list, MultiMap *m, bool using_checkpoints, bool *converter_missing)
+{
+	if (formatIsOneOf(getFormat(), otherformat_list)) { if (converter_missing) *converter_missing = false; return *this; }
 #ifndef NO_GENOCONVMANAGER
 	GenoConvManager *converters = getConverters();
 	if (converters)
 	{
-		if ((otherformat == "0") && (!m) && (!using_checkpoints))
+		if ((isF0Format(otherformat_list)) && (!m) && (!using_checkpoints))
 		{
 			if (!f0gen)
-				f0gen = new Geno(converters->convert(*this, otherformat, NULL, using_checkpoints, converter_missing));
+				f0gen = new Geno(converters->convert(*this, otherformat_list, NULL, using_checkpoints, converter_missing));
 			else
 			{
@@ -327,9 +353,9 @@
 		}
 		else
-			return converters->convert(*this, otherformat, m, using_checkpoints, converter_missing);
+			return converters->convert(*this, otherformat_list, m, using_checkpoints, converter_missing);
 	}
 #endif
 	if (converter_missing) *converter_missing = true;
-	return (otherformat == getFormat()) ? *this : Geno("", "", "", "GenConvManager not available");
+	return (formatIsOneOf(getFormat(), otherformat_list)) ? *this : Geno("", "", "", "GenConvManager not available");
 }
 
Index: cpp/frams/genetics/geno.h
===================================================================
--- cpp/frams/genetics/geno.h	(revision 969)
+++ cpp/frams/genetics/geno.h	(revision 972)
@@ -129,4 +129,8 @@
 	static GenoConvManager* useConverters(GenoConvManager* gcm);
 	static GenoConvManager* getConverters();
+
+	static bool formatIsOneOf(const SString& format, const SString& format_list);
+	static bool isF0Format(const SString& format_list);
+	static const SString F0_FORMAT_LIST;
 };
 
Index: cpp/frams/genetics/genoconv.cpp
===================================================================
--- cpp/frams/genetics/genoconv.cpp	(revision 969)
+++ cpp/frams/genetics/genoconv.cpp	(revision 972)
@@ -123,5 +123,5 @@
 /// (can be NULL if you don't need this information)
 
-GenoConverter **GenoConvManager::getPath(const SString& in, const SString& out, GenoConverter **path, int maxlen, int *mapavailable)
+GenoConverter **GenoConvManager::getPath(const SString& in_format, const SString& out_format_list, GenoConverter **path, int maxlen, int *mapavailable)
 {
 	if (!maxlen) return 0;
@@ -130,8 +130,8 @@
 	for (; gk = (GenoConverter*)converters(i); i++)
 	{
-		if ((gk->enabled) && (gk->in_format == in))
+		if ((gk->enabled) && (gk->in_format == in_format))
 		{
 			*path = gk;
-			if (gk->out_format == out)
+			if (Geno::formatIsOneOf(gk->out_format, out_format_list))
 			{
 				if (mapavailable)
@@ -142,5 +142,5 @@
 			{
 				int mapavail;
-				GenoConverter **ret = getPath(gk->out_format, out, path + 1, maxlen - 1, &mapavail);
+				GenoConverter **ret = getPath(gk->out_format, out_format_list, path + 1, maxlen - 1, &mapavail);
 				if (ret)
 				{
@@ -155,7 +155,10 @@
 }
 
-Geno GenoConvManager::convert(Geno &in, SString format, MultiMap *map, bool using_checkpoints, bool *converter_missing)
-{
-	if (in.getFormat() == format) { if (converter_missing) *converter_missing = false; return in; }
+Geno GenoConvManager::convert(Geno &in, SString format_list, MultiMap *map, bool using_checkpoints, bool *converter_missing)
+{
+	if (Geno::formatIsOneOf(in.getFormat(), format_list))
+	{
+		if (converter_missing) *converter_missing = false; return in;
+	}
 	GenoConverter *path[10];
 	int dep;
@@ -164,10 +167,10 @@
 	int mapavail;
 	for (dep = 1; dep < (int)sizeof(path); dep++) //iterative deepening
-		if (ret = getPath(in.getFormat(), format, path, dep, &mapavail)) break;
+		if (ret = getPath(in.getFormat(), format_list, path, dep, &mapavail)) break;
 	if (!ret) { if (converter_missing) *converter_missing = true; return Geno("", Geno::INVALID_FORMAT, "", "converter not found"); }
 	if (converter_missing) *converter_missing = false;
 	if (!map) mapavail = 0;
 	GenoConverter **t = path;
-	SString tmp;
+	SString tmp, out_format;
 	tmp = in.getGenes();
 	MultiMap lastmap, tmpmap;
@@ -177,5 +180,6 @@
 		GenoConverter *gk = *t;
 		tmp = gk->convert(tmp, mapavail ? &tmpmap : 0, using_checkpoints);
-		if (!tmp.len())
+		out_format = gk->out_format;
+		if (!tmp.length())
 		{
 			string t = ssprintf("f%s->f%s conversion failed (%s)", gk->in_format.c_str(), gk->out_format.c_str(), gk->name);
@@ -200,4 +204,4 @@
 	if (map)
 		*map = lastmap;
-	return Geno(tmp, format, in.getName(), in.getComment());
-}
+	return Geno(tmp, out_format, in.getName(), in.getComment());
+}
Index: cpp/frams/genetics/genoconv.h
===================================================================
--- cpp/frams/genetics/genoconv.h	(revision 969)
+++ cpp/frams/genetics/genoconv.h	(revision 972)
@@ -77,5 +77,5 @@
 	/// make a genotype in other format. genotype will be invalid
 	/// if GenoConvManager cannot convert it.
-	Geno convert(Geno &in, SString format, MultiMap *map = 0, bool using_checkpoints = false, bool *converter_missing = NULL);
+	Geno convert(Geno &in, SString format_list, MultiMap *map = 0, bool using_checkpoints = false, bool *converter_missing = NULL);
 	/// register GenoConverter, the added object will be automatically deleted when GenoConvManager is destructed (call removeConverter() if this is not desirable)
 	void addConverter(GenoConverter *conv);
