Skip to content

Commit

Permalink
Merge branch 'main' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-gricourt committed Jan 27, 2023
2 parents ae89105 + b3fa43b commit e3b1771
Show file tree
Hide file tree
Showing 21 changed files with 603 additions and 211 deletions.
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
echo "$USER $PROJECT"
github_changelog_generator --user "$USER" --project "$PROJECT" --no-unreleased
- name: 'Upload Artifact Changelog'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: changelog-artifact
path: CHANGELOG.md
Expand All @@ -82,7 +82,7 @@ jobs:
echo "version_path=$VERSION_PATH" >> "$GITHUB_OUTPUT"
echo "version_dir=$VERSION_DIR" >> "$GITHUB_OUTPUT"
- name: 'Upload Artifact Version'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: version-artifact
path: ${{ steps.update_version.outputs.version_path }}
Expand Down Expand Up @@ -177,7 +177,7 @@ jobs:
filename=$(find ${{ env.dirbuild }} | head -n 1)
echo "asset=$filename" >> "$GITHUB_OUTPUT"
- name: 'Upload Artifact Package'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: package-conda-artifact
path: ${{ steps.identify_asset.outputs.asset }}
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ super-linter.log
build
debug
.tox
papier
cmd.sh
*.xml
8 changes: 4 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Changelog

## [0.8.0](https://github.com/brsynth/neo4jsbml/tree/0.8.0) (2023-01-16)
## [0.8.2](https://github.com/brsynth/neo4jsbml/tree/0.8.2) (2023-01-16)

