Index: sasmodels/convert.py
===================================================================
--- sasmodels/convert.py	(revision 07c8d460b7b27e8016df36dcd00643a649cd4e71)
+++ sasmodels/convert.py	(revision f80f334d8db7925a28a9d4e57dc2f7b7a04bfb1b)
@@ -53,10 +53,4 @@
     ("_pd_nsigma", ".nsigmas"),
     ("_pd_type", ".type"),
-    (".lower", ".lower"),
-    (".upper", ".upper"),
-    (".fittable", ".fittable"),
-    (".std", ".std"),
-    (".units", ".units"),
-    ("", "")
     ]
 
@@ -70,4 +64,6 @@
     if id.startswith('M0:'):
         return True
+    if id.startswith('volfraction') or id.startswith('radius_effective'):
+        return False
     if '_pd' in id or '.' in id:
         return False
@@ -79,5 +75,5 @@
         if p.id == id:
             return p.type == 'sld'
-    return False
+    raise ValueError("unknown parameter %r in conversion"%id)
 
 def _rescale_sld(model_info, pars, scale):
@@ -92,7 +88,7 @@
 
 
-def _get_translation_table(model_info, version=(3,1,2)):
-    conv_param = CONVERSION_TABLE.get(version, {}).get(model_info.id, [None, {}])
-    translation = conv_param[1].copy()
+def _get_translation_table(model_info):
+    _, translation = CONVERSION_TABLE.get(model_info.id, [None, {}])
+    translation = translation.copy()
     for p in model_info.parameters.kernel_parameters:
         if p.length > 1:
@@ -123,4 +119,30 @@
 def _pd_to_underscores(pars):
     return dict((_dot_pd_to_underscore_pd(k), v) for k, v in pars.items())
+
+def _convert_name(conv_dict, pars):
+    """
+    Renames parameter values (upper, lower, etc) to v4.0 names
+    :param conv_dict: conversion dictionary mapping new name : old name
+    :param pars: parameters to convert
+    :return:
+    """
+    new_pars = {}
+    i = 0
+    j = 0
+    for key_par, value_par in pars.iteritems():
+        j += 1
+        for key_conv, value_conv in conv_dict.iteritems():
+            if re.search(value_conv, key_par):
+                new_pars[key_par.replace(value_conv, key_conv)] = value_par
+                i += 1
+                break
+            elif re.search("background", key_par) or re.search("scale", key_par):
+                new_pars[key_par] = value_par
+                i += 1
+                break
+        if i != j:
+            new_pars[key_par] = value_par
+            i += 1
+    return new_pars
 
 def _convert_pars(pars, mapping):
@@ -145,5 +167,6 @@
     return newpars
 
-def _conversion_target(model_name, version=(3,1,2)):
+
+def _conversion_target(model_name):
     """
     Find the sasmodel name which translates into the sasview name.
@@ -153,16 +176,11 @@
     two variants in sasview.
     """
-    for sasmodels_name, sasview_dict in \
-            CONVERSION_TABLE.get(version, {}).items():
-        if sasview_dict[0] == model_name:
+    for sasmodels_name, [sasview_name, _] in CONVERSION_TABLE.items():
+        if sasview_name == model_name:
             return sasmodels_name
     return None
 
-def _hand_convert(name, oldpars, version=(3,1,2)):
-    if version == (3,1,2):
-        oldpars = _hand_convert_3_1_2_to_4_1(name, oldpars)
-    return oldpars
-
-def _hand_convert_3_1_2_to_4_1(name, oldpars):
+
+def _hand_convert(name, oldpars):
     if name == 'core_shell_parallelepiped':
         # Make sure pd on rim parameters defaults to zero
@@ -197,18 +215,4 @@
             pd = oldpars['radius.width']*oldpars['radius']/thickness
             oldpars['radius.width'] = pd
-    elif name == 'multilayer_vesicle':
-        if 'scale' in oldpars:
-            oldpars['volfraction'] = oldpars['scale']
-            oldpars['scale'] = 1.0
-        if 'scale.lower' in oldpars:
-            oldpars['volfraction.lower'] = oldpars['scale.lower']
-        if 'scale.upper' in oldpars:
-            oldpars['volfraction.upper'] = oldpars['scale.upper']
-        if 'scale.fittable' in oldpars:
-            oldpars['volfraction.fittable'] = oldpars['scale.fittable']
-        if 'scale.std' in oldpars:
-            oldpars['volfraction.std'] = oldpars['scale.std']
-        if 'scale.units' in oldpars:
-            oldpars['volfraction.units'] = oldpars['scale.units']
     elif name == 'pearl_necklace':
         pass
