vector <TString> OnlineConfig::SplitString(TString instring,TString delim) { // Utility to split up a string on the deliminator. // returns a vector of strings. vector <TString> v; TString remainingString = instring; TString tempstring = instring; int i; while (remainingString.Index(delim) != -1) { i = remainingString.Index(delim); tempstring.Remove(i); v.push_back(tempstring); remainingString.Remove(0,i+1); while(remainingString.Index(delim) == 0) { remainingString.Remove(0,1); } tempstring = remainingString; } while(tempstring.EndsWith(delim)) { tempstring.Chop(); } if(!tempstring.IsNull()) v.push_back(tempstring); return v; }
TString OnlineConfig::GetPageTitle(UInt_t page) { // Returns the title of the page. // if it is not defined in the config, then return "Page #" TString title; UInt_t iter_command = pageInfo[page].first+1; for(UInt_t i=0; i<pageInfo[page].second; i++) { // go through each command if(sConfFile[iter_command+i][0] == "title") { // Combine the strings, and return it for (UInt_t j=1; j<sConfFile[iter_command+i].size(); j++) { title += sConfFile[iter_command+i][j]; title += " "; } title.Chop(); return title; } } title = "Page "; title += page; return title; }
//_____________________________________________________________________________ Int_t THaVDC::ReadDatabase( const TDatime& date ) { // Read VDC database FILE* file = OpenFile( date ); if( !file ) return kFileError; // load global VDC parameters static const char* const here = "ReadDatabase"; const int LEN = 200; char buff[LEN]; // Look for the section [<prefix>.global] in the file, e.g. [ R.global ] TString tag(fPrefix); Ssiz_t pos = tag.Index("."); if( pos != kNPOS ) tag = tag(0,pos+1); else tag.Append("."); tag.Prepend("["); tag.Append("global]"); TString line; bool found = false; while (!found && fgets (buff, LEN, file) != NULL) { char* buf = ::Compress(buff); //strip blanks line = buf; delete [] buf; if( line.EndsWith("\n") ) line.Chop(); if ( tag == line ) found = true; } if( !found ) { Error(Here(here), "Database section %s not found!", tag.Data() ); fclose(file); return kInitError; } // We found the section, now read the data // read in some basic constants first // fscanf(file, "%lf", &fSpacing); // fSpacing is now calculated from the actual z-positions in Init(), // so skip the first line after [ global ] completely: fgets(buff, LEN, file); // Skip rest of line // Read in the focal plane transfer elements // For fine-tuning of these data, we seek to a matching time stamp, or // if no time stamp found, to a "configuration" section. Examples: // // [ 2002-10-10 15:30:00 ] // comment line goes here // t 0 0 0 ... // y 0 0 0 ... etc. // // or // // [ config=highmom ] // comment line // t 0 0 0 ... etc. // if( (found = SeekDBdate( file, date )) == 0 && !fConfig.IsNull() && (found = SeekDBconfig( file, fConfig.Data() )) == 0 ) { // Print warning if a requested (non-empty) config not found Warning( Here(here), "Requested configuration section \"%s\" not " "found in database. Using default (first) section.", fConfig.Data() ); } // Second line after [ global ] or first line after a found tag. // After a found tag, it must be the comment line. If not found, then it // can be either the comment or a non-found tag before the comment... fgets(buff, LEN, file); // Skip line if( !found && IsTag(buff) ) // Skip one more line if this one was a non-found tag fgets(buff, LEN, file); fTMatrixElems.clear(); fDMatrixElems.clear(); fPMatrixElems.clear(); fPTAMatrixElems.clear(); fYMatrixElems.clear(); fYTAMatrixElems.clear(); fLMatrixElems.clear(); fFPMatrixElems.clear(); fFPMatrixElems.resize(3); typedef vector<string>::size_type vsiz_t; map<string,vsiz_t> power; power["t"] = 3; // transport to focal-plane tensors power["y"] = 3; power["p"] = 3; power["D"] = 3; // focal-plane to target tensors power["T"] = 3; power["Y"] = 3; power["YTA"] = 4; power["P"] = 3; power["PTA"] = 4; power["L"] = 4; // pathlength from z=0 (target) to focal plane (meters) power["XF"] = 5; // forward: target to focal-plane (I think) power["TF"] = 5; power["PF"] = 5; power["YF"] = 5; map<string,vector<THaMatrixElement>*> matrix_map; matrix_map["t"] = &fFPMatrixElems; matrix_map["y"] = &fFPMatrixElems; matrix_map["p"] = &fFPMatrixElems; matrix_map["D"] = &fDMatrixElems; matrix_map["T"] = &fTMatrixElems; matrix_map["Y"] = &fYMatrixElems; matrix_map["YTA"] = &fYTAMatrixElems; matrix_map["P"] = &fPMatrixElems; matrix_map["PTA"] = &fPTAMatrixElems; matrix_map["L"] = &fLMatrixElems; map <string,int> fp_map; fp_map["t"] = 0; fp_map["y"] = 1; fp_map["p"] = 2; // Read in as many of the matrix elements as there are. // Read in line-by-line, so as to be able to handle tensors of // different orders. while( fgets(buff, LEN, file) ) { string line(buff); // Erase trailing newline if( line.size() > 0 && line[line.size()-1] == '\n' ) { buff[line.size()-1] = 0; line.erase(line.size()-1,1); } // Split the line into whitespace-separated fields vector<string> line_spl = Split(line); // Stop if the line does not start with a string referring to // a known type of matrix element. In particular, this will // stop on a subsequent timestamp or configuration tag starting with "[" if(line_spl.empty()) continue; //ignore empty lines const char* w = line_spl[0].c_str(); vsiz_t npow = power[w]; if( npow == 0 ) break; // Looks like a good line, go parse it. THaMatrixElement ME; ME.pw.resize(npow); ME.iszero = true; ME.order = 0; vsiz_t pos; for (pos=1; pos<=npow && pos<line_spl.size(); pos++) { ME.pw[pos-1] = atoi(line_spl[pos].c_str()); } vsiz_t p_cnt; for ( p_cnt=0; pos<line_spl.size() && p_cnt<kPORDER && pos<=npow+kPORDER; pos++,p_cnt++ ) { ME.poly[p_cnt] = atof(line_spl[pos].c_str()); if (ME.poly[p_cnt] != 0.0) { ME.iszero = false; ME.order = p_cnt+1; } } if (p_cnt < 1) { Error(Here(here), "Could not read in Matrix Element %s%d%d%d!", w, ME.pw[0], ME.pw[1], ME.pw[2]); Error(Here(here), "Line looks like: %s",line.c_str()); fclose(file); return kInitError; } // Don't bother with all-zero matrix elements if( ME.iszero ) continue; // Add this matrix element to the appropriate array vector<THaMatrixElement> *mat = matrix_map[w]; if (mat) { // Special checks for focal plane matrix elements if( mat == &fFPMatrixElems ) { if( ME.pw[0] == 0 && ME.pw[1] == 0 && ME.pw[2] == 0 ) { THaMatrixElement& m = (*mat)[fp_map[w]]; if( m.order > 0 ) { Warning(Here(here), "Duplicate definition of focal plane " "matrix element: %s. Using first definition.", buff); } else m = ME; } else Warning(Here(here), "Bad coefficients of focal plane matrix " "element %s", buff); } else { // All other matrix elements are just appended to the respective array // but ensure that they are defined only once! bool match = false; for( vector<THaMatrixElement>::iterator it = mat->begin(); it != mat->end() && !(match = it->match(ME)); it++ ) {} if( match ) { Warning(Here(here), "Duplicate definition of " "matrix element: %s. Using first definition.", buff); } else mat->push_back(ME); } } else if ( fDebug > 0 ) Warning(Here(here), "Not storing matrix for: %s !", w); } //while(fgets) // Compute derived quantities and set some hardcoded parameters const Double_t degrad = TMath::Pi()/180.0; fTan_vdc = fFPMatrixElems[T000].poly[0]; fVDCAngle = TMath::ATan(fTan_vdc); fSin_vdc = TMath::Sin(fVDCAngle); fCos_vdc = TMath::Cos(fVDCAngle); // Define the VDC coordinate axes in the "detector system". By definition, // the detector system is identical to the VDC origin in the Hall A HRS. DefineAxes(0.0*degrad); fNumIter = 1; // Number of iterations for FineTrack() fErrorCutoff = 1e100; // figure out the track length from the origin to the s1 plane // since we take the VDC to be the origin of the coordinate // space, this is actually pretty simple const THaDetector* s1 = 0; if( GetApparatus() ) s1 = GetApparatus()->GetDetector("s1"); if(s1 == NULL) fCentralDist = 0; else fCentralDist = s1->GetOrigin().Z(); CalcMatrix(1.,fLMatrixElems); // tensor without explicit polynomial in x_fp // FIXME: Set geometry data (fOrigin). Currently fOrigin = (0,0,0). fIsInit = true; fclose(file); return kOK; }
//_____________________________________________________________________________ Int_t THaVDCPlane::ReadDatabase( const TDatime& date ) { // Allocate TClonesArray objects and load plane parameters from database FILE* file = OpenFile( date ); if( !file ) return kFileError; // Use default values until ready to read from database static const char* const here = "ReadDatabase"; const int LEN = 100; char buff[LEN]; // Build the search tag and find it in the file. Search tags // are of form [ <prefix> ], e.g. [ R.vdc.u1 ]. TString tag(fPrefix); tag.Chop(); // delete trailing dot of prefix tag.Prepend("["); tag.Append("]"); TString line; bool found = false; while (!found && fgets (buff, LEN, file) != NULL) { char* buf = ::Compress(buff); //strip blanks line = buf; delete [] buf; if( line.EndsWith("\n") ) line.Chop(); //delete trailing newline if ( tag == line ) found = true; } if( !found ) { Error(Here(here), "Database section \"%s\" not found! " "Initialization failed", tag.Data() ); fclose(file); return kInitError; } //Found the entry for this plane, so read data Int_t nWires = 0; // Number of wires to create Int_t prev_first = 0, prev_nwires = 0; // Set up the detector map fDetMap->Clear(); do { fgets( buff, LEN, file ); // bad kludge to allow a variable number of detector map lines if( strchr(buff, '.') ) // any floating point number indicates end of map break; // Get crate, slot, low channel and high channel from file Int_t crate, slot, lo, hi; if( sscanf( buff, "%6d %6d %6d %6d", &crate, &slot, &lo, &hi ) != 4 ) { if( *buff ) buff[strlen(buff)-1] = 0; //delete trailing newline Error( Here(here), "Error reading detector map line: %s", buff ); fclose(file); return kInitError; } Int_t first = prev_first + prev_nwires; // Add module to the detector map fDetMap->AddModule(crate, slot, lo, hi, first); prev_first = first; prev_nwires = (hi - lo + 1); nWires += prev_nwires; } while( *buff ); // sanity escape // Load z, wire beginning postion, wire spacing, and wire angle sscanf( buff, "%15lf %15lf %15lf %15lf", &fZ, &fWBeg, &fWSpac, &fWAngle ); fWAngle *= TMath::Pi()/180.0; // Convert to radians fSinAngle = TMath::Sin( fWAngle ); fCosAngle = TMath::Cos( fWAngle ); // Load drift velocity (will be used to initialize crude Time to Distance // converter) fscanf(file, "%15lf", &fDriftVel); fgets(buff, LEN, file); // Read to end of line fgets(buff, LEN, file); // Skip line // first read in the time offsets for the wires float* wire_offsets = new float[nWires]; int* wire_nums = new int[nWires]; for (int i = 0; i < nWires; i++) { int wnum = 0; float offset = 0.0; fscanf(file, " %6d %15f", &wnum, &offset); wire_nums[i] = wnum-1; // Wire numbers in file start at 1 wire_offsets[i] = offset; } // now read in the time-to-drift-distance lookup table // data (if it exists) // fgets(buff, LEN, file); // read to the end of line // fgets(buff, LEN, file); // if(strncmp(buff, "TTD Lookup Table", 16) == 0) { // // if it exists, read the data in // fscanf(file, "%le", &fT0); // fscanf(file, "%d", &fNumBins); // // this object is responsible for the memory management // // of the lookup table // delete [] fTable; // fTable = new Float_t[fNumBins]; // for(int i=0; i<fNumBins; i++) { // fscanf(file, "%e", &(fTable[i])); // } // } else { // // if not, set some reasonable defaults and rewind the file // fT0 = 0.0; // fNumBins = 0; // fTable = NULL; // cout<<"Could not find lookup table header: "<<buff<<endl; // fseek(file, -strlen(buff), SEEK_CUR); // } // Define time-to-drift-distance converter // Currently, we use the analytic converter. // FIXME: Let user choose this via a parameter delete fTTDConv; fTTDConv = new THaVDCAnalyticTTDConv(fDriftVel); //THaVDCLookupTTDConv* ttdConv = new THaVDCLookupTTDConv(fT0, fNumBins, fTable); // Now initialize wires (those wires... too lazy to initialize themselves!) // Caution: This may not correspond at all to actual wire channels! for (int i = 0; i < nWires; i++) { THaVDCWire* wire = new((*fWires)[i]) THaVDCWire( i, fWBeg+i*fWSpac, wire_offsets[i], fTTDConv ); if( wire_nums[i] < 0 ) wire->SetFlag(1); } delete [] wire_offsets; delete [] wire_nums; // Set location of chamber center (in detector coordinates) fOrigin.SetXYZ( 0.0, 0.0, fZ ); // Read additional parameters (not in original database) // For backward compatibility with database version 1, these parameters // are in an optional section, labelled [ <prefix>.extra_param ] // (e.g. [ R.vdc.u1.extra_param ]) or [ R.extra_param ]. If this tag is // not found, a warning is printed and defaults are used. tag = "["; tag.Append(fPrefix); tag.Append("extra_param]"); TString tag2(tag); found = false; rewind(file); while (!found && fgets(buff, LEN, file) != NULL) { char* buf = ::Compress(buff); //strip blanks line = buf; delete [] buf; if( line.EndsWith("\n") ) line.Chop(); //delete trailing newline if ( tag == line ) found = true; } if( !found ) { // Poor man's default key search rewind(file); tag2 = fPrefix; Ssiz_t pos = tag2.Index("."); if( pos != kNPOS ) tag2 = tag2(0,pos+1); else tag2.Append("."); tag2.Prepend("["); tag2.Append("extra_param]"); while (!found && fgets(buff, LEN, file) != NULL) { char* buf = ::Compress(buff); //strip blanks line = buf; delete [] buf; if( line.EndsWith("\n") ) line.Chop(); //delete trailing newline if ( tag2 == line ) found = true; } } if( found ) { if( fscanf(file, "%lf %lf", &fTDCRes, &fT0Resolution) != 2) { Error( Here(here), "Error reading TDC scale and T0 resolution\n" "Line = %s\nFix database.", buff ); fclose(file); return kInitError; } fgets(buff, LEN, file); // Read to end of line if( fscanf( file, "%d %d %d %d %d %lf %lf", &fMinClustSize, &fMaxClustSpan, &fNMaxGap, &fMinTime, &fMaxTime, &fMinTdiff, &fMaxTdiff ) != 7 ) { Error( Here(here), "Error reading min_clust_size, max_clust_span, " "max_gap, min_time, max_time, min_tdiff, max_tdiff.\n" "Line = %s\nFix database.", buff ); fclose(file); return kInitError; } fgets(buff, LEN, file); // Read to end of line // Time-to-distance converter parameters if( THaVDCAnalyticTTDConv* analytic_conv = dynamic_cast<THaVDCAnalyticTTDConv*>(fTTDConv) ) { // THaVDCAnalyticTTDConv // Format: 4*A1 4*A2 dtime(s) (9 floats) Double_t A1[4], A2[4], dtime; if( fscanf(file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf", &A1[0], &A1[1], &A1[2], &A1[3], &A2[0], &A2[1], &A2[2], &A2[3], &dtime ) != 9) { Error( Here(here), "Error reading THaVDCAnalyticTTDConv parameters\n" "Line = %s\nExpect 9 floating point numbers. Fix database.", buff ); fclose(file); return kInitError; } else { analytic_conv->SetParameters( A1, A2, dtime ); } } // else if( (... *conv = dynamic_cast<...*>(fTTDConv)) ) { // // handle parameters of other TTD converters here // } fgets(buff, LEN, file); // Read to end of line Double_t h, w; if( fscanf(file, "%lf %lf", &h, &w) != 2) { Error( Here(here), "Error reading height/width parameters\n" "Line = %s\nExpect 2 floating point numbers. Fix database.", buff ); fclose(file); return kInitError; } else { fSize[0] = h/2.0; fSize[1] = w/2.0; } fgets(buff, LEN, file); // Read to end of line // Sanity checks if( fMinClustSize < 1 || fMinClustSize > 6 ) { Error( Here(here), "Invalid min_clust_size = %d, must be betwwen 1 and " "6. Fix database.", fMinClustSize ); fclose(file); return kInitError; } if( fMaxClustSpan < 2 || fMaxClustSpan > 12 ) { Error( Here(here), "Invalid max_clust_span = %d, must be betwwen 1 and " "12. Fix database.", fMaxClustSpan ); fclose(file); return kInitError; } if( fNMaxGap < 0 || fNMaxGap > 2 ) { Error( Here(here), "Invalid max_gap = %d, must be betwwen 0 and 2. " "Fix database.", fNMaxGap ); fclose(file); return kInitError; } if( fMinTime < 0 || fMinTime > 4095 ) { Error( Here(here), "Invalid min_time = %d, must be betwwen 0 and 4095. " "Fix database.", fMinTime ); fclose(file); return kInitError; } if( fMaxTime < 1 || fMaxTime > 4096 || fMinTime >= fMaxTime ) { Error( Here(here), "Invalid max_time = %d. Must be between 1 and 4096 " "and >= min_time = %d. Fix database.", fMaxTime, fMinTime ); fclose(file); return kInitError; } } else { Warning( Here(here), "No database section \"%s\" or \"%s\" found. " "Using defaults.", tag.Data(), tag2.Data() ); fTDCRes = 5.0e-10; // 0.5 ns/chan = 5e-10 s /chan fT0Resolution = 6e-8; // 60 ns --- crude guess fMinClustSize = 3; fMaxClustSpan = 7; fNMaxGap = 1; fMinTime = 800; fMaxTime = 2200; fMinTdiff = 3e-8; // 30ns -> ~20 deg track angle //fMaxTdiff = 1.5e-7; // 150ns -> ~60 deg track angle fMaxTdiff = 2.0e-7; // 200ns if( THaVDCAnalyticTTDConv* analytic_conv = dynamic_cast<THaVDCAnalyticTTDConv*>(fTTDConv) ) { Double_t A1[4], A2[4], dtime = 4e-9; A1[0] = 2.12e-3; A1[1] = A1[2] = A1[3] = 0.0; A2[0] = -4.2e-4; A2[1] = 1.3e-3; A2[2] = 1.06e-4; A2[3] = 0.0; analytic_conv->SetParameters( A1, A2, dtime ); } } THaDetectorBase *sdet = GetParent(); if( sdet ) fOrigin += sdet->GetOrigin(); // finally, find the timing-offset to apply on an event-by-event basis //FIXME: time offset handling should go into the enclosing apparatus - //since not doing so leads to exactly this kind of mess: THaApparatus* app = GetApparatus(); const char* nm = "trg"; // inside an apparatus, the apparatus name is assumed if( !app || !(fglTrg = dynamic_cast<THaTriggerTime*>(app->GetDetector(nm))) ) { Warning(Here(here),"Trigger-time detector \"%s\" not found. " "Event-by-event time offsets will NOT be used!!",nm); } fIsInit = true; fclose(file); return kOK; }