TH2::Interpolate() fails for some values

Dear all,

I have a similar problem than the one described here: https://root-forum.cern.ch/t/wrong-values-from-tgraph2d-interpolate/17078

I have noticed that Interpolate() method is supposed to be called internally, but I think it is worth to mention it.

It is a bit less straightforward to highlight since the data for filling the TGraph2D are taken form a file. The TGraph2D is well displayed but the interpolation shows unexpected values.

Here is the code I use:

	std::vector<double> x;
	std::vector<double> y;
	std::vector<double> val;

	std::ifstream f("1000y.txt");
	if (!f) {
		std::cout << "1000y.txt" << " cannot be read!" << std::endl;
		system("pause");
		exit(0);
	}
	double time = 0.0;
	f >> time;
	double temp = 0.0;
	while (f >> temp) {
		x.push_back(temp);
		f >> temp;
		y.push_back(temp);
		f >> temp;
		val.push_back(temp);
	}
	f.close();

	TGraph2D* tg2d = new  TGraph2D(x.size(), &x[0], &y[0], &val[0]); // only created for interpolation

	TH2D* th2d_file = new TH2D("title", "title",
		100 + 1,
		-0.5,
		+100.5,
		100 + 1,
		-0.5,
		+100.5
	);

	for (unsigned int kx = 0; kx < (100 + 1); ++kx) {
		double bcx = ((TAxis*)th2d_file->GetXaxis())->GetBinCenter(kx + 1);
		for (unsigned int ky = 0; ky < (100 + 1); ++ky) {
			double bcy = ((TAxis*)th2d_file->GetYaxis())->GetBinCenter(ky + 1);
			th2d_file->SetBinContent(kx + 1,
				ky + 1,
				tg2d->Interpolate(bcx, bcy)
			);
			// std::cout << kx+1 << ": "<< bcx << " " << ky+1 << ": " << bcy << " " << tg2d->Interpolate(bcx, bcy) << std::endl;
		}
	}

	TCanvas* c = new TCanvas("ctg", "ctg", 0, 0, 1920, 1080);
	c->Divide(2, 1, .02, .02, 0);
	c->cd(1);
	tg2d->Draw("COLZ");
	c->cd(2);
	th2d_file->Draw("COLZ");


Please read tips for efficient and successful posting and posting code

ROOT Version: root-907c1d3
Platform: Windows 10
Compiler: Visual Studio Community 16.3.7
___1000y.txt (415.3 KB)

You macro has several mistakes and odes not run. Can you fix them ?
Here is what I get:

In file included from input_line_11:1:
/Users/couet/Downloads/bou.C:7:16: error: 'file' does not refer to a value
                std::cout << file << " cannot be read!" << std::endl;
                             ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include/sys/kernel_types.h:50:8: note: declared here
struct file;
       ^
In file included from input_line_11:1:
/Users/couet/Downloads/bou.C:25:29: error: use of undeclared identifier 'title'
        TH2D* th2d_file = new TH2D(title.c_str(), title.c_str(),
                                   ^
/Users/couet/Downloads/bou.C:25:44: error: use of undeclared identifier 'title'
        TH2D* th2d_file = new TH2D(title.c_str(), title.c_str(),
                                                  ^
/Users/couet/Downloads/bou.C:27:11: error: use of undeclared identifier 'a'
                                                                - a / 100 / 2.0,
                                                                  ^
/Users/couet/Downloads/bou.C:28:11: error: use of undeclared identifier 'a'
                                                                + a / 100 / 2.0,
                                                                  ^
/Users/couet/Downloads/bou.C:30:11: error: use of undeclared identifier 'b'
                                                                - b / 100 / 2.0,
                                                                  ^
/Users/couet/Downloads/bou.C:31:11: error: use of undeclared identifier 'b'
                                                                + b / 100 / 2.0
                                                                  ^
/Users/couet/Downloads/bou.C:34:34: error: use of undeclared identifier 'NX'
        for (unsigned int kx = 0; kx < (NX+1); ++kx) {
                                        ^
/Users/couet/Downloads/bou.C:36:35: error: use of undeclared identifier 'NY'
                for (unsigned int ky = 0; ky < (NY+1); ++ky) {

Sorry, the code was part of a much larger code, so it should be OK now.

Thank you for your reply.

I guess these are again problems with the “Delaunay triangles” caused by the “regular rectangular grid” (i.e. “X” and “Y” values) of the graph.

I get this plot now. Is it what you get too ?

Yes, I get the same. The “white pixels” are simply 0.

Yes, this is what I have too.

The plots are meant to highlight the differences.

@couet Take the point at x = 58, y = 16. This is the “tg2d” graph’s point number 8542 with z = 413.268 (line number 8544 in the input file: “57.999999999999986 16.0 4.132677164611E+2”) but tg2d->Interpolate(58., 16.) returns 0.

When you draw the tg2d with the option COL or SURF it indeed draws the underlaying histogram produced by interpolation on the triangles… and this plot (the left one) is correct… I will need to look
what is done right by TGraph2D you are doing wrong in your macro.

Hi all,
I think Wile is (nearly) right. When points
of the TGraph2d happen to fall on straight lines
the algorithm seems to fail (sometimes??)
If one shakes the points a little bit:

tg2d->Interpolate(bcx+0.00001*(gRandom->Rndm()-0.5),
 bcy+0.00001*(gRandom->Rndm()-0.5))
+0.00001*(gRandom->Rndm()-0.5) 

the plot looks smooth.
Note: one needs to shake x,y and z, not only x, y
Cheers
Otto

@OSchaile You don’t need to “shake z”. The “z” values on the outside graph’s borders may actually be 0 (so some “blank pixels” are fine there).

yes, you are right
Otto

At the very end the ComputeZ is used.
GetHistogram, like Interpolate, use it but seems to do the right thing.
Try;

	tg2d->GetHistogram()->Draw("COLZ");

@couet tg2d->SetNpx(102); tg2d->SetNpy(102);

1 Like

Thank you for your reply.

That was a simplified example here but the ting is I want to use the th2d to compare its values with an another one (calculated with an analytical solution) on a very “specific mesh” which might be not the one returned by the tg2d->GetHistogram().

I really use tg2d to have the interpolation only.

See how TGraph2D::GetHistogram uses ComputeZ. Also try @Wile_E_Coyote suggestion.

@couet Actually, my last “suggestion” was to show you that your method also returns “blank pixels” inside. I really think that the procedure which produces “Delaunay triangles” needs fixes.

we use external code

I will have a look on the TGraph2D::GetHistogram… Thank you for your suggestion.

Yes I agree with Wile_E_Coyote, as shown some returned values are clearly unexpected. So does it mean that you might envisage another external code for interpolation in the future?

Ok I need a closer look … I am just saying that GetHistogram does something similar to what you are doing and does it properly whereas you get all in you case. I do not know why I must admit … I need to look …