Plotting scattered vectors

Hi,

I have the need to get something really close to what was asked here: Scatter plot with vector associated to each point
Shortly: a set of scattered vectors to display.

The issue is that my vectors are 3D: for each vector I have 3 coordinates for the positions and 3 values for its components.
Is there a way to get such a picture?

There is no such predefined representation in ROOT but it does not seems very difficult to do. For the markers you can make a TGraph with the (x,y) points. For the little line segments it is a bit more complicated but basically it is a loop producing a set of TLine. If you have a small sample of your data I can try to provide you some example.

1 Like

Yep… Dots were not an issue for me either, but for the vectors/segments…

Here’s an example: test.txt (30.6 KB)

Thank you. :slight_smile:

So you are looking for a plot in 3D ?

Yes.
I need to have an idea of how to classify vectors into some angular binning, so yes, I need a 3D plot.

You need to define properly the vector but the idea is the following:

void plot3dwithvector() {
   auto g = new TGraph2D();

   double x[10] = { 0.333168894052505  , 1.46091299058071E-08 , 2.24945768678708E-08 , 0.152351081371307  , 5.51142020910334E-09 , 5.69387808013744E-08 , 2.64541766270554E-09 , 5.13162241588816E-08 , 1.78169090592206E-09 , 0.007284481078386 };
   double y[10] = { 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 , 1500.05798339844 };
   double z[10] = { 0.918900966644287,  -0.932851850986481,  -0.380060702562332,  -1.52324450016022,  0.094302758574486,  -1.5516140460968,  0.801989138126373,  1.78688251972199,  -2.29705429077148,  2.20811176300049};

   for (int i = 0; i<10; i++)  g->SetPoint(i , x[i], y[i], z[i]);

   g->Draw("P0");

   double ux[10] = {11.7526865005493 , 14.0614671707153 , 14.0148906707764 , 15.8330516815186 , 14.732702255249  , 13.1480436325073 , 13.8227872848511 , 15.4252738952637 , 13.5150909423828 , 15.0704441070557 };
   double uy[10] = {0.999999768794254 , 0.999995963966835 , 0.999999542140503 , 0.999996438482454 , 0.999999880467112 , 0.999998747243802 , 0.999999695773325 , 0.999997365844202 , 0.999994719735028 , 0.999995373222123 };
   double uz[10] = {-0.000498842739034 , -0.002375233219936 , 0.000518542365171 , -0.002600628184155 , -0.000466246623546 , -0.000749222934246 , -0.000105562685349 , 0.002096008975059 , -0.003230506321415 , 0.002058336278424 };

   for (int j = 0; j<10; j++) {
      auto *l3 = new TPolyLine3D(2);
      l3->SetPoint(0 , x[j], y[j], z[j]);
      l3->SetPoint(1 , ux[j], uy[j], uz[j]);
      l3->Draw();
   }
}

What do you mean by that?
I found out that I gave you a bad input file, but that doesn’t matter.
I’m not sure about what these do:

l3->SetPoint(0 , x[j], y[j], z[j]);
l3->SetPoint(1 , ux[j], uy[j], uz[j]);
It looks like you’re setting two point, which are like the starting and ending points for each line…?

I just took the 10 first lines of your file to build up a small example. The idea is to draw the points (circles) using a TGraph2D made with the x y z positions and then add the lines (vectors) on this plot using several TPolyLine3D made of 2 points. The first point a given polyline is the same as the circle position and the second point as to be computed properly. Right now I just took the ux uy uz but it does not seems to be right.
Now, for the second point, I simply do:

l3->SetPoint(1 , ux[j], uy[j], uz[j]);

You need to change this to have the correct end point of the lines.

Uhm… So yes, the two lines I quoted are starting and ending points.

This should work, from the mathematical point of view…

l3->SetPoint(1 , x[j]+ux[j], y[j]+uy[j], z[j]+uz[j]);

edit: no, It’s wrong also from the mathematical point of view! :joy:
But I’m on it. :wink:

Yes, I gathered that. I let you find the right formula.

1 Like

:smiley:

Yup!
I do remember some algebra yet, despite my premature senility. :slight_smile:

Gotta fix a few things yet, but the main issue is solved.
Thank you couet. :slight_smile:
Thank you a lot.

1 Like

@couet:

Why I can’t set a user range for the TGraph2D axes?

This is the code I wrote thanks to your help:

// .x trial.c("input.txt")

bool verb = 1;	// verbose?

const string tab("\t");

