Code Monkey home page Code Monkey logo

deviser's Introduction

Deviser

Deviser stands for "Design Explorer and Viewer for Iterative SBML Enhancement of Representations". It is a code generator for defining and prototyping SBML Level 3 packages and code for use with libSBML.

   ⭐️ This is the repository for Deviser's code generation facility. The GUI is in a separate repository. ⭐️   

Authors: Sarah M. Keating and Frank T. Bergmann

Contributors: Matthew S. Gillman, Brett Olivier, Orod Razeghi, Lucian Smith & Mike Hucka
Repository: https://github.com/sbmlteam/deviser
Repository for GUI: https://github.com/sbmlteam/QtDeviser
Pivotal tracker: https://www.pivotaltracker.com/n/projects/977192
License: LGPL version 2.1 – see the file LICENSE for details

Background

Computation modeling has become crucial to biological research, and SBML (the Systems Biology Markup Language) has become the de facto standard open format for exchanging models between software tools in systems biology. SBML Level 3 has a modular structure, with as a core augmented with optional packages that add syntax and features. Development of new Level 3 packages is ongoing.

LibSBML is a free, open-source programming library to help developers read, write, manipulate, translate, and validate SBML files and data streams in their software systems. It is written in C++ and provides language bindings for other programming languages. Support for SBML Level 3 can be added to LibSBML by integrating the package-specific code and building with the package enabled.

Deviser facilitates the development of SBML Level 3 packages by enabling the creation of basic specifications, UML diagrams and code for integration with LibSBML.

Deviser is written in Python and is compatible with Python version 2.6 onwards.

Using Deviser

Deviser Edit GUI

The Deviser Edit tool allows you to quickly define an SBML Level 3 package. It then provides the following functionality

  1. Create and view a UML diagram.
  2. Generate the necessary libSBML code for the package.
  3. Generate TeX files and generate a PDF of a basic specification document for the package.
  4. Integrate and test the package with libSBML.

The Deviser Edit tool creates an XML description of the package that is used by the deviser code to generate the requested files. This XML description is exemplified in the samples directory.

Command Line Interface

There is command line version of the function that can be used to invoke Deviser on the XML file. This is the deviser.py file found in the generator directory.

deviser.py [--generate][--latex] input-file.xml    

This program will use a Deviser XML file, and generate either a C++ libSBML extension for it, or generate a LaTeX scaffold for its specification.

Full documentation is available in the docs directory.

Installation

The deviser release includes bundles/installer for each of the main operating systems.

Prerequisites

  1. A C++ compiler must be installed if you wish to compile the libSBML code generated.
  2. A pdflatex compiler must be installed if you wish to generate a PDF file from the TeX sources generated.

NOTE: These may already be available on your OS.

Microsoft Windows OS

A windows installation executable which installs the Deviser Edit tool (QtDeviser.exe), all the necessary Deviser files. Additionally it includes a Python interpreter and the sbmlpkgspec files for generating SBML Level 3 Package specifications.

Linux OS

A self-contained, binary installer is available that contains Deviser, DeviserEdit and the sbmlpkgspec modules. After installation DeviserEdit can be run from either a desktop icon or by calling the DeviserEdit.sh script in the installation directory. Deviser samples can be found in the deviser/samples subdirectory.

Mac OS X

A .dmg file is available containing the DeviserEdit Application that embeds the necessary Deviser and sbmlpkgspec files in addition to docs and samples directories.

Source archives

The source archives contain the Deviser code that can be used via the command line.

Other resources

Not all of the following are necessary as what is necessary depends on which operating system is being used and which Deviser functionality is required. These links are given as a quick reference.

Acknowledgments

The development of Deviser was supported in part by funding from the National Institute of General Medical Sciences (USA) under grant R01 GM070923 (principal investigator: Michael Hucka).

Fuether enhancement of Deviser was funded by Chan Zuckerberg Initiative under grant 2020-218578 (5022) (principal investigator: Sarah M Keating).

Copyright and license

Copyright (C) 2014-2018 jointly by the California Institute of Technology, Pasadena, CA, USA, EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK and the University of Heidelberg, Heidelberg, Germany

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or any later version.

