diff --git a/TODO b/TODO
index 7888754d828ec1a9861d7066dab881e757c545e2..a5dfd3fe963df67392d6ab4f52949778c40b669f 100644
--- a/TODO
+++ b/TODO
@@ -148,6 +148,8 @@ parallelize global fits
 
 == WAITING FOR CLUE ==
 
+parallel execution: upon first exception kill all threads
+
 rework dy, dp
 
 How to treat blanks in user input:
diff --git a/pub/lib/file_in.cpp b/pub/lib/file_in.cpp
index 96c6dd0caae75bf3a24ab545338a1b42fb4c26dc..a1f1b9f12290f5c377fcc0d5957c30f1ff4cbd61 100644
--- a/pub/lib/file_in.cpp
+++ b/pub/lib/file_in.cpp
@@ -33,7 +33,7 @@
 using namespace std;
 
 namespace NFileIn {
-    void Load_08( ifstream& F_in, string fnam );
+    void Load_yda( ifstream& F_in, string fnam );
 }
 
 
@@ -53,12 +53,7 @@ void NFileIn::load(void)
             if( FS.fail() )
                 throw string("cannot open file");
             cout << ".. loading file " << fnam << "\n";
-            if      ( fext=="y08" )
-                Load_08( FS, fshort );
-            else if ( fext=="yda" )
-                cout << "TODO\n";
-            else
-                throw "BUG: unforeseen extension " + fext;
+            Load_yda( FS, fshort );
             FS.close();
         }
         catch(string& ex) {
@@ -70,9 +65,9 @@ void NFileIn::load(void)
     }
 }
 
-//! Load a YAML file in y08 format.
+//! Load a YAML file in yda format.
 
-void NFileIn::Load_08(ifstream& FS, string fnam)
+void NFileIn::Load_yda(ifstream& FS, string fnam)
 {
     const YAML::Node doc = YAML::Load(FS);
     if( doc.Type() != YAML::NodeType::Map )
@@ -81,14 +76,19 @@ void NFileIn::Load_08(ifstream& FS, string fnam)
     //read meta
     if(!doc["Meta"])
         throw S("no Meta");
-    if ( doc["Meta"].Type() != YAML::NodeType::Map && doc["Meta"].size() > 0 )
-        throw S("Meta is not a MAP type");
+    if ( doc["Meta"].Type() != YAML::NodeType::Map )
+        throw S("Meta is not of MAP type");
 
     if(!doc["Meta"]["format"])
         throw S("no format in Meta");
     string s = doc["Meta"]["format"].as<string>();
-    if ( s != "frida/y08 for yaml1" )
-        throw S("format is not frida/y08 for yaml1");
+    int version;
+    if      ( s == "frida/y08 for yaml1" )
+        version = 1;
+    else if ( s == "frida/y15 for yaml1.2" )
+        version = 2;
+    else
+        throw "unknown data format '" + s + "'";
 
     if(!doc["Meta"]["type"])
         throw S("no type in Meta");
@@ -108,13 +108,14 @@ void NFileIn::Load_08(ifstream& FS, string fnam)
         fc = POlc( new COlc );
         fout = fc;
     } else
-        throw "Meta section has invalid type "+type;
+        throw "Invalid file type "+type;
 
     // read history
     if(!doc["History"])
         throw S("no History");
