Commit 2abf493a authored by Ludovic Cottret's avatar Ludovic Cottret
Browse files

Merge branch 'toolboxJsonDesc' into 'develop'

[toolbox] Galaxy wrappers and json description

See merge request !11
parents b3df96bd 5a829478
......@@ -19,4 +19,4 @@ met4j-core/src/main/java/fr/inra/toulouse/metexplore/met4j_core/Test\.java
dependency-reduced-pom.xml
/met4j.sif
*.sif
......@@ -3,6 +3,7 @@
stages:
- build
- test
- package
- deploy
- build-containers
......@@ -11,10 +12,34 @@ stages:
image: docker:latest
services:
- docker:dind
script:
- if [ "$CI_COMMIT_BRANCH" = "master" ]; then docker build -t "$DOCKER_IMAGE:latest" .; fi
- if [ "$CI_COMMIT_BRANCH" = "master" ]; then docker push "$DOCKER_IMAGE:latest"; fi
- if [ "$CI_COMMIT_BRANCH" = "develop" -o "$CI_COMMIT_BRANCH" = "master" ]; then docker build -t "$DOCKER_IMAGE:$VERSION" .; fi
# version in lower case
- if [ "$CI_COMMIT_BRANCH" = "develop" -o "$CI_COMMIT_BRANCH" = "master" -a "$VERSION" != "$LOWER_CASE_VERSION" ]; then docker build -t "$DOCKER_IMAGE:$LOWER_CASE_VERSION" .; fi
- if [ "$CI_COMMIT_BRANCH" = "develop" -o "$CI_COMMIT_BRANCH" = "master" -a "$VERSION" != "$LOWER_CASE_VERSION" ]; then docker push "$DOCKER_IMAGE:$LOWER_CASE_VERSION"; fi
- docker build -t "$DOCKER_IMAGE:$CI_COMMIT_BRANCH" .
- docker push "$DOCKER_IMAGE:$CI_COMMIT_BRANCH"
# branch in lower case
- docker build -t "$DOCKER_IMAGE:$LOWER_CASE_COMMIT_BRANCH" .
- docker push "$DOCKER_IMAGE:$LOWER_CASE_COMMIT_BRANCH"
rules:
- if: $CI_COMMIT_BRANCH == "master"
when: always
- if: $CI_COMMIT_BRANCH == "develop"
when: always
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: never
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
when: manual
needs:
- build
- package
variables:
MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
cache:
paths:
......@@ -24,15 +49,45 @@ build:
image: maven:3.6-adoptopenjdk-14
stage: build
script:
- mvn compile
- mvn $MAVEN_OPTS compile
- TRUEVERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
- VERSION=$TRUEVERSION
- if [ "$CI_COMMIT_BRANCH" = "master" ]; then VERSION=${VERSION%"-SNAPSHOT"}; fi
- LOWER_CASE_VERSION=${VERSION,,}
- LOWER_CASE_COMMIT_BRANCH=${CI_COMMIT_BRANCH,,}
- echo "VERSION=$VERSION" >> build.env
- echo "TRUEVERSION=$TRUEVERSION" >> build.env
- echo "LOWER_CASE_VERSION=$LOWER_CASE_VERSION" >> build.env
- echo "LOWER_CASE_COMMIT_BRANCH=$LOWER_CASE_COMMIT_BRANCH" >> build.env
artifacts:
expire_in: 60 min
paths:
- target/
- "*/target"
reports:
dotenv: build.env
test:
image: maven:3.6-adoptopenjdk-14
stage: test
script:
- mvn clean test
- find . -name "*.class" -exec touch {} \+
- mvn $MAVEN_OPTS clean test
- cat coverage/target/site/jacoco-aggregate/index.html | grep -o '<tfoot>.*</tfoot>'
package:
image: maven:3.6-adoptopenjdk-14
stage: package
script:
- mvn $MAVEN_OPTS clean install -DskipTests=true
- cd met4j-toolbox
- mvn $MAVEN_OPTS package -DskipTests=true
- cd ..
artifacts:
expire_in: 60 min
paths:
- "met4j-toolbox/target/met4j-toolbox-$TRUEVERSION.jar"
deploySnapshot:
image: maven:3.6-adoptopenjdk-14
stage: deploy
......@@ -71,39 +126,35 @@ buildSingularity:
entrypoint: [ "" ]
script:
- singularity build met4j-toolbox.sif met4j.singularity
- singularity push --docker-username "${CI_REGISTRY_USER}" --docker-password "${CI_REGISTRY_PASSWORD}" met4j-toolbox.sif oras://"$CI_REGISTRY_IMAGE"/met4j-singularity:"$CI_COMMIT_TAG"
- if [ "$CI_COMMIT_BRANCH" = "master" ]; then singularity push --docker-username "${CI_REGISTRY_USER}" --docker-password "${CI_REGISTRY_PASSWORD}" met4j-toolbox.sif oras://"$CI_REGISTRY_IMAGE"/met4j-singularity:"latest"; fi
- if [ "$CI_COMMIT_BRANCH" = "develop" -o "$CI_COMMIT_BRANCH" = "master" ]; then singularity push --docker-username "${CI_REGISTRY_USER}" --docker-password "${CI_REGISTRY_PASSWORD}" met4j-toolbox.sif oras://"$CI_REGISTRY_IMAGE"/met4j-singularity:"$VERSION"; fi
# version in lower case
- if [ "$CI_COMMIT_BRANCH" = "develop" -o "$CI_COMMIT_BRANCH" = "master" -a "$VERSION" != "$LOWER_CASE_VERSION"]; then singularity push --docker-username "${CI_REGISTRY_USER}" --docker-password "${CI_REGISTRY_PASSWORD}" met4j-toolbox.sif oras://"$CI_REGISTRY_IMAGE"/met4j-singularity:"$LOWER_CASE_VERSION"; fi
- singularity push --docker-username "${CI_REGISTRY_USER}" --docker-password "${CI_REGISTRY_PASSWORD}" met4j-toolbox.sif oras://"$CI_REGISTRY_IMAGE"/met4j-singularity:"$CI_COMMIT_BRANCH"
# branch in lower case
- singularity push --docker-username "${CI_REGISTRY_USER}" --docker-password "${CI_REGISTRY_PASSWORD}" met4j-toolbox.sif oras://"$CI_REGISTRY_IMAGE"/met4j-singularity:"$LOWER_CASE_COMMIT_BRANCH"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
- if: $CI_COMMIT_BRANCH == "master"
when: always
- if: $CI_COMMIT_BRANCH == "develop"
when: always
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: never
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
when: manual
needs:
- build
- package
buildDockerProdGitlab:
extends: .template_docker
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t "$CI_REGISTRY/metexplore/met4j/met4j-docker:latest" .
- docker push "$CI_REGISTRY/metexplore/met4j/met4j-docker:latest"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
when: manual
- DOCKER_IMAGE="$CI_REGISTRY/metexplore/met4j/met4j-docker"
buildDockerProdDockerhub:
extends: .template_docker
before_script:
- docker login -u "$DOCKERHUB_USER" -p "$DOCKERHUB_PASSWORD" $DOCKERHUB_REGISTRY
script:
- docker build --pull -t "$DOCKERHUB_IMAGE:latest" .
- docker push "$DOCKERHUB_IMAGE:latest"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
- if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
when: manual
- DOCKER_IMAGE=$DOCKERHUB_IMAGE
\ No newline at end of file
......@@ -4,25 +4,16 @@ RUN export DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y openjdk-11-jre git maven \
&& apt-get install -y openjdk-11-jre maven \
&& apt-get clean \
&& apt-get purge
RUN mkdir -p /opt && cd /opt \
&& git clone https://forgemia.inra.fr/metexplore/met4j.git \
&& cd met4j \
&& mvn install \
&& cd met4j-toolbox \
&& mvn package
RUN mkdir -p /opt/bin \
&& cd /opt/met4j/met4j-toolbox \
&& cp target/met4j*.jar /opt/bin/met4j.jar \
&& cd /opt \
&& rm -rf met4j ~/.m2 \
&& apt-get remove -y git && apt-get autoremove -y
RUN mkdir -p /opt/bin
COPY ./docker_files/met4j.sh /opt/bin
COPY ./met4j-toolbox/target/met4j*.jar /opt/bin/met4j.jar
RUN chmod a+x /opt/bin/met4j.sh
ENTRYPOINT ["/opt/bin/met4j.sh"]
RUN cd /usr/bin && ln -s /opt/bin/met4j.sh
......@@ -10,17 +10,14 @@
**Met4J is an open-source Java library dedicated to the structural analysis of metabolic networks. It also came with a toolbox gathering CLI for several analyses relevant to metabolism-related research.**
Met4j is composed by several modules:
Met4j is composed by three main modules:
- [met4j-core](met4j-core/README.md): it's the key module which contains all the core
classes for handling metabolic networks
- [met4j-io](met4j-io/README.md): for importing/exporting metabolic networks in several
formats (SBML, MetExploreXml, KEGG)
- [met4j-graph](met4j-graph/README.md): for performing graph-based topological analysis of metabolic networks.
The other modules contains utilities to serve the main modules listed here.
The full list of implemented metabolic network analysis can be found in the [met4j-toolbox](met4j-toolbox/README.md)
The package [met4j-toolbox](met4j-toolbox/README.md) contains high-level apps that can be run in command line by using either jar file or Singularity or Docker containers.
## Installation
......@@ -52,41 +49,22 @@ git clone https://forgemia.inra.fr/metexplore/met4j.git;
cd met4j;
mvn clean install
```
to build the executable toolbox jar:
```
cd met4j-toolbox
mvn clean compile assembly:single
mv ./target/*-jar-with-dependencies.jar ../../../
```
## Usage
Documentation for the library modules can be found in each module's own README.
Detailed code examples can be found at [here](https://forgemia.inra.fr/metexplore/tutorialmet4j).
The toolbox can be launched using
```
java -jar met4j-toolbox-0.8.0-jar-with-dependencies.jar
```
which will list all the contained applications that can be called using
```
java -cp met4j-toolbox-0.8.0-jar-with-dependencies.jar <App full name> -h
```
### With singularity
You need at least [singularity](https://sylabs.io/guides/3.5/user-guide/quick_start.html) v3.5.
```console
singularity pull met4j-toolbox.sif oras://registry.forgemia.inra.fr/metexplore/met4j/met4j-singularity:latest
```
Detailed code examples can be found at [here](https://forgemia.inra.fr/metexplore/tutorialmet4j).
## Contributing
Pull requests are welcome **on the gitlab repo** ([https://forgemia.inra.fr/metexplore/met4j](https://forgemia.inra.fr/metexplore/met4j)). For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
## Issues
Issues or suggestions can be posted [here](https://forgemia.inra.fr/metexplore/met4j/-/issues).
## License
Met4J is distributed under the open license [CeCILL-2.1](https://cecill.info/licences/Licence_CeCILL_V2.1-en.html) (compatible GNU-GPL).
......
......@@ -44,6 +44,6 @@ if [ $# -lt 1 ]
echo "display Help"
exec java -jar $path_jar
else
echo "Lauch met4j-toolbox"
echo "Launch met4j-toolbox"
exec java -Dlog4j.configuration= -cp $path_jar fr.inrae.toulouse.metexplore.met4j_toolbox."$@"
fi
\ No newline at end of file
......@@ -81,7 +81,7 @@ public abstract class BioEntity {
*/
public BioEntity(String id, String name) {
if (StringUtils.isVoid(id)) {
String newId = UUID.randomUUID().toString().replaceAll("-", "_");
String newId = "_"+UUID.randomUUID().toString().replaceAll("-", "_");
this.id = newId;
} else {
this.id = id;
......
......@@ -64,234 +64,225 @@ import static fr.inrae.toulouse.metexplore.met4j_core.utils.StringUtils.*;
* because they do not extend the {@link fr.inrae.toulouse.metexplore.met4j_core.biodata.BioPhysicalEntity} class
*
* @author Benjamin
* @since 3.0
* @version $Id: $Id
* @since 3.0
*/
public class AnnotationParser implements PackageParser, AdditionalDataTag, ReaderSBML1Compatible, ReaderSBML2Compatible,
ReaderSBML3Compatible {
/** Constant <code>ORIGIN="SBML"</code> */
public static final String ORIGIN = "SBML";
/**
* The Jsbml Model
*/
public Model model;
/**
* The BioNetwork
*/
public BioNetwork bionetwork;
/**
* The user defined annotation pattern used in the regular expression of
* this class
*/
public String annotationPattern;
/**
* The default annotation pattern:
* <ul>
* <li>http://identifiers.org/([^/]+)/(.*)
* </ul>
* The first parenthesis group is
*/
public static final String defaultAnnotationPattern = "https?://identifiers.org/([^/]+)/(.*)";
/**
* Constructor
*
* @param useDefault
* true to use the {@link #defaultAnnotationPattern}
*/
public AnnotationParser(boolean useDefault) {
if (useDefault)
this.setAnnotationPattern(defaultAnnotationPattern);
}
/**
* Constructor
*
* @param pattern
* the user defined pattern
*/
public AnnotationParser(String pattern) {
this.annotationPattern = pattern;
}
/**
* <p>getAssociatedPackageName.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getAssociatedPackageName() {
return "annot";
}
/** {@inheritDoc} */
public boolean isPackageUseableOnModel(Model model) {
return true;
}
/**
* {@inheritDoc}
*
* Parse all model entities to retrieve their annotations and extract the
* desired information
*/
public void parseModel(Model model, BioNetwork bionetwork) {
System.err.println("Starting " + this.getAssociatedPackageName() + " plugin...");
this.setBionetwork(bionetwork);
this.setModel(model);
this.parseAnnotation(bionetwork,model.getAnnotation());
this.parseSbmlAnnotations(bionetwork.getReactionsView());
this.parseSbmlAnnotations(bionetwork.getMetabolitesView());
this.parseSbmlAnnotations(bionetwork.getGenesView());
this.parseSbmlAnnotations(bionetwork.getCompartmentsView());
}
/**
*
* One of the different lists present in the {@link BioNetwork}
* class
*/
private void parseSbmlAnnotations(BioCollection<?> collection) {
for (BioEntity entry : collection) {
String id = entry.getId();
if(entry.getAttribute("oldId") != null)
{
id = (String) entry.getAttribute("oldId");
}
UniqueNamedSBase sbase = this.getModel().findUniqueNamedSBase(id);
if (sbase != null && !sbase.getAnnotation().isEmpty() && sbase.hasValidAnnotation()) {
this.parseAnnotation(entry, sbase.getAnnotation());
}
}
}
/**
* Parse entity's annotation to extract external identifiers
*
* @param annot
* the SBML annotation element
*/
private void parseAnnotation(BioEntity ent, Annotation annot) {
Matcher m;
for (CVTerm cv : annot.getListOfCVTerms()) {
String qual;
if(cv.isBiologicalQualifier()) {
qual = cv.getBiologicalQualifierType().getElementNameEquivalent();
}
else {
qual = cv.getModelQualifierType().getElementNameEquivalent();
}
for (String ress : cv.getResources()) {
if (this.getAnnotationPattern() != null
&& (m = Pattern.compile(this.getAnnotationPattern()).matcher(ress)).matches()) {
if (m.group(1).equalsIgnoreCase("ec-code") && ent instanceof BioReaction) {
String oldEc = ((BioReaction) ent).getEcNumber();
if(isVoid(oldEc))
{
((BioReaction) ent).setEcNumber(m.group(2));
}
else {
((BioReaction) ent).setEcNumber(oldEc+";"+m.group(2));
}
}
ent.addRef(m.group(1), m.group(2), 1, qual, ORIGIN);
}
}
}
String nonrdfAnnot = annot.getNonRDFannotationAsString();
if (ent instanceof BioMetabolite && nonrdfAnnot != null && !nonrdfAnnot.isEmpty()) {
String specialInchiPattern = "<in:inchi xmlns:in=\"([^\"]+)\">InChI=([^<]+)</in:inchi>";
m = Pattern.compile(specialInchiPattern, Pattern.DOTALL).matcher(nonrdfAnnot);
while (m.find()) {
if (m.group(1).equalsIgnoreCase("http://biomodels.net/inchi")) {
String inchi = m.group(2);
if (!ent.hasRef("inchi", inchi)) {
ent.addRef("inchi", inchi, 1, "is", ORIGIN);
}
}
}
}
}
/**
* <p>Getter for the field <code>model</code>.</p>
*
* @return the model
*/
public Model getModel() {
return model;
}
/**
* <p>Setter for the field <code>model</code>.</p>
*
* @param model
* the model to set
*/
public void setModel(Model model) {
this.model = model;
}
/**
* <p>Getter for the field <code>bionetwork</code>.</p>
*
* @return the bionetwork
*/
public BioNetwork getBionetwork() {
return bionetwork;
}
/**
* <p>Setter for the field <code>bionetwork</code>.</p>
*
* @param bionetwork
* the bionetwork to set
*/
public void setBionetwork(BioNetwork bionetwork) {
this.bionetwork = bionetwork;
}
/**
* <p>Getter for the field <code>annotationPattern</code>.</p>
*
* @return the annotationPattern
*/
public String getAnnotationPattern() {
return annotationPattern;
}
/**
* <p>Setter for the field <code>annotationPattern</code>.</p>
*
* @param annotationPattern
* the annotationPattern to set
*/
public void setAnnotationPattern(String annotationPattern) {
this.annotationPattern = annotationPattern;
}
ReaderSBML3Compatible {
/**
* Constant <code>ORIGIN="SBML"</code>
*/
public static final String ORIGIN = "SBML";
/**
* The Jsbml Model
*/
public Model model;
/**
* The BioNetwork
*/
public BioNetwork bionetwork;
/**
* The user defined annotation pattern used in the regular expression of
* this class
*/
public String annotationPattern;
/**
* The default annotation pattern:
* <ul>
* <li>http://identifiers.org/([^/]+)/(.*)
* </ul>
* The first parenthesis group is
*/
public static final String defaultAnnotationPattern = "https?://identifiers.org/([^/]+)/(.*)";
/**
* Constructor
*
* @param useDefault true to use the {@link #defaultAnnotationPattern}
*/
public AnnotationParser(boolean useDefault) {
if (useDefault)
this.setAnnotationPattern(defaultAnnotationPattern);
}
/**
* Constructor
*
* @param pattern the user defined pattern
*/
public AnnotationParser(String pattern) {
this.annotationPattern = pattern;
}
/**
* <p>getAssociatedPackageName.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getAssociatedPackageName() {
return "annot";
}
/**
* {@inheritDoc}
*/
public boolean isPackageUseableOnModel(Model model) {
return true;
}
/**
* {@inheritDoc}
* <p>
* Parse all model entities to retrieve their annotations and extract the
* desired information
*/
public void parseModel(Model model, BioNetwork bionetwork) {
System.err.println("Starting " + this.getAssociatedPackageName() + " plugin...");
this.setBionetwork(bionetwork);
this.setModel(model);
this.parseAnnotation(bionetwork, model.getAnnotation());
this.parseSbmlAnnotations(bionetwork.getReactionsView());
this.parseSbmlAnnotations(bionetwork.getMetabolitesView());
this.parseSbmlAnnotations(bionetwork.getGenesView());
this.parseSbmlAnnotations(bionetwork.getCompartmentsView());
}
/**