From 299e08b0e5bde910d64a0d0400dbf61968f63325 Mon Sep 17 00:00:00 2001 From: Pavlos Stephanos Bekiaris <36934614+Paulocracy@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:39:19 +0200 Subject: [PATCH] Version 122 (#526) * Preparations for version 1.2.2 * Add installer scripts * Refurbishments & Add conda instructions * Update CI test and add Python version file * Add workflow_dispatch * Remove push * workflow_dispatch not needed * Use cplex==22.1.0 * Try cplex==22.1.1.2 * Try Python 3.10.14 * install cplex before cnapy * Pre-install jpype1 * Pre-install install-jdk>=1.1 * Pre-install pytest>=7.2 * Pre-install pyqt5 * use efmtool_link 0.0.8 * still need jpype1 install-jdk>=1.1 * try pip install * cleanup (?) * remove obsolete packaging instructions * Add openjdk; Enforce conda-forge; Fix run script * Fix extreme amount of bugs in install scripts * Set installers to 1.2.2 & Refurbish README * Info about conda package * README corrections and refurbishments * Fix Linux/MacOS installer * Fix Linux/MacOS installer again * Update CPLEX & Gurobi configuration dialogs --------- Co-authored-by: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Co-authored-by: axelvonkamp --- .github/workflows/ci-test.yml | 58 ++++-- .gitignore | 3 - .python-version | 1 + Packaging.md | 43 ----- README.md | 188 ++++++------------- cnapy/appdata.py | 2 +- cnapy/data/blank.svg | 2 +- cnapy/gui_elements/configuration_cplex.py | 22 +-- cnapy/gui_elements/configuration_gurobi.py | 18 +- constructor/linux/LICENSE | 201 --------------------- constructor/linux/README.md | 8 - constructor/linux/construct.yaml | 19 -- constructor/linux/post_install.sh | 6 - constructor/win/LICENSE | 201 --------------------- constructor/win/README.md | 83 --------- constructor/win/construct.yaml | 24 --- constructor/win/post_install.bat | 5 - constructor/win/welcome.png | Bin 19300 -> 0 bytes docs/index.md | 4 +- installers/install_cnapy_here.bat | 83 +++++++++ installers/install_cnapy_here.sh | 74 ++++++++ pyproject.toml | 4 +- recipes/linux/meta.yaml | 58 ------ recipes/noarch/app.ico | Bin 44379 -> 0 bytes recipes/noarch/bld.bat | 6 - recipes/noarch/menu-windows.json | 13 -- recipes/noarch/meta.yaml | 61 ------- recipes/win/app.ico | Bin 44379 -> 0 bytes recipes/win/bld.bat | 6 - recipes/win/menu-windows.json | 13 -- recipes/win/meta.yaml | 58 ------ 31 files changed, 278 insertions(+), 986 deletions(-) create mode 100644 .python-version delete mode 100644 Packaging.md delete mode 100644 constructor/linux/LICENSE delete mode 100644 constructor/linux/README.md delete mode 100644 constructor/linux/construct.yaml delete mode 100644 constructor/linux/post_install.sh delete mode 100644 constructor/win/LICENSE delete mode 100644 constructor/win/README.md delete mode 100644 constructor/win/construct.yaml delete mode 100644 constructor/win/post_install.bat delete mode 100644 constructor/win/welcome.png create mode 100644 installers/install_cnapy_here.bat create mode 100755 installers/install_cnapy_here.sh delete mode 100644 recipes/linux/meta.yaml delete mode 100644 recipes/noarch/app.ico delete mode 100644 recipes/noarch/bld.bat delete mode 100644 recipes/noarch/menu-windows.json delete mode 100644 recipes/noarch/meta.yaml delete mode 100644 recipes/win/app.ico delete mode 100644 recipes/win/bld.bat delete mode 100644 recipes/win/menu-windows.json delete mode 100644 recipes/win/meta.yaml diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 9ce6be1b..e0027cfe 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -1,39 +1,61 @@ name: CI Test -on: [push, pull_request] +on: [pull_request] jobs: build-linux: runs-on: "ubuntu-latest" steps: - uses: actions/checkout@v4 - - uses: conda-incubator/setup-miniconda@v3 + - name: Set up Python + uses: actions/setup-python@v4 with: - auto-update-conda: true - python-version: ${{ matrix.python-version }} - environment-file: environment.yml - miniforge-version: latest - activate-environment: cnapy + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest>=7.2 + - name: Install CNApy + run: | + pip install . - name: Test CNApy run: | - conda init bash - source ~/.bashrc - conda activate cnapy - python setup.py install pytest -v ./cnapy/tests/test.py build-windows: runs-on: "windows-latest" steps: - uses: actions/checkout@v4 - - uses: conda-incubator/setup-miniconda@v3 + - name: Set up Python + uses: actions/setup-python@v4 with: - auto-update-conda: true - python-version: ${{ matrix.python-version }} - environment-file: environment.yml - miniforge-version: latest - activate-environment: cnapy + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest>=7.2 + - name: Install CNApy + run: | + pip install . + - name: Test CNApy + run: | + pytest -v ./cnapy/tests/test.py + + build-macos: + runs-on: "macos-latest" + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest>=7.2 + - name: Install CNApy + run: | + pip install . - name: Test CNApy run: | - python setup.py install pytest -v ./cnapy/tests/test.py diff --git a/.gitignore b/.gitignore index 7afae7f0..c74f6067 100644 --- a/.gitignore +++ b/.gitignore @@ -75,9 +75,6 @@ target/ # Jupyter Notebook .ipynb_checkpoints -# pyenv -.python-version - # celery beat schedule file celerybeat-schedule diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..7c7a975f --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 \ No newline at end of file diff --git a/Packaging.md b/Packaging.md deleted file mode 100644 index be6286df..00000000 --- a/Packaging.md +++ /dev/null @@ -1,43 +0,0 @@ -# Packaging - -## First: Change the version number - -An easy way to do this in VS Code is to replace the current version number (which you can deduce from the current release) by replacing the version number globally with your desired new value. -If there are any now undesired additions such as beta, rc1 etc. you should remove them now. - -## Prerequisites - -```sh -conda install conda-build -conda install anaconda-client -conda install constructor -``` - -## Create and upload a conda package - -You have to create a noarch package for all systems except Windows and a win64 package for Windows. -Otherwise, without a specific win64 package, the Windows .exe installer won't work. - -```sh -conda config --add channels IBMDecisionOptimization -conda config --add channels Gurobi -conda config --add channels conda-forge - -cd recipes/noarch -conda-build . -c conda-forge -c cnapy -anaconda login -anaconda upload -u cnapy FILENAME - -cd .. -cd win -conda-build . -c conda-forge -c cnapy -anaconda login -anaconda upload -u cnapy FILENAME -``` - -## Create a windows installer with constructor - -```sh -cd constructor/win -constructor . -``` diff --git a/README.md b/README.md index 52bc6d3b..fe3c7d77 100644 --- a/README.md +++ b/README.md @@ -9,34 +9,39 @@ ## Introduction -**If you have questions, suggestions or bug reports regarding CNApy, you can use either of the [CNApy GitHub issues](https://github.com/cnapy-org/CNApy/issues), the [CNApy GitHub discussions](https://github.com/cnapy-org/CNApy/discussions) or the [CNApy Gitter chat room](https://gitter.im/cnapy-org/community).** +CNApy [[Paper]](https://doi.org/10.1093/bioinformatics/btab828) is a Python-based graphical user interface for a) many common methods of Constraint-Based Reconstruction and Analysis (COBRA) with stoichiometric metabolic models, b) the visualization of COBRA calculation results as *interactive and editable* metabolic maps (including Escher maps [[GitHub]](https://escher.github.io/#/)[[Paper]]()) and c) the creation and editing of metabolic models, including its reactions, metabolites and genes. For model loading and export, CNApy supports the widely used SBML standard format [[Site]](https://sbml.org/)[[Paper]](https://www.embopress.org/doi/abs/10.15252/msb.20199110). -CNApy is a Python-based graphical user interface for a) many common methods of Constraint-Based Reconstruction and Analysis (COBRA) with stoichiometric metabolic models, b) the visualization of COBRA calculation results and c) the creation and editing of metabolic models. +Supported COBRA methods (partly provided by cobrapy [[GitHub]](https://github.com/opencobra/cobrapy)[[Paper]](https://doi.org/10.1186/1752-0509-7-74)) include: -Supported COBRA methods (partly provided by [cobrapy](https://opencobra.github.io/cobrapy/)) include: +- Flux Balance Analysis (FBA) [[Review]](https://doi.org/10.1038/nbt.1614) +- Flux Variability Analysis (FVA) [[Paper]](https://doi.org/10.1016/j.ymben.2003.09.002) +- Yield optimization (based on linear-fractional programming) [[Paper]](https://doi.org/10.1016/j.ymben.2018.02.001) +- Phase plane analyses (can include flux and/or yield optimizations) +- Making measured *in vivo* flux scenarios stoichiometrically feasible, optionally also by altering a biomass reaction [[Paper]](https://academic.oup.com/bioinformatics/article/39/10/btad600/7284109) +- Elementary Flux Modes (EFM) [[Review]](https://analyticalsciencejournals.onlinelibrary.wiley.com/doi/full/10.1002/biot.201200269) +- Thermodynamic methods based on OptMDFpathway [[Paper]](https://doi.org/10.1371/journal.pcbi.1006492) +- Many advanced strain design algorithms such as OptKnock [[Paper]](https://doi.org/10.1002/bit.10803), RobustKnock [[Paper]](https://doi.org/10.1093/bioinformatics/btp704), OptCouple [[Paper]](https://doi.org/10.1016/j.mec.2019.e00087) and advanced Minimal Cut Sets [[Paper]](https://doi.org/10.1371/journal.pcbi.1008110) through its StrainDesign [[GitHub]](https://github.com/klamt-lab/straindesign)[[Paper]](https://doi.org/10.1093/bioinformatics/btac632) integration -- Flux Balance Analysis (FBA) -- Flux Variability Analysis (FVA) -- Making measured flux scenarios stoichiometrically feasible -- Elementary Flux Modes (EFM) -- Thermodynamic methods based on [OptMDFpathway](https://doi.org/10.1371/journal.pcbi.1006492) -- Many advanced strain design algorithms such as [OptKnock](https://doi.org/10.1002/bit.10803), [RobustKnock](https://doi.org/10.1093/bioinformatics/btp704), [OptCouple](https://doi.org/10.1016/j.mec.2019.e00087) and [advanced Minimal Cut Sets](https://doi.org/10.1371/journal.pcbi.1008110) through its integration of the [StrainDesign](https://github.com/klamt-lab/straindesign) package -- Yield optimization (based on linear-fractional programming) -- Phase plane analysis +**→ For information about how to install CNApy, see section [Installation Options](#installation-options)** -All calculation results can be visualized in CNApy's interactive and editable metabolic maps. These maps can also use vector-based (SVG) backgrounds. [Escher maps](https://escher.github.io/#/) are also natively supported and can be created and edited inside CNApy. +**→ For more details on CNApy's many features, see section [Documentation and Tutorials](#documentation-and-tutorials)** -Aside of performing calculations on metabolic models, CNApy can also be used to create and/or edit metabolic models. This includes all important aspects of the model's reactions, metabolites and genes. For model loading and export, CNApy supports the widely used [SBML standard format](https://sbml.org/). +**→ If you have questions, suggestions or bug reports regarding CNApy, you can use either of the [CNApy GitHub issues](https://github.com/cnapy-org/CNApy/issues), the [CNApy GitHub discussions](https://github.com/cnapy-org/CNApy/discussions) or the [CNApy Gitter chat room](https://gitter.im/cnapy-org/community)** -**For more details on CNApy's many more features, see section [Documentation and Tutorials](#documentation-and-tutorials).** +**→ If you want to cite CNApy, see section [How to cite CNApy](#how-to-cite-cnapy)** -**For information about how to install CNApy, see section [Installation Options](#installation-options).** +**→ For information about how to contribute to CNApy as a developer, see section [Contribute to the CNApy development](#contribute-to-the-cnapy-development)** -**For information about how to contribute to CNApy as a developer, see section [Contribute to the CNApy development](#contribute-to-the-cnapy-development).** +*Associated project note*: If you want to use the well-known MATLAB-based *CellNetAnalyzer* (CNA), *which is not compatible with CNApy*, you can download it from [CNA's website](https://www2.mpi-magdeburg.mpg.de/projects/cna/cna.html). -**If you want to cite CNApy, see section [How to cite CNApy](#how-to-cite-cnapy).** +## Installation Options -*Associated project note*: If you want to use the well-known MATLAB-based *CellNetAnalyzer* (CNA), *which is not compatible with CNApy*, you can download it from [CNA's website](https://www2.mpi-magdeburg.mpg.de/projects/cna/cna.html). +There are 4 alternative ways to install CNApy: + +1. The easiest way for any user to install CNApy is by downloading its installer, which is provided for Windows, Linux and MacOS, see [Using CNApy installer](#using-cnapy-installer) for more. +2. If you already have installed Python 3.10 (no other version) on your system, you can install CNApy simply through ```pip install cnapy``` in your console. Afterwards, you can start CNApy's GUI by running either ```cnapy``` or, if this doesn't work, ```python -m cnapy``` where "python" must call your Python 3.10 installation. +3. If you already use conda or mamba (for mamba, just change the "conda" command to "mamba"), you can create a CNApy environment named ```cnapy-1.2.2``` as follows: 1) Run ```conda create --name cnapy-1.2.2 python=3.10 pip openjdk -c conda-forge```, 2) run ```conda activate cnapy-1.2.2```, 3) run ```pip install cnapy```. Then, you can start CNApy in the cnapy-1.2.2 conda environment by running either ```cnapy``` or, if this doesn't work, ```python -m cnapy```. Note that the [cnapy conda package](https://anaconda.org/cnapy/cnapy) is currently *not* being updated due to licensing uncertainties. +4. If you want to develop CNApy, follow the instruction for the cloning and setup of the CNApy repository using git and conda or mamba in section [Setup the CNApy development environment](#setup-the-cnapy-development-environment). ## Documentation and Tutorials @@ -44,144 +49,63 @@ Aside of performing calculations on metabolic models, CNApy can also be used to - Our [CNApy YouTube channel](https://www.youtube.com/channel/UCRIXSdzs5WnBE3_uukuNMlg) provides some videos of working with CNApy. - We also provide directly usable [CNApy example projects](https://github.com/cnapy-org/CNApy-projects/releases/latest) which include some of the most common *E. coli* models. These projects can also be downloaded within CNApy at its first start-up or via CNApy's File menu. -## Installation Options - -There are 4 alternative ways to install CNApy: - -1. If you use Windows, the easiest way is to use our Windows installer, see section [Using the Windows installer](#using-the-windows-installer). -2. If you have Python 3.10 on your computer you can directly install CNApy from PyPI with: ```pip install cnapy```. -3. If you have installed [Anaconda](https://www.anaconda.com/), [Miniconda](https://docs.anaconda.com/free/miniconda/index.html) or [Miniforge](https://github.com/conda-forge/miniforge) on your computer, you can directly install CNApy as a conda package as described in section [Install CNApy as conda package](#install-cnapy-as-conda-package). *Note*: If you're on MacOS and want to use CPLEX as solver, you have to use the x86 version of Anaconda as the Apple Silicon one is not supported by CPLEX yet. -4. If you use Linux or Apple MacOS X, the easiest installation producure is our assisted installation protocol, see [Assisted installation under Linux and MacOS X](#assisted-installation-under-linux-and-macos-x). -5. If you want to develop CNApy, follow the instruction for the cloning and setup of the CNApy repository using git and conda or mamba in section [Setup the CNApy development environment](#setup-the-cnapy-development-environment). - -## Contribute to the CNApy development -Everyone is welcome to contribute to CNApy's development. [See our contribution file for more detailed instructions](https://github.com/cnapy-org/CNApy/blob/master/CONTRIBUTING.md). +## Using CNApy installer -## Using the Windows installer +This installer lets you create a local installation of CNApy under Windows, Linux or MacOS by following these instructions: -1. Download the zipped CNApy Windows installer [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.1/cnapy-windows-installer.zip). -2. Unzip the file into your desired location. You can do this by right-clicking on the file and selecting the option to extract the files. -3. In the location where you unzipped the file, click on "INSTALL_CNAPY.bat"; This installation procedure only works with an active internet conncection. As soon as the installation is finished, the appearing window closes and you can start CNApy either by double-clicking on the newly created CNApy shortcut on your desktop (which also shows CNApy's logo) or the newly created RUN_CNAPY.bat in the folder where INSTALL_CNAPY.bat lies. If CNApy is not starting, this might have been caused by an internet connection problem; Running "INSTALL_CNAPY.bat" again might solve the problem. To uninstall CNApy, double-click on the UNINSTALL_CNAPY.bat in the same folder. +*If you use Windows:* -## Assisted installation under Linux and MacOS X +- Download the Windows installer [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.2/install_cnapy_here.bat) +- Put this file into a folder where you want CNApy to be installed. +- Double click on the file and let the CNApy installation run +- Afterwards, you can run CNApy by either double-clicking on the newly created CNApy desktop icon, or by double-clicking "RUN_CNApy.bat" in the newly created cnapy-1.2.2 subfolder. -Click on the operating system you use: +*If you use Linux or MacOS*: -- [Linux](#assisted-linux-installation) -- [Apple MacOS X](#assisted-macos-x-installation) +- Download the Linux & MacOS installer [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.2/install_cnapy_here.sh). +- Put this file into a folder where you want CNApy to be installed. +- Make the script executable by opening your console in the folder and run ```chmod u+x ./install_cnapy_here.sh```. Alternatively, if supported on your system, right-click on the file, go the file's settings and mark it as executable. +- Now, either run ```./install_cnapy_here.sh``` in your console or, if supported on your system, double-click on install_cnapy_here.sh. +- Finally, you can run CNApy by calling ```./run_cnapy.sh``` in your console (for this without another path beforehand, your console must point to the folder where run_cnapy.sh is located, e.g. if you are in the folder where install_cnapy_here.sh is located, through ```cd cnapy-1.2.2```). Alternatively, if supported by your system, double-click on "run_cnapy.sh" in the newly created cnapy-1.2.2 subfolder. -### Assisted Linux installation +Technical side note: CNApy's installer is utilizing [micromamba](https://mamba.readthedocs.io/en/latest/installation/micromamba-installation.html). -1. Download Miniforge [from here](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh). -2. Install Miniforge by double-clicking the downloaded file. If the script does not run, right-click on the file, open its settings and select the option to make it executable (alternative: run 'chmod u+x ./Miniconda3-latest-Linux-x86_64.sh' in your terminal). Follow the appearing installation instructions and remember in which folder you install Miniconda. *Note*: If you already have installed Anaconda on your computer before (for which we also directly provide a conda CNApy package, [see here](#install-cnapy-as-conda-package)), deactivate all installation options which put Miniconda to your console or system PATH to avoid possible problems. -3. Using your file manager, go to the folder where you installed Miniforge. Then, open the appearing sub-folder "condabin". -4. Download the CNApy installation assistant script [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.1/cnapy-assistant-script.sh) into the mentioned "condabin" folder. -5. In the file manager, double-click on the newly downloaded installation assistant script which is called "cnapy-assistant-script.sh". If the script does not run, right-click on the file, open its settings and select the option to make it executable or, alternatively, run 'chmod u+x ./cnapy-assistant-script.sh' in your terminal in the mentioned "condabin" folder. Wait until CNApy is downloaded and installed. -6. You can now run CNApy by executing the following two terminal instructions in the mentioned "condabin" folder: +## Setup the CNApy development environment -```sh -./conda activate cnapy-1.2.1 -cnapy -``` +*Note:* The following instructions only have to be followed if you want to contribute to CNApy as a programmer. If this is not the case, follow other steps of the [Installation Options](#installation-options). -If you installed Miniforge system-wide, it's also possible to run these commands in any other terminal folder. +Everyone is welcome to contribute to CNApy's development. [See our contribution file for general instructions](https://github.com/cnapy-org/CNApy/blob/master/CONTRIBUTING.md). Any contribution intentionally submitted for inclusion in the work by you, shall be licensed under the terms of the Apache 2.0 license without any additional terms or conditions. -### Assisted MacOS X installation +Programatically, we recommend to use uv [[GitHub]](https://github.com/astral-sh/uv) to install all dependencies and manage installed Python versions. Alternatively, one can also use conda/mamba for the same tasks, although you would have to install CNApy's dependencies manually. -*Note*: Currently, if you want to use the CPLEX solver within CNApy, you have to install the Intel processor version of Miniconda regardless of your Mac's processor. This is caused by the lack of a CPLEX ARM Python package ([see also this issue for more details](https://github.com/cnapy-org/CNApy/issues/491)). +### uv usage +You can use uv for CNApy as follows: -1. If you have a (new) Mac with an ARM processor, such as the M1, M2 or M3, download Miniconda [from here](https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.pkg). If you have an (older) Mac with an Intel processor, download Miniconda [from here](https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.pkg). If you are unsure which processor your Mac has, click on the Apple menu in the upper-left of your screen and choose "About This Mac". -2. Install Miniconda by double-clicking the downloaded file. Follow the appearing installation instructions and remember in which folder you install Miniconda. *Note*: If you already use Anaconda on your computer (for which we directly provide a conda CNApy package, [see here](#install-cnapy-as-conda-package)), deactivate all installation options which put Miniconda to your console or system PATH to avoid possible problems -3. Using Finder, go to the folder where you installed Miniconda. Then, open the appearing sub-folder "condabin". -4. Download the CNApy installation assistant script [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.1/cnapy-assistant-script.sh) into the mentioned "condabin" folder. -5. In the file manager, double-click on the newly downloaded installation assistant script which is called "cnapy-installation-script.sh". If the script does not run, right-click on the file, open its settings and select the option to make it executable (alternative: run 'chmod u+x ./cnapy-assistant-script.sh' in your terminal). Wait until CNApy is downloaded and installed. -6. Open the terminal in the mentioned "condabin" folder. You can now run CNApy by executing the following two terminal instructions: +1. Make sure that you have installed uv (*Note*: uv can be installed under any Python version as uv will manage the needed Python version later): ```sh -./conda activate cnapy-1.2.1 -cnapy +pip install uv ``` -## Install CNApy as conda package - -*Note for Mac users (does not affect Windows or Linux users)*: Currently, if you want to use the CPLEX solver within CNApy, you have to install the Intel processor version of Anaconda/Miniconda/Miniforge regardless of your Mac's processor. This is caused by the lack of a CPLEX ARM Python package ([see also this issue for more details](https://github.com/cnapy-org/CNApy/issues/491)). - -*Note for all users*: If you've installed mamba on your system (e.g., with [Miniforge](https://github.com/conda-forge/miniforge)), it is the recommended way to install CNApy as it is much faster than conda. To use mamba, just replace the "conda" command in the following steps with "mamba". - -1. Create a conda environment with all dependencies - - ```sh - conda create -n cnapy-1.2.1 -c Gurobi -c IBMDecisionOptimization -c conda-forge -c cnapy cnapy=1.2.1 --yes - ``` - -2. Activate the cnapy conda environment - - ```sh - conda activate cnapy-1.2.1 - ``` - -3. Run CNApy within you activated conda environment +2. Checkout the latest cnapy development version using git - ```sh - cnapy - ``` - -Furthermore, you can also perform the following optional steps: - -4. (optional and only possible if you have already installed CNApy by using conda) If you already have a cnapy environment, e.g., cnapy-1.X.X, you can delete it with the command - - ```sh - # Here, the Xs stand for the last CNApy version you've installed by using conda - conda env remove -n cnapy-1.X.X - ``` - -5. (optional, but recommended if you also use other Python distributions or Anaconda environments) In order to solve potential package version problems, set a systems variable called "PYTHONNOUSERSITE" to the value "True". - - Under Linux systems, you can do this with the following command: - - ```sh - export PYTHONNOUSERSITE=True - ``` - - Under Windows systems, you can do this by searching for your system's "environmental variables" and adding - the variable PYTHONNOUSERSITE with the value True using Window's environmental variables setting window. - -## Setup the CNApy development environment - -We use conda as package manager to install all dependencies. You can use [miniconda](https://docs.conda.io/en/latest/miniconda.html). -If you have conda installed you can: - -1. Create a conda development environment with all dependencies - - ```sh - conda env create -n cnapy-dev -f environment.yml - ``` - -2. Activate the development environment - - ```sh - conda activate cnapy-dev - ``` - -3. Checkout the latest cnapy development version using git - - ```sh - git clone https://github.com/cnapy-org/CNApy.git - ``` +```sh +git clone https://github.com/cnapy-org/CNApy.git +``` -4. Change into the source directory and run CNApy +3. Change into the source directory and run CNApy - ```sh - cd CNApy - python cnapy.py - ``` +```sh +cd CNApy +uv run cnapy.py +``` -Any contribution intentionally submitted for inclusion in the work by you, shall be licensed under the terms of the Apache 2.0 license without any additional terms or conditions. +uv will automatically install the correct Python version (by reading ./.python-version) and CNApy dependencies (by reading ./pyproject.toml). If you get a Java/JDK/JVM/jpype error when running CNApy, consider installing OpenJDK [[Site]](https://openjdk.org/install/) on your system to fix this problem. ## How to cite CNApy -If you use CNApy in your scientific work, please consider to cite CNApy's publication: +If you use CNApy in your scientific work, please cite CNApy's publication: Thiele et al. (2022). CNApy: a CellNetAnalyzer GUI in Python for analyzing and designing metabolic networks. *Bioinformatics* 38, 1467-1469, [doi.org/10.1093/bioinformatics/btab828](https://doi.org/10.1093/bioinformatics/btab828). diff --git a/cnapy/appdata.py b/cnapy/appdata.py index c341f768..463a8e4a 100644 --- a/cnapy/appdata.py +++ b/cnapy/appdata.py @@ -31,7 +31,7 @@ class AppData(QObject): def __init__(self): QObject.__init__(self) - self.version = "cnapy-1.2.1" + self.version = "cnapy-1.2.2" self.format_version = 2 self.unsaved = False self.project = ProjectData() diff --git a/cnapy/data/blank.svg b/cnapy/data/blank.svg index 1fb4d437..264fdc8a 100644 --- a/cnapy/data/blank.svg +++ b/cnapy/data/blank.svg @@ -5,7 +5,7 @@ viewBox="0 0 482.67059 404.35686" id="svg2" version="1.1" - inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)" + inkscape:version="1.2.2 (9c6d41e410, 2022-07-14)" sodipodi:docname="blank.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" diff --git a/cnapy/gui_elements/configuration_cplex.py b/cnapy/gui_elements/configuration_cplex.py index 90a1f2a7..b0efeab7 100644 --- a/cnapy/gui_elements/configuration_cplex.py +++ b/cnapy/gui_elements/configuration_cplex.py @@ -24,21 +24,19 @@ def __init__(self, appdata: AppData): "By default, right after CNApy's installation, you have only access to the IBM CPLEX Community Edition\n" "which can only handle up to 1000 variables simultaneously.\n" "In order to use the full version of IBM CPLEX, with no variable number limit, follow the next steps in the given order:\n" - "1. (only if not already done and only necessary if you encounter problems with the following steps despite the installation tips in step 3)\n" + "1. (only necessary if you encounter problems with the following steps despite the installation tips in step 3)\n" "Restart CNApy with administrator privileges as follows:\n" " i) Close this session of CNApy\n" " ii) Find out your operating system by looking at the next line:\n" f" {platform.system()}\n" - " iii) Depending on your operating system, do the following:\n" - " >Only if you use Windows: If you used CNApy's exe installer: Right click on cnapy.exe or the CNApy desktop icon\n" + " iii) Depending on your operating system:\n" + " >Only if you use Windows: If you used CNApy's bat installer: Right click on RUN_CNApy.bat or the CNApy desktop icon\n" " or the CNApy entry in the start menu's program list and select 'Run as adminstrator'.\n" - " If you didn't use CNApy's .exe installer: Search for 'cmd.exe', right-click on its symbol and\n" - " select 'Run as administrator'. Then, move to CNApy's folder with the cd command, activate CNApy's\n" - " Anaconda environment with 'conda activate cnapy-dev' and run 'python cnapy.py'.\n" - " >Only if you use Linux or MacOS (MacOS is also called Darwin): The most common way is by using the 'sudo' command. To do this, \n" - " open your system's terminal, move to CNApy's folder with the cd command, activate CNApy's Anaconda\n" - " environment with 'conda activate cnapy-dev' and run 'sudo python cnapy.py'. For the last part, you may need to enter an adminstrator\n" - " password.\n" + " If you didn't use CNApy's .bat installer but Python or conda/mamba, start your Windows console or Powershell with administrator rights\n" + " and startup CNApy." + " >Only if you use Linux or MacOS (MacOS may be called Darwin): The most common way is by using the 'sudo' command. If you used the\n" + " CNApy sh installer, you can start CNApy with administrator rights through 'sudo run_cnapy.sh'. If you didn't use CNApy's .bat installer\n" + " but Python or conda/mamba, run your usual CNApy command with 'sudo' in front of it.\n" " NOTE: It may be possible that you're not allowed to get administrator rights on your computer. If this is the case, contact your system's administrator to resolve the problem.\n" "2. (if not already done) Obtain an IBM CPLEX license and download IBM CPLEX itself onto your computer.\n" " NOTE: CNApy only works with recent IBM CPLEX versions (not older than version 20.1.0)!\n" @@ -51,7 +49,7 @@ def __init__(self, appdata: AppData): self.cplex_directory = QPushButton() self.cplex_directory.setText( - "NOT SET YET! PLEASE SET THE PATH TO IBM CPLEX (see steps 1 to 3 above)." + "NOT SET YET! PLEASE SET THE PATH TO THE IBM CPLEX MAIN FOLDER (see steps 1 to 3 above)." ) self.layout.addWidget(self.cplex_directory) @@ -80,7 +78,7 @@ def __init__(self, appdata: AppData): "Select 'edit environmental variables for this account' (or similar) and, in the newly opened window, click the 'New' button. Write 'PYTHONPATH' as the\n" "variable's name and write, as a value, the path given above in this step 5. Then, click 'OK' and again 'OK'.\n" "> Only if you use Linux or MacOS (MacOS is also called Darwin): In your console, run 'export PYTHONPATH=PATH' (without the quotation marks) where PATH has to be the path\n" - "given under this step 5 above." + "given under this step 5 above. Alternatively, if this doesn't work, set the PYTHONPATH variable in the run_cnapy.sh in the quoted line and un-quote it." ) self.layout.addWidget(label) diff --git a/cnapy/gui_elements/configuration_gurobi.py b/cnapy/gui_elements/configuration_gurobi.py index 03d4b012..d789d9e7 100644 --- a/cnapy/gui_elements/configuration_gurobi.py +++ b/cnapy/gui_elements/configuration_gurobi.py @@ -29,16 +29,14 @@ def __init__(self, appdata: AppData): " i) Close this session of CNApy\n" " ii) Find out your operating system by looking at the next line:\n" f" {platform.system()}\n" - " iii) Depending on your operating system, do the following:\n" - " >Only if you use Windows: If you used CNApy's exe installer: Right click on cnapy.exe or the CNApy desktop icon\n" + " iii) Depending on your operating system:\n" + " >Only if you use Windows: If you used CNApy's bat installer: Right click on RUN_CNApy.bat or the CNApy desktop icon\n" " or the CNApy entry in the start menu's program list and select 'Run as adminstrator'.\n" - " If you didn't use CNApy's .exe installer: Search for 'cmd.exe', right-click on its symbol and\n" - " select 'Run as administrator'. Then, move to CNApy's folder with the cd command, activate CNApy's\n" - " Anaconda environment with 'conda activate cnapy-dev' and run 'python cnapy.py'.\n" - " >Only if you use Linux or MacOS (MacOS is also called Darwin): The most common way is by using the 'sudo' command. To do this, \n" - " open your system's terminal, move to CNApy's folder with the cd command, activate CNApy's Anaconda\n" - " environment with 'conda activate cnapy-dev' and run 'sudo python cnapy.py'. For the last part, you may need to enter an adminstrator\n" - " password.\n" + " If you didn't use CNApy's .bat installer but Python or conda/mamba, start your Windows console or Powershell with administrator rights\n" + " and startup CNApy." + " >Only if you use Linux or MacOS (MacOS may be called Darwin): The most common way is by using the 'sudo' command. If you used the\n" + " CNApy sh installer, you can start CNApy with administrator rights through 'sudo run_cnapy.sh'. If you didn't use CNApy's .bat installer\n" + " but Python or conda/mamba, run your usual CNApy command with 'sudo' in front of it.\n" " NOTE: It may be possible that you're not allowed to get administrator rights on your computer. If this is the case, contact your system's administrator to resolve the problem.\n" "2. (if not already done) Obtain an Gurobi license and download Gurobi itself onto your computer.\n" " NOTE: CNApy only works with recent Gurobi versions (not older than version 20.1.0)!\n" @@ -51,7 +49,7 @@ def __init__(self, appdata: AppData): self.gurobi_directory = QPushButton() self.gurobi_directory.setText( - "NOT SET YET! PLEASE SET THE PATH TO GUROBI (see steps 1 to 3 above)." + "NOT SET YET! PLEASE SET THE PATH TO THE GUROBI MAIN FOLDER (see steps 1 to 3 above)." ) self.layout.addWidget(self.gurobi_directory) diff --git a/constructor/linux/LICENSE b/constructor/linux/LICENSE deleted file mode 100644 index 261eeb9e..00000000 --- a/constructor/linux/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/constructor/linux/README.md b/constructor/linux/README.md deleted file mode 100644 index 630ca4f9..00000000 --- a/constructor/linux/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# CNApy - An integrated environment for metabolic network analysis - -## How to run a script in the CNApy terminal - -```python -import testscript -testscript.run(cna) -``` diff --git a/constructor/linux/construct.yaml b/constructor/linux/construct.yaml deleted file mode 100644 index 26cd5f3b..00000000 --- a/constructor/linux/construct.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: CNApy -version: 1.2.1 - -ignore_duplicate_files: True - -channels: - - http://repo.anaconda.com/pkgs/main/ - - cnapy - - conda-forge - -specs: - - conda - - pip - - python=3.8 - - menuinst [win] - -license_file: LICENSE - -post_install: post_install.sh diff --git a/constructor/linux/post_install.sh b/constructor/linux/post_install.sh deleted file mode 100644 index a5f9c32a..00000000 --- a/constructor/linux/post_install.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -source $PREFIX/etc/profile.d/conda.sh -conda activate $PREFIX - -conda install -v -c cnapy -c conda-forge --yes -conda clean --all --yes \ No newline at end of file diff --git a/constructor/win/LICENSE b/constructor/win/LICENSE deleted file mode 100644 index 261eeb9e..00000000 --- a/constructor/win/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/constructor/win/README.md b/constructor/win/README.md deleted file mode 100644 index 7c0e4e17..00000000 --- a/constructor/win/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# CNApy - -## *An integrated environment for metabolic network analysis* - -![CNApy screenshot](screenshot.png) - - -## Downloads - -- The latest release can be found on the [release page](https://github.com/cnapy-org/CNApy/releases/latest) - -- The [CNApy user guide](https://cnapy-org.github.io/CNApy/CNApyUsersGuide.html) - -- Example projects [CNApy projects](https://github.com/cnapy-org/CNApy-projects/releases/latest) - -## Video tutorials - -- [Create a new CNApy project](http://www.youtube.com/watch?v=bsNXZBmtyWw) -- [Perform FBA and FVA with CNApy](http://www.youtube.com/watch?v=I5RJjXRBRaQ) - -## Install CNApy with conda - -We use conda as package manager to install CNApy. You can use [miniconda](https://docs.conda.io/en/latest/miniconda.html). - -1. Create a conda environment with all dependencies - ```sh - conda create -n cnapy-1.2.1 -c conda-forge -c cnapy cnapy=1.2.1 - ``` - -2. Activate the cnapy conda environment - ``` - conda activate cnapy-1.2.1 - ``` - -3. Run CNApy - ``` - cnapy - ``` - - -## How to run a script in the CNApy terminal - -A toy example is included in this repository [here](https://github.com/cnapy-org/CNApy/blob/master/testscript.py). -You can execute the script from the CNApy console like this. - -```python -import testscript -testscript.run(cna) -``` - -## Contributing - -[How to make a contribution to `CNApy`?](https://github.com/cnapy-org/CNApy/blob/master/CONTRIBUTING.md) - -Any contribution intentionally submitted for inclusion in the work by you, shall be licensed under the terms of the Apache 2.0 license without any additional terms or conditions. - -## Setup the CNApy development environment with conda - -We use conda as package manager to install all dependencies. You can use [miniconda](https://docs.conda.io/en/latest/miniconda.html). -If you have conda installed you can: - - -1. Create a conda devlopment environment with all dependencies - ``` - conda env create -n cnapy-dev -f environment.yml - ``` - -2. Activate the development environment - ``` - conda activate cnapy-dev - ``` - -2. Checkout the latest cnapy development version using git - ``` - git clone https://github.com/cnapy-org/CNApy.git - ``` - -3. Change into the source directory and run CNApy - ``` - cd CNApy - python cnapy.py - ``` -Any contribution intentionally submitted for inclusion in the work by you, shall be licensed under the terms of the Apache 2.0 license without any additional terms or conditions. diff --git a/constructor/win/construct.yaml b/constructor/win/construct.yaml deleted file mode 100644 index a80e4f59..00000000 --- a/constructor/win/construct.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: CNApy -version: 1.2.1 - -ignore_duplicate_files: True - -channels: - - http://repo.anaconda.com/pkgs/main/ - - cnapy - - conda-forge - -specs: - - conda - # - cnapy=1.2.1 - - mamba - - pip - - python=3.8 - - menuinst [win] - -license_file: LICENSE - -# Welcome image for Windows installer -welcome_image: welcome.png [win] - -post_install: post_install.bat diff --git a/constructor/win/post_install.bat b/constructor/win/post_install.bat deleted file mode 100644 index 441d7135..00000000 --- a/constructor/win/post_install.bat +++ /dev/null @@ -1,5 +0,0 @@ -call %~dp0..\Scripts\activate.bat - -call mamba install cnapy=1.2.1 -c cnapy -c conda-forge -v --yes -call pause -call %~dp0..\Scripts\conda clean --all --yes diff --git a/constructor/win/welcome.png b/constructor/win/welcome.png deleted file mode 100644 index 989a3915179eb645f60192526f3b0e2f6856594c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19300 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
    K{9?OZLRae4J7shG+oR=xQC$maOQng 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 "%psFile%" +echo. >> "%psFile%" +echo $CNAPY_VERSION = "1.2.2" ^# Replace with the actual version if needed >> "%psFile%" +echo $RELEASE_URL="https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-win-64" >> "%psFile%" +echo. >> "%psFile%" +echo Write-Output "Downloading micromamba from $RELEASE_URL" >> "%psFile%" +echo curl.exe -L -o micromamba.exe $RELEASE_URL >> "%psFile%" +echo. >> "%psFile%" +echo ^# Get the directory where the script is located >> "%psFile%" +echo $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path >> "%psFile%" +echo. >> "%psFile%" +echo $InstallDir = Join-Path -Path $ScriptDir -ChildPath "cnapy-$CNAPY_VERSION" >> "%psFile%" +echo New-Item -ItemType Directory -Force -Path $InstallDir ^| out-null >> "%psFile%" +echo. >> "%psFile%" +echo $MAMBA_INSTALL_PATH = Join-Path -Path $InstallDir -ChildPath "micromamba.exe" >> "%psFile%" +echo. >> "%psFile%" +echo Write-Output "`nInstalling micromamba to $InstallDir`n" >> "%psFile%" +echo Move-Item -Force micromamba.exe $MAMBA_INSTALL_PATH ^| out-null >> "%psFile%" +echo. >> "%psFile%" +echo ^# Use ^& to execute the micromamba commands stored in the variable >> "%psFile%" +echo ^& $MAMBA_INSTALL_PATH create -y -p "./cnapy-$CNAPY_VERSION/cnapy-environment" python=3.10 pip openjdk -r "./cnapy-$CNAPY_VERSION/" -c conda-forge >> "%psFile%" +echo Copy-Item -Path "cnapy-1.2.2/condabin/mamba.bat" -Destination "cnapy-1.2.2/condabin/micromamba.bat" >> "%psFile%" +echo ^& $MAMBA_INSTALL_PATH run -p "./cnapy-$CNAPY_VERSION/cnapy-environment" -r "./cnapy-$CNAPY_VERSION/" pip install --no-cache-dir uv >> "%psFile%" +echo ^& $MAMBA_INSTALL_PATH run -p "./cnapy-$CNAPY_VERSION/cnapy-environment" -r "./cnapy-$CNAPY_VERSION/" uv --no-cache pip install --no-cache-dir cnapy >> "%psFile%" +echo. >> "%psFile%" +echo ^# Create a new PowerShell file called "cnapy_runner_helper.ps1" >> "%psFile%" +echo $PsFilePath = Join-Path -Path $InstallDir -ChildPath "cnapy_runner_helper.ps1" >> "%psFile%" +echo $PsFileContent = "$MAMBA_INSTALL_PATH run -p `"$InstallDir\cnapy-environment`" -r `"$InstallDir\`" cnapy" >> "%psFile%" +echo Set-Content -Path $PsFilePath -Value $PsFileContent >> "%psFile%" +echo. >> "%psFile%" +echo ^# Create a new batch file called "RUN_CNApy.bat" >> "%psFile%" +echo $BatchFilePath = Join-Path -Path $InstallDir -ChildPath "RUN_CNApy.bat" >> "%psFile%" +echo $BatchFileContent = "powershell -NoProfile -ExecutionPolicy Bypass -File `"$InstallDir\cnapy_runner_helper.ps1`"" >> "%psFile%" +echo Set-Content -Path $BatchFilePath -Value $BatchFileContent >> "%psFile%" +echo. >> "%psFile%" +echo ^# Create desktop icon using PowerShell >> "%psFile%" +echo $ShortcutPath = [System.IO.Path]::Combine($Env:USERPROFILE, "Desktop", "CNApy-$CNAPY_VERSION.lnk") >> "%psFile%" +echo $WScriptShell = New-Object -ComObject WScript.Shell >> "%psFile%" +echo $Shortcut = $WScriptShell.CreateShortcut($ShortcutPath) >> "%psFile%" +echo $Shortcut.TargetPath = $BatchFilePath >> "%psFile%" +echo ^# $Shortcut.IconLocation = Join-Path -Path $ScriptDir -ChildPath "icon\CNApy_Icon.ico" >> "%psFile%" +echo $Shortcut.WorkingDirectory = $ScriptDir >> "%psFile%" +echo $Shortcut.Save() >> "%psFile%" +echo. >> "%psFile%" +echo Write-Output "`nDesktop shortcut created successfully`n" >> "%psFile%" + +:: Ensure the PowerShell script file exists before running it +if exist "%psFile%" ( + :: Run the PowerShell script + powershell -NoProfile -ExecutionPolicy Bypass -File "%psFile%" + if %errorlevel% neq 0 ( + echo An error occurred while running the PowerShell script. CNApy was not installed correctly. + echo If PowerShell was not found, install it on your device. + del "%psFile%" + pause + exit /b 1 + ) + + :: Delete the PowerShell script file + del "%psFile%" + + :: Congratulate the user + echo Congratulations! CNApy was successfully installed! + echo To run CNApy, double-click on the newly created CNApy-1.2.2 desktop icon or, + echo alternatively, double-click on the RUN_CNApy.bat file in the newly created cnapy-1.2.2 subfolder. + echo To deinstall CNApy later, simply delete the newly created cnapy-1.2.2 subfolder. + pause +) else ( + echo PowerShell script file not found: %psFile% + echo Maybe your disk is full or you need to install CNApy in a folder where you allowed to write new files. + echo This is because, often, folders such as the default Programs folder are restricted, so that other folders might work. + echo Alternatively, you might need to run this installer with administrator priviledges! + pause +) + +endlocal diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh new file mode 100755 index 00000000..23361afd --- /dev/null +++ b/installers/install_cnapy_here.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# Adapted from https://raw.githubusercontent.com/mamba-org/micromamba-releases/main/install.sh + +set -eu + +# CNApy version +CNAPY_VERSION="1.2.2" + +# Folders +BIN_FOLDER="${BIN_FOLDER:-./cnapy-${CNAPY_VERSION}}" +CONDA_FORGE_YES="${CONDA_FORGE_YES:-yes}" + +# Computing artifact location +case "$(uname)" in + Linux) + PLATFORM="linux" ;; + Darwin) + PLATFORM="osx" ;; + *NT*) + PLATFORM="win" ;; +esac + +ARCH="$(uname -m)" +case "$ARCH" in + aarch64|ppc64le|arm64) + ;; # pass + *) + ARCH="64" ;; +esac + +case "$PLATFORM-$ARCH" in + linux-aarch64|linux-ppc64le|linux-64|osx-arm64|osx-64|win-64) + ;; # pass + *) + echo "Failed to detect your operating system. This installer only supports linux-aarch64|linux-ppc64le|linux-64|osx-arm64|osx-64|win-64" >&2 + exit 1 + ;; +esac + +RELEASE_URL="https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-${PLATFORM}-${ARCH}" + +# Downloading artifact +mkdir -p "${BIN_FOLDER}" +if hash curl >/dev/null 2>&1; then + curl "${RELEASE_URL}" -o "${BIN_FOLDER}/micromamba" -fsSL --compressed ${CURL_OPTS:-} +elif hash wget >/dev/null 2>&1; then + wget ${WGET_OPTS:-} -qO "${BIN_FOLDER}/micromamba" "${RELEASE_URL}" +else + echo "Neither curl nor wget was found. Please install one of them on your system." >&2 + exit 1 +fi +chmod +x "${BIN_FOLDER}/micromamba" + +./cnapy-${CNAPY_VERSION}/micromamba create -y -p ./cnapy-${CNAPY_VERSION}/cnapy-environment python=3.10 pip openjdk -r ./cnapy-${CNAPY_VERSION}/ -c conda-forge +./cnapy-${CNAPY_VERSION}/micromamba run -p ./cnapy-${CNAPY_VERSION}/cnapy-environment -r ./cnapy-${CNAPY_VERSION}/ pip install --no-cache-dir uv +./cnapy-${CNAPY_VERSION}/micromamba run -p ./cnapy-${CNAPY_VERSION}/cnapy-environment -r ./cnapy-${CNAPY_VERSION}/ uv --no-cache pip install --no-cache-dir cnapy + +cat << 'EOF' > ./cnapy-${CNAPY_VERSION}/run_cnapy.sh +#!/bin/bash + +# Add CPLEX variable here, e.g. +# export PYTHONPATH=/path_to_cplex/cplex/python/3.10/x86-64_linux + +export LD_LIBRARY_PATH="./cnapy-environment/lib/" # For Linux +export DYLD_LIBRARY_PATH="./cnapy-environment/lib/" # For MacOS +./micromamba run -p ./cnapy-environment cnapy +EOF + +# Make the shell script executable +chmod +x ./cnapy-${CNAPY_VERSION}/run_cnapy.sh + +echo CNApy was succesfully installed! +echo You can now run CNApy by executing run_cnapy.sh in the newly created cnapy-${CNAPY_VERSION} subfolder. +echo To deinstall CNApy later, simply delete the cnapy-${CNAPY_VERSION} subfolder. diff --git a/pyproject.toml b/pyproject.toml index fcb65235..41b3240d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cnapy" -version = "1.2.1.1" +version = "1.2.2" authors = [ { name="Sven Thiele" }, { name="Axel von Kamp" }, @@ -16,7 +16,7 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = ["appdirs>=1.4", "matplotlib>=3.6", "requests>=2.28", - "cobra>=0.29", "efmtool_link>=0.0.7", "optlang_enumerator>=0.0.12", "straindesign>=1.12", + "cobra>=0.29", "efmtool_link>=0.0.8", "optlang_enumerator>=0.0.12", "straindesign>=1.12", "qtpy>=2.3", "pyqtwebengine>=5.15", "qtconsole==5.4", "gurobipy>=11.0", "cplex>=22.1", "numpy==1.23", "scipy==1.12", "openpyxl"] diff --git a/recipes/linux/meta.yaml b/recipes/linux/meta.yaml deleted file mode 100644 index fc70b610..00000000 --- a/recipes/linux/meta.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{% set version = '1.2.1' %} - -package: - name: cnapy - version: {{ version }} - -source: - git_url: https://github.com/cnapy-org/CNApy.git - git_rev: v{{ version }} - -requirements: - channels: - - cnapy - - conda-forge - - defaults - - Gurobi - - IBMDecisionOptimization - build: - - setuptools - - pip - - python=3.8 - run: - - pydantic=1.10 - - matplotlib-base=3.6 - - python=3.8 - - qtpy=2.3 - - pyqtwebengine=5.15 - - appdirs=1.4 - - cobra>=0.26.3 - - qtconsole=5.4 - - requests=2.28 - - psutil=5.9 - - efmtool_link>=0.0.6 - - optlang_enumerator>=0.0.11 - - straindesign>=1.9 - - gurobi - - cplex - - numpy=1.23 - - openpyxl - -build: - number: 0 # NOTE: increment for new build/set to zero for new version - script: - - python setup.py install --single-version-externally-managed --record record.txt - entry_points: - - cnapy = cnapy.__main__:main_cnapy -test: - imports: - - cnapy - -about: - home: https://github.com/cnapy-org/CNApy - license: Apache 2 - license_family: MIT - license_file: LICENSE - summary: An integrated environment for metabolic network analysis - doc_url: https://github.com/cnapy-org/CNApy - dev_url: https://github.com/cnapy-org/CNApy \ No newline at end of file diff --git a/recipes/noarch/app.ico b/recipes/noarch/app.ico deleted file mode 100644 index f6c6c151f1427b558fa230f957566ccdde0929cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44379 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 X;>yPs31jq5T2ppP+n4c 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.26.3 - - qtconsole=5.4 - - requests=2.28 - - psutil=5.9 - - efmtool_link>=0.0.6 - - optlang_enumerator>=0.0.11 - - straindesign>=1.9 - - nest-asyncio - - gurobi - - cplex - - numpy=1.23 - - openpyxl - -build: - noarch: python - number: 0 # NOTE: increment for new build/set to zero for new version - script: - - python setup.py install --single-version-externally-managed --record record.txt - entry_points: - - cnapy = cnapy.__main__:main_cnapy -test: - imports: - - cnapy - -about: - home: https://github.com/cnapy-org/CNApy - license: Apache 2 - license_family: MIT - license_file: LICENSE - summary: An integrated environment for metabolic network analysis - doc_url: https://github.com/cnapy-org/CNApy - dev_url: https://github.com/cnapy-org/CNApy \ No newline at end of file diff --git a/recipes/win/app.ico b/recipes/win/app.ico deleted file mode 100644 index f6c6c151f1427b558fa230f957566ccdde0929cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44379 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 X;>yPs31jq5T2ppP+n4c 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.26.3 - - qtconsole=5.4 - - requests=2.28 - - psutil=5.9 - - efmtool_link>=0.0.6 - - optlang_enumerator>=0.0.11 - - straindesign>=1.9 - - nest-asyncio - - gurobi - - cplex - - numpy=1.23 - - openpyxl - -build: - number: 0 # NOTE: increment for new build/set to zero for new version - entry_points: - - cnapy = cnapy.__main__:main_cnapy -test: - imports: - - cnapy - -about: - home: https://github.com/cnapy-org/CNApy - license: Apache 2 - license_family: MIT - license_file: LICENSE - summary: An integrated environment for metabolic network analysis - doc_url: https://github.com/cnapy-org/CNApy - dev_url: https://github.com/cnapy-org/CNApy \ No newline at end of file