/* * when the original gate vertices are at the threshold * it is likely that the gates were truncated in flowJo xml * currently what we can do is to extend it to the real data range to avoid losing * the data points that are below this theshold range * to cut data range) */ void polygonGate::extend(flowData & fdata,float extend_val){ string x=param.xName(); string y=param.yName(); valarray<double> xdata(fdata.subset(x)); valarray<double> ydata(fdata.subset(y)); vector<coordinate> v=param.getVertices(); /* * get R_min */ double xMin=xdata.min(); double yMin=ydata.min(); for(unsigned i=0;i<v.size();i++) { if(v.at(i).x<=extend_val) { if(g_loglevel>=POPULATION_LEVEL) COUT <<"extending "<<x<<"from "<<v.at(i).x<<" to :"<<xMin<<endl; v.at(i).x=xMin; } if(v.at(i).y<=extend_val) { if(g_loglevel>=POPULATION_LEVEL) COUT <<"extending "<<y<<"from "<<v.at(i).y<<" to :"<<yMin<<endl; v.at(i).y=yMin; } } param.setVertices(v); }
//makePlot created a plot. We now update its data. void MainWindow::refreshPlot(int *x, int *y, int len, uint8_t plot_index) { //From array to QVector: QVector<double> xdata(len), ydata(len); qCopy(x, x+len, xdata.begin()); qCopy(y, y+len, ydata.begin()); ui->customPlot->graph(plot_index)->setData(xdata, ydata); //ToDo: Modify this code to take the max of all curves! //In Automatic mode we constantly adjust the axis: if(ui->radioButtonXAuto->isChecked()) { array_minmax(x, len, &plot_xmin, &plot_xmax); ui->customPlot->xAxis->setRange(plot_xmin, plot_xmax); ui->plot_xmin_lineEdit->setText(QString::number(plot_xmin)); ui->plot_xmax_lineEdit->setText(QString::number(plot_xmax)); } if(ui->radioButtonYAuto->isChecked()) { array_minmax(y, len, &plot_ymin, &plot_ymax); ui->customPlot->yAxis->setRange(plot_ymin-10, plot_ymax+10); ui->plot_ymin_lineEdit->setText(QString::number(plot_ymin)); ui->plot_ymax_lineEdit->setText(QString::number(plot_ymax)); } ui->customPlot->replot(); }
int run_vanilla_nolemma(unsigned epochs, float alpha){ //Data set (Ratnaparkhi's 94 RRR data set) vector<string> ydict; vector<string> xdict; PPADataEncoder data_set("PPAttachData/training"); data_set.add_data("PPAttachData/devset"); data_set.add_data("PPAttachData/test"); data_set.getYdictionary(ydict); data_set.getXdictionary(xdict); //External Word vectors Word2vec w2v; vector<string> wvdict; af::array w2v_embeddings; w2v.load_dictionary("PPAttachData/embeddings/deps.words"); w2v.filter(xdict); //training set data_set.clear(); data_set.add_data("PPAttachData/training"); data_set.getXdictionary(xdict); //build network cerr << "building network"<<endl; SymbolicFeedForwardNetwork<string,string> net; net.set_output_layer("loss",new SoftMaxLoss<string>(ydict)); net.add_layer("top",new LinearLayer()); net.add_layer("hidden",new ReLUActivation(400)); net.add_layer("A",new LinearLayer()); net.add_input_layer("lookupA",new LinearLookup<string>(w2v.get_keys(),w2v.get_values(),data_set.x_vocab_size(),true)); net.connect_layers("loss","top"); net.connect_layers("top","hidden"); net.connect_layers("hidden","A"); net.connect_layers("A","lookupA"); vector<string> ydata; vector<vector<string>> xdata(1,vector<string>()); data_set.getYdata(ydata); data_set.getXdata(xdata[0]); net.set_batch_data(ydata,xdata); net.train_all(ydata,xdata,epochs,100,alpha,true,epochs/2);//10 epochs, batch size= 100,alpha=0.01, Adagrad=On, start averaging at 50th epoch PPADataEncoder dev_set("PPAttachData/devset"); dev_set.getYdata(ydata); dev_set.getXdata(xdata[0]); float dev_acc = net.eval_avg(ydata,xdata); cout << "dev acc = " << dev_acc << endl; PPADataEncoder test_set("PPAttachData/test"); test_set.getYdata(ydata); test_set.getXdata(xdata[0]); float test_acc = net.eval_avg(ydata,xdata); cout << "test acc = " << test_acc << endl; return 0; }
void RateStateSimWindow::recalc(void) { std::vector<std::vector<realtype> > results; double time_max = 200, time_step = 0.01; RSParams params(NBLOCKS, NEQ, NPARAMS, time_step, time_max); unsigned int i, npoints; double xi, vi, hi; std::cerr << param_a << " " << param_b << " " << param_k << " " << param_r << " " << param_w << std::endl; for (i=0;i<params.num_blocks();++i) { params.param(i, A_PARAM) = RCONST(param_a); params.param(i, B_PARAM) = RCONST(param_b); params.param(i, K_PARAM) = RCONST(param_k); params.param(i, R_PARAM) = RCONST(param_r); params.param(i, W_PARAM) = RCONST(param_w); params.init_val(i, EQ_X) = RCONST(-10.0); params.init_val(i, EQ_V) = RCONST(1.0); params.init_val(i, EQ_H) = RCONST(1.0); } run_rate_state_sim(results, params); npoints = results.size(); QVector<QPointF> xdata(npoints), vdata(npoints), hdata(npoints), fdata(npoints), dp_data(npoints); double force_integral=0, old_t=0; for (i=0;i<results.size();++i) { xi = results[i][1]; vi = results[i][2]; hi = results[i][3]; xdata[i] = QPointF(results[i][0], xi); vdata[i] = QPointF(results[i][0], vi); hdata[i] = QPointF(results[i][0], hi); fdata[i] = QPointF(results[i][0], F(0, vi, hi, params)); dp_data[i] = QPointF(results[i][0], results[i][0]); force_integral += (results[i][0]-old_t)*F(0, vi, hi, params); old_t = results[i][0]; } force_integral /= (results.size()/(time_step*time_max)); //std::cerr << force_integral << std::endl; position_data->setData(new QwtPointSeriesData(xdata)); velocity_data->setData(new QwtPointSeriesData(vdata)); theta_data->setData(new QwtPointSeriesData(hdata)); force_data->setData(new QwtPointSeriesData(fdata)); driver_data->setData(new QwtPointSeriesData(dp_data)); position_plot->replot(); velocity_plot->replot(); theta_plot->replot(); force_plot->replot(); }
vector<bool> rectGate::gating(flowData & fdata){ vector<coordinate> vertices=param.getVertices(); unsigned nVertex=vertices.size(); if(nVertex!=2) throw(domain_error("invalid number of vertices for rectgate!")); string x=param.xName(); string y=param.yName(); valarray<double> xdata(fdata.subset(x)); valarray<double> ydata(fdata.subset(y)); unsigned nEvents=xdata.size(); //init the indices vector<bool> ind(nEvents); /* * actual gating */ for(unsigned i=0;i<nEvents;i++) { bool inX,inY; double xMin=vertices.at(0).x; double yMin=vertices.at(0).y; double xMax=vertices.at(1).x; double yMax=vertices.at(1).y; if(xMin>xMax||yMin>yMax) throw(domain_error("invalid vertices for rectgate!")); inX=xdata[i]<=xMax&&xdata[i]>=xMin; inY=ydata[i]<=yMax&&ydata[i]>=yMin; ind[i]=inX&&inY; } if(isNegate()) ind.flip(); return ind; }
/* * translated from flowCore::%in% method for ellipsoidGate */ vector<bool> ellipseGate::gating(flowData & fdata){ // get data valarray<double> xdata(fdata.subset(param.xName())); valarray<double> ydata(fdata.subset(param.yName())); //center the data xdata = xdata - mu.x; ydata = ydata - mu.y; //inverse the cov matrix /* * | a,b | | c,d | --> | aa, bb | | cc, dd | */ double a , b, c, d; a = cov.at(0).x; b = cov.at(0).y; c = cov.at(1).x; d = cov.at(1).y; double det = a* d - b* c; double aa, bb, cc, dd; aa = d/det; bb = -b/det; cc = -c/det; dd = a/det; // if inside of the ellipse unsigned nEvents=xdata.size(); vector<bool> res (nEvents); for(unsigned i =0;i<nEvents;i++){ double x = xdata[i]; double y = ydata[i]; res[i] = (x * x * aa + x* y * cc + x* y * bb + y * y * dd) <= pow(dist, 2); } return res; }
/****************************************************************************** * Plots the data computed by the modifier. ******************************************************************************/ void BinAndReduceModifierEditor::plotData() { BinAndReduceModifier* modifier = static_object_cast<BinAndReduceModifier>(editObject()); if(!modifier) return; int binDataSizeX = std::max(1, modifier->numberOfBinsX()); int binDataSizeY = std::max(1, modifier->numberOfBinsY()); if (modifier->is1D()) binDataSizeY = 1; size_t binDataSize = binDataSizeX*binDataSizeY; if (modifier->is1D()) { // If previous plot was a color map, delete and create graph. if (!_averagesGraph) { if (_averagesColorMap) { _averagesPlot->removePlottable(_averagesColorMap); _averagesColorMap = nullptr; } _averagesGraph = _averagesPlot->addGraph(); } _averagesPlot->setInteraction(QCP::iRangeDrag, true); _averagesPlot->axisRect()->setRangeDrag(Qt::Vertical); _averagesPlot->setInteraction(QCP::iRangeZoom, true); _averagesPlot->axisRect()->setRangeZoom(Qt::Vertical); if(modifier->firstDerivative()) { _averagesPlot->yAxis->setLabel("d( "+modifier->sourceProperty().name()+" )/d( Position )"); } else { _averagesPlot->yAxis->setLabel(modifier->sourceProperty().name()); } if(modifier->binData().empty()) return; QVector<double> xdata(binDataSize+2); QVector<double> ydata(binDataSize+2); double binSize = ( modifier->xAxisRangeEnd() - modifier->xAxisRangeStart() ) / binDataSize; for(int i = 0; i < binDataSize; i++) { xdata[i+1] = binSize * ((double)i + 0.5) + modifier->xAxisRangeStart(); ydata[i+1] = modifier->binData()[i]; } xdata.front() = modifier->xAxisRangeStart(); ydata.front() = modifier->binData().front(); xdata.back() = modifier->xAxisRangeEnd(); ydata.back() = modifier->binData().back(); _averagesPlot->graph()->setLineStyle(QCPGraph::lsStepCenter); _averagesPlot->graph()->setData(xdata, ydata); // Check if range is already correct, because setRange emits the rangeChanged signal // which is to be avoided if the range is not determined automatically. _rangeUpdate = false; _averagesPlot->xAxis->setRange(modifier->xAxisRangeStart(), modifier->xAxisRangeEnd()); _averagesPlot->yAxis->setRange(modifier->propertyAxisRangeStart(), modifier->propertyAxisRangeEnd()); _rangeUpdate = true; } else { // If previous plot was a graph, delete and create color map. if (!_averagesColorMap) { if (_averagesGraph) { _averagesPlot->removeGraph(_averagesGraph); _averagesGraph = nullptr; } _averagesColorMap = new QCPColorMap(_averagesPlot->xAxis, _averagesPlot->yAxis); _averagesPlot->addPlottable(_averagesColorMap); } _averagesPlot->setInteraction(QCP::iRangeDrag, false); _averagesPlot->setInteraction(QCP::iRangeZoom, false); _averagesPlot->yAxis->setLabel("Position"); if(modifier->binData().empty()) return; _averagesColorMap->setInterpolate(false); _averagesColorMap->setTightBoundary(false); _averagesColorMap->setGradient(QCPColorGradient::gpJet); _averagesColorMap->data()->setSize(binDataSizeX, binDataSizeY); _averagesColorMap->data()->setRange(QCPRange(modifier->xAxisRangeStart(), modifier->xAxisRangeEnd()), QCPRange(modifier->yAxisRangeStart(), modifier->yAxisRangeEnd())); _averagesPlot->xAxis->setRange(QCPRange(modifier->xAxisRangeStart(), modifier->xAxisRangeEnd())); _averagesPlot->yAxis->setRange(QCPRange(modifier->yAxisRangeStart(), modifier->yAxisRangeEnd())); // Copy data to QCPColorMapData object. for (int j = 0; j < binDataSizeY; j++) { for (int i = 0; i < binDataSizeX; i++) { _averagesColorMap->data()->setCell(i, j, modifier->binData()[j*binDataSizeX+i]); } } // Check if range is already correct, because setRange emits the rangeChanged signal // which is to be avoided if the range is not determined automatically. _rangeUpdate = false; _averagesColorMap->setDataRange(QCPRange(modifier->propertyAxisRangeStart(), modifier->propertyAxisRangeEnd())); _rangeUpdate = true; } _averagesPlot->replot(QCustomPlot::rpQueued); }
/* * * reimplement c++ version of inPolygon_c * indices are allocated within gating function, so it is up to caller to free it * and now it is freed in destructor of its owner "nodeProperties" object */ vector<bool> polygonGate::gating(flowData & fdata){ vector<coordinate> vertices=param.getVertices(); unsigned nVertex=vertices.size(); string x=param.xName(); string y=param.yName(); valarray<double> xdata(fdata.subset(x)); valarray<double> ydata(fdata.subset(y)); unsigned nEvents=xdata.size(); //init the indices vector<bool> ind(nEvents); unsigned counter; double xinters; double p1x, p2x, p1y, p2y; for(unsigned i=0; i<nEvents; i++) {//iterate over points p1x=vertices.at(0).x; p1y=vertices.at(0).y; counter=0; for(unsigned j=1; j <= nVertex; j++) {// iterate over vertices /*p1x,p1y and p2x,p2y are the endpoints of the current vertex*/ if (j == nVertex) {//the last vertice must "loop around" p2x = vertices.at(0).x; p2y = vertices.at(0).y; } else { p2x = vertices.at(j).x; p2y = vertices.at(j).y; } /*if horizontal ray is in range of vertex find the x coordinate where ray and vertex intersect*/ if(ydata[i] >= min(p1y, p2y) && ydata[i] < max(p1y, p2y) &&xdata[i] <= max(p1x, p2x)) { xinters = (ydata[i]-p1y)*(p2x-p1x)/(p2y-p1y)+p1x; /*if intersection x coordinate == point x coordinate it lies on the boundary of the polygon, which means "in"*/ if(xinters==xdata[i]) { counter=1; break; } /*count how many vertices are passed by the ray*/ if (xinters > xdata[i])counter++; } p1x=p2x; p1y=p2y; } /*uneven number of vertices passed means "in"*/ ind[i]=((counter % 2) != 0); } if(isNegate()) ind.flip(); return ind; }
//makePlot created a plot. We now update its data. void MainWindow::refreshPlot(int *x, int *y, int len, uint8_t plot_index) { static int graph_ylim[2*VAR_NUM] = {0,0,0,0,0,0,0,0,0,0,0,0}; //From array to QVector: QVector<double> xdata(len), ydata(len); qCopy(x, x+len, xdata.begin()); qCopy(y, y+len, ydata.begin()); ui->customPlot->graph(plot_index)->setData(xdata, ydata); //ToDo: Modify this code to take the max of all curves! //In Automatic mode we constantly adjust the axis: if(ui->radioButtonXAuto->isChecked()) { array_minmax(x, len, &plot_xmin, &plot_xmax); ui->customPlot->xAxis->setRange(plot_xmin, plot_xmax); ui->plot_xmin_lineEdit->setText(QString::number(plot_xmin)); ui->plot_xmax_lineEdit->setText(QString::number(plot_xmax)); } else { //X is in manual mode. } if(ui->radioButtonYAuto->isChecked()) { //Unusued channels (index == 0) aren't used for the automatic gain if(data_to_plot[plot_index] == 0) { //qDebug() << "Ch[" << plot_index << "] is Unused."; //Unused channel. We take the min & max from used channels. int u = 0; for(int k= 0; k < VAR_NUM; k++) { //Grab min & max from any used channel if(data_to_plot[k] != 0) { plot_ymin = graph_ylim[k]; plot_ymax = graph_ylim[k+VAR_NUM]; } else { u++; } } if(u == VAR_NUM) { //All unused, force to 0: plot_ymin = -10; plot_ymax = 10; } //qDebug() << "Min/Max =" << plot_ymin << "," << plot_ymax; } else { //Limits for this graph: array_minmax(y, len, &plot_ymin, &plot_ymax); //qDebug() << "Ch[" << plot_index << "] is used."; } //Compare to all others and get max(max(()) graph_ylim[plot_index] = plot_ymin; graph_ylim[plot_index+VAR_NUM] = plot_ymax; //qDebug() << "Min/Max =" << plot_ymin << "," << plot_ymax; array_minmax(graph_ylim, 2*VAR_NUM, &plot_ymin, &plot_ymax); //Add 5%: plot_ymin = (plot_ymin-(abs(plot_ymin)/20)); plot_ymax = (plot_ymax+(abs(plot_ymax)/20)); //Set axis 5% above minimum ui->customPlot->yAxis->setRange(plot_ymin, plot_ymax); ui->plot_ymin_lineEdit->setText(QString::number(plot_ymin)); ui->plot_ymax_lineEdit->setText(QString::number(plot_ymax)); } //qDebug() << "Final Min/Max =" << plot_ymin << "," << plot_ymax; //qDebug() << ""; ui->customPlot->replot(); }
void MeshEnergy::GetNormalsTangentPlane( const std::vector<int>& C, const std::vector<double>& phi, std::valarray<double>& ne1, std::valarray<double>& ne2, MeshData* vtkNotUsed(meshdata)) { vtkPoints* verts = meshdata->polydata->GetPoints(); for( ::size_t k_ = 0; k_ < C.size(); k_++ ) { int k = C[k_]; std::vector<double> nhat(3); nhat[0] = meshdata->nx[k]; // these are normal to surface; the nx_ are the contour normals nhat[1] = meshdata->ny[k]; nhat[2] = meshdata->nz[k]; // step 1. create the rotation matrix that orients the current normal as [0,0,1]'. double phiang = atan2( nhat[0], nhat[1] ); std::vector<double> rotate1(9); rotate1[0] = cos(phiang); rotate1[1] = -sin(phiang); rotate1[2] = 0; rotate1[3] = sin(phiang); rotate1[4] = cos(phiang); rotate1[5] = 0; rotate1[6] = 0; rotate1[7] = 0; rotate1[8] = 1.0; std::vector<double> nhat_a(3); pkmult( nhat, rotate1, nhat_a ); double ytilde = nhat_a[1]; double theta = M_PI_2 - atan2(nhat[2],ytilde); std::vector<double> rotate2(9); rotate2[0] = 1.0; rotate2[1] = 0; rotate2[2] = 0; rotate2[3] = 0; rotate2[4] = cos(theta); rotate2[5] = -sin(theta); rotate2[6] = 0; rotate2[7] = sin(theta); rotate2[8] = cos(theta); std::vector<double> nhat_b(3); pkmult( nhat_a, rotate2, nhat_b ); // nhat_b should now be [0 0 1]' double thispt[3]; verts->GetPoint( k, thispt ); // apply rotate2 * rotate1 to each *translated* neighbor of this k-th point ::size_t num_neigh = meshdata->adj[k].myNeighbs.size(); double vec[3]; std::vector<double> vv(3); std::vector<double> vv_(3); std::valarray<double> xdata(num_neigh); std::valarray<double> ydata(num_neigh); std::valarray<double> zdata(num_neigh); // step 2. create temporary set of std::vectors as copies of neighboring points // translated to origin // step 3. apply the rotation to all these points for ( ::size_t i = 0; i < num_neigh; i++ ) { int idx = meshdata->adj[k].myNeighbs[i]; verts->GetPoint( idx, vec ); vv[0] = vec[0] - thispt[0]; vv[1] = vec[1] - thispt[1]; vv[2] = vec[2] - thispt[2]; pkmult( vv, rotate1, vv_ ); pkmult( vv_, rotate2, vv ); xdata[i] = vv[0]; ydata[i] = vv[1]; zdata[i] = phi[idx] - phi[k]; //vv[2]; // zero reference phi at the vertex where we are forming tangent plane } /*if( abs(zdata).min() < 1e-6 ) continue;*/ // step 4. find least-squares fit for H(x,y) = ax + by std::valarray<double> RHS(2); std::valarray<double> ATA(4); ATA[0] = (xdata * xdata).sum(); ATA[1] = (xdata * ydata).sum(); ATA[2] = ATA[1]; ATA[3] = (ydata * ydata).sum(); RHS[0] = (xdata * zdata).sum(); RHS[1] = (ydata * zdata).sum(); int maxits = 1000; std::valarray<double> ab = RHS; // initial guess std::valarray<double> LHS(2); pkmult2( ab, ATA, LHS ); double res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); double tol = 1e-8; int iter = 0; while( iter < maxits && res > tol ) { iter++; ab[0] = (RHS[0] - ( ab[1]*ATA[1] ) )/ ATA[0]; ab[1] = (RHS[1] - ( ab[0]*ATA[2] ) )/ ATA[3]; pkmult2( ab, ATA, LHS ); res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); } ne1[k_] = ab[0] / sqrt( (ab*ab).sum() ); ne2[k_] = ab[1] / sqrt( (ab*ab).sum() ); // step 5. differentiate the plane along principal directions } }
void MeshEnergy::GetKappa( const std::vector<int>& C, const std::vector<double>& phi, std::valarray<double>& kappa) { // kappa: divergence of normal // dy^2 * dxx - 2dxdydxy + dx^2dyy / ( dx^2 + dy^2 )^(3/2) vtkPoints* verts = meshdata->polydata->GetPoints(); for( ::size_t k_ = 0; k_ < C.size(); k_++ )\ { int k = C[k_]; std::vector<double> nhat(3); nhat[0] = meshdata->nx[k]; // these are normal to surface; the nx_ are the contour normals nhat[1] = meshdata->ny[k]; nhat[2] = meshdata->nz[k]; // step 1. create the rotation matrix that orients the current normal as [0,0,1]'. double phiang = atan2( nhat[0], nhat[1] ); std::vector<double> rotate1(9); rotate1[0] = cos(phiang); rotate1[1] = -sin(phiang); rotate1[2] = 0; rotate1[3] = sin(phiang); rotate1[4] = cos(phiang); rotate1[5] = 0; rotate1[6] = 0; rotate1[7] = 0; rotate1[8] = 1.0; std::vector<double> nhat_a(3); pkmult( nhat, rotate1, nhat_a ); double ytilde = nhat_a[1]; double theta = M_PI_2 - atan2(nhat[2],ytilde); std::vector<double> rotate2(9); rotate2[0] = 1.0; rotate2[1] = 0; rotate2[2] = 0; rotate2[3] = 0; rotate2[4] = cos(theta); rotate2[5] = -sin(theta); rotate2[6] = 0; rotate2[7] = sin(theta); rotate2[8] = cos(theta); std::vector<double> nhat_b(3); pkmult( nhat_a, rotate2, nhat_b ); // nhat_b should now be [0 0 1]' double thispt[3]; verts->GetPoint( k, thispt ); // apply rotate2 * rotate1 to each *translated* neighbor of this k-th point ::size_t num_neigh = meshdata->adj[k].myNeighbs.size(); double vec[3]; std::vector<double> vv(3); std::vector<double> vv_(3); std::valarray<double> xdata(num_neigh); std::valarray<double> ydata(num_neigh); std::valarray<double> zdata(num_neigh); // step 2. create temporary set of std::vectors as copies of neighboring points // translated to origin // step 3. apply the rotation to all these points for (::size_t i = 0; i < num_neigh; i++ ) { int idx = meshdata->adj[k].myNeighbs[i]; verts->GetPoint( idx, vec ); vv[0] = vec[0] - thispt[0]; vv[1] = vec[1] - thispt[1]; vv[2] = vec[2] - thispt[2]; pkmult( vv, rotate1, vv_ ); pkmult( vv_, rotate2, vv ); xdata[i] = vv[0]; ydata[i] = vv[1]; zdata[i] = phi[idx] - phi[k]; //vv[2]; // zero reference phi at the vertex where we are forming tangent plane } /*if( abs(zdata).min() < 1e-6 ) continue;*/ // step 4. find first derivatives double phi_x = 0.0; double phi_y = 0.0; { std::valarray<double> RHS(2); std::valarray<double> ATA(4); ATA[0] = (xdata * xdata).sum(); ATA[1] = (xdata * ydata).sum(); ATA[2] = ATA[1]; ATA[3] = (ydata * ydata).sum(); RHS[0] = (xdata * zdata).sum(); RHS[1] = (ydata * zdata).sum(); int maxits = 1000; std::valarray<double> ab = RHS; // initial guess std::valarray<double> LHS(2); pkmult2( ab, ATA, LHS ); double res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); double tol = 1e-8; int iter = 0; while( iter < maxits && res > tol ) { iter++; ab[0] = (RHS[0] - ( ab[1]*ATA[1] ) )/ ATA[0]; ab[1] = (RHS[1] - ( ab[0]*ATA[2] ) )/ ATA[3]; pkmult2( ab, ATA, LHS ); res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); } phi_x = ab[0]; phi_y = ab[1]; } // step 4. find least-squares fit for phi(x,y) = ax^2 + bxy + cy^2 // to get second derivatives std::valarray<double> RHS(3); // A'z RHS[0] = ( xdata * xdata * zdata ).sum(); RHS[1] = ( xdata * ydata * zdata ).sum(); RHS[2] = ( ydata * ydata * zdata ).sum(); double tik_delta = 1e-1 * abs(RHS).min(); std::vector<double> ATA(9); // A'A ATA[0] = tik_delta + (xdata * xdata * xdata * xdata).sum(); ATA[1] = (xdata * xdata * xdata * ydata).sum(); ATA[2] = (xdata * xdata * ydata * ydata).sum(); ATA[3] = (xdata * ydata * xdata * xdata).sum(); ATA[4] = tik_delta + (xdata * ydata * xdata * ydata).sum(); ATA[5] = (xdata * ydata * ydata * ydata).sum(); ATA[6] = (ydata * ydata * xdata * xdata).sum(); ATA[7] = (ydata * ydata * xdata * ydata).sum(); ATA[8] = tik_delta + (ydata * ydata * ydata * ydata).sum(); int maxits = 1000; std::valarray<double> abc = RHS; // initial guess std::valarray<double> LHS(3); pkmult( abc, ATA, LHS ); double res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); double tol = 1e-8; int iter = 0; while( iter < maxits && res > tol ) { iter++; abc[0] = (RHS[0] - ( abc[1]*ATA[1] + abc[2]*ATA[2] ) )/ ATA[0]; abc[1] = (RHS[1] - ( abc[0]*ATA[3] + abc[2]*ATA[5] ) )/ ATA[4]; abc[2] = (RHS[2] - ( abc[0]*ATA[6] + abc[1]*ATA[7] ) )/ ATA[8]; pkmult( abc, ATA, LHS ); res = sqrt( ( (LHS - RHS)*(LHS - RHS) ).sum() ); } // step 5. get the derivatives from quadratic form double phi_xx = 2*abc[0]; double phi_xy = abc[1]; double phi_yy = 2*abc[2]; kappa[k_] = phi_y * phi_y * phi_xx - 2 * phi_x * phi_y * phi_xy + phi_x * phi_x * phi_yy; if( abs(phi_x) + abs(phi_y) > 1e-9 ) { kappa[k_] /= pow( (phi_x*phi_x + phi_y*phi_y), 1.5 ); } } }