Dear Canguo,
> Can ROOT read card files (like FFREAD)?
> I guess the answer should be yes. Can anybody refer me to the relevant
> section of the ROOT manuals?
> My plan is to read in things like detector parameters from
> free-formatted files into arrays in my ROOT application, and then in my
> program assign these parameters to some objects(e.g., material class
> predefined by ROOT). I think this should work. However, I wonder if there's
> a better or more efficient way to achieve this purpose.
Below is the example of ROOT class with function that produce FFREAD keys.
Notes:
1. All FFREAD keys must be data members of a ROOT class.
2. Data memebers of class Parameter may be
Float_t (for REAL) or (U)Int_t (for INTEGER).
3. One-dimension arrays are supported.
4. The first symbol of data memeber name will removed. (Removing leading
'f','g' or 'k' symbols.)
------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////
// Example of GEANT UGINIT subroutine.
const int FFREAD_SIZE=2000;
float cfread_[FFREAD_SIZE];
void UGINIT(void)
{
GINIT();
FFINIT(FFREAD_SIZE);
FFSET("SIZE",32);
Parameters P;
P.CreateFFREADcards();
GFFGO();
P.Dump();
//....
}
//////////////////////////////////////////////////////////////////////////////
class Parameters : public TObject
{
public:
void CreateFFREADcards (void);
virtual ~Parameters (void) {}
Parameters (void) :// For default values.
fPar (0.01)
{ fDim[0]=0; fDim[1]=1;}
Float_t fPar; // Par Set your name!
Int_t fDim[2]; // Dim Set your name!
private:
ClassDef(Parameters,1) // Parameters
};
//////////////////////////////////////////////////////////////////////////////
void ffkey_( const char *key, void *ptr, const int &Nvar, const char *type,
int,int);
inline void FFKEY(const char *key, void *ptr, int Nvar, const char *type)
{ ffkey_(key,ptr,Nvar,type,strlen(key),strlen(type)); }
void
Parameters::CreateFFREADcards(void)
{
cout << __PRETTY_FUNCTION__ << "\n";
TIter next(Class()->GetListOfDataMembers());
while( TDataMember *obj = (TDataMember*)next() )
{
if( !strcmp("fgIsA",obj->GetName()) ) // Skip this variable
continue;
// cout << obj -> GetName() << "\n"
// << obj -> GetDataType() -> GetTypeName() << "\n"
// << obj -> GetDataType() -> GetFullTypeName() << "\n"
// << obj -> GetOffset() << "\n"
// << obj -> GetArrayDim() << "\n"
// << obj -> GetMaxIndex(0) << "\n"
// << "-----------------------------------------------\n";
cout << obj->GetName(); // Print variable name
for( int i=strlen(obj->GetName()); i<22; i++ ) // Add spaces for good
cout << ' '; // print.
cout << obj->GetDataType()->GetFullTypeName(); // Print variable type
for( int i=strlen(obj->GetDataType()->GetFullTypeName()); i<18; i++ )
cout << ' '; // Add spaces for good print
if( strlen(obj->GetName())<2 || obj->GetName()[0]!='f' )
{
cout << "Bad name. Skipped.\n";
continue;
}
char type[11]="";
if( !strcmp("int" , obj -> GetDataType() -> GetTypeName()) )
strcpy(type,"INTEGER");
if( !strcmp("float" , obj -> GetDataType() -> GetTypeName()) )
strcpy(type,"REAL");
if( *type == 0 )
{
cout << "Unknown type.\n";
continue;
}
int size;
switch( obj->GetArrayDim() )
{
case 0: size = 1; break;
case 1: size = obj->GetMaxIndex(0); break;
default:
cout << "Only one dimensional arrays are supported. Skipped.\n";
continue;
}
cout.form("amount=%d\n",size);
FFKEY( obj->GetName()+1 , (void*)((int)this + (int)obj->GetOffset()) ,
size , type );
}
}
//////////////////////////////////////////////////////////////////////////////