void drawPatch(GLfloat *ptrData, GLuint &ptrIndex, GLfloat p1[3], GLfloat p2[3], GLfloat p3[3], int level, GLuint *count)
{
	int i;
	if (level > 0) {
		GLfloat q1[3],q2[3],q3[3];		 // sub-vertices
		for (i=0; i<3; i++) {
			q1[i] = 0.5f*(p1[i]+p2[i]);
			q2[i] = 0.5f*(p2[i]+p3[i]);
			q3[i] = 0.5f*(p3[i]+p1[i]);
		}
		GLfloat length1 = (GLfloat)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2]));
		GLfloat length2 = (GLfloat)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2]));
		GLfloat length3 = (GLfloat)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2]));
		for (i=0; i<3; i++) {
			q1[i] *= length1;
			q2[i] *= length2;
			q3[i] *= length3;
		}
		drawPatch(ptrData,ptrIndex,p1,q1,q3,level-1,count);
		drawPatch(ptrData,ptrIndex,q1,p2,q2,level-1,count);
		drawPatch(ptrData,ptrIndex,q1,q2,q3,level-1,count);
		drawPatch(ptrData,ptrIndex,q3,q2,p3,level-1,count);
	} else {
		if( count ) {
			*count += 3;
		} else {
			EmitVertex(ptrData,ptrIndex,p1[0],p1[1],p1[2]); // vertex
			EmitVertex(ptrData,ptrIndex,p1[0],p1[1],p1[2]); // normal
			EmitVertex(ptrData,ptrIndex,p2[0],p2[1],p2[2]); // vertex
			EmitVertex(ptrData,ptrIndex,p2[0],p2[1],p2[2]); // normal
			EmitVertex(ptrData,ptrIndex,p3[0],p3[1],p3[2]); // vertex
			EmitVertex(ptrData,ptrIndex,p3[0],p3[1],p3[2]); // normal
		}
	}
}
Example #2
0
void drawVarAllCent (double, double highPt, TH1D* hvar, TString var,TString varName,  TCut addCut, bool doLog, TString subName,bool onleMC, float maxY ) {
   
   TCanvas* c2 = new TCanvas(Form("c2_%s%s",var.Data(),subName.Data()),"",1000,400);
   makeMultiPanelCanvas(c2,3,1,0.0,0.0,0.2,0.15,0.02);
   for ( int icent = 1 ; icent<=3 ; icent++) {
      int lowCent = centBin_std[icent-1];
      int highCent = centBin_std[icent]-1; 
      c2->cd(4-icent);
      drawVariable(lowCent,highCent,60,10000,hvar, var, addCut,doLog,onleMC, maxY);
      if (doLog )    
	 gPad->SetLogy();
      
      drawText(Form("%.0f %% - %.0f %%", float((float)lowCent*2.5), float((float)(highCent+1)*2.5)),0.6580963,0.9069118,1,16);
      //  drawText("Photon E_{T} > 60GeV",0.3680963,0.6569118,1,15);
      if ( icent == 1 ) {
	 if (!onleMC) drawCMS2011(0.338,0.906,84,16);
      }
      if (icent==2) { 
	 TH1D* data = new TH1D("data11","",1,0,1);
	 data->Sumw2();
	 TH1D* mcSig = new TH1D("mcSig11","",1,0,1);
	 mcStyle(mcSig);
	 TH1D* mcBkg = new TH1D("mcBkg11","",1,0,1);
         dijetStyle(mcBkg);
	 TLegend* leg1 = new TLegend(0.1586395,0.7137837,0.9992263,0.9626509,NULL,"brNDC");
	 easyLeg(leg1,varName.Data());
	 if( !onleMC) leg1->AddEntry(data,"Data","pl");
	 leg1->AddEntry(mcSig,"MC #gamma-jet + HYDJET","fl");
	 leg1->AddEntry(mcBkg,"MC dijet Background","fl");
	 leg1->Draw();
      }
   
      drawPatch(0,0,0.05,0.14,0,1001,"NDC");
      drawPatch(0.93,0.05,1.01,0.14,0,1001,"NDC");

   }
   
   if (subName ==""){
      c2->SaveAs(Form("%s_MCvsDATA_allCent.pdf",var.Data()));
      c2->SaveAs(Form("%s_MCvsDATA_allCent.gif",var.Data()));
   }
   else {
      c2->SaveAs(Form("%s_MCvsDATA_allCent.pdf",subName.Data()));
      c2->SaveAs(Form("%s_MCvsDATA_allCent.gif",subName.Data()));
   }
   
   
}
void plotSubLeadingJetAllCent_onlyImbalancedJets() {

  TCanvas *c1 = new TCanvas("c1","",1250,530);

  makeMultiPanelCanvas(c1,3,1,0.0,0.0,0.2,0.15,0.02);

  c1->cd(1);
  plotLeadingJet(2,"data.root","pythia.root","mix.root",true,false,false);
  gPad->SetLogy();
  drawText("30-100%",0.25,0.24);
  drawPatch(0.976,0.0972,1.1,0.141);


  c1->cd(2);
  plotLeadingJet(1,"data.root","pythia.root","mix.root",true,true,false);
  gPad->SetLogy();
  drawText("10-30%",0.10,0.24);
  drawPatch(-0.00007,0.0972,0.0518,0.141);
  drawPatch(0.976,0.0972,1.1,0.141);

  c1->cd(3);
  plotLeadingJet(0,"data.root","pythia.root","mix.root",true,false,true);
  gPad->SetLogy();
  drawText("0-10%",0.10,0.24);
  drawPatch(-0.00007,0.0972,0.0518,0.141);

  TLatex *cms = new TLatex(81,1.8,"CMS Preliminary");
  cms->SetTextFont(63);
  cms->SetTextSize(18);
  cms->Draw();                                                                                                                                        
  //  TLatex *imb = new TLatex(150,0.18,"(p_{T}^{j1}-p_{T}^{j2})/(p_{T}^{j1}+p_{T}^{j2})>0.3");
  TLatex *imb = new TLatex(81,0.27,"A_{J} > 0.3");
  imb->SetTextFont(63);
  imb->SetTextSize(18);
  imb->Draw();  
  
  TLatex *lumi = new TLatex(111,1.8,"#intL dt = 6.7 #mub^{-1}");
  lumi->SetTextFont(63);
  lumi->SetTextSize(15);
  lumi->Draw(); 

  c1->Print("./fig/dijet_subleadingjet_all_cent_onlyImbalancedJets_20101127_v0.gif");
  c1->Print("./fig/dijet_subleadingjet_all_cent_onlyImbalancedJets_20101127_v0.eps");
  c1->Print("./fig/dijet_subleadingjet_all_cent_onlyImbalancedJets_20101127_v0.pdf");

}
void plotBackgroundSystematics(){
   
   TCanvas *c1 = new TCanvas("c1","",1650,430);
   makeMultiPanelCanvas(c1,5,1,0.0,0.0,0.2,0.15,0.02);
   
   c1->cd(1);
   plotRatio(4,"mix.root","mix.root","pythia.root",false,false,false);
   drawText("50-100%",0.76,0.24);
   drawPatch(0.976,0.0972,1.1,0.171);
   gPad->SetLeftMargin(0.25);
   gPad->SetBottomMargin(0.18);
   
  c1->cd(2);
  plotRatio(3,"mix.root","mix.root","pythia.root",false,false,false);
  drawText("30-50%",0.75,0.24);
  drawPatch(-0.00007,0.0972,0.0518,0.171);
  drawPatch(0.976,0.0972,1.1,0.171);
  gPad->SetBottomMargin(0.18);

  c1->cd(3);
  plotRatio(2,"mix.root","mix.root","pythia.root",false,true,false);
  drawText("20-30%",0.75,0.24);
  drawPatch(-0.00007,0.0972,0.0518,0.171);
  gPad->SetBottomMargin(0.18);
  drawPatch(0.976,0.0972,1.1,0.171);

  c1->cd(4);
  plotRatio(1,"mix.root","mix.root","pythia.root",false,false,false);
  drawText("10-20%",0.75,0.24);
  drawPatch(-0.00007,0.0972,0.0518,0.171);
  gPad->SetBottomMargin(0.18);
  drawPatch(0.976,0.0972,1.1,0.171);

  c1->cd(5);
  plotRatio(0,"mix.root","mix.root","pythia.root",false,false,true);
  drawText("0-10%",0.75,0.24);
  gPad->SetBottomMargin(0.18);
  drawPatch(-0.00007,0.0972,0.0518,0.171);

  TLatex *cms = new TLatex(0.086,4.5,"CMS Preliminary");
  cms->SetTextFont(63);
  cms->SetTextSize(18);
  cms->Draw();                                                                                                                                        

  TLatex *lumi = new TLatex(0.15,4.1,"#intL dt = 7 #mub^{-1}");
  lumi->SetTextFont(63);
  lumi->SetTextSize(15);
//  lumi->Draw(); 

  c1->Print("./fig/ratio_pythiaToMix_20101207_v0.gif");
  c1->Print("./fig/ratio_pythiaToMix_20101207_v0.eps");
  c1->Print("./fig/ratio_pythiaToMix_20101207_v0.pdf");

}
void plotLeadingEtaBalance_AllCent(){

  TCanvas *c1 = new TCanvas("c1","",1250,530);

  makeMultiPanelCanvas(c1,3,1,0.0,0.0,0.2,0.15,0.02);

  c1->cd(1);
  plotDeltaPhi(2,"data.root","pythia.root","mix.root",true,false,false);
  gPad->SetLogy();
  drawText("30-100%",0.77,0.66);
  drawPatch(0.976,0.0972,1.1,0.141);

  c1->cd(2);
  plotDeltaPhi(1,"data.root","pythia.root","mix.root",true,true,false);
  gPad->SetLogy();
  drawText("10-30%",0.75,0.66);
  drawPatch(-0.00007,0.0972,0.0518,0.141);
  drawPatch(0.976,0.0972,1.1,0.141);

  c1->cd(3);
  plotDeltaPhi(0,"data.root","pythia.root","mix.root",true,false,true);
  gPad->SetLogy();
  drawText("0-10%",0.75,0.66);
  drawPatch(-0.00007,0.0972,0.0518,0.141);

  TLatex *cms = new TLatex(-2.,2.49,"CMS Preliminary");
  cms->SetTextFont(63);
  cms->SetTextSize(18);
  cms->Draw();                                                                                                                                        
  TLatex *lumi = new TLatex(0.3,2.49,"#intL dt = 6.7 #mub^{-1}");
  lumi->SetTextFont(63);
  lumi->SetTextSize(15);
  lumi->Draw(); 

  TLatex *aj= new TLatex(-2.,0.2,"A_{J} < 0.3");
  aj->SetTextFont(63);
  aj->SetTextSize(18);
  aj->Draw();

  c1->Print("./fig/dijet_leadingEta_balance_all_cent_20101126_v0.gif");
  c1->Print("./fig/dijet_leadingEta_balance_all_cent_20101126_v0.eps");
  c1->Print("./fig/dijet_leadingEta_balance_all_cent_20101126_v0.pdf");

}
void getBatchFaceCount(
	// input
	const double *FM, int fNum, const double *VM, int vNum, const double *objCenterV, double maxRadius,
	const double *majorAxisM, const double *lightDirM, int lightNum, int maxHeight, int maxWidth, 
	unsigned int channelModFactor,
	// output
	void *FacePixelCountM)
{
	int i;
	
	GLubyte *imageBuffer = (GLubyte *) mxMalloc(maxHeight * maxWidth * 3);
	GLuint batchList = createDisplayList(FM, fNum, VM, vNum, channelModFactor);

	
	//memset(FacePixelCountM, 0, sizeof(double) * fNum * lightNum);
	
	printf("Facet Number: %d, Vertex Number: %d\nProjecting images: \n", fNum, vNum);
	
	float screenScale;
	
	// make sure that maxHeight always >= maxWidth
	if (maxHeight < maxWidth) {
		int temp = maxHeight;
		maxHeight = maxWidth;
		maxWidth = temp;	
	}
	
	for (i = 0; i < lightNum; i++) {
		
		printf(" %d ", i);
		if (i % 16 == 15) {
			printf("\n");
		}		
		orthoCameraSetup(objCenterV, lightDirM + 3*i, maxRadius, majorAxisM, maxHeight, maxWidth, screenScale);

		drawPatch(batchList, imageBuffer, maxHeight, maxWidth);		
		
		extractFaceCount(imageBuffer, channelModFactor, maxHeight, maxWidth, fNum, i%(32),
			(unsigned int*) FacePixelCountM + i/32 * fNum);
	}
	printf("\n");
	mxFree(imageBuffer);	
		
}
void Patch::draw() {

    if (isMouseOver()) {
        hover = true;
    } else {
        hover = false;
    }

    ofPushStyle();
    ofSetColor(150.0f);
    ofEnableSmoothing();
    ofEnableAntiAliasing();
    ofSetLineWidth(2.0f);

    if (port_connect) {
        ofLine(line_start, ofPoint(ofGetMouseX(), ofGetMouseY()));
    }

    // also draw all connections
    for (int i = 0; i < connections.size(); i++) {
        ofLine(connections[i]->from->cp, connections[i]->to->cp);
    }

    ofPopStyle();


    switch (type) {
    case PATCH:
        drawPatch();
        break;
    case UI_BUTTON:
        drawButton();
        break;
    case UI_FIXED_BUTTON:
        drawFixedButton();
        break;
    };
}
void drawSphere(GLfloat *ptrData, GLuint &ptrIndex, int sphere_quality, GLuint *count)
{
	// icosahedron data for an icosahedron of radius 1.0
#define ICX 0.525731112119133606f
#define ICZ 0.850650808352039932f
	static GLfloat idata[12][3] = {
		{-ICX, 0, ICZ},
		{ICX, 0, ICZ},
		{-ICX, 0, -ICZ},
		{ICX, 0, -ICZ},
		{0, ICZ, ICX},
		{0, ICZ, -ICX},
		{0, -ICZ, ICX},
		{0, -ICZ, -ICX},
		{ICZ, ICX, 0},
		{-ICZ, ICX, 0},
		{ICZ, -ICX, 0},
		{-ICZ, -ICX, 0}
	};

	static int index[20][3] = {
		{0, 4, 1},	  {0, 9, 4},
		{9, 5, 4},	  {4, 5, 8},
		{4, 8, 1},	  {8, 10, 1},
		{8, 3, 10},   {5, 3, 8},
		{5, 2, 3},	  {2, 7, 3},
		{7, 10, 3},   {7, 6, 10},
		{7, 11, 6},   {11, 0, 6},
		{0, 1, 6},	  {6, 1, 10},
		{9, 0, 11},   {9, 11, 2},
		{9, 2, 5},	  {7, 2, 11},
	};

	for (int i=0; i<20; i++) {
		drawPatch(ptrData, ptrIndex, &idata[index[i][2]][0],&idata[index[i][1]][0],
			&idata[index[i][0]][0],sphere_quality, count);
	}
}
// ######################################################################
void SimulationViewerStats::save1(const ModelComponentSaveInfo& sinfo)
{
  // Use a LINFO here since we are already slowed down by writing
  // stats, we should at least have a short debug on this fact
  LINFO("SAVING STATS TO %s",itsStatsFname.getVal().c_str());

  // Lock the file. We put this here to support multi-process in the
  // future. However, this will not work on NFS mounts.
  struct flock fl; int fd;
  lockFile(itsStatsFname.getVal().c_str(),fd,fl);

  // Since this is more or less debug info we open and flush every iteration.
  // rather than once each run.
  std::ofstream statsFile;
  statsFile.open(itsStatsFname.getVal().c_str(),std::ios_base::app);

  // get the OFS to save to, assuming sinfo is of type
  // SimModuleSaveInfo (will throw a fatal exception otherwise):
  nub::ref<FrameOstream> ofs =
    dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs;

  // also get the SimEventQueue:
  SimEventQueue *q    = dynamic_cast<const SimModuleSaveInfo&>(sinfo).q;

  // initialize our stats dump file if desired:
  if(itsFrameIdx == 0)
  {
    rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
    q->request(vcxm); // VisualCortex is now filling-in the maps...

    if (itsStatsFname.getVal().size())
    {
      itsStatsFile = new std::ofstream(itsStatsFname.getVal().c_str());
      if (itsStatsFile->is_open() == false)
        LFATAL("Failed to open '%s' for writing.",
               itsStatsFname.getVal().c_str());

      // dump the settings of the model:
      getRootObject()->printout(*itsStatsFile, "# ");

      // list all our channels:
      //LFATAL("FIXME");
      // also get the SimEventQueue:

      rutz::shared_ptr<ChannelMaps> chm        = vcxm->channelmaps();
      uint                          numSubmaps = chm->numSubmaps();

      *itsStatsFile << "# CHANNELS: ";

      for(uint i = 0; i < numSubmaps; i++)
      {
        NamedImage<float> smap = chm->getRawCSmap(i);
        *itsStatsFile << smap.name() << ", ";
      }
      *itsStatsFile << std::endl;
    }
  }

  // We flush frequently since this output is debuggy in nature or it's being used
  // to collect information which needs assurance of accuracy for instance in
  // RSVP analysis. It is better to err on the side of caution.
  (*itsStatsFile).flush();
  (*itsStatsFile).close();

  // get the basic input frame info
  if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this))
  {
    itsSizeX       = e->frame().getWidth();
    itsSizeY       = e->frame().getHeight();
    itsFrameNumber = (unsigned int)e->frameNum();
    itsFrameIdx    = itsFrameNumber;
  }
  else
  {
    itsFrameNumber = itsFrameIdx;
    itsFrameIdx++;
  }

  // get the latest input frame:
  // Since we are only using it's basic statistics (Height / Width) , we don't care about it's
  // blackboard status. Use SEQ_ANY then. Otherwise, this will not fetch at any rate.
  Image< PixRGB<byte> > input;
  if (SeC<SimEventRetinaImage> e = q->check<SimEventRetinaImage>(this,SEQ_ANY))
    input = e->frame().colorByte();
  else
    LINFO("No input? Check the SimEventCue.");

  // Get the current frame number or keep track on your own
  /*
  if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this))
    itsFrameIdx = e->frameNum();
  else
    itsFrameIdx++;
  */

  // get the latest raw AGM:
  Image<float> agm;
  if (SeC<SimEventAttentionGuidanceMapOutput> e =
      q->check<SimEventAttentionGuidanceMapOutput>(this))
    agm = e->agm(1.0F);
  else
    LINFO("No AGM? Check the SimEventCue.");

  // if we are missing input or agm, return:
  // We also need to warn so that we know why the stats file may be empty
  bool quit = false;
  if (input.initialized() == false)
    {
      LINFO("WARNING!!! Input seems not to be initialized, so detailed stats cannot be saved.");
      quit = true;
    }
  if(agm.initialized() == false)
    {
      LINFO("WARNING!!! NO Attention Guidance MAP \"AGM\" so detailed stats cannot be saved.");
      quit = true;
    }

  if(quit == true) return;

  // update the trajectory:
  Image< PixRGB<byte> > res;
  const int w = input.getWidth();

  // save image results? if so let's prepare it
  if (itsSaveXcombo.getVal() || itsSaveYcombo.getVal())
    {
      Image<float> nagm = getMap(*q);
      res = colGreyCombo(input, nagm, itsSaveXcombo.getVal(),
                         itsDisplayInterp.getVal());
    }

  // if we are saving single channel stats save saliency stats using a compatable format
  // SEE: SingleChannel.C / saveStats(..) for more info on format
  if (itsGetSingleChannelStats.getVal())
    saveCompat(agm);

  // Save a bunch of stats?
  if (statsFile)
    {
      // start with the current simulation time:
       statsFile <<std::endl<<"= "<<q->now().msecs()
                     <<" # time of frame in ms"<<std::endl;

      // get min/max/avg and stdev and number of peaks in AGM:
      float mi, ma, av; getMinMaxAvg(agm, mi, ma, av);
      double sdev = stdev(agm);
      double peaksum; int npeaks = findPeaks(agm, 0.0f, 255.0f, peaksum);

      // find the location of max in the AGM, at scale of original input:
      float maxval; Point2D<int> maxloc;
      findMax(agm, maxloc, maxval);
      float scale = float(w) / float(agm.getWidth());
      maxloc.i = int(maxloc.i * scale + 0.4999F);
      maxloc.j = int(maxloc.j * scale + 0.4999F);
      if (res.initialized())
        {
          drawPatch(res, maxloc, 4, COL_YELLOW);
          drawPatch(res, maxloc + Point2D<int>(w, 0), 4, COL_YELLOW);
        }

      // find the location of min in the AGM, at scale of original input:
      float minval; Point2D<int> minloc;
      findMin(agm, minloc, minval);
      minloc.i = int(minloc.i * scale + 0.4999F);
      minloc.j = int(minloc.j * scale + 0.4999F);
      if (res.initialized())
        {
          drawPatch(res, minloc, 4, COL_GREEN);
          drawPatch(res, minloc + Point2D<int>(w, 0), 4, COL_GREEN);
        }

      // save some stats for that location:
       statsFile  <<maxloc.i<<' '<<maxloc.j<<' '<<minloc.i<<' '
                  <<minloc.j<<' '<<ma<<' '<<mi<<' '<<av<<' '<<sdev
                  <<' '<<npeaks<<' '<<peaksum
                  <<" # Xmax Ymax Xmin Ymin max min avg std npeaks peaksum"
                  <<std::endl;

      // build a vector of points where we will save samples. First is
      // the max, second the min, then a bunch of random locations:
      std::vector<Point2D<int> > loc;
      loc.push_back(maxloc);
      loc.push_back(minloc);
      for (uint n = 0; n < 100; n ++)
        loc.push_back(Point2D<int>(randomUpToNotIncluding(input.getWidth()),
                              randomUpToNotIncluding(input.getHeight())));

      // Get all the conspicuity maps:
      ImageSet<float> cmap;
      //LFATAL("FIXME");
      rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
      q->request(vcxm); // VisualCortex is now filling-in the maps...
      rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps();
      uint numSubmaps = chm->numSubmaps();
      for(uint i=0;i < numSubmaps; i++)
      {
        NamedImage<float> tempMap = chm->getRawCSmap(i);
        Image<float> m = tempMap;
        cmap.push_back(m);

        // also store sample points at the min/max locations:
        Point2D<int> p; float v;
        findMax(m, p, v); loc.push_back(p);
        findMin(m, p, v); loc.push_back(p);
      }
      /*
      for (uint i = 0; i < itsBrain->getVC()->numChans(); i ++)
        {
          Image<float> m = itsBrain->getVC()->subChan(i)->getOutput();
          cmap.push_back(m);

          // also store sample points at the min/max locations:
          Point2D<int> p; float v;
          findMax(m, p, v); loc.push_back(p);
          findMin(m, p, v); loc.push_back(p);
        }
      */

      // Go over all sample points and save feature map and
      // conspicuity map values at those locations:
      for (uint i = 0; i < loc.size(); i ++)
        {
          Point2D<int> p = loc[i];
          Point2D<int> pp(int(p.i / scale), int(p.j / scale));

           statsFile <<p.i<<' '<<p.j<<"     ";

          // do the conspicuity maps first. Since they are all at the
          // scale of the AGM, we use pp:
          for (uint j = 0; j < cmap.size(); j ++)
          {
            if((int(p.i / scale) < agm.getWidth()) &&
               (int(p.j / scale) < agm.getHeight()))
            {
              (statsFile)<<cmap[j].getVal(pp)<<' ';
              (statsFile)<<"    ";
            }
            else
            {
              (statsFile)<<"-1"<<' ';
              (statsFile)<<"    ";
            }
          }

          // now the feature maps, we use coordinates p:
          /* TOO BOGUS - disabled for now
          std::vector<double> f;
          itsBrain->getVC()->getFeatures(p, f);
          for (uint j = 0; j < f.size(); j ++) (*statsFile)<<f[j]<<' ';
          */

           statsFile  <<"# features "<<i<<" at ("<<p.i
                         <<", "<<p.j<<')'<<std::endl;
        }
  }

  statsFile.flush();
  statsFile.close();
  unlockFile(itsStatsFname.getVal().c_str(),fd,fl);
  // save results?
  if (res.initialized())
    ofs->writeRGB(res, "T",
                  FrameInfo("SimulationViewerStats trajectory", SRC_POS));

  // Should we compute attention gate stats
  // If we have AG stats we will save the basic LAM stats anyways
  if(itsComputeAGStats.getVal())
    computeAGStats(*q);
  else if (SeC<SimEventAttentionGateOutput> ag =
           q->check<SimEventAttentionGateOutput>(this))
    computeLAMStats(ag->lam());

  //! Save the overlap image
  if(itsOverlap.initialized())
    ofs->writeRGB(itsOverlap, "AG-STAT-MASK",
                  FrameInfo("Stats mask overlap", SRC_POS));

  if(itsVisualSegments.initialized())
    ofs->writeRGB(itsVisualSegments, "AG-STAT-SEGS",
                  FrameInfo("Stats segments", SRC_POS));

  if(itsVisualCandidates.initialized())
    ofs->writeGray(itsVisualCandidates, "AG-STAT-CAND",
                   FrameInfo("Stats candidates", SRC_POS));

}
Example #10
0
namespace SkRecords {

// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
static SkBitmap shallow_copy(const SkBitmap& bitmap) {
    return bitmap;
}

// NoOps draw nothing.
template <> void Draw::draw(const NoOp&) {}

#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
DRAW(Restore, restore());
DRAW(Save, save());
DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags));
DRAW(PopCull, popCull());
DRAW(PushCull, pushCull(r.rect));
DRAW(Clear, clear(r.color));
DRAW(Concat, concat(r.matrix));
DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));