This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder is on an "as is" basis, and the California Institute of Technology has no obligations to provide maintenance, support, updates, enhancements or modifications. In no event shall the California Institute of Technology be liable to any party for direct, indirect, special, incidental or consequential damages, including lost profits, arising out of the use of this software and its documentation, even if the California Institute of Technology has been advised of the possibility of such damage. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library in the file named "LICENSE" included with the software distribution.


                                         

deviser's People

Contributors

bgoli avatar dpshelio avatar fbergmann avatar luciansmith avatar mattagape avatar mhucka avatar orodrazeghi avatar robertvi avatar skeating avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

deviser's Issues

Update old links in DEVISER_MANUAL

A number of links in the Deviser Manual still refer to Sourceforge. These need updating (assuming we no longer want to use Sourceforge)

Request: remove hard-wrapping of tex files

Deviser output writes tex files (particularly the validation appendix) and hard-wraps the lines at 80 characters. This makes it difficult to run search-and-replace functions, which are particularly necessary when dealing with non-SBML specifications, but can also be a pain for normal SBML package specifications. If hard wrapping was removed, it would make dealing with these files easier.

Force pytest failures when wrong input to CPP tests

I have added the tests originally in run_cpp_tests.py to generator/pytest_files/test_cpp/test_cpp.py. Generally things are working well, but we need to make sure silly input causes a test failure, which it currently doesn't. e.g. using Defggggggggg as a class name.

Information missing in deviser.rng schema document

In XML schema document deviser/docs/deviser.rng, some content is missing.

Currently there is no information for <language> nodes and their children, e.g. as in samples/sbgn.xml.

Once this is corrected, we ought to write a little script to iterate over the samples and see if they are fully covered by the schema. Although that assumes the samples cover every type of node that Deviser might encounter, and I don't know if that is the case.

Validation ignores 'XML Name'

When generating LaTeX validation rules, the internal ID is used instead of the 'XML name'.

As an example:

image

The 'rangeId' attribute is actually just 'range' in the XML, but the validation rules (both in the generated C++ and in the LaTeX) claim that it is 'rangeId'.

Deviser does not generate getAllElements

It would seem that the getAllElements functions are not being generated. It would also be nice to have the ElementFilter functionality as we have it in libSBML automatically generated.

Which case is correct?

In ParseXML.py, function get_loclass_name_value(), comment says "we expect this to be camelCase starting with lower", but code returns a string starting with upper case.

Inconsistent use of function argument parameter

In util/generateCode.py, function create_dir_structure() takes a parameter overwrite. If this param is False, the function executes the line print('directory already exists - terminating to avoid overwriting'). BUT just before that, there is a call to create_dir(directories[index], overwrite)

If I look at create_dir(), it has the signature:
def create_dir(name, skip_existing):

So the skip_existing parameter is the same as overwrite. But surely these want different outcomes to each other? Or have I missed something??

E.g. if overwrite is True (I want to overwrite any existing directory with this name), this means skip_existing will be True. So, if the directory already exists, the create_dir() function just skips it and says done = True … but it isn’t?!

Hard-coded magic numbers

In ParseXML.py function parse_deviser.xml(), the following lines appear:

    sbml_level = 3
    sbml_version = 1
    pkg_version = 1

We need to discuss what to do about these numbers. e.g. should they be stored in a "versions" file which Deviser reads in?

error code uniqueness / enums

I've noticed that when using two libraries generated by deviser, some enum names are unfortunately, causing compile errors (for example using latest combine archive / sedml, if included together). Most names are already prefixed, but some are not (like AllowedAttributes).

Consolidate generate*.pycode in deviser/generator/util

In directory deviser/generator/util, there are a number of files which have almost identical structures:

generateCode.py, generateExamples.py, generateLatex.py, generateRNG.py, generateTest.py and generateXML.py.

They can all be invoked from the command line and:

  • check the number of command-line arguments is correct
  • Invoke ParseXML.ParseXML()on the filename supplied at the command line
  • generate big dictionary object structure from ParseXML.parse_deviser_xml()
  • then invoke creation of the desired file type using the big structure object just obtained.

I think there is a lot of scope for merging these into one file, with command-line options to enable selection of the desired output file type.

NB Obviously any client code needs to be identified and updated, too.

Elements in a listOf

Up until L3V2 a ListOf element in SBML could not be empty so the min no of children in a listOf defaults to 1. L3V2 changed this and also other standards do not have this rule.

