00001 #include "BField/Viz/BfldCanvas.h"
00002
00003 #include <iostream>
00004 #include <map>
00005 using namespace std;
00006
00007 #include "TMath.h"
00008 #include "TStyle.h"
00009 #include "TPolyLine.h"
00010 #include "TEllipse.h"
00011 #include "TStopwatch.h"
00012
00013 #include "Conventions/Munits.h"
00014
00016
00018 int BfldCanvas::fgVerbose = 0;
00019 double BfldCanvas::fgKGMin = 0.0;
00020 double BfldCanvas::fgKGMax = 22.0;
00021 int BfldCanvas::fgArrowGridX = 40;
00022 BfldInterpMethod::InterpMethod_t BfldCanvas::fgDefaultInterpMethod
00023 = BfldInterpMethod::kDefault;
00024
00026
00027 BfldCanvas::BfldCanvas()
00028 : fCanvas(0)
00029 , fScatter(0)
00030 , fPhase(0)
00031 , fIsCoil(0)
00032 , fVldc()
00033 , fZ(-999)
00034 , fScaleMax(1.0)
00035 , fArrowScale(1.0)
00036 , fInterpMethod(fgDefaultInterpMethod)
00037 {
00038
00039 }
00040
00041 BfldCanvas::~BfldCanvas()
00042 {
00043 if (fCanvas) delete fCanvas;
00044 if (fScatter) delete fScatter;
00045 if (fPhase) delete fPhase;
00046 }
00047
00048 BfldCanvas::BfldCanvas(VldContext& vldc, std::string tag, int iscoil)
00049 : fCanvas(0)
00050 , fScatter(0)
00051 , fPhase(0)
00052 , fIsCoil(iscoil)
00053 , fVldc(vldc)
00054 , fZ(-999)
00055 , fScaleMax(1.0)
00056 , fArrowScale(1.0)
00057 , fInterpMethod(fgDefaultInterpMethod)
00058 {
00059
00060 double xmin = -5.0*Munits::m, xmax = +5.0*Munits::m;
00061 double ymin = -5.0*Munits::m, ymax = +5.0*Munits::m;
00062 double scalea = 1.0;
00063 int xpixels = 800, ypixels = 800;
00064 int nx=500, ny=500;
00065 int nxa=40, nya=40;
00066
00067 DetermineLimits(xmin,xmax,ymin,ymax,xpixels,ypixels);
00068 DetermineColorGrid(nx,ny);
00069 DetermineArrowGrid(nxa,nya,scalea);
00070
00071 std::string cname = tag; cname += "_canvas";
00072 std::string sname = tag;
00073 std::string pname = tag; pname += "_phase";
00074 fCanvas = new TCanvas(cname.c_str(),cname.c_str(),xpixels,ypixels);
00075 fScatter = new TH2F(sname.c_str(),sname.c_str(),nx,xmin,xmax,ny,ymin,ymax);
00076 fPhase = new TH2F(pname.c_str(),pname.c_str(),nxa,xmin,xmax,nya,ymin,ymax);
00077 AdjustLabels();
00078 SetScaleMax();
00079
00080 }
00081
00082 void BfldCanvas::SetScaleMax(double scale)
00083 {
00084 fScaleMax = scale;
00085 if ( fScatter ) {
00086 fScatter->SetMinimum(fgKGMin*Munits::kilogauss);
00087 fScatter->SetMaximum(fgKGMax*Munits::kilogauss*fScaleMax);
00088 }
00089 }
00090
00091 void BfldCanvas::SetTitle(std::string title)
00092 {
00093 std::string name = title.substr(0,title.find(" "));
00094
00095
00096
00097 static std::map<std::string,int> namecnt;
00098 int icnt = namecnt[title]++;
00099 std::string nameuniq = "";
00100 if ( icnt > 0 ) nameuniq = Form("_%d",icnt);
00101
00102 std::string cname = name;
00103 cname += "_canvas";
00104 fCanvas->SetTitle(cname.c_str());
00105 cname += nameuniq;
00106 fCanvas->SetName(cname.c_str());
00107
00108 fScatter->SetTitle("");
00109 title += "_phase";
00110 fPhase->SetTitle(title.c_str());
00111
00112 name += nameuniq;
00113 fScatter->SetName(name.c_str());
00114 name += "_phase";
00115 fPhase->SetName(name.c_str());
00116
00117 }
00118
00119 void BfldCanvas::Fill(BField& bfld)
00120 {
00121 Fill(&bfld,0);
00122 }
00123 void BfldCanvas::Fill(BfldHandler& bhandler)
00124 {
00125 Fill(0,&bhandler);
00126 }
00127
00128 void BfldCanvas::Draw()
00129 {
00130 fCanvas->Draw();
00131 fCanvas->cd();
00132 AdjustMargins();
00133
00134 fScatter->SetContour(gStyle->GetNumberOfColors());
00135 fScatter->Draw("COLZ");
00136
00137 if ( fArrowScale > 0 ) DrawArrows();
00138
00139
00140
00141
00142
00143 fCanvas->Update();
00144
00145 }
00146
00147 void BfldCanvas::DetermineLimits(double& xmin, double& xmax,
00148 double& ymin, double& ymax,
00149 int& xpixels, int& ypixels)
00150 {
00151 xmin = -5.0*Munits::m; xmax = +5.0*Munits::m;
00152 ymin = -5.0*Munits::m; ymax = +5.0*Munits::m;
00153
00154 if (Detector::kNear == fVldc.GetDetector()) {
00155 xmin = -2.8*Munits::m, xmax = +4.0*Munits::m;
00156 ymin = -2.4*Munits::m, ymax = +2.4*Munits::m;
00157 }
00158
00159 if ( fIsCoil > 0 ) {
00160
00161 xmin = -0.55*Munits::m, xmax = +0.55*Munits::m;
00162 ymin = -0.55*Munits::m, ymax = +0.55*Munits::m;
00163
00164 if ( fIsCoil > 1 ) {
00165 xmin = -0.35*Munits::m, xmax = +0.35*Munits::m;
00166 ymin = -0.35*Munits::m, ymax = +0.35*Munits::m;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 }
00177
00178 xpixels = ypixels = 800;
00179 xpixels = TMath::Nint(ypixels * (xmax-xmin)/(ymax-ymin));
00180 }
00181
00182 void BfldCanvas::DetermineColorGrid(int& nx, int& ny)
00183 {
00184 nx = ny = 500;
00185 }
00186
00187 void BfldCanvas::DetermineArrowGrid(int& nxa, int& nya, double& scalea)
00188 {
00189 nxa = nya = 40;
00190 scalea = 1.0;
00191
00192 if ( fIsCoil ) {
00193
00194 nxa = nya = 25;
00195 scalea = 2.5;
00196
00197 nxa = nya = 40;
00198 scalea = 2.0;
00199 }
00200
00201 double xmin, xmax, ymin, ymax;
00202 int xpixels, ypixels;
00203 DetermineLimits(xmin,xmax,ymin,ymax,xpixels,ypixels);
00204
00205 scalea = 1.5*5.0*(Munits::cm)*(xmax-xmin)/10.0*(Munits::m);
00206
00207 scalea *= fArrowScale;
00208
00209
00210 nxa = TMath::Nint((float)(nxa) * (float)fgArrowGridX/40.0);
00211
00212
00213 nya = TMath::Nint((float)(nxa) * (ymax-ymin)/(xmax-xmin));
00214
00215 }
00216
00217 void BfldCanvas::AdjustLabels()
00218 {
00219 fScatter->SetStats(false);
00220 fScatter->SetDirectory(0);
00221 fScatter->SetXTitle("x [ m ]");
00222 fScatter->SetYTitle("y [ m ]");
00223 fScatter->SetZTitle("B [ T ]");
00224 double tsize = 0.045, lsize = 0.035;
00225 fScatter->GetXaxis()->SetTitleSize(tsize);
00226 fScatter->GetYaxis()->SetTitleSize(tsize);
00227 fScatter->GetZaxis()->SetTitleSize(tsize);
00228 fScatter->GetXaxis()->SetLabelSize(lsize);
00229 fScatter->GetYaxis()->SetLabelSize(lsize);
00230 fScatter->GetZaxis()->SetLabelSize(lsize);
00231 }
00232
00233 void BfldCanvas::AdjustMargins()
00234 {
00235 fCanvas->SetTopMargin(0.1625);
00236 fCanvas->SetBottomMargin(0.10);
00237 fCanvas->SetLeftMargin(0.10);
00238 fCanvas->SetRightMargin(0.1875);
00239 }
00240
00241 void BfldCanvas::Fill(BField* bfld, BfldHandler* bhandler)
00242 {
00243
00244 TVector3 xyz, bxyz;
00245
00246 xyz.SetZ(fZ);
00247
00248 if (fgVerbose) cout << " start loop over grid " << endl;
00249
00250
00251 for (int pass=0; pass<2; ++pass) {
00252 TH2F* h2 = ((pass==0) ? fScatter : fPhase );
00253 double x, y;
00254 int ix, iy;
00255
00256
00257
00258
00259 TAxis* xaxis = h2->GetXaxis();
00260 int nx = xaxis->GetNbins();
00261 double xmin = xaxis->GetXmin();
00262 double xmax = xaxis->GetXmax();
00263
00264 TAxis* yaxis = h2->GetYaxis();
00265 int ny = yaxis->GetNbins();
00266 double ymin = yaxis->GetXmin();
00267 double ymax = yaxis->GetXmax();
00268
00269 if (fgVerbose) {
00270 cout << " x " << xmin << " " << xmax << " nx " << nx << endl;
00271 cout << " y " << ymin << " " << ymax << " ny " << ny << endl;
00272 }
00273
00274
00275
00276
00277 for (ix=1; ix<=nx; ++ix) {
00278 x = xaxis->GetBinCenter(ix);
00279 xyz.SetX(x);
00280 for (iy=1; iy<=ny; ++iy) {
00281 y = yaxis->GetBinCenter(iy);
00282 xyz.SetY(y);
00283
00284
00285
00286 if ( bfld ) {
00287 bxyz = bfld->GetBField(xyz);
00288 } else if ( bhandler ) {
00289 bxyz = bhandler->GetBField(xyz,false);
00290 }
00291
00292 double bmag = bxyz.Mag();
00293 double value = bmag;
00294 if ( pass == 1 ) {
00295 double phi = ( (bmag > 0.0) ? bxyz.Phi() : 42 );
00296 value = phi;
00297 }
00298 h2->Fill(x,y,value);
00299
00300 #ifdef RWHDEBUG
00301 double r2 = x*x + y*y;
00302 double r2lo = 0.09 * 0.09;
00303 double r2hi = 0.12 * 0.12;
00304
00305 if ( false && r2lo < r2 && r2 < r2hi ) {
00306 if (fgVerbose) cout << " pos " << xyz << " B " << bxyz << endl;
00307 }
00308 #endif
00309
00310 }
00311 }
00312
00313 }
00314
00315 }
00316
00317 void BfldCanvas::DrawArrows()
00318 {
00319
00320 int i,j;
00321 double scalea;
00322 DetermineArrowGrid(i,j,scalea);
00323
00324 TAxis* xaxis = fPhase->GetXaxis();
00325 int nx = xaxis->GetNbins();
00326
00327
00328
00329 TAxis* yaxis = fPhase->GetYaxis();
00330 int ny = yaxis->GetNbins();
00331
00332
00333
00334 double x, y;
00335 int ix, iy;
00336
00337
00338
00339
00340 for (ix=1; ix<=nx; ++ix) {
00341 x = xaxis->GetBinCenter(ix);
00342 for (iy=1; iy<=ny; ++iy) {
00343 y = yaxis->GetBinCenter(iy);
00344
00345 int ihashbin = fPhase->GetBin(ix,iy);
00346 double phi = fPhase->GetBinContent(ihashbin);
00347 if ( phi > TMath::TwoPi() ) continue;
00348
00349 double bx = TMath::Cos(phi);
00350 double by = TMath::Sin(phi);
00351 DrawCheveron(x,y,bx,by,scalea);
00352
00353 }
00354 }
00355
00356 }
00357
00358 void BfldCanvas::DrawCheveron(double x0, double y0, double dx, double dy,
00359 double scale)
00360 {
00361 static double xp[] = { -0.16, -0.50, 0.60, -0.50, -0.16};
00362 static double yp[] = { 0.00, 0.25, 0.00, -0.25, 0.00};
00363 double x[5], y[5];
00364 double len = TMath::Sqrt(dx*dx+dy*dy);
00365 if (len<=0) return;
00366 double c = dx/len;
00367 double s = dy/len;
00368
00369 for (int i=0; i<5; ++i) {
00370 x[i] = (xp[i]*c - yp[i]*s)*scale + x0;
00371 y[i] = (xp[i]*s + yp[i]*c)*scale + y0;
00372 }
00373 static TPolyLine cheveron;
00374 cheveron.SetLineWidth(1);
00375 cheveron.DrawPolyLine(5,x,y);
00376
00377
00378
00379
00380 }
00381
00382 std::string BfldCanvas::GetZoomInterpString()
00383 {
00384 std::string result = ( GetIsCoil() ? "_coil" : "_full");
00385 int im = GetInterpMethod();
00386 if ( im != (int)BfldInterpMethod::kDefault )
00387 result += Form("_im%d",im);
00388 return result;
00389 }