DRAW(ClipPath, clipPath(r.path, r.op, r.doAA));
DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA));
DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA));
DRAW(ClipRegion, clipRegion(r.region, r.op));

DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint));
DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint));
DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint));
DRAW(DrawBitmapRectToRect,
        drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags));
DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
DRAW(DrawOval, drawOval(r.oval, r.paint));
DRAW(DrawPaint, drawPaint(r.paint));
DRAW(DrawPath, drawPath(r.path, r.paint));
DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode.get(), r.paint));
DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint));
DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
DRAW(DrawRect, drawRect(r.rect, r.paint));
DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint));
DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint));
DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
                                r.xmode.get(), r.indices, r.indexCount, r.paint));
#undef DRAW


// This is an SkRecord visitor that fills an SkBBoxHierarchy.
//
// The interesting part here is how to calculate bounds for ops which don't
// have intrinsic bounds.  What is the bounds of a Save or a Translate?
//
// We answer this by thinking about a particular definition of bounds: if I
// don't execute this op, pixels in this rectangle might draw incorrectly.  So
// the bounds of a Save, a Translate, a Restore, etc. are the union of the
// bounds of Draw* ops that they might have an effect on.  For any given
// Save/Restore block, the bounds of the Save, the Restore, and any other
// non-drawing ("control") ops inside are exactly the union of the bounds of
// the drawing ops inside that block.
//
// To implement this, we keep a stack of active Save blocks.  As we consume ops
// inside the Save/Restore block, drawing ops are unioned with the bounds of
// the block, and control ops are stashed away for later.  When we finish the
// block with a Restore, our bounds are complete, and we go back and fill them
// in for all the control ops we stashed away.
class FillBounds : SkNoncopyable {
public:
    FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.count()) {
        // Calculate bounds for all ops.  This won't go quite in order, so we'll need
        // to store the bounds separately then feed them in to the BBH later in order.
        fCTM.setIdentity();
        for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) {
            record.visit<void>(fCurrentOp, *this);
        }

        // If we have any lingering unpaired Saves, simulate restores to make
        // sure all ops in those Save blocks have their bounds calculated.
        while (!fSaveStack.isEmpty()) {
            this->popSaveBlock();
        }

        // Any control ops not part of any Save/Restore block draw everywhere.
        while (!fControlIndices.isEmpty()) {
            this->popControl(SkIRect::MakeLargest());
        }

        // Finally feed all stored bounds into the BBH.  They'll be returned in this order.
        SkASSERT(NULL != bbh);
        for (uintptr_t i = 0; i < record.count(); i++) {
            if (!fBounds[i].isEmpty()) {
                bbh->insert((void*)i, fBounds[i], true/*ok to defer*/);
            }
        }
        bbh->flushDeferredInserts();
    }

    template <typename T> void operator()(const T& r) {
        this->updateCTM(r);
        this->trackBounds(r);
    }

private:
    struct SaveBounds {
        int controlOps;  // Number of control ops in this Save block, including the Save.
        SkIRect bounds;  // Bounds of everything in the block.
    };

    template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ }
    void updateCTM(const Restore& r)   { fCTM = r.matrix; }
    void updateCTM(const SetMatrix& r) { fCTM = r.matrix; }
    void updateCTM(const Concat& r)    { fCTM.preConcat(r.matrix); }

    // The bounds of these ops must be calculated when we hit the Restore
    // from the bounds of the ops in the same Save block.
    void trackBounds(const Save&)       { this->pushSaveBlock(); }
    // TODO: bounds of SaveLayer may be more complicated?
    void trackBounds(const SaveLayer&)  { this->pushSaveBlock(); }
    void trackBounds(const Restore&)    { fBounds[fCurrentOp] = this->popSaveBlock(); }

    void trackBounds(const Concat&)     { this->pushControl(); }
    void trackBounds(const SetMatrix&)  { this->pushControl(); }
    void trackBounds(const ClipRect&)   { this->pushControl(); }
    void trackBounds(const ClipRRect&)  { this->pushControl(); }
    void trackBounds(const ClipPath&)   { this->pushControl(); }
    void trackBounds(const ClipRegion&) { this->pushControl(); }

    // For all other ops, we can calculate and store the bounds directly now.
    template <typename T> void trackBounds(const T& op) {
        fBounds[fCurrentOp] = this->bounds(op);
        this->updateSaveBounds(fBounds[fCurrentOp]);
    }

    // TODO: remove this trivially-safe default when done bounding all ops
    template <typename T> SkIRect bounds(const T&) { return SkIRect::MakeLargest(); }

    void pushSaveBlock() {
        // Starting a new Save block.  Push a new entry to represent that.
        SaveBounds sb = { 0, SkIRect::MakeEmpty() };
        fSaveStack.push(sb);
        this->pushControl();
    }

    SkIRect popSaveBlock() {
        // We're done the Save block.  Apply the block's bounds to all control ops inside it.
        SaveBounds sb;
        fSaveStack.pop(&sb);
        while (sb.controlOps --> 0) {
            this->popControl(sb.bounds);
        }

        // This whole Save block may be part another Save block.
        this->updateSaveBounds(sb.bounds);

        // If called from a real Restore (not a phony one for balance), it'll need the bounds.
        return sb.bounds;
    }

    void pushControl() {
        fControlIndices.push(fCurrentOp);
        if (!fSaveStack.isEmpty()) {
            fSaveStack.top().controlOps++;
        }
    }

    void popControl(const SkIRect& bounds) {
        fBounds[fControlIndices.top()] = bounds;
        fControlIndices.pop();
    }

    void updateSaveBounds(const SkIRect& bounds) {
        // If we're in a Save block, expand its bounds to cover these bounds too.
        if (!fSaveStack.isEmpty()) {
            fSaveStack.top().bounds.join(bounds);
        }
    }

    SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); }  // NoOps don't draw anywhere.

    SkAutoTMalloc<SkIRect> fBounds;  // One for each op in the record.
    SkMatrix fCTM;
    unsigned fCurrentOp;
    SkTDArray<SaveBounds> fSaveStack;
    SkTDArray<unsigned>   fControlIndices;
};

}  // namespace SkRecords
Example #11
0
namespace SkRecords {

// NoOps draw nothing.
template <> void Draw::draw(const NoOp&) {}

#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
DRAW(Restore, restore());
DRAW(Save, save());
DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds,
                                                 r.paint,
                                                 r.backdrop.get(),
                                                 r.saveLayerFlags)));
DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
DRAW(Concat, concat(r.matrix));
DRAW(Translate, translate(r.dx, r.dy));

DRAW(ClipPath, clipPath(r.path, r.opAA.op, r.opAA.aa));
DRAW(ClipRRect, clipRRect(r.rrect, r.opAA.op, r.opAA.aa));
DRAW(ClipRect, clipRect(r.rect, r.opAA.op, r.opAA.aa));
DRAW(ClipRegion, clipRegion(r.region, r.op));

#ifdef SK_EXPERIMENTAL_SHADOWING
DRAW(TranslateZ, SkCanvas::translateZ(r.z));
#else
template <> void Draw::draw(const TranslateZ& r) { }
#endif

DRAW(DrawArc, drawArc(r.oval, r.startAngle, r.sweepAngle, r.useCenter, r.paint));
DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
DRAW(DrawImage, drawImage(r.image.get(), r.left, r.top, r.paint));

template <> void Draw::draw(const DrawImageLattice& r) {
    SkCanvas::Lattice lattice;
    lattice.fXCount = r.xCount;
    lattice.fXDivs = r.xDivs;
    lattice.fYCount = r.yCount;
    lattice.fYDivs = r.yDivs;
    lattice.fFlags = (0 == r.flagCount) ? nullptr : r.flags;
    lattice.fBounds = &r.src;
    fCanvas->drawImageLattice(r.image.get(), lattice, r.dst, r.paint);
}

DRAW(DrawImageRect, legacy_drawImageRect(r.image.get(), r.src, r.dst, r.paint, r.constraint));
DRAW(DrawImageNine, drawImageNine(r.image.get(), r.center, r.dst, r.paint));
DRAW(DrawOval, drawOval(r.oval, r.paint));
DRAW(DrawPaint, drawPaint(r.paint));
DRAW(DrawPath, drawPath(r.path, r.paint));
DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint));
DRAW(DrawPicture, drawPicture(r.picture.get(), &r.matrix, r.paint));

#ifdef SK_EXPERIMENTAL_SHADOWING
DRAW(DrawShadowedPicture, drawShadowedPicture(r.picture.get(), &r.matrix, r.paint, r.params));
#else
template <> void Draw::draw(const DrawShadowedPicture& r) { }
#endif

DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
DRAW(DrawRect, drawRect(r.rect, r.paint));
DRAW(DrawRegion, drawRegion(r.region, r.paint));
DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
DRAW(DrawTextBlob, drawTextBlob(r.blob.get(), r.x, r.y, r.paint));
DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, &r.matrix, r.paint));
DRAW(DrawTextRSXform, drawTextRSXform(r.text, r.byteLength, r.xforms, r.cull, r.paint));
DRAW(DrawAtlas, drawAtlas(r.atlas.get(),
                          r.xforms, r.texs, r.colors, r.count, r.mode, r.cull, r.paint));
DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
                                r.xmode, r.indices, r.indexCount, r.paint));
DRAW(DrawAnnotation, drawAnnotation(r.rect, r.key.c_str(), r.value.get()));
#undef DRAW

template <> void Draw::draw(const DrawDrawable& r) {
    SkASSERT(r.index >= 0);
    SkASSERT(r.index < fDrawableCount);
    if (fDrawables) {
        SkASSERT(nullptr == fDrawablePicts);
        fCanvas->drawDrawable(fDrawables[r.index], r.matrix);
    } else {
        fCanvas->drawPicture(fDrawablePicts[r.index], r.matrix, nullptr);
    }
}

// This is an SkRecord visitor that fills an SkBBoxHierarchy.
//
// The interesting part here is how to calculate bounds for ops which don't
// have intrinsic bounds.  What is the bounds of a Save or a Translate?
//
// We answer this by thinking about a particular definition of bounds: if I
// don't execute this op, pixels in this rectangle might draw incorrectly.  So
// the bounds of a Save, a Translate, a Restore, etc. are the union of the
// bounds of Draw* ops that they might have an effect on.  For any given
// Save/Restore block, the bounds of the Save, the Restore, and any other
// non-drawing ("control") ops inside are exactly the union of the bounds of
// the drawing ops inside that block.
//
// To implement this, we keep a stack of active Save blocks.  As we consume ops
// inside the Save/Restore block, drawing ops are unioned with the bounds of
// the block, and control ops are stashed away for later.  When we finish the
// block with a Restore, our bounds are complete, and we go back and fill them
// in for all the control ops we stashed away.
class FillBounds : SkNoncopyable {
public:
    FillBounds(const SkRect& cullRect, const SkRecord& record, SkRect bounds[])
        : fNumRecords(record.count())
        , fCullRect(cullRect)
        , fBounds(bounds) {
        fCTM = SkMatrix::I();
        fCurrentClipBounds = fCullRect;
    }

    void cleanUp() {
        // If we have any lingering unpaired Saves, simulate restores to make
        // sure all ops in those Save blocks have their bounds calculated.
        while (!fSaveStack.isEmpty()) {
            this->popSaveBlock();
        }

        // Any control ops not part of any Save/Restore block draw everywhere.
        while (!fControlIndices.isEmpty()) {
            this->popControl(fCullRect);
        }
    }

    void setCurrentOp(int currentOp) { fCurrentOp = currentOp; }


    template <typename T> void operator()(const T& op) {
        this->updateCTM(op);
        this->updateClipBounds(op);
        this->trackBounds(op);
    }

    // In this file, SkRect are in local coordinates, Bounds are translated back to identity space.
    typedef SkRect Bounds;

    int currentOp() const { return fCurrentOp; }
    const SkMatrix& ctm() const { return fCTM; }
    const Bounds& getBounds(int index) const { return fBounds[index]; }

    // Adjust rect for all paints that may affect its geometry, then map it to identity space.
    Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const {
        // Inverted rectangles really confuse our BBHs.
        rect.sort();

        // Adjust the rect for its own paint.
        if (!AdjustForPaint(paint, &rect)) {
            // The paint could do anything to our bounds.  The only safe answer is the current clip.
            return fCurrentClipBounds;
        }

        // Adjust rect for all the paints from the SaveLayers we're inside.
        if (!this->adjustForSaveLayerPaints(&rect)) {
            // Same deal as above.
            return fCurrentClipBounds;
        }

        // Map the rect back to identity space.
        fCTM.mapRect(&rect);

        // Nothing can draw outside the current clip.
        if (!rect.intersect(fCurrentClipBounds)) {
            return Bounds::MakeEmpty();
        }

        return rect;
    }

private:
    struct SaveBounds {
        int controlOps;        // Number of control ops in this Save block, including the Save.
        Bounds bounds;         // Bounds of everything in the block.
        const SkPaint* paint;  // Unowned.  If set, adjusts the bounds of all ops in this block.
        SkMatrix ctm;
    };

