3 changes: 1 addition & 2 deletions pyKst/pykst.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
try:
from PyQt4 import QtNetwork, QtGui
except ImportError as err2:
print "ImportError: {} and {}. One of the two is required.".format(err1, err2)
sys.exit()
raise ImportError("{} and {}. One of the two is required.".format(err1, err2))

QtGui.QApplication([""])

Expand Down
25 changes: 13 additions & 12 deletions src/libkst/generatedvector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ ScriptInterface* GeneratedVector::createScriptInterface() {

void GeneratedVector::save(QXmlStreamWriter &s) {
s.writeStartElement("generatedvector");
s.writeAttribute("first", QString::number(value(0)));
s.writeAttribute("last", QString::number(value(length()-1)));
s.writeAttribute("min", QString::number(min()));
s.writeAttribute("max", QString::number(max()));
s.writeAttribute("count", QString::number(length()));
Expand All @@ -61,24 +63,23 @@ void GeneratedVector::changeRange(double x0, double x1, int n) {
if (n != length()) {
resize(n, false);
}
if (x0 > x1) {
double tx;
tx = x0;
x0 = x1;
x1 = tx;
} else if (x0 == x1) {
x1 = x0 + 0.1;
}

for (int i = 0; i < n; i++) {
_v_raw[i] = x0 + double(i) * (x1 - x0) / double(n - 1);
}

_min = x0;
_max = x1;
if (x0 < x1) {
_min = x0;
_max = x1;
} else {
_min = x1;
_max = x0;
}

_scalars["min"]->setValue(x0);
_scalars["max"]->setValue(x1);
_scalars["min"]->setValue(_min);
_scalars["max"]->setValue(_max);
_scalars["first"]->setValue(x0);
_scalars["last"]->setValue(x1);

_numNew = length();
registerChange();
Expand Down
14 changes: 10 additions & 4 deletions src/libkst/vectorfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ GeneratedVectorFactory::~GeneratedVectorFactory() {


PrimitivePtr GeneratedVectorFactory::generatePrimitive(ObjectStore *store, QXmlStreamReader& xml) {
double min=-1.0, max=1.0;
double first=-1.0, last=1.0;
int count=0;
QString descriptiveName;

Expand All @@ -109,8 +109,14 @@ PrimitivePtr GeneratedVectorFactory::generatePrimitive(ObjectStore *store, QXmlS
if (xml.isStartElement()) {
if (n == GeneratedVector::staticTypeTag) {
QXmlStreamAttributes attrs = xml.attributes();
min = attrs.value("min").toString().toDouble();
max = attrs.value("max").toString().toDouble();
if (attrs.value("first").isEmpty()) {
// Legacy: assume the generated vector is increasing
first = attrs.value("min").toString().toDouble();
last = attrs.value("max").toString().toDouble();
} else {
first = attrs.value("first").toString().toDouble();
last = attrs.value("last").toString().toDouble();
}
count = attrs.value("count").toString().toInt();
if (attrs.value("descriptiveNameIsManual").toString() == "true") {
descriptiveName = attrs.value("descriptiveName").toString();
Expand All @@ -135,7 +141,7 @@ PrimitivePtr GeneratedVectorFactory::generatePrimitive(ObjectStore *store, QXmlS
}

GeneratedVectorPtr vector = store->createObject<GeneratedVector>();
vector->changeRange(min, max, count);
vector->changeRange(first, last, count);
vector->setDescriptiveName(descriptiveName);

vector->writeLock();
Expand Down
8 changes: 4 additions & 4 deletions src/libkstapp/vectordialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ void VectorDialog::configureTab(ObjectPtr vector) {
if (!vector) {
_vectorTab->dataRange()->loadWidgetDefaults();
_vectorTab->setFile(dialogDefaults().value("vector/datasource",_vectorTab->file()).toString());
_vectorTab->setFrom(dialogDefaults().value("genVector/min",-10).toInt());
_vectorTab->setTo(dialogDefaults().value("genVector/max",10).toInt());
_vectorTab->setFrom(dialogDefaults().value("genVector/first",-10).toInt());
_vectorTab->setTo(dialogDefaults().value("genVector/last",10).toInt());
_vectorTab->setNumberOfSamples(dialogDefaults().value("genVector/length",1000).toInt());
_vectorTab->setVectorMode((VectorTab::VectorMode)dialogDefaults().value("genVector/vectorType",VectorTab::GeneratedVector).toInt()); // FIXME: should be sticky
} else if (DataVectorPtr dataVector = kst_cast<DataVector>(vector)) {
Expand Down Expand Up @@ -421,8 +421,8 @@ void VectorDialog::configureTab(ObjectPtr vector) {
}
} else if (GeneratedVectorPtr generatedVector = kst_cast<GeneratedVector>(vector)) {
_vectorTab->setVectorMode(VectorTab::GeneratedVector);
_vectorTab->setFrom(generatedVector->min());
_vectorTab->setTo(generatedVector->max());
_vectorTab->setFrom(generatedVector->value(0));
_vectorTab->setTo(generatedVector->value(generatedVector->length()-1));
_vectorTab->setNumberOfSamples(generatedVector->length());
_vectorTab->hideDataOptions();
if (_editMultipleWidget) {
Expand Down
6 changes: 3 additions & 3 deletions src/libkstmath/histogram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,14 @@ void Histogram::internalUpdate() {
break;
}

_bVector->setLabelInfo(_inputVectors[RAWVECTOR]->labelInfo());

label_info.quantity.clear();
label_info.units.clear();
_bVector->setLabelInfo(_inputVectors[RAWVECTOR]->labelInfo());
label_info.name = tr( "Histogram of %1").arg(_bVector->labelInfo().name);
label_info.file = _bVector->labelInfo().file;

_hVector->setTitleInfo(label_info);
_hVector->setLabelInfo(label_info);


double *bins = _bVector->raw_V_ptr();
double *hist = _hVector->raw_V_ptr();
Expand Down
1 change: 0 additions & 1 deletion src/plugins/filters/flag/filterflag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ class ConfigWidgetFilterFlagPlugin : public Kst::DataObjectConfigWidget, public

virtual bool configurePropertiesFromXml(Kst::ObjectStore *store, QXmlStreamAttributes& attrs) {
Q_UNUSED(store);
Q_UNUSED(attrs);

bool validTag = true;

Expand Down
165 changes: 132 additions & 33 deletions src/plugins/fits/exponential_unweighted/fitexponential_unweighted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,45 +161,141 @@ void FitExponentialUnweightedSource::setupOutputs() {
}


void function_initial_estimate( const double* pdX, const double* pdY, int iLength, double* pdParameterEstimates ) {
Q_UNUSED( pdX )
Q_UNUSED( pdY )
Q_UNUSED( iLength )

pdParameterEstimates[0] = 1.0;
pdParameterEstimates[1] = 0.0;
pdParameterEstimates[2] = 0.0;
double _X0 = 0; // this use of a global is a hack to inject the first sample into the function.

void swapDouble(double *A, double *B) {
double C;

C = *A;
*A = *B;
*B = C;
}

void function_initial_estimate( const double x[], const double y[], int npts, double P0[] ) {
Q_UNUSED( x )
Q_UNUSED( y )
Q_UNUSED( npts )

_X0 = x[0];

// determine the signs of the terms.
// get the average of the first 5%, last 5% and middle 5% of points
int n_ave = npts/20;
if (n_ave < 1) n_ave = 1;
if (n_ave > 100) n_ave = 100;

double y0 = 0;
double x0 = 0;
double x1 = 0;
double y1 = 0;
double x2 = 0;
double y2 = 0;
int d1 = npts/2 - n_ave/2;
int d2 = npts-n_ave;

if ((d1 + n_ave > npts) || (d2 + n_ave > npts)) { // bail if not enough points.
P0[0] = 1.0;
P0[1] = 0.0;
P0[2] = 0.0;
return;
}

double function_calculate( double dX, double* pdParameters ) {
double dScale = pdParameters[0];
double dLambda = pdParameters[1];
double dOffset = pdParameters[2];
double dY;
for (int i=0; i<n_ave; i++) {
x0+=x[i];
y0+=y[i];
x1+=x[i+d1];
y1+=y[i+d1];
x2+=x[i+d2];
y2+=y[i+d2];
}
x0 /= (double)n_ave;
y0 /= (double)n_ave;
x1 /= (double)n_ave;
y1 /= (double)n_ave;
x2 /= (double)n_ave;
y2 /= (double)n_ave;

// Make sure x0, x1, x2 are monotonic.
if (x2 > x0) {
if (x1 > x2) {
swapDouble(&x1, &x2);
swapDouble(&y1, &y2);
}
if (x1 < x0) {
swapDouble(&x1, &x0);
swapDouble(&y1, &y0);
}
} else {
if (x1 < x2) {
swapDouble(&x1, &x2);
swapDouble(&y1, &y2);
}
if (x1 > x0) {
swapDouble(&x1, &x0);
swapDouble(&y1, &y0);
}
}

dY = ( dScale * exp( -dLambda * dX ) ) + dOffset;
if ((x1 == x0) || (x2 == x0) || (x1 == x2)) { // bail if no x range
P0[0] = 1.0;
P0[1] = 0.0;
P0[2] = 0.0;
return;
}

return dY;
P0[0] = fabs(y2 - y0)/M_E;
P0[1] = M_E/fabs(x2 - x0);
P0[2] = y0;

double m = (y2 - y0)/(x2 - x0);
if (m > 0) { // rising
if ((x1-x0)*m + y0 > y1) { // neg curvature +A, +B
//P0[0] *= -1;
//P0[1] *= -1.0;
} else { // -A, -B
P0[0] *= -1;
P0[1] *= -1.0;
}
} else { // falling
if ((x1-x0)*m + y0 > y1) { // Curving down +A, -B
//P0[0] *= -1;
P0[1] *= -1.0;
} else { // -A, +B
P0[0] *= -1;
//P0[1] *= -1.0;
}
}

fflush(stdout);
}


void function_derivative( double dX, double* pdParameters, double* pdDerivatives ) {
double dScale = pdParameters[0];
double dLambda = pdParameters[1];
double dExp;
double ddScale;
double ddLambda;
double ddOffset;
double function_calculate( double x, double* P ) {
double A = P[0];
double B = P[1];
double C = P[2];
double y;

dExp = exp( -dLambda * dX );
ddScale = dExp;
ddLambda = -dX * dScale * dExp;
ddOffset = 1.0;
y = ( A*exp( B*(x - _X0) ) ) + C;

return y;
}


void function_derivative( double x, double* P, double* dFdP ) {
double A = P[0];
double B = P[1];
double exp_BxXo;

// dFdA = exp(b*(x-_X0)
// dFdB = A*(x-_X0)*exp(b*(x-_X0))

exp_BxXo = exp( B * (x-_X0) );

dFdP[0] = exp_BxXo;
dFdP[1] = (x-_X0) * A * exp_BxXo;
dFdP[2] = 1.0;

pdDerivatives[0] = ddScale;
pdDerivatives[1] = ddLambda;
pdDerivatives[2] = ddOffset;
}


Expand All @@ -214,7 +310,10 @@ bool FitExponentialUnweightedSource::algorithm() {
Kst::ScalarPtr outputScalar = _outputScalars[SCALAR_OUT];

Kst::LabelInfo label_info = inputVectorY->labelInfo();
label_info.name = tr("Exponential Fit to %1").arg(label_info.name);

_X0 = inputVectorX->noNanValue()[0];

label_info.name = tr("a e^{-b(x-x_o)} + c fit to %1").arg(label_info.name);
outputVectorYFitted->setLabelInfo(label_info);

label_info.name = tr("Exponential Fit Residuals");
Expand Down Expand Up @@ -286,13 +385,13 @@ QString FitExponentialUnweightedSource::parameterName(int index) const {
QString parameter;
switch (index) {
case 0:
parameter = "Scale";
parameter = "a";
break;
case 1:
parameter = "Lambda";
parameter = "b";
break;
case 2:
parameter = "Offset";
parameter = "c";
break;
}

Expand Down
Loading