Need to check

  • get_lo_min_children() and its usage

  • minNumListOfChildren variable

Tests failing for run_cpp_tests.py

In deviser/generator/tests/test_cpp_code, run_cpp_tests.py experiences two test failures (for both Python 2 and Python 3):

REPORT for CPP Tests
All tests were run.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 fails reported:
test-code/Def.h
test-code/Def.cpp

Bug in util/strFunctions.py singular()

In deviser/util/strFunctions.py, function singular() correctly deals with some plurals ending in "es" but not others.

e.g. singular("foxes") -> "fox". ✔️
but
singular("apples") -> "appl" 👎

Non-negative and positive aren't the same

If I set an attribute as being a 'positive int', the resulting validation rule says that it must be non-negative. This is incorrect. Non-negative means [0, 1, ...] and positive means [1, 2, ...].

Remove 'dist' and 'check' targets from CMakeLists

I've been pulling various SBML-adjacent projects into a 'dependencies' project that builds everything at once for the various things we make. If I put more than one Deviser-generated project in there, I get CMake errors that there are multiple 'dist' targets. The dist target was a holdover from gnumake days; it's probably best to drop it.

generated c++ code needs should be compatible with c++17 and above

As discussed in this issue: sbmlteam/libsbml#36, the current libSBML only compiles with c++ standard up to 14. This is because of the use of unary_function and ptr_function. The code compiles fine without these, so all that needs doing is not to inherit from unary functions.

Deviser generates them for finding elements by id or reference:

 /**
  * Used by ListOf::get() to lookup an SBase based by its id.
  */
 struct IdEqS : public unary_function<SBase*, bool>
 {
   const string& mId;
 
   IdEqS (const string& id) : mId(id) { }
   bool operator() (SBase* sb) 
        { return static_cast <Species *> (sb)->getId() == mId; }
 };

this struct will work just as well, by not using the unary_function.

Update copyright statements (throughout the code)

Currently we are being funded by the Chan Zuckerberg Initiative, and work is being done by paid employees at UCL.

We should add CZI (and UCL?) acknowledgements or whatever in the files such as init.py etc

Consider new class for global_variables.py

In file deviser/generator/util/global_variables.py, there are a lot of lines like:

global language
language = 'sbml'

and, further down the file:

def set_globals(lang, ...):
    global language
    language = lang
    ...

There are an awful lot of global declarations, seemingly to allow the varables so-called to be accessed in the functions in the lower part of the file.

We could consider replacing the code in this file with a new GlobalVariables class. That would make the code simpler. The set_globals() function would be replaced by a constructor. Then pairs of lines such as those shown in the set_globals() function shown above would be replaced with one line, e.g.:

def __init(lang,...):
    self.language = lang
    ....

Already, in client code, we see things like:

import global_variables as gv
...
    if gv.code_returned == gv.return_codes['success']:
        print('code successfully written')
...

This could be replaced by something like:

import GlobalVariables as GV
...
   if GV.code_returned == ...

I'm guessing we'd probably need static functions so we don't require an object instance, in which case the GlobalVariables constructor could be replaced with a suitable @staticmethod etc...

What do people think about this suggestion?

::removeChildObject generated produces memory issue

sonar noticed that the code generated for removeChildObject is invalid. What happens is that

  • a ptr to the object is retained
  • then the object is freed
  • then the ptr to the freed element is returned for reuse, which ought to be fixed.

Instead of a call to unsetXXX the elements member variable should just be set to NULL.

Function argument changes meaning

In util/generateCode.py, function create_dir_structure() takes a parameter overwrite. If this param is False, the function executes the line print('directory already exists - terminating to avoid overwriting'). BUT just before that, there is a call to create_dir(directories[index], overwrite)

If I look at create_dir(), it has the signature:
def create_dir(name, skip_existing):

So the skip_existing parameter is the same as overwrite. But surely these want different outcomes to each other? Or have I missed something??

E.g. if overwrite is True (I want to overwrite any existing directory with this name), this means skip_existing will be True. So, if the directory already exists, the create_dir() function just skips it and says done = True … but it isn’t?!

Flattening functions need updating

Currently, for Distrib, the following function is generated:

