//! event method
int
saModuleSngmuonMing::event(PHCompositeNode *topNode, sa_hist_mangager_ptr hm)
{

  SingleMuonContainer* sngmuons = findNode::getClass<SingleMuonContainer>(topNode,
      "SingleMuonContainer");
  if (!sngmuons)
    {
      cout << "saModuleSngmuonMing:: SngMuonContainer - ERROR - not in Node Tree"
          << endl;
      return ABORTRUN;
    }

  const saEventProperty * ep = findNode::getClass<saEventProperty>(topNode,
      "saEventProperty");
  if (!ep)
    {
      cout << "saModuleSngmuonMing::event - ERROR  - Cannot find EventProperty node in Top Node"
          << endl;
      return ABORTRUN;
    }

  //  int fill_number = ep->get_fill_number();
  int run_number  = ep->get_run_number();

  // good run12pp510 run # = 366283 - 366059
  // good run13pp510 run # = 386773 - 397990

  bool run12pp510 = false;
  bool run13pp510 = false;

  if (run_number > 360000 && run_number < 370000) run12pp510 = true;
  if (run_number > 380000 && run_number < 400000) run13pp510 = true;


  RpcSingleMuonContainer* rpcsngmuons = findNode::getClass<RpcSingleMuonContainer>(topNode,
      "RpcSingleMuonContainer");

  if (!rpcsngmuons)
    {
      if(run13pp510){
	cout << "saModuleSngmuonMing:: RpcSingelMuonContainer - ERROR - not in Node Tree"
	     << endl;
	return ABORTRUN;
      }
      else {
	cout << "this is <run12 pp510>, NO RpcSingleMuonContainer !" << endl;
      }
    }

  if (Verbosity() >= 2)
    {
      cout << "saModuleSngmuonMing::event - INFO  - ";
      ep->identify();
    }


  // --- 
  saFlagC *flag = findNode::getClass<saFlagC>(topNode, "SngmuonFlag");
  if (!flag)
    {
      cout << "saModuleSngmuonMing::event - SngmuonFlag not in Node Tree"
          << endl;
      return ABORTRUN;
    }

  // syncronizely set the cut flag with the SingleMuonContainer
  flag->flags.Set(sngmuons->get_nSingleMuons());
  flag->flags.Reset(0);

  // save the event for DST files?
  //  int return_code = dimuons->get_nDiMuons() >0 ? EVENT_OK : DISCARDEVENT;

  // determine this event's primary VTX      
  double Evt_fvtxX = sngmuons->get_Evt_fvtxX();
  double Evt_fvtxY = sngmuons->get_Evt_fvtxY();
  double Evt_fvtxZ = sngmuons->get_Evt_fvtxZ();

  double Evt_fvtxX2 = sngmuons->get_Evt_fvtxX2();
  double Evt_fvtxY2 = sngmuons->get_Evt_fvtxY2();
  double Evt_fvtxZ2 = sngmuons->get_Evt_fvtxZ2();

  double Evt_bbcZ = sngmuons->get_Evt_fvtxZ();

  double Evt_X0 =  -999;   // the primary z-vtx associated with muon candidate
  double Evt_Y0 =  -999;   // the primary z-vtx associated with muon candidate
  double Evt_Z0 =  -999;   // the primary z-vtx associated with muon candidate
    
  if ( fabs(Evt_bbcZ) > 100) {

    return DISCARDEVENT;
  }

  if ( fabs(Evt_fvtxZ) > 100 && fabs(Evt_fvtxZ2) > 100 ) {

    return DISCARDEVENT;
  }

  if ( sqrt(Evt_fvtxX*Evt_fvtxX + Evt_fvtxY*Evt_fvtxY) > 5 && sqrt(Evt_fvtxX2*Evt_fvtxX2 + Evt_fvtxY2*Evt_fvtxY2) > 5 ) {
    return DISCARDEVENT;
  }
 

  bool fill_ok = false;  // output this event to ooutput pdst file if "true"

  for (unsigned int imuon = 0; imuon < sngmuons->get_nSingleMuons(); imuon++)
    {
      SingleMuon* sngmuon = sngmuons->get_SingleMuon(imuon);

      // get RPC information for Run13 pp510
      RpcSingleMuon* rpcsngmuon = NULL;
      if (run13pp510) {
        rpcsngmuon = rpcsngmuons->get_RpcSingleMuon(imuon);
      }

      int charge = 0;

      charge = 2*sngmuon->get_charge() -1 ;   // charge in pdst = 1 for Q+ and 0 for Q-

      int arm = (sngmuon->get_pz() > 0) ? 1 : 0;
     
      double pX = sngmuon->get_px();
      double pY = sngmuon->get_py();
      double pZ = sngmuon->get_pz();

      double pT = sqrt(pX*pX +  pY*pY); 

      double pTot =  sqrt(pT*pT + pZ*pZ);

      double pX1 = sngmuon->get_st1px();
      double pY1 = sngmuon->get_st1py();
      double pZ1 = sngmuon->get_st1pz();

      double X1 = sngmuon->get_xst1();
      double Y1 = sngmuon->get_yst1();
      //      double Z1 = sngmuon->get_zst1();
      double Z1 = 0;

      if (run13pp510){
	Z1 = rpcsngmuon->get_zst1();
      }
      else {
	if (pZ >0){
	  Z1 = 189.1;   // <Z1> = 189.1 cm in run13pp510 data
	}
	else {
	  Z1 =  -189.1;
	}
      }

      double X2 = sngmuon->get_xst2();
      double Y2 = sngmuon->get_yst2();

      double X3 = sngmuon->get_xst3();
      double Y3 = sngmuon->get_yst3();

      double phi_1 = atan2(Y1,X1);
      double phi_2 = atan2(Y2,X2);
      double phi_3 = atan2(Y3,X3);

      double phi_13 = phi_3 - phi_1;
      double phi_23 = phi_3 - phi_2;

      //      double phi_13 = acos( (X1*X3 + Y1*Y3)/sqrt(X1*X1+Y1*Y1)/sqrt(X3*X3 + Y3*Y3) );    
      //      double phi_23 = acos( (X2*X3 + Y2*Y3)/sqrt(X2*X2+Y2*Y2)/sqrt(X3*X3 + Y3*Y3) );    

      double dA01 = -99;  // normalized multiple scattering angle VTX-ST1 vector x St1P 

      double eta     = sngmuon->get_rapidity();
      double lastGap = sngmuon->get_lastgap();
      double DG0 = sngmuon->get_DG0();
      double DDG0 = sngmuon->get_DDG0();

      double ntrhits = sngmuon->get_ntrhits();
      double nidhits = sngmuon->get_nidhits();

      double trchi2 = sngmuon->get_trchi2();
      double idchi2 = sngmuon->get_trchi2();

      double dca_z = sngmuon->get_dca_z();
      double dca_r = sngmuon->get_dca_r();

      double dphi_fvtx = sngmuon->get_dphi_fvtx();
      double dtheta_fvtx = sngmuon->get_dtheta_fvtx();
      double dr_fvtx = sngmuon->get_dr_fvtx();

      double Rpc3DCA =  -999;
      double Rpc1DCA =  -999;

      if (run12pp510){
	//      double Rpc3time = sngmuon->get_Rpctime();
	Rpc3DCA = sngmuon->get_RpcDCA();

	//      double Rpc1time = sngmuon->get_Rpc1time();
	Rpc1DCA = sngmuon->get_Rpc1DCA();
      }
      if (run13pp510){
	Rpc3DCA = rpcsngmuon->get_Rpc3St3DCA();
	Rpc1DCA = rpcsngmuon->get_Rpc1St1DCA();
      }


      //
      //--- basic event and track selections ---
      //

      if (fabs(pZ)  < 3.0 or fabs(pZ) > 500) continue;

      if (pT < 1 || pT > 100) continue;

      if (fabs(DG0) > 10.0) continue; 
      if (fabs(DDG0) > 10.0) continue; 

      if (fabs(ntrhits) < 10.0) continue; 
      if (fabs(nidhits) < 6.0) continue; 

      if (fabs(trchi2) > 10.0) continue; 
      if (fabs(idchi2) > 5.0) continue; 

      if (fabs(dca_z) > 100.0) continue;   // not cut 
      if (fabs(dca_r) > 5.0) continue; 

      if (fabs(dphi_fvtx) > 20.0) continue;   // D= -99
      if (fabs(dtheta_fvtx) > 20.0) continue; // D= -99
      if (fabs(dr_fvtx) > 20.0) continue;     // D= -99


      // --- RPC timing cut --- effectively seltected "deep muons" ------ 1H and 1D are different 
      //      if (fabs(Rpc3DCA) > 50.0 && fabs(Rpc1DCA) > 10.0 ) continue;   // D = -9999


      //
      // using the 1st absorber multiple-scattrering to reject fake soft "high pT" tracks
      //


      // determine the primary vtx as the one closest to the Evt_bbcZ (or better muon track candidate)
      // at least one of them are close to the muon track z
      if (fabs(Evt_fvtxZ - Evt_bbcZ) > 100 && fabs(Evt_fvtxZ2 - Evt_bbcZ) > 100) continue ; 


      //select the primary vtx with FVTX, need to use "muon's DCA or Chi2 fit"
      if (fabs(Evt_fvtxZ - Evt_bbcZ) < fabs(Evt_fvtxZ2 - Evt_bbcZ) ){
	Evt_X0 = Evt_fvtxX;
	Evt_Y0 = Evt_fvtxY;
	Evt_Z0 = Evt_fvtxZ;
      }
      if (fabs(Evt_fvtxZ - Evt_bbcZ) > fabs(Evt_fvtxZ2 - Evt_bbcZ) ){
	Evt_X0 = Evt_fvtxX2;
	Evt_Y0 = Evt_fvtxY2;
	Evt_Z0 = Evt_fvtxZ2;
      }

      //calcualte VTX-ST1: dTheta and dPhi; need th eprimary vtx infor

      double v1  = (X1 - Evt_X0)*pX1 + (Y1 - Evt_Y0)*pY1 + (Z1 - Evt_Z0)*pZ1;
      double v2a = sqrt( (X1 - Evt_X0)*(X1 - Evt_X0)  + (Y1 - Evt_Y0)*(Y1 - Evt_Y0) + (Z1 - Evt_Z0)*(Z1 - Evt_Z0) );
      double v2b = sqrt( pX1*pX1 + pY1*pY1 + pZ1*pZ1 );

      dA01 = pZ*acos(v1/v2a/v2b)*sqrt(pTot/abs(pZ));     // singed according to arms 
      if (fabs(dA01)>0.5) continue ;


      //calcualte VTX-ST1-ST3: dTheta and dPhi

      // -- comparision ---
      double dw23 = sin(phi_23)*pT*(pT/pTot) ;


      //
      // this is an event used to fill the histogram
      // 
      flag->flags[imuon] = 1;   

      //
      //--- end of event and track selections ---
      //


      fill_ok = true;   // output this event for later analysis 

      //
      //---- fill general event and track properties ---
      //

      _h_dA->Fill(ep, dA01);

      _h2_dA->Fill(ep, pZ, fabs(dA01) );

      if (pZ > 0) {
	_h_Rpc1DCA_N->Fill(ep,Rpc1DCA);
	_h_Rpc3DCA_N->Fill(ep,Rpc3DCA);
      }
      else {
	_h_Rpc1DCA_S->Fill(ep, Rpc1DCA);
	_h_Rpc3DCA_S->Fill(ep, Rpc3DCA);
      }

      // MuTr phi angles 
      if (pZ > 0) {
	_h_phi_1N->Fill(ep,phi_1);
	_h_phi_2N->Fill(ep,phi_2);
	_h_phi_3N->Fill(ep,phi_3);

	_h_phi_13N->Fill(ep,phi_13);
	_h_phi_23N->Fill(ep,phi_23);

	_h2_phi_13N->Fill(ep,pZ,fabs(pZ)*phi_13);
	_h2_phi_23N->Fill(ep,pZ,fabs(pZ)*phi_23);

	_h_ST1Z_N->Fill(ep,Z1);

      }
      else if (pZ < 0){
	_h_phi_1S->Fill(ep,phi_1);
	_h_phi_2S->Fill(ep,phi_2);
	_h_phi_3S->Fill(ep,phi_3);

	_h_phi_13S->Fill(ep,phi_13);
	_h_phi_23S->Fill(ep,phi_23);

	_h2_phi_13S->Fill(ep,pZ,fabs(pZ)*phi_13);
	_h2_phi_23S->Fill(ep,pZ,fabs(pZ)*phi_23);

	_h_ST1Z_S->Fill(ep,Z1);

      }

      //
      //  --- now for spin asymmetry stuff ---
      //

      //
      // --- deep muon pT dependent asymetry  ----
      //

      if ( (fabs(Rpc3DCA) < 50.0 || fabs(Rpc1DCA) < 10.0) && lastGap > 3 ) {   // D = -9999

	// all sngmuons Q(+,-)      
	_h_pT->Fill(ep, pT);
	
	if (arm ==1){      // north
	  _h_pT_n->Fill(ep, pT);
	}
	if (arm ==0){      // south
	  _h_pT_s->Fill(ep, pT);
	}
	
	// sngmuons Q(+)
	if (charge >0 and arm ==1){      // north
	  _h_pT_p->Fill(ep, pT);
	  _h_pT_p_n->Fill(ep, pT);
	}
	if (charge <0 and arm ==0){      // south
	  _h_pT_m->Fill(ep, pT);
	  _h_pT_m_s->Fill(ep, pT);
	}
	// sngmuons Q(-)
	if (charge >0 and arm ==1){      // north
	  _h_pT_p->Fill(ep, pT);
	  _h_pT_p_n->Fill(ep, pT);
	}
	if (charge <0 and arm ==0){      // south
	  _h_pT_m->Fill(ep, pT);
	  _h_pT_m_s->Fill(ep, pT);
	}
	
      } //  --- en dof deep muon + RPCs


      //
      // --- stopped hadron pT dependent asymetry  ----
      //

      if ( (fabs(Rpc1DCA) < 10.0) && lastGap < 4 ) {   // D = -9999

	// all sngmuons Q(+,-)      
	_h_pTH->Fill(ep, pT);
	
	if (arm ==1){      // north
	  _h_pTH_n->Fill(ep, pT);
	}
	if (arm ==0){      // south
	  _h_pTH_s->Fill(ep, pT);
	}
	
	// sngmuons Q(+)
	if (charge >0 and arm ==1){      // north
	  _h_pTH_p->Fill(ep, pT);
	  _h_pTH_p_n->Fill(ep, pT);
	}
	if (charge <0 and arm ==0){      // south
	  _h_pTH_p->Fill(ep, pT);
	  _h_pTH_p_s->Fill(ep, pT);
	}
	// sngmuons Q(-)
	if (charge <0 and arm ==1){      // north
	  _h_pTH_m->Fill(ep, pT);
	  _h_pTH_m_n->Fill(ep, pT);
	}
	if (charge <0 and arm ==0){      // south
	  _h_pTH_m->Fill(ep, pT);
	  _h_pTH_m_s->Fill(ep, pT);
	}
     
      } // --- end of hadron selection lastGap < 4 & RPC1 


      //
      // -- repidity dependance --- W analysis "deep muon" + RPCs
      //

      // -- hadron background ---
      if ( (fabs(Rpc1DCA) < 10.0) && lastGap < 4 ) {   // D = -9999

	// sngmuons stopped hadrons -> mu +/-
	if (charge >0 and lastGap < 4){     
	  _h_etaH->Fill(ep, eta);
	  _h_etaH_p->Fill(ep, eta);
	}
	if (charge < 0 and lastGap < 4 ){
	  _h_etaH->Fill(ep, eta);
	  _h_etaH_m->Fill(ep, eta);
	}
      }  // -- hadrons -- 


      // -- deep muons ---
      if ( (fabs(Rpc3DCA) < 50.0 || fabs(Rpc1DCA) < 10.0) && lastGap > 3 ) {   // D = -9999
      
	// sngmuons heavy -> mu +/-
	if (charge >0 and lastGap > 3){     
	  _h_eta->Fill(ep, eta);
	  _h_eta_p->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_p->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_p->Fill(ep, dw23);
	  } //

	}
	if (charge < 0 and lastGap >3 ){
	  _h_eta->Fill(ep, eta);
	  _h_eta_m->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_m->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_m->Fill(ep, dw23);
	  } //

	}

	// sngmuons W -> mu +/-, pT>10
	if (charge >0 and lastGap >3 and pT > 10){            // W->mu+
	  _h_etaW10->Fill(ep, eta);
	  _h_etaW10_p->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_PT10_p->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_PT10_p->Fill(ep, dw23);
	  } //

	}

	if  (charge <0 and lastGap >3 and pT > 10){      // W->mu-
	  _h_etaW10->Fill(ep, eta);
	  _h_etaW10_m->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_PT10_m->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_PT10_m->Fill(ep, dw23);
	  } //

	}

	
	// sngmuons W -> mu +/-, pT>15
	if (charge >0 and lastGap >3 and pT > 15){            // W->mu+
	  _h_etaW15->Fill(ep, eta);
	  _h_etaW15_p->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_PT15_p->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_PT15_p->Fill(ep, dw23);
	  } //

	}
	if  (charge <0 and lastGap >3 and pT > 15){      // W->mu-
	  _h_etaW15->Fill(ep, eta);
	  _h_etaW15_m->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_PT15_m->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_PT15_m->Fill(ep, dw23);
	  } //

	}


	// sngmuons W -> mu +/-, pT>20
	if (charge >0 and lastGap >3 and pT > 20){            // W->mu+
	  _h_etaW20->Fill(ep, eta);
	  _h_etaW20_p->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_PT20_p->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_PT20_p->Fill(ep, dw23);
	  } //

	}
	if  (charge <0 and lastGap >3 and pT > 20){      // W->mu-
	  _h_etaW20->Fill(ep, eta);
	  _h_etaW20_m->Fill(ep, eta);

	  if (pZ > 0) {
	    _h_dw23N_PT20_m->Fill(ep, dw23);
	  }
	  else if (pZ < 0) {
	    _h_dw23S_PT20_m->Fill(ep, dw23);
	  } //

	}

      } // -- end of deep muon + RPCs 
      
      //      fill_ok = true;

    }

  return fill_ok? EVENT_OK : DISCARDEVENT;
}
//! event method
int saModuleSingleMuonAN::event(PHCompositeNode *topNode, sa_hist_mangager_ptr hm)
{
	SingleMuonContainer* sngmuons = findNode::getClass<SingleMuonContainer>(topNode,
			"SingleMuonContainer");
	if (!sngmuons)
	{
		cout << "saModuleSingleMuonAN:: SingleMuonContainer - ERROR - not in Node Tree"
			<< endl;
		return ABORTRUN;
	}

	const saEventProperty * ep = findNode::getClass<saEventProperty>(topNode,
			"saEventProperty");
	if (!ep)
	{
		cout << "saModuleSingleMuonAN::event - ERROR  - Cannot find EventProperty node in Top Node"
			<< endl;
		return ABORTRUN;
	}

	if (Verbosity() >= 2)
	{
		cout << "saModuleSingleMuonAN::event - INFO  - ";
		ep->identify();
	}

	saFlagC *flag = findNode::getClass<saFlagC>(topNode, "SinglemuonFlag");
	if (!flag)
	{
		cout << "saModuleSingleMuonAN::event - SinglemuonFlag not in Node Tree"
			<< endl;
		return ABORTRUN;
	}

	TrigLvl1* triglv1 = findNode::getClass<TrigLvl1>(topNode,
			"TrigLvl1");
	if (!triglv1)
	{
		cout << "saModuleSingleMuonAN:: TrigLvl1 - ERROR - not in Node Tree"
			<< endl;
		return ABORTRUN;
	}

	// syncronizely set the cut flag with singlemuon container
	flag->flags.Set(sngmuons->get_nSingleMuons());
	flag->flags.Reset(0);

	// save the event for DST files?
	// int return_code = sngmuons->get_nSingleMuons() >0 ? EVENT_OK : DISCARDEVENT;

	bool fill_ok = false;   // save the event for DST output 

	if(_use_bbc_cut) if(!(TMath::Abs(sngmuons->get_Evt_bbcZ())<30.)) return DISCARDEVENT;

	for (unsigned int imuon = 0; imuon < sngmuons->get_nSingleMuons(); imuon++)
	{
		SingleMuon* singlemuon = sngmuons->get_SingleMuon(imuon);

		if(!pass_sngmuon_cut(singlemuon)) continue;

		enum EVENT_TYPE type = BAD_EVENT;

		int last_gap = singlemuon->get_lastgap();

		enum ARM_TYPE arm;
		arm = (singlemuon->get_rapidity() > 0) ? NORTH : SOUTH;

		if (singlemuon->get_charge() == 0
                                && arm==NORTH
                                && last_gap==4
                         )
                        type = MuM_N_LG4;

                if (singlemuon->get_charge() == 0
                                && arm==NORTH
                                && (last_gap==2 || last_gap==3)
                         )
                        type = MuM_N_LG23;

		if (singlemuon->get_charge() == 0
				&& arm==SOUTH
				&& last_gap==4
			 )
			type = MuM_S_LG4;

                if (singlemuon->get_charge() == 0
                                && arm==SOUTH
                                && (last_gap==2 || last_gap==3)
                         )
                        type = MuM_S_LG23;

		if(verbosity>1)
		{
			cout
				<<" pT: "<<singlemuon->get_pT()
				<<" type: "<<type
				<<endl;
		}

		// this is an event used to fill the histogram 
		flag->flags[imuon] = 1;   

		float py = singlemuon->get_py();
		float px = singlemuon->get_px();
		double phi = TMath::ATan(py/px)+(px<0&&py>0)*TMath::Pi()-(px<0&&py<0)*TMath::Pi();


		if(type==MuM_N_LG4)  _sah_pT_phi_MuM_phi_N_LG4->Fill( ep,singlemuon->get_pT(),phi);
		if(type==MuM_N_LG23) _sah_pT_phi_MuM_phi_N_LG23->Fill(ep,singlemuon->get_pT(),phi);
		if(type==MuM_S_LG4)  _sah_pT_phi_MuM_phi_S_LG4->Fill( ep,singlemuon->get_pT(),phi);
		if(type==MuM_S_LG23) _sah_pT_phi_MuM_phi_S_LG23->Fill(ep,singlemuon->get_pT(),phi);


		if(_doControlData
				&&singlemuon->get_pT()>0.&&singlemuon->get_pT()<2.
				//&&ep->get_spin_state()==0
				&&(
					type==MuM_N_LG4
					//|| type==OS_SIG_S
					)
			)
		{
			fout
				//<<setw(15)<<" run num: "<<setw(10)<<ep->get_run_number()
				//<<setw(15)<<" event num: "<<setw(10)<<ep->get_event_number()
				//<<setw(15)<<" FillCounter: "<<setw(10)<<_FillCounter++
				//<<setw(15)<<" XingPHENIX: "<<setw(4)<<ep->get_crossing_id()
				//<<setw(15)<<" spin stats: "<<setw(3)<<ep->get_spin_state()
				<<setw(15)<<" beamclk0: "<<setw(10)<<triglv1->get_lvl1_beam_clk(0)
				//<<setw(15)<<" beamclk1: "<<setw(10)<<triglv1->get_lvl1_beam_clk(1)
				//<<setw(15)<<" Tr0_idhits: "<<setw(10)<<singlemuon->get_Tr0_idhits()
				//<<setw(15)<<" Tr1_idhits: "<<setw(10)<<singlemuon->get_Tr1_idhits()
				<<endl;

		}

		fill_ok = true;
	}

	return fill_ok? EVENT_OK : DISCARDEVENT;
}