const string blue("\033[1;34m");	// info
const string green("\033[1;32m");	// request
const string pink("\033[1;35m");	// test
const string red("\033[1;31m");		// errors
const string yellow("\033[1;33m");	// warnings

const string reset("\033[0m\e[0m");

double xMin(1498);
double xMax(1898);
double yMin(-6);
double yMax(6);
double zMin(1);
double zMax(199);

bool fileExist(const char *fileName) {
	ifstream infile(fileName);
	return infile.good();
}

TCanvas * generateCanvas(int cW = 800, int cH = 800) {
	TCanvas * c = new TCanvas("c", "plot1d", cW, cH);
	c->SetMargin(0.1, 0.1, 0.1, 0.1);
	c->ToggleEventStatus();
//	c->ToggleEditor();
	return c;
}

void trial (string input)
{
	// check if input file exist
	if (!fileExist(input.c_str())) {
		cerr << red << "ERROR :: file " << input.c_str() << " doesn't exist!" << reset << endl;
		return 1;
	}
	
	// dummy variables. How to avoid them?
	double x, y, z;
	double ux, uy, uz;
	
	vector<double> vx, vy, vz;
	vector<double> vux, vuy, vuz;
	
	int p;
	string line;

	// generate Canvas using external function
	TCanvas * c = generateCanvas();
	TGraph2D * g = new TGraph2D();
	
	// overwrite log-scale settings
	gPad->SetLogx(false);
	gPad->SetLogy(false);
	gPad->SetLogz(false);

	if (verb) cout << "Index" << tab << "x:" << tab << tab << "y:" << tab << tab << "z:" << tab << tab << "ux:" << tab << tab << "uy:" << tab << tab << "uz:" << endl;
	
	// read input file and populate v* and vu* vectors which are origins and components of vectors
	ifstream fileInput (input.c_str());
	while (getline(fileInput, line)) {
		if (line[0] == '#' || line[0] == '\0') continue;

		stringstream(line) >> p >> x >> y >> z >> ux >> uy >> uz;
		if (verb) cout << p << tab << scientific << x << tab << y << tab << z << tab << ux << tab << uy << tab << uz << endl;
		
		vx.push_back(x);
		vy.push_back(y);
		vz.push_back(z);
		vux.push_back(ux);
		vuy.push_back(uy);
		vuz.push_back(uz);
		
		// draw origins on TGraph2D
		g->SetPoint(p , x, y, z);
	}
	
	if (verb) cout << blue << ++p << " points read from input file" << reset << endl;
	
	
	// setting user range. Why this doesn't work!?
	if (xMin != xMax) {
		g->GetXaxis()->SetRangeUser(xMin, xMax);
		if (verb) cout << blue << scientific << "User defined range for the x axis: [" << xMin << ", " << xMax << "]" << reset << endl;
	}
	if (yMin != yMax) {
		g->GetYaxis()->SetRangeUser(yMin, yMax);
		if (verb) cout << blue << scientific << "User defined range for the y axis: [" << yMin << ", " << yMax << "]" << reset << endl;
	}
	if (zMin != zMax) {
		g->GetXaxis()->SetRangeUser(zMin, zMax);
		if (verb) cout << blue << scientific << "User defined range for the z axis: [" << zMin << ", " << zMax << "]" << reset << endl;
	}
	
	g->Draw("p0");
	
	// draw 'vectors'
	for (size_t i = 0; i < vx.size(); ++i) {
		TPolyLine3D * l = new TPolyLine3D(2);
		l->SetPoint(0, vx[i], vy[i], vz[i]);
		l->SetPoint(1, vx[i] + 100*vux[i], vy[i] + 100*vuy[i], vz[i] + 100*vuz[i]);
		l->Draw("tri same");
	}
	
	return;
}

You can try that using this as input file: input.txt (30.2 KB)

Please note that I use these xMin, xMax, yMin, etc variables for setting the user range.

Does your example really works ? it gives me:

root [0] .x try.c("input.txt")
In file included from input_line_11:1:
try.c:35:6: error: expected unqualified-id
void try (string input)
     ^
root [1] 

Sorry, I didn’t change the first comment.
You can run it by

.x trial.c ("input.txt")

Ok.

Btw do:

		l->Draw();

no need for any option (see my initial code)

Yep…
I tried to get some different style. I failed. :slight_smile:
:man_shrugging:

You put some TGraph2D option into TPolyLine3D … it is normal it fail… have a look at the TPolyLIne3D options …
for the range:

g->GetHistogram()->GetXaxis()->SetRangeUser(xMin, xMax);

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.