    // Only Restore, SetMatrix, Concat, and Translate change the CTM.
    template <typename T> void updateCTM(const T&) {}
    void updateCTM(const Restore& op)   { fCTM = op.matrix; }
    void updateCTM(const SetMatrix& op) { fCTM = op.matrix; }
    void updateCTM(const Concat& op)    { fCTM.preConcat(op.matrix); }
    void updateCTM(const Translate& op) { fCTM.preTranslate(op.dx, op.dy); }

    // Most ops don't change the clip.
    template <typename T> void updateClipBounds(const T&) {}

    // Clip{Path,RRect,Rect,Region} obviously change the clip.  They all know their bounds already.
    void updateClipBounds(const ClipPath&   op) { this->updateClipBoundsForClipOp(op.devBounds); }
    void updateClipBounds(const ClipRRect&  op) { this->updateClipBoundsForClipOp(op.devBounds); }
    void updateClipBounds(const ClipRect&   op) { this->updateClipBoundsForClipOp(op.devBounds); }
    void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); }

    // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside.
    void updateClipBoundsForClipOp(const SkIRect& devBounds) {
        Bounds clip = SkRect::Make(devBounds);
        // We don't call adjustAndMap() because as its last step it would intersect the adjusted
        // clip bounds with the previous clip, exactly what we can't do when the clip grows.
        if (this->adjustForSaveLayerPaints(&clip)) {
            fCurrentClipBounds = clip.intersect(fCullRect) ? clip : Bounds::MakeEmpty();
        } else {
            fCurrentClipBounds = fCullRect;
        }
    }

    // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes.
    void updateClipBounds(const Restore& op) {
        // This is just like the clip ops above, but we need to skip the effects (if any) of our
        // paired saveLayer (if it is one); it has not yet been popped off the save stack.  Our
        // devBounds reflect the state of the world after the saveLayer/restore block is done,
        // so they are not affected by the saveLayer's paint.
        const int kSavesToIgnore = 1;
        Bounds clip = SkRect::Make(op.devBounds);
        if (this->adjustForSaveLayerPaints(&clip, kSavesToIgnore)) {
            fCurrentClipBounds = clip.intersect(fCullRect) ? clip : Bounds::MakeEmpty();
        } else {
            fCurrentClipBounds = fCullRect;
        }
    }

    // We also take advantage of SaveLayer bounds when present to further cut the clip down.
    void updateClipBounds(const SaveLayer& op)  {
        if (op.bounds) {
            // adjustAndMap() intersects these layer bounds with the previous clip for us.
            fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint);
        }
    }

    // The bounds of these ops must be calculated when we hit the Restore
    // from the bounds of the ops in the same Save block.
    void trackBounds(const Save&)          { this->pushSaveBlock(nullptr); }
    void trackBounds(const SaveLayer& op)  { this->pushSaveBlock(op.paint); }
    void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); }

    void trackBounds(const SetMatrix&)         { this->pushControl(); }
    void trackBounds(const Concat&)            { this->pushControl(); }
    void trackBounds(const Translate&)         { this->pushControl(); }
    void trackBounds(const TranslateZ&)        { this->pushControl(); }
    void trackBounds(const ClipRect&)          { this->pushControl(); }
    void trackBounds(const ClipRRect&)         { this->pushControl(); }
    void trackBounds(const ClipPath&)          { this->pushControl(); }
    void trackBounds(const ClipRegion&)        { this->pushControl(); }


    // For all other ops, we can calculate and store the bounds directly now.
    template <typename T> void trackBounds(const T& op) {
        fBounds[fCurrentOp] = this->bounds(op);
        this->updateSaveBounds(fBounds[fCurrentOp]);
    }

    void pushSaveBlock(const SkPaint* paint) {
        // Starting a new Save block.  Push a new entry to represent that.
        SaveBounds sb;
        sb.controlOps = 0;
        // If the paint affects transparent black, the bound shouldn't be smaller
        // than the current clip bounds.
        sb.bounds =
            PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds::MakeEmpty();
        sb.paint = paint;
        sb.ctm = this->fCTM;

        fSaveStack.push(sb);
        this->pushControl();
    }

    static bool PaintMayAffectTransparentBlack(const SkPaint* paint) {
        if (paint) {
            // FIXME: this is very conservative
            if (paint->getImageFilter() || paint->getColorFilter()) {
                return true;
            }

            // Unusual blendmodes require us to process a saved layer
            // even with operations outisde the clip.
            // For example, DstIn is used by masking layers.
            // https://code.google.com/p/skia/issues/detail?id=1291
            // https://crbug.com/401593
            switch (paint->getBlendMode()) {
                // For each of the following transfer modes, if the source
                // alpha is zero (our transparent black), the resulting
                // blended alpha is not necessarily equal to the original
                // destination alpha.
                case SkBlendMode::kClear:
                case SkBlendMode::kSrc:
                case SkBlendMode::kSrcIn:
                case SkBlendMode::kDstIn:
                case SkBlendMode::kSrcOut:
                case SkBlendMode::kDstATop:
                case SkBlendMode::kModulate:
                    return true;
                    break;
                default:
                    break;
            }
        }
        return false;
    }

    Bounds popSaveBlock() {
        // We're done the Save block.  Apply the block's bounds to all control ops inside it.
        SaveBounds sb;
        fSaveStack.pop(&sb);

        while (sb.controlOps --> 0) {
            this->popControl(sb.bounds);
        }

        // This whole Save block may be part another Save block.
        this->updateSaveBounds(sb.bounds);

        // If called from a real Restore (not a phony one for balance), it'll need the bounds.
        return sb.bounds;
    }

    void pushControl() {
        fControlIndices.push(fCurrentOp);
        if (!fSaveStack.isEmpty()) {
            fSaveStack.top().controlOps++;
        }
    }

    void popControl(const Bounds& bounds) {
        fBounds[fControlIndices.top()] = bounds;
        fControlIndices.pop();
    }

    void updateSaveBounds(const Bounds& bounds) {
        // If we're in a Save block, expand its bounds to cover these bounds too.
        if (!fSaveStack.isEmpty()) {
            fSaveStack.top().bounds.join(bounds);
        }
    }

    // FIXME: this method could use better bounds
    Bounds bounds(const DrawText&) const { return fCurrentClipBounds; }

    Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; }
    Bounds bounds(const NoOp&)  const { return Bounds::MakeEmpty(); }    // NoOps don't draw.

    Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); }
    Bounds bounds(const DrawRegion& op) const {
        SkRect rect = SkRect::Make(op.region.getBounds());
        return this->adjustAndMap(rect, &op.paint);
    }
    Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); }
    // Tighter arc bounds?
    Bounds bounds(const DrawArc& op) const { return this->adjustAndMap(op.oval, &op.paint); }
    Bounds bounds(const DrawRRect& op) const {
        return this->adjustAndMap(op.rrect.rect(), &op.paint);
    }
    Bounds bounds(const DrawDRRect& op) const {
        return this->adjustAndMap(op.outer.rect(), &op.paint);
    }
    Bounds bounds(const DrawImage& op) const {
        const SkImage* image = op.image.get();
        SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height());

        return this->adjustAndMap(rect, op.paint);
    }
    Bounds bounds(const DrawImageLattice& op) const {
        return this->adjustAndMap(op.dst, op.paint);
    }
    Bounds bounds(const DrawImageRect& op) const {
        return this->adjustAndMap(op.dst, op.paint);
    }
    Bounds bounds(const DrawImageNine& op) const {
        return this->adjustAndMap(op.dst, op.paint);
    }
    Bounds bounds(const DrawPath& op) const {
        return op.path.isInverseFillType() ? fCurrentClipBounds
                                           : this->adjustAndMap(op.path.getBounds(), &op.paint);
    }
    Bounds bounds(const DrawPoints& op) const {
        SkRect dst;
        dst.set(op.pts, op.count);

        // Pad the bounding box a little to make sure hairline points' bounds aren't empty.
        SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f);
        dst.outset(stroke/2, stroke/2);

        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawPatch& op) const {
        SkRect dst;
        dst.set(op.cubics, SkPatchUtils::kNumCtrlPts);
        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawVertices& op) const {
        SkRect dst;
        dst.set(op.vertices, op.vertexCount);
        return this->adjustAndMap(dst, &op.paint);
    }

    Bounds bounds(const DrawAtlas& op) const {
        if (op.cull) {
            // TODO: <reed> can we pass nullptr for the paint? Isn't cull already "correct"
            // for the paint (by the caller)?
            return this->adjustAndMap(*op.cull, op.paint);
        } else {
            return fCurrentClipBounds;
        }
    }

    Bounds bounds(const DrawPicture& op) const {
        SkRect dst = op.picture->cullRect();
        op.matrix.mapRect(&dst);
        return this->adjustAndMap(dst, op.paint);
    }

    Bounds bounds(const DrawShadowedPicture& op) const {
        SkRect dst = op.picture->cullRect();
        op.matrix.mapRect(&dst);
        return this->adjustAndMap(dst, op.paint);
    }

    Bounds bounds(const DrawPosText& op) const {
        const int N = op.paint.countText(op.text, op.byteLength);
        if (N == 0) {
            return Bounds::MakeEmpty();
        }

        SkRect dst;
        dst.set(op.pos, N);
        AdjustTextForFontMetrics(&dst, op.paint);
        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawPosTextH& op) const {
        const int N = op.paint.countText(op.text, op.byteLength);
        if (N == 0) {
            return Bounds::MakeEmpty();
        }

        SkScalar left = op.xpos[0], right = op.xpos[0];
        for (int i = 1; i < N; i++) {
            left  = SkMinScalar(left,  op.xpos[i]);
            right = SkMaxScalar(right, op.xpos[i]);
        }
        SkRect dst = { left, op.y, right, op.y };
        AdjustTextForFontMetrics(&dst, op.paint);
        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawTextOnPath& op) const {
        SkRect dst = op.path.getBounds();

        // Pad all sides by the maximum padding in any direction we'd normally apply.
        SkRect pad = { 0, 0, 0, 0};
        AdjustTextForFontMetrics(&pad, op.paint);

        // That maximum padding happens to always be the right pad today.
        SkASSERT(pad.fLeft == -pad.fRight);
        SkASSERT(pad.fTop  == -pad.fBottom);
        SkASSERT(pad.fRight > pad.fBottom);
        dst.outset(pad.fRight, pad.fRight);

        return this->adjustAndMap(dst, &op.paint);
    }

    Bounds bounds(const DrawTextRSXform& op) const {
        if (op.cull) {
            return this->adjustAndMap(*op.cull, nullptr);
        } else {
            return fCurrentClipBounds;
        }
    }

    Bounds bounds(const DrawTextBlob& op) const {
        SkRect dst = op.blob->bounds();
        dst.offset(op.x, op.y);
        return this->adjustAndMap(dst, &op.paint);
    }

    Bounds bounds(const DrawDrawable& op) const {
        return this->adjustAndMap(op.worstCaseBounds, nullptr);
    }

    Bounds bounds(const DrawAnnotation& op) const {
        return this->adjustAndMap(op.rect, nullptr);
    }

    static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) {
#ifdef SK_DEBUG
        SkRect correct = *rect;
#endif
        // crbug.com/373785 ~~> xPad = 4x yPad
        // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x
        const SkScalar yPad = 2.5f * paint.getTextSize(),
                       xPad = 4.0f * yPad;
        rect->outset(xPad, yPad);
#ifdef SK_DEBUG
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);
        correct.fLeft   += metrics.fXMin;
        correct.fTop    += metrics.fTop;
        correct.fRight  += metrics.fXMax;
        correct.fBottom += metrics.fBottom;
        // See skia:2862 for why we ignore small text sizes.
        SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct),
                  "%f %f %f %f vs. %f %f %f %f\n",
                  -xPad, -yPad, +xPad, +yPad,
                  metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom);
