Пример #1
0
void
CUSESTest::setUp()
{
  mCUSESBootstrap = CreateCUSESBootstrap();
  mBootstrap = CreateCellMLBootstrap();
  mModelLoader = mBootstrap->modelLoader();
}
Пример #2
0
int CellmlModelDefinition::loadModel(const std::string &url)
{
    std::cout << "Creating CellML Model Definition from the URL: "
              << url << std::endl;
    mUrl = url;
    if (mUrl.empty()) return -1;
    std::wstring urlW = s2ws(url);
    ObjRef<iface::cellml_api::CellMLBootstrap> cb = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> ml = cb->modelLoader();
    int code;
    try
    {
        ObjRef<iface::cellml_api::Model> model = ml->loadFromURL(urlW);
        model->fullyInstantiateImports();
        // we have a model, so we can start grabbing hold of the CellML API objects
        mCapi = new CellmlApiObjects();
        mCapi->model = model;
        code = instantiateCellmlApiObjects();
    }
    catch (...)
    {
      std::wcerr << L"Error loading model: " << urlW << std::endl;
      return -1;
    }
    return code;
}
Пример #3
0
std::string getCellMLMetadataAsRDFXMLString(const char* mbrurl)
{
    std::string s;

    // Get the URL from which to load the model
    if (!mbrurl) return(s);
    std::wstring URL = string2wstring(mbrurl);

    RETURN_INTO_OBJREF(cb, iface::cellml_api::CellMLBootstrap, CreateCellMLBootstrap());
    RETURN_INTO_OBJREF(ml, iface::cellml_api::ModelLoader, cb->modelLoader());
    // Try and load the CellML model from the URL
    try
    {
        RETURN_INTO_OBJREF(model, iface::cellml_api::Model, ml->loadFromURL(URL.c_str()));
        RETURN_INTO_OBJREF(rr, iface::cellml_api::RDFRepresentation,
                           model->getRDFRepresentation(L"http://www.cellml.org/RDFXML/string"));
        if (rr)
        {
            DECLARE_QUERY_INTERFACE(rrs,rr,cellml_api::RDFXMLStringRepresentation);
            std::wstring rdf = rrs->serialisedData();
            s = wstring2string(rdf.c_str());
        }
    }
    catch (...)
    {
        std::cerr << "getCellMLMetadataAsRDFXMLString: Error loading model URL: " << mbrurl << std::endl;
        return(s);
    }
    return(s);
}
void
AnnoToolsTest::testStringAnnotation()
{
  iface::cellml_api::CellMLBootstrap* bs = CreateCellMLBootstrap();
  iface::cellml_api::DOMModelLoader* ml = bs->modelLoader();
  bs->release_ref();
  iface::cellml_api::Model* m =
    ml->loadFromURL(BASE_DIRECTORY L"Ach_cascade_1995.xml");
  
  CPPUNIT_ASSERT_NO_THROW(mAS->setStringAnnotation(m, L"thestring", L"hello"));

  std::wstring anno = mAS->getStringAnnotation(m, L"thestring");
  CPPUNIT_ASSERT_EQUAL(std::wstring(L"hello"), anno);

  std::wstring anno2 = mAS->getStringAnnotationWithDefault(m, L"thestring", L"mystring");
  CPPUNIT_ASSERT_EQUAL(std::wstring(L"hello"), anno2);
  std::wstring anno3 = mAS->getStringAnnotationWithDefault(m, L"thestringno", L"mystring");
  CPPUNIT_ASSERT_EQUAL(std::wstring(L"mystring"), anno3);


  std::wstring fstr = mAS->prefixURI();
  fstr += L"thestring";

  iface::cellml_api::UserData* oa = m->getUserData(fstr.c_str());
  CPPUNIT_ASSERT(oa);
  oa->release_ref();

  mAS->release_ref();
  mAS = NULL;
  
  CPPUNIT_ASSERT_THROW(oa = m->getUserData(fstr.c_str()), iface::cellml_api::CellMLException);

  ml->release_ref();
  m->release_ref();
}
Пример #5
0
int CellmlModelDefinition::loadModelFromString(const std::string &ms)
{
    std::cout << "Creating CellML Model Definition from the given model string"
              << std::endl;
    mUrl = "";
    std::wstring msW = s2ws(ms);
    ObjRef<iface::cellml_api::CellMLBootstrap> cb = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> ml = cb->modelLoader();
    int code;
    try
    {
        ObjRef<iface::cellml_api::Model> model = ml->createFromText(msW);
        model->fullyInstantiateImports();
        // we have a model, so we can start grabbing hold of the CellML API objects
        mCapi = new CellmlApiObjects();
        mCapi->model = model;
        code = instantiateCellmlApiObjects();
    }
    catch (...)
    {
      std::wcerr << L"Error loading model from string." << std::endl;
      return -1;
    }
    return code;
}
Пример #6
0
int main(int argc, char ** argv)
{
    RETURN_INTO_OBJREF(cbs, iface::cellml_api::CellMLBootstrap,
                       CreateCellMLBootstrap());

    RETURN_INTO_OBJREF(ml, iface::cellml_api::DOMModelLoader,
                       cbs->modelLoader());

    try {
        RETURN_INTO_OBJREF(model, iface::cellml_api::Model,
                           ml->loadFromURL(L"http://www.cellml.org/models/beeler_reuter_1977_version04/download"));

        RETURN_INTO_WSTRING(cmid, model->cmetaId());

        printf("Model's cmeta:id is %S\n", cmid.c_str());
    } catch (iface::cellml_api::CellMLException& e) {
        RETURN_INTO_WSTRING(msg, ml->lastErrorMessage());

        printf("Got a CellML Exception loading a model. Error was %S\n",
               msg.c_str());

        return 1;
    }

    return 0;
}
void
CellMLEventsTest::setUp()
{
  mGlycolysis = NULL;
  mBootstrap = CreateCellMLBootstrap();
  mModelLoader = mBootstrap->modelLoader();
  mGlycolysis =
    mModelLoader->loadFromURL
    (BASE_DIRECTORY L"glycolysis_pathway_1997.xml");
  QUERY_INTERFACE(mGlyET, mGlycolysis, events::EventTarget);
}
Пример #8
0
bool CellmlFile::doLoad(const QString &pFileName, const QString &pFileContents,
                        ObjRef<iface::cellml_api::Model> *pModel,
                        CellmlFileIssues &pIssues)
{
    // Make sure that pIssues is empty

    pIssues.clear();

    // Get a bootstrap object and its model loader

    ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();

    // Try to create the model

    try {
        if (pFileContents.isEmpty())
            *pModel = modelLoader->loadFromURL(QUrl::fromPercentEncoding(QUrl::fromLocalFile(pFileName).toEncoded()).toStdWString());
        else
            *pModel = modelLoader->createFromText(pFileContents.toStdWString());
    } catch (iface::cellml_api::CellMLException &exception) {
        // Something went wrong with the loading of the model

        if (pFileContents.isEmpty()) {
            pIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                       QObject::tr("the model could not be loaded (%1)").arg(Core::formatMessage(QString::fromStdWString(exception.explanation))));
        } else {
            pIssues << CellmlFileIssue(CellmlFileIssue::Error,
                                       QObject::tr("the model could not be created (%1)").arg(Core::formatMessage(QString::fromStdWString(exception.explanation))));
        }

        return false;
    }

    // Update the base URI, should the CellML file be a remote one or its
    // contents be directly passed onto us

    Core::FileManager *fileManagerInstance = Core::FileManager::instance();
    ObjRef<iface::cellml_api::URI> baseUri = (*pModel)->xmlBase();

    if (fileManagerInstance->isRemote(pFileName)) {
        // We are dealing with a remote file, so its XML base value should point
        // to its remote location

        baseUri->asText(fileManagerInstance->url(pFileName).toStdWString());
    } else if (!pFileContents.isEmpty()) {
        // We are dealing with a file which contents was directly passed onto
        // us, so its XML base value should point to its actual location

        baseUri->asText(pFileName.toStdWString());
    }

    return true;
}
Пример #9
0
void Tests::basicTests()
{
    // Some very basic tests to make sure that we have access to the CellML API

    // Get a bootstrap object and its model loader

    ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();

    QVERIFY(cellmlBootstrap);
    QVERIFY(modelLoader);

    // Create a CellML 1.0 model

    ObjRef<iface::cellml_api::Model> cellml10Model = cellmlBootstrap->createModel(L"1.0");

    QVERIFY(cellml10Model);

    // Create a CellML 1.1 model

    ObjRef<iface::cellml_api::Model> cellml11Model = cellmlBootstrap->createModel(L"1.1");

    QVERIFY(cellml11Model);

    // Create an invalid CellML model

    ObjRef<iface::cellml_api::Model> invalidCellmlModel;

    try {
        invalidCellmlModel = cellmlBootstrap->createModel(L"xxx");
    } catch (...) {
        QVERIFY(!invalidCellmlModel);
    }

    // Load an existing model

    ObjRef<iface::cellml_api::Model> existingModel = modelLoader->loadFromURL(QUrl::fromPercentEncoding(QUrl::fromLocalFile(QFileInfo(OpenCOR::fileName("models/noble_model_1962.cellml")).canonicalFilePath()).toEncoded()).toStdWString());

    QVERIFY(existingModel);

    QCOMPARE(QString::fromStdWString(existingModel->name()), QString("noble_model_1962"));
    QCOMPARE(QString::fromStdWString(existingModel->cellmlVersion()), QString("1.0"));

    // Load a non-existing model

    ObjRef<iface::cellml_api::Model> nonExistingModel;

    try {
        nonExistingModel = modelLoader->loadFromURL(L"xxx");
    } catch (...) {
        QVERIFY(!nonExistingModel);
    }
}
Пример #10
0
bool CellmlFileManager::canLoadFileContents(const QString &pFileContents) const
{
    // Try to load the CellML file contents

    ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
    ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();
    ObjRef<iface::cellml_api::Model> model;

    try {
        model = modelLoader->createFromText(pFileContents.toStdWString());

        return true;
    } catch (iface::cellml_api::CellMLException &) {
        return false;
    }
}
void
AnnoToolsTest::testObjectAnnotation()
{
  iface::cellml_api::CellMLBootstrap* bs = CreateCellMLBootstrap();
  iface::cellml_api::DOMModelLoader* ml = bs->modelLoader();
  bs->release_ref();
  iface::cellml_api::Model* m =
    ml->loadFromURL(BASE_DIRECTORY L"Ach_cascade_1995.xml");
  
  CPPUNIT_ASSERT_NO_THROW(mAS->setObjectAnnotation(m, L"theloader", ml));

  iface::XPCOM::IObject* oa = mAS->getObjectAnnotation(m, L"theloader");
  {
    CPPUNIT_ASSERT(oa);
    std::string o1 = oa->objid();
    std::string o2 = ml->objid();
    CPPUNIT_ASSERT(o1 == o2);
  }
  oa->release_ref();

  oa = mAS->getObjectAnnotationWithDefault(m, L"theloader", NULL);
  {
    CPPUNIT_ASSERT(oa);
    std::string o1 = oa->objid();
    std::string o2 = ml->objid();
    CPPUNIT_ASSERT(o1 == o2);
  }
  oa->release_ref();
  oa = mAS->getObjectAnnotationWithDefault(m, L"theloaderno", NULL);
  CPPUNIT_ASSERT(!oa);

  std::wstring fstr = mAS->prefixURI();
  fstr += L"theloader";

  oa = m->getUserData(fstr.c_str());
  CPPUNIT_ASSERT(oa);
  oa->release_ref();

  mAS->release_ref();
  mAS = NULL;
  
  CPPUNIT_ASSERT_THROW(oa = m->getUserData(fstr.c_str()), iface::cellml_api::CellMLException);

  ml->release_ref();
  m->release_ref();
}
Пример #12
0
bool isCellmlFile(const QString &pFileName)
{
    // If the given file is already managed by our CellML file manager, then we
    // consider that it's still a CellML file (even though it may not be a
    // CellML file anymore after having been edited and saved, but in this case
    // it's good to keep considering the file as a CellML file, so that the user
    // can continue editing it for example)

    QString nativeFileName = Core::nativeCanonicalFileName(pFileName);

    if (CellMLSupport::CellmlFileManager::instance()->cellmlFile(nativeFileName))
        return true;

    // The given file is not managed by our CellML file manager, so check
    // whether it's a new file and, if so, consider it as a CellML file

    if (Core::FileManager::instance()->isNew(nativeFileName))
        return true;

    // Check whether we are dealing with an empty file or a file that contains
    // spaces of sorts and, if not, whether we can load it using the CellML API

    QString fileContents;

    if (Core::readTextFromFile(nativeFileName, fileContents)) {
        if (fileContents.trimmed().isEmpty())
            return true;

        ObjRef<iface::cellml_api::CellMLBootstrap> cellmlBootstrap = CreateCellMLBootstrap();
        ObjRef<iface::cellml_api::DOMModelLoader> modelLoader = cellmlBootstrap->modelLoader();
        ObjRef<iface::cellml_api::Model> model;

        try {
            model = modelLoader->createFromText(fileContents.toStdWString());

            return true;
        } catch (iface::cellml_api::CellMLException &) {
            return false;
        }
    } else {
        return false;
    }
}
already_AddRefd<iface::cellml_services::DictionaryGenerator>
CDA_CeLEDSBootstrap::createDictGeneratorFromText(const std::wstring& XMLText)
  throw(std::exception&)
{
  mLoadError = L"";
  RETURN_INTO_OBJREF(cb, iface::cellml_api::CellMLBootstrap,
                     CreateCellMLBootstrap());
  RETURN_INTO_OBJREF(URLLoader, iface::cellml_api::DOMURLLoader,
                     cb->localURLLoader());

  try
  {
    RETURN_INTO_OBJREF(langDoc, iface::dom::Document,
                       URLLoader->loadDocumentFromText(XMLText));
    return new CDA_DictionaryGenerator(langDoc);
  }
  catch (...)
  {
    RETURN_INTO_WSTRING(lem, URLLoader->lastErrorMessage());
    mLoadError = lem;
    return NULL;
  }
}
Пример #14
0
void
MaLaESTest::testMaLaESObject()
{
  iface::cellml_services::MaLaESTransform* mt =
    mMaLaESBootstrap->compileTransformer
    (
L"opengroup: (\r\n"
L"closegroup: )\r\n"
L"abs: #prec[H]fabs(#expr1)\r\n"
L"and: #prec[20]#exprs[&&]\r\n"
L"arccos: #prec[H]acos(#expr1)\r\n"
L"arccosh: #prec[H]acosh(#expr1)\r\n"
L"arccot: #prec[1000(900)]atan(1.0/#expr1)\r\n"
L"arccoth: #prec[1000(900)]atanh(1.0/#expr1)\r\n"
L"arccsc: #prec[1000(900)]asin(1/#expr1)\r\n"
L"arccsch: #prec[1000(900)]asinh(1/#expr1)\r\n"
L"arcsec: #prec[1000(900)]acos(1/#expr1)\r\n"
L"arcsech: #prec[1000(900)]acosh(1/#expr1)\r\n"
L"arcsin: #prec[H]asin(#expr1)\r\n"
L"arcsinh: #prec[H]asinh(#expr1)\r\n"
L"arctan: #prec[H]atan(#expr1)\r\n"
L"arctanh: #prec[H]atanh(#expr1)\r\n"
L"ceiling: #prec[H]ceil(#expr1)\r\n"
L"cos: #prec[H]cos(#expr1)\r\n"
L"cosh: #prec[H]cosh(#expr1)\r\n"
L"cot: #prec[900(0)]1.0/tan(#expr1)\r\n"
L"coth: #prec[900(0)]1.0/tanh(#expr1)\r\n"
L"csc: #prec[900(0)]1.0/sin(#expr1)\r\n"
L"csch: #prec[900(0)]1.0/sinh(#expr1)\r\n"
L"diff: #lookupDiffVariable\r\n"
L"divide: #prec[900]#expr1/#expr2\r\n"
L"eq: #prec[30]#exprs[==]\r\n"
L"exp: #prec[H]exp(#expr1)\r\n"
L"factorial: #prec[H]factorial(#expr1)\r\n"
L"factorof: #prec[30(900)]#expr1 % #expr2 == 0\r\n"
L"floor: #prec[H]floor(#expr1)\r\n"
L"gcd: #prec[H]gcd_multi(#count, #exprs[, ])\r\n"
L"geq: #prec[30]#exprs[>=]\r\n"
L"gt: #prec[30]#exprs[>]\r\n"
L"implies: #prec[10(950)]!#expr1 || #expr2\r\n"
L"int: #prec[H]defint(func#unique1, BOUND, CONSTANTS, RATES, VARIABLES, #bvarIndex)#supplement double func#unique1(double* BOUND, double* CONSTANTS, double* RATES, double* VARIABLES) { return #expr1; }\r\n"
L"lcm: #prec[H]lcm_multi(#count, #exprs[, ])\r\n"
L"leq: #prec[30]#exprs[<=]\r\n"
L"ln: #prec[H]log(#expr1)\r\n"
L"log: #prec[H]arbitrary_log(#expr1, #logbase)\r\n"
L"lt: #prec[30]#exprs[<]\r\n"
L"max: #prec[H]multi_max(#count, #exprs[, ])\r\n"
L"min: #prec[H]multi_min(#count, #exprs[, ])\r\n"
L"minus: #prec[500]#expr1 - #expr2\r\n"
L"neq: #prec[30]#expr1 != #expr2\r\n"
L"not: #prec[950]!#expr1\r\n"
L"or: #prec[10]#exprs[||]\r\n"
L"plus: #prec[500]#exprs[+]\r\n"
L"power: #prec[H]pow(#expr1, #expr2)\r\n"
L"quotient: #prec[900(0)](int)(#expr1) / (int)(#expr2)\r\n"
L"rem: #prec[900(0)](int)(#expr1) % (int)(#expr2)\r\n"
L"root: #prec[1000(900)]pow(#expr1, 1.0 / #degree)\r\n"
L"sec: #prec[900(0)]1.0 / cos(#expr1)\r\n"
L"sech: #prec[900(0)]1.0 / cosh(#expr1)\r\n"
L"sin: #prec[H]sin(#expr1)\r\n"
L"sinh: #prec[H]sinh(#expr1)\r\n"
L"tan: #prec[H]tan(#expr1)\r\n"
L"tanh: #prec[H]tanh(#expr1)\r\n"
L"times: #prec[900]#exprs[*]\r\n"
L"unary_minus: #prec[950]-#expr1\r\n"
L"units_conversion: #prec[500(900)]#expr1*#expr2 + #expr3\r\n"
L"units_conversion_offset: #prec[500]#expr1+#expr2\r\n"
L"units_conversion_factor: #prec[900]#expr1*#expr2\r\n"
L"xor: #prec[25(30)](#expr1 != 0) ^ (#expr2 != 0)\r\n"
    );

  iface::cellml_api::CellMLBootstrap* cellbs = CreateCellMLBootstrap();
  iface::cellml_api::DOMModelLoader* ml = cellbs->modelLoader();
  cellbs->release_ref();

  iface::cellml_api::Model* m = ml->loadFromURL
    (BASE_DIRECTORY L"glycolysis_pathway_1997.xml");
  ml->release_ref();

  iface::cellml_services::CeVASBootstrap* cb =
    CreateCeVASBootstrap();

  iface::cellml_services::CeVAS* cev = cb->createCeVASForModel(m);
  cb->release_ref();

  iface::cellml_services::CUSESBootstrap* cub = CreateCUSESBootstrap();
  iface::cellml_services::CUSES* cu =
    cub->createCUSESForModel(m, false);
  cub->release_ref();

  iface::cellml_services::AnnotationToolService* ats =
    CreateAnnotationToolService();
  iface::cellml_services::AnnotationSet* as = ats->createAnnotationSet();
  ats->release_ref();

  iface::cellml_api::CellMLComponentSet* ccs = m->localComponents();
  iface::cellml_api::CellMLComponent * glcC, * gts, * gp;
  glcC = ccs->getComponent(L"Glc_C");
  gts = ccs->getComponent(L"glucose_transport_system");
  gp = ccs->getComponent(L"glucose_phosphorylation");
  ccs->release_ref();

  iface::cellml_api::CellMLVariableSet* vs = glcC->variables();
  iface::cellml_api::CellMLVariable * vglcC, * vdelta_Glc_C_rxn1, * vdelta_Glc_C_rxn2;
  vglcC = vs->getVariable(L"Glc_C");
  vs->release_ref();
  vs = gts->variables();
  vdelta_Glc_C_rxn1 = vs->getVariable(L"delta_Glc_C_rxn1");
  vs->release_ref();
  vs = gp->variables();
  vdelta_Glc_C_rxn2 = vs->getVariable(L"delta_Glc_C_rxn2");
  vs->release_ref();

  as->setStringAnnotation(vglcC, L"expression_d1",
                          L"first_derivative_of_glcC");
  as->setStringAnnotation(vglcC, L"expression",
                          L"glcC");
  as->setStringAnnotation(vdelta_Glc_C_rxn1, L"expression",
                          L"delta_Glc_C_rxn1");
  as->setStringAnnotation(vdelta_Glc_C_rxn2, L"expression",
                          L"delta_Glc_C_rxn2");

  iface::cellml_api::MathList* matl =
    glcC->math();
  iface::cellml_api::MathMLElementIterator* mei = matl->iterate();
  iface::mathml_dom::MathMLElement* math = mei->next();
  DECLARE_QUERY_INTERFACE(mmel, math, mathml_dom::MathMLMathElement);
  math->release_ref();
  mei->release_ref();
  matl->release_ref();
  iface::mathml_dom::MathMLElement* expr = mmel->getArgument(1);
  mmel->release_ref();

  iface::cellml_services::MaLaESResult* mr =
    mt->transform(cev, cu, as, expr, glcC, NULL, NULL, 0);

  CPPUNIT_ASSERT(mr);

  std::wstring str = mr->compileErrors();
  CPPUNIT_ASSERT_EQUAL(std::wstring(L""), str);

  str = mr->expression();
  CPPUNIT_ASSERT_EQUAL(std::wstring(L"first_derivative_of_glcC*0.00100000==1000.00*(1000.00*(delta_Glc_C_rxn1*0.00100000)+delta_Glc_C_rxn2)"), str);

  uint32_t l = mr->supplementariesLength();
  CPPUNIT_ASSERT_EQUAL(0, (int)l);

  std::set<iface::cellml_api::CellMLVariable*> invVars;
  iface::cellml_api::CellMLVariableIterator* cvi = mr->iterateInvolvedVariables();
  iface::cellml_api::CellMLVariable* var;
  while ((var = cvi->nextVariable()) != NULL)
  {
    CPPUNIT_ASSERT_EQUAL(0, (int)invVars.count(var));
    invVars.insert(var);
  }
  cvi->release_ref();

  std::set<iface::cellml_api::CellMLVariable*>::iterator invVarsI;

  // Time is included in the count as well.
  CPPUNIT_ASSERT_EQUAL(4, (int)invVars.size());
  CPPUNIT_ASSERT_EQUAL(1, (int)invVars.count(vglcC));
  CPPUNIT_ASSERT_EQUAL(1, (int)invVars.count(vdelta_Glc_C_rxn1));
  CPPUNIT_ASSERT_EQUAL(1, (int)invVars.count(vdelta_Glc_C_rxn2));
  for (invVarsI = invVars.begin(); invVarsI != invVars.end(); invVarsI++)
    (*invVarsI)->release_ref();

  cvi = mr->iterateBoundVariables();
  var = cvi->nextVariable();
  CPPUNIT_ASSERT(var != vglcC);
  var->release_ref();
  CPPUNIT_ASSERT(!cvi->nextVariable().getPointer());
  cvi->release_ref();

  CPPUNIT_ASSERT_EQUAL(1, (int)mr->getDiffDegree(vglcC));
  CPPUNIT_ASSERT(!mr->involvesExternalCode());

  mr->release_ref();
  expr->release_ref();
  vglcC->release_ref();
  vdelta_Glc_C_rxn1->release_ref();
  vdelta_Glc_C_rxn2->release_ref();
  gts->release_ref();
  gp->release_ref();
  glcC->release_ref();
  as->release_ref();
  cu->release_ref();
  cev->release_ref();
  mt->release_ref();
  m->release_ref();
}
Пример #15
0
CellMLModelDefinition::CellMLModelDefinition(const char* url) :
		mURL(url)
{
  //mCompileCommand = "gcc -fPIC -O3 -shared -x c -o";
  mCompileCommand = "gcc -fPIC -g -shared -x c -o";
  mTmpDirExists = false;
  mCodeFileExists = false;
  mDsoFileExists = false;
  mSaveTempFiles = false;
  mInstantiated = false;
  nBound = -1;
  nRates = -1;
  nAlgebraic = -1;
  nConstants = -1;
  mNumberOfWantedVariables = 0;
  mNumberOfKnownVariables = 0;
  mNumberOfIndependentVariables = 0;
  mStateCounter = 0;
  mIntermediateCounter = 0;
  mParameterCounter = 0;
  mModel = NULL;
  mCodeInformation = NULL;
  mAnnotations = NULL;
  std::cout << "Creating CellMLModelDefinition from the URL: " 
	    << url << std::endl;
  if (! mURL.empty())
  {
    //std::cout << "Have a valid simulation description." << std::endl;
    //std::cout << "  CellML model URI: " << mURL.c_str() << std::endl;
    RETURN_INTO_WSTRING(URL,string2wstring(mURL.c_str()));
    RETURN_INTO_OBJREF(cb,iface::cellml_api::CellMLBootstrap,
      CreateCellMLBootstrap());
    RETURN_INTO_OBJREF(ml,iface::cellml_api::ModelLoader,cb->modelLoader());
    iface::cellml_api::Model* model = (iface::cellml_api::Model*)NULL;
    try
    {
      model = ml->loadFromURL(URL.c_str());
      model->fullyInstantiateImports();
      mModel = static_cast<void*>(model);
      // create the annotation set
      RETURN_INTO_OBJREF(ats,iface::cellml_services::AnnotationToolService,CreateAnnotationToolService());
      iface::cellml_services::AnnotationSet* as = ats->createAnnotationSet();
      mAnnotations = static_cast<void*>(as);
      // make sure we can generate code and get the initial code information
      RETURN_INTO_OBJREF(cgb,iface::cellml_services::CodeGeneratorBootstrap,
        CreateCodeGeneratorBootstrap());
      RETURN_INTO_OBJREF(cg,iface::cellml_services::CodeGenerator,
        cgb->createCodeGenerator());
      try
      {
        RETURN_INTO_OBJREF(cci,iface::cellml_services::CodeInformation,
          cg->generateCode(model));
        // need to keep a handle on the code information
        cci->add_ref();
        mCodeInformation = static_cast<void*>(cci);
        // and add all state variables as wanted and the variable of integration as known
        RETURN_INTO_OBJREF(cti,iface::cellml_services::ComputationTargetIterator,cci->iterateTargets());
        while(1)
        {
          RETURN_INTO_OBJREF(ct,iface::cellml_services::ComputationTarget,cti->nextComputationTarget());
          if (ct == NULL) break;
          if (ct->type() == iface::cellml_services::STATE_VARIABLE)
          {
            as->setStringAnnotation(ct->variable(),L"flag",L"STATE");
            as->setStringAnnotation(ct->variable(),L"array",L"OC_STATE");
            as->setStringAnnotation(ct->variable(),L"array_index",formatNumber(mStateCounter).c_str());
            mStateCounter++;
          }
          else if (ct->type() == iface::cellml_services::VARIABLE_OF_INTEGRATION)
          {
            as->setStringAnnotation(ct->variable(),L"flag",L"INDEPENDENT");
            mNumberOfIndependentVariables++;
          }
          else if (ct->degree() > 0)
          {
            //as->setStringAnnotation(ct->variable(),L"flag-degree",L"WANTED");
            //mNumberOfWantedVariables++;
          }
        }
      }
      catch (...)
      {
        std::wcerr << L"Error generating the code information for the model" << std::endl;
        mCodeInformation = static_cast<void*>(NULL);
      }
    }
    catch (...)
    {
      std::wcerr << L"Error loading model URL: " << URL.c_str() << std::endl;
      mModel = static_cast<void*>(NULL);
    }
  }
}
int
main(int argc, char** argv)
{
  // Get the URLs from which to load the model and the 
  // the language definition file
  if (argc != 3)
  {
    printf("Usage: testCeLEDS modelURL languageDefinitionURL\n");
    return -1;
  }

  wchar_t* modelURL;
  size_t l = strlen(argv[1]);
  modelURL = new wchar_t[l + 1];
  memset(modelURL, 0, (l + 1) * sizeof(wchar_t));
  const char* mbrurl = argv[1];
  mbsrtowcs(modelURL, &mbrurl, l, NULL);

  wchar_t* languageURL;
  l = strlen(argv[2]);
  languageURL = new wchar_t[l + 1];
  memset(languageURL, 0, (l + 1) * sizeof(wchar_t));
  const char* lbrurl = argv[2];
  mbsrtowcs(languageURL, &lbrurl, l, NULL);

  RETURN_INTO_OBJREF(cb, iface::cellml_api::CellMLBootstrap,
    CreateCellMLBootstrap());

  RETURN_INTO_OBJREF(ml, iface::cellml_api::ModelLoader,
    cb->modelLoader());

  ObjRef<iface::cellml_api::Model> mod;
  try
  {
    mod = already_AddRefd<iface::cellml_api::Model>(ml->loadFromURL(modelURL));
    if (mod == NULL)
      throw L"";
  }
  catch (...)
  {
    printf("Error loading model URL.\n");
    delete [] modelURL;
    delete [] languageURL;
    return -1;
  }

  delete [] modelURL;

  RETURN_INTO_OBJREF(ceb, iface::cellml_services::CeLEDSExporterBootstrap,
    CreateCeLEDSExporterBootstrap());
  RETURN_INTO_OBJREF(ce, iface::cellml_services::CodeExporter,
      ceb->createExporter(languageURL));

  RETURN_INTO_WSTRING(le, ceb->loadError());
  if (!le.empty()) {
    wprintf(L"Could not load language definition file:\n");
    wprintf(L"    %ls\n",le.c_str());
    return -1;
  }
  delete [] languageURL;

  std::wstring code = ce->generateCode(mod);
  wprintf(L"%ls", code.c_str());

  return 0;
}
Пример #17
0
int
main(int argc, char** argv)
{
  // Get the URL from which to load the model...
  if (argc < 2)
  {
    printf("Usage: CellML2C modelURL\n");
    return -1;
  }

  uint32_t usenames = 0, useida = 0;

  for (int32_t i = 2; i < argc; i++)
  {
    if (!strcmp(argv[i], "usenames"))
      usenames = 1;
    else if (!strcmp(argv[i], "useida"))
      useida = 1;
  }

  wchar_t* URL;
  size_t l = strlen(argv[1]);
  URL = new wchar_t[l + 1];
  memset(URL, 0, (l + 1) * sizeof(wchar_t));
  const char* mbrurl = argv[1];
  mbsrtowcs(URL, &mbrurl, l, NULL);

  iface::cellml_api::CellMLBootstrap* cb =
    CreateCellMLBootstrap();

  iface::cellml_api::ModelLoader* ml =
    cb->modelLoader();
  cb->release_ref();

  iface::cellml_api::Model* mod;
  try
  {
    mod = ml->loadFromURL(URL);
  }
  catch (...)
  {
    printf("Error loading model URL.\n");
    // Well, a leak on exit wouldn't be so bad, but someone might reuse this
    // code, so...
    delete [] URL;
    ml->release_ref();
    return -1;
  }

  ml->release_ref();
  delete [] URL;

  mod->fullyInstantiateImports();

  iface::cellml_services::CodeGeneratorBootstrap* cgb =
    CreateCodeGeneratorBootstrap();
  iface::cellml_services::CodeGenerator* cg;
  iface::cellml_services::IDACodeGenerator* icg;

  if (useida)
    cg = icg = cgb->createIDACodeGenerator();
  else
    cg = cgb->createCodeGenerator();
  cgb->release_ref();

  if (usenames)
    doNameAnnotations(mod, cg);

  iface::cellml_services::CodeInformation* cci = NULL;
  try
  {
    cci = cg->generateCode(mod);
  }
  catch (iface::cellml_api::CellMLException&)
  {
    printf("Caught a CellMLException while generating code.\n");
    cg->release_ref();
    mod->release_ref();
    return -1;
  }
  catch (...)
  {
    printf("Unexpected exception calling generateCode!\n");
    // this is a leak, but it should also never happen :)
    return -1;
  }
  mod->release_ref();
  cg->release_ref();

  std::wstring m = cci->errorMessage();
  if (m != L"")
  {
    printf("Error generating code: %S\n", m.c_str());
    cci->release_ref();
    return -1;
  }

  // We now have the code information...
  WriteCode(cci, useida);
  cci->release_ref();

  return 0;
}
Пример #18
0
int
main(int argc, char** argv)
{
  if (argc < 5)
  {
    printf("Usage: CustomGen modelURL wanted known unwanted\n"
           "Each of wanted, known, and unwanted is a comma separated list.\n"
           "Use a single comma to specify an empty list.\n"
           "Each entry in the list should be in the form:\n"
           "  component/variable:degreeOfDerivative\n");
    return -1;
  }

  std::wstring URL(MakeWideString(argv[1]));

  std::set<std::pair<std::pair<std::wstring, std::wstring>, uint32_t> > wanted, known, unwanted;

  TargetDescriptionToSet(argv[2], wanted);
  TargetDescriptionToSet(argv[3], known);
  TargetDescriptionToSet(argv[4], unwanted);

  RETURN_INTO_OBJREF(cb, iface::cellml_api::CellMLBootstrap,
                     CreateCellMLBootstrap());
  RETURN_INTO_OBJREF(ml, iface::cellml_api::ModelLoader,
                     cb->modelLoader());
  // These assignments to NULL are only here in the test code to help look for
  // memory errors by freeing things early... in production code, they wouldn't
  // be necessary.
  cb = NULL;

  ObjRef<iface::cellml_api::Model> mod;
  try
  {
    mod = already_AddRefd<iface::cellml_api::Model>(ml->loadFromURL(URL.c_str()));
  }
  catch (...)
  {
    printf("Error loading model URL.\n");
    return -1;
  }

  RETURN_INTO_OBJREF(cgb, iface::cellml_services::CodeGeneratorBootstrap,
                     CreateCodeGeneratorBootstrap()
                    );
  RETURN_INTO_OBJREF(cg, iface::cellml_services::CodeGenerator,
                     cgb->createCodeGenerator());
  cgb = NULL;

  cg->stateVariableNamePattern(L"VARS[%]");
  RETURN_INTO_OBJREF(ccg, iface::cellml_services::CustomGenerator,
                     cg->createCustomGenerator(mod));
  cg = NULL;
  mod = NULL;
  RETURN_INTO_OBJREF(cti, iface::cellml_services::ComputationTargetIterator,
                     ccg->iterateTargets());
  while (true)
  {
    RETURN_INTO_OBJREF(ct, iface::cellml_services::ComputationTarget,
                       cti->nextComputationTarget());
    if (ct == NULL)
      break;

    RETURN_INTO_OBJREF(cv, iface::cellml_api::CellMLVariable, ct->variable());
    RETURN_INTO_WSTRING(compname, cv->componentName());
    RETURN_INTO_WSTRING(varname, cv->name());
    std::pair<std::pair<std::wstring, std::wstring>, uint32_t> p
      (std::pair<std::wstring, std::wstring>(compname, varname), ct->degree());
    if (wanted.count(p))
      ccg->requestComputation(ct);
    else if (known.count(p))
      ccg->markAsKnown(ct);
    else if (unwanted.count(p))
      ccg->markAsUnwanted(ct);
  }
  cti = NULL;

  RETURN_INTO_OBJREF(cci, iface::cellml_services::CustomCodeInformation,
                     ccg->generateCode());
  ccg = NULL;
  printf("Constraint level = ");
  switch (cci->constraintLevel())
  {
  case iface::cellml_services::UNDERCONSTRAINED:
    printf("UNDERCONSTRAINED\n");
    break;
  case iface::cellml_services::UNSUITABLY_CONSTRAINED:
    printf("UNSUITABLY_CONSTRAINED\n");
    break;
  case iface::cellml_services::OVERCONSTRAINED:
    printf("OVERCONSTRAINED\n");
    break;
  case iface::cellml_services::CORRECTLY_CONSTRAINED:
    printf("CORRECTLY_CONSTRAINED\n");
    break;
  default:
    printf("Unkown value\n");
  }
  printf("Index count: %u\n", cci->indexCount());
  cti = already_AddRefd<iface::cellml_services::ComputationTargetIterator>(cci->iterateTargets());
  while (true)
  {
    RETURN_INTO_OBJREF(ct, iface::cellml_services::ComputationTarget,
                       cti->nextComputationTarget());
    if (ct == NULL)
      break;

    RETURN_INTO_OBJREF(cv, iface::cellml_api::CellMLVariable, ct->variable());
    RETURN_INTO_WSTRING(compname, cv->componentName());
    RETURN_INTO_WSTRING(varname, cv->name());
    printf("* Computation target %S/%S:%u:\n", compname.c_str(), varname.c_str(),
           ct->degree());
    printf("  => Type = ");
    switch (ct->type())
    {
    case iface::cellml_services::VARIABLE_OF_INTEGRATION:
      printf("VARIABLE_OF_INTEGRATION - was marked as independent.\n");
      break;
    case iface::cellml_services::CONSTANT:
      printf("CONSTANT - this should not happen!\n");
      break;
    case iface::cellml_services::STATE_VARIABLE:
      printf("STATE_VARIABLE - was requested, and is available.\n");
      break;
    case iface::cellml_services::ALGEBRAIC:
      printf("ALGEBRAIC - is used as an intermediate.\n");
      break;
    case iface::cellml_services::FLOATING:
      printf("FLOATING - unused and not requested.\n");
      break;
    case iface::cellml_services::LOCALLY_BOUND:
      printf("LOCALLY_BOUND - locally bound in expressions only.\n");
      break;
    case iface::cellml_services::PSEUDOSTATE_VARIABLE:
      printf("PSEUDOSTATE_VARIABLE - target was requested, but could "
             "not be computed from the independent variables and model.\n");
      break;
    default:
      printf("Unknown type!\n");
    }
    RETURN_INTO_WSTRING(targname, ct->name());
    printf("  => Name = %S\n", targname.c_str());
    printf("  => Index = %u\n", ct->assignedIndex());
  }
  // To do: Print output from cci->iterateTargets();
  RETURN_INTO_WSTRING(functionsString, cci->functionsString());
  printf("Functions: %S\n", functionsString.c_str());
  RETURN_INTO_WSTRING(code, cci->generatedCode());
  printf("Code: %S\n", code.c_str());
}
Пример #19
0
int main(int argc, char** argv)
{
  try
  {
    std::wstring modelURL
      (L"http://models.cellml.org/workspace/hodgkin_huxley_1952/@@rawfile/949cd4d3/hodgkin_huxley_1952.cellml");

    // Create a CellML Bootstrap and a model loader.
    ObjRef<iface::cellml_api::CellMLBootstrap> bootstrap(CreateCellMLBootstrap());
    ObjRef<iface::cellml_api::DOMModelLoader> loader(bootstrap->modelLoader());

    // Load a CellML model.
    ObjRef<iface::cellml_api::Model> hhModel
      (loader->loadFromURL(modelURL));

    // Request a RDF/API capable RDF representation...
    ObjRef<iface::cellml_api::RDFRepresentation> rr(hhModel->getRDFRepresentation(L"http://www.cellml.org/RDF/API"));
    ObjRef<iface::rdf_api::RDFAPIRepresentation> rrHH(QueryInterface(rr));

    // Retrieve the DataSource. Note: Changes to the data source are not pushed back
    // to the model until the source attribute is set on the rrHH again.
    ObjRef<iface::rdf_api::DataSource> dsHH(rrHH->source());

    // Get the resource corresponding to the cmeta:id on the model. Note that
    // cmetaId can return the empty string, which you should check for in
    // production code, if there is no cmeta:id
    ObjRef<iface::rdf_api::URIReference> hhModelRef
      (dsHH->getURIReference(bootstrap->makeURLAbsolute(modelURL, L"#" + hhModel->cmetaId())));

#ifdef DUMP_ALL_TRIPLES_FIRST
    {
      ObjRef<iface::rdf_api::TripleSet> ts(dsHH->getAllTriples());
      ObjRef<iface::rdf_api::TripleEnumerator> te(ts->enumerateTriples());
      while (true)
      {
        ObjRef<iface::rdf_api::Triple> t(te->getNextTriple());
        if (t == NULL)
          break;

        displayTriple(t);
      }
    }
#endif

    ObjRef<iface::rdf_api::URIReference> pmid(dsHH->getURIReference(L"http://www.cellml.org/bqs/1.0#Pubmed_id"));
    // Note: Calls like this could fail with an exception if there was no pubmed ID - production code should check.
    ObjRef<iface::rdf_api::Triple> t(hhModelRef->getTripleOutOfByPredicate(pmid));
    ObjRef<iface::rdf_api::Node> n(t->object());
    ObjRef<iface::rdf_api::Literal> lPMID(QueryInterface(n));
    if (lPMID != NULL) // It will be null if for some reason it isn't a literal...
      std::wcout << L"Model pubmed ID: " << lPMID->lexicalForm() << std::endl;

    ObjRef<iface::rdf_api::URIReference> bqsReference(dsHH->getURIReference(L"http://www.cellml.org/bqs/1.0#reference"));
    ObjRef<iface::rdf_api::TripleSet> ts(hhModelRef->getTriplesOutOfByPredicate(bqsReference));
    ObjRef<iface::rdf_api::TripleEnumerator> te(ts->enumerateTriples());
    while (true)
    {
      t = te->getNextTriple();
      if (t == NULL) break;
      ObjRef<iface::rdf_api::Resource> r(QueryInterface(t->object()));
      if (r == NULL) continue;
      std::wcout << L"Found a resource description:" << std::endl;
      try
      {
        t = r->getTripleOutOfByPredicate(pmid);
        n = t->object();
        lPMID = QueryInterface(n);
        if (lPMID != NULL)
          std::wcout << L"  Reference pubmed ID: " << lPMID->lexicalForm() << std::endl;
      }
      catch(...) {}
      // Look up the subject...
      ObjRef<iface::rdf_api::URIReference> subject(dsHH->getURIReference(L"http://purl.org/dc/elements/1.1/subject"));
      ts = r->getTriplesOutOfByPredicate(subject);
      ObjRef<iface::rdf_api::TripleEnumerator> te2 = ts->enumerateTriples();
      while (true)
      {
        t = te2->getNextTriple();
        if (t == NULL)
          break;
        n = t->object();
        r = QueryInterface(n);
        if (r == NULL)
          continue;
        std::wcout << "  Subject:" << std::endl;
        ObjRef<iface::rdf_api::URIReference> subjectType(dsHH->getURIReference(L"http://www.cellml.org/bqs/1.0#subject_type"));
        ts = r->getTriplesOutOfByPredicate(subjectType);
        ObjRef<iface::rdf_api::TripleEnumerator> te3 = ts->enumerateTriples();
        t = te3->getNextTriple();
        if (t)
        {
          n = t->object();
          ObjRef<iface::rdf_api::Literal> l(QueryInterface(n));
          std::wcout << "    Subject Type=" << l->lexicalForm() << std::endl;
        }
        ObjRef<iface::rdf_api::URIReference> value(dsHH->getURIReference(L"http://www.w3.org/1999/02/22-rdf-syntax-ns#value"));
        ts = r->getTriplesOutOfByPredicate(value);
        te3 = ts->enumerateTriples();

        t = te3->getNextTriple();
        if (t == NULL) continue;
        n = t->object();
        r = QueryInterface(n);
        if (r == NULL) continue;
        ObjRef<iface::rdf_api::Container> cont(r->correspondingContainer());

        // Add a new entry to the container first...
        ObjRef<iface::rdf_api::PlainLiteral> newPL(dsHH->getPlainLiteral(L"Newly created label", L"en"));
        cont->appendChild(newPL);

        // Delete any labels that match 'giant axon'...
        ObjRef<iface::rdf_api::NodeIterator> ni(cont->iterateChildren());
        while (true)
        {
          ObjRef<iface::rdf_api::Node> n(ni->getNextNode());
          if (n == NULL)
            break;
          ObjRef<iface::rdf_api::Literal> l(QueryInterface(n));
          if (l == NULL)
            continue;
          if (l->lexicalForm() == L"giant axon")
            // The false means don't renumber immediately. This leaves the
            // container with gaps...
            cont->removeChild(l, false);
        }
        cont->renumberContainer(); // Remove the gaps.

        displayContainer(cont, L"    ");
      }
    }
  }
  catch (iface::cellml_api::CellMLException&)
  {
    std::wcout << L"A CellMLException was raised. In production code, you would normally have more "
               << L"exception handlers to work out exactly where the problem occurred. This program "
               << L"avoids that for simplicity, to make the normal control flow easier to understand. "
               << L"The most likely cause is a network problem retrieving the hardcoded model URL."
               << std::endl;
    return 1;
  }
  catch (iface::rdf_api::RDFProcessingError&)
  {
    std::wcout << L"An RDFProcessingError was raised. In production code, you would normally have more "
               << L"exception handlers to work out exactly where the problem occurred. This program "
               << L"avoids that for simplicity, to make the normal control flow easier to understand."
               << std::endl;
    return 2;
  }
  return 0;
}
void
MathMLTest::setUp()
{
  cb = CreateCellMLBootstrap();
}
int
main(int argc, char** argv)
{
  // Fetch a bootstrap object. The bootstrap object is a special 'root' object
  // from which you can get at everything else. CreateCellMLBootstrap() is a
  // C++ binding specific method, which fetches the CellMLBootstrap object.
  // It is the only non-OO method that you should ever call from the CellML
  // API.
  // ObjRef is a template defined in cellml-api-cxx-support.hpp. CreateCellMLBootstrap
  // has already_Addrefd<iface::cellml_api::CellMLBootstrap> as its return type,
  // which is the signal that a reference is added (i.e. the reference count is
  // incremented on the return value, and the caller must ensure it is decremented).
  // ObjRef will, when given an already_Addrefd argument, not increment the reference
  // count, but will decrement it when it goes out of scope. If an ObjRef is constructed
  // from a pointer or another ObjRef, it will add a reference on construction,
  // and release the reference on destruction.
  ObjRef<iface::cellml_api::CellMLBootstrap> cbs(CreateCellMLBootstrap());

  // Now would be a good time to see what methods we can call. In the
  // CellML_DOM_API source, find interfaces/CellML_APISPEC.idl.
  // This defines the interfaces you can call. Search down to find
  // this text...
  /*
  interface CellMLBootstrap
    : XPCOM::IObject
  {
    ...
   */
  // We want to load a model, so we want the modelLoader attribute. We fetch
  // the attribute like this...
  ObjRef<iface::cellml_api::DOMModelLoader> ml(cbs->modelLoader());

  // Suppose we only had a general model loader...
  ObjRef<iface::cellml_api::ModelLoader> generalModelLoader(ml);
  // if we wanted to get from this to a DOM model loader, we can't just cast,
  // because the API is designed so it can work through bridges and we might
  // need to switch to a different bridge (you can cast from an interface to a
  // parent interface in the inheritance hierarchy, but not the other way).
  // Instead, we call query_interface to ask the underlying object if it
  // supports the interface we want, and to return us a value.
  ObjRef<iface::cellml_api::DOMModelLoader> ml2(do_QueryInterface(generalModelLoader));
  // ml2 would be null if generalModelLoader didn't support DOMModelLoader.

  // Start a try, because we might get an exception...
  try
  {
    // We now have a DOMModelLoader, stored in ml. DOMModelLoader inherits from
    // ModelLoader, which defines a loadFromURL operation (check in the IDL).
    // Be warned that is a synchronous (blocking) load. In a real application,
    // you are probably better to download the file using another asynchronous
    // http library, and then creating the model from the serialised text.
    ObjRef<iface::cellml_api::Model> model(ml->loadFromURL(L"http://www.cellml.org/models/beeler_reuter_1977_version04/download"));

    // Fetch the models cmeta:id (there obviously lots of other things we could
    // do here!)
    std::wstring cmid = model->cmetaId();
    printf("Model's cmeta:id is %S\n", cmid.c_str());
  }
  // Most parts of the CellML API raise this exception. The DOM/MathML API, on the
  // other hand, raises iface::dom::DOMException.
  catch (iface::cellml_api::CellMLException&)
  {
    // Unfortunately, due to the need to support the 'lowest common
    // denominator' of functionality in our bindings, exceptions can't have
    // supplementary information (to suit XPCOM). However, many classes have
    // a way to get the last error, e.g. lastErrorMessage on ModelLoader.
    // However, threadsafety is potentially an issue with this.
    std::wstring msg = ml->lastErrorMessage();
    printf("Got a CellML Exception loading a model. Error was %S\n",
           msg.c_str());
    return 1;
  }

  return 0;
}