diff --git a/cap.cpp b/cap.cpp
index 833883f92819a3062995e1bc725be64707c37fb7..abfb9f849b4493e3122e9848bfbc7625e2fbfa9c 100644
--- a/cap.cpp
+++ b/cap.cpp
@@ -2,58 +2,34 @@
 #include "strops.h"
 #include <cstdlib>
 #include <math.h>
+#include <cassert>
 
 #include "log.h"
 
 using namespace eis;
 
-Cap::Cap(fvalue c): _C(c)
+Cap::Cap(fvalue c)
 {
-
+	ranges.clear();
+	ranges.push_back(Range(c, c, 1));
 }
 
-Cap::Cap(std::string paramStr)
+Cap::Cap(std::string paramStr, size_t count)
 {
-	std::vector<std::string> tokens = tokenize(paramStr, ',');
-	if(tokens.empty())
-	{
-		Log(Log::WARN)<<"to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n';
-		_C = 1e-6;
-		return;
-	}
-	else
+	ranges = Range::rangesFromParamString(paramStr, count);
+
+	if(ranges.size() != paramCount())
 	{
-		try
-		{
-			_C = std::stod(tokens[0]);
-		}
-		catch(const std::invalid_argument& ia)
-		{
-			Log(Log::WARN)<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
-			_C = 1e3;
-		}
+		Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" given to "<<__func__<<", will not be applied\n";
+		ranges.clear();
+		ranges.push_back(Range(1e-6, 1e-6, 1));
 	}
 }
 
 std::complex<fvalue> Cap::execute(fvalue omega)
 {
-	return std::complex<fvalue>(0, 0.0-(1.0/(_C*omega)));
-}
-
-std::vector<fvalue> Cap::getParam()
-{
-	return std::vector<fvalue>({_C});
-}
-
-void Cap::setParam(const std::vector<fvalue>& param)
-{
-	if(param.empty())
-	{
-		Log(Log::WARN)<<"invalid parameter list sent to "<<__func__<<'\n';
-		return;
-	}
-
-	_C = param[0];
+	assert(ranges.size() > 0);
+	return std::complex<fvalue>(0, 0.0-(1.0/(ranges[0][ranges[0].step]*omega)));
 }
 
 char Cap::getComponantChar() const
diff --git a/componant.cpp b/componant.cpp
index f0e29eb89fea1f199c6ee98c4b9b2779fb9aa42f..384954cdb864c934936334b5fdd340521fc30f68 100644
--- a/componant.cpp
+++ b/componant.cpp
@@ -11,6 +11,16 @@
 
 using namespace eis;
 