#endif
    }

    // Returns true if rect was meaningfully adjusted for the effects of paint,
    // false if the paint could affect the rect in unknown ways.
    static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
        if (paint) {
            if (paint->canComputeFastBounds()) {
                *rect = paint->computeFastBounds(*rect, rect);
                return true;
            }
            return false;
        }
        return true;
    }

    bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const {
        for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) {
            SkMatrix inverse;
            if (!fSaveStack[i].ctm.invert(&inverse)) {
                return false;
            }
            inverse.mapRect(rect);
            if (!AdjustForPaint(fSaveStack[i].paint, rect)) {
                return false;
            }
            fSaveStack[i].ctm.mapRect(rect);
        }
        return true;
    }

    const int fNumRecords;

    // We do not guarantee anything for operations outside of the cull rect
    const SkRect fCullRect;

    // Conservative identity-space bounds for each op in the SkRecord.
    Bounds* fBounds;

    // We walk fCurrentOp through the SkRecord, as we go using updateCTM()
    // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative
    // identity-space bounds of the current clip (fCurrentClipBounds).
    int fCurrentOp;
    SkMatrix fCTM;
    Bounds fCurrentClipBounds;

    // Used to track the bounds of Save/Restore blocks and the control ops inside them.
    SkTDArray<SaveBounds> fSaveStack;
    SkTDArray<int>   fControlIndices;
};

}  // namespace SkRecords
Example #12
0
void updateHIN11010(int etPho = 60, int etJet = 30, bool scaleByR=true, bool drawMC=true, int prodDate=20131021) {
  bool mcOnly=false;

  int percentBin[5] = {0,10,30,50,100};
  TH1D* hxgj[5][10];   //[data kind] [ centrality] 
  TH1D* hxgjpp[20];
  TFile *fSum1 = new TFile(Form("histOutputFiles60GeVInclusive/HisOutput_Photonv7_v29_akPu3PF_InclPtRatio_gamma%djet%ddphiSig2749_Isol0_Norm1.root",etPho,etJet));
  for ( int icent=0; icent<=3 ; icent++) { 
    hxgj[khimc][icent] =  (TH1D*)fSum1->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khimc,icent));
    hxgj[khidata][icent] =  (TH1D*)fSum1->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khidata,icent));
  }
  hxgjpp[kppdata] = (TH1D*)fSum1->Get("dataSrc2_reco1_cent0SubtractedExtrapExtrapNorm");

  TFile *fSum2 = new TFile(Form("histOutputFiles60GeVInclusive/HisOutput_Photonv7_v29_akPu3PF_InclPtRatio_gamma%djet%ddphiSig2749_Isol0_Norm2.root",etPho,etJet));
  TGraphAsymmErrors* mxhimc = (TGraphAsymmErrors*)fSum2->Get("dataSrc0_reco1_x_Summary_0");
  TGraphAsymmErrors* mxhidata = (TGraphAsymmErrors*)fSum2->Get("dataSrc1_reco1_x_Summary_0");
  //  TGraphAsymmErrors* mxppdata = (TGraphAsymmErrors*)fSum2->Get("dataSrc2_reco1_x_Summary_0");
  TGraphAsymmErrors* mxppdata;
  TGraphAsymmErrors* mxppmc = (TGraphAsymmErrors*)fSum2->Get("dataSrc10_reco1_x_Summary_0");

  TGraphAsymmErrors* rxhimc = (TGraphAsymmErrors*)fSum2->Get("dataSrc0_reco1_R_Summary_0");
  TGraphAsymmErrors* rxhidata = (TGraphAsymmErrors*)fSum2->Get("dataSrc1_reco1_R_Summary_0");
  TGraphAsymmErrors* rxppdata = (TGraphAsymmErrors*)fSum2->Get("dataSrc2_reco1_R_Summary_0");
  TGraphAsymmErrors* rxppmc = (TGraphAsymmErrors*)fSum2->Get("dataSrc10_reco1_R_Summary_0");

  TFile *fSum3 = new TFile(Form("histOutputFiles60GeVInclusive/HisOutput_Photonv7_v29_akPu3PF_InclDeltaPhi_gamma%djet%ddphiSig628_subJ1SS1_Isol0_Norm1.root",etPho,etJet));

  TFile *fSum4 = new TFile("histOutputFiles60GeVInclusive/HisSummary_Photonv7_v29_akPu3PF_InclDeltaPhi_gamma60jet30dphiSig628_subJ1SS1_Isol0_Norm1.root");
  TGraphAsymmErrors* dphihimc = (TGraphAsymmErrors*)fSum4->Get("dataSrc0_reco1_dphi_Summary");
  TGraphAsymmErrors* dphihidata = (TGraphAsymmErrors*)fSum4->Get("dataSrc1_reco1_dphi_Summary");
  TGraphAsymmErrors* dphippdata = (TGraphAsymmErrors*)fSum4->Get("dataSrc2_reco1_dphi_Summary");
  TGraphAsymmErrors* dphippmc = (TGraphAsymmErrors*)fSum4->Get("dataSrc10_reco1_dphi_Summary");

  // new dphihidata points
  //


  double sysDphi[4] = {0.032,0.03,0.045,0.077};
  //0.109940, 0.046998, 0.034206,0.142664};
  double sysDphipp[1] = {sysDphi[3]};
  
  double sysR[4] = {0.045,0.039,0.041,0.037};
  //0.017232,0.012847,0.011691,0.012724};
  double sysRpp[1] = {sysR[3]};
  
  double sysMx[4] = { 0.053,0.048,0.051,0.032};
  double sysMxpp[1] = {0.009};
  double corrSysMx =  0.028;

  TH1D* hdphi[5][5];   //[data kind] [ centrality]                                                                                     
  TH1D* hdphipp[20];
  for ( int icent=0; icent<=3 ; icent++) {
    hdphi[khimc][icent] =  (TH1D*)fSum3->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khimc,icent));
    hdphi[khidata][icent] =  (TH1D*)fSum3->Get(Form("dataSrc%d_reco1_cent%dSubtractedExtrapExtrapNorm",khidata,icent));
  }
  hdphipp[kppdata] = (TH1D*)fSum3->Get("dataSrc2_reco1_cent0SubtractedExtrapExtrapNorm");
  
  // 2013 pp data!!!!!!
  TFile* pp13 = new TFile(Form("ffFilesPP60GeVInclusive/photonTrackCorr_ppDATA_output_photonPtThr60_to_9999_jetPtThr30_%d.root", prodDate));
  // TFile* pp13 = new TFile("ffFilesPP60GeVInclusive/oldSmearing.root");

  hdphi[kppdata13][1] =  (TH1D*)pp13->Get("jetDphi_icent10010_final");
  hxgj[kppdata13][1] = (TH1D*)pp13->Get("xjg_icent10010_final");
  hdphi[kppdata13][2] =  (TH1D*)pp13->Get("jetDphi_icent11030_final");
  hxgj[kppdata13][2] = (TH1D*)pp13->Get("xjg_icent11030_final");
  hdphi[kppdata13][3] =  (TH1D*)pp13->Get("jetDphi_icent13050_final");
  hxgj[kppdata13][3] = (TH1D*)pp13->Get("xjg_icent13050_final");
  hdphi[kppdata13][4] =  (TH1D*)pp13->Get("jetDphi_icent15099_final");
  hxgj[kppdata13][4] = (TH1D*)pp13->Get("xjg_icent15099_final");
  hdphi[kppdata13][5] =  (TH1D*)pp13->Get("jetDphi_icent7_final");
  hxgj[kppdata13][5] = (TH1D*)pp13->Get("xjg_icent7_final");
  

  for ( int icent  = 1 ; icent<=5 ; icent++) {
    hdphi[kppdata13][icent]->Scale(1./hdphi[kppdata13][icent]->Integral());
    for ( int i = 1 ; i<=5 ; i++) {
      hdphi[kppdata13][icent]->SetBinContent(i,-1e4);
    }
    //    hxgj[kppdata13][icent]->Rebin(10);  // Now the bins are already rebined from photonTrackCorr_ppDATA_output_photonPtThr60_to_9999_jetPtThr30_20131021.root
    hxgj[kppdata13][icent]->Scale(1./hxgj[kppdata13][icent]->Integral("width"));
  }
  
  TH1D* hPtPP2013[10];  
  hPtPP2013[1] = (TH1D*)pp13->Get("jetPt_icent10010_final");
  hPtPP2013[2] = (TH1D*)pp13->Get("jetPt_icent11030_final");
  hPtPP2013[3] = (TH1D*)pp13->Get("jetPt_icent13050_final");
  hPtPP2013[4] = (TH1D*)pp13->Get("jetPt_icent15099_final");
  hPtPP2013[5] = (TH1D*)pp13->Get("jetPt_icent7_final");
  
  TH1D* hRpp2013[10]; 
  hRpp2013[1] = new TH1D("hrpp2013_icent1","",1, 359.1-10, 359.1+10);
  hRpp2013[2] = new TH1D("hrpp2013_icent2","",1, 235.6-10, 235.6+10);
  hRpp2013[3] = new TH1D("hrpp2013_icent3","",1, 116.4-10, 116.4+10);
  hRpp2013[4] = new TH1D("hrpp2013_icent4","",1, 43.6-10,  43.6 +10);
  hRpp2013[5] = new TH1D("hrpp2013_icent5","",1, -8,  18 );

  for ( int icent=1 ;  icent<=5; icent++) { 
    double temprPP13err;
    double temprPP13 = hPtPP2013[icent]->IntegralAndError(1,hPtPP2013[icent]->GetNbinsX(),temprPP13err,"width");
    hRpp2013[icent]->SetBinContent(1,temprPP13);
    hRpp2013[icent]->SetBinError(1,temprPP13err);
    handsomeTH1(hRpp2013[icent],1);
    hRpp2013[icent]->SetMarkerStyle(21);
  }
  
  TH1D* hMXpp2013[10];
  hMXpp2013[1] = new TH1D("hmxpp2013_icent1","",1, 359.1-10, 359.1+10);
  hMXpp2013[2] = new TH1D("hmxpp2013_icent2","",1, 235.6-10, 235.6+10);
  hMXpp2013[3] = new TH1D("hmxpp2013_icent3","",1, 116.4-10, 116.4+10);
  hMXpp2013[4] = new TH1D("hmxpp2013_icent4","",1, 43.6-10,  43.6 +10);
  hMXpp2013[5] = new TH1D("hmxpp2013_icent5","",1, -8, 18);
  for ( int icent=1 ;  icent<=5; icent++) {
    hMXpp2013[icent]->SetBinContent(1,hxgj[kppdata13][icent]->GetMean());
    hMXpp2013[icent]->SetBinError(1,hxgj[kppdata13][icent]->GetMeanError());
    handsomeTH1(hMXpp2013[icent],1);
    hMXpp2013[icent]->SetMarkerStyle(21);
  }


  TFile* fPPsys = new TFile("ffFilesPP60GeVInclusive/relativeSys_merged_pp60GeV.root");

  TH1D* hdphiWidth  = (TH1D*)fPPsys->Get("dphiWidth_uncertainty_merged");
  
  TH1D* hDphiPPUnc = new TH1D("hdphippunc","",1,0,1);
  hDphiPPUnc->SetBinContent(1, hdphiWidth->GetBinContent(1) );

  TH1D* ppSysX[4];
  ppSysX[0] = (TH1D*)fPPsys->Get("dNdXjg_uncertainty_merged");
  ppSysX[1] = (TH1D*)ppSysX[0]->Clone("ppSysx1");
  ppSysX[2] = (TH1D*)ppSysX[0]->Clone("ppSysx2");
  ppSysX[3] = (TH1D*)ppSysX[0]->Clone("ppSysx3");

  TH1D* meanXpp13Sys = (TH1D*)fPPsys->Get("meanXjg_uncertainty_merged");

  float ppSysMx60 = meanXpp13Sys->GetBinContent(1);    // UPDATED on Oct 22nd
  TH1D* ppSysMx = new TH1D("ppSysMx","",1,0,1);
  ppSysMx->SetBinContent(1,ppSysMx60);

  TH1D* meanRpp13Sys = (TH1D*)fPPsys->Get("meanRjg_uncertainty_merged");
  float ppSysR60 = meanRpp13Sys->GetBinContent(1); // UPDATED on Oct 22nd
  TH1D* ppSysR = new TH1D("ppSysR","",1,0,1);
  ppSysR->SetBinContent(1,ppSysR60);

  
  
  // xjg distributions
  TCanvas *c1 = new TCanvas("c1","",1100,330);
  makeMultiPanelCanvas(c1,4,1,0.0,0.0,0.24,0.15,0.075);
  c1->cd(0);
  drawCMSppPbPb(0.1,0.95);
  //c1->Divide(4,1,0.0,0.0);
  for ( int icent=0; icent<=3 ; icent++) {
    c1->cd( 4 - icent);
    //hxgj[khimc][icent]->SetAxisRange(-.2,2.5,"Y");
    hxgj[khimc][icent]->SetAxisRange(0,2.5,"Y");
    hxgj[khimc][icent]->SetNdivisions(505);
    //    hxgj[khimc][icent]->SetTitle(";x_{J#gamma} = p^{Jet}_{T}/p^{#gamma}_{T}; #frac{1}{N_{J#gamma}} #frac{dN_{J#gamma}}{dx_{J#gamma}}");
    hxgj[khimc][icent]->SetTitle(";x_{J#gamma}; #frac{1}{N_{J#gamma}} #frac{dN_{J#gamma}}{dx_{J#gamma}}");
    handsomeTH1(hxgj[khimc][icent]);
    fixedFontHist(hxgj[khimc][icent],1,1.35);
    mcStyle2(hxgj[khimc][icent]);
    handsomeTH1(hxgj[khidata][icent],2);
    
    hxgj[khimc][icent]->GetYaxis()->SetTitleOffset(1.5);
    TH1D * htemp41 = (TH1D*)hxgj[khimc][icent]->Clone(Form("htemp41_%d",icent));
    for ( int i=0 ; i<=20 ; i++) {
      htemp41->SetBinContent(i,0);
      htemp41->SetBinError(i,0);
    }
    if (scaleByR) {
      htemp41->SetAxisRange(0,2,"Y");
      htemp41->SetYTitle("#frac{1}{N_{#gamma}} #frac{dN_{J#gamma}}{dx_{J#gamma}}");
    }
    htemp41->DrawCopy("hist");

    if (scaleByR)    {
      hxgj[kppdata13][icent+1]->Scale(hRpp2013[icent+1]->GetBinContent(1));
      std::cout <<"  Scaled by pp R :" << hRpp2013[icent+1]->GetBinContent(1) << std::endl;
      
      double x,y;
      rxhidata->GetPoint(icent, x,y);
      hxgj[khidata][icent]->Scale(y);
      std::cout << " scaled by PbPb R: " << y << std::endl;

      rxhimc->GetPoint(icent, x,y);
      hxgj[khimc][icent]->Scale(y);
      std::cout << " scaled by PbPb R: " << y << std::endl;
    }
    if(drawMC) hxgj[khimc][icent]->DrawCopy("hist same");

    if ( !mcOnly )    drawXSys(icent,hxgj[khidata][icent]);
    //   if ( icent==3){ }
    
    handsomeTH1(hxgj[kppdata13][icent+1]);
    hxgj[kppdata13][icent+1]->SetMarkerStyle(21);

    drawSys(hxgj[kppdata13][icent+1],ppSysX[icent],kGreen,3001);

    hxgj[kppdata13][icent+1]->Draw("same ");
    
    if ( !mcOnly )   hxgj[khidata][icent]->Draw("same");
    //onSun(0,0,2,0);
 
    // if ( icent == 2) {
    //   TLegend *leg0  = new TLegend(0.2796373,0.7545885,0.9742202,0.9937661,NULL,"brNDC");
    //     easyLeg(leg0,"");
    //   //      if ( !mcOnly )       leg0->AddEntry(hxgj[khidata][icent],"PbPb Data","p");
    //   leg0->AddEntry(hxgj[khimc][icent],"PYTHIA + HYDJET","f");
    //   leg0->AddEntry(hxgjpp[kppdata],"","");

    //   leg0->Draw();
    // }
    
    if ( icent == 3) {
      TLegend *leg0 = new TLegend(0.2916647,0.7045885,0.9862476,0.9869226,NULL,"brNDC");
      easyLeg(leg0);
      leg0->AddEntry(hxgj[khidata][icent],"PbPb Data","p");
      if ( !mcOnly )       leg0->AddEntry(hxgj[kppdata13][icent+1],"Smeared pp reference","p");
      //    leg0->AddEntry(hxgj[khidata][icent],"","");
      if(drawMC) leg0->AddEntry(hxgj[khimc][icent],"PbPb PYTHIA + HYDJET","f");
      leg0->Draw();
      //drawText("#sqrt{s_{NN}}=2.76 TeV ",0.65,0.74,0,15);
    }
        
    if ( icent == 2) {
      drawText(Form("p^{#gamma}_{T} > %d GeV/c     |#eta^{#gamma}| < 1.44",etPho),0.2,0.85,0,15);
      drawText(Form("p^{Jet}_{T} > %d GeV/c    |#eta^{Jet}| < 1.6",etJet),0.2,0.77,0,15);
      drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.2,0.69,0,15);
    }
    if ( icent == 0 ) {
      //      drawText("CMS",0.8,0.9,1);
      //      drawText("pp       #int L dt = 231 nb^{-1}",0.4,0.68,1,15);
    }
    
    if ( icent == 3) 
      drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.72,0.5,0,15);
    else 
      drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.67,0.5,0,15);
    
    /*    if ( icent == 3)
      drawText("(a)",0.275,0.8,1);
    if ( icent == 2)
      drawText("(b)",0.05,0.8,1);  
    if ( icent == 1)
      drawText("(c)",0.05,0.8,1);   
    if ( icent == 0)
      drawText("(d)",0.05,0.8,1);
    */
    gPad->RedrawAxis();
  }

  c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.pdf");
  //c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.png");
  //c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.gif");
  //c1->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_distribution.C");

  
  
  // TCanvas *c1all = new TCanvas("c1all","",500,500);

  // for ( int icent=0;icent<4;icent++){
  //   hxgj[khimc][icent]->SetFillStyle(0);
  //   hxgj[khimc][icent]->SetMarkerSize(1.5);
  // }
  // hxgj[khimc][0]->SetMarkerStyle(22);
  // hxgj[khimc][1]->SetMarkerStyle(26);
  // hxgj[khimc][2]->SetMarkerStyle(23);
  // hxgj[khimc][3]->SetMarkerStyle(32);
  // hxgj[khimc][0]->DrawCopy("");
  // hxgj[khimc][1]->DrawCopy(" same");
  // hxgj[khimc][2]->DrawCopy(" same");
  // hxgj[khimc][3]->DrawCopy(" same");
  // jumSun(0,0,2,0);

  // drawText("PYTHIA+HYDJET",0.2,0.80,0,25);
  // TLegend *legc1all = new TLegend(0.6149194,0.6716102,0.9435484,0.9555085,NULL,"brNDC");
  // easyLeg(legc1all,"");
  // legc1all->AddEntry(hxgj[khimc][3],"50-100%","p");
  // legc1all->AddEntry(hxgj[khimc][2],"30-50%","p");
  // legc1all->AddEntry(hxgj[khimc][1],"10-30%","p");
  // legc1all->AddEntry(hxgj[khimc][0],"0-10%","p");
  // legc1all->Draw();
  
  // dphi distributions
  TCanvas *c1ppDphi = new TCanvas("c1ppDphi","",500,500);
  TString fitFunc = "(TMath::Pi()/20.0)*exp(-(TMath::Pi()-x)/[0])/([0]*(1-exp(-TMath::Pi()/[0])))";
  float fitxmin=3.1415926*2./3;
  TF1 *fdphiPP[10];
  TH1D* hDphiPP2013[10];
  hDphiPP2013[1] = new TH1D("hDphiPP2013_icent1","",1, 359.1-10, 359.1+10);
  hDphiPP2013[2] = new TH1D("hDphiPP2013_icent2","",1, 235.6-10, 235.6+10);
  hDphiPP2013[3] = new TH1D("hDphiPP2013_icent3","",1, 116.4-10, 116.4+10);
  hDphiPP2013[4] = new TH1D("hDphiPP2013_icent4","",1, 43.6-10,  43.6 +10);
  hDphiPP2013[5] = new TH1D("hDphiPP2013_icent5","",1, -8, 18);
  
  for ( int icent=1; icent<=5 ; icent++) {
    fdphiPP[icent] = new TF1(Form("fdphiPP_icent%d",icent),fitFunc.Data(),2.0*TMath::Pi()/3.0,TMath::Pi());
    fdphiPP[icent]->SetParName(0,"width");
    fdphiPP[icent]->SetParameter("width",0.3);
    hdphi[kppdata13][icent]->Fit(Form("fdphiPP_icent%d",icent),"0","",fitxmin,3.1415926);
    fdphiPP[icent]->SetLineWidth(1);
    fdphiPP[icent]->SetLineStyle(2);
    fdphiPP[icent]->SetLineColor(1);
    hdphi[kppdata13][icent]->SetAxisRange(1.00001e-3,1,"Y");
    hdphi[kppdata13][icent]->SetStats(0);
    hdphi[kppdata13][icent]->Draw("");
    hdphi[kppdata13][icent]->SetAxisRange(1.00001e-3,1,"Y");
    hdphi[kppdata13][icent]->SetStats(0);
    fdphiPP[icent]->SetLineWidth(2);
    fdphiPP[icent]->SetLineStyle(7); 
    fdphiPP[icent]->DrawCopy("same");
    gPad->SetLogy();
  
    float dphiWidth13 = fdphiPP[icent]->GetParameter(0) ; 
    float dphiWidth13err = fdphiPP[icent]->GetParError(0);
    hDphiPP2013[icent]->SetBinContent(1,dphiWidth13);
    hDphiPP2013[icent]->SetBinError(  1,dphiWidth13err);
    handsomeTH1(hDphiPP2013[icent],1);
    hDphiPP2013[icent]->SetMarkerStyle(21);
  }

  TCanvas *c1dphi = new TCanvas("c1dphi","",1100,330);
  makeMultiPanelCanvas(c1dphi,4,1,0.0,0.0,0.24,0.18,0.075);
  c1dphi->cd(0);
  drawCMSppPbPb(0.1,0.95);

  for ( int icent=0; icent<=3 ; icent++) {
    c1dphi->cd( 4 - icent);
    hdphi[khimc][icent]->SetAxisRange(1.e-3,1,"Y");
    //   hdphi[khimc][icent]->SetNdivisions(505);
    hdphi[khimc][icent]->GetXaxis()->SetNdivisions(3,5,0,kFALSE);
    
    hdphi[khimc][icent]->SetTitle(";#Delta#phi_{J#gamma};Pair Fraction");

    handsomeTH1(hdphi[khimc][icent]);
    fixedFontHist(hdphi[khimc][icent],1,1.35);
    mcStyle2(hdphi[khimc][icent]);
    handsomeTH1(hdphi[khidata][icent],2);

    TF1 *fdphi = new TF1("fdphi",fitFunc.Data(),2.0*TMath::Pi()/3.0,TMath::Pi());
    fdphi->SetParName(0,"width");
    fdphi->SetParameter("width",0.3);
    
    hdphi[khimc][icent]->Fit("fdphi","0llm","",fitxmin,3.1415926);

    fdphi->SetLineWidth(1);
    fdphi->SetLineStyle(2);
    fdphi->SetLineColor(kBlue); 
    // float dphiWidth = fdphi->GetParameter("width");
    // float dphiWidthErr = fdphi->GetParError(0);
    // std::cout << " dphiWidth,dphiWidthErr = " << dphiWidth <<"   "<< dphiWidthErr << std::endl;
    hdphi[khimc][icent]->SetAxisRange(1.00001e-3,1,"Y");
    hdphi[khimc][icent]->SetStats(0);
    TH1D* hdphitemp = (TH1D*)hdphi[khimc][icent]->Clone(Form("hdphitemp55_%d",icent));
    if(!drawMC)
    {
      for ( int i=0;i<=30;i++) { 
	hdphitemp->SetBinContent(i,0);
	hdphitemp->SetBinError(i,0);
      }
    }
    hdphitemp->Draw("hist");
    hdphi[khidata][icent]->SetAxisRange(1.00001e-3,1,"Y");
    if (!mcOnly) hdphi[khidata][icent]->Draw("same ");
    hdphi[khidata][icent]->SetStats(0);
    fdphi->SetLineWidth(2);
    fdphi->SetLineStyle(7);
    if ( mcOnly )    fdphi->DrawCopy("same");


    gPad->SetLogy();
    handsomeTH1(hdphi[kppdata13][icent+1]);
    
    hdphi[kppdata13][icent+1]->SetMarkerStyle(21);
    hdphi[kppdata13][icent+1]->Draw("same");

    
    if ( icent == 3) {
      TLegend *leg0  = new TLegend(0.32,0.7,0.9,0.89,NULL,"brNDC");
      easyLeg(leg0);
      if ( !mcOnly )   leg0->AddEntry(hdphi[kppdata13][icent+1],"Smeared pp reference","p");
      if ( !mcOnly )      leg0->AddEntry(hdphi[khidata][icent],"PbPb Data","p");
      if(drawMC) leg0->AddEntry(hdphi[khimc][icent],"PYTHIA + HYDJET","f");
      leg0->Draw();
    }

    if (( !mcOnly ) && ( icent == 2)) {
      //drawText("#sqrt{s_{NN}}=2.76 TeV ",0.4,0.88,0,15);
      //drawText("#int L dt = 150 #mub^{-1}",0.4,0.75,0,15);
    }

    if ( icent == 1) {
      drawText(Form("p^{#gamma}_{T} > %d GeV/c     |#eta^{#gamma}| < 1.44",etPho),0.15,0.8,0,15);
      drawText(Form("p^{Jet}_{T} > %d GeV/c    |#eta^{Jet}| < 1.6",etJet),0.15,0.7,0,15);
    }

    if ( icent == 0 ) {
      //      drawText("CMS",0.8,0.9,1);
      //      drawText("pp       #int L dt = 231 nb^{-1}",0.4,0.68,1,15);                                                                     
    }


    if ( icent == 3)
      drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.313,0.6,0,15);
    else
      drawText(Form("%d%% - %d%%",percentBin[icent],percentBin[icent+1]),0.1,0.6,0,15);

    if ( icent == 3)
      drawText("(a)",0.275,0.8,1);
    if ( icent == 2)
      drawText("(b)",0.05,0.8,1);
    if ( icent == 1)
      drawText("(c)",0.05,0.8,1);
    if ( icent == 0)
      drawText("(d)",0.05,0.8,1);
    
    double bottomY = 0.0009;
    double pi = TMath::Pi();

    drawPatch(-0.5,bottomY/100,pi+0.5,bottomY);

    bottomY = 0.0005;
    drawText("0",0.05,bottomY,0,18,false);
    drawText("#frac{1}{3}#pi",pi/3-0.05,bottomY,0,18,0);
    drawText("#frac{2}{3}#pi",2*pi/3-0.05,bottomY,0,18,0);
    if ( icent==0) 
      drawText("#pi",pi-0.1,bottomY,0,18,0);
    drawText("#Delta#phi_{J#gamma}",pi/2.-0.1,bottomY-0.0002,0,18,0);
    
  }
  


  gPad->RedrawAxis();
  c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.pdf");
  //c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.png");
  //c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.gif");
  //c1dphi->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dPhi_dist.C");
  
  ////////////////////////////// summary plots
  TCanvas *c2 = new TCanvas("c2","",350,350);
  TH1D* hTemp2 = new TH1D("htemp2",";N_{part};<x_{J#gamma}>",100,-20,400);
  hTemp2->SetNdivisions(505);
  handsomeTH1(hTemp2,1);
  handsomeTGraph(mxhidata,2);
  mxhidata->SetMarkerStyle(20);
  handsomeTGraph(mxhimc,1);
  mxhimc->SetMarkerStyle(24);
  //  handsomeTGraph(mxppdata,1);
  //  mxppdata->SetMarkerStyle(21);
  handsomeTGraph(mxppmc,1);
  mxppmc->SetMarkerStyle(25);
  
    
  hTemp2->SetAxisRange(0.6,1.1,"Y");
  hTemp2->DrawCopy();
  //  TH1D* hMXpp2013_2 = new TH1D("hmxpp2013_2","",1,-10,370);
  //  hMXpp2013_2->SetBinContent(1,hMXpp2013->GetBinContent(1));
  //  if ( !mcOnly )   drawSys(hMXpp2013_2,sysMxpp,kGreen,3001);
  if ( !mcOnly )   drawSys(mxhidata,sysMx,10);
  
  // mxppmc->Draw("p");
  //  if ( !mcOnly )   mxppdata->Draw("p");
  if ( !mcOnly )  {
    hMXpp2013[5]->SetMarkerStyle(20);
    for ( int icent = 1 ; icent<=5 ; icent++) {
      drawSys(hMXpp2013[icent],ppSysMx,kGreen,3001);
      hMXpp2013[icent]->DrawCopy("p same");
    }
  }
  if(drawMC) mxhimc->Draw("p same");
  if ( !mcOnly )  mxhidata->Draw("p same");

  hMXpp2013[5]->SetFillStyle(3001);
  hMXpp2013[5]->SetFillColor(kGreen);
  hMXpp2013[5]->SetLineColor(0);
  hDphiPP2013[2]->SetFillStyle(3001);
  hDphiPP2013[2]->SetFillColor(kGreen);
  hDphiPP2013[2]->SetLineColor(0);
  TH1D *dummyHist = new TH1D("dummyHist","",10,0,1);
  dummyHist->SetFillStyle(1001);
  dummyHist->SetMarkerColor(kRed);
  dummyHist->SetFillColor(90);
  dummyHist->SetLineColor(0);
  
  //// sys bar by energy scale
  /*
  TBox *b1 = new TBox(400-20,0.85 - corrSysMx ,400,  0.85 + corrSysMx);
  b1->SetFillColor(1);
  b1->SetFillStyle(1001);
  if ( !mcOnly )   b1->Draw();
  TBox *b2 = new TBox(400-20+3,0.85 - corrSysMx+ 0.002 ,400-3,  0.85 + corrSysMx- 0.002);
  b2->SetFillColor(0);
  b2->SetFillStyle(1001);
  if ( !mcOnly )   b2->Draw();
  */
  //  drawText("Common uncertainty due to jet ",0.35,0.25,0,15);
  //  drawText("energy scale & photon purity",0.35,0.2,0,15);
  //  drawText("#sqrt{s_{NN}}=2.76 TeV ",0.5,0.85,0,15);
  //  drawText("#int L dt = 150 #mub^{-1}",0.5,0.72,0,15);
  //  drawText("(a)",0.22,0.87,1);
  drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.7,0.75,0);
  drawCMSppPbPb(0.1,0.95,12);
  //  drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.5,0.38,0);
  // drawText("CMS",0.78,0.88,1);

  TLegend *leg4 =  new TLegend(0.1630303,0.6054839,0.7590909,0.8931183,NULL,"brNDC");
  easyLeg(leg4,"");
  //  if ( !mcOnly )  leg4->AddEntry(mxppdata,"pp Data 231nb^{-1}","p");
  if ( !mcOnly ) leg4->AddEntry(dummyHist,"PbPb Data","fp");
  if ( !mcOnly )  leg4->AddEntry(hMXpp2013[5],"pp Data","fp");
  if ( !mcOnly )  leg4->AddEntry(hDphiPP2013[2],"Smeared pp reference","fp");
  if(drawMC) leg4->AddEntry(mxhimc,"PYTHIA + HYDJET","p");
  //  leg4->AddEntry(mxppmc,"PYTHIA","p");




  //  leg4->AddEntry(hSysTemp,"Sys. Uncertainty","f");                                                                                         
  leg4->Draw();


  gPad->RedrawAxis();
  
  c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.pdf");
  //c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.png");
  //c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.gif");
  //c2->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_xjg_npart.C");
  
  ////////////////////////////// rx 
  TCanvas *c3 = new TCanvas("c3","",350,350);

  TH1D* hTemp3 = new TH1D("htemp2",";N_{part};R_{J#gamma}",100,-20,400);
  hTemp3->SetNdivisions(505);
  handsomeTH1(hTemp3,1);
  handsomeTGraph(rxhidata,2);
  rxhidata->SetMarkerStyle(20);
  handsomeTGraph(rxhimc,1);
  rxhimc->SetMarkerStyle(24);
  handsomeTGraph(rxppdata,1);
  rxppdata->SetMarkerStyle(21);
  handsomeTGraph(rxppmc,1);
  rxppmc->SetMarkerStyle(25);

  hTemp3->SetAxisRange(0.41,1.,"Y");
  hTemp3->Draw();


  // Ratio
  // DivideTG(rxppdata,rxppmc);
  // DivideTG(rxhidata,rxhimc);
  //////////////////////////////////////////////
  //  TH1D* hdphi2013_2 = new TH1D("hdphi2013_2","",1,-10,370);
  //  hdphi2013_2->SetBinContent(1,hRpp2013->GetBinContent(1));
  //  if ( !mcOnly )   drawSys(hdphi2013_2,sysRpp,kGreen,3001);
  if ( !mcOnly )   drawSys(rxhidata,sysR,10);
  //  if ( !mcOnly )   drawSys(rxppdata,sysRpp,10);
  // jumSun(-10,1,400,1);
  if(drawMC) rxhimc->Draw("p");
  //  rxppmc->Draw("p");
  //  if ( !mcOnly )   rxppdata->Draw("p");
  if ( !mcOnly )   {
    hRpp2013[5]->SetMarkerStyle(20);
    for ( int icent =1 ; icent<=5 ; icent++) { 
      drawSys(hRpp2013[icent],ppSysR,kGreen,3001);
      hRpp2013[icent]->Draw("same");
    }
  }
  if ( !mcOnly )   rxhidata->Draw("p same");
  //  drawText(Form("p^{#gamma}_{T} > %d GeV/c",etPho),0.6,0.75,0,15);
  //  drawText(Form("p^{Jet}_{T} > %d GeV/c",etJet),0.6,0.67,0,15);
  //  drawText("CMS",0.78,0.88,1);
  //  drawText("(b)",0.22,0.87,1);
  drawText("#Delta#phi_{J#gamma} > #frac{7}{8}#pi",0.7,0.75,0);
  drawCMSppPbPb(0.1,0.95,12);

  leg4->Draw();
  gPad->RedrawAxis();

  c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.pdf");
  //c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.png");
  //c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.gif");
  //c3->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_r_npart.C");
  
  TCanvas *c4 = new TCanvas("c4","",350,350);

  TH1D* hTemp4 = new TH1D("htemp2",";N_{part};#sigma(#Delta#phi_{J#gamma})",100,-20,400);
  hTemp4->SetNdivisions(505);
  handsomeTH1(hTemp4,1);
  handsomeTGraph(dphihidata,2);
  dphihidata->SetMarkerStyle(20);
  handsomeTGraph(dphihimc,1);
  dphihimc->SetMarkerStyle(24);
  handsomeTGraph(dphippdata,1);
  dphippdata->SetMarkerStyle(21);
  handsomeTGraph(dphippmc,1);
  dphippmc->SetMarkerStyle(25);

  hTemp4->SetAxisRange(0,.5,"Y");
  hTemp4->Draw();
  
                                                                                 
  // TH1D* h2013_3 = new TH1D("hdphi2013_3","",1,-10,370);
  //  h2013_3->SetBinContent(1,hDphiPP2013->GetBinContent(1));

  //  if ( !mcOnly )  drawSys(h2013_3,sysDphipp,kGreen,3001);
  if ( !mcOnly )  drawSys(dphihidata,sysDphi,10);
  if(drawMC) dphihimc->Draw("p same");
  // dphippmc->Draw("p");
  //  if ( !mcOnly )  dphippdata->Draw("p");
  for ( int icent=1 ; icent<=5 ; icent++){
    drawSys(hDphiPP2013[icent], hDphiPPUnc, kGreen,3001);
  }
  
  TH1D* hDphiPP2013Temp = new TH1D("hDphiPP2013Temp","",1,380,400);
  hDphiPP2013Temp->SetBinContent(1,0.27);
  hDphiPP2013[5]->SetMarkerStyle(20);
  for ( int icent=1 ; icent<=5 ; icent++){ 
    hDphiPP2013[icent]->Draw("same");
  }
  if ( !mcOnly )  dphihidata->Draw("p");

  // TLegend *legDphi =  new TLegend(0.32,0.18,0.93,0.7,NULL,"brNDC");
  // easyLeg(legDphi,"");
  // legDphi->SetTextSize(17);
  // //  drawText("|#Delta#phi_{J#gamma}| > #frac{2}{3}#pi",0.5,0.38,0);
  // //  drawText("Fit : #frac{e^{#frac{|#Delta#phi_{J#gamma}|-#pi}{#sigma}}}{#sigma(1-e^{-#pi/#sigma})}",0.5,0.23,0);
  // legDphi->Draw();
  // //  drawText("(a)",0.22,0.87,1);
  // //  drawText("CMS",0.78,0.88,1);


  TH1D* hSysTemp = new TH1D("hSystemp","",1,0,1);
  hSysTemp->SetFillColor(newYellow);
  hSysTemp->SetLineColor(newYellow);

  leg4->Draw();

  drawText(Form("p^{#gamma}_{T} > %d GeV/c     |#eta^{#gamma}| < 1.44",etPho),0.25,0.3,0,15);
  drawText(Form("p^{Jet}_{T} > %d GeV/c    |#eta^{Jet}| < 1.6",etJet),0.25,0.2,0,15);
  drawCMSppPbPb(0.1,0.95,12);

  gPad->RedrawAxis();
  c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.pdf");
  //c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.png");
  //c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.gif");
  //c4->SaveAs("plotPPPbPb/inclusivePt_ppPbPb_dphi_npart.C");

   // // print numbers
   // std::cout << " Summary of Points for PbPb " << std::endl;
   // PrintGraphAndSys(dphihidata,sysDphi);
   // PrintGraphAndSys(mxhidata,sysMx);
   // PrintGraphAndSys(rxhidata,sysR);

   // std::cout << " Summary of Points for PYTHIA + HYDJET " << std::endl;
   // PrintGraph(dphihimc);
   // PrintGraph(mxhimc);
   // PrintGraph(rxhimc);

   //   std::cout << " Summary of Points for pp " << std::endl;
   //  PrintGraphAndSys(dphippdata[5],sysDphipp);
   //  PrintGraphAndSys(mxppdata[5],sysMxpp);
   // PrintGraphAndSys(rxppdata[5],sysRpp);


   
   /*
   TCanvas *c5 = new TCanvas("c5","",500,500);
   hxgj[khidata][0]->SetAxisRange(-.2,2.5,"Y");
   hxgj[khidata][0]->SetNdivisions(505);
   fixedFontHist(hxgj[khidata][0],1,1.35);
   handsomeTH1(hxgj[khidata][0],2);
   hxgj[khidata][0]->GetYaxis()->SetTitleOffset(1.5);
   hxgj[khidata][0]->DrawCopy("");
   handsomeTH1(hxgj[kppdata13][5],4);
   hxgj[kppdata13][5]->Draw("same hist");
   onSun(0,0,2,0);
   */
}
Example #13
0
File: main.cpp Project: 9gix/cg
void display(void)
{
	int startTime=glutGet(GLUT_ELAPSED_TIME);
	int counter = 1;
	
	glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//floor plane
	glBegin(GL_POLYGON);
	glColor3f(0.3, 0.73, 0.1);
	glVertex3f(-75, -0.02, 75);
	glVertex3f(75, -0.02, 75);
	glVertex3f(75, -0.02, -75);
	glVertex3f(-75, -0.02, -75);
	glEnd();

	//draw patches
	for(int i=0;i<9;i++)
	{
		for(int j=0;j<9;j++)
		{
			glPushMatrix();
			glTranslatef((i-4.5)*10+5, 0, (j-4.5)*10+5);
			glLoadName(counter);
			counter++;
			drawPatch();
			glPopMatrix();
		}
	}

	
	A0116631House(texSet);

	/*
	glPushMatrix();
	drawMyHouse(texSet);

	glTranslatef(10, 0, 0);
	drawMyHouse(texSet);

	glTranslatef(10, 0, 0);
	drawMyHouse(texSet);

	glTranslatef(10, 0, 0);
	drawMyHouse(texSet);

	glTranslatef(10, 0, 0);
	drawMyHouse(texSet);

	glPopMatrix();
	*/

	
	int endTime=glutGet(GLUT_ELAPSED_TIME);
	cout<<"Frame Rate: "<<(float)1000/(endTime-startTime)<<"\n";
	glFlush();
	glutSwapBuffers();

}
Example #14
0
Patch* MapDraw::draw()
{
  // TODO: Fit this one in too so I don't have to to all the MODEL_SCALE multiplications.
//  glScalef(MODEL_SCALE, MODEL_SCALE, MODEL_SCALE);

  int x,y, temp;
  Patch* bottomLeft = '\0';
  Patch* tp = '\0';

  // Eventually this call will be made to whatever generic character the
  // map should be centered on.  i.e. the player, or an enemy ant.
  bottomLeft = getGrid()->getPatch(getCenterX(), getCenterY());

  // Shift from the center to the bottomLeft.
  // shift left a bunch of times or until we hit the left wall.
  for (temp=0; ((bottomLeft) && (Grid::getLeft(bottomLeft)) && (temp < GRID_SIZE)); temp++)
    bottomLeft = Grid::getLeft(bottomLeft);

  int offsetx = 0;
  // At the bottom, offset...
  if (temp < GRID_SIZE)
    offsetx = GRID_SIZE - temp;

  // shift up a bunch of times or until we hit the top wall.
  for (temp=0; ((bottomLeft) && (Grid::getDown(bottomLeft)) && (temp < GRID_SIZE)); temp++)
    bottomLeft = Grid::getDown(bottomLeft);

  int offsety = 0;
  // At the bottom, offset...
  if (temp < GRID_SIZE)
    offsety = GRID_SIZE - temp;
    //printf("EXTREME");

  tp=bottomLeft;

  // Setup for drawing.
//  glBegin(GL_QUADS);

  for (y=GRID_SIZE*-1 + (offsety); (bottomLeft && (y < (GRID_SIZE+1))); y+=1)
  {
    tp=bottomLeft;
    for (x=GRID_SIZE*-1 + (offsetx); x < (GRID_SIZE+1); x+=1)
    {
      if (pickMode)
        startCheck();
      // scale by *MODEL_SCALE then "translate" by adding the smooth scroll factors.
      // I really have no idea why I was scaling this thing, but I think this is screwing
      // up tile alignment.
      // OK, well if x and y get too big I get weird graphical issues with boxes wrapping
      // around the screen, so lets keep things small for now...
      drawPatch(x*MODEL_SCALE, y*MODEL_SCALE, tp);
      if (pickMode)
        if (endCheck())
        {
          //glEnd();
          return tp;
        }
      tp=tp->right;
    }
    if (bottomLeft)
      bottomLeft = Grid::getUp(bottomLeft);
  }

  // Finished drawing.
  //glEnd();
  return '\0';
}
void photonTemplateProducer(int cutOpt=3, int ppHI = kHI, int isoChoice = kSumIso, int isoCut = -100, bool onlygjEvents=false, float specialSbCut=10, float mcSigShift=0, float sbBkgShift=0) {
  
  CutAndBinCollection cab;
  cab.setCuts(cutOpt);
  int nPtBin = cab.getNPtBin();
  vector<double> ptBinVector = cab.getPtBin();
  double ptBin[100];
  for ( int i = 0 ; i<=nPtBin ;i++) {
    ptBin[i] = ptBinVector[i];
  }
  
  int nCentBin = cab.getNCentBin();
  vector<double> centBinVector = cab.getCentBin();
  double centBin[100];
  for ( int i = 0 ; i<=nCentBin ;i++) {
    centBin[i] = centBinVector[i];
  }
  
  TString pphiLabel = "";
  if ( ppHI == kPP) pphiLabel = "pp";
  
  TCanvas* c1[5];
    
   TH1D* hData[5][5];
   TH1D* hSig[5][5];
   TH1D* hBkg[5][5];
   
   //   TH1D* hDatapp[5];
   //   TH1D* hSigpp[5];
   //   TH1D* hBkgpp[5];
   
   TH1D* hBkgMCsr[5][5];
   TH1D* hBkgMCsb[5][5];
      
   TH1D* rawSpectra[5];
   TH1D* finSpectra[5];
    
   TH2D* hPurity2D = new TH2D("hPurity2D",";pT(GeV);Centrality bin",nPtBin,ptBin,nCentBin,centBin);
   
   int nCent(-1);
   if ( ppHI == kHI ) nCent = nCentBin;
   if ( ppHI == kPP ) nCent = 1;
   
   for ( int icent = 1 ; icent<=nCent ; icent++) {
      rawSpectra[icent] = new TH1D(Form("rawSpec_icent%d_%s",icent,getIsoLabel(isoChoice).Data()),"",nPtBin,ptBin);
   }

   
   for (int ipt = 1; ipt <= nPtBin ; ipt++) { 
      c1[ipt] = new TCanvas(Form("c1_ipt%d",ipt),"",700,700);
      if ( ppHI == kHI )  makeMultiPanelCanvas(c1[ipt],nCent/2,2,0.0,0.0,0.2,0.15,0.02);

      TCut ptCut = Form("corrPt>%.2f && corrPt<%.2f",(float)ptBin[ipt-1],(float)ptBin[ipt]); 
      

      for ( int icent = 1 ; icent<=nCent ; icent++) { 
	 int lowCent =  centBinVector[icent-1];    
	 int highCent = centBinVector[icent]-1;
	 
	 hData[icent][ipt]  = new TH1D(Form("hData_cent%d_pt%d",icent,ipt),";shower shape (#sigma_{#eta#eta});Entries per photon candidate;",25,0,0.025);
	 hSig[icent][ipt]   = (TH1D*)hData[icent][ipt]->Clone(Form("hSig_cent%d_pt%d",icent,ipt));
	 hBkg[icent][ipt]   = (TH1D*)hData[icent][ipt]->Clone(Form("hBkg_cent%d_pt%d",icent,ipt));
	 hBkgMCsr[icent][ipt] = (TH1D*)hData[icent][ipt]->Clone(Form("hBkgMCsr_cent%d_pt%d",icent,ipt));
	 hBkgMCsb[icent][ipt] =(TH1D*)hData[icent][ipt]->Clone(Form("hBkgMCsb_cent%d_pt%d",icent,ipt));
	
	 TString fNamedata = fNameHIdata;
	 if ( ppHI == kPP ) fNamedata = fNamePPdata;
	 
	 getTemplate(ppHI, hSig[icent][ipt],"meaningless",isoChoice,isoCut, kSig,lowCent,highCent,ptCut,onlygjEvents,specialSbCut,mcSigShift);
	 getTemplate(ppHI, hData[icent][ipt],fNamedata ,isoChoice,isoCut, kData,lowCent,highCent,ptCut,onlygjEvents,specialSbCut);
	 if ( ppHI == kHI) {
	   getTemplate(ppHI, hBkg[icent][ipt], fNamedata ,isoChoice,isoCut, kSBB,lowCent,highCent,ptCut,onlygjEvents,specialSbCut,sbBkgShift);
	 }
	 if ( ppHI == kPP)
           getTemplate(ppHI, hBkg[icent][ipt], fNamedata ,isoChoice,isoCut, kSBBpp,lowCent,highCent,ptCut,onlygjEvents,specialSbCut);
	 
      }
            
      
      for ( int icent = 1 ; icent<=nCent ; icent++) {
	int lowerCent = centBinVector[icent-1];
	int upperCent =centBinVector[icent]-1;
	 
	 c1[ipt]->cd(nCent - icent+1);
	 fitResult fitr = doFit ( hSig[icent][ipt], hBkg[icent][ipt], hData[icent][ipt], 0.005,0.025);
	 if ( icent== nCent) drawPatch(0,0,0.05,0.14,0,1001, "ndc");
	 
	 cout << " shift = " << mcSigShift << endl;
	 cout << " purity = " << fitr.purity010 << endl;

	 
	 if ( ptBin[ipt]> 200)
	    drawText(Form(" E_{T}^{#gamma} > %d GeV", (int)ptBin[ipt-1]),0.5680963,0.529118);
	 else
	    drawText(Form("%d - %d GeV", (int)ptBin[ipt-1], (int)ptBin[ipt]),0.5680963,0.529118);
	 
	 if ( ppHI == kHI) {
	   drawText(Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),0.5680963,0.4369118);
	 }
	 else if ( ppHI == kPP) {
	   drawText("7TeV pp",0.5680963,0.4369118);
         }
	 
	 
	 
	 if ( (icent == nCent) || (icent == 2)) 
	   drawText(Form("Purity(#sigma_{#eta#eta} < 0.01) : %.0f%%", (float)fitr.purity010*100),0.5680963,0.3569118,1,15);
	 else 
	   drawText(Form("Purity(#sigma_{#eta#eta} < 0.01) : %.0f%%", (float)fitr.purity010*100),0.4980963,0.3569118,1,15);
	 
	 drawText(Form("#pm %.0f%% (stat)", float( 100. * fitr.purity010 * (float)fitr.nSigErr / (float)fitr.nSig ) ),0.6680963,0.2869118,1,15);
	 
	 
	 hPurity2D->SetBinContent(ipt,icent,fitr.purity010);
	 hPurity2D->SetBinError  (ipt,icent,fitr.purity010* fitr.nSigErr/fitr.nSig);

	 rawSpectra[icent]->SetBinContent( ipt, fitr.nSig);
	 rawSpectra[icent]->SetBinError(   ipt,fitr.nSigErr);

	 TString aa = "";
	 if (isoChoice == kSumIso)  aa = "Sum Iso Method";
	 if (isoChoice == k3dIso)   aa = "3d Cut Method";
	 if (isoChoice == kFisher)  aa = "Fisher Method";
	 
	 if ( (ppHI == kHI)  && ( icent==nCent -1) )
	   drawText(aa.Data(),0.1980963,0.8569118,1,20);
	 else if ( ppHI == kPP) 
	   drawText(aa.Data(),0.1980963,0.8569118,1,20);
	 
	 if ( icent<= 2) drawPatch(0,0,0.05,0.14,0,1001, ndcOpt);
	 //	 drawPatch(0.9,0.05,1.01,0.14,0,1001,ndcOpt);
	 if  ( (ppHI == kPP) && ( mcSigShift != 0 )) 
           drawText(Form("Signal template shifted by %f",mcSigShift),0.1980963,0.7569118,1,15);
	 if  ( (ppHI == kHI) && ( mcSigShift != 0 ) && (icent==3))
	   drawText(Form("Signal template shifted by %f",mcSigShift),0.1980963,0.7569118,1,15);


      }   
      
      TString ppLabel ="";  
      if ( ppHI == kPP) ppLabel = "_pp";
      TString shiftLabel="";
      if ( mcSigShift != 0 )  shiftLabel = Form("_%fSigShifted",(float)mcSigShift);
      c1[ipt]->SaveAs(Form("fittingPurity%s_%s_pt%d%s.pdf",ppLabel.Data(), getIsoLabel(isoChoice).Data(),ipt,shiftLabel.Data()));

   }
   
   // efficiency plots          
   TCanvas* c2  = new TCanvas("c2","",700,700); //100 + nCent_std*300,400);
   if ( ppHI == kHI) makeMultiPanelCanvas(c2,nCent/2,2,0.0,0.0,0.2,0.15,0.02);
   
   TH1D* heff[7][5];
   TH1D* heffGj[5];
   TH1D* heffDphi[5];
   TH1D* effSingleBin = new TH1D("effSingleBin","",1,60,100000);
   TGraphAsymmErrors* geff[7][5];
   TGraphAsymmErrors* gSingleBin = new TGraphAsymmErrors();
   TGraphAsymmErrors* geffGj[5];
   TGraphAsymmErrors* geffDphi[5];
   
   for (int icent = 1; icent <=nCent; icent++) {
     for ( int iid=1 ; iid<=5; iid++) {
       heff[icent][iid] = new TH1D(Form("heff_icent%d_id%d",icent,iid),";photon E_{T} (GeV);Efficiency",nPtBin, ptBin);
       if ( isoChoice == kSumIso2)
	 heff[icent][iid]->SetName(Form("heff_icent%d_id%d_isoCut%d",icent,iid,(int)isoCut));
       if ( isoChoice == kSumIso3)
	 heff[icent][iid]->SetName(Form("heff_icent%d_id%d_sbIsoCut%d",icent,iid,(int)specialSbCut));
       
       geff[icent][iid] = new TGraphAsymmErrors();
       geff[icent][iid]->SetName(Form("geff_%s",heff[icent][iid]->GetName()));
     }
     heffGj[icent]   = new TH1D(Form("heff_icent%d_Gj",  icent),";x_J#gamma;Efficiency",10,0,2);
     heffDphi[icent] = new TH1D(Form("heff_icent%d_Dphi",icent),";#Delta#phi of pair;Efficiency",9,0.3141592,3.141592);
     geffGj[icent] = new TGraphAsymmErrors();
     geffDphi[icent] = new TGraphAsymmErrors();

   }
   
   TCut srIsoCut = getIsoCut(isoChoice,isoCut);
   int nId=4;
   for (int icent = 1; icent <=nCent ; icent++) {
     int lowCent = centBinVector[icent-1];
     int highCent = centBinVector[icent]-1;
     TCut centCut      = Form("yEvt.hiBin >= %d && yEvt.hiBin<= %d",lowCent,highCent);
     if ( ppHI == kPP ) centCut = "";
     getEff("genMatchedPt",heff[icent][1],geff[icent][1],centCut, "swissCrx<0.90 && seedTime<4");
     getEff("genMatchedPt",heff[icent][2],geff[icent][2],centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1");
     getEff("genMatchedPt",heff[icent][3],geff[icent][3],centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1" && srIsoCut);
     getEff("genMatchedPt",heff[icent][4],geff[icent][4],centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1 && sigmaIetaIeta<0.010"&& srIsoCut);
     effSingleBin->Reset();
     getEff("genMatchedPt",effSingleBin, gSingleBin, centCut, "swissCrx<0.90 && seedTime<4 && hadronicOverEm<0.1" && srIsoCut);
     
     
     cout << " here Gj" << endl;
     getEff("yJet.jtpt/photonEt",heffGj[icent],geffGj[icent], centCut && " genIso<5 && abs(genMomId)<=22 && photonEt>60 && abs(yJet.jteta)<2 && yJet.jtpt>30 && acos(cos(photonPhi-yJet.jtphi))>2.749", "hovere<0.1 && sigmaIetaIeta<0.010 && (cc4+cr4+ct4PtCut20)/0.9<1",true);
     getEff("acos(cos(photonPhi-yJet.jtphi))",heffDphi[icent],geffDphi[icent],centCut && " genIso<5 && abs(genMomId)<=22 && photonEt>60 && abs(yJet.jteta)<2 && yJet.jtpt>30", "hovere<0.1 && sigmaIetaIeta<0.010 && (cc4+cr4+ct4PtCut20)/0.9<1",true);
   }
   
   for (int icent = 1; icent <=nCent; icent++) {
     for ( int iid=1 ; iid<=nId ; iid++) {
       handsomeTH1(heff[icent][iid],ycolor[iid]);
       handsomeTGraph(geff[icent][iid],ycolor[iid]);
     }
   }
   

   
   
   
   TH1D* htmp = (TH1D*)heff[1][1]->Clone("htmp");
   htmp->Reset();
   htmp->SetAxisRange(0,1.3,"Y");
   htmp->SetYTitle("Efficiency");
   handsomeTH1(htmp);
   
   for (int icent = 1; icent <=nCent; icent++) {
      int lowerCent = centBinVector[icent-1];
      int upperCent = centBinVector[icent]-1;
      if ( ppHI == kHI) c2->cd(nCent - icent + 1);
      htmp->DrawCopy();
      for ( int iid=1 ; iid<=nId ; iid++) {
         heff[icent][iid]->Draw("p same");
         geff[icent][iid]->Draw("p");
	 
      }
      if ( ( icent == nCent ) ||   ( ppHI == kPP)  )
         {
            TLegend* leg1 =  new TLegend(0.25,0.20,0.95,0.55,NULL,"brNDC");
            easyLeg(leg1,"Photon ID efficiency");
            leg1->AddEntry(heff[icent][1],"spike rejection","lp");
            leg1->AddEntry(heff[icent][2],"+ H/E < 0.1","lp");
	    if (isoChoice == kSumIso)
	      leg1->AddEntry(heff[icent][3],"+ SumIso cut","lp");
	    if (isoChoice == kFisher) 
	      leg1->AddEntry(heff[icent][3],"+ Fisher cut","lp");
	    leg1->AddEntry(heff[icent][4],"+ #sigma_{#eta#eta} <0.010","lp");
            leg1->Draw();
         }
      drawText(Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),0.5680963,0.8369118);
      if ( icent<=2) drawPatch(0,0,0.05,0.14,0,1001,ndcOpt);
      //  drawPatch(0.9,0.05,1.01,0.14,0,1001,ndcOpt);
      
   }
   
   
   c2->SaveAs(Form("photonID_efficiency_%s.pdf",getIsoLabel(isoChoice).Data()));  

   TCanvas* c2b  = new TCanvas("c2b","",1000,500); //100 + nCent_std*300,400);                                             
   c2b->Divide(2,1);
   c2b->cd(1);
   TH1D* htmpG = (TH1D*)heffGj[1]->Clone("htmpG");
   htmpG->Reset();
   htmpG->SetAxisRange(0,1.3,"Y");
   htmpG->SetYTitle("Efficiency");
   handsomeTH1(htmpG);   
      
   TLegend* legCent = new TLegend(0.4657258,0.2245763,1,0.4512712,NULL,"brNDC");
   easyLeg(legCent,"Centrality");
   if (isoChoice == kSumIso)  easyLeg(legCent,"SumIso Method");
   if (isoChoice == kFisher)  easyLeg(legCent,"Fisher Method");
   cout<< " heffGj "<< endl << endl<< endl;
   for (int icent = 1; icent <=nCent; icent++) {
     handsomeTH1(heffGj[icent],ycolor[icent]);
     heffGj[icent]->Fit("pol1");
     heffGj[icent]->GetFunction("pol1")->SetLineColor(ycolor[icent]);
     heffGj[icent]->GetFunction("pol1")->SetLineStyle(7);
   }
   htmpG->DrawCopy();
   for (int icent = 1; icent <=nCent; icent++) {
     heffGj[icent]->Draw("same");
     int lowerCent = centBinVector[icent-1];     int upperCent = centBinVector[icent]-1;
     legCent->AddEntry(heffGj[icent],Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),"pl");
   }
   legCent->Draw();

   c2b->cd(2);
   TH1D* htmpDp = new TH1D("htmpDp",";#Delta#phi of pair;Efficiency",10,0,3.14);
   htmpDp->Reset();
   htmpDp->SetAxisRange(0,1.3,"Y");
   htmpDp->SetYTitle("Efficiency");
   handsomeTH1(htmpDp);
   cout << " heffDphi " << endl << endl << endl ;
   for (int icent = 1; icent <=nCent; icent++) {
     handsomeTH1(heffDphi[icent],ycolor[icent]);
     heffDphi[icent]->Fit("pol1");
     heffDphi[icent]->GetFunction("pol1")->SetLineColor(ycolor[icent]);
     heffDphi[icent]->GetFunction("pol1")->SetLineStyle(7);
   }
   htmpDp->DrawCopy();
   for (int icent = 1; icent <=nCent; icent++) {
     heffDphi[icent]->Draw("same");
   }
   legCent->Draw();
   
   c2b->SaveAs(Form("photonID_efficiency_%s_2.pdf",getIsoLabel(isoChoice).Data()));
   
   
   TCanvas* c3 = new TCanvas("cPurity","",500,500);

   TH1D* hPurity[10];
   for (int icent = 1; icent <=nCent; icent++) {
     hPurity[icent] = (TH1D*)hPurity2D->ProjectionX(Form("purity1D_icent%d",icent),icent,icent);
     hPurity[icent]->Fit("pol1");
     hPurity[icent]->GetFunction("pol1")->SetLineColor(ycolor[icent]);
     hPurity[icent]->GetFunction("pol1")->SetLineStyle(7);
   }
   TH1D* tempPurity = (TH1D*)hPurity[1]->Clone("purityTemp");
   tempPurity->Reset();
   handsomeTH1(tempPurity,1);
   tempPurity->SetXTitle("pT (Gev)");
   tempPurity->SetYTitle("Purity");
   tempPurity->SetAxisRange(0.45,1.2,"Y");

   tempPurity->Draw();
   for (int icent = 1; icent <=nCent; icent++) {
     handsomeTH1(hPurity[icent],ycolor[icent]);
     hPurity[icent]->Draw("same");
   }
   TLegend* legPurity = new TLegend(0.4657258,0.2245763,1,0.4512712,NULL,"brNDC");
   easyLeg(legPurity,"Purity");
   if (isoChoice == kSumIso)  easyLeg(legPurity,"SumIso Method");
   if (isoChoice == kFisher)  easyLeg(legPurity,"Fisher Method");
   for (int icent = 1; icent <=nCent; icent++){
     int lowerCent = centBinVector[icent-1];     int upperCent = centBinVector[icent]-1;
     legPurity->AddEntry(hPurity[icent],Form("%.0f%% - %.0f%%", float((float)lowerCent*2.5), float((float)(upperCent+1)*2.5)),"pl");
   }
   legPurity->Draw();
   
   if ( !onlygjEvents) 
     drawText("inclusive photon",0.25,0.2);
   
   c3->SaveAs(Form("purity_%s.pdf",getIsoLabel(isoChoice).Data()));
  
   
   TCanvas* c4 = new TCanvas("efficiencyCorrection","",1000,500);
   c4->Divide(2,1);
   c4->cd(1);
   for (int icent = 1; icent <=nCent; icent++) {
      TH1ScaleByWidth(rawSpectra[icent]);    // divide by width
      finSpectra[icent] = (TH1D*)rawSpectra[icent]->Clone(Form("finSpec_icent%d_%s",icent,getIsoLabel(isoChoice).Data()));
      if ( isoChoice == kSumIso2)
	 finSpectra[icent]->SetName(Form("finSpec_icent%d_%s_isoCut%d",icent,getIsoLabel(isoChoice).Data(),(int)isoCut));
      if ( isoChoice == kSumIso3)
         finSpectra[icent]->SetName(Form("finSpec_icent%d_%s_sbisoCut%d",icent,getIsoLabel(isoChoice).Data(),(int)specialSbCut));
      
      finSpectra[icent]->Divide(heff[icent][3]);
      handsomeTH1(finSpectra[icent],ycolor[icent]);
   }
   // TAA and centrality 
   //

   TFile outf = TFile(cab.getPurityFileName(),"recreate");
   hPurity2D->Write();
   for ( int icent=1 ; icent<=nCent ; icent++) {
      heff[icent][3]->Write();
      heff[icent][4]->Write();
      finSpectra[icent]->Write();
      hPurity[icent]->Write();
      for (int ipt = 1; ipt <= nPtBin ; ipt++) {
	hData[icent][ipt]->Write();
      }
      //      hBkgMCRatioFit[icent][1]->Write();

   }



   outf.Close();
}
void	GL_Geometry::MakeSphere( float radius, unsigned int quality )
{
  m_Primitives.clear();
  m_Vertices.clear();
  m_Normales.clear();
  m_TexCoords.clear();
  m_Prim_index.clear();
  m_Norm_index.clear();

  set_treeSearcher.clear();

  {
    unsigned int	vertices_size = 12;
    unsigned int	indices_size = 20;

    int	inc = (quality > 0 ? 30 : 0);

    for (unsigned int i = 0; i < quality; ++i)
      {
	indices_size *= 4;

	vertices_size += inc;
	inc *= 4;
      }

    m_Primitives.resize( indices_size, 0 );

    if (vertices_size <= m_Vertices.capacity())
      m_Vertices.reserve( vertices_size );

    if (vertices_size <= m_Normales.capacity())
      m_Normales.reserve( vertices_size );

    if (indices_size * 3 <= m_Prim_index.capacity())
      m_Prim_index.reserve( indices_size * 3 );

    if (indices_size * 3 <= m_Norm_index.capacity())
      m_Norm_index.reserve( indices_size * 3 );
  }

#define	D_ICX	0.525731112119133606f
#define	D_ICZ	0.850650808352039932f

  static sf::Vector3f	idata[12] = {
    sf::Vector3f(-D_ICX, 0.0f, +D_ICZ),
    sf::Vector3f(+D_ICX, 0.0f, +D_ICZ),
    sf::Vector3f(-D_ICX, 0.0f, -D_ICZ),
    sf::Vector3f(+D_ICX, 0.0f, -D_ICZ),
    sf::Vector3f(0.0f, +D_ICZ, +D_ICX),
    sf::Vector3f(0.0f, +D_ICZ, -D_ICX),
    sf::Vector3f(0.0f, -D_ICZ, +D_ICX),
    sf::Vector3f(0.0f, -D_ICZ, -D_ICX),
    sf::Vector3f(+D_ICZ, +D_ICX, 0.0f),
    sf::Vector3f(-D_ICZ, +D_ICX, 0.0f),
    sf::Vector3f(+D_ICZ, -D_ICX, 0.0f),
    sf::Vector3f(-D_ICZ, -D_ICX, 0.0f)
  };

#undef	D_ICX
#undef	D_ICZ

  static int	index[20][3] = {
    {0,  4,  1},	{ 0,  9,  4},
    {9,  5,  4},	{ 4,  5,  8},
    {4,  8,  1},	{ 8, 10,  1},
    {8,  3, 10},	{ 5,  3,  8},
    {5,  2,  3},	{ 2,  7,  3},
    {7, 10,  3},	{ 7,  6, 10},
    {7, 11,  6},	{11,  0,  6},
    {0,  1,  6},	{ 6,  1, 10},
    {9,  0, 11},	{ 9, 11,  2},
    {9,  2,  5},	{ 7,  2, 11},
  };

  t_drawPatch_data::Initialize( m_Vertices, m_Normales, m_TexCoords,
				m_Prim_index, m_Norm_index,
				radius );

  for (int i = 0; i < 20; i++)
    {
      drawPatch( t_drawPatch_data( idata[ index[i][2] ],
				   idata[ index[i][1] ],
				   idata[ index[i][0] ],
				   quality ) );
    }

  // std::cerr << std::endl;

  // std::cerr << "Sphere stats :" << std::endl;
  // std::cerr << "m_Vertices   :" << m_Vertices.size() << std::endl;
  // std::cerr << "m_Normales   :" << m_Normales.size() << std::endl;
  // std::cerr << "m_TexCoords  :" << m_TexCoords.size() << std::endl;
  // std::cerr << "m_Prim_index :" << m_Prim_index.size() << std::endl;
  // std::cerr << "m_Norm_index :" << m_Norm_index.size() << std::endl;

  // std::cerr << std::endl;

  // for ( unsigned int i = 0; i < m_Vertices.size(); ++i )
  //   std::cerr << std::fixed << std::setprecision(2)
  // 	      << "v (" << std::setw(6) << m_Vertices[i].x
  // 	      << " / " << std::setw(6) << m_Vertices[i].y
  // 	      << " / " << std::setw(6) << m_Vertices[i].z << "), "
  // 	      << "t (" << std::setw(6) << m_TexCoords[i].x
  // 	      << " / " << std::setw(6) << m_TexCoords[i].y << ")"
  // 	      << std::endl;

  // for ( std::vector< sf::Vector3f >::iterator itr = m_Vertices.begin();
  // 	itr != m_Vertices.end();
  //       ++itr )
  //   std::cerr << "v :" << itr->x << " / " << itr->y << " / " << itr->z << std::endl;

  // std::cerr << std::endl;

  // for ( std::vector< sf::Vector2f >::iterator itr = m_TexCoords.begin();
  // 	itr != m_TexCoords.end();
  //       ++itr )
  //   std::cerr << "t :" << itr->x << " / " << itr->y << std::endl;

  // std::cerr << std::endl;
  // std::cerr << std::endl;

  // static std::vector< sf::Vector3f >*	s_Vertices;
  // static std::vector< sf::Vector3f >*	s_Normales;
  // static std::vector< sf::Vector2f >*	s_TexCoords;
  // static std::vector< unsigned int >*	s_Indices;
  // static std::vector< unsigned int >*	s_Indices2;
  // static float				s_radius;

  set_treeSearcher.clear();

  Setup();
}
void	drawPatch( const t_drawPatch_data& data )
{
  if (data.s_level > 0)
    {
      sf::Vector3f	q1, q2, q3;

#define	D_SET_VERTEX(q, l, r)		\
      (q).x = 0.5f * ((l).x + (r).x);	\
      (q).y = 0.5f * ((l).y + (r).y);	\
      (q).z = 0.5f * ((l).z + (r).z);

      D_SET_VERTEX(q1, data.s_p1, data.s_p2);
      D_SET_VERTEX(q2, data.s_p2, data.s_p3);
      D_SET_VERTEX(q3, data.s_p3, data.s_p1);

#undef	D_SET_VERTEX

#define	D_SQ(v)			((v) * (v))
#define	D_VEC_LENGTH(v3)	(sqrtf( D_SQ( (v3).x ) + D_SQ( (v3).y ) + D_SQ( (v3).z ) ))

#define	D_NORM(q)						\
      length = 1.0f / D_VEC_LENGTH(q);				\
      (q).x *= length; (q).y *= length; (q).z *= length;

      float	length;

      D_NORM(q1);
      D_NORM(q2);
      D_NORM(q3);

#undef	D_NORM
#undef	D_VEC_LENGTH
#undef	D_SQ

      drawPatch( t_drawPatch_data( data.s_p1, q1, q3, data.s_level - 1 ) );
      drawPatch( t_drawPatch_data( q1, data.s_p2, q2, data.s_level - 1 ) );
      drawPatch( t_drawPatch_data( q1, q2, q3,        data.s_level - 1 ) );
      drawPatch( t_drawPatch_data( q3, q2, data.s_p3, data.s_level - 1 ) );
    }

  else
    {
      sf::Vector3f*	px_array[] = { &data.s_p1, &data.s_p2, &data.s_p3 };

      for (int i_point = 0; i_point < 3; ++i_point)
	{
	  sf::Vector3f&	curr_px = *px_array[i_point];

	  unsigned int	i_search = 0;

	  ////
	  std::set< t_index_vertex, t_cmpfunc >::iterator	set_itr;
	  t_index_vertex	index_vertex(data.s_Normales->size(), &curr_px);

	  set_itr = set_treeSearcher.find( index_vertex );

	  if (set_itr != set_treeSearcher.end())
	    i_search = set_itr->s_index;

	  else
	    {
	      i_search = index_vertex.s_index;

	      data.s_Vertices->push_back( curr_px * data.s_radius );
	      data.s_Normales->push_back( curr_px );


	      {
		sf::Vector2f	texCoord;

		{ // billboard

		  float	theta = 0;
		  float	phi = 0;

		  {
		    // sf::Vector3f	Center(0, 0, 0);
		    sf::Vector3f	Normal(curr_px);

		    // theta = atan2f( Center.y - Normal.y, Center.x - Normal.x ) * 180.0f / 3.14f;
		    theta = atan2f( Normal.y, Normal.x ) * 180.0f / 3.14f;

#define	D_SQ(v)		((v) * (v))
// #define	D_LENGTH(v1, v2) sqrtf( D_SQ((v1).x - (v2).x) + D_SQ((v1).y - (v2).y) )
#define	D_LENGTH(v3)	sqrtf( D_SQ( (v3).x ) + D_SQ( (v3).y ) )

		    sf::Vector2f	Profile_Pos;

		    // Profile_Pos.x = D_LENGTH( Center, Normal );
		    // Profile_Pos.y = Center.z - Normal.z;
		    Profile_Pos.x = D_LENGTH( Normal );
		    Profile_Pos.y = Normal.z;

#undef	D_SQ

		    phi = atan2f( Profile_Pos.y, Profile_Pos.x ) * 180.0f / 3.14f;

		  }


		  // std::cerr << "phi : " << phi << ", theta : " << theta << std::endl;

		  texCoord.x = (180.0f + theta) / 360.0f;
		  texCoord.y = (90.0f + phi) / 180.0f;

		  // std::cerr << std::fixed << std::setprecision(2)
		  // 	    << "v (" << std::setw(5) << texCoord.x
		  // 	    << " / " << std::setw(5) << texCoord.y
		  // 	    << "), theta (" << std::setw(7) << theta
		  // 	    << "), phi (" << std::setw(7) << phi << ")" << std::endl;

		} // /billboard

		// texCoord.x = 0.5f + 0.5f * curr_px.x;
		// texCoord.y = 0.5f + 0.5f * curr_px.y;


		// texCoord.x = (1.0f - curr_px.x) * 0.5f;
		// texCoord.y = (1.0f - curr_px.y) * 0.5f;


		// std::cerr << "tx : " << texCoord.x << " / " << texCoord.y << std::endl;

		data.s_TexCoords->push_back( texCoord );
	      }

	      index_vertex.s_pVertex = &data.s_Normales->back();

	      set_treeSearcher.insert( index_vertex );
	    }
	  ////


	  // for (; i_search < data.s_Normales->size(); ++i_search)
	  //   if ( (*data.s_Normales)[i_search].x == curr_px.x &&
	  //   	 (*data.s_Normales)[i_search].y == curr_px.y &&
	  //   	 (*data.s_Normales)[i_search].z == curr_px.z )
	  //     break;

	  // if (i_search == data.s_Normales->size())
	  //   {
	  //     data.s_Vertices->push_back( curr_px * data.s_radius );
	  //     data.s_Normales->push_back( curr_px );
	  //   }

	  data.s_Indices->push_back( i_search );
	  data.s_Indices2->push_back( i_search );
	}

    }
}
Example #18
0
/* CTextureCanvas::drawTexture
 * Draws the currently opened composite texture
 *******************************************************************/
