Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

BDTarget.cxx

Go to the documentation of this file.
00001 #include "BDTarget.h"
00002 #include "BDProfMon.h"
00003 
00004 #include <Conventions/Munits.h>
00005 #include <RawData/RawBeamMonBlock.h>
00006 #include <RawData/RawBeamData.h>
00007 
00008 #include <MessageService/MsgService.h>
00009 CVSID("$Id: BDTarget.cxx,v 1.17 2007/01/26 22:06:11 mdier Exp $");
00010 
00011 
00012 #include <cmath>
00013 #include <string>
00014 #include <cmath>
00015 using namespace std;
00016 
00017 BDTarget::BDTarget()
00018     : BDProcessor()
00019 {
00020     for (int ind=0; ind<4; ++ind) fBpms[ind] = 0;
00021     for (int ind=0; ind<2; ++ind) fPMs[ind] = 0;
00022     for (int ind=0; ind<3; ++ind) fTgt[ind] = 0;
00023 }
00024 
00025 BDTarget::~BDTarget()
00026 {
00027 }
00028 
00029 static bool check_data(const RawBeamData* const* d, int n)
00030 {
00031     for (int ind=0; ind<n; ++ind) {
00032         if (0 == d[ind]) return false;
00033         if (0 == d[ind]->GetDataLength()) return false;
00034     }
00035     return true;
00036 }
00037 
00038 static double get_dae_time(const RawBeamData* const* d, int n)
00039 {
00040 // Get the time from one of the devices
00041     double devtime =0;
00042     for (int idev=0; idev<n; ++idev){
00043         if (devtime==0) devtime = d[idev]->GetSeconds();
00044     }
00045     return devtime;
00046 }
00047 
00048 void BDTarget::SetSpill(const RawBeamMonHeaderBlock& /*rbmhb*/,
00049                         const RawBeamMonBlock& rbmb)
00050 {
00051 
00052     // Order matters!
00053     const char* bpms[] = { "E:VP121", "E:HP121", "E:VPTGT", "E:HPTGT",
00054                            "E:VITGT", "E:HITGT", 0 };
00055     for (int ind=0; bpms[ind]; ++ind) {
00056         fBpms[ind] = rbmb[bpms[ind]];
00057         if (!fBpms[ind])
00058             MSG("BDU",Msg::kDebug) << "BPM \"" << bpms[ind] << "\" not found\n";
00059     }
00060     
00061     const char* pms[] = { "E:M121DS", "E:MTGTDS", 0 };
00062     for (int ind=0; pms[ind]; ++ind) fPMs[ind] = rbmb[pms[ind]];
00063     if (check_data(fPMs,2)) {
00064         fPM121.SetData(*fPMs[0]);
00065         fPMTGT.SetData(*fPMs[1]);
00066     }
00067     
00068     const char* tgt[] = { "I:NUTARZ", "I:NUTGUV", "I:NUTGDV", 0 };
00069     for (int ind=0; tgt[ind]; ++ind) fTgt[ind] = rbmb[tgt[ind]];
00070 }
00071 
00072 // Extrapolate from point 1 to 2 to point 3.  Returns the transverse
00073 // position at point 3 given longitudinal one.
00074 static double extrapolate_position(double t1, double z1, double t2, double z2, double z3)
00075 {
00076     return t1+(t2-t1)*(z3-z1)/(z2-z1);
00077 }
00078 
00079 /* From Jim Hylen
00080 
00081 Pseudo-ME target location is now defined as 100 cm upstream
00082 of standard target LE location.
00083 The beginning of the 95.2 cm long vertical fin target is
00084 38 cm upstream of ACTRN1 for LE and
00085 138 cm upstream of ACTRN1 for Semi-ME.
00086 There will be small adjustments to this from the final
00087 survey data.
00088 
00089 */
00090 
00091 /* Plus beam sheet:
00092    http://www-numi.fnal.gov/numwork/tdh/TDH_V2_4.1_Appendix_C.txt
00093 */
00094 
00095 static const double
00096     z_hp121 =    -72.2309*Munits::foot, // HP121
00097     z_vp121 =    -71.3142*Munits::foot, // VP121
00098     z_pm121 =    -70.5267*Munits::foot, // PM121
00099     z_hptgt =    -33.1564*Munits::foot, // HPTGT
00100     z_vptgt =    -32.2397*Munits::foot, // VPTGT
00101     z_pmtgt =    -31.5980*Munits::foot, // PMTGT
00102     z_target_le = 0.0*Munits::foot, // LE location
00103     actrn1  =     1.2467192*Munits::foot; // ACTRN1
00104 
00105 
00106 
00107 int BDTarget::GetNbatches() const
00108 {
00109     // return the shortest physical array length of all BPM positions
00110     // and intensities used.
00111     int n = fBpms[0]->GetDataLength();
00112     for (int ind=1; ind<6; ++ind) {
00113         int n2 = fBpms[ind]->GetDataLength();
00114         if (n2<n) n=n2;
00115     }
00116     return n;
00117 }
00118 
00119 
00120 void BDTarget::BpmProjection(vector<double> &xp, vector<double> &yp,
00121                              vector<double> &xi, vector<double> &yi) const
00122 {
00123     xp.clear();
00124     yp.clear();
00125     xi.clear();
00126     yi.clear();
00127 
00128     if (!check_data(fBpms,6)) return;
00129     
00130     double devtime = get_dae_time(fBpms,6);
00131     double z_targ=0;
00132     bool is_in = false;
00133     if (! this->TargetIn(is_in,z_targ,devtime) || !is_in) return;
00134 
00135     // find smallest number of batches (should all be same)
00136     int n = this->GetNbatches();
00137 
00138     int start=0;
00139     if (n>1) ++start; // skip average but only if multiple batches
00140 
00141     for (int ind=start; ind<n; ++ind) {
00142 
00143         if (fBpms[4]->GetData()[ind] == 0 || fBpms[5]->GetData()[ind] == 0) {
00144             yp.push_back(0.0);
00145             xp.push_back(0.0);
00146             yi.push_back(0.0);
00147             xi.push_back(0.0);
00148             continue;
00149         }
00150 
00151         yp.push_back
00152             (extrapolate_position(fBpms[0]->GetData()[ind]*Munits::mm,z_vp121,
00153                                   fBpms[2]->GetData()[ind]*Munits::mm,z_vptgt,
00154                                   z_targ));
00155         xp.push_back
00156             (extrapolate_position(fBpms[1]->GetData()[ind]*Munits::mm,z_hp121,
00157                                   fBpms[3]->GetData()[ind]*Munits::mm,z_hptgt,
00158                                   z_targ));
00159         yi.push_back(fBpms[4]->GetData()[ind]);
00160         xi.push_back(fBpms[5]->GetData()[ind]);
00161     }
00162     return;
00163 }
00164 
00165 int BDTarget::ProfileProjection(double &x, double &y, double &xrms, double &yrms) const
00166 {
00167     if (!check_data(fPMs,2)) return 0;    
00168 
00169     double devtime = get_dae_time(fPMs,2);
00170 
00171     double z_targ=0;
00172     bool is_in = false;
00173     if (! this->TargetIn(is_in,z_targ,devtime) || !is_in) return 0;
00174 
00175     double x121=-999,y121=-999,xrms121=-999,yrms121=-999;
00176     //    fPM121.GetStats(x121,y121,xrms121,yrms121);
00177     fPM121.GetGaussFit(x121,y121,xrms121,yrms121);
00178     
00179     double xtgt=0,ytgt=0,xrmstgt=0,yrmstgt=0;
00180     //    fPMTGT.GetStats(xtgt,ytgt,xrmstgt,yrmstgt);
00181     fPMTGT.GetGaussFit(xtgt,ytgt,xrmstgt,yrmstgt);
00182 
00183     if (fabs(x121) < 11*Munits::mm &&
00184         fabs(xtgt) < 11*Munits::mm &&
00185         fabs(y121) < 11*Munits::mm &&
00186         fabs(ytgt) < 11*Munits::mm) {
00187       x = extrapolate_position(x121,z_pm121,xtgt,z_pmtgt,z_targ);
00188       y = extrapolate_position(y121,z_pm121,ytgt,z_pmtgt,z_targ);
00189     }
00190     
00191     xrms = xrmstgt;
00192     yrms = yrmstgt;
00193 
00194     return 1;
00195 }
00196 
00197 BDTarget::BeamType BDTarget::TargetIn(bool& is_in, double& location, double spilltime) const
00198 {        
00199         /* From Jim Hylen
00200 
00201         Look at I:NUTGUV and I:NUTGDV
00202         If they are around 1531 and 1441, target is "in"
00203         If they are between 8800 and 8900, target is "out"
00204         Unit is .001"
00205     
00206         For I:NUTARZ, LE ~ 0, Semi-ME ~ 39373, Semi-HE ~98408
00207         Calibration appears to have been drifting by a few
00208         tenths of a percent.
00209         */
00210 
00211         // note on units: mils are used here implicitly as this is what
00212         // the raw data is in.  location is returned in Munits
00213 
00214     is_in = false;
00215     location = -9999/Munits::mil;
00216 
00217     if (spilltime==0){
00218         // use the device readout to determine the target position
00219         if (!check_data(fTgt,3)) return kUnknown;
00220         location = fTgt[0]->GetData()[0];
00221         double up = fTgt[1]->GetData()[0];
00222         double down = fTgt[2]->GetData()[0];
00223         
00224         // Check insert.
00225         if (up < 2000 && down < 2000) is_in = true;
00226         
00227     }
00228     else {
00229         // use the measured average over a period of time in order to
00230         // avoid throwing away spills where the target was actually in
00231         // but the device failed to read out 
00232 
00233         // default assume target is in
00234         is_in = true;
00235         // target positions        
00236         // FIXME: this is hardcoded for the time being, it would be
00237         // good if this goes into a database
00238         if (spilltime <= 1109540100) location = 39465;      // 100 cm
00239         else if (spilltime <= 1109899600) location = 98070; // 250 cm
00240         else if (spilltime <= 1110280000) location = 39465; // 100 cm
00241         else if (spilltime <= 1112010000) location = 815.4; //   0 cm
00242         else if (spilltime <= 1112574300) location = 39350; // 100 cm
00243         else if (spilltime <= 1114040000) is_in = false;
00244         else if (spilltime <= 1114062000) location = 39372; // 100 cm
00245         else if (spilltime <= 1114640000) is_in = false;
00246         else if (spilltime <= 1115935000) location = 39363; // 100 cm
00247         else if (spilltime <= 1116615000) location = 98578; // 250 cm
00248         else if (spilltime <= 1149202720) location = 3935;  // 10 cm
00249         else if (spilltime <= 1150047812) location = 57313; // 150 cm
00250         else if (spilltime <= 1155564632) location = 96227; // 250 cm
00251         else location = 3937;                               // 10 cm
00252     }
00253     
00254     location *= Munits::mil;
00255     BeamType bt = kUnknown;
00256     const float dist_cut = 0.35*Munits::meter;
00257     const float le_pos   = 0.0*Munits::meter;
00258     const float pme_pos  = 1.25*Munits::meter;
00259     const float phe_pos  = 2.5*Munits::meter;
00260     if (fabs(location-le_pos) < dist_cut)       bt = kLE;
00261     else if (fabs(location-pme_pos) < dist_cut) bt = kPsME;
00262     else if (fabs(location-phe_pos) < dist_cut) bt = kPsHE;
00263     else bt = kUnknown;
00264 
00265     return bt;
00266     }

Generated on Sat Nov 21 22:45:30 2009 for loon by  doxygen 1.3.9.1