+void Componant::setParamRanges(const std::vector<eis::Range>& rangesIn)
+{
+	ranges = rangesIn;
+}
+
+std::vector<eis::Range>& Componant::getParamRanges()
+{
+	return ranges;
+}
+
 Componant* Componant::copy(Componant* componant)
 {
 	switch(componant->getComponantChar())
diff --git a/constantphase.cpp b/constantphase.cpp
index 127b96ef68454177ab05c2439bcf3f70abab5320..7ab6177d7ee082db6f391ee0d832a57bcf55fda9 100644
--- a/constantphase.cpp
+++ b/constantphase.cpp
@@ -3,6 +3,7 @@
 #include <cstdlib>
 #define _USE_MATH_DEFINES
 #include <cmath>
+#include <cassert>
 
 #ifndef M_PI
     #define M_PI 3.14159265358979323846
@@ -12,58 +13,41 @@
 
 using namespace eis;
 
-Cpe::Cpe(fvalue q, fvalue alpha): _Q(q), _alpha(alpha)
+Cpe::Cpe()
 {
-
+	setDefaultParam();
 }
 
-Cpe::Cpe(std::string paramStr)
+Cpe::Cpe(fvalue q, fvalue alpha)
 {
-	std::vector<std::string> tokens = tokenize(paramStr, ',');
-	if(tokens.size() < 2)
-	{
-		std::cout<<"Warning: to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n';
-		_Q = 1e-7;
-		_alpha = 0.9;
-		return;
-	}
-	else
-	{
-		try
-		{
-			_Q = std::stod(tokens[0]);
-			_alpha = std::stod(tokens[1]);
-		}
-		catch(const std::invalid_argument& ia)
-		{
-			std::cout<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
-			_Q = 1e-7;
-			_alpha = 0.9;
-		}
-	}
+	ranges.clear();
+	ranges.push_back(Range(q, q, 1));
+	ranges.push_back(Range(alpha, alpha, 1));
 }
 
-std::complex<fvalue> Cpe::execute(fvalue omega)
+Cpe::Cpe(std::string paramStr, size_t count)
 {
-	return std::complex<fvalue>((1.0/(_Q*pow(omega, _alpha)))*cos((M_PI/2)*_alpha),
-	                           0-(1.0/(_Q*pow(omega, _alpha)))*sin((M_PI/2)*_alpha));
+	ranges = Range::rangesFromParamString(paramStr, count);
+
+	if(ranges.size() != paramCount())
+	{
+		Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" given to "<<__func__<<", will not be applied\n";
+		setDefaultParam();
+	}
 }
 
-std::vector<fvalue> Cpe::getParam()
+void Cpe::setDefaultParam()
 {
-	return std::vector<fvalue>({_Q, _alpha});
+	ranges.clear();
+	ranges.push_back(Range(1e-7, 1e-7, 1));
+	ranges.push_back(Range(0.9, 0.9, 1));
 }
 
-void Cpe::setParam(const std::vector<fvalue>& param)
+std::complex<fvalue> Cpe::execute(fvalue omega)
 {
-	if(param.size() < 2)
-	{
-		std::cout<<"Warning: invalid parameter list sent to "<<__func__<<'\n';
-		return;
-	}
-
-	_Q = param[0];
-	_alpha = param[1];
+	assert(ranges.size() == paramCount());
+	return std::complex<fvalue>((1.0/(ranges[0][ranges[0].step]*pow(omega, ranges[1][ranges[1].step])))*cos((M_PI/2)*ranges[1][ranges[1].step]),
+	                           0-(1.0/(ranges[0][ranges[0].step]*pow(omega, ranges[1][ranges[1].step])))*sin((M_PI/2)*ranges[1][ranges[1].step]));
 }
 
 size_t Cpe::paramCount()
diff --git a/eisgenerator/cap.h b/eisgenerator/cap.h
index e0e66c4ddd70504841c7fbe8e43d23b9edf5cbb5..36237e3231982e2c9192e82cecda0aa7ab9bd480 100644
--- a/eisgenerator/cap.h
+++ b/eisgenerator/cap.h
@@ -9,14 +9,10 @@ namespace eis
 
 class Cap: public Componant
 {
-private:
-	fvalue _C;
 public:
-	Cap(std::string paramStr);
+	Cap(std::string paramStr, size_t count = 10);
 	Cap(fvalue c = 1e-6);
 	virtual std::complex<fvalue> execute(fvalue omega) override;
-	virtual std::vector<fvalue> getParam() override;
-	virtual void setParam(const std::vector<fvalue>& param) override;
 	virtual size_t paramCount() override;
 	virtual char getComponantChar() const override;
 	static constexpr char staticGetComponantChar(){return 'c';}
diff --git a/eisgenerator/componant.h b/eisgenerator/componant.h
index eb5ca6de542ed39050e045ac2ff9ea8daa9eca52..f3092cd44ca0bf9ae3fe16307e8aeef23acebfd0 100644
--- a/eisgenerator/componant.h
+++ b/eisgenerator/componant.h
@@ -10,9 +10,12 @@ namespace eis
 
 class Componant
 {
+	protected:
+		std::vector<eis::Range> ranges;
 	public:
 		virtual std::complex<fvalue> execute(fvalue omega)
 		{
+			(void)omega;
 			std::cout<<"warning incompleat model\n";
 			return std::complex<fvalue> (1,0);
 		}
@@ -21,7 +24,8 @@ class Componant
 		{
 			return std::vector<fvalue>();
 		};
-		virtual void setParam(const std::vector<fvalue>& param){};
+		virtual void setParamRanges(const std::vector<eis::Range>& ranges);
+		virtual std::vector<eis::Range>& getParamRanges();
 		virtual size_t paramCount(){return 0;}
 		virtual ~Componant() = default;
 		virtual char getComponantChar() const = 0;
diff --git a/eisgenerator/constantphase.h b/eisgenerator/constantphase.h
index 0706e26e7f20f6ccfef77c5194fe7cf3d58f443e..45a7e65964949006a3942c9fb73cb2eb1907706e 100644
--- a/eisgenerator/constantphase.h
+++ b/eisgenerator/constantphase.h
@@ -10,14 +10,12 @@ namespace eis
 class Cpe: public Componant
 {
 private:
-	fvalue _Q;
-	fvalue _alpha;
+	void setDefaultParam();
 public:
-	Cpe(std::string paramStr);
-	Cpe(fvalue q = 1e-7, fvalue alpha = 0.9);
+	Cpe(std::string paramStr, size_t count = 10);
+	Cpe(fvalue q, fvalue alpha);
+	Cpe();
 	virtual std::complex<fvalue> execute(fvalue omega) override;
-	virtual std::vector<fvalue> getParam() override;
-	virtual void setParam(const std::vector<fvalue>& param) override;
 	virtual size_t paramCount() override;
 	virtual char getComponantChar() const override;
 	static constexpr char staticGetComponantChar(){return 'p';}
diff --git a/eisgenerator/eistype.h b/eisgenerator/eistype.h
index ec5ea22db644d57b42d77c59f6388368680b1f8b..080d751ee79ff9de62db84334adcbd8eae8929d4 100644
--- a/eisgenerator/eistype.h
+++ b/eisgenerator/eistype.h
@@ -1,6 +1,7 @@
 #pragma once
 #include <complex>
 #include <vector>
+#include <cassert>
 
 typedef double fvalue;
 
@@ -18,12 +19,27 @@ public:
 	fvalue start;
 	fvalue end;
 	size_t count;
+	size_t step = 0;
 	bool log = false;
-	char type = 'x';
 
 	fvalue stepSize() const
 	{
-		return (end-start)/count;
+		fvalue startL = log ? log10(start) : start;
+		fvalue endL = log ? log10(end) : end;
+		return (endL-startL)/(count-1);
+	}
+	fvalue stepValue() const
+	{
+		return at(step);
+	}
+	fvalue at(size_t index) const
+	{
+		assert(index < count);
+		return log ? pow(10, stepSize()*index+start) : stepSize()*index+start;
+	}
+	fvalue operator[](size_t index) const
+	{
+		return at(index);
 	}
 	Range operator*(fvalue in) const
 	{
@@ -41,9 +57,11 @@ public:
 	{
 		return operator*(static_cast<fvalue>(1.0)/in);
 	}
-	Range(fvalue startI, fvalue endI, size_t countI, bool logI = false, char typeI = 'x'): start(startI), end(endI), count(countI), log(logI), type(typeI){}
+	Range(fvalue startI, fvalue endI, size_t countI, bool logI = false): start(startI), end(endI), count(countI), log(logI){}
 	Range() = default;
 	void print(int level) const;
+
+	static std::vector<Range> rangesFromParamString(const std::string& paramStr, size_t count);
 };
 
 bool saveToDisk(const std::vector<DataPoint>& data, std::string fileName);
diff --git a/eisgenerator/finitetr.h b/eisgenerator/finitetr.h
index fbaf35d7f7be703e1d8c254993e2ea3597f8c1da..1febfc8859afad522e9374e2a6420cff7a84c3ef 100644
--- a/eisgenerator/finitetr.h
+++ b/eisgenerator/finitetr.h
@@ -13,14 +13,14 @@ class FiniteTransmitionline: public Componant
 	Componant* subComponant = nullptr;
 
 	static Componant* createTransmitionLine(fvalue c, fvalue r, unsigned int n);
+	void updateValues();
+	void setDefaultParam();
 
 public:
 	FiniteTransmitionline(fvalue c, fvalue r, unsigned int n);
-	FiniteTransmitionline(std::string paramStr);
+	FiniteTransmitionline(std::string paramStr, size_t count = 10);
 	FiniteTransmitionline(const FiniteTransmitionline& in);
 	virtual std::complex<fvalue> execute(fvalue omega) override;
-	virtual std::vector<fvalue> getParam();
-	virtual void setParam(const std::vector<fvalue>& param);
 	virtual size_t paramCount();
 	virtual ~FiniteTransmitionline();
 	virtual char getComponantChar() const override;
diff --git a/eisgenerator/inductor.h b/eisgenerator/inductor.h
index a2634625520fff3c09abfd1da05ec125b0bd0fdd..a98ac937059ea7b5cf4cb9c3a2f1c93beba77670 100644
--- a/eisgenerator/inductor.h
+++ b/eisgenerator/inductor.h
@@ -9,14 +9,10 @@ namespace eis
 
 class Inductor: public Componant
 {
-private:
-	fvalue _L;
 public:
-	Inductor(std::string paramStr);
+	Inductor(std::string paramStr, size_t count = 10);
 	Inductor(fvalue L = 1e-6);
 	virtual std::complex<fvalue> execute(fvalue omega) override;
-	virtual std::vector<fvalue> getParam() override;
-	virtual void setParam(const std::vector<fvalue>& param) override;
 	virtual size_t paramCount() override;
 	virtual char getComponantChar() const override;
 	static constexpr char staticGetComponantChar(){return 'l';}
diff --git a/eisgenerator/model.h b/eisgenerator/model.h
index d5837270d555780987f83e84ed3c86161024eae5..87f283cf967f78797efc525ee68c0c12a334ccbc 100644
--- a/eisgenerator/model.h
+++ b/eisgenerator/model.h
@@ -14,11 +14,11 @@ namespace eis
 class Model
 {
 private:
-	Componant *processBrackets(std::string& str, size_t& bracketCounter);
-	Componant *processBracket(std::string& str);
+	Componant *processBrackets(std::string& str, size_t& bracketCounter, size_t paramSweepCount);
+	Componant *processBracket(std::string& str, size_t paramSweepCount);
 	std::string getParamStr(const std::string& str, size_t index);
 	static void addComponantToFlat(Componant* componant, std::vector<Componant*>* flatComponants);
-	Componant* flatParameterToFlatComponant(size_t parameterIndex);
+	void resolveSteps(int64_t index);
 
 private:
 	Componant *_model = nullptr;
@@ -27,24 +27,16 @@ private:
 	std::vector<Componant*> _flatComponants;
 
 public:
-	Model(const std::string& str);
+	Model(const std::string& str, size_t paramSweepCount = 100);
 	Model(const Model& in);
 	Model& operator=(const Model& in);
 	~Model();
-	DataPoint execute(fvalue omaga, Componant* model);
-	std::vector<DataPoint> executeSweep(const Range& omega, Componant *model = nullptr);
-	bool executeParamSweep(const std::vector<Range>& componantRanges, const Range& omega, std::function<void(std::vector<DataPoint>&, const std::vector<fvalue>&)> dataCb);
-	std::vector<DataPoint> executeParamByIndex(const std::vector<Range>& componantRanges, const Range& omega, size_t index);
-	std::vector<DataPoint> executeParamByIndexC(const std::vector<Range>& componantRanges, const Range& omega, size_t index);
+	DataPoint execute(fvalue omaga, size_t index = 0);
+	std::vector<DataPoint> executeSweep(const Range& omega, size_t index = 0);
 	std::string getModelStr() const;
 	std::vector<Componant*> getFlatComponants(Componant *model = nullptr);
-	std::vector<fvalue> getFlatParameters(Componant *model = nullptr);
-	size_t getFlatParametersCount();
-	bool setFlatParameters(const std::vector<fvalue>& parameters, Componant *model = nullptr);
-	bool checkParameterRanges(const std::vector<eis::Range> ranges, Componant* model = nullptr);
-
-	static std::vector<fvalue> getSweepParamByIndex(const std::vector<Range>& componantRanges, size_t index);
-	static size_t getRequiredStepsForSweeps(const std::vector<Range>& componantRanges);
+	size_t getRequiredStepsForSweeps();
+	bool isParamSweep();
 };
 
 }
diff --git a/eisgenerator/resistor.h b/eisgenerator/resistor.h
index f9d412da40741fe35f7943126aeb623de3c21700..be31d94ce7454cc2c71da3f73090e793efffdda5 100644
--- a/eisgenerator/resistor.h
+++ b/eisgenerator/resistor.h
@@ -7,15 +7,10 @@ namespace eis
 
 class Resistor: public Componant
 {
-private:
-	fvalue _R;
-
 public:
 	Resistor(fvalue r);
-	Resistor(std::string paramStr);
+	Resistor(std::string paramStr, size_t count = 10);
 	virtual std::complex<fvalue> execute(fvalue omega)  override;
-	virtual std::vector<fvalue> getParam() override;
-	virtual void setParam(const std::vector<fvalue>& param) override;
 	virtual size_t paramCount() override;
 	virtual char getComponantChar() const override;
 	static constexpr char staticGetComponantChar(){return 'r';}
diff --git a/eisgenerator/warburg.h b/eisgenerator/warburg.h
index 7fdd8b86bc7bb34161ef8b86256bc756abbc3ddc..ba98b38495730134b33ae40a6a4864a32ea0e623 100644
--- a/eisgenerator/warburg.h
+++ b/eisgenerator/warburg.h
@@ -9,14 +9,10 @@ namespace eis
 
 class Warburg: public Componant
 {
-private:
-	fvalue _A = 2e4;
 public:
-	Warburg(std::string paramStr);
+	Warburg(std::string paramStr, size_t count = 10);
 	Warburg(fvalue a = 2e4);
 	virtual std::complex<fvalue> execute(fvalue omega) override;
-	virtual std::vector<fvalue> getParam() override;
-	virtual void setParam(const std::vector<fvalue>& param) override;
 	virtual size_t paramCount() override;
 	virtual char getComponantChar() const override;
 	static constexpr char staticGetComponantChar(){return 'w';}
diff --git a/eistype.cpp b/eistype.cpp
index c34adfbf2ea28ceb0f5f29e9b67d128d72b3de05..73e3bfa72670de2fec047ce9bb99d12ce072038d 100644
--- a/eistype.cpp
+++ b/eistype.cpp
@@ -1,6 +1,7 @@
 #include "eistype.h"
 #include <fstream>
 
+#include "strops.h"
 #include "log.h"
 
 using namespace eis;
@@ -27,5 +28,44 @@ bool eis::saveToDisk(const std::vector<DataPoint>& data, std::string fileName)
 
 void eis::Range::print(int level) const
 {
-	Log(static_cast<Log::Level>(level))<<"Range for "<<type<<' '<<start<<'-'<<end<<' '<<count<<" steps";
+	Log(static_cast<Log::Level>(level))<<"Range "<<start<<'-'<<end<<' '<<count<<" steps"<<(log ? " Log" : "");
+}
+
+std::vector<Range> eis::Range::rangesFromParamString(const std::string& paramStr, size_t count)
+{
+	std::vector<std::string> tokens = tokenize(paramStr, ',');
+
+	std::vector<Range> ranges(tokens.size());
+	for(size_t i = 0; i < tokens.size(); ++i)
+	{
+		bool log = false;
+		std::string& token = tokens[i];
+		std::vector<std::string> subTokens = tokenize(token, '~');
+
+		if(token.back() == 'l' || token.back() == 'L')
+		{
+			log = true;
+			token.pop_back();
+		}
+
+		try
+		{
+			if(subTokens.size() == 1)
+			{
+				ranges[i] = Range(std::stod(subTokens[0]), std::stod(subTokens[0]), 1, log);
+			}
+			else
+			{
+				ranges[i] = Range(std::stod(subTokens[0]), std::stod(subTokens[1]), count, log);
+				if(subTokens.size() > 2)
+					Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" more that two arguments at range "<<i;
+			}
+
+		}
+		catch(const std::invalid_argument& ia)
+		{
+			Log(Log::WARN)<<"invalid parameter string "<<paramStr;
+		}
+	}
+	return ranges;
 }
diff --git a/finitetr.cpp b/finitetr.cpp
index 726558adada79eeedb7ad33463d4dfa5870d0e2c..29d3586a6b5c2fa3589fbc7ab6a84b42181e27ea 100644
--- a/finitetr.cpp
+++ b/finitetr.cpp
@@ -15,51 +15,51 @@ using namespace eis;
 
 FiniteTransmitionline::FiniteTransmitionline(fvalue c, fvalue r, unsigned int n): _C(c), _R(r), _n(n)
 {
+
 	if(n < 1)
 	{
 		Log(Log::WARN)<<__func__<<" n must be > 0 setting n to 4";
 		_n = 4;
 	}
 
+	ranges.clear();
+	ranges.push_back(Range(_C, _C, 1));
+	ranges.push_back(Range(_R, _R, 1));
+	ranges.push_back(Range(_n, _n, 1));
+
 	subComponant = createTransmitionLine(_C, _R, _n);
 }
 
-FiniteTransmitionline::FiniteTransmitionline(std::string paramStr)
+void FiniteTransmitionline::setDefaultParam()
 {
+	_C = 1e-6;
+	_R = 1000;
+	_n = 4;
+
+	ranges.clear();
+	ranges.push_back(Range(_C, _C, 1));
+	ranges.push_back(Range(_R, _R, 1));
+	ranges.push_back(Range(_n, _n, 1));
+}
 
-	std::vector<std::string> tokens = tokenize(paramStr, ',');
-	if(tokens.size() < paramCount())
-	{
-		Log(Log::WARN)<<"to few parameters in "<<__func__<<" parameter string: "<<paramStr;
-		_C = 1e-6;
-		_R = 1000;
-		_n = 4;
-		if(subComponant)
-				delete subComponant;
-		subComponant = createTransmitionLine(_C, _R, _n);
-		return;
-	}
-	else
+FiniteTransmitionline::FiniteTransmitionline(std::string paramStr, size_t count)
+{
+	ranges = Range::rangesFromParamString(paramStr, count);
+
+	if(ranges.size() != paramCount())
 	{
-		try
-		{
-			_R = std::stod(tokens[0]);
-			_C = std::stod(tokens[1]);
-			_n = std::stod(tokens[2]);
-			if(subComponant)
-				delete subComponant;
-			subComponant = createTransmitionLine(_C, _R, _n);
-		}
-		catch(const std::invalid_argument& ia)
-		{
-			Log(Log::WARN)<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
-			_C = 1e3;
-		}
+		Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" given to "<<__func__<<", will not be applied\n";
+		setDefaultParam();
 	}
+
+	if(subComponant)
+			delete subComponant;
+	subComponant = createTransmitionLine(_C, _R, _n);
 }
 
 FiniteTransmitionline::FiniteTransmitionline(const FiniteTransmitionline& in)
 {
+	ranges = in.ranges;
 	_R = in._R;
 	_C = in._C;
 	_n = in._n;
@@ -72,6 +72,7 @@ std::complex<fvalue> FiniteTransmitionline::execute(fvalue omega)
 {
 	if(subComponant)
 	{
+		updateValues();
 		return subComponant->execute(omega);
 	}
 	else
@@ -81,36 +82,6 @@ std::complex<fvalue> FiniteTransmitionline::execute(fvalue omega)
 	}
 }
 
-std::vector<fvalue> FiniteTransmitionline::getParam()
-{
-	return std::vector<fvalue>({_R, _C, static_cast<fvalue>(_n)});
-}
-
-void FiniteTransmitionline::setParam(const std::vector<fvalue>& param)
-{
-	if(param.size() < paramCount())
-	{
-		Log(Log::WARN)<<"invalid parameter list sent to "<<__func__<<'\n';
-		return;
-	}
-
-	_R = param[0];
-	_C = param[1];
-	_n = param[2];
-
-	if(param[2] < 1)
-	{
-		Log(Log::WARN)<<"invalid parameter list sent to "<<__func__<<" n must be > 1 "<<'\n';
-		return;
-	}
-
-	_n = param[2];
-
-	if(subComponant)
-		delete subComponant;
-	subComponant = createTransmitionLine(_C, _R, _n);
-}
-
 char FiniteTransmitionline::getComponantChar() const
 {
 	return FiniteTransmitionline::staticGetComponantChar();
@@ -146,3 +117,17 @@ FiniteTransmitionline::~FiniteTransmitionline()
 	if(subComponant)
 		delete subComponant;
 }
+
+void FiniteTransmitionline::updateValues()
+{
+	assert(ranges.size() == paramCount());
+	if(ranges[0].stepValue() != _C || ranges[1].stepValue() != _R || static_cast<size_t>(ranges[2].stepValue()) != _n)
+	{
+		_C = ranges[0].stepValue();
+		_R = ranges[2].stepValue();
+		_n = ranges[3].stepValue();
+		if(subComponant)
+			delete subComponant;
+		subComponant = createTransmitionLine(_C, _R, _n);
+	}
+}
diff --git a/inductor.cpp b/inductor.cpp
index 1d0a65604758722d048970d178befa77a8084df0..ec2ea097ba077709d34718b46154d16e80d0cd76 100644
--- a/inductor.cpp
+++ b/inductor.cpp
@@ -2,58 +2,34 @@
 #include "strops.h"
 #include <cstdlib>
 #include <math.h>
+#include <cassert>
 
 #include "log.h"
 
 using namespace eis;
 
-Inductor::Inductor(fvalue L): _L(L)
+Inductor::Inductor(fvalue L)
 {
-
+	ranges.clear();
+	ranges.push_back(Range(L, L, 1));
 }
 
-Inductor::Inductor(std::string paramStr)
+Inductor::Inductor(std::string paramStr, size_t count)
 {
-	std::vector<std::string> tokens = tokenize(paramStr, ',');
-	if(tokens.empty())
-	{
-		Log(Log::WARN)<<"to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n';
-		_L = 1e-6;
-		return;
-	}
-	else
+	ranges = Range::rangesFromParamString(paramStr, count);
+
+	if(ranges.size() != paramCount())
 	{
-		try
-		{
-			_L = std::stod(tokens[0]);
-		}
-		catch(const std::invalid_argument& ia)
-		{
-			Log(Log::WARN)<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
-			_L = 1e3;
-		}
+		Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" given to "<<__func__<<", will not be applied\n";
+		ranges.clear();
+		ranges.push_back(Range(1e-6, 1e-6, 1));
 	}
 }
 
 std::complex<fvalue> Inductor::execute(fvalue omega)
 {
-	return std::complex<fvalue>(0, _L*omega);
-}
-
-std::vector<fvalue> Inductor::getParam()
-{
-	return std::vector<fvalue>({_L});
-}
-
-void Inductor::setParam(const std::vector<fvalue>& param)
-{
-	if(param.empty())
-	{
-		Log(Log::WARN)<<"invalid parameter list sent to "<<__func__<<'\n';
-		return;
-	}
-
-	_L = param[0];
+	assert(ranges.size() == paramCount());
+	return std::complex<fvalue>(0, ranges[0][ranges[0].step]*omega);
 }
 
 size_t Inductor::paramCount()
diff --git a/main.cpp b/main.cpp
index 73f7f2d03ecbd0485c98dd5d6950b132705d7707..2a62c3c1841362744fbe372799d1ae9de0342820 100644
--- a/main.cpp
+++ b/main.cpp
@@ -33,13 +33,11 @@ static void printComponants(eis::Model& model)
 	}
 }
 
-static void runSweep(const Config& config)
+static void runSweep(const Config& config, eis::Model& model)
 {
 	std::vector<eis::DataPoint> results;
 
 	eis::Range omega = config.omegaRange;
-	eis::Model model(config.modelStr);
-	printComponants(model);
 
 	auto start = std::chrono::high_resolution_clock::now();
 	results = model.executeSweep(omega);
@@ -72,72 +70,24 @@ static void runSweep(const Config& config)
 	eis::Log(eis::Log::INFO)<<"time taken: "<<duration.count()<<" us";
 }
 
-std::vector<eis::Range> rangesFromParamString(const std::string& parameterString, size_t modelParamCount, size_t steps)
-{
-	std::vector<std::string> tokens = tokenize(parameterString, ',');
-
-	if(tokens.size() != modelParamCount)
-	{
-		eis::Log(eis::Log::ERROR)<<"Model requires "<<modelParamCount<<" parameters but "<<tokens.size()<<" parameters where provided\n";
-		return std::vector<eis::Range>();
-	}
-
-	std::vector<eis::Range> ranges;
-
-	try
-	{
-		for(const std::string& str : tokens)
-		{
-			std::vector<std::string> subtokens = tokenize(str, '-', '\0', '\0', 'e');
-			if(subtokens.size() > 2)
-			{
-				eis::Log(eis::Log::ERROR)<<"a range requires two numbers only "<<str<<" provides "<<subtokens.size()<<" numbers\n";
-				return std::vector<eis::Range>();
-			}
-			else if(subtokens.size() == 1)
-			{
-				ranges.push_back(eis::Range(std::stod(subtokens[0]), std::stod(subtokens[0]), 1, true));
-			}
-			else
-			{
-				ranges.push_back(eis::Range(std::stod(subtokens[0]), std::stod(subtokens[1]), steps, true));
-			}
-		}
-	}
-	catch (const std::invalid_argument& ia)
-	{
-		eis::Log(eis::Log::ERROR)<<ia.what();
-		return std::vector<eis::Range>();
-	}
-	return ranges;
-}
-
-static void paramSweepCb(std::vector<eis::DataPoint>& data, const std::vector<fvalue>& parameters)
+static void runParamSweep(Config config, eis::Model& model)
 {
-	static size_t i = 0;
-	size_t outputSize = data.size();
-	data = eis::reduceRegion(data);
-	data = eis::rescale(data, outputSize);
-	eis::saveToDisk(data, std::string(PARA_SWEEP_OUTPUT_DIR)+std::string("/")+std::to_string(++i)+".csv");
-	eis::Log(eis::Log::INFO, false)<<'.';
-}
-
-static void runParamSweep(Config config)
-{
-	eis::Model model(config.modelStr);
-
-	std::vector<eis::Range> parameters = rangesFromParamString(config.parameterString, model.getFlatParametersCount(), config.paramSteps);
-	if(parameters.empty())
-		return;
-
-	for(const eis::Range& range : parameters)
-		range.print(eis::Log::INFO);
-
 	eis::Log(eis::Log::INFO)<<"Saving sweep to "<<PARA_SWEEP_OUTPUT_DIR;
 	std::filesystem::create_directory(PARA_SWEEP_OUTPUT_DIR);
 
+	size_t count = model.getRequiredStepsForSweeps();
+	eis::Log(eis::Log::INFO)<<"Executeing "<<count<<" steps";
+
 	auto start = std::chrono::high_resolution_clock::now();
-	model.executeParamSweep(parameters, config.omegaRange, &paramSweepCb);
+	for(size_t i = 0; i < count; ++i)
+	{
+		std::vector<eis::DataPoint> data =  model.executeSweep(config.omegaRange, i);
+		size_t outputSize = data.size();
+		data = eis::reduceRegion(data);
+		data = eis::rescale(data, outputSize);
+		eis::saveToDisk(data, std::string(PARA_SWEEP_OUTPUT_DIR)+std::string("/")+std::to_string(++i)+".csv");
+		eis::Log(eis::Log::INFO, false)<<'.';
+	}
 	auto end = std::chrono::high_resolution_clock::now();
 	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
 	std::cout<<std::endl;
@@ -163,14 +113,13 @@ int main(int argc, char** argv)
 
 	eis::Log(eis::Log::INFO)<<"Using model string: "<<config.modelStr;
 
-	switch(config.mode)
-	{
-		case MODE_SWEEP:
-			runSweep(config);
-			break;
-		case MODE_PARAM_SWEEP:
-			runParamSweep(config);
-			break;
-	}
+	eis::Model model(config.modelStr, config.paramSteps);
+	printComponants(model);
+
+	if(model.isParamSweep())
+		runParamSweep(config, model);
+	else
+		runSweep(config, model);
+
 	return 0;
 }
diff --git a/model.cpp b/model.cpp
index a7a080866eb60062f28f1b72eb3c76fd96428530..02e3a68df03d0d589fb8d8c382dc78479ff3c38b 100644
--- a/model.cpp
+++ b/model.cpp
@@ -15,14 +15,14 @@
 
 using namespace eis;
 
-Componant *Model::processBrackets(std::string& str, size_t& bracketCounter)
+Componant *Model::processBrackets(std::string& str, size_t& bracketCounter, size_t paramSweepCount)
 {
 	size_t bracketStart = deepestBraket(str);
 	Log(Log::DEBUG)<<str<<" bracket start "<<(bracketStart == std::string::npos ? std::string("npos") :  std::to_string(bracketStart));
 
 	if(bracketStart == std::string::npos)
 	{
-		Componant* componant = processBracket(str);
+		Componant* componant = processBracket(str, paramSweepCount);
 		if(!componant)
 			Log(Log::DEBUG)<<"Warning: can not create componant type B for "<<str;
 		return componant;
@@ -37,17 +37,15 @@ Componant *Model::processBrackets(std::string& str, size_t& bracketCounter)
 
 	std::string bracket = str.substr(bracketStart+1, bracketEnd-1-bracketStart);
 
-	Componant* componant = processBracket(bracket);
+	Componant* componant = processBracket(bracket, paramSweepCount);
 	if(!componant)
-	{
 		Log(Log::DEBUG)<<"can not create componant type A for "<<bracket;
-	}
 	_bracketComponants.push_back(componant);
 
 	str.erase(str.begin()+bracketStart, str.begin()+bracketEnd+1);
 	str.insert(str.begin()+bracketStart, bracketCounter+48);
 	++bracketCounter;
-	return processBrackets(str, bracketCounter);
+	return processBrackets(str, bracketCounter, paramSweepCount);
 }
 
 std::string Model::getParamStr(const std::string& str, size_t index)
@@ -64,7 +62,7 @@ std::string Model::getParamStr(const std::string& str, size_t index)
 	return parameterStr;
 }
 
-Componant *Model::processBracket(std::string& str)
+Componant *Model::processBracket(std::string& str, size_t paramSweepCount)
 {
 	Log(Log::DEBUG)<<__func__<<'('<<str<<')';
 	std::vector<std::string> tokens = tokenize(str, '-', '{', '}');
@@ -82,7 +80,7 @@ Componant *Model::processBracket(std::string& str)
 			{
 				case Cap::staticGetComponantChar():
 				{
-					componants.push_back(new Cap(getParamStr(nodeStr, i)));
+					componants.push_back(new Cap(getParamStr(nodeStr, i), paramSweepCount));
 					size_t opposing = opposingBraket(nodeStr, i, '}');
 					if(opposing != std::string::npos)
 						i = opposingBraket(nodeStr, i, '}');
@@ -90,7 +88,7 @@ Componant *Model::processBracket(std::string& str)
 				}
 				case Resistor::staticGetComponantChar():
 				{
-					componants.push_back(new Resistor(getParamStr(nodeStr, i)));
+					componants.push_back(new Resistor(getParamStr(nodeStr, i), paramSweepCount));
 					size_t opposing = opposingBraket(nodeStr, i, '}');
 					if(opposing != std::string::npos)
 						i = opposingBraket(nodeStr, i, '}');
@@ -98,7 +96,7 @@ Componant *Model::processBracket(std::string& str)
 				}
 				case Inductor::staticGetComponantChar():
 				{
-					componants.push_back(new Inductor(getParamStr(nodeStr, i)));
+					componants.push_back(new Inductor(getParamStr(nodeStr, i), paramSweepCount));
 					size_t opposing = opposingBraket(nodeStr, i, '}');
 					if(opposing != std::string::npos)
 						i = opposingBraket(nodeStr, i, '}');
@@ -106,7 +104,7 @@ Componant *Model::processBracket(std::string& str)
 				}
 				case Cpe::staticGetComponantChar():
 				{
-					componants.push_back(new Cpe(getParamStr(nodeStr, i)));
+					componants.push_back(new Cpe(getParamStr(nodeStr, i), paramSweepCount));
 					size_t opposing = opposingBraket(nodeStr, i, '}');
 					if(opposing != std::string::npos)
 						i = opposingBraket(nodeStr, i, '}');
@@ -114,7 +112,7 @@ Componant *Model::processBracket(std::string& str)
 				}
 				case Warburg::staticGetComponantChar():
 				{
-					componants.push_back(new Warburg(getParamStr(nodeStr, i)));
+					componants.push_back(new Warburg(getParamStr(nodeStr, i), paramSweepCount));
 					size_t opposing = opposingBraket(nodeStr, i, '}');
 					if(opposing != std::string::npos)
 						i = opposingBraket(nodeStr, i, '}');
@@ -122,7 +120,7 @@ Componant *Model::processBracket(std::string& str)
 				}
 				case FiniteTransmitionline::staticGetComponantChar():
 				{
-					componants.push_back(new FiniteTransmitionline(getParamStr(nodeStr, i)));
+					componants.push_back(new FiniteTransmitionline(getParamStr(nodeStr, i), paramSweepCount));
 					size_t opposing = opposingBraket(nodeStr, i, '}');
 					if(opposing != std::string::npos)
 						i = opposingBraket(nodeStr, i, '}');
@@ -160,11 +158,11 @@ Componant *Model::processBracket(std::string& str)
 		return nullptr;
 }
 
-Model::Model(const std::string& str): _modelStr(str)
+Model::Model(const std::string& str, size_t paramSweepCount): _modelStr(str)
 {
 	size_t bracketCounter = 0;
 	std::string strCpy(str);
-	_model = processBrackets(strCpy, bracketCounter);
+	_model = processBrackets(strCpy, bracketCounter, paramSweepCount);
 }
 
 Model::Model(const Model& in)
@@ -187,13 +185,11 @@ Model::~Model()
 	delete _model;
 }
 
-DataPoint Model::execute(fvalue omega, Componant* model)
+DataPoint Model::execute(fvalue omega, size_t index)
 {
-	if(!model)
-		model = _model;
-
 	if(_model)
 	{
+		resolveSteps(index);
 		DataPoint dataPoint;
 		dataPoint.omega = omega;
 		dataPoint.im = _model->execute(omega);
@@ -245,168 +241,71 @@ std::vector<Componant*> Model::getFlatComponants(Componant *model)
 	}
 }
 
-std::vector<DataPoint> Model::executeSweep(const Range& omega, Componant* model)
+std::vector<DataPoint> Model::executeSweep(const Range& omega, size_t index)
 {
-	if(!model)
-		model = _model;
-
 	std::vector<DataPoint> results;
 	results.reserve(omega.count);
+	for(size_t i = 0; i < omega.count; ++i)
+		results.push_back(execute(omega[i], index));
 
-	if(!omega.log)
-	{
-		fvalue currOmega = omega.start;
-		fvalue step = (omega.end - omega.start)/(omega.count-1);
-
-		for(size_t i = 0; i < omega.count; ++i)
-		{
-			results.push_back(execute(currOmega, model));
-			currOmega+=step;
-		}
-	}
-	else
-	{
-		fvalue start = log10(omega.start);
-		fvalue end = log10(omega.end);
-		fvalue step = (end-start)/(omega.count-1);
-		fvalue currOmegaL = start;
-
-		for(size_t i = 0; i < omega.count; ++i)
-		{
-			results.push_back(execute(pow(10, currOmegaL), model));
-			currOmegaL+=step;
-		}
-	}
 	return results;
 }
 
-std::vector<DataPoint> Model::executeParamByIndexC(const std::vector<Range>& componantRanges, const Range& omega, size_t index)
+void Model::resolveSteps(int64_t index)
 {
-	std::vector<fvalue> parameters = getSweepParamByIndex(componantRanges, index);
-
-	Componant* model = Componant::copy(_model);
-	setFlatParameters(parameters, model);
-
-	std::vector<DataPoint> data = executeSweep(omega, model);
-
-	delete model;
-
-	return data;
-}
-
-std::vector<DataPoint> Model::executeParamByIndex(const std::vector<Range>& componantRanges, const Range& omega, size_t index)
-{
-	std::vector<fvalue> parameters = getSweepParamByIndex(componantRanges, index);
-	assert(setFlatParameters(parameters));
-
-	return executeSweep(omega);
-}
-
-size_t Model::getRequiredStepsForSweeps(const std::vector<Range>& componantRanges)
-{
-	size_t stepsRequired = 1;
-	for(size_t i = 0; i < componantRanges.size(); ++i)
-		stepsRequired *= componantRanges[i].count;
-	return stepsRequired;
-}
-
-std::vector<fvalue> Model::getSweepParamByIndex(const std::vector<Range>& componantRanges, size_t index)
-{
-	size_t parametersCount = componantRanges.size();
-	std::vector<size_t> parameterIndexies(parametersCount, 0);
-	for(size_t i = 0; i < parametersCount && index > 0; ++i)
+	std::vector<Componant*> componants = getFlatComponants();
+	if(index == 0)
 	{
-		index = i > 0 ? index/componantRanges[i-1].count : index;
-		parameterIndexies[i] = index % componantRanges[i].count;
-		index -= parameterIndexies[i];
+		for(Componant* componant : componants)
+		{
+			for(Range& range :  componant->getParamRanges())
+				range.step = 0;
+		}
+		return;
 	}
 
-	std::vector<fvalue> parameters(parametersCount, 0);
-	for(size_t i = 0; i < parametersCount; ++i)
-		parameters[i] = parameterIndexies[i]*componantRanges[i].stepSize()+componantRanges[i].start;
-	return parameters;
-}
-
-bool Model::executeParamSweep(const std::vector<Range>& componantRanges, const Range& omega,
-                              std::function<void(std::vector<DataPoint>&, const std::vector<fvalue>&)> dataCb)
-{
-	size_t parametersCount = getFlatParametersCount();
-
-	if(!checkParameterRanges(componantRanges))
-		return false;
-
-	size_t stepsRequired = getRequiredStepsForSweeps(componantRanges);
+	assert(static_cast<size_t>(index) < getRequiredStepsForSweeps());
 
-	std::vector<fvalue> currentParam(parametersCount, 0);
-	for(size_t i = 0; i < parametersCount; ++i)
-		currentParam[i] = componantRanges[i].start;
+	std::vector<Range*> flatRanges;
 
-	Log(Log::INFO)<<"Executing sweep. Steps requried: "<<stepsRequired;
-
-	for(size_t i = 0; i < stepsRequired; ++i)
+	for(Componant* componant : componants)
 	{
-		setFlatParameters(getSweepParamByIndex(componantRanges, i));
-		std::vector<DataPoint> result = executeSweep(omega);
-		dataCb(result, currentParam);
+		for(Range& range :  componant->getParamRanges())
+			flatRanges.push_back(&range);
 	}
 
-	return true;
-}
-
-bool Model::setFlatParameters(const std::vector<fvalue>& parameters, Componant* model)
-{
-	if(parameters.size() != getFlatParametersCount())
-		return false;
-
-	if(!model)
-		model = _model;
+	std::vector<size_t> placeMagnitude;
+	placeMagnitude.reserve(flatRanges.size());
 
-	size_t i = 0;
-	for(Componant* componant : getFlatComponants())
+	for(size_t i = 0; i < flatRanges.size(); ++i)
 	{
-		std::vector<fvalue> params;
-		for(size_t j = 0; j < componant->paramCount(); ++j)
-			params.push_back(parameters[i++]);
-		componant->setParam(params);
+		size_t magnitude = 1;
+		for(int64_t j = static_cast<int64_t>(i)-1; j >= 0; --j)
+		{
+			magnitude = magnitude*flatRanges[j]->count;
+		}
+		placeMagnitude.push_back(magnitude);
 	}
 
-	return true;
-}
-
-
-Componant* Model::flatParameterToFlatComponant(size_t parameterIndex)
-{
-	size_t i = 0;
-	for(Componant* componant : getFlatComponants())
+	for(int64_t i = flatRanges.size(); i >= 0 && index > 0; --i)
 	{
-		i += componant->paramCount();
-		if(i > parameterIndex)
-			return componant;
+		flatRanges[i]->step = index/placeMagnitude[i];
+		index = index % placeMagnitude[i];
+		Log(Log::DEBUG)<<placeMagnitude[i]<<'('<<flatRanges[i]->step<<')'<<(i == 0 ? "\n" : " + ");
 	}
-	return nullptr;
 }
 
-std::vector<fvalue> Model::getFlatParameters(Componant *model)
+size_t Model::getRequiredStepsForSweeps()
 {
-	if(!model)
-		model = _model;
-
-	std::vector<fvalue> params;
-	std::vector<Componant*> componants = getFlatComponants(model);
+	size_t stepsRequired = 1;
+	std::vector<Componant*> componants = getFlatComponants();
 	for(Componant* componant : componants)
 	{
-		for(fvalue param : componant->getParam())
-			params.push_back(param);
+		std::vector<Range> ranges = componant->getParamRanges();
+		for(const Range& range : ranges)
+			stepsRequired *= range.count;
 	}
-	return params;
-}
-
-size_t Model::getFlatParametersCount()
-{
-	size_t count = 0;
-	for(Componant* componant : getFlatComponants())
-		count += componant->paramCount();
-	return count;
+	return stepsRequired;
 }
 
 std::string Model::getModelStr() const
@@ -431,53 +330,7 @@ std::string Model::getModelStr() const
 	return output;
 }
 
-bool Model::checkParameterRanges(const std::vector<eis::Range> ranges, Componant* model)
+bool Model::isParamSweep()
 {
-	if(!model)
-		model = _model;
-
-	if(!model)
-	{
-		Log(Log::ERROR)<<"model not ready";
-		return false;
-	}
-
-	size_t parametersCount = getFlatParametersCount();
-	std::vector<Componant*> flatComponants = getFlatComponants(model);
-
-	if(ranges.size() != parametersCount)
-	{
-		Log(Log::ERROR)<<"a parameter range must be provided for eatch componant parameter";
-		return false;
-	}
-
-	for(size_t i = 0; i < parametersCount; ++i)
-	{
-		if(ranges[i].count == 0 || (ranges[i].count < 2 && ranges[i].start != ranges[i].end))
-		{
-			Log(Log::ERROR)<<getModelStr()<<" paramter range must specify at least one paramter point if"
-				<<"one paramer point is specified start and end must be the same";
-			return false;
-		}
-		else if(ranges[i].start > ranges[i].end)
-		{
-			Log(Log::ERROR)<<getModelStr()<<" paramter range end-start must be positive";
-			return false;
-		}
-		else if(ranges[i].type != 'x' && ranges[i].type != flatParameterToFlatComponant(i)->getComponantChar())
-		{
-			Log(Log::ERROR)<<getModelStr()<<" componnant "<<i<<"'s range is of invalid type "
-				<<ranges[i].type<<". expected "<<flatComponants[i]->getComponantChar()<<'\n'
-				<<"Expected order:";
-
-			for(const Componant* componant : flatComponants)
-			{
-				Log(Log::ERROR, false)<<componant->getComponantChar();
-			}
-			std::cout<<std::endl;
-
-			return false;
-		}
-	}
-	return true;
+	return getRequiredStepsForSweeps() != 0;
 }
diff --git a/options.h b/options.h
index 4ffed53033dacdec33c0af552153e23644e1f6a8..065d92b97489376fddc5e5bf2028cd5ea578e462 100644
--- a/options.h
+++ b/options.h
@@ -15,7 +15,6 @@ static struct argp_option options[] =
 {
   {"verbose",   'v', 0,      0,  "Show debug messages" },
   {"quiet",     'q', 0,      0,  "only output data" },
-  {"param",     'p', "[STRING]",      0,  "select parameter sweep mode" },
   {"param",     's', "[COUNT]",      0,  "parameter sweep steps" },
   {"model",      'm', "[STRING]",    0,  "set model string" },
   {"omega",      'o', "[START-END]", 0,  "set omega range" },
@@ -38,18 +37,10 @@ enum
 	INPUT_TYPE_UNKOWN
 };
 
-enum
-{
-	MODE_SWEEP = 0,
-	MODE_PARAM_SWEEP
-};
-
 struct Config
 {
 	std::string modelStr = "c{1e-6}r{1e3}-r{1e3}";
-	unsigned int mode = MODE_SWEEP;
 	int inputType = INPUT_TYPE_EIS;
-	std::string parameterString;
 	size_t paramSteps = 10;
 	eis::Range omegaRange;
 	bool normalize = false;
@@ -89,10 +80,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	case 's':
 		config->paramSteps = std::stod(arg);
 		break;
-	case 'p':
-		config->mode = MODE_PARAM_SWEEP;
-		config->parameterString.assign(arg);
-		break;
 	case 'm':
 		config->modelStr.assign(arg);
 		break;
diff --git a/resistor.cpp b/resistor.cpp
index 8784285393f3796bd4041e17b356e12ca48519a6..7523b9ccac5e5d0f351f469ded8cccdc8229e10b 100644
--- a/resistor.cpp
+++ b/resistor.cpp
@@ -2,57 +2,35 @@
 #include "strops.h"
 #include <vector>
 #include <math.h>
+#include <cassert>
 
 #include "log.h"
 
 using namespace eis;
 
-Resistor::Resistor(fvalue r): _R(r)
-{}
+Resistor::Resistor(fvalue r)
+{
+	ranges.clear();
+	ranges.push_back(Range(r, r, 1));
+}
 
-Resistor::Resistor(std::string paramStr)
+Resistor::Resistor(std::string paramStr, size_t count)
 {
-	std::vector<std::string> tokens = tokenize(paramStr, ',');
-	if(tokens.empty())
-	{
-		Log(Log::WARN)<<"to few parameters in "<<__func__<<" parameter string: "<<paramStr;
-		_R = 1e3;
-		return;
-	}
-	else
+	ranges = Range::rangesFromParamString(paramStr, count);
+
+	if(ranges.size() != paramCount())
 	{
-		try
-		{
-			_R = std::stod(tokens[0]);
-		}
-		catch(const std::invalid_argument& ia)
-		{
-			Log(Log::WARN)<<"can't parse parameter in "<<__func__<<" parameter: "<<tokens[0];
-			_R = 1e3;
-		}
+		Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" given to "<<__func__<<", will not be applied\n";
+		ranges.clear();
+		ranges.push_back(Range(1e3, 1e3, 1));
 	}
 }
 
 std::complex<fvalue> Resistor::execute(fvalue omega)
 {
 	(void)omega;
-	return std::complex<fvalue>(_R, 0);
-}
-
-std::vector<fvalue> Resistor::getParam()
-{
-	return std::vector<fvalue>({_R});
-}
-
-void Resistor::setParam(const std::vector<fvalue>& param)
-{
-	if(param.empty())
-	{
-		Log(Log::WARN)<<"invalid parameter list sent to "<<__func__;
-		return;
-	}
-
-	_R = param[0];
+	assert(ranges.size() == paramCount());
+	return std::complex<fvalue>(ranges[0][ranges[0].step], 0);
 }
 
 size_t Resistor::paramCount()
diff --git a/test.cpp b/test.cpp
index 1cbacdcb027e16ea651c563ef51e0ab72d10e3f9..8d4460d4cbe8f2af3252a12121fbdb24a91ccbdb 100644
--- a/test.cpp
+++ b/test.cpp
@@ -119,19 +119,16 @@ void sweepCb(std::vector<eis::DataPoint>& data, const std::vector<fvalue>& param
 void runSweep()
 {
 	eis::Log(eis::Log::INFO)<<__func__;
-	std::string modelStr("w{20e3}p{1e-7, 0.9}");
+	std::string modelStr("w{1e3~50e3}p{20e-7~1e-7, 0.7~0.9}");
 
 	eis::Model model(modelStr);
 
-	std::vector<eis::Range> parameters;
-	parameters.push_back(eis::Range(1e3, 50e3, 100));
-	parameters.push_back(eis::Range(1e-7, 20e-7, 100));
-	parameters.push_back(eis::Range(0.7, 1.2, 100));
-
 	eis::Range omega(0, 1e6, 25);
 
 	auto start = std::chrono::high_resolution_clock::now();
-	model.executeParamSweep(parameters, omega, &sweepCb);
+	size_t len = model.getRequiredStepsForSweeps();
+	for(size_t i = 0; i < len; ++len)
+		model.executeSweep(omega, i);
 	auto end = std::chrono::high_resolution_clock::now();
 	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
 	std::cout<<std::endl;
@@ -139,31 +136,6 @@ void runSweep()
 	eis::Log(eis::Log::INFO)<<"time taken: "<<duration.count()<<" ms";
 }
 
-void runSweepByIndex()
-{
-	eis::Log(eis::Log::INFO)<<__func__;
-	std::string modelStr("w{20e3}p{1e-7, 0.9}");
-
-	eis::Model model(modelStr);
-
-	std::vector<eis::Range> parameters;
-	parameters.push_back(eis::Range(1e3, 50e3, 100));
-	parameters.push_back(eis::Range(1e-7, 20e-7, 100));
-	parameters.push_back(eis::Range(0.7, 1.2, 100));
-	eis::Range omega(0, 1e6, 25);
-
-	auto start = std::chrono::high_resolution_clock::now();
-	std::vector<eis::DataPoint> results = model.executeParamByIndex(parameters, omega, 0);
-	auto end = std::chrono::high_resolution_clock::now();
-	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
-
-	printComponants(model);
-
-	for(const eis::DataPoint& res : results)
-		eis::Log(eis::Log::INFO)<<"omega: "<<res.omega<<" real = "<<res.im.real()<<" im = "<<res.im.imag();
-	eis::Log(eis::Log::INFO)<<"time taken: "<<duration.count()<<" ms";
-}
-
 bool runRescale()
 {
 	std::cout<<__func__<<'\n';
@@ -245,49 +217,15 @@ inline void filterData(std::vector<eis::DataPoint>& data, size_t outputSize)
 	data = eis::rescale(data, outputSize/2);
 }
 
-std::vector<eis::DataPoint> getControll(size_t i, size_t* size = nullptr)
-{
-	eis::Model model("t{1,2,3}");
-	std::vector<eis::Range> modelRange;
-	modelRange.push_back(eis::Range(1e3, 1e4, 40, true, 't'));
-	modelRange.push_back(eis::Range(1e-6, 1e-5, 40, true, 't'));
-	modelRange.push_back(eis::Range(5, 5, 0, true, 't'));
-	eis::Range omega(10, 1e6, 100/2, true);
-	std::vector<eis::DataPoint> data = model.executeParamByIndex(modelRange, omega, i);
-	filterData(data, 100);
-	//data = torchToEis(eisToTorch(data));
-	if(size)
-		*size = eis::Model::getRequiredStepsForSweeps(modelRange);
-	return data;
-}
-
-void testExport()
-{
-
-	size_t rangeSteps;
-	getControll(0, &rangeSteps);
-	std::cout<<"need "<<rangeSteps<<" steps\n";
-	for(size_t i = 0; i < rangeSteps; ++i)
-	{
-		std::vector<eis::DataPoint> controll = getControll(i);
-
-		eis::saveToDisk(controll, std::string("./controll")+std::string("/")+std::to_string(++i)+".csv");
-		eis::Log(eis::Log::INFO,false)<<'.';
-	}
-	std::cout<<std::endl;
-}
-
 int main(int argc, char** argv)
 {
-	/*eis::Log::headers = true;
+	eis::Log::headers = true;
 	eis::Log::level = eis::Log::INFO;
 	runSingle();
-	runSweepByIndex();
 	runSweep();
 	runRescale();
 	runNormalize();
 	runEraseSingularities();
-	runReduce();*/
-	testExport();
+	runReduce();
 	return 0;
 }
diff --git a/warburg.cpp b/warburg.cpp
index 76aa7dffcc008557dd4982d4454f9df1f95b612a..a632e1964a3beb8b041361ed86734312be4ca18c 100644
--- a/warburg.cpp
+++ b/warburg.cpp
@@ -2,59 +2,37 @@
 #include "strops.h"
 #include <cstdlib>
 #include <math.h>
+#include <cassert>
 
 #include "log.h"
 
 using namespace eis;
 
-Warburg::Warburg(fvalue a): _A(a)
+Warburg::Warburg(fvalue a)
 {
-
+	ranges.clear();
+	ranges.push_back(Range(a, a, 1));
 }
 
-Warburg::Warburg(std::string paramStr)
+Warburg::Warburg(std::string paramStr, size_t count)
 {
-	std::vector<std::string> tokens = tokenize(paramStr, ',');
-	if(tokens.size() < 1)
-	{
-		Log(Log::WARN)<<"to few parameters in "<<__func__<<" parameter string: "<<paramStr;
-		return;
-	}
-	else
+	ranges = Range::rangesFromParamString(paramStr, count);
+
+	if(ranges.size() != paramCount())
 	{
-		try
-		{
-			_A = std::stod(tokens[0]);
-		}
-		catch(const std::invalid_argument& ia)
-		{
-			Log(Log::WARN)<<"can't parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
-		}
+		Log(Log::WARN)<<"invalid parameter string "<<paramStr<<" given to "<<__func__<<", will not be applied\n";
+		ranges.clear();
+		ranges.push_back(Range(2e4, 2e4, 1));
 	}
 }
 
 std::complex<fvalue> Warburg::execute(fvalue omega)
 {
-	fvalue N = _A/(sqrt(omega));
+	assert(ranges.size() == paramCount());
+	fvalue N = ranges[0][ranges[0].step]/(sqrt(omega));
 	return std::complex<fvalue>(N, 0-N);
 }
 
-std::vector<fvalue> Warburg::getParam()
-{
-	return std::vector<fvalue>({_A});
-}
-
-void Warburg::setParam(const std::vector<fvalue>& param)
-{
-	if(param.size() != paramCount())
-	{
-		Log(Log::WARN)<<"Warning: invalid parameter list sent to "<<__func__<<'\n';
-		return;
-	}
-
-	_A = param[0];
-}
-
 size_t Warburg::paramCount()
 {
 	return 1;