void CTextureCanvas::drawTexture()
{
	// Push matrix
	glPushMatrix();

	// Calculate top-left position of texture (for glScissor, since it ignores the current translation/scale)
	double left = offset.x + (GetSize().x * 0.5) - (texture->getWidth() * 0.5 * scale);
	double top = -offset.y + (GetSize().y * 0.5) - (texture->getHeight() * 0.5 * scale);

	// Translate to middle of the canvas
	glTranslated(GetSize().x * 0.5, GetSize().y * 0.5, 0);

	// Zoom
	double yscale = (tx_arc ? scale * 1.2 : scale);
	glScaled(scale, yscale, 1);

	// Draw offset guides if needed
	drawOffsetLines();

	// Apply texture scale
	double tscalex = 1;
	double tscaley = 1;
	if (tex_scale)
	{
		tscalex = texture->getScaleX();
		if (tscalex == 0) tscalex = 1;
		tscaley = texture->getScaleY();
		if (tscaley == 0) tscaley = 1;
		glScaled(1.0 / tscalex, 1.0 / tscaley, 1);
	}

	// Translate by offsets if needed
	if (view_type == 0)
		glTranslated(texture->getWidth() * -0.5, texture->getHeight() * -0.5, 0);	// No offsets
	if (view_type >= 1)
		glTranslated(-texture->getOffsetX(), -texture->getOffsetY(), 0);			// Sprite offsets
	if (view_type == 2)
		glTranslated(-160*tscalex, -100*tscaley, 0);								// HUD offsets

	// Draw the texture border
	//if (gfx_show_border)
	drawTextureBorder();

	// Enable textures
	glEnable(GL_TEXTURE_2D);

	// First, draw patches semitransparently (for anything outside the texture)
	// But only if we are drawing stuff outside the texture area
	if (draw_outside)
	{
		for (uint32_t a = 0; a < texture->nPatches(); a++)
			drawPatch(a, true);
	}

	// Reset colouring
	OpenGL::setColour(COL_WHITE);

	// If we're currently dragging, draw a 'basic' preview of the texture using opengl
	if (dragging)
	{
		glEnable(GL_SCISSOR_TEST);
		glScissor(left, top, texture->getWidth() * scale, texture->getHeight() * scale);
		for (uint32_t a = 0; a < texture->nPatches(); a++)
			drawPatch(a);
		glDisable(GL_SCISSOR_TEST);
	}

	// Otherwise, draw the fully generated texture
	else
	{
		// Generate if needed
		if (!tex_preview.isLoaded())
		{
			// Determine image type
			SIType type = PALMASK;
			if (blend_rgba) type = RGBA;

			// CTexture -> temp Image -> GLTexture
			SImage temp(type);
			texture->toImage(temp, parent, &palette, blend_rgba);
			tex_preview.loadImage(&temp, &palette);
		}

		// Draw it
		tex_preview.draw2d();
	}

	// Disable textures
	glDisable(GL_TEXTURE_2D);

	// Now loop through selected patches and draw selection outlines
	OpenGL::setColour(70, 210, 220, 255, BLEND_NORMAL);
	glEnable(GL_LINE_SMOOTH);
	glLineWidth(1.5f);
	for (size_t a = 0; a < selected_patches.size(); a++)
	{
		// Skip if not selected
		if (!selected_patches[a])
			continue;

		// Get patch
		CTPatch* patch = texture->getPatch(a);
		CTPatchEx* epatch = (CTPatchEx*)patch;

		// Check for rotation
		if (texture->isExtended() && (epatch->getRotation() == 90 || epatch->getRotation() == -90))
		{
			// Draw outline, width/height swapped
			glBegin(GL_LINE_LOOP);
			glVertex2i(patch->xOffset(), patch->yOffset());
			glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_textures[a]->getWidth());
			glVertex2i(patch->xOffset() + (int)patch_textures[a]->getHeight(), patch->yOffset() + (int)patch_textures[a]->getWidth());
			glVertex2i(patch->xOffset() + (int)patch_textures[a]->getHeight(), patch->yOffset());
			glEnd();
		}
		else
		{
			// Draw outline
			glBegin(GL_LINE_LOOP);
			glVertex2i(patch->xOffset(), patch->yOffset());
			glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_textures[a]->getHeight());
			glVertex2i(patch->xOffset() + (int)patch_textures[a]->getWidth(), patch->yOffset() + (int)patch_textures[a]->getHeight());
			glVertex2i(patch->xOffset() + (int)patch_textures[a]->getWidth(), patch->yOffset());
			glEnd();
		}
	}

	// Finally, draw a hilight outline if anything is hilighted
	if (hilight_patch >= 0)
	{
		// Set colour
		OpenGL::setColour(255, 255, 255, 150, BLEND_ADDITIVE);

		// Get patch
		CTPatch* patch = texture->getPatch(hilight_patch);
		CTPatchEx* epatch = (CTPatchEx*)patch;
		GLTexture* patch_texture = patch_textures[hilight_patch];

		// Check for rotation
		if (texture->isExtended() && (epatch->getRotation() == 90 || epatch->getRotation() == -90))
		{
			// Draw outline, width/height swapped
			glBegin(GL_LINE_LOOP);
			glVertex2i(patch->xOffset(), patch->yOffset());
			glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_texture->getWidth());
			glVertex2i(patch->xOffset() + (int)patch_texture->getHeight(), patch->yOffset() + (int)patch_texture->getWidth());
			glVertex2i(patch->xOffset() + (int)patch_texture->getHeight(), patch->yOffset());
			glEnd();
		}
		else
		{
			// Draw outline
			glBegin(GL_LINE_LOOP);
			glVertex2i(patch->xOffset(), patch->yOffset());
			glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_texture->getHeight());
			glVertex2i(patch->xOffset() + (int)patch_texture->getWidth(), patch->yOffset() + (int)patch_texture->getHeight());
			glVertex2i(patch->xOffset() + (int)patch_texture->getWidth(), patch->yOffset());
			glEnd();
		}
	}
	glDisable(GL_LINE_SMOOTH);
	glLineWidth(1.0f);

	// Pop matrix
	glPopMatrix();
}
// ######################################################################
// get gist histogram to visualize the data
Image<float> RawGistEstimatorGen::getGistImage(int sqSize,
    float minO, float maxO,
    float minC, float maxC,
    float minI, float maxI)
{
  // square size
  int s = sqSize;
  Image<float> img(NUM_GIST_COL * s, NUM_GIST_FEAT * s, ZEROS);
  float range;
  
  // setup range for orientation channel if necessary
  if(maxO == minO)
    {
      minO = itsGistVector.getVal(0);
      maxO = itsGistVector.getVal(0);
      for(int i = 0; i < 16; i++)
        for(int j = 0; j < NUM_GIST_FEAT; j++)
          {
            float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
            if(val < minO)
              minO = val;
            else if(val > maxO)
              maxO = val;
          }
      LDEBUG("Orientation Channel Min: %f, max: %f", minO, maxO);
    }
  range = maxO - minO;
  
  // orientation channel
  for(int a = 0; a < 4; a++)
    for(int b = 0; b < 4; b++)
      for(int j = 0; j < NUM_GIST_FEAT; j++)
        {
          int i  = b*4 + a;
          int ii = a*4 + b;
          float val = itsGistVector.getVal(ii*NUM_GIST_FEAT+j);
          drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minO)/range);
        }
  
  // setup range for color channel if necessary
  if(maxC == minC)
    {
      minC = itsGistVector.getVal(16*NUM_GIST_FEAT);
      maxC = itsGistVector.getVal(16*NUM_GIST_FEAT);
      for(int i = 16; i < 28; i++)
        for(int j = 0; j < NUM_GIST_FEAT; j++)
          {
            float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
            if(val < minC)
              minC = val;
            else if(val > maxC)
              maxC = val;
          }
      LDEBUG("Color Channel Min: %f, max: %f", minC, maxC);
    }
  range = maxC - minC;
  
  // color channel
  for(int i = 16; i < 28; i++)
    for(int j = 0; j < NUM_GIST_FEAT; j++)
      {
        float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
        drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minC)/range);
      }
  
  // setup range for intensity channel if necessary
  if(maxI == minI)
    {
      minI = itsGistVector.getVal(28*NUM_GIST_FEAT);
      maxI = itsGistVector.getVal(28*NUM_GIST_FEAT);
      for(int i = 28; i < 34; i++)
        for(int j = 0; j < NUM_GIST_FEAT; j++)
          {
            float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
            if(val < minI)
              minI = val;
            else if(val > maxI)
              maxI = val;
          }
      LDEBUG("Intensity Channel Min: %f, max: %f", minI, maxI);
    }
  range = maxI - minI;
  
  // intensity channel
  for(int i = 28; i < NUM_GIST_COL; i++)
    for(int j = 0; j < NUM_GIST_FEAT; j++)
      {
        float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
        drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minI)/range);
      }
  
  // draw the delineation
  // spatially
  float max = 1.0f;
  drawLine(img, Point2D<int>(0,  1*s), Point2D<int>(NUM_GIST_COL*s,  1*s), max,   1);
  drawLine(img, Point2D<int>(0,  5*s), Point2D<int>(NUM_GIST_COL*s,  5*s), max,   1);
  drawLine(img, Point2D<int>(0,  9*s), Point2D<int>(NUM_GIST_COL*s,  9*s), max/2, 1);
  drawLine(img, Point2D<int>(0, 13*s), Point2D<int>(NUM_GIST_COL*s, 13*s), max/2, 1);
  drawLine(img, Point2D<int>(0, 17*s), Point2D<int>(NUM_GIST_COL*s, 17*s), max/2, 1);
  
  // channelwise
  drawLine(img, Point2D<int>( 4*s, 0), Point2D<int>( 4*s, NUM_GIST_FEAT*s), max, 1);
  drawLine(img, Point2D<int>( 8*s, 0), Point2D<int>( 8*s, NUM_GIST_FEAT*s), max, 1);
  drawLine(img, Point2D<int>(12*s, 0), Point2D<int>(12*s, NUM_GIST_FEAT*s), max, 1);
  drawLine(img, Point2D<int>(16*s, 0), Point2D<int>(16*s, NUM_GIST_FEAT*s), max, 1);
  drawLine(img, Point2D<int>(22*s, 0), Point2D<int>(22*s, NUM_GIST_FEAT*s), max, 1);
  drawLine(img, Point2D<int>(28*s, 0), Point2D<int>(28*s, NUM_GIST_FEAT*s), max, 1);

  return img;
}
Example #20
0
namespace SkRecords {

// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
static SkBitmap shallow_copy(const SkBitmap& bitmap) {
    return bitmap;
}

// NoOps draw nothing.
template <> void Draw::draw(const NoOp&) {}

#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
DRAW(Restore, restore());
DRAW(Save, save());
DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags));
DRAW(PopCull, popCull());
DRAW(PushCull, pushCull(r.rect));
DRAW(Clear, clear(r.color));
DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));

