CellML Discussion List

Text archives Help


[cellml-discussion] cmeta:id's and the CCGS


Chronological Thread 
  • From: david.nickerson at nus.edu.sg (David Nickerson)
  • Subject: [cellml-discussion] cmeta:id's and the CCGS
  • Date: Fri, 29 Dec 2006 09:07:25 +0800

Hi Andrew,

Ideally getting a list of variables connected to each code variable from
the CCGS would be great - its really what I wanted but as you can see
from my code I could barely work out how to get a string passed through
:-) I think this has to be done in the CCGS as there is no guarantee
that the mapping from a model variable to a code variable in a
particular piece of generated code will always be the same as following
the connections in a live representation of the model.

And just to note that the comma separated list poses no problems (for
me) as you end up simply searching the complete string for a substring
that matches the entire URI of the ID you happen to be looking for. If
you wanted to further process the string then the comma might start
posing problems on splitting up the URIs and the list approach might be
beneficial.


David.

Andrew Miller wrote:
> David Nickerson wrote:
>> Hi all,
>>
>> I have been thinking about the best way to map between variables in a
>> model and variables in code generated from the model (or more
>> precisely the mapping between variables in a model and results from
>> numerical simulation of the model using the code generated by the
>> CCGS). The typical way to do anything with a particular variable in a
>> model is via the variable's cmeta:id (i.e., graph metadata).
>>
>> Using the current CCGS implementation it is fairly easy to grab the
>> original CellML variable object for each variable in the generated
>> code and from that you can get the variable's cmeta:id. However, the
>> problem is that there can be multiple variables in a model which
>> resolve to the same underlying variable in the generated code. Thus,
>> when trying to use a particular variable from a model via its cmeta:id
>> it may not appear directly in the code, and hence the simulation
>> result data.
>>
>> One way to get all the variables in a model which link to a given
>> variable in the generated code is to simply search the model looking
>> at connections and source variables, etc. to determine this
>> information. An alternate method is to provide this information
>> directly via the CCGS - which internally handles all model connections
>> in a more efficient manner.
>>
>> Following up on this I have modified the CCGS to provide a method on
>> the CCodeVariable object/interface which provides a character array
>> containing a comma separated list of all the cmeta:id's which are
>> linked to each code variable (see attached patch for current trunk
>> source). For me this works quite well and provides a means to describe
>> in the generated code all the variables in a model which are linked to
>> a given variable/array index in the generated code.
> From an API design perspective, I have a few comments:
> Why not just expose the list of variables connected to each variable
> from the CCGS? That way, the user can go through the complete list of
> all variables efficiently, and check the cmeta:id (or anything else they
> want to do) for themselves?
>
> If we are going to expose just the cmeta:id attributes, I don't think a
> comma separated list is the right approach. It should ideally be a list
> data-structure of some kind, with an iterator interface to iterate
> through the cmeta:id values. This is especially relevant given that
> RFC3986 (Uniform Resource Identifier (URI): Generic Syntax) allows ,
> characters to be present in URIs.
>
>> I'm sure the actual implementation is pretty bad, but the general idea
>> seems sound to me. What do people think? Perhaps there is already a
>> way to do this or something similar, but I couldn't find it. Or maybe
>> I'm just going about this in completely the wrong way?
> I think we do need to extend the CCGS (or alternatively, make it more
> efficient to get the connections information from the CellML API, which
> is problematic given that the API is 'live' unlike the CCGS) to support
> this.
>>
>> David.
>>
>> ------------------------------------------------------------------------
>>
>> Index: CCGS/sources/CCGSGenerator.cpp
>> ===================================================================
>> --- CCGS/sources/CCGSGenerator.cpp (revision 1014)
>> +++ CCGS/sources/CCGSGenerator.cpp (working copy)
>> @@ -993,7 +993,7 @@
>> (new CDA_CCodeVariable
>> ((*i)->GetSourceVariable(), (*i)->GetIndex(),
>> ((*i)->GetArray() == VariableInformation::DEPENDENT_AND_RATE),
>> - (*i)->GetDegree(), type
>> + (*i)->GetDegree(), type, (*i)->GetIDString()
>> ));
>> }
>> }
>> Index: CCGS/sources/VariableConnections.cpp
>> ===================================================================
>> --- CCGS/sources/VariableConnections.cpp (revision 1014)
>> +++ CCGS/sources/VariableConnections.cpp (working copy)
>> @@ -302,7 +302,17 @@
>> aMsg += (*i).second->getSource()->GetName();
>> throw CodeGenerationError(aMsg);
>> }
>> +
>> + /* Append the ID */
>> + vi->AppendID(var);
>>
>> + /* ANDRE
>> + RETURN_INTO_WSTRING(vn,var->name());
>> + printf("variable and source \"%S\"\n",vn.c_str());
>> + std::wstring fred = vi->GetIDString();
>> + printf(" ID string = \"%S\"\n",fred.c_str());
>> + */
>> +
>> (*i).second->setSource(vi);
>>
>> // Set the annotation...
>> @@ -338,6 +348,17 @@
>> RETURN_INTO_OBJREF(vi, VariableInformation,
>> new VariableInformation(var, varinfoKey, source));
>>
>> + /* Append the ID */
>> + vi->AppendID(var);
>> +
>> + /* ANDRE
>> + RETURN_INTO_WSTRING(vn,var->name());
>> + std::wstring sn = source->GetName();
>> + printf("variable \"%S\" has source \"%S\"\n",vn.c_str(),sn.c_str());
>> + std::wstring fred = vi->GetIDString();
>> + printf(" ID string = \"%S\"\n",fred.c_str());
>> + */
>> +
>> // Set the annotation...
>> annot.addAnnotation(vi);
>>
>> Index: CCGS/sources/CCGSImplementation.hpp
>> ===================================================================
>> --- CCGS/sources/CCGSImplementation.hpp (revision 1014)
>> +++ CCGS/sources/CCGSImplementation.hpp (working copy)
>> @@ -144,11 +144,11 @@
>> iface::cellml_api::CellMLVariable* aVar, uint32_t aVariableIndex=0,
>> bool aHasDifferential=false, uint32_t aDerivative=0,
>> iface::cellml_services::VariableEvaluationType aType=
>> - iface::cellml_services::COMPUTED
>> + iface::cellml_services::COMPUTED, const wchar_t* idString=NULL
>>
> NULL?
>
> 21.3.1 of ISO/IEC 14882-1998 says:
> basic_string(const charT* s, const Allocator& a = Allocator());
> Requires: s shall not be a null pointer.
>
> Therefore, the default argument value will potentially cause a crash. I
> suggest L"" instead.
>
>> )
>> : _cda_refcount(1), mVar(aVar), mVariableIndex(aVariableIndex),
>> mHasDifferential(aHasDifferential), mDerivative(aDerivative),
>> - mType(aType)
>> + mType(aType), mIDString(idString)
>>
>> {
>> mVar->add_ref();
>> }
>> @@ -189,12 +189,28 @@
>> return mVar;
>> }
>>
>> + char* ids()
>> + throw (std::exception&)
>> + {
>> + const wchar_t* str = mIDString.c_str();
>> + size_t len = wcsrtombs(NULL,&str,0,NULL);
>>
> Shouldn't you be using UTF16 here, like the rest of the code that deals
> with variable names / URIs?
>> + if (len > 0)
>> + {
>> + len++;
>> + char* s = (char*)malloc(len);
>> + wcsrtombs(s,&str,len,NULL);
>> + return(s);
>>
>> + }
>> + return((char*)NULL);
>>
> NULL is not a valid value for a string in the Physiome CellML Mapping,
> because the caller is supposed to be able to pass it to free. You should
> return an empty string instead.
>> + }
>> +
>> private:
>> iface::cellml_api::CellMLVariable* mVar;
>> uint32_t mVariableIndex;
>> bool mHasDifferential;
>> uint32_t mDerivative;
>> iface::cellml_services::VariableEvaluationType mType;
>> + std::wstring mIDString;
>> };
>>
>> class CDA_CCodeVariableIterator
>> Index: CCGS/sources/Variables.hxx
>> ===================================================================
>> --- CCGS/sources/Variables.hxx (revision 1014)
>> +++ CCGS/sources/Variables.hxx (working copy)
>> @@ -12,7 +12,7 @@
>> VariableInformation(iface::cellml_api::CellMLVariable* aSourceVariable,
>> TemporaryAnnotationKey& aKey)
>> : TemporaryAnnotation(aSourceVariable, aKey),
>> mSource(aSourceVariable),
>> - mFlags(0), mDegree(1), mSourceInformation(NULL)
>> + mFlags(0), mDegree(1), mIDString(), mSourceInformation(NULL)
>>
> This is unnecessary, as that is the default constructor anyway.
>> {
>> wchar_t* tmp = aSourceVariable->name();
>> mName = tmp;
>> @@ -131,12 +131,61 @@
>> return mSource;
>> }
>>
>> + /* Andre Hack */
>> + void AppendID(iface::cellml_api::CellMLVariable* aVar)
>> + {
>> + if (mSourceInformation)
>> + mSourceInformation->AppendID(aVar);
>> + else
>> + {
>> + /* Does the variable have a cmeta:id? */
>> + RETURN_INTO_WSTRING(id,aVar->cmetaId());
>> + if (id.length() > 0)
>> + {
>> + iface::cellml_api::Model* model = aVar->modelElement();
>>
> I have been trying to use ObjRefs rather than explicit memory management
> for all new code. This means that if, for example, base_uri() throws for
> some reason, model still won't be leaked.
> RETURN_INTO_OBJREF(model, iface::cellml_api::Model, aVar->modelElement())
>> + iface::cellml_api::URI* uri = model->base_uri();
>>
>> + RETURN_INTO_WSTRING(uriS,uri->asText());
>> + uriS.append(L"#");
>> + uriS.append(id);
>> + if (mIDString.length() > 0) mIDString.append(L",");
>> + mIDString.append(uriS);
>> + uri->release_ref();
>> + model->release_ref();
>> + }
>> + }
>> + }
>> + const wchar_t* GetIDString()
>> + {
>> + if (mSourceInformation)
>> + return mSourceInformation->GetIDString();
>> + else
>> + return mIDString.c_str();
>> + }
>> +
>> +#if defined ANDRES_BAD_HACK
>> + void SetVariable(iface::cellml_api::CellMLVariable* aVar)
>> + {
>> + mCellMLElement = aVar;
>> + }
>> +
>> + iface::cellml_api::CellMLVariable* GetVariable()
>> + {
>> + if (mSourceInformation)
>> + return mSourceInformation->GetVariable();
>> + else if (mCellMLElement) return
>> + dynamic_cast<iface::cellml_api::CellMLVariable*>
>> + (mCellMLElement.getPointer());
>> + return NULL;
>> + }
>> +#endif
>> +
>> const wchar_t* GetName() { return mName.c_str(); }
>> private:
>> iface::cellml_api::CellMLVariable* mSource;
>> double mInitialValue;
>> uint32_t mFlags, mDegree, mIndex;
>> std::wstring mName;
>> + std::wstring mIDString;
>> uint32_t mArrayType;
>> VariableInformation* mSourceInformation;
>> };
>> Index: interfaces/CCGS.idl
>> ===================================================================
>> --- interfaces/CCGS.idl (revision 1014)
>> +++ interfaces/CCGS.idl (working copy)
>> @@ -80,6 +80,12 @@
>> * The CellML variable element of the source (no in interfaces).
>> */
>> readonly attribute cellml_api::CellMLVariable source;
>> +
>> + /* Andre's hack */
>> + /**
>> + * The list of (absolute) IDs referencing this variable.
>> + */
>> + readonly attribute string ids;
>> };
>> #pragma terminal-interface
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> cellml-discussion mailing list
>> cellml-discussion at cellml.org
>> http://www.cellml.org/mailman/listinfo/cellml-discussion
>>
>
> _______________________________________________
> cellml-discussion mailing list
> cellml-discussion at cellml.org
> http://www.cellml.org/mailman/listinfo/cellml-discussion

--
David Nickerson, PhD
Research Fellow
Division of Bioengineering
Faculty of Engineering
National University of Singapore
Email: david.nickerson at nus.edu.sg




Archive powered by MHonArc 2.6.18.

Top of page