-    if ( doc["History"].Type() != YAML::NodeType::Sequence  && doc["History"].size() > 0 )
-        throw S("History is not a SEQUENCE type");
+    if ( doc["History"].Type() != YAML::NodeType::Sequence &&
+         (version>1 || doc["History"].size()>0 ) )
+        throw S("History is not of SEQUENCE type");
     for (int i = 0; i < doc["History"].size(); i++) {
         string s = doc["History"][i].as<string>();
         fout->lDoc.push_back(s);
@@ -123,113 +124,225 @@ void NFileIn::Load_08(ifstream& FS, string fnam)
     // read coord
     if(!doc["Coord"])
         throw S("no Coord");
-    if ( doc["Coord"].Type() != YAML::NodeType::Map && doc["Coord"].size() > 0 )
-        throw S("Coord is not a MAP type");
-    if( const YAML::Node& pName = doc["Coord"]["x"] ){
-        fout->xco.name = pName["name"].as<string>();
-        fout->xco.unit =pName["unit"].as<string>();
+    if ( doc["Coord"].Type() != YAML::NodeType::Map )
+        throw S("Coord is not of MAP type");
+    if( const YAML::Node& dCo = doc["Coord"]["x"] ){
+        fout->xco.name = dCo["name"].as<string>();
+        fout->xco.unit =dCo["unit"].as<string>();
     } else
         throw S("no x coord");
-    if( const YAML::Node& pName = doc["Coord"]["y"] ){
-        fout->yco.name = pName["name"].as<string>();
-        fout->yco.unit = pName["unit"].as<string>();
+    if( const YAML::Node& dCo = doc["Coord"]["y"] ){
+        fout->yco.name = dCo["name"].as<string>();
+        fout->yco.unit = dCo["unit"].as<string>();
     } else
         throw S("no y coord");
-
-    int iz = 0;
-    while(const YAML::Node& pName = doc["Coord"]["z"+S(iz)]){
-        CCoord co(pName["name"].as<string>(), pName["unit"].as<string>());
-        fout->ZCo.push_back( co );
-        ++iz;
+    if ( version==1 ) {
+        int iz = 0;
+        while(const YAML::Node& dCo = doc["Coord"]["z"+S(iz)]){
+            CCoord co(dCo["name"].as<string>(), dCo["unit"].as<string>());
+            fout->ZCo.push_back( co );
+            ++iz;
+        }
+    } else {
+        if ( doc["Coord"]["z"].Type() != YAML::NodeType::Sequence )
+            throw S("Coord[z] is not of SEQUENCE type");
+        for ( auto dCo: doc["Coord"]["z"] ) {
+            CCoord co(dCo["name"].as<string>(), dCo["unit"].as<string>());
+            fout->ZCo.push_back( co );
+        }
     }
 
-    // read Param
-    if(!doc["Param"])
-        throw S("no Param");
-    if ( doc["Param"].Type() != YAML::NodeType::Sequence  && doc["Param"].size() > 0)
-        throw S("Param is not a SEQUENCE type");
-    for( int iParam = 0; iParam < (doc["Param"].size()); iParam++ ){
-        if ( doc["Param"][iParam].Type() != YAML::NodeType::Map )
-            throw "Param " + S(iParam) + " is not a MAP type";
-        CCoord co(doc["Param"][iParam]["name"].as<string>(),
-                  doc["Param"][iParam]["unit"].as<string>());
-        string s = doc["Param"][iParam]["value"].as<string>();
-        double num;
-        if( !triv::any2dbl( s, &num ) )
-            throw "param(" + co.name + "): invalid value " + s;
-        fout->RPar.push_back( CParam( co, num ) );
+    // read r-pars
+    if ( version==1 ) {
+        if(!doc["Param"])
+            throw S("no Param");
+        if ( doc["Param"].Type() != YAML::NodeType::Sequence  && doc["Param"].size() > 0)
+            throw S("Param is not of SEQUENCE type");
+        for( int iParam = 0; iParam < (doc["Param"].size()); iParam++ ){
+            if ( doc["Param"][iParam].Type() != YAML::NodeType::Map )
+                throw "Param " + S(iParam) + " is not of MAP type";
+            CCoord co(doc["Param"][iParam]["name"].as<string>(),
+                      doc["Param"][iParam]["unit"].as<string>());
+            string s = doc["Param"][iParam]["value"].as<string>();
+            double num;
+            if( !triv::any2dbl( s, &num ) )
+                throw "param(" + co.name + "): invalid value " + s;
+            fout->RPar.push_back( CParam( co, num ) );
+        }
+    } else {
+        if(!doc["RPar"])
+            throw S("no RPar");
+        if ( doc["RPar"].Type() != YAML::NodeType::Sequence )
+            throw S("RPar is not of SEQUENCE type");
+        for ( auto dCo: doc["RPar"] ) {
+            if ( dCo.Type() != YAML::NodeType::Map )
+                throw S("an r-par is not of MAP type");
+            CCoord co(dCo["name"].as<string>(), dCo["unit"].as<string>());
+            double val = dCo["val"].as<double>();
+            fout->RPar.push_back( CParam( co, val ) );
+        }
     }
 
     // for curve, read formula
     if( !isdata ) {
-        const YAML::Node& pName = doc["Formula"];
-        if( !pName )
-            throw S("DEFICIENT FILE: no formula");
-        string s = pName.as<string>();
-        fc->parse_function( s );
+        string expr;
+        if ( version==1 ) {
+            const YAML::Node& nod = doc["Formula"];
+            if( !nod )
+                throw S("DEFICIENT FILE: no formula");
+            expr = nod.as<string>();
+            fc->parse_function( s );
+            fc->curve_set_defaults();
+        } else {
+            const YAML::Node& nod = doc["Curve"];
+            if( !nod )
+                throw S("DEFICIENT FILE: no Curve section");
+            expr = nod["expr"].as<string>();
+            fc->nP = nod["nPar"].as<int>();
+            fc->weighing = COlc::name2wgt( nod["weighing"].as<string>() );
+            fc->chi2 = nod["chi2"].as<double>();
+        }
+        fc->parse_function( expr );
         fc->curve_set_defaults();
     }
 
-    //start to read Tables
-    if(!doc["Tables"])
-        throw S("no Tables");
-    if ( doc["Tables"].Type() != YAML::NodeType::Sequence && doc["Tables"].size() > 0 )
-        throw S("Tables is not a SEQUENCE type");
-    for (int iTable = 0; iTable < (doc["Tables"].size()); iTable++) {
-        if ( doc["Tables"][iTable].Type() != YAML::NodeType::Map )
-            throw "Tables " + S(iTable) + " is not a MAP type";
-        vector<RObj> z;
-        for(int iz=0; iz<fout->ZCo.size(); ++iz ){
-            string s = doc["Tables"][iTable]["z" + S(iz)].as<string>() ;
-            double num;
-            if( !triv::any2dbl( s, &num ) )
-                throw "z" + S(iz) + ": invalid value " + s;
-            z.push_back( RObjDbl( new CObjDbl( num ) ) );
+    // start to read slices
+    if ( version==1 ) {
+        if(!doc["Tables"])
+            throw S("no Tables");
+        if ( doc["Tables"].Type() != YAML::NodeType::Sequence && doc["Tables"].size() > 0 )
+            throw S("Tables is not of SEQUENCE type");
+        for (int iTable = 0; iTable < (doc["Tables"].size()); iTable++) {
+            if ( doc["Tables"][iTable].Type() != YAML::NodeType::Map )
+                throw "Tables " + S(iTable) + " is not of MAP type";
+            vector<RObj> z;
+            for(int iz=0; iz<fout->ZCo.size(); ++iz ){
+                string s = doc["Tables"][iTable]["z" + S(iz)].as<string>() ;
+                double num;
+                if( !triv::any2dbl( s, &num ) )
+                    throw "z" + S(iz) + ": invalid value " + s;
+                z.push_back( RObjDbl( new CObjDbl( num ) ) );
+            }
+
+            if( isdata ) {
+                PSpec sout( new CSpec );
+                sout->z = z;
+                string xytag;
+                if ( doc["Tables"][iTable]["xy"] ) {
+                    string res, lin;
+                    string val = doc["Tables"][iTable]["xy"].as<string>();
+                    while( val != "" ) {
+                        triv::string_extract_line( val, &lin, &res );
+                        double vx, vy;
+                        if( sscanf( lin.c_str(), "%lg %lg\n", &vx, &vy )!=2 )
+                            throw "xy: bad data line: " + lin;
+                        sout->push_xy( vx, vy );
+                        val = res;
+                    };
+                } else if ( doc["Tables"][iTable]["xyd"] ) {
+                    //itxy.second() >> val;
+                    string res, lin;
+                    string val = doc["Tables"][iTable]["xyd"].as<string>();
+                    while( val != "" ) {
+                        triv::string_extract_line( val, &lin, &res );
+                        double vx, vy, dy;
+                        if( sscanf( lin.c_str(), "%lg %lg %lg\n",&vx, &vy, &dy )!=3 )
+                            throw "xyd: bad data line: " + lin;
+                        sout->push_xyd( vx, vy, dy );
+                        val = res;
+                    };
+                } else
+                    throw "invalid xytag " + xytag;
+                fout->V.push_back( sout );
+            } else {
+                PCurve cout( new CCurve );
+                cout->z = z;
+                for( int ip=0; ip<fc->nP; ++ip ){
+                    string res;
+                    string val = doc["Tables"][iTable]["p" + S(ip)].as<string>();
+                    double num;
+                    if( !triv::any2dbl( val, &num ) )
+                        throw "p" + S(ip) + ": invalid value " + val;
+                    cout->P.push_back( num );
+                    cout->ParAttr.push_back( 'u' );
+                }
+                fout->V.push_back( cout );
+            }
         }
+    } else {
+        if(!doc["Slices"])
+            throw S("no Slices");
+        if ( doc["Slices"].Type() != YAML::NodeType::Sequence )
+            throw S("section Slices is not of SEQUENCE type");
+        for ( const YAML::Node& nodeSlic: doc["Slices"] ) {
+            if ( nodeSlic.Type() != YAML::NodeType::Map )
+                throw S("a slice is not of MAP type");
+            const YAML::Node& nodeZ = nodeSlic["z"];
+            if(!nodeZ)
+                throw S("a slice has no z entry");
+            if ( nodeZ.Type() != YAML::NodeType::Sequence )
+                throw S("a z entry is not of SEQUENCE type");
+            vector<RObj> z;
+            for ( const YAML::Node& nodeZi: nodeZ ) {
+                if ( nodeSlic.Type() != YAML::NodeType::Map )
+                    throw S("a z entry is not of MAP type");
+                z.push_back( RObjDbl( new CObjDbl( nodeZi["val"].as<double>() ) ) );
+            }
+            if( isdata ) {
+                PSpec sout( new CSpec );
+                sout->z = z;
+                if(!nodeSlic["x"])
+                    throw S("a slice has no x entry");
+                if ( nodeSlic["x"].Type() != YAML::NodeType::Sequence )
+                    throw S("an x entry is not of SEQUENCE type");
+                for ( const YAML::Node& nodeEle: nodeSlic["x"] )
+                    sout->x.push_back( nodeEle.as<double>() );
 
-        if( isdata ) {
-            PSpec sout( new CSpec );
-            sout->z = z;
-            string xytag;
-            if ( doc["Tables"][iTable]["xy"] ) {
-                string res, lin;
-                string val = doc["Tables"][iTable]["xy"].as<string>();
-                while( val != "" ) {
-                    triv::string_extract_line( val, &lin, &res );
-                    double vx, vy;
-                    if( sscanf( lin.c_str(), "%lg %lg\n", &vx, &vy )!=2 )
-                        throw "xy: bad data line: " + lin;
-                    sout->push_xy( vx, vy );
-                    val = res;
-                };
-            } else if ( doc["Tables"][iTable]["xyd"] ) {
-                //itxy.second() >> val;
-                string res, lin;
-                string val = doc["Tables"][iTable]["xyd"].as<string>();
-                while( val != "" ) {
-                    triv::string_extract_line( val, &lin, &res );
-                    double vx, vy, dy;
-                    if( sscanf( lin.c_str(), "%lg %lg %lg\n",&vx, &vy, &dy )!=3 )
-                        throw "xyd: bad data line: " + lin;
-                    sout->push_xyd( vx, vy, dy );
-                    val = res;
-                };
-            } else
-                throw "invalid xytag " + xytag;
-            fout->V.push_back( sout );
-        } else {
-            PCurve cout( new CCurve );
-            cout->z = z;
-            for( int ip=0; ip<fc->nP; ++ip ){
-                string res;
-                string val = doc["Tables"][iTable]["p" + S(ip)].as<string>();
-                double num;
-                if( !triv::any2dbl( val, &num ) )
-                    throw "p" + S(ip) + ": invalid value " + val;
-                cout->P.push_back( num );
-                cout->ParAttr.push_back( 'u' );
+                if(!nodeSlic["y"])
+                    throw S("a slice has no y entry");
+                if ( nodeSlic["y"].Type() != YAML::NodeType::Sequence )
+                    throw S("a y entry is not of SEQUENCE type");
+                for ( const YAML::Node& nodeEle: nodeSlic["y"] )
+                    sout->y.push_back( nodeEle.as<double>() );
+                if( sout->y.size() != sout->x.size() )
+                    throw S("a y entry differs in length from x");
+
+                if( nodeSlic["dy"] ) {
+                    if ( nodeSlic["dy"].Type() != YAML::NodeType::Sequence )
+                        throw S("a dy entry is not of SEQUENCE type");
+                    for ( const YAML::Node& nodeEle: nodeSlic["dy"] )
+                        sout->dy.push_back( nodeEle.as<double>() );
+                    if( sout->dy.size() != sout->x.size() )
+                        throw S("a dy entry differs in length from x");
+                }
+                fout->V.push_back( sout );
+            } else {
+                PCurve cout( new CCurve );
+                cout->z = z;
+                if(!nodeSlic["p"])
+                    throw S("a slice has no p entry");
+                if ( nodeSlic["p"].Type() != YAML::NodeType::Sequence )
+                    throw S("a p entry is not of SEQUENCE type");
+                for ( const YAML::Node& nodeEle: nodeSlic["p"] )
+                    cout->P.push_back( nodeEle.as<double>() );
+                if ( cout->P.size()!=fc->nP )
+                    throw S("number of p entries conflicts with nPar");
+
+                if(!nodeSlic["attr"])
+                    throw S("a slice has no attr entry");
+                if ( nodeSlic["attr"].Type() != YAML::NodeType::Sequence )
+                    throw S("an attr entry is not of SEQUENCE type");
+                for ( const YAML::Node& nodeEle: nodeSlic["attr"] )
+                    cout->ParAttr.push_back( nodeEle.as<char>() );
+                if ( cout->ParAttr.size()!=fc->nP )
+                    throw S("number of attr entries conflicts with nPar");
+
+                cout->fitOutcome = nodeSlic["fitOutcome"].as<double>();
+                cout->fitChi2 = nodeSlic["fitChi2"].as<double>();
+                cout->fitR2 = nodeSlic["fitR2"].as<double>();
+
+                fout->V.push_back( cout );
             }
-            fout->V.push_back( cout );
         }
     }
 
diff --git a/pub/lib/file_out.cpp b/pub/lib/file_out.cpp
index b9ed944547d2e1055aca2d7591ff35514dcf3c8a..0864aac23f2013c712f9affebb974a180fee28ee 100644
--- a/pub/lib/file_out.cpp
+++ b/pub/lib/file_out.cpp
@@ -95,7 +95,7 @@ void NFileOut::save_yda( std::ofstream& ofs, POlo f )
     out << YAML::Key << "format" << YAML::Value << "frida/y15 for yaml1.2";
     out << YAML::Key << "type" << YAML::Value << ( fd ? "generic tabular data" : "frida2 curve" );
     out << YAML::EndMap;
-    
+
     out << YAML::Key << "History" << YAML::Value << YAML::BeginSeq;
     for ( string lin: f->lDoc )
         out << lin;
@@ -108,7 +108,7 @@ void NFileOut::save_yda( std::ofstream& ofs, POlo f )
     out << YAML::Key << "y" << YAML::Value << YAML::Flow << YAML::BeginMap <<
         YAML::Key << "name" << YAML::Value << f->yco.name <<
         YAML::Key << "unit" << YAML::Value << f->yco.unit << YAML::EndMap;
-    out << YAML::Key << "z" << YAML::Value << YAML::Flow << YAML::BeginSeq;    
+    out << YAML::Key << "z" << YAML::Value << YAML::Flow << YAML::BeginSeq;
     for ( auto& zco: f->ZCo )
         out << YAML::BeginMap <<
             YAML::Key << "name" << YAML::Value << zco.name <<
@@ -129,12 +129,13 @@ void NFileOut::save_yda( std::ofstream& ofs, POlo f )
         out << YAML::Key << "Curve" << YAML::Value << YAML::BeginMap;
 
         out << YAML::Key << "expr" << YAML::Value << fc->expr;
+        out << YAML::Key << "nPar" << YAML::Value << fc->nP;
         out << YAML::Key << "weighing" << YAML::Value << COlc::wgtNames[fc->weighing];
         out << YAML::Key << "chi2" << YAML::Value << fc->chi2;
 
         out << YAML::EndMap;
     }
-    
+
     out << YAML::Key << "Slices" << YAML::Value << YAML::BeginSeq;
     for( size_t j=0; j<f->V.size(); ++j ) {
         out << YAML::BeginMap;
diff --git a/pub/lib/olf.cpp b/pub/lib/olf.cpp
index 0cd8f596bc114ea918215e4cc31c8170aaeeb192..bed8246427733ca86ef2f2279d0b4fe95368fa07 100644
--- a/pub/lib/olf.cpp
+++ b/pub/lib/olf.cpp
@@ -330,6 +330,16 @@ bool COld::has_nonzero_dy() const
 
 string COlc::wgtNames[] = { "lin", "log", "var", "varc", "vard" };
 
+//! Converts weight from string to enum
+
+COlc::TWgt COlc::name2wgt( string name )
+{
+    for ( int i=0; i<=_LAST_TWGT; ++i )
+        if( name==COlc::wgtNames[i] )
+            return (TWgt)i;
+    throw "undefined weighing key '" + name + "'";
+}
+
 //! Prompt for curve description, and initialize things.
 
 void COlc::curve_query( const string& quest )
diff --git a/pub/lib/olf.hpp b/pub/lib/olf.hpp
index 47e78e557c85ce93e894f559adcb65d69c783364..3a5812e77f90e205779edd930f0a3b119bac253c 100644
--- a/pub/lib/olf.hpp
+++ b/pub/lib/olf.hpp
@@ -94,9 +94,10 @@ public:
     // Fitting:
     int           kd;           ///< Index of data file to be fitted.
     int           kconv;        ///< Index of resolution file to convolve with.
-    enum TWgt { _LIN, _LOG, _VAR, _VARC, _VARD }
+    enum TWgt { _LIN, _LOG, _VAR, _VARC, _VARD, _LAST_TWGT=_VARD }
                   weighing;     ///< Weight mode for fitting.
     static string wgtNames[];
+    static TWgt name2wgt( string name );
     bool          plot_to_grid; ///< Use grid from file 'kd' ?
     string        range_expr;   ///< Restricts points to be fitted.
     RNode         range_T;      ///< Parsed range_expr.