DRAW(ClipPath, clipPath(r.path, r.op, r.doAA));
DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA));
DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA));
DRAW(ClipRegion, clipRegion(r.region, r.op));

DRAW(BeginCommentGroup, beginCommentGroup(r.description));
DRAW(AddComment, addComment(r.key, r.value));
DRAW(EndCommentGroup, endCommentGroup());

DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint));
DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint));
DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint));
DRAW(DrawBitmapRectToRect,
        drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags));
DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
DRAW(DrawImage, drawImage(r.image, r.left, r.top, r.paint));
DRAW(DrawImageRect, drawImageRect(r.image, r.src, r.dst, r.paint));
DRAW(DrawOval, drawOval(r.oval, r.paint));
DRAW(DrawPaint, drawPaint(r.paint));
DRAW(DrawPath, drawPath(r.path, r.paint));
DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint));
DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint));
DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
DRAW(DrawRect, drawRect(r.rect, r.paint));
DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint));
DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint));
DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint));
DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
                                r.xmode.get(), r.indices, r.indexCount, r.paint));
DRAW(DrawData, drawData(r.data, r.length));
#undef DRAW

// This is an SkRecord visitor that fills an SkBBoxHierarchy.
//
// The interesting part here is how to calculate bounds for ops which don't
// have intrinsic bounds.  What is the bounds of a Save or a Translate?
//
// We answer this by thinking about a particular definition of bounds: if I
// don't execute this op, pixels in this rectangle might draw incorrectly.  So
// the bounds of a Save, a Translate, a Restore, etc. are the union of the
// bounds of Draw* ops that they might have an effect on.  For any given
// Save/Restore block, the bounds of the Save, the Restore, and any other
// non-drawing ("control") ops inside are exactly the union of the bounds of
// the drawing ops inside that block.
//
// To implement this, we keep a stack of active Save blocks.  As we consume ops
// inside the Save/Restore block, drawing ops are unioned with the bounds of
// the block, and control ops are stashed away for later.  When we finish the
// block with a Restore, our bounds are complete, and we go back and fill them
// in for all the control ops we stashed away.
class FillBounds : SkNoncopyable {
public:
    FillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHierarchy* bbh) 
        : fCullRect(cullRect)
        , fBounds(record.count()) {
        // Calculate bounds for all ops.  This won't go quite in order, so we'll need
        // to store the bounds separately then feed them in to the BBH later in order.
        fCTM = &SkMatrix::I();
        fCurrentClipBounds = fCullRect;
        for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) {
            record.visit<void>(fCurrentOp, *this);
        }

        // If we have any lingering unpaired Saves, simulate restores to make
        // sure all ops in those Save blocks have their bounds calculated.
        while (!fSaveStack.isEmpty()) {
            this->popSaveBlock();
        }

        // Any control ops not part of any Save/Restore block draw everywhere.
        while (!fControlIndices.isEmpty()) {
            this->popControl(fCullRect);
        }

        // Finally feed all stored bounds into the BBH.  They'll be returned in this order.
        SkASSERT(bbh);
        bbh->insert(&fBounds, record.count());
    }

    template <typename T> void operator()(const T& op) {
        this->updateCTM(op);
        this->updateClipBounds(op);
        this->trackBounds(op);
    }