[Full Changelog](https://github.com/brsynth/neo4jsbml/compare/0.8.1...0.8.0)
[Full Changelog](https://github.com/brsynth/neo4jsbml/compare/0.8.0...0.8.2)

## [0.8.1](https://github.com/brsynth/neo4jsbml/tree/0.8.1) (2023-01-16)
## [0.8.0](https://github.com/brsynth/neo4jsbml/tree/0.8.0) (2023-01-16)

[Full Changelog](https://github.com/brsynth/neo4jsbml/compare/710ac296807b62182b8280c407d990537bacdce7...0.8.1)
[Full Changelog](https://github.com/brsynth/neo4jsbml/compare/710ac296807b62182b8280c407d990537bacdce7...0.8.0)

**Implemented enhancements:**

Expand Down
41 changes: 35 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,46 @@ pip install --no-deps .

## Usage

### Step 1

Create a schema with [arrows](https://arrows.app) like:
![schema](tests/dataset/PathwayModelisation-1.0.0.png "Schema SBML")
Rules:
* Nodes are labelled based on SBML object name as defined in the [SBML specification](https://sbml.org)
* Properties are labelled based on SBML object properties as defined the [SBML specification](https://sbml.org)

### Step 2

Export your schema at the JSON format.

### Step 3

Import your data with `neo4jsbml` into Neo4j.
* Use either a configuration file `ini`, an example is provided in the `template` directory or individual parameters
* Password needs to be store in a file for safety security
* Pass a `tag` to identify the model loaded into the database

```sh
python -m neo4jsbml \
# Database parameters
--input-protocol-str ["neo4j", "bolt"] \
--input-url-str "localhost:7687" \
--input-url-str "localhost" \
--input-port-int 7687 \
--input-user-str "neo4j" \
--input-password-file <file> \
--input-database-str <file> \
# Input file
--input-database-str <str> \
--input-batch-int <int> \
# Config file
--input-config-file <file> \

# Input
--input-file-sbml <file> \
--input-id-str <id> \
# Parameters
--input-modelisation-str <modelisation>
--input-tag-str "" \
--input-modelisation-json <file>
```

## Test

```sh
python -m pytest
```
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: "2"

services:
neo4j:
image: neo4j:5.3.0-community
container_name: neo4j
ports:
- "7474:7474"
- "7687:7687"
environment:
- NEO4J_PLUGINS=["apoc"]
- NEO4J_AUTH=none
63 changes: 17 additions & 46 deletions src/neo4jsbml/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,62 +75,33 @@ def main():
help="Modelisation created and downloaded from arrow",
)

# Parameters
parser_parameters = parser.add_argument_group("Parameters")
parser_parameters.add_argument(
"--log-level",
choices=[
"debug",
"info",
"warning",
"error",
"critical",
"silent",
],
default="info",
help="Adds a console logger for the specified level (default: info)",
)
# Compute
args = parser.parse_args()

# Logging.
logger = logging.getLogger(name=_version.__app_name__)
formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - %(message)s", datefmt="%d-%m-%Y %H:%M"
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
datefmt="%d-%m-%Y %H:%M",
)
st_handler = logging.StreamHandler()
st_handler.setFormatter(formatter)
logger.addHandler(st_handler)
log_level = logging.NOTSET
if args.log_level == "debug":
log_level = logging.DEBUG
elif args.log_level == "info":
log_level = logging.INFO
elif args.log_level == "warning":
log_level = logging.WARNING
elif args.log_level == "error":
log_level = logging.ERROR
elif args.log_level == "critical":
log_level = logging.CRITICAL
logger.setLevel(log_level)

# Check arguments.
logger.info("Start - %s" % (_version.__app_name__,))
logging.info("Start - %s" % (_version.__app_name__,))
if not os.path.isfile(args.input_file_sbml):
logger.error("Model SBML file does not exist: %s" % (args.input_file_sbml,))
logging.error("Model SBML file does not exist: %s" % (args.input_file_sbml,))
parser.exit(1)
if not os.path.isfile(args.input_modelisation_json):
logger.error(
logging.error(
"Modelisation JSON file does not exist: %s"
% (args.input_modelisation_json,)
)
parser.exit(1)

# Connection to database
logger.info("Connection to database")
logging.info("Connection to database")
con = None
if args.input_config_file:
logger.warning("Configuration file is provided, ignore indiviual arguments")
logging.warning("Configuration file is provided, ignore indiviual arguments")
con = connect.Connect.from_config(path=args.input_config_file)
else:
con = connect.Connect(
Expand All @@ -147,31 +118,31 @@ def main():
parser.exit(1)

# Load model
logger.info("Load SBML file")
logging.info("Load SBML file")
sbm = sbml.Sbml.from_sbml(path=args.input_file_sbml, tag=args.input_tag_str)

# Load modelisation
logger.info("Load modelisation file")
logging.info("Load modelisation file")
arr = arrows.Arrows.from_json(path=args.input_modelisation_json)

# Mapping
logger.info("Map schema to data - nodes")
logging.info("Map schema to data - nodes")
nod = sbm.format_nodes(nodes=arr.nodes)

logger.info("Map schema to data - relationships")
logging.info("Map schema to data - relationships")
rel = sbm.format_relationships(relationships=arr.relationships)

# Import into neo4j
logger.info("Import into neo4j - nodes")
logging.info("Import into neo4j - nodes")
con.create_nodes(nodes=nod)

if arr.relationships is not None and len(arr.relationships) > 0:
logger.info("Import into neo4j - relationships")
logging.info("Import into neo4j - relationships")
con.create_relationships(relationships=rel)
else:
logger.info("None relationship created")
logging.info("None relationship created")

logger.info("End - %s" % (_version.__app_name__,))
logging.info("End - %s" % (_version.__app_name__,))

return 0

Expand Down
2 changes: 1 addition & 1 deletion src/neo4jsbml/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__app_name__ = "neo4jsbml"
__version__ = "0.8.2"
__version__ = "0.8.3"
10 changes: 5 additions & 5 deletions src/neo4jsbml/arrows.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def from_json(cls, path: str) -> "Arrows":
------
Arrows
"""
logger = logging.getLogger(name=_version.__app_name__)
data = {}
with open(path) as hd:
data = json.load(hd)
Expand All @@ -68,13 +67,14 @@ def from_json(cls, path: str) -> "Arrows":
arrow_node["properties"][snode.SNode.LABEL_ID] = arrow_node[
"properties"
].pop(id_label)
logger.warning(
logging.warning(
'Entity: %s has an "%s" in properties, but it will be renamed into: %s'
% (" ".join(arrow_node["labels"]), id_label, snode.SNode.LABEL_ID)
% (":".join(arrow_node["labels"]), id_label, snode.SNode.LABEL_ID)
)
if not is_id_found:
logger.warning(
logging.warning(
'Entity: %s has not "id" in properties, it will be added'
% (":".join(arrow_node["labels"]),)
)
arrow_node["properties"][snode.SNode.LABEL_ID] = "str"
# Append node
Expand All @@ -83,7 +83,7 @@ def from_json(cls, path: str) -> "Arrows":
relationships = []
for arrow_rel in data["relationships"]:
if arrow_rel["type"] == "str":
logger.warning(
logging.warning(
"A relationship must be have a type filled, %s will be skipped"
% (arrow_rel["id"],)
)
Expand Down
26 changes: 26 additions & 0 deletions src/neo4jsbml/cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import logging
import subprocess
from typing import List


def run(args: List[str], show_output: bool = True) -> subprocess.CompletedProcess:
"""Run a command line.
Parameters
----------
args: List[str]
A list of argument
show_output: bool (default: True)
Output command line
Return
------
subprocess.CompletedProcess
Return result obtained with subprocess
"""
ret = subprocess.run(args, capture_output=True, encoding="utf8")
if show_output and ret.stdout is not None:
logging.info(ret.stdout)
if show_output and ret.stderr is not None:
logging.warning(ret.stderr)
return ret
20 changes: 20 additions & 0 deletions src/neo4jsbml/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ class Entity(metaclass=ABCMeta):
The properties as defined by arrows.
Key are the name of the property to search in the SBML.
Values are unused.
Methods
-------
add_property(self, label: str, value: str, overwrite: bool = True) -> None
Add a property to the properties attribute
has_property(self, label: str) -> bool
Check if a node has a property
clean_properties(self)
Remove empty values
properties_to_neo4j() -> str
Format properties to insert in query
"""

def __init__(self, id: str, properties: Dict[str, str], *args, **kwargs) -> None:
Expand Down Expand Up @@ -76,6 +90,12 @@ def add_property(self, label: str, value: str, overwrite: bool = True) -> None:
self.properties[label] = value

def properties_to_neo4j(self) -> str:
"""Format properties to insert in query
Return
------
str
"""
data = "{"
for k, v in self.properties.items():
data += k
Expand Down
Loading

0 comments on commit e3b1771

Please sign in to comment.