#pragma once#include"itkParticleShapeMatrixAttribute.h"#include"vnl/vnl_vector.h"#include"itkParticleSystem.h"namespaceitk{template<classT,unsignedintVDimension>classITK_EXPORTParticleShapeLinearRegressionMatrixAttribute:publicParticleShapeMatrixAttribute<T,VDimension>{public:typedefTDataType;typedefParticleShapeLinearRegressionMatrixAttributeSelf;typedefParticleShapeMatrixAttribute<T,VDimension>Superclass;typedefSmartPointer<Self>Pointer;typedefSmartPointer<constSelf>ConstPointer;typedefWeakPointer<constSelf>ConstWeakPointer;itkNewMacro(Self);itkTypeMacro(ParticleShapeLinearRegressionMatrixAttribute,ParticleShapeMatrixAttribute);voidUpdateMeanMatrix(){// for each samplefor(unsignedinti=0;i<m_MeanMatrix.cols();i++){// compute the meanm_MeanMatrix.set_column(i,m_Intercept+m_Slope*m_Expl(i));}}inlinevnl_vector<double>ComputeMean(doublek)const{returnm_Intercept+m_Slope*k;}voidResizeParameters(unsignedintn){vnl_vector<double>tmpA=m_Intercept;// copy existing matrixvnl_vector<double>tmpB=m_Slope;// copy existing matrix// Create new m_Intercept.set_size(n);m_Slope.set_size(n);// Copy old data into new vector.for(unsignedintr=0;r<tmpA.size();r++){m_Intercept(r)=tmpA(r);m_Slope(r)=tmpB(r);}}virtualvoidResizeMeanMatrix(intrs,intcs){vnl_matrix<T>tmp=m_MeanMatrix;// copy existing matrix// Create new column (shape)m_MeanMatrix.set_size(rs,cs);m_MeanMatrix.fill(0.0);// Copy old data into new matrix.for(unsignedintc=0;c<tmp.cols();c++){for(unsignedintr=0;r<tmp.rows();r++){m_MeanMatrix(r,c)=tmp(r,c);}}}voidResizeExplanatory(unsignedintn){if(n>m_Expl.size()){vnl_vector<double>tmp=m_Expl;// copy existing matrix// Create new m_Expl.set_size(n);m_Expl.fill(0.0);// Copy old data into new vector.for(unsignedintr=0;r<tmp.size();r++){m_Expl(r)=tmp(r);}}}virtualvoidDomainAddEventCallback(Object*,constEventObject&e){constitk::ParticleDomainAddEvent&event=dynamic_cast<constitk::ParticleDomainAddEvent&>(e);unsignedintd=event.GetDomainIndex();if(d%this->m_DomainsPerShape==0){this->ResizeMatrix(this->rows(),this->cols()+1);this->ResizeMeanMatrix(this->rows(),this->cols()+1);this->ResizeExplanatory(this->cols());}}virtualvoidPositionAddEventCallback(Object*o,constEventObject&e){constitk::ParticlePositionAddEvent&event=dynamic_cast<constitk::ParticlePositionAddEvent&>(e);constitk::ParticleSystem*ps=dynamic_cast<constitk::ParticleSystem*>(o);constintd=event.GetDomainIndex();constunsignedintidx=event.GetPositionIndex();consttypenameitk::ParticleSystem::PointTypepos=ps->GetTransformedPosition(idx,d);constunsignedintPointsPerDomain=ps->GetNumberOfParticles(d);// Make sure we have enough rows.if((ps->GetNumberOfParticles(d)*VDimension*this->m_DomainsPerShape)>this->rows()){this->ResizeParameters(PointsPerDomain*VDimension*this->m_DomainsPerShape);this->ResizeMatrix(PointsPerDomain*VDimension*this->m_DomainsPerShape,this->cols());this->ResizeMeanMatrix(PointsPerDomain*VDimension*this->m_DomainsPerShape,this->cols());}// CANNOT ADD POSITION INFO UNTIL ALL POINTS PER DOMAIN IS KNOWN// Add position info to the matrixunsignedintk=((d%this->m_DomainsPerShape)*PointsPerDomain*VDimension)+(idx*VDimension);for(unsignedinti=0;i<VDimension;i++){this->operator()(i+k,d/this->m_DomainsPerShape)=pos[i];}// std::cout << "Row " << k << " Col " << d / this->m_DomainsPerShape << " = " << pos << std::endl;}virtualvoidPositionSetEventCallback(Object*o,constEventObject&e){constitk::ParticlePositionSetEvent&event=dynamic_cast<constitk::ParticlePositionSetEvent&>(e);constitk::ParticleSystem*ps=dynamic_cast<constitk::ParticleSystem*>(o);constintd=event.GetDomainIndex();constunsignedintidx=event.GetPositionIndex();consttypenameitk::ParticleSystem::PointTypepos=ps->GetTransformedPosition(idx,d);constunsignedintPointsPerDomain=ps->GetNumberOfParticles(d);// Modify matrix info// unsigned int k = VDimension * idx;unsignedintk=((d%this->m_DomainsPerShape)*PointsPerDomain*VDimension)+(idx*VDimension);for(unsignedinti=0;i<VDimension;i++){this->operator()(i+k,d/this->m_DomainsPerShape)=pos[i]-m_MeanMatrix(i+k,d/this->m_DomainsPerShape);}}virtualvoidPositionRemoveEventCallback(Object*,constEventObject&){// NEED TO IMPLEMENT THIS}voidSetDomainsPerShape(inti){this->m_DomainsPerShape=i;}intGetDomainsPerShape()const{returnthis->m_DomainsPerShape;}voidSetExplanatory(std::vector<double>v){// std::cout << "Setting expl " << std::endl;ResizeExplanatory(v.size());for(unsignedinti=0;i<v.size();i++){// std::cout << v[i] << std::endl;m_Expl[i]=v[i];}}voidSetExplanatory(unsignedinti,doubleq){m_Expl[i]=q;}constdouble&GetExplanatory(unsignedinti)const{returnm_Expl[i];}double&GetExplanatory(unsignedinti){returnm_Expl[i];}constvnl_vector<double>&GetSlope()const{returnm_Slope;}constvnl_vector<double>&GetIntercept()const{returnm_Intercept;}voidSetSlope(conststd::vector<double>&v){ResizeParameters(v.size());for(unsignedinti=0;i<v.size();i++){m_Slope[i]=v[i];}}voidSetIntercept(conststd::vector<double>&v){ResizeParameters(v.size());for(unsignedinti=0;i<v.size();i++){m_Intercept[i]=v[i];}}voidEstimateParameters(){// std::cout << "Estimating params" << std::endl;// std::cout << "Explanatory: " << m_Expl << std::endl;vnl_matrix<double>X=*this+m_MeanMatrix;// Number of samplesdoublen=static_cast<double>(X.cols());vnl_vector<double>sumtx=m_Expl[0]*X.get_column(0);vnl_vector<double>sumx=X.get_column(0);doublesumt=m_Expl[0];doublesumt2=m_Expl[0]*m_Expl[0];for(unsignedintk=1;k<X.cols();k++)// k is the sample number{sumtx+=m_Expl[k]*X.get_column(k);sumx+=X.get_column(k);sumt+=m_Expl[k];sumt2+=m_Expl[k]*m_Expl[k];}m_Slope=(n*sumtx-(sumx*sumt))/(n*sumt2-(sumt*sumt));vnl_vector<double>sumbt=m_Slope*m_Expl[0];for(unsignedintk=1;k<X.cols();k++){sumbt+=m_Slope*m_Expl[k];}m_Intercept=(sumx-sumbt)/n;}// voidInitialize(){m_Intercept.fill(0.0);m_Slope.fill(0.0);m_MeanMatrix.fill(0.0);}virtualvoidBeforeIteration(){m_UpdateCounter++;if(m_UpdateCounter>=m_RegressionInterval){m_UpdateCounter=0;this->EstimateParameters();this->UpdateMeanMatrix();}}voidSetRegressionInterval(inti){m_RegressionInterval=i;}intGetRegressionInterval()const{returnm_RegressionInterval;}protected:ParticleShapeLinearRegressionMatrixAttribute(){this->m_DefinedCallbacks.DomainAddEvent=true;this->m_DefinedCallbacks.PositionAddEvent=true;this->m_DefinedCallbacks.PositionSetEvent=true;this->m_DefinedCallbacks.PositionRemoveEvent=true;m_UpdateCounter=0;m_RegressionInterval=1;}virtual~ParticleShapeLinearRegressionMatrixAttribute(){};voidPrintSelf(std::ostream&os,Indentindent)const{Superclass::PrintSelf(os,indent);}private:ParticleShapeLinearRegressionMatrixAttribute(constSelf&);//purposely not implementedvoidoperator=(constSelf&);//purposely not implementedintm_UpdateCounter;intm_RegressionInterval;// Parameters for the linear modelvnl_vector<double>m_Intercept;vnl_vector<double>m_Slope;// The explanatory variable value for each sample (matrix column)vnl_vector<double>m_Expl;// A matrix to store the mean estimated for each explanatory variable (each sample)vnl_matrix<double>m_MeanMatrix;};}// end namespace