private:
    // In this file, SkRect are in local coordinates, Bounds are translated back to identity space.
    typedef SkRect Bounds;

    struct SaveBounds {
        int controlOps;        // Number of control ops in this Save block, including the Save.
        Bounds bounds;         // Bounds of everything in the block.
        const SkPaint* paint;  // Unowned.  If set, adjusts the bounds of all ops in this block.
    };

    // Only Restore and SetMatrix change the CTM.
    template <typename T> void updateCTM(const T&) {}
    void updateCTM(const Restore& op)   { fCTM = &op.matrix; }
    void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; }

    // Most ops don't change the clip.
    template <typename T> void updateClipBounds(const T&) {}

    // Clip{Path,RRect,Rect,Region} obviously change the clip.  They all know their bounds already.
    void updateClipBounds(const ClipPath&   op) { this->updateClipBoundsForClipOp(op.devBounds); }
    void updateClipBounds(const ClipRRect&  op) { this->updateClipBoundsForClipOp(op.devBounds); }
    void updateClipBounds(const ClipRect&   op) { this->updateClipBoundsForClipOp(op.devBounds); }
    void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); }

    // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside.
    void updateClipBoundsForClipOp(const SkIRect& devBounds) {
        Bounds clip = SkRect::Make(devBounds);
        // We don't call adjustAndMap() because as its last step it would intersect the adjusted
        // clip bounds with the previous clip, exactly what we can't do when the clip grows.
        fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : fCullRect;
    }

    // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes.
    void updateClipBounds(const Restore& op) {
        // This is just like the clip ops above, but we need to skip the effects (if any) of our
        // paired saveLayer (if it is one); it has not yet been popped off the save stack.  Our
        // devBounds reflect the state of the world after the saveLayer/restore block is done,
        // so they are not affected by the saveLayer's paint.
        const int kSavesToIgnore = 1;
        Bounds clip = SkRect::Make(op.devBounds);
        fCurrentClipBounds =
            this->adjustForSaveLayerPaints(&clip, kSavesToIgnore) ? clip : fCullRect;
    }

    // We also take advantage of SaveLayer bounds when present to further cut the clip down.
    void updateClipBounds(const SaveLayer& op)  {
        if (op.bounds) {
            // adjustAndMap() intersects these layer bounds with the previous clip for us.
            fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint);
        }
    }

    // The bounds of these ops must be calculated when we hit the Restore
    // from the bounds of the ops in the same Save block.
    void trackBounds(const Save&)          { this->pushSaveBlock(NULL); }
    void trackBounds(const SaveLayer& op)  { this->pushSaveBlock(op.paint); }
    void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); }

    void trackBounds(const SetMatrix&)         { this->pushControl(); }
    void trackBounds(const ClipRect&)          { this->pushControl(); }
    void trackBounds(const ClipRRect&)         { this->pushControl(); }
    void trackBounds(const ClipPath&)          { this->pushControl(); }
    void trackBounds(const ClipRegion&)        { this->pushControl(); }
    void trackBounds(const PushCull&)          { this->pushControl(); }
    void trackBounds(const PopCull&)           { this->pushControl(); }
    void trackBounds(const BeginCommentGroup&) { this->pushControl(); }
    void trackBounds(const AddComment&)        { this->pushControl(); }
    void trackBounds(const EndCommentGroup&)   { this->pushControl(); }
    void trackBounds(const DrawData&)          { this->pushControl(); }

    // For all other ops, we can calculate and store the bounds directly now.
    template <typename T> void trackBounds(const T& op) {
        fBounds[fCurrentOp] = this->bounds(op);
        this->updateSaveBounds(fBounds[fCurrentOp]);
    }

    void pushSaveBlock(const SkPaint* paint) {
        // Starting a new Save block.  Push a new entry to represent that.
        SaveBounds sb;
        sb.controlOps = 0;
        // If the paint affects transparent black, the bound shouldn't be smaller
        // than the current clip bounds.
        sb.bounds =
            PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds::MakeEmpty();
        sb.paint = paint;

        fSaveStack.push(sb);
        this->pushControl();
    }

    static bool PaintMayAffectTransparentBlack(const SkPaint* paint) {
        if (paint) {
            // FIXME: this is very conservative
            if (paint->getImageFilter() || paint->getColorFilter()) {
                return true;
            }

            // Unusual Xfermodes require us to process a saved layer
            // even with operations outisde the clip.
            // For example, DstIn is used by masking layers.
            // https://code.google.com/p/skia/issues/detail?id=1291
            // https://crbug.com/401593
            SkXfermode* xfermode = paint->getXfermode();
            SkXfermode::Mode mode;
            // SrcOver is ok, and is also the common case with a NULL xfermode.
            // So we should make that the fast path and bypass the mode extraction
            // and test.
            if (xfermode && xfermode->asMode(&mode)) {
                switch (mode) {
                    // For each of the following transfer modes, if the source
                    // alpha is zero (our transparent black), the resulting
                    // blended alpha is not necessarily equal to the original
                    // destination alpha.
                    case SkXfermode::kClear_Mode:
                    case SkXfermode::kSrc_Mode:
                    case SkXfermode::kSrcIn_Mode:
                    case SkXfermode::kDstIn_Mode:
                    case SkXfermode::kSrcOut_Mode:
                    case SkXfermode::kDstATop_Mode:
                    case SkXfermode::kModulate_Mode:
                        return true;
                        break;
                    default:
                        break;
                }
            }
        }
        return false;
    }

    Bounds popSaveBlock() {
        // We're done the Save block.  Apply the block's bounds to all control ops inside it.
        SaveBounds sb;
        fSaveStack.pop(&sb);

        while (sb.controlOps --> 0) {
            this->popControl(sb.bounds);
        }

        // This whole Save block may be part another Save block.
        this->updateSaveBounds(sb.bounds);

        // If called from a real Restore (not a phony one for balance), it'll need the bounds.
        return sb.bounds;
    }

    void pushControl() {
        fControlIndices.push(fCurrentOp);
        if (!fSaveStack.isEmpty()) {
            fSaveStack.top().controlOps++;
        }
    }

    void popControl(const Bounds& bounds) {
        fBounds[fControlIndices.top()] = bounds;
        fControlIndices.pop();
    }

    void updateSaveBounds(const Bounds& bounds) {
        // If we're in a Save block, expand its bounds to cover these bounds too.
        if (!fSaveStack.isEmpty()) {
            fSaveStack.top().bounds.join(bounds);
        }
    }

    // FIXME: this method could use better bounds
    Bounds bounds(const DrawText&) const { return fCurrentClipBounds; }

    Bounds bounds(const Clear&) const { return fCullRect; }             // Ignores the clip.
    Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; }
    Bounds bounds(const NoOp&)  const { return Bounds::MakeEmpty(); }    // NoOps don't draw.

    Bounds bounds(const DrawSprite& op) const {
        const SkBitmap& bm = op.bitmap;
        return Bounds::MakeXYWH(op.left, op.top, bm.width(), bm.height());  // Ignores the matrix.
    }

    Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); }
    Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); }
    Bounds bounds(const DrawRRect& op) const {
        return this->adjustAndMap(op.rrect.rect(), &op.paint);
    }
    Bounds bounds(const DrawDRRect& op) const {
        return this->adjustAndMap(op.outer.rect(), &op.paint);
    }
    Bounds bounds(const DrawImage& op) const {
        const SkImage* image = op.image;
        SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height());

        return this->adjustAndMap(rect, op.paint);
    }
    Bounds bounds(const DrawImageRect& op) const {
        return this->adjustAndMap(op.dst, op.paint);
    }
    Bounds bounds(const DrawBitmapRectToRect& op) const {
        return this->adjustAndMap(op.dst, op.paint);
    }
    Bounds bounds(const DrawBitmapNine& op) const {
        return this->adjustAndMap(op.dst, op.paint);
    }
    Bounds bounds(const DrawBitmap& op) const {
        const SkBitmap& bm = op.bitmap;
        return this->adjustAndMap(SkRect::MakeXYWH(op.left, op.top, bm.width(), bm.height()),
                                  op.paint);
    }
    Bounds bounds(const DrawBitmapMatrix& op) const {
        const SkBitmap& bm = op.bitmap;
        SkRect dst = SkRect::MakeWH(bm.width(), bm.height());
        op.matrix.mapRect(&dst);
        return this->adjustAndMap(dst, op.paint);
    }

    Bounds bounds(const DrawPath& op) const {
        return op.path.isInverseFillType() ? fCurrentClipBounds
                                           : this->adjustAndMap(op.path.getBounds(), &op.paint);
    }
    Bounds bounds(const DrawPoints& op) const {
        SkRect dst;
        dst.set(op.pts, op.count);

        // Pad the bounding box a little to make sure hairline points' bounds aren't empty.
        SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f);
        dst.outset(stroke/2, stroke/2);

        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawPatch& op) const {
        SkRect dst;
        dst.set(op.cubics, SkPatchUtils::kNumCtrlPts);
        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawVertices& op) const {
        SkRect dst;
        dst.set(op.vertices, op.vertexCount);
        return this->adjustAndMap(dst, &op.paint);
    }

    Bounds bounds(const DrawPicture& op) const {
        SkRect dst = op.picture->cullRect();
        if (op.matrix) {
            op.matrix->mapRect(&dst);
        }
        return this->adjustAndMap(dst, op.paint);
    }

    Bounds bounds(const DrawPosText& op) const {
        const int N = op.paint.countText(op.text, op.byteLength);
        if (N == 0) {
            return Bounds::MakeEmpty();
        }

        SkRect dst;
        dst.set(op.pos, N);
        AdjustTextForFontMetrics(&dst, op.paint);
        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawPosTextH& op) const {
        const int N = op.paint.countText(op.text, op.byteLength);
        if (N == 0) {
            return Bounds::MakeEmpty();
        }

        SkScalar left = op.xpos[0], right = op.xpos[0];
        for (int i = 1; i < N; i++) {
            left  = SkMinScalar(left,  op.xpos[i]);
            right = SkMaxScalar(right, op.xpos[i]);
        }
        SkRect dst = { left, op.y, right, op.y };
        AdjustTextForFontMetrics(&dst, op.paint);
        return this->adjustAndMap(dst, &op.paint);
    }
    Bounds bounds(const DrawTextOnPath& op) const {
        SkRect dst = op.path.getBounds();

        // Pad all sides by the maximum padding in any direction we'd normally apply.
        SkRect pad = { 0, 0, 0, 0};
        AdjustTextForFontMetrics(&pad, op.paint);

        // That maximum padding happens to always be the right pad today.
        SkASSERT(pad.fLeft == -pad.fRight);
        SkASSERT(pad.fTop  == -pad.fBottom);
        SkASSERT(pad.fRight > pad.fBottom);
        dst.outset(pad.fRight, pad.fRight);

        return this->adjustAndMap(dst, &op.paint);
    }

    Bounds bounds(const DrawTextBlob& op) const {
        SkRect dst = op.blob->bounds();
        dst.offset(op.x, op.y);
        return this->adjustAndMap(dst, &op.paint);
    }

    static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) {
#ifdef SK_DEBUG
        SkRect correct = *rect;
#endif
        // crbug.com/373785 ~~> xPad = 4x yPad
        // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x
        const SkScalar yPad = 2.5f * paint.getTextSize(),
                       xPad = 4.0f * yPad;
        rect->outset(xPad, yPad);
#ifdef SK_DEBUG
        SkPaint::FontMetrics metrics;
        paint.getFontMetrics(&metrics);
        correct.fLeft   += metrics.fXMin;
        correct.fTop    += metrics.fTop;
        correct.fRight  += metrics.fXMax;
        correct.fBottom += metrics.fBottom;
        // See skia:2862 for why we ignore small text sizes.
        SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct),
                  "%f %f %f %f vs. %f %f %f %f\n",
                  -xPad, -yPad, +xPad, +yPad,
                  metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom);
