Inversion thread with Neighbourhood tuning parameters. More...
#include <InversionThread.h>
Signals | |
| void | started () |
| void | stopped () |
Public Member Functions | |
| int | activeModelCount () const |
| int | bestModelCount () const |
| void | checkImportModels () |
| void | clear () |
| int | expectedModelCount () const |
| AbstractForward * | forward () |
| double | giveUp () const |
| int | giveUpCount () const |
| bool | hasModelsToImport () const |
| bool | hasReportFile () const |
| void | importModels (QString fileName, bool strict=true) |
| InversionThread (QObject *parent=0) | |
| bool | isReportExists () const |
| void | lock () const |
| double | misfit (int modelIndex) const |
| int | nr () const |
| int | ns () const |
| int | ns0 () const |
| int | nw () const |
| bool | operator!= (const InversionThread &o) const |
| bool | operator== (const InversionThread &o) const |
| int | rejectedCount () const |
| void | removeReport () |
| double | reportBestMisfit () const |
| QDir | reportDir () const |
| QString | reportFileName () const |
| void | setForward (AbstractForward *forward) |
| void | setGiveUp (double giveUp) |
| void | setImportOnly () |
| void | setNr (int nr) |
| void | setNs (int ns) |
| void | setNs0 (int ns0) |
| void | setNw (int nw) |
| void | setObjectName (QString name) |
| bool | setReportDir (const QDir &d) |
| void | setStorage () |
| void | setTuningParameters (InversionThread *t) |
| void | start () |
| void | terminate () |
| void | unlock () const |
| int | validModelCount () const |
| const Parameter * | variableParameter (int paramIndex) const |
| int | variableParameterCount () const |
| double | variableParameterValue (int modelIndex, int paramIndex) const |
| int | visitedModelCount () const |
| virtual const QString & | xml_tagName () const |
| ~InversionThread () | |
Static Public Attributes | |
| static const QString | xmlInversionThreadTag = "InversionThread" |
Protected Member Functions | |
| virtual void | run () |
| virtual XMLMember | xml_member (XML_MEMBER_ARGS) |
| virtual void | xml_polish (XML_POLISH_ARGS) |
| virtual bool | xml_setProperty (XML_SETPROPERTY_ARGS) |
| virtual void | xml_writeChildren (XML_WRITECHILDREN_ARGS) const |
| virtual void | xml_writeProperties (XML_WRITEPROPERTIES_ARGS) const |
Inversion thread with Neighbourhood tuning parameters.
| InversionThread::InversionThread | ( | QObject * | parent = 0 | ) |
References dinverGui, and TRACE.
: Thread(parent) { TRACE; // Create log stream for this thread dinverGui->logs()->addView(this, "unamed"); _itmax=0; // Kept for compatibility _ns0=50; _ns=2500; _nr=50; _nw=2; _giveUp=0.9; _hasReportFile=false; _hasModelsToImport=false; _importOnly=false; _reportValidModelCount=0; _reportBestMisfit=0.0; }
References dinverGui, and DinverCore::ModelRepository::forward().
| int InversionThread::activeModelCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::activeModelCount().
Referenced by ProcessStatus::synchronize().
{return _models.activeModelCount();}
| int InversionThread::bestModelCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::bestModelCount().
Referenced by ProcessStatus::synchronize().
{return _models.bestModelCount();}
| void InversionThread::checkImportModels | ( | ) |
Check if the run has an attached report and if models can be imported from it. Models will be imported only if the run is started.
References DinverCore::ModelRepository::importModels(), QGpCoreTools::tr(), and DinverCore::ModelRepository::validModelCount().
Referenced by DinverGui::open().
{
StreamRedirection sr(&App::stream(this));
QFileInfo fi(_reportFileName);
if(_hasReportFile) {
if(fi.exists()) {
_hasModelsToImport=true;
} else {
// Try to translate the path
QString fn= Application::instance()->translatePath(_reportFileName, tr("Loading reports ..."),
tr( "Report file (%1)" ));
fi.setFile(fn);
if( !fn.isEmpty() && fi.exists()) {
_reportFileName=fn;
_hasModelsToImport=true;
} else {
_hasReportFile=false;
}
}
} else if(fi.exists()) { // Detected a report file with the same name...
_models.importModels(_reportFileName, true);
// Take ownership only if models are compatible
if(_models.validModelCount()>0) _hasReportFile=true;
_hasModelsToImport=false;
}
}
| void InversionThread::clear | ( | ) |
References DinverCore::ModelRepository::clear(), QGpCoreTools::endl(), removeReport(), terminate(), QGpCoreTools::tr(), and TRACE.
Referenced by DinverGui::clearThread().
| int InversionThread::expectedModelCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::expectedModelCount().
Referenced by ProcessStatus::synchronize().
{return _models.expectedModelCount();}
| AbstractForward* InversionThread::forward | ( | ) | [inline] |
References DinverCore::ModelRepository::forward().
{return _models.forward();}
| double InversionThread::giveUp | ( | ) | const [inline] |
Referenced by LaunchThreadItem::data(), setGiveUp(), and setTuningParameters().
{return _giveUp;}
| int InversionThread::giveUpCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::giveUpCount().
Referenced by ProcessStatus::synchronize().
{return _models.giveUpCount();}
| bool InversionThread::hasModelsToImport | ( | ) | const [inline] |
{return _hasModelsToImport;}
| bool InversionThread::hasReportFile | ( | ) | const [inline] |
Referenced by DinverGui::open(), DinverGui::removeThread(), and setObjectName().
{return _hasReportFile;}
| void InversionThread::importModels | ( | QString | fileName, |
| bool | strict = true |
||
| ) | [inline] |
References DinverCore::ModelRepository::importModels().
Referenced by ThreadLauncher::importModels().
{_models.importModels(fileName, strict);}
| bool InversionThread::isReportExists | ( | ) | const [inline] |
Check whether or not the report file exist.
Referenced by removeReport(), and setObjectName().
{QFileInfo fi(_reportFileName); return fi.exists();}
| void InversionThread::lock | ( | ) | const [inline] |
References DinverCore::ModelRepository::lock().
Referenced by PSViewer::synchronize(), and ProcessStatus::updateMisfitCurve().
{_models.lock();}
| double InversionThread::misfit | ( | int | modelIndex | ) | const [inline] |
References DinverCore::ModelRepository::misfit().
Referenced by ModelThreadInfo::operator<(), PSViewer::setLimits(), PSViewer::synchronize(), ProcessStatus::updateMisfitCurve(), and NAModelsPlot::xml_writeBinaryData().
{return _models.misfit(modelIndex);}
| int InversionThread::nr | ( | ) | const [inline] |
Referenced by LaunchThreadItem::data(), setNr(), and setTuningParameters().
{return _nr;}
| int InversionThread::ns | ( | ) | const [inline] |
Referenced by LaunchThreadItem::data(), setNs(), and setTuningParameters().
{return _ns;}
| int InversionThread::ns0 | ( | ) | const [inline] |
Referenced by LaunchThreadItem::data(), setNs0(), and setTuningParameters().
{return _ns0;}
| int InversionThread::nw | ( | ) | const [inline] |
Referenced by LaunchThreadItem::data(), setNw(), and setTuningParameters().
{return _nw;}
| bool InversionThread::operator!= | ( | const InversionThread & | o | ) | const [inline] |
{return !(_models==o._models);}
| bool InversionThread::operator== | ( | const InversionThread & | o | ) | const [inline] |
{return _models==o._models;}
| int InversionThread::rejectedCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::rejectedCount().
Referenced by ProcessStatus::synchronize().
{return _models.rejectedCount();}
| void InversionThread::removeReport | ( | ) |
Removes report file (and attached files) from disk if a report exists.
References QGpCoreTools::endl(), isReportExists(), QGpCoreTools::tr(), and TRACE.
Referenced by clear(), and DinverGui::removeThread().
{
TRACE;
if(isReportExists()) {
QFileInfo fi(_reportFileName);
QDir d(fi.path());
QString fn;
// Remove report file
fn=objectName()+".report";
App::stream() << tr("Removing %1").arg(fn) << endl;
d.remove(fn);
// Remove parameter file
fn=objectName()+".param";
App::stream() << tr("Removing %1").arg(fn) << endl;
d.remove(fn);
// Remove target file
fn=objectName()+".target";
App::stream() << tr("Removing %1").arg(fn) << endl;
d.remove(fn);
}
}
| double InversionThread::reportBestMisfit | ( | ) | const [inline] |
{return _reportBestMisfit;}
| QDir InversionThread::reportDir | ( | ) | const |
References TRACE.
Referenced by DinverGui::save().
{
TRACE;
QFileInfo fi (_reportFileName);
return fi.absoluteDir();
}
| QString InversionThread::reportFileName | ( | ) | const [inline] |
Referenced by xml_writeProperties().
{return _reportFileName;}
| void InversionThread::run | ( | ) | [protected, virtual] |
References DinverCore::ModelRepository::bestModelIndex(), DinverCore::ModelRepository::clear(), QGpCoreTools::endl(), DinverCore::ModelRepository::importModels(), DinverCore::ModelRepository::misfit(), DinverCore::ModelRepository::openReport(), DinverCore::ModelRepository::setBestModelCount(), DinverCore::ModelRepository::setGiveUp(), DinverCore::ModelRepository::setMaximumModelCount(), DinverCore::ModelRepository::setMaximumQueueLength(), DinverCore::ModelRepository::setWalkCount(), DinverCore::ModelRepository::start(), started(), stopped(), QGpCoreTools::tr(), TRACE, DinverCore::ModelRepository::validModelCount(), and DinverCore::ModelRepository::wait().
{
TRACE;
emit started();
MessageContext();
// Effectively import models if there available in my report
if(_hasModelsToImport) {
_models.importModels(_reportFileName, false);
if(_importOnly) {
_reportValidModelCount=_models.validModelCount();
_reportBestMisfit=_models.misfit(_models.bestModelIndex());
_models.clear();
} else {
_hasModelsToImport=false;
}
}
if(_importOnly) {
_importOnly=false;
return; // Do not emit stop because process was not started through ThreadLauncher
}
if(!_reportFileName.isEmpty()) {
if( !_models.openReport(_reportFileName) ) {
emit stopped();
return;
}
_hasReportFile=true; // Takes ownership of the report file
}
Application::instance()->setStreamPrefix(QString::null);
App::stream() << tr("Initialization of parameter space...") << endl;
_models.setBestModelCount(_nr);
_models.setWalkCount(_nw);
_models.setGiveUp(_giveUp);
_models.setMaximumQueueLength(50);
if(_ns0>0) {
App::stream() << tr("Generating %1 models randomly...").arg(_ns0) << endl;
_models.setMaximumModelCount(_models.validModelCount()+_ns0);
_models.start(Thread::idealThreadCount(), Generator::MonteCarlo);
_models.wait();
App::stream() << tr("Generated %1 models randomly").arg(_ns0) << endl;
}
if(_ns>0) {
Application::instance()->setStreamPrefix(QString::null);
App::stream() << tr("Generating %1 models with Neighborhood...").arg(_ns) << endl;
_models.setMaximumModelCount(_models.validModelCount()+_ns);
_models.start(Thread::idealThreadCount(), Generator::Neighborhood);
_models.wait();
App::stream() << tr("Generated %1 models with Neighborhood").arg(_ns) << endl;
}
Application::instance()->setStreamPrefix(QString::null);
//printBestModels();
emit stopped();
}
| void InversionThread::setForward | ( | AbstractForward * | forward | ) |
References DinverCore::ModelRepository::setForward().
Referenced by ThreadLauncher::newThread(), and XMLDinverGui::xml_member().
{
_models.setForward(forward);
}
| void InversionThread::setGiveUp | ( | double | giveUp | ) | [inline] |
References giveUp().
Referenced by LaunchThreadItem::setData(), and setTuningParameters().
{_giveUp=giveUp;}
| void InversionThread::setImportOnly | ( | ) | [inline] |
Referenced by DinverGui::open().
{_importOnly=true;}
| void InversionThread::setNr | ( | int | nr | ) | [inline] |
| void InversionThread::setNs | ( | int | ns | ) | [inline] |
| void InversionThread::setNs0 | ( | int | ns0 | ) | [inline] |
| void InversionThread::setNw | ( | int | nw | ) | [inline] |
| void InversionThread::setObjectName | ( | QString | name | ) |
References dinverGui, QGpCoreTools::endl(), hasReportFile(), isReportExists(), QGpCoreTools::tr(), and TRACE.
Referenced by ThreadLauncher::newThread(), LaunchThreadItem::setData(), and xml_setProperty().
{
TRACE;
if(name==objectName()) return;
if(isRunning()) {
App::stream() << tr("run %1: cannot change the name of a running inversion.")
.arg(objectName()) << endl;
return;
}
// Check if name is unique
const ThreadList threads=dinverGui->threads();
for(ThreadList::const_iterator it=threads.begin(); it<threads.end(); it++ ) {
if((*it)->objectName()==name) {
App::stream() << tr("The new name for run %1 is not unique, nothing changed.").arg(objectName()) << endl;
return;
}
}
QObject::setObjectName(name);
QFileInfo fi(_reportFileName);
QDir d(fi.path());
QString oldName =objectName();
bool oldReportExist=isReportExists();
_reportFileName=d.absoluteFilePath(name+".report");
if(oldReportExist && hasReportFile()) {
renameReport(oldName);
}
}
| bool InversionThread::setReportDir | ( | const QDir & | d | ) |
References QGpCoreTools::endl(), QGpCoreTools::tr(), and TRACE.
Referenced by ThreadLauncher::newThread(), DinverGui::open(), and DinverGui::save().
{
TRACE;
if(isRunning()) {
App::stream() << tr("run %1 is runnnig cannot copy report to %2.")
.arg(objectName()).arg(d.absolutePath()) << endl;
return false;
} else {
QString newFileName=d.absoluteFilePath(objectName()+".report");
if(!_reportFileName.isEmpty()) {
QFileInfo fi(_reportFileName);
if(fi.exists()) {
QDir oldDir(fi.path());
if(oldDir!=d) {
QFile::copy(_reportFileName, newFileName);
}
}
}
_reportFileName=newFileName;
return true;
}
}
| void InversionThread::setStorage | ( | ) |
References DinverCore::ModelRepository::setStorage().
Referenced by ThreadLauncher::newThread().
{
_models.setStorage();
}
| void InversionThread::setTuningParameters | ( | InversionThread * | t | ) |
| void InversionThread::start | ( | ) |
References DinverCore::ModelRepository::checksum(), QGpCoreTools::endl(), DinverCore::ModelRepository::expectedModelCount(), DinverCore::ModelRepository::init(), stopped(), QGpCoreTools::tr(), TRACE, and DinverCore::ModelRepository::variableParameterCount().
Referenced by DinverGui::open().
{
TRACE;
if(_importOnly) {
App::stream(this) << tr("\n---------------------- Getting information at ")
<< QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << "\n\n"
<< tr(" Dimension of parameter space =%1\n").arg(_models.variableParameterCount())
<< tr(" Model file =%1\n").arg(_reportFileName) << endl;
} else {
App::stream(this) << tr("\n---------------------- Starting at ")
<< QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << "\n\n"
<< tr(" Num samples Monte-Carlo =%1\n").arg(_ns0)
<< tr(" Num samples Neighborhood =%1\n").arg(_ns)
<< tr(" Num cells to resample =%1\n").arg(_nr)
<< tr(" Num of walks before accepting model =%1\n").arg(_nw)
<< tr(" Max reject ratio before cell give up=%1\n").arg(_giveUp)
<< tr(" Dimension of parameter space =%1\n").arg(_models.variableParameterCount())
<< tr(" Parameterization checksum =%1\n").arg(_models.checksum())
<< tr(" Total number of models =%1\n").arg(_models.expectedModelCount())
<< tr(" Model file =%1\n").arg(_reportFileName) << endl;
if(_models.variableParameterCount()==0) {
App::stream(this) << tr("Number of variable parameters is null, nothing to optimize, aborting.") << endl;
emit stopped();
return;
}
}
_models.init();
QThread::start();
//run();
}
| void InversionThread::started | ( | ) | [signal] |
Referenced by run().
| void InversionThread::stopped | ( | ) | [signal] |
| void InversionThread::terminate | ( | ) |
References QGpCoreTools::endl(), DinverCore::ModelRepository::stop(), QGpCoreTools::tr(), and TRACE.
Referenced by clear(), ThreadLauncher::remove(), and ThreadLauncher::stop().
| void InversionThread::unlock | ( | ) | const [inline] |
References DinverCore::ModelRepository::unlock().
Referenced by PSViewer::synchronize(), and ProcessStatus::updateMisfitCurve().
{_models.unlock();}
| int InversionThread::validModelCount | ( | ) | const |
References DinverCore::ModelRepository::validModelCount().
Referenced by ProcessStatus::synchronize().
{
if(_hasModelsToImport) {
return _reportValidModelCount;
} else {
return _models.validModelCount();
}
}
| const Parameter* InversionThread::variableParameter | ( | int | paramIndex | ) | const [inline] |
References DinverCore::ModelRepository::variableParameter().
Referenced by NAModelsPlotProperties::setParameterList(), NAModelsPlot::setParamX(), and NAModelsPlot::setParamY().
{return _models.variableParameter(paramIndex);}
| int InversionThread::variableParameterCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::variableParameterCount().
Referenced by PSViewer::addThreadData(), and NAModelsPlotProperties::setParameterList().
{return _models.variableParameterCount();}
| double InversionThread::variableParameterValue | ( | int | modelIndex, |
| int | paramIndex | ||
| ) | const [inline] |
References DinverCore::ModelRepository::variableParameterValue().
Referenced by NAModelsPlot::xml_writeBinaryData().
{return _models.variableParameterValue(modelIndex, paramIndex);}
| int InversionThread::visitedModelCount | ( | ) | const [inline] |
References DinverCore::ModelRepository::visitedModelCount().
Referenced by PSViewer::synchronize(), and ProcessStatus::synchronize().
{return _models.visitedModelCount();}
| XMLMember InversionThread::xml_member | ( | XML_MEMBER_ARGS | ) | [protected, virtual] |
Re-implement this function to offer XML restore (children and properties) support to your class.
From tag and map (with contains the attibute value) return a unique identifier under the format of a XMLMember. XMLMember is initialized with 3 types of contructors:
Map of attributes can be inspected in this way (can be achived also in xml_setProperty()):
static const QString tmp("childrenName"); XMLRestoreAttributeIterator it=map.find(tmp); if(it!=map.end()) { // found attribute "childrenName" }
If the map of attributes is not used:
Q_UNUSED(attributes);
if(tag=="x1") return XMLMember(0);
else if(tag=="y1") return XMLMember(1);
else if(tag=="x2") return XMLMember(2);
else if(tag=="y2") return XMLMember(3);
else return XMLMember(XMLMember::Unknown);
Arithmetic operations + and - apply to XMLMember to avoid confusion of property id numbers between inherited objects. Offset 3 corresponds to the number of properties defined in this object.
if(tag=="anInteger") return XMLMember(0); else if(tag=="aString") return XMLMember(1); else if(tag=="aDouble") return XMLMember(2); return AbstractLine::xml_member(tag, attributes, context)+3;
For the arguments of this function use Macro XML_MEMBER_ARGS.
Reimplemented from QGpCoreTools::XMLClass.
References DinverCore::ModelRepository::forward(), TRACE, and DinverCore::AbstractForward::xml_member().
{
TRACE;
if(tag=="ns0" ) return XMLMember(1);
else if(tag=="ns" ) return XMLMember(2);
else if(tag=="nr" ) return XMLMember(3);
else if(tag=="nw" ) return XMLMember(4);
else if(tag=="giveUp" ) return XMLMember(5);
else if(tag=="report" ) return XMLMember(7);
else if(tag=="checksum" ) return XMLMember(9);
else if(tag=="hasReportFile" ) return XMLMember(10);
else if(tag=="itmax" ) return XMLMember(0); // Kept for compatibility
else if(tag=="seed" ) return XMLMember(8); // Kept for compatibility
else if(tag=="runType" ) return XMLMember(8); // Kept for compatibility
else if(tag=="jointRun" ) return XMLMember(8); // Kept for compatibility
else if(tag=="acceptableMisfit" ) return XMLMember(8); // Kept for compatibility
else if(tag=="scaling" ) return XMLMember(8); // Kept for compatibility
else if(tag=="dynScale" ) return XMLMember(8); // Kept for compatibility
else if(tag=="cellDist" ) return XMLMember(8); // Kept for compatibility
else {
return _models.forward()->xml_member(tag, attributes, context)+15;
}
}
| void InversionThread::xml_polish | ( | XML_POLISH_ARGS | ) | [protected, virtual] |
Reimplemented from QGpCoreTools::XMLClass.
References DinverCore::ModelRepository::forward(), DinverCore::ModelRepository::setStorage(), TRACE, and DinverCore::AbstractForward::xml_polish().
{
TRACE;
if(_itmax>0) { // Kept for compatibility
_ns*=_itmax;
_itmax=0;
}
StreamRedirection sr(&App::stream(this));
_models.forward()->xml_polish(context);
_models.setStorage();
}
| bool InversionThread::xml_setProperty | ( | XML_SETPROPERTY_ARGS | ) | [protected, virtual] |
Re-implement this function to offer XML restore properties support to your class.
From memberID set the corresponding property with value content. The map of attributes is given as a supplementary information (not useful in all cases).
For a general case:
Q_UNUSED(attributes); double val=content.toDouble(); switch (memberID) { case 0: _x1=val; return true; case 1: _y1=val; return true; case 2: _x2=val; return true; case 3: _y2=val; return true; default: return false; }
For classes inheriting other classes (see also xml_member())
switch (memberID) { case 0: _anInteger=content.toString(); return true; case 1: _aString=content.toInt(); return true; case 2: _aDouble=content.toDouble(); return true; default: return AbstractLine::xml_setProperty(memberID-3, map, content);
For the arguments of this function use Macro XML_SETPROPERTY_ARGS.
Reimplemented from QGpCoreTools::XMLClass.
References dinverGui, DinverCore::ModelRepository::forward(), setObjectName(), TRACE, and DinverCore::AbstractForward::xml_setProperty().
{
TRACE;
switch (memberID) {
case 0:
_itmax=content.toInt(); // Kept for compatibility
return true;
case 1:
_ns0=content.toInt();
return true;
case 2:
_ns=content.toInt();
return true;
case 3:
_nr=content.toInt();
return true;
case 4:
_nw=content.toInt();
return true;
case 5:
_giveUp=content.toDouble();
return true;
case 7: {
_reportFileName=content.toString();
QFileInfo fi(_reportFileName);
QObject::setObjectName(fi.baseName());
dinverGui->logs()->setViewName(this, fi.baseName());
_hasReportFile=true; // set a default value (compatibility)
}
return true;
case 8: // Kept for compatibility
return true;
case 9:
// Checksum not read from file
return true;
case 10:
_hasReportFile=content.toBool();
return true;
default:
return _models.forward()->xml_setProperty(memberID-15, tag, attributes, content, context);
}
}
| virtual const QString& InversionThread::xml_tagName | ( | ) | const [inline, virtual] |
Implements QGpCoreTools::XMLClass.
References xmlInversionThreadTag.
{return xmlInversionThreadTag;}
| void InversionThread::xml_writeChildren | ( | XML_WRITECHILDREN_ARGS | ) | const [protected, virtual] |
Reimplemented from QGpCoreTools::XMLClass.
References DinverCore::ModelRepository::forward(), TRACE, and DinverCore::AbstractForward::xml_writeChildren().
{
TRACE;
_models.forward()->xml_writeChildren(s, context);
}
| void InversionThread::xml_writeProperties | ( | XML_WRITEPROPERTIES_ARGS | ) | const [protected, virtual] |
Reimplemented from QGpCoreTools::XMLClass.
References DinverCore::ModelRepository::checksum(), DinverCore::ModelRepository::forward(), reportFileName(), TRACE, QGpCoreTools::XMLClass::writeProperty(), and DinverCore::AbstractForward::xml_writeProperties().
{
TRACE;
writeProperty(s, "ns0",_ns0);
writeProperty(s, "ns",_ns);
writeProperty(s, "nr",_nr);
writeProperty(s, "nw",_nw);
writeProperty(s, "giveUp",_giveUp);
writeProperty(s, "report",reportFileName());
writeProperty(s, "checksum",(int)_models.checksum());
writeProperty(s, "hasReportFile",_hasReportFile);
_models.forward()->xml_writeProperties(s, context);
}
const QString InversionThread::xmlInversionThreadTag = "InversionThread" [static] |
Referenced by xml_tagName().