int main(int argc, char* argv[]) { 

  if( argc != 4 && argc != 5 ) {
    std::cout << "USAGE: ./do2ndLevel_PhotonJet_batch [dataset] [inputFileList] [flags] [useGenJets=false]" << std::endl;
    exit(23);
  }


  std::string dataset(argv[1]);
  std::string inputFileList(argv[2]);
  std::string flags(argv[3]);
  bool useGenJets = false;

  if( argc == 5 ) {
    std::string useGenJets_str(argv[4]);
    if( useGenJets_str=="true" ) useGenJets = true;
  }

  TRegexp run2010("Run2010");
  TRegexp run2011("Run2011");
  TRegexp run2012("Run2012");
  TString dataset_str(dataset);
  
  if( dataset_str.Contains(run2010) || dataset_str.Contains(run2011) || dataset_str.Contains(run2012) ) { // then it's data
    doSingleLoop(inputFileList, dataset, flags, (bool)true, (bool)false);
  } else {
    doSingleLoop(inputFileList, dataset, flags, (bool)false, useGenJets);
  }


}
int main(int argc, char* argv[]) { 

  if( argc != 6 && argc != 7 ) {
    std::cout << "USAGE: ./do2ndLevel_PhotonJet_batch [dataset] [recoType] [jetAlgo] [inputFileList] [flags] [useGenJets=false]" << std::endl;
    exit(23);
  }


  std::string dataset(argv[1]);
  std::string recoType(argv[2]);
  std::string jetAlgo(argv[3]);
  std::string inputFileList(argv[4]);
  std::string flags(argv[5]);
  bool useGenJets = false;

  std::cout << "argv[1]: " << argv[1] << std::endl;
  std::cout << "argv[2]: " << argv[2] << std::endl;
  std::cout << "argv[3]: " << argv[3] << std::endl;
  std::cout << "argv[4]: " << argv[4] << std::endl;
  std::cout << "argv[5]: " << argv[5] << std::endl;

  if( argc == 7 ) {
    std::string useGenJets_str(argv[6]);
    if( useGenJets_str=="true" ) useGenJets = true;
  }

  TRegexp run2010("Run2010");
  TRegexp run2011("Run2011");
  TRegexp minbias("MinimumBias_Commissioning10");
  TRegexp nov4("Nov4ReReco");
  TRegexp dec22("Dec22ReReco");
  TString dataset_str(dataset);
  
  if( dataset_str.Contains(run2010) || dataset_str.Contains(run2011) ||dataset_str.Contains(minbias) || dataset_str.Contains(nov4) || dataset_str.Contains(dec22) ) { // then it's data
    doSingleLoop(inputFileList, dataset, recoType, jetAlgo, flags, (bool)true, (bool)false);
  } else {
    doSingleLoop(inputFileList, dataset, recoType, jetAlgo, flags, (bool)false, useGenJets);
  }


}
int main (int argc, char** argv)
{  
  std::cout<<"--------> DUMPER: READ RECO DATA AND PRODUCE PROFILE PLOTS <--------"<<std::endl;
  
  
  //--------Read Options--------------------------------
  std::string inputFileList(argv[1]);
  std::string outputLabel = argv[2];
  int entriesMax = atoi(argv[3]);
  
  std::cout << "--------------------------------" << std::endl;
  std::cout << "inputFileList: "       << argv[1] << std::endl;
  std::cout << "outputLabel: "         << argv[2] << std::endl;
  std::cout << "entriesMax: "          << argv[3] << std::endl;
  std::cout << "--------------------------------" << std::endl;
  
  
  //-------start to read the input file list--------
  
  TChain* treeReco = new TChain("ntu");
  RecoTreeVars recoTV;
  InitRecoTree(treeReco,recoTV);
  FillChain(treeReco,inputFileList);
  
  
  //---------output histograms----------------
  TFile* outputFile = TFile::Open(Form("plots/plots_studyProfiles_%s.root",outputLabel.c_str()),"RECREATE");
  TH2F* h2_beamPosition_TDC = new TH2F("h2_beamPosition_TDC","",100,-240,-140.,100,-146,-46.);
  TH2F* h2_beamPosition_hodo11 = new TH2F("h2_beamPosition_hodo11","",160,-210.,-130.,160,-155.,-75.);
  TH2F* h2_beamPosition_hodo22 = new TH2F("h2_beamPosition_hodo22","",160,-210.,-130.,160,-155.,-75.);
  TH2F* h2_beamPosition_hodo12 = new TH2F("h2_beamPosition_hodo12","",160,-210.,-130.,160,-155.,-75.);
  TH2F* h2_beamPosition_hodo21 = new TH2F("h2_beamPosition_hodo21","",160,-210.,-130.,160,-155.,-75.);
  
  std::map<int,TProfile*> p_cellProfileX_TDC;
  std::map<int,TProfile*> p_cellProfileX_hodo12;
  std::map<int,TProfile*> p_cellProfileY_TDC;
  std::map<int,TProfile*> p_cellProfileY_hodo12;
  std::map<int,TH1F*> h_cell_charge;
  for(int iCh = 0; iCh < 32; ++iCh)
  {
    p_cellProfileX_TDC[iCh]    = new TProfile(Form("p_cell%02dProfileX_TDC",iCh),"",   100,-240.,-140.);
    p_cellProfileX_hodo12[iCh] = new TProfile(Form("p_cell%02dProfileX_hodo12",iCh),"",160,-210.,-130.);
    p_cellProfileY_TDC[iCh]    = new TProfile(Form("p_cell%02dProfileY_TDC",iCh),"",   100,-146., -46.);
    p_cellProfileY_hodo12[iCh] = new TProfile(Form("p_cell%02dProfileY_hodo12",iCh),"",160,-155., -75.);
    h_cell_charge[iCh] = new TH1F(Form("h_cell%02d_charge",iCh),"",100000,0., 10000000.);
  }
  
  TH1F* h_total_charge = new TH1F("h_total_charge","",100000,0., 10000000.);
  TProfile2D* p2_cellPosition_TDC    = new TProfile2D("p2_cellPosition_TDC",   "",100,-240.,-140.,100,-152.,-52.);
  TProfile2D* p2_cellPosition_hodo12 = new TProfile2D("p2_cellPosition_hodo12","",160,-210.,-130.,160,-155.,-75.);
  
  
  //-----Data loop--------------------------------------------------------
  int nEntries = treeReco -> GetEntries();
  if( entriesMax < 0 ) entriesMax = nEntries;
  for(int iEntry = 0; iEntry < entriesMax; ++iEntry)
  {
    if( iEntry%1 == 0 ) std::cout << ">>> reading entry: " << iEntry << " / " << nEntries << "\r" << std::flush;
    
    
    //---Read the entry
    ClearRecoTreeVars(recoTV);
    treeReco->GetEntry(iEntry);
    
    
    //---Reconstruct beam position
    float beamX_TDC = -recoTV.tableX + recoTV.tdcX;
    float beamY_TDC = -recoTV.tableY + recoTV.tdcY;
    
    float hodoX1 = GetHodoWire(recoTV.nHodoX1,recoTV.hodoX1);
    float hodoY1 = GetHodoWire(recoTV.nHodoY1,recoTV.hodoY1);
    float hodoX2 = GetHodoWire(recoTV.nHodoX2,recoTV.hodoX2);
    float hodoY2 = GetHodoWire(recoTV.nHodoY2,recoTV.hodoY2);
    float beamX_hodo1 = hodoX1 >= 0 ? -recoTV.tableX + 0.5*hodoX1 : -999;
    float beamY_hodo1 = hodoY1 >= 0 ? -recoTV.tableY - 0.5*hodoY1 : -999;
    float beamX_hodo2 = hodoX2 >= 0 ? -recoTV.tableX + 0.5*hodoX2 : -999;
    float beamY_hodo2 = hodoY2 >= 0 ? -recoTV.tableY - 0.5*hodoY2 : -999;
    
    
    //---Fill histograms
    h2_beamPosition_TDC -> Fill(beamX_TDC,beamY_TDC);
    if( beamX_hodo1 != -999 && beamY_hodo1 != -999 ) h2_beamPosition_hodo11 -> Fill(beamX_hodo1,beamY_hodo1);
    if( beamX_hodo2 != -999 && beamY_hodo2 != -999 ) h2_beamPosition_hodo22 -> Fill(beamX_hodo2,beamY_hodo2);
    if( beamX_hodo1 != -999 && beamY_hodo2 != -999 ) h2_beamPosition_hodo12 -> Fill(beamX_hodo1,beamY_hodo2);
    if( beamX_hodo2 != -999 && beamY_hodo1 != -999 ) h2_beamPosition_hodo21 -> Fill(beamX_hodo2,beamY_hodo1);
    
    float total_charge = 0.;
    for(int iCh = 0; iCh < 32; ++iCh)
    {
      if( recoTV.amp_DQM[iCh] > 500 ) p2_cellPosition_TDC    -> Fill(beamX_TDC,  beamY_TDC,  32*(iCh%2)+pow(-1,iCh)*iCh);
      if( recoTV.amp_DQM[iCh] > 500 ) p2_cellPosition_hodo12 -> Fill(beamX_hodo1,beamY_hodo2,32*(iCh%2)+pow(-1,iCh)*iCh);
      if( recoTV.amp_DQM[iCh] > 0. && recoTV.amp_DQM[iCh] < 999999. )
      {
        p_cellProfileX_TDC[iCh]    -> Fill(beamX_TDC,  recoTV.amp_DQM[iCh]);
        p_cellProfileX_hodo12[iCh] -> Fill(beamX_hodo1,recoTV.amp_DQM[iCh]);
        p_cellProfileY_TDC[iCh]    -> Fill(beamY_TDC,  recoTV.amp_DQM[iCh]);
        p_cellProfileY_hodo12[iCh] -> Fill(beamY_hodo2,recoTV.amp_DQM[iCh]);
        h_cell_charge[iCh] -> Fill(recoTV.charge_DQM[iCh]);
        if(iCh==12 || iCh==13 || iCh==18 || iCh==19)
          total_charge += recoTV.charge_DQM[iCh];
      }
    }
    
    if( (fabs(beamX_hodo1+180.) < 5.) &&
        (fabs(beamY_hodo2+117.) < 5.) )
      h_total_charge -> Fill(total_charge);
  }
  std::cout << std::endl;
  
  
  // //-----close everything-----------------------------------------------------
  outputFile -> Write();
  outputFile -> Close();
  
  
  //---------Done-----------------------------------------------------------------
}
int
main
	(
	int		argc,
	char*	argv[]
	)
{
	// parse the command line options

	JPtrArray<JString> inputFileList(JPtrArrayT::kDeleteAll);
	JString dataVarName, outputFileName, databaseFileName;
	JBoolean debug;
	GetOptions(argc, argv, &inputFileList,
			   &dataVarName, &outputFileName, &databaseFileName, &debug);

	const JSize inputCount = inputFileList.GetElementCount();

	// check mod times of input files
/*
	This doesn't work because compiling different versions of the program
	requires different sets of string files, none of which may have been
	modified in a long time.  The output file still needs to be re-built,
	however!

	time_t outputTime;
	if ((JGetModificationTime(outputFileName, &outputTime)).OK())
		{
		JBoolean changed = kJFalse;

		for (JIndex i=1; i<=inputCount; i++)
			{
			const JString* inputFileName = inputFileList.NthElement(i);
			time_t t;
			if (!(JGetModificationTime(*inputFileName, &t)).OK())
				{
				cerr << argv[0] << ":  " << *inputFileName << " does not exist" << endl;
				return 1;
				}
			else if (t >= outputTime)
				{
				changed = kJTrue;
				break;
				}
			}

		if (!changed)
			{
			return 0;
			}
		}
*/
	// process the input files

	JStringManager mgr;

	for (JIndex i=1; i<=inputCount; i++)
		{
		const JString* inputFileName = inputFileList.NthElement(i);
		if (JDirectoryExists(*inputFileName))
			{
			continue;
			}

		ifstream input(*inputFileName);
		if (!input.good())
			{
			cerr << argv[0] << ":  unable to open " << *inputFileName << endl;
			return 1;
			}
		mgr.MergeFile(input, debug);
		if (input.fail())
			{
			cerr << argv[0] << ":  error while reading " << *inputFileName << endl;
			return 1;
			}
		}

	// generate the output file

	std::ostringstream data1;
	mgr.WriteFile(data1);

	JString data1Str = data1.str();
	if (!databaseFileName.IsEmpty())
		{
		ofstream dbOutput(databaseFileName);
		data1Str.Print(dbOutput);
		}

	if (!outputFileName.IsEmpty())
		{
		JIndex i = 1;
		while (data1Str.LocateNextSubstring("\\", &i))
			{
			data1Str.ReplaceSubstring(i,i, "\\\\");
			i += 2;
			}
		i = 1;
		while (data1Str.LocateNextSubstring("\"", &i))
			{
			data1Str.ReplaceSubstring(i,i, "\\\"");
			i += 2;
			}
		i = 1;
		while (data1Str.LocateNextSubstring("\n", &i))
			{
			data1Str.ReplaceSubstring(i,i, "\\n");
			i += 2;
			}

		std::ostringstream data2;
		data2 << "#include <jTypes.h>" << endl;
		data2 << "static const JCharacter* ";
		dataVarName.Print(data2);
		data2 << "[] = {" << endl;

		// Visual C++ cannot handle file with more than 2048 characters on a line
		// and cannot compile string constant more than 2048 characters!

		const JSize l1 = data1Str.GetLength();
		for (i=0; i<l1; )
			{
			JSize l2 = JMin((JSize) 2040, l1 - i);
			while (l2 > 0 && data1Str.GetCharacter(i+l2) == '\\')
				{
				l2--;
				}
			assert( l2 > 0 );

			data2 << "\"";
			data2.write(((const char*) data1Str) + i, l2);
			data2 << "\"," << endl;

			i += l2;
			}

		data2 << "NULL };" << endl;

		// if the file won't change, don't re-write it

		const JString s2 = data2.str();
		if (JFileExists(outputFileName))
			{
			JString origData;
			JReadFile(outputFileName, &origData);
			if (origData == s2)
				{
				JUpdateCVSIgnore(outputFileName);
				return 0;
				}
			}

		// write file

		ofstream output(outputFileName);
		s2.Print(output);

		if (!output.good())
			{
			cerr << argv[0] << ":  unable to write to " << outputFileName << endl;
			return 1;
			}

		JUpdateCVSIgnore(outputFileName);
		}

	return 0;
}