#endif
    }

    // Returns true if rect was meaningfully adjusted for the effects of paint,
    // false if the paint could affect the rect in unknown ways.
    static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
        if (paint) {
            if (paint->canComputeFastBounds()) {
                *rect = paint->computeFastBounds(*rect, rect);
                return true;
            }
            return false;
        }
        return true;
    }

    bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const {
        for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) {
            if (!AdjustForPaint(fSaveStack[i].paint, rect)) {
                return false;
            }
        }
        return true;
    }

    // Adjust rect for all paints that may affect its geometry, then map it to identity space.
    Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const {
        // Inverted rectangles really confuse our BBHs.
        rect.sort();

        // Adjust the rect for its own paint.
        if (!AdjustForPaint(paint, &rect)) {
            // The paint could do anything to our bounds.  The only safe answer is the current clip.
            return fCurrentClipBounds;
        }

        // Adjust rect for all the paints from the SaveLayers we're inside.
        if (!this->adjustForSaveLayerPaints(&rect)) {
            // Same deal as above.
            return fCurrentClipBounds;
        }

        // Map the rect back to identity space.
        fCTM->mapRect(&rect);

        // Nothing can draw outside the current clip.
        // (Only bounded ops call into this method, so oddballs like Clear don't matter here.)
        rect.intersect(fCurrentClipBounds);
        return rect;
    }

    // We do not guarantee anything for operations outside of the cull rect
    const SkRect fCullRect;

    // Conservative identity-space bounds for each op in the SkRecord.
    SkAutoTMalloc<Bounds> fBounds;

    // We walk fCurrentOp through the SkRecord, as we go using updateCTM()
    // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative
    // identity-space bounds of the current clip (fCurrentClipBounds).
    unsigned fCurrentOp;
    const SkMatrix* fCTM;
    Bounds fCurrentClipBounds;

    // Used to track the bounds of Save/Restore blocks and the control ops inside them.
    SkTDArray<SaveBounds> fSaveStack;
    SkTDArray<unsigned>   fControlIndices;
};

}  // namespace SkRecords