I have then 2 questions:
1/ the matrix elements are not 1, obviously a normalization concern, but should’nt the option “N” normalize the covariance matrix ?

2/ the matrix is not symmetric, is that made to save computing ressources ? is there an automated way to symmetrize it ?

The doc from TPrincipal claims that the matrix released by GetCovarianceMatrix() is symmetric, but checking that with

TPrincipal* p = new TPrincipal( n, "ND");
Double_t data[4];
p->AddRow( data );
TMatrixD* p->GetCovarianceMatrix();
p->Print();
cout << p->IsSymmetric() << endl;

For reasons unknown, the author stored the only the lower left
part of the matrix in a TMatrixD.

However, when calculating the eigen vectors, symmetric algorithms
are used and the matrix is converted to a TMatrixDSym:

TMatrixD* m = p.GetCovarianceMatrix();
TMatrixDSym sym; sym.Use(m->GetNrows(),m->GetMatrixArray());

(Notice the “Use” which makes sure that we do not copy data back and
forth)

You can do this too in your code and of course this should be updated
in the TPrincipal class.

Concerning your normalization question:

Looking at the code the “N” option makes sure that the covariance
matrix is normalized before calculating the eigen vectors and values.
HOWEVER, the matrix stored in the class is not touched in other
words GetCovarianceMatrix will always give you the same matrix.

You can create yourself this normalized matrix by doing the
following operation on your matrix m:

M + M^T does not symmetrize the matrix because you are adding the diagonal twice.

Maddalena is right, the covariance matrix IS symmetric, what you have here is what we call a bug. The function should return a TMatrixDSym. It’s been years and no one has done anything about this.

I think the safest way would be to just loop over the matrix to make a symmetric version.

I will do it. As I understand it I should download the ROOT sources, find the place in the code where this is done, modify it, recompile it and test it. When I be sure that it is fixed I should tell you what the changes should be, so that you update the source code. Is this correct?

Hi,
Is there some news about this issue? I am trying to use TPrincipal::GetCovarianceMatrix right now but I have the same problem. The matrix is not symetric and show me just its lower left. I need this to be symetric in order to do some math. Could you guys please suggest another method?

Any reason not to use my recipe proposed in Jan 2017

const TMatrixD* m = p.GetCovarianceMatrix();
TMatrixD mt = *m; mt.T();
TMatrixDDiag d(mt); d = 0;
TMatrixDSym sym = *m+mt;

As stated in the TPrincipal description, it is an implementation of the LINTRA package which was developed at a time when memory was a KB and not a GB issue …

Changing GetCovariance could be a backward compatibility issue, unless it is done by adding a new option variable.
Probably better to update the documentation.

Any volunteers ?

rooter_03 …:

saw that his analysis is not Nobel-prize suspicious

dropped this “physics - thing” and created a startup with a planned IPO in 2020

rewrote his code in Python and is still waiting for an answer …