void
UncertParameter::renameSIdRefs(const std::string& oldid,
                               const std::string& newid)
{
  if (isSetVar() && mVar == oldid)
  {
    setVar(newid);
  }

  if (isSetUnits() && mUnits == oldid)
  {
    setUnits(newid);
  }
}

However, this is incorrect: the units are not SIdRefs, and are instead UnitSIdRefs. There is a completely different function for renaming units, named renameUnitSIdRefs, which instead needs the unit renaming code.

In addition, UncertParameters have MathML children, which may have both SIdRefs and UnitSIdRefs, in them. The upshot is that instead of the above single function, we instead need the following:

void
UncertParameter::renameSIdRefs(const std::string& oldid,
                               const std::string& newid)
{
  DistribBase::renameSIdRefs(oldid, newid);
  if (isSetVar() && mVar == oldid)
  {
    setVar(newid);
  }

  if (isSetMath()) 
  {
      mMath->renameSIdRefs(oldid, newid);
  }
}

void
UncertParameter::renameUnitSIdRefs(const std::string& oldid, const std::string& newid)
{
    DistribBase::renameUnitSIdRefs(oldid, newid);

    if (isSetUnits() && mUnits == oldid)
    {
        setUnits(newid);
    }

    if (isSetMath()) 
    {
        mMath->renameUnitSIdRefs(oldid, newid);
    }
}

Also, there is one more function that needs to be implemented:

/** @cond doxygenLibsbmlInternal */
void
UncertParameter::replaceSIDWithFunction(const std::string& id, const ASTNode* function)
{
    if (isSetMath()) {
        if (mMath->getType() == AST_NAME && mMath->getName() == id) {
            delete mMath;
            mMath = function->deepCopy();
        }
        else {
            mMath->replaceIDWithFunction(id, function);
        }
    }
}
/** @endcond */

This function is for handling the cases where the replacement needs to be scaled by some conversion factor.

Unfortunately, there's no already-built-in way to convert the value of any UncertParameter by a conversion factor, but hopefully that won't become an issue. The units will still be correct, if set.

Also, the UncertSpan::renameSIdRefs() needs to call the base class:

void
UncertSpan::renameSIdRefs(const std::string& oldid, const std::string& newid)
{
  UncertParameter::renameSIdRefs(oldid, newid);
  if (isSetVarLower() && mVarLower == oldid)
  [...]

(In general, the rename functions should always call the base class.)

Look at query get_max_length

TODO will this throw an exception if elements other
than the first one do not have the attribute?
Is that possible?
"

Writer dereferences NULL document

I've noticed that all deviser generated writers have issues with dereferencing NULL documents when writing. (This also happens in libSBML). The fix needs to go to:

generator/code_files/templates/Writer.cpp

This also needs to check that the error log is not NULL.

Tests failing for run_other_library_tests.py

In directory deviser/generator/tests/test_other_library, the file run_other_library_tests.py is having a number of failures. This is due to differences between the reference files and the test/temp files.

I have only looked at a couple of these, but it appears that the test/temp files have additional code which makes them more robust. I therefore suspect that (some of) the reference files are out-of-date.

The branch I was working on for this was matt-tests

The failure cases are:

temp/sedml/SedModel.cpp
temp/sedml/SedListOfModels.h
temp/sedml/SedListOfModels.cpp
temp/sedml/SedDocument.cpp
temp/sedml/SedSetValue.cpp
temp/sedml/SedDataGenerator.cpp
temp/sedml/SedRepeatedTask.cpp
temp/sedml/SedSimulation.cpp
temp/sedml/SedAbstractTask.cpp
temp/sedml/SedListOfTasks.h
temp/sedml/SedListOfTasks.cpp
temp/sedml/SedOutput.cpp
temp/sedml/SedListOfOutputs.h
temp/sedml/SedListOfOutputs.cpp
temp/sedml/cmake/src/CMakeLists.txt
temp/sedml/cmake/src/bindings/CMakeLists.txt
temp/sedml/cmake/src/sedml/CMakeLists.txt
temp/omex/CaContent.cpp
temp/omex/CaListOfContents.h
temp/omex/CaListOfContents.cpp
temp/omex/cmake/src/CMakeLists.txt
temp/omex/cmake/src/bindings/CMakeLists.txt
temp/omex/cmake/src/omex/CMakeLists.txt

It should be borne in mind that the problems probably lie in the corresponding reference files, not the above test files.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.