From 486d68ec743e3711462a614a19a2745f7016c045 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Wed, 25 Sep 2024 12:46:50 +0200 Subject: [PATCH 01/28] Preparations for version 1.2.2 --- README.md | 184 ++++++++------------------- cnapy/appdata.py | 2 +- cnapy/data/blank.svg | 2 +- 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 +- pyproject.toml | 2 +- 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 --------- 23 files changed, 58 insertions(+), 898 deletions(-) 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 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/README.md b/README.md index 52bc6d3b..f0f017f9 100644 --- a/README.md +++ b/README.md @@ -9,179 +9,101 @@ ## 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]](https://doi.org/10.1371/journal.pcbi.1004321)) and c) the creation and editing of metabolic models. -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 +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 [[Site]](https://sbml.org/)[[Paper]](https://www.embopress.org/doi/abs/10.15252/msb.20199110). -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 information about how to install CNApy, see section [Installation Options](#installation-options)** -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/). +**→ For more details on CNApy's many features, see section [Documentation and Tutorials](#documentation-and-tutorials)** -**For more details on CNApy's many more features, see section [Documentation and Tutorials](#documentation-and-tutorials).** +**→ 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 information about how to install CNApy, see section [Installation Options](#installation-options).** +**→ If you want to cite CNApy, see section [How to cite CNApy](#how-to-cite-cnapy)** -**For information about how to contribute to CNApy as a developer, see section [Contribute to the CNApy development](#contribute-to-the-cnapy-development).** - -**If you want to cite CNApy, see section [How to cite CNApy](#how-to-cite-cnapy).** +**→ 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). +## Installation Options + +There are 3 alternative ways to install CNApy: + +1. The easiest way 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 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 - The [CNApy guide](https://cnapy-org.github.io/CNApy-guide/) contains information for all major functions of CNApy. - 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). +## Using CNApy installer -## Contribute to the CNApy development +This installer lets you create a local and portable installation of CNApy under Windows, Linux or MacOS by following these instructions: -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). +*If you use Windows:* +* Download the Windows installer [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.2/install_cnapy_here.ps1) +* 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. -## Using the Windows installer +*If you use Linux or MacOS*: +* 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```. +* Now, either run ```./install_cnapy_here.sh``` in your console or double-click on install_cnapy_here.sh. +* Finally, you can run CNApy by double-clicking "run_cnapy.sh" in the newly created cnapy-1.2.2 subfolder or by calling run_cnapy.sh in your console (for the latter, your console must point to the folder where run_cnapy.sh is located). -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. +Technical side note: CNApy's installer is utilizing [micomamba](https://mamba.readthedocs.io/en/latest/installation/micromamba-installation.html). -## Assisted installation under Linux and MacOS X +## Setup the CNApy development environment -Click on the operating system you use: +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). -- [Linux](#assisted-linux-installation) -- [Apple MacOS X](#assisted-macos-x-installation) +Programatically, we use uv [[GitHub]](https://github.com/astral-sh/uv) to install all dependencies and manage our installed Python versions (alternatives, such as using conda or mamba are also possible if uv doesn't work for you). -### Assisted Linux installation +You can use uv through the following steps: -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: +1. Make sure that you have installed uv (uv can be installed under any Python version as uv will manage our Python version later): ```sh -./conda activate cnapy-1.2.1 -cnapy +pip install uv ``` -If you installed Miniforge system-wide, it's also possible to run these commands in any other terminal folder. - -### Assisted MacOS X installation - -*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)). - -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: +2. Checkout the latest cnapy development version using git ```sh -./conda activate cnapy-1.2.1 -cnapy +git clone https://github.com/cnapy-org/CNApy.git ``` -## 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 - - ```sh - cnapy - ``` +3. Change into the source directory and run 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 - ``` - -4. Change into the source directory and run CNApy +```sh +cd CNApy +uv run cnapy.py +``` - ```sh - cd CNApy - python cnapy.py - ``` +uv will automatically install the correct Python version (by reading ./.python-version) and CNApy dependencies (by reading ./pyproject.toml). 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. ## 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/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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.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 From 11a61885d71a54efd849e139ed26e8b5d94073d3 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Wed, 25 Sep 2024 13:03:14 +0200 Subject: [PATCH 02/28] Add installer scripts --- installers/install_cnapy_here.ps1 | 39 +++++++++++++++++++ installers/install_cnapy_here.sh | 64 +++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 installers/install_cnapy_here.ps1 create mode 100755 installers/install_cnapy_here.sh diff --git a/installers/install_cnapy_here.ps1 b/installers/install_cnapy_here.ps1 new file mode 100644 index 00000000..b4ec6f99 --- /dev/null +++ b/installers/install_cnapy_here.ps1 @@ -0,0 +1,39 @@ +# Adapted from https://raw.githubusercontent.com/mamba-org/micromamba-releases/main/install.ps1 + +$CNAPY_VERSION = "1.2.1.1" # Replace with the actual version if needed +$RELEASE_URL="https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-win-64" + +Write-Output "Downloading micromamba from $RELEASE_URL" +curl.exe -L -o micromamba.exe $RELEASE_URL + +# Get the directory where the script is located +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path + +$InstallDir = Join-Path -Path $ScriptDir -ChildPath "cnapy-$CNAPY_VERSION" +New-Item -ItemType Directory -Force -Path $InstallDir | out-null + +$MAMBA_INSTALL_PATH = Join-Path -Path $InstallDir -ChildPath "micromamba.exe" + +Write-Output "`nInstalling micromamba to $InstallDir`n" +Move-Item -Force micromamba.exe $MAMBA_INSTALL_PATH | out-null + +# Use & to execute the micromamba commands stored in the variable +& $MAMBA_INSTALL_PATH create -y -p "./cnapy-$CNAPY_VERSION/cnapy-environment" python=3.10 pip -r "./cnapy-$CNAPY_VERSION/" +& $MAMBA_INSTALL_PATH run -p "./cnapy-$CNAPY_VERSION/cnapy-environment" -r "./cnapy-$CNAPY_VERSION/" pip install --no-cache-dir uv +& $MAMBA_INSTALL_PATH run -p "./cnapy-$CNAPY_VERSION/cnapy-environment" -r "./cnapy-$CNAPY_VERSION/" uv --no-cache pip install --no-cache-dir cnapy + +# Create a new batch file called "RUN_CNApy.bat" +$BatchFilePath = Join-Path -Path $InstallDir -ChildPath "RUN_CNApy.bat" +$BatchFileContent = "@echo off`n" + "& `"$MAMBA_INSTALL_PATH`" run -p `".\cnapy-$CNAPY_VERSION\cnapy-environment`" -r `".\cnapy-$CNAPY_VERSION\`" cnapy" +Set-Content -Path $BatchFilePath -Value $BatchFileContent + +# Create desktop icon using PowerShell +$ShortcutPath = [System.IO.Path]::Combine($Env:USERPROFILE, "Desktop", "CNApy-$CNAPY_VERSION.lnk") +$WScriptShell = New-Object -ComObject WScript.Shell +$Shortcut = $WScriptShell.CreateShortcut($ShortcutPath) +$Shortcut.TargetPath = $BatchFilePath +# $Shortcut.IconLocation = Join-Path -Path $ScriptDir -ChildPath "icon\CNApy_Icon.ico" +$Shortcut.WorkingDirectory = $ScriptDir +$Shortcut.Save() + +Write-Output "`nDesktop shortcut created successfully`n" diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh new file mode 100755 index 00000000..3b086187 --- /dev/null +++ b/installers/install_cnapy_here.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# Adapted from https://raw.githubusercontent.com/mamba-org/micromamba-releases/main/install.sh + +set -eu + +# CNApy version +CNAPY_VERSION="1.2.1.1" + +# 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 -r ./cnapy-${CNAPY_VERSION}/ +./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' > run_cnapy.sh +#!/bin/bash +./cnapy-${CNAPY_VERSION}/micromamba run -p ./cnapy-${CNAPY_VERSION}/cnapy-environment -r ./cnapy-${CNAPY_VERSION}/ cnapy +EOF + +# Make the shell script executable +chmod +x run_cnapy.sh From 91ade93599d673ed878baa57347ff3189ca37360 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:17:50 +0200 Subject: [PATCH 03/28] Refurbishments & Add conda instructions --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f0f017f9..cce07d3e 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,12 @@ Aside of performing calculations on metabolic models, CNApy can also be used to ## Installation Options -There are 3 alternative ways to install CNApy: +There are 4 alternative ways to install CNApy: -1. The easiest way 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. +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 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). +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```, 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```. +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 @@ -53,7 +54,7 @@ There are 3 alternative ways to install CNApy: ## Using CNApy installer -This installer lets you create a local and portable installation of CNApy under Windows, Linux or MacOS by following these instructions: +This installer lets you create a local installation of CNApy under Windows, Linux or MacOS by following these instructions: *If you use Windows:* * Download the Windows installer [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.2/install_cnapy_here.ps1) @@ -74,11 +75,11 @@ Technical side note: CNApy's installer is utilizing [micomamba](https://mamba.re 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). -Programatically, we use uv [[GitHub]](https://github.com/astral-sh/uv) to install all dependencies and manage our installed Python versions (alternatives, such as using conda or mamba are also possible if uv doesn't work for you). +Programatically, we use uv [[GitHub]](https://github.com/astral-sh/uv) to install all dependencies and manage our installed Python versions (alternatives, such as using conda or mamba are also possible if uv doesn't work for you although you would have to install all CNApy dependencies manually). -You can use uv through the following steps: +You can use uv for CNApy as follows: -1. Make sure that you have installed uv (uv can be installed under any Python version as uv will manage our Python version later): +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 pip install uv From 1b38e72c8fd18cfc35df86d2867a2ff6801a8e7b Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:27:52 +0200 Subject: [PATCH 04/28] Update CI test and add Python version file --- .github/workflows/ci-test.yml | 57 +++++++++++++++++++++++++---------- .gitignore | 3 -- .python-version | 1 + 3 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 .python-version diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 9ce6be1b..ddcbaa56 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -7,33 +7,58 @@ jobs: 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 - - name: Test CNApy + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install uv + uv pip install -r requirements.txt + - name: Install CNApy run: | - conda init bash - source ~/.bashrc - conda activate cnapy python setup.py install + - name: Test CNApy + run: | 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 uv + uv pip install -r requirements.txt + - name: Install CNApy + run: | + python setup.py 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 uv + uv pip install -r requirements.txt + - name: Install CNApy run: | python setup.py install + - name: Test CNApy + run: | 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 From ef029cb72c68cea76c434e2ef949a1003f3244c0 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:48:40 +0200 Subject: [PATCH 05/28] Add workflow_dispatch --- .github/workflows/ci-test.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index ddcbaa56..f3d0c52f 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -1,6 +1,7 @@ name: CI Test on: [push, pull_request] +workflow_dispatch: jobs: build-linux: @@ -14,8 +15,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install uv - uv pip install -r requirements.txt - name: Install CNApy run: | python setup.py install @@ -34,8 +33,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install uv - uv pip install -r requirements.txt - name: Install CNApy run: | python setup.py install @@ -54,8 +51,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install uv - uv pip install -r requirements.txt - name: Install CNApy run: | python setup.py install From 4182005b7faccc7d9e10a54d3055406aa907da52 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:50:02 +0200 Subject: [PATCH 06/28] Remove push --- .github/workflows/ci-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index f3d0c52f..cab219ad 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -1,6 +1,6 @@ name: CI Test -on: [push, pull_request] +on: [pull_request] workflow_dispatch: jobs: From c7a44204d8d5c7d3590b6424e2c46137ac21719d Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 10:55:29 +0200 Subject: [PATCH 07/28] workflow_dispatch not needed --- .github/workflows/ci-test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index cab219ad..152052a0 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -1,7 +1,6 @@ name: CI Test on: [pull_request] -workflow_dispatch: jobs: build-linux: From bc2858117d426ba55e733821da78137fd0ab1364 Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:03:22 +0200 Subject: [PATCH 08/28] Use cplex==22.1.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d7d5281c..f0160f88 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ 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", "qtpy>=2.3", "pyqtwebengine>=5.15", "qtconsole==5.4", - "gurobipy>=11.0", "cplex>=22.1", "numpy==1.23", "scipy==1.12", "openpyxl"] + "gurobipy>=11.0", "cplex==22.1.0", "numpy==1.23", "scipy==1.12", "openpyxl"] [project.scripts] cnapy = "cnapy.__main__:main_cnapy" From 657dde4827384658cc85a0cfa02004ef9534867a Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:17:17 +0200 Subject: [PATCH 09/28] Try cplex==22.1.1.2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f0160f88..2bf955ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ 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", "qtpy>=2.3", "pyqtwebengine>=5.15", "qtconsole==5.4", - "gurobipy>=11.0", "cplex==22.1.0", "numpy==1.23", "scipy==1.12", "openpyxl"] + "gurobipy>=11.0", "cplex==22.1.1.2", "numpy==1.23", "scipy==1.12", "openpyxl"] [project.scripts] cnapy = "cnapy.__main__:main_cnapy" From 7f4088cdedf8ee3fcb01bbfcf14be2d4a157e6b3 Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:22:50 +0200 Subject: [PATCH 10/28] Try Python 3.10.14 --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 152052a0..72ba9288 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -10,7 +10,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.10.14' - name: Install dependencies run: | python -m pip install --upgrade pip @@ -28,7 +28,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.10.14' - name: Install dependencies run: | python -m pip install --upgrade pip @@ -46,7 +46,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.10.14' - name: Install dependencies run: | python -m pip install --upgrade pip From 16969e6100b0172b0fd28ab923cd3de6ec2f09c3 Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:29:57 +0200 Subject: [PATCH 11/28] install cplex before cnapy --- .github/workflows/ci-test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 72ba9288..349e9a44 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -10,10 +10,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10.14' + python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip + pip install cplex - name: Install CNApy run: | python setup.py install @@ -28,10 +29,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10.14' + python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip + pip install cplex - name: Install CNApy run: | python setup.py install @@ -46,10 +48,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10.14' + python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip + pip install cplex - name: Install CNApy run: | python setup.py install From 3980e5566e16db1d53e81d823c7b7f589c3525c4 Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:39:13 +0200 Subject: [PATCH 12/28] Pre-install jpype1 --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 349e9a44..ba7265d3 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex + pip install cplex jpype1 - name: Install CNApy run: | python setup.py install @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex + pip install cplex jpype1 - name: Install CNApy run: | python setup.py install @@ -52,7 +52,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex + pip install cplex jpype1 - name: Install CNApy run: | python setup.py install From b8640ea00b6705db722bb2bfc77adc45d3c4b8d7 Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:56:29 +0200 Subject: [PATCH 13/28] Pre-install install-jdk>=1.1 --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index ba7265d3..660d1136 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 + pip install cplex jpype1 install-jdk>=1.1 - name: Install CNApy run: | python setup.py install @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 + pip install cplex jpype1 install-jdk>=1.1 - name: Install CNApy run: | python setup.py install @@ -52,7 +52,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 + pip install cplex jpype1 install-jdk>=1.1 - name: Install CNApy run: | python setup.py install From 047d8e85511a4958a5eb290487caacbcd21a78af Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:01:16 +0200 Subject: [PATCH 14/28] Pre-install pytest>=7.2 --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 660d1136..7c50171b 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 install-jdk>=1.1 + pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 - name: Install CNApy run: | python setup.py install @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 install-jdk>=1.1 + pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 - name: Install CNApy run: | python setup.py install @@ -51,7 +51,7 @@ jobs: python-version: '3.10' - name: Install dependencies run: | - python -m pip install --upgrade pip + python -m pip install --upgrade pip pytest>=7.2 pip install cplex jpype1 install-jdk>=1.1 - name: Install CNApy run: | From 68b670b6d349ef1991202af3d2fa1a595154aff7 Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Thu, 26 Sep 2024 12:51:17 +0200 Subject: [PATCH 15/28] Pre-install pyqt5 --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 7c50171b..5233adb0 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 + pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 pyqt5 - name: Install CNApy run: | python setup.py install @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 + pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 pyqt5 - name: Install CNApy run: | python setup.py install @@ -51,7 +51,7 @@ jobs: python-version: '3.10' - name: Install dependencies run: | - python -m pip install --upgrade pip pytest>=7.2 + python -m pip install --upgrade pip pytest>=7.2 pyqt5 pip install cplex jpype1 install-jdk>=1.1 - name: Install CNApy run: | From 7fe05d60a154842b52df89c8fc748a20013d9b9c Mon Sep 17 00:00:00 2001 From: axelvonkamp Date: Thu, 26 Sep 2024 13:43:08 +0200 Subject: [PATCH 16/28] use efmtool_link 0.0.8 --- .github/workflows/ci-test.yml | 8 ++++---- pyproject.toml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 5233adb0..547dd3a8 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 pyqt5 + pip install cplex pytest>=7.2 pyqt5 - name: Install CNApy run: | python setup.py install @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex jpype1 install-jdk>=1.1 pytest>=7.2 pyqt5 + pip install cplex pytest>=7.2 pyqt5 - name: Install CNApy run: | python setup.py install @@ -51,8 +51,8 @@ jobs: python-version: '3.10' - name: Install dependencies run: | - python -m pip install --upgrade pip pytest>=7.2 pyqt5 - pip install cplex jpype1 install-jdk>=1.1 + python -m pip install --upgrade pip + pip install cplex pytest>=7.2 pyqt5 - name: Install CNApy run: | python setup.py install diff --git a/pyproject.toml b/pyproject.toml index 2bf955ad..41b3240d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,9 +16,9 @@ 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.1.2", "numpy==1.23", "scipy==1.12", "openpyxl"] + "gurobipy>=11.0", "cplex>=22.1", "numpy==1.23", "scipy==1.12", "openpyxl"] [project.scripts] cnapy = "cnapy.__main__:main_cnapy" From 56f8c996c54cbdc38b6077d37b5ffaa6077ccc86 Mon Sep 17 00:00:00 2001 From: axelvonkamp Date: Thu, 26 Sep 2024 13:52:02 +0200 Subject: [PATCH 17/28] still need jpype1 install-jdk>=1.1 --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 547dd3a8..139902b0 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 + pip install cplex pytest>=7.2 pyqt5 jpype1 install-jdk>=1.1 - name: Install CNApy run: | python setup.py install @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 + pip install cplex pytest>=7.2 pyqt5 jpype1 install-jdk>=1.1 - name: Install CNApy run: | python setup.py install @@ -52,7 +52,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 + pip install cplex pytest>=7.2 pyqt5 jpype1 install-jdk>=1.1 - name: Install CNApy run: | python setup.py install From f89efc2694a7255725ac191b4698a5ba3210a967 Mon Sep 17 00:00:00 2001 From: axelvonkamp Date: Thu, 26 Sep 2024 14:00:10 +0200 Subject: [PATCH 18/28] try pip install --- .github/workflows/ci-test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 139902b0..68b3434f 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,10 +14,10 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 jpype1 install-jdk>=1.1 + pip install cplex pytest>=7.2 pyqt5 - name: Install CNApy run: | - python setup.py install + pip install . - name: Test CNApy run: | pytest -v ./cnapy/tests/test.py @@ -33,10 +33,10 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 jpype1 install-jdk>=1.1 + pip install cplex pytest>=7.2 pyqt5 - name: Install CNApy run: | - python setup.py install + pip install . - name: Test CNApy run: | pytest -v ./cnapy/tests/test.py @@ -52,10 +52,10 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 jpype1 install-jdk>=1.1 + pip install cplex pytest>=7.2 pyqt5 - name: Install CNApy run: | - python setup.py install + pip install . - name: Test CNApy run: | pytest -v ./cnapy/tests/test.py From 2e009d10f3b05f97d2984631e911f325a30a745f Mon Sep 17 00:00:00 2001 From: axelvonkamp Date: Thu, 26 Sep 2024 14:02:46 +0200 Subject: [PATCH 19/28] cleanup (?) --- .github/workflows/ci-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml index 68b3434f..e0027cfe 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-test.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 + pip install pytest>=7.2 - name: Install CNApy run: | pip install . @@ -33,7 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 + pip install pytest>=7.2 - name: Install CNApy run: | pip install . @@ -52,7 +52,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install cplex pytest>=7.2 pyqt5 + pip install pytest>=7.2 - name: Install CNApy run: | pip install . From a331b2d689a64b04718c8451911d2251b2618a2b Mon Sep 17 00:00:00 2001 From: axelvonkamp Date: Fri, 27 Sep 2024 10:19:05 +0200 Subject: [PATCH 20/28] remove obsolete packaging instructions --- Packaging.md | 43 ------------------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 Packaging.md 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 . -``` From b31b51bd6f4ad6239f0ff9e50a78250533df0ba7 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Fri, 27 Sep 2024 13:47:08 +0200 Subject: [PATCH 21/28] Add openjdk; Enforce conda-forge; Fix run script --- installers/install_cnapy_here.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh index 3b086187..fecf8534 100755 --- a/installers/install_cnapy_here.sh +++ b/installers/install_cnapy_here.sh @@ -51,12 +51,13 @@ else fi chmod +x "${BIN_FOLDER}/micromamba" -./cnapy-${CNAPY_VERSION}/micromamba create -y -p ./cnapy-${CNAPY_VERSION}/cnapy-environment python=3.10 pip -r ./cnapy-${CNAPY_VERSION}/ +./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' > run_cnapy.sh #!/bin/bash +CNAPY_VERSION=1.2.1.1 ./cnapy-${CNAPY_VERSION}/micromamba run -p ./cnapy-${CNAPY_VERSION}/cnapy-environment -r ./cnapy-${CNAPY_VERSION}/ cnapy EOF From 463525d3fbf580ed990b95a56e6d47c917d89e29 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:03:13 +0200 Subject: [PATCH 22/28] Fix extreme amount of bugs in install scripts --- installers/install_cnapy_here.bat | 83 +++++++++++++++++++++++++++++++ installers/install_cnapy_here.ps1 | 39 --------------- installers/install_cnapy_here.sh | 10 ++-- 3 files changed, 90 insertions(+), 42 deletions(-) create mode 100644 installers/install_cnapy_here.bat delete mode 100644 installers/install_cnapy_here.ps1 diff --git a/installers/install_cnapy_here.bat b/installers/install_cnapy_here.bat new file mode 100644 index 00000000..7a169526 --- /dev/null +++ b/installers/install_cnapy_here.bat @@ -0,0 +1,83 @@ +@echo off +setlocal + +:: Set the PowerShell script file name +set "psFile=install_cnapy.ps1" + +:: Write the PowerShell script to a file +echo # Adapted from https://raw.githubusercontent.com/mamba-org/micromamba-releases/main/install.ps1 > "%psFile%" +echo. >> "%psFile%" +echo $CNAPY_VERSION = "1.2.1.1" ^# 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.1.1/condabin/mamba.bat" -Destination "cnapy-1.2.1.1/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.1.1 desktop icon or, + echo alternatively, double-click on the RUN_CNApy.bat file in the newly created cnapy-1.2.1.1 subfolder. + echo To deinstall CNApy later, simply delete the newly created cnapy-1.2.1.1 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.ps1 b/installers/install_cnapy_here.ps1 deleted file mode 100644 index b4ec6f99..00000000 --- a/installers/install_cnapy_here.ps1 +++ /dev/null @@ -1,39 +0,0 @@ -# Adapted from https://raw.githubusercontent.com/mamba-org/micromamba-releases/main/install.ps1 - -$CNAPY_VERSION = "1.2.1.1" # Replace with the actual version if needed -$RELEASE_URL="https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-win-64" - -Write-Output "Downloading micromamba from $RELEASE_URL" -curl.exe -L -o micromamba.exe $RELEASE_URL - -# Get the directory where the script is located -$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path - -$InstallDir = Join-Path -Path $ScriptDir -ChildPath "cnapy-$CNAPY_VERSION" -New-Item -ItemType Directory -Force -Path $InstallDir | out-null - -$MAMBA_INSTALL_PATH = Join-Path -Path $InstallDir -ChildPath "micromamba.exe" - -Write-Output "`nInstalling micromamba to $InstallDir`n" -Move-Item -Force micromamba.exe $MAMBA_INSTALL_PATH | out-null - -# Use & to execute the micromamba commands stored in the variable -& $MAMBA_INSTALL_PATH create -y -p "./cnapy-$CNAPY_VERSION/cnapy-environment" python=3.10 pip -r "./cnapy-$CNAPY_VERSION/" -& $MAMBA_INSTALL_PATH run -p "./cnapy-$CNAPY_VERSION/cnapy-environment" -r "./cnapy-$CNAPY_VERSION/" pip install --no-cache-dir uv -& $MAMBA_INSTALL_PATH run -p "./cnapy-$CNAPY_VERSION/cnapy-environment" -r "./cnapy-$CNAPY_VERSION/" uv --no-cache pip install --no-cache-dir cnapy - -# Create a new batch file called "RUN_CNApy.bat" -$BatchFilePath = Join-Path -Path $InstallDir -ChildPath "RUN_CNApy.bat" -$BatchFileContent = "@echo off`n" + "& `"$MAMBA_INSTALL_PATH`" run -p `".\cnapy-$CNAPY_VERSION\cnapy-environment`" -r `".\cnapy-$CNAPY_VERSION\`" cnapy" -Set-Content -Path $BatchFilePath -Value $BatchFileContent - -# Create desktop icon using PowerShell -$ShortcutPath = [System.IO.Path]::Combine($Env:USERPROFILE, "Desktop", "CNApy-$CNAPY_VERSION.lnk") -$WScriptShell = New-Object -ComObject WScript.Shell -$Shortcut = $WScriptShell.CreateShortcut($ShortcutPath) -$Shortcut.TargetPath = $BatchFilePath -# $Shortcut.IconLocation = Join-Path -Path $ScriptDir -ChildPath "icon\CNApy_Icon.ico" -$Shortcut.WorkingDirectory = $ScriptDir -$Shortcut.Save() - -Write-Output "`nDesktop shortcut created successfully`n" diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh index fecf8534..6f630bd0 100755 --- a/installers/install_cnapy_here.sh +++ b/installers/install_cnapy_here.sh @@ -55,11 +55,15 @@ chmod +x "${BIN_FOLDER}/micromamba" ./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' > run_cnapy.sh +cat << 'EOF' > ./cnapy-${CNAPY_VERSION}/run_cnapy.sh #!/bin/bash CNAPY_VERSION=1.2.1.1 -./cnapy-${CNAPY_VERSION}/micromamba run -p ./cnapy-${CNAPY_VERSION}/cnapy-environment -r ./cnapy-${CNAPY_VERSION}/ cnapy +./micromamba run -p ./cnapy-environment -r ./cnapy EOF # Make the shell script executable -chmod +x run_cnapy.sh +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. From 2b0ba027309cab889b3afd7bfef6b8f6f3e80f0d Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:22:46 +0200 Subject: [PATCH 23/28] Set installers to 1.2.2 & Refurbish README --- README.md | 26 +++++++++++++------------- installers/install_cnapy_here.bat | 10 +++++----- installers/install_cnapy_here.sh | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index cce07d3e..9c36d8de 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Introduction -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]](https://doi.org/10.1371/journal.pcbi.1004321)) and c) the creation and editing of metabolic models. +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)](). Supported COBRA methods (partly provided by cobrapy [[GitHub]](https://github.com/opencobra/cobrapy)[[Paper]](https://doi.org/10.1186/1752-0509-7-74)) include: @@ -22,8 +22,6 @@ Supported COBRA methods (partly provided by cobrapy [[GitHub]](https://github.co - 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 -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 [[Site]](https://sbml.org/)[[Paper]](https://www.embopress.org/doi/abs/10.15252/msb.20199110). - **→ For information about how to install CNApy, see section [Installation Options](#installation-options)** **→ For more details on CNApy's many features, see section [Documentation and Tutorials](#documentation-and-tutorials)** @@ -57,19 +55,21 @@ There are 4 alternative ways to install CNApy: This installer lets you create a local installation of CNApy under Windows, Linux or MacOS by following these instructions: *If you use Windows:* -* Download the Windows installer [from here](https://github.com/cnapy-org/CNApy/releases/download/v1.2.2/install_cnapy_here.ps1) -* 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. + +- 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. *If you use Linux or MacOS*: -* 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```. -* Now, either run ```./install_cnapy_here.sh``` in your console or double-click on install_cnapy_here.sh. -* Finally, you can run CNApy by double-clicking "run_cnapy.sh" in the newly created cnapy-1.2.2 subfolder or by calling run_cnapy.sh in your console (for the latter, your console must point to the folder where run_cnapy.sh is located). -Technical side note: CNApy's installer is utilizing [micomamba](https://mamba.readthedocs.io/en/latest/installation/micromamba-installation.html). +- 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 double-clicking "run_cnapy.sh" in the newly created cnapy-1.2.2 subfolder or by calling run_cnapy.sh in your console (for the latter, your console must point to the folder where run_cnapy.sh is located). + +Technical side note: CNApy's installer is utilizing [micromamba](https://mamba.readthedocs.io/en/latest/installation/micromamba-installation.html). ## Setup the CNApy development environment diff --git a/installers/install_cnapy_here.bat b/installers/install_cnapy_here.bat index 7a169526..2b9862f9 100644 --- a/installers/install_cnapy_here.bat +++ b/installers/install_cnapy_here.bat @@ -7,7 +7,7 @@ set "psFile=install_cnapy.ps1" :: Write the PowerShell script to a file echo # Adapted from https://raw.githubusercontent.com/mamba-org/micromamba-releases/main/install.ps1 > "%psFile%" echo. >> "%psFile%" -echo $CNAPY_VERSION = "1.2.1.1" ^# Replace with the actual version if needed >> "%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%" @@ -26,7 +26,7 @@ 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.1.1/condabin/mamba.bat" -Destination "cnapy-1.2.1.1/condabin/micromamba.bat" >> "%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%" @@ -68,9 +68,9 @@ if exist "%psFile%" ( :: Congratulate the user echo Congratulations! CNApy was successfully installed! - echo To run CNApy, double-click on the newly created CNApy-1.2.1.1 desktop icon or, - echo alternatively, double-click on the RUN_CNApy.bat file in the newly created cnapy-1.2.1.1 subfolder. - echo To deinstall CNApy later, simply delete the newly created cnapy-1.2.1.1 subfolder. + 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% diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh index 6f630bd0..ecd004d6 100755 --- a/installers/install_cnapy_here.sh +++ b/installers/install_cnapy_here.sh @@ -4,7 +4,7 @@ set -eu # CNApy version -CNAPY_VERSION="1.2.1.1" +CNAPY_VERSION="1.2.2" # Folders BIN_FOLDER="${BIN_FOLDER:-./cnapy-${CNAPY_VERSION}}" @@ -57,7 +57,7 @@ chmod +x "${BIN_FOLDER}/micromamba" cat << 'EOF' > ./cnapy-${CNAPY_VERSION}/run_cnapy.sh #!/bin/bash -CNAPY_VERSION=1.2.1.1 +CNAPY_VERSION=1.2.2 ./micromamba run -p ./cnapy-environment -r ./cnapy EOF From 8d8383f81d5e3b10b20d4b61365a66bd11500d6d Mon Sep 17 00:00:00 2001 From: axelvonkamp <47664585+axelvonkamp@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:35:15 +0200 Subject: [PATCH 24/28] Info about conda package --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c36d8de..18e8a4dd 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ 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```, 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```. +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```, 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 From 107ae1e6a6ea030fc4cd9235f0c9e3ee80a60e21 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Tue, 1 Oct 2024 07:50:15 +0200 Subject: [PATCH 25/28] README corrections and refurbishments --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 18e8a4dd..fe3c7d77 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Introduction -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)](). +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). Supported COBRA methods (partly provided by cobrapy [[GitHub]](https://github.com/opencobra/cobrapy)[[Paper]](https://doi.org/10.1186/1752-0509-7-74)) include: @@ -40,7 +40,7 @@ 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```, 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. +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 @@ -67,16 +67,19 @@ This installer lets you create a local installation of CNApy under Windows, Linu - 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 double-clicking "run_cnapy.sh" in the newly created cnapy-1.2.2 subfolder or by calling run_cnapy.sh in your console (for the latter, your console must point to the folder where run_cnapy.sh is located). +- 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. Technical side note: CNApy's installer is utilizing [micromamba](https://mamba.readthedocs.io/en/latest/installation/micromamba-installation.html). ## Setup the CNApy development environment -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). +*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). -Programatically, we use uv [[GitHub]](https://github.com/astral-sh/uv) to install all dependencies and manage our installed Python versions (alternatives, such as using conda or mamba are also possible if uv doesn't work for you although you would have to install all CNApy dependencies manually). +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. +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. + +### uv usage You can use uv for CNApy as follows: 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): @@ -98,9 +101,7 @@ cd CNApy uv run cnapy.py ``` -uv will automatically install the correct Python version (by reading ./.python-version) and CNApy dependencies (by reading ./pyproject.toml). - -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 From fa6ab9e5f355f77cd6ff21983b49d3d13a64c96b Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:53:28 +0200 Subject: [PATCH 26/28] Fix Linux/MacOS installer --- installers/install_cnapy_here.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh index ecd004d6..57ec95b9 100755 --- a/installers/install_cnapy_here.sh +++ b/installers/install_cnapy_here.sh @@ -57,8 +57,11 @@ chmod +x "${BIN_FOLDER}/micromamba" cat << 'EOF' > ./cnapy-${CNAPY_VERSION}/run_cnapy.sh #!/bin/bash -CNAPY_VERSION=1.2.2 -./micromamba run -p ./cnapy-environment -r ./cnapy + +# Add CPLEX variable here, e.g. +# export PYTHONPATH=/path_to_cplex/cplex/python/3.10/x86-64_linux + +./micromamba run -p ./cnapy-environment cnapy EOF # Make the shell script executable From cb943782958afe4ec580af19f86100808edee1a9 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Wed, 2 Oct 2024 09:05:23 +0200 Subject: [PATCH 27/28] Fix Linux/MacOS installer again --- installers/install_cnapy_here.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/installers/install_cnapy_here.sh b/installers/install_cnapy_here.sh index 57ec95b9..23361afd 100755 --- a/installers/install_cnapy_here.sh +++ b/installers/install_cnapy_here.sh @@ -61,6 +61,8 @@ cat << 'EOF' > ./cnapy-${CNAPY_VERSION}/run_cnapy.sh # 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 From e6ea744ef1f730bbaf033b7704a562983fb4cef1 Mon Sep 17 00:00:00 2001 From: Paulocracy <36934614+Paulocracy@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:15:22 +0200 Subject: [PATCH 28/28] Update CPLEX & Gurobi configuration dialogs --- cnapy/gui_elements/configuration_cplex.py | 22 ++++++++++------------ cnapy/gui_elements/configuration_gurobi.py | 18 ++++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) 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)