@@ -232,23 +236,5 @@
                 oldpars[p + ".upper"] /= 1e-13
     elif name == 'spherical_sld':
-        j = 0
-        while "func_inter" + str(j) in oldpars:
-            name = "func_inter" + str(j)
-            new_name = "shape" + str(j + 1)
-            if oldpars[name] == 'Erf(|nu|*z)':
-                oldpars[new_name] = int(0)
-            elif oldpars[name] == 'RPower(z^|nu|)':
-                oldpars[new_name] = int(1)
-            elif oldpars[name] == 'LPower(z^|nu|)':
-                oldpars[new_name] = int(2)
-            elif oldpars[name] == 'RExp(-|nu|*z)':
-                oldpars[new_name] = int(3)
-            elif oldpars[name] == 'LExp(-|nu|*z)':
-                oldpars[new_name] = int(4)
-            else:
-                oldpars[new_name] = int(0)
-            oldpars.pop(name)
-            oldpars['n_shells'] = str(j + 1)
-            j += 1
+        oldpars["CONTROL"] += 1
     elif name == 'teubner_strey':
         # basically undoing the entire Teubner-Strey calculations here.
@@ -295,44 +281,31 @@
     return oldpars
 
-def convert_model(name, pars, use_underscore=False, model_version=(3,1,2)):
+def convert_model(name, pars, use_underscore=False):
     """
     Convert model from old style parameter names to new style.
     """
-    newpars = pars
-    keys = sorted(CONVERSION_TABLE.keys())
-    for i, version in enumerate(keys):
-        # Don't allow indices outside list
-        next_i = i + 1
-        if next_i == len(keys):
-            next_i = i
-        # If the save state is from a later version, skip the check
-        if model_version <= keys[next_i]:
-            newname = _conversion_target(name, version)
-        else:
-            newname = None
-        # If no conversion is found, move on
-        if newname is None:
-            newname = name
-            continue
-        if ':' in newname:   # core_shell_ellipsoid:1
-            model_info = load_model_info(newname[:-2])
-            # Know the table exists and isn't multiplicity so grab it directly
-            # Can't use _get_translation_table since that will return the 'bare'
-            # version.
-            translation = CONVERSION_TABLE.get(version, {})[newname][1]
-        else:
-            model_info = load_model_info(newname)
-            translation = _get_translation_table(model_info, version)
-        newpars = _hand_convert(newname, newpars, version)
-        newpars = _convert_pars(newpars, translation)
-        # TODO: Still not convinced this is the best check
-        if not model_info.structure_factor and version == (3,1,2):
-            newpars = _rescale_sld(model_info, newpars, 1e6)
-        newpars.setdefault('scale', 1.0)
-        newpars.setdefault('background', 0.0)
-        if use_underscore:
-            newpars = _pd_to_underscores(newpars)
-        name = newname
+    newname = _conversion_target(name)
+    if newname is None:
+        return name, pars
+    if ':' in newname:   # core_shell_ellipsoid:1
+        model_info = load_model_info(newname[:-2])
+        # Know that the table exists and isn't multiplicity so grab it directly
+        # Can't use _get_translation_table since that will return the 'bare'
+        # version.
+        translation = CONVERSION_TABLE[newname][1]
+    else:
+        model_info = load_model_info(newname)
+        translation = _get_translation_table(model_info)
+    newpars = _hand_convert(newname, pars.copy())
+    newpars = _convert_name(translation, newpars)
+    newpars = _convert_pars(newpars, translation)
+    if not model_info.structure_factor:
+        newpars = _rescale_sld(model_info, newpars, 1e6)
+    newpars.setdefault('scale', 1.0)
+    newpars.setdefault('background', 0.0)
+    if use_underscore:
+        newpars = _pd_to_underscores(newpars)
     return newname, newpars
+
 
 # ========= BACKWARD CONVERSION sasmodels => sasview 3.x ===========
