API documentation
Module.cpp
Go to the documentation of this file.
00001 00005 /* 00006 * JEMRIS Copyright (C) 2007-2010 Tony Stöcker, Kaveh Vahedipour 00007 * Forschungszentrum Jülich, Germany 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 */ 00023 00024 #include "Module.h" 00025 #include "Parameters.h" 00026 #include "SequenceTree.h" 00027 #include "ConcatSequence.h" 00028 #include "Pulse.h" 00029 #include "XMLIO.h" 00030 00031 /***********************************************************/ 00032 Module::Module() { 00033 00034 m_node = NULL ; 00035 m_seq_tree = NULL ; 00036 m_duration = 0.0 ; 00037 m_calls = 0 ; 00038 00039 }; 00040 00041 /***********************************************************/ 00042 void Module::Initialize (DOMNode* node) { 00043 00044 //if node has no "Name" attribute, insert it and use the node name for its value 00045 string s = StrX(((DOMElement*) node)->getAttribute (StrX("Name").XMLchar() )).std_str() ; 00046 if (s.empty()) 00047 ((DOMElement*) node)->setAttribute(StrX("Name").XMLchar(),node->getNodeName()); 00048 00049 //set the module name to the node name as well 00050 SetName( StrX(node->getNodeName()).std_str() ); 00051 00052 //set the instances of this node and the sequence tree 00053 m_node = node; 00054 m_seq_tree = SequenceTree::instance(); 00055 m_parameters = m_seq_tree->GetParameters(); 00056 00057 } 00058 00059 /***********************************************************/ 00060 bool Module::Prepare (PrepareMode mode){ 00061 00062 ATTRIBUTE("Duration", m_duration); 00063 //ATTRIBUTE("Observe" , NULL); //special case of observing attributes 00064 00065 return Prototype::Prepare(mode); 00066 00067 }; 00068 00069 /***********************************************************/ 00070 Module* Module::GetPrototypeByAttributeValue(string name, string attrib) { 00071 return m_seq_tree->GetModuleByAttributeValue(name,attrib); 00072 } 00073 00074 /***********************************************************/ 00075 Module* Module::GetParent () { 00076 00077 if (m_seq_tree==NULL || m_node==NULL) return NULL; 00078 return m_seq_tree->GetParent(m_node); 00079 00080 } 00081 00082 /***********************************************************/ 00083 vector<Module*> Module::GetChildren () { 00084 00085 if (m_seq_tree==NULL || m_node==NULL) return vector<Module*>() ; 00086 return m_seq_tree->GetChildren(m_node); 00087 00088 } 00089 00090 /***********************************************************/ 00091 Module* Module::GetChild (unsigned int position) { 00092 00093 if (m_seq_tree==NULL || m_node==NULL) return NULL; 00094 return m_seq_tree->GetChild(m_node, position); 00095 00096 } 00097 00098 /***********************************************************/ 00099 int Module::GetNumberOfChildren () { 00100 00101 vector<Module*> vc=GetChildren(); 00102 return vc.size(); 00103 00104 }; 00105 00106 /***********************************************************/ 00107 bool Module::InsertChild (string name){ 00108 00109 if ( m_seq_tree==NULL || GetNode()==NULL) return false; 00110 00111 DOMElement* node = m_seq_tree->GetDOMDocument()->createElement(StrX(name).XMLchar()); 00112 if (node==NULL) return false; 00113 00114 Module* mod = m_seq_tree->GetMPF()->CloneModule(node); 00115 if (mod==NULL) return false; 00116 00117 GetNode()->appendChild (node); 00118 m_seq_tree->GetModuleMap()->insert(pair<DOMNode*, Module*> (node, mod)); 00119 mod->Initialize(node); 00120 00121 return true; 00122 00123 }; 00124 00125 /***********************************************************/ 00126 bool Module::AddDOMattribute (const string attribute, const string value){ 00127 00128 if (HasDOMattribute(attribute)) 00129 return false; 00130 00131 ((DOMElement*) m_node)->setAttribute( StrX(attribute).XMLchar(), StrX(value).XMLchar() ); 00132 00133 return true; 00134 00135 }; 00136 00137 /***********************************************************/ 00138 void Module::AddAllDOMattributes (bool show_hidden){ 00139 00140 map<string,Attribute*>::iterator iter; 00141 00142 for(iter = m_attributes.begin(); iter != m_attributes.end(); iter++) { 00143 00144 string attrib_name = iter->first; 00145 Attribute* attrib = iter->second; 00146 00147 //do not take hidden and unobservable attributes into account 00148 if (!attrib->IsObservable() && !attrib->IsPublic()) continue; 00149 //mark hidden attributes 00150 if (!attrib->IsPublic()) attrib_name +="HIDDEN"; 00151 00152 stringstream sstr; 00153 if (attrib->IsObservable()) { 00154 void* p = attrib->GetAddress() ; 00155 if (attrib->GetTypeID()==typeid( double*).name()) sstr << (*((double*) p)); 00156 if (attrib->GetTypeID()==typeid( int*).name()) sstr << (*((int*) p)); 00157 if (attrib->GetTypeID()==typeid( long*).name()) sstr << (*((long*) p)); 00158 if (attrib->GetTypeID()==typeid(unsigned*).name()) sstr << (*((unsigned*) p)); 00159 if (attrib->GetTypeID()==typeid( bool*).name()) sstr << (*((bool*) p)); 00160 if (attrib->GetTypeID()==typeid( string*).name()) sstr << (*((string*) p)); 00161 } 00162 00163 //some exceptions (ugly): Constants/AnalyticTime in Analytic Pulses, Modules in DelayAtoms, NLG field terms in Gradients 00164 if ( attrib_name.find("Constant",0) != string::npos && !attrib->IsPublic() ) continue; 00165 if ( attrib_name.find("Analytic",0) != string::npos && !attrib->IsPublic() ) continue; 00166 if ( attrib_name.find("Module" ,0) != string::npos && !attrib->IsPublic() ) continue; 00167 if ( attrib_name.find("NLG_" ,0) != string::npos && !attrib->IsPublic() ) continue; 00168 00169 AddDOMattribute( attrib_name, sstr.str() ); 00170 } 00171 00172 /* 00173 map<string, void*>::iterator it; 00174 00175 for( it = m_attrib_addr.begin(); it != m_attrib_addr.end(); it++ ) { 00176 00177 map<string, bool>::iterator is_obs_attrib = m_attrib_observable.find(it->first); 00178 map<string, bool>::iterator is_xml_attrib = m_attrib_xml.find(it->first); 00179 00180 if (is_obs_attrib->second) { 00181 00182 string attrib_name = it->first; 00183 00184 if (!is_xml_attrib->second) { 00185 if (!show_hidden) continue; 00186 attrib_name +="HIDDEN"; 00187 } 00188 00189 stringstream sstr; 00190 00191 void* p = it->second; 00192 map<string, string>::iterator type = m_attrib_type.find(it->first); 00193 00194 00195 if (IsDynamic(attrib_name)) { 00196 //cout << GetName() << ":" << attrib_name << " is a dynamic attribute:" << endl; 00197 AddDOMattribute(attrib_name, "dynamic" ); 00198 if ( type->second == typeid(double*).name() ) { 00199 pair<multimap< string , double > ::iterator, multimap< string , double > ::iterator> itp; 00200 itp = m_record_double.equal_range(attrib_name); 00201 multimap< string , double >::iterator it; 00202 for (it=itp.first; it!=itp.second; ++it) { 00203 double d=it->second; 00204 if (attrib_name == "InitialPhase") d=fmod(d,360.0); 00205 sstr << d << " "; 00206 } 00207 AddDOMattribute(attrib_name+"Values", sstr.str() ); 00208 } 00209 if ( type->second == typeid(int*).name() ) { 00210 pair<multimap< string , int > ::iterator, multimap< string , int > ::iterator> itp; 00211 itp = m_record_int.equal_range(attrib_name); 00212 multimap< string , int >::iterator it; 00213 for (it=itp.first; it!=itp.second; ++it) { 00214 sstr << it->second << " "; 00215 } 00216 AddDOMattribute(attrib_name+"Values", sstr.str() ); 00217 } 00218 } 00219 else { 00220 if ( type->second == typeid(double*).name() ) sstr << (*((double*) p)); 00221 if ( type->second == typeid(float*).name() ) sstr << (*((float*) p)); 00222 if ( type->second == typeid(int*).name() ) sstr << (*((int*) p)); 00223 if ( type->second == typeid(unsigned int*).name()) sstr << (*((unsigned int*) p)); 00224 if ( type->second == typeid(bool*).name() ) sstr << (*((bool*) p)); 00225 if ( type->second == typeid(long*).name() ) sstr << (*((long*) p)); 00226 if ( type->second == typeid(PulseAxis*).name() ) sstr << (*((int*) p)); 00227 if ( type->second == typeid(string*).name() ) sstr << (*((string*) p)); 00228 00229 if (!show_hidden) 00230 if (sstr.str().empty() || sstr.str()=="0") continue; 00231 00232 AddDOMattribute(attrib_name, sstr.str() ); 00233 } 00234 00235 } 00236 } 00237 */ 00238 }; 00239 00240 /***********************************************************/ 00241 void Module::DumpTree (string file, Module* mod,int ichild, int level) { 00242 00243 //root node redirects output buffer, if filename is given 00244 streambuf* sobuf = 0; 00245 std::ofstream* pfout = 0; 00246 if (mod ==NULL) { 00247 00248 mod=this; 00249 00250 if (!file.empty()) { 00251 00252 sobuf = cout.rdbuf(); // Save the original stdout buffer. 00253 pfout = new ofstream(file.c_str()); 00254 00255 if (*pfout) cout.rdbuf(pfout->rdbuf()); // Redirect cout output to the opened file. 00256 00257 } 00258 00259 } 00260 00261 //Dump info on this module 00262 vector<Module*> children = mod->GetChildren(); 00263 stringstream spaces_bef; 00264 for (int j=0;j<level;++j) spaces_bef << " "; 00265 stringstream spaces_aft; 00266 for (int j=level; j<m_seq_tree->GetDepth(); ++j) spaces_aft << " "; 00267 00268 if (ichild) cout << spaces_bef.str() << "|_ child " << ichild << " "; 00269 else cout << "dump of sequence tree\n" 00270 << spaces_aft.str() << " TYPE CLASS NAME duration ADCs TPOIs | module specific\n" 00271 << spaces_aft.str() << " ----------------------------------------------------------------- | ---------------\n" 00272 << "sequence-root"; 00273 00274 for (int j=level; j<m_seq_tree->GetDepth(); ++j) cout << "--"; 00275 cout << "> "; 00276 00277 string class_type = mod->GetClassType(); 00278 string name = mod->GetName(); 00279 transform(class_type.begin(), class_type.end(), class_type.begin(), (int(*)(int)) toupper); 00280 00281 string type; 00282 int adcs = 0; 00283 00284 if (mod->GetType() == MOD_CONCAT) { 00285 type="CONCAT"; 00286 adcs=((Sequence*) mod)->GetNumOfADCs(); 00287 } 00288 00289 if (mod->GetType() == MOD_ATOM) { 00290 type="ATOM"; 00291 adcs=((Sequence*) mod)->GetNumOfADCs(); 00292 } 00293 00294 if (mod->GetType() == MOD_PULSE) { 00295 type="PULSE"; 00296 adcs=((Pulse*) mod)->GetNADC() ; 00297 } 00298 00299 int tpois = mod->GetNumOfTPOIs(); 00300 char chform[70]; 00301 sprintf(chform,"%8s %20s %8s %9.3f %7d %8d",type.c_str(),class_type.c_str(),name.c_str(),mod->GetDuration(),adcs,tpois); 00302 cout << chform << " | " << mod->GetInfo() << "\n"; 00303 00304 level++; 00305 00306 for (unsigned int i=0; i<children.size() ; ++i) 00307 DumpTree(file, mod->GetChild(i),i+1,level); 00308 00309 // root node restores cout to original state. 00310 if (ichild == 0 && !file.empty() ) { 00311 cout.rdbuf(sobuf); 00312 delete pfout; 00313 } 00314 00315 }; 00316 00317 /***********************************************************/ 00318 bool Module::WriteStaticXML (string xml_file) { 00319 00320 DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(StrX("Core").XMLchar() ); 00321 00322 if (impl==NULL) return false; 00323 00324 DOMDocument* doc = impl->createDocument( 0, StrX("PARAM").XMLchar(), 0); 00325 DOMNode* topnode = doc->getFirstChild(); 00326 Parameters* parameters = m_seq_tree->GetParameters(); 00327 DOMNode* backup_node = parameters->GetNode(); 00328 XMLIO* xmlio = new XMLIO(); 00329 00330 parameters->SetNode(topnode); 00331 parameters->AddAllDOMattributes(false); 00332 00333 if ( ((DOMElement*) topnode)->getAttributeNode(StrX("Name").XMLchar()) != NULL) 00334 ((DOMElement*) topnode)->removeAttribute (StrX("Name").XMLchar()); 00335 00336 parameters->SetNode(backup_node); 00337 00338 //recursively add elements 00339 if (!StaticDOM(doc,topnode)) return false; 00340 00341 xmlio->Write (impl, topnode, xml_file); 00342 00343 delete doc; 00344 delete topnode; 00345 delete parameters; 00346 delete backup_node; 00347 delete xmlio; 00348 00349 return true; 00350 00351 }; 00352 00353 /***********************************************************/ 00354 bool Module::StaticDOM(DOMDocument* doc, DOMNode* node, bool append){ 00355 bool ret = true; 00356 /* 00357 DOMNode* backup_node = m_node; 00358 00359 DOMElement* elem; 00360 00361 00362 //trigger the recording of sequence changes through repetition counters 00363 if (GetType() == MOD_CONCAT ) { 00364 if (append){ 00365 elem = doc->createElement ( StrX("CONCAT").XMLchar() ); 00366 m_node = elem; 00367 AddAllDOMattributes(false); 00368 node->appendChild(elem); 00369 m_node = backup_node; 00370 if ( ((DOMElement*) elem)->getAttributeNode(StrX("Name").XMLchar()) != NULL) 00371 ((DOMElement*) elem)->removeAttribute (StrX("Name").XMLchar()); 00372 } 00373 ConcatSequence* cs = ((ConcatSequence*) this); 00374 for (int r=0;r< cs->GetMyRepetitions(); r++) { 00375 cs->SetRepCounter(r,true); 00376 vector<Module*> children = GetChildren(); 00377 for (unsigned int j=0; j<children.size() ; ++j) { 00378 bool lastrep = (r+1==cs->GetMyRepetitions()) ; 00379 ret = ( children[j]->StaticDOM(doc, elem, (append && lastrep) ) && ret); 00380 } 00381 } 00382 return ret; 00383 } 00384 00385 if (!append) return ret; 00386 00387 string class_type = GetClassType(); 00388 transform(class_type.begin(), class_type.end(), class_type.begin(), (int(*)(int)) toupper); 00389 00390 if (GetType() == MOD_ATOM ) elem = doc->createElement ( StrX("ATOMIC").XMLchar() ); 00391 if (GetType() == MOD_PULSE ) elem = doc->createElement ( StrX("PULSE").XMLchar() ); 00392 Module* p = GetParent(); 00393 00394 m_node = elem; 00395 00396 if (GetType() == MOD_PULSE ){ 00397 string val=""; 00398 if ( class_type == "HARDRFPULSE" ) val="RF_RECT"; 00399 if ( class_type == "SINCRFPULSE" ) val="RF_SINC"; 00400 if ( class_type == "GAUSSIANRFPULSE" ) val="RF_GAUSS"; 00401 if ( class_type == "SECHRFPULSE" ) val="RF_SECH"; 00402 if ( class_type == "TRAPGRADPULSE" ) val="GR"; 00403 if ( class_type == "EMPTYPULSE" ) { 00404 if ( ( (Pulse*) this)->GetNADC() > 0 ) 00405 val="RO"; 00406 else 00407 val="NONE"; 00408 //special case of empty pulses in a variable-length DelayAtom 00409 string p_class_type = p->GetClassType(); 00410 transform(p_class_type.begin(), p_class_type.end(), p_class_type.begin(), (int(*)(int)) toupper); 00411 if (p_class_type=="DELAYATOMICSEQUENCE" && p->IsDynamic("Delay")){ 00412 string dval = StrX(((DOMElement*) node)->getAttribute (StrX("DelayValues").XMLchar())).std_str() ; 00413 //cout << GetName() << " " << p_class_type << " " << dval << endl; 00414 AddDOMattribute("Duration","dynamic"); 00415 AddDOMattribute("DurationValues",dval); 00416 ((DOMElement*) node)->removeAttribute (StrX("DelayValues").XMLchar()); 00417 } 00418 } 00419 //if ( GetClassType() == "") val=""; 00420 AddDOMattribute("Type", val ); 00421 } 00422 AddAllDOMattributes(false); 00423 00424 node->appendChild(elem); 00425 00426 if ( GetType() == MOD_PULSE && class_type == "EMPTYPULSE" ) { 00427 } 00428 00429 00430 m_node = backup_node; 00431 00432 vector<Module*> children = GetChildren(); 00433 for (unsigned int j=0; j<children.size() ; ++j) 00434 ret = ( children[j]->StaticDOM(doc, elem) && ret); 00435 00436 //clean up the XML: remove attributes unnecessary for IDEA 00437 if ( ((DOMElement*) elem)->getAttributeNode(StrX("Name").XMLchar()) != NULL) 00438 ((DOMElement*) elem)->removeAttribute (StrX("Name").XMLchar()); 00439 if (GetType() == MOD_ATOM ) { 00440 map<string, void*>::iterator it; 00441 for( it = m_attrib_addr.begin(); it != m_attrib_addr.end(); it++ ) { 00442 if ( ((DOMElement*) elem)->getAttributeNode(StrX(it->first).XMLchar()) != NULL) 00443 ((DOMElement*) elem)->removeAttribute (StrX(it->first).XMLchar()); 00444 } 00445 } 00446 00447 00448 */ 00449 return ret; 00450 }; 00451
