Skip to content

Commit

Permalink
Merge pull request #161 from MetaCell/feature/PSYNEU-140
Browse files Browse the repository at this point in the history
#PSYNEU-140 - Fixing installation process on Mac and Linux, #PSYNEU-138 - Add bash scripts to install and run psyneulinkviewer in mac and linux, updates read me with instructions
  • Loading branch information
ddelpiano authored Sep 6, 2024
2 parents f2996e1 + b922e30 commit 57fb424
Show file tree
Hide file tree
Showing 13 changed files with 335 additions and 94 deletions.
117 changes: 105 additions & 12 deletions package/README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,122 @@
# PsyNeuLinkView Package Building
# Installing on Linux

To build pip package
Download bash script to install [here](https://raw.githubusercontent.com/MetaCell/PsyNeuLinkView/feature/PSYNEU-140/package/linux_installer.sh).
It's recommended to download it in your home directory.

On terminal, go to your root directory
```
cd package
python3 -m build
cd ~
```

And run installer
```
sudo bash -i linux_installer.sh
```

To upload to distribution server. You will need token shared privately.
The application should open up after succesfully installing psyneulinkviewer.

# Installing on MAC

Download bash script to install [here](https://raw.githubusercontent.com/MetaCell/PsyNeuLinkView/feature/PSYNEU-140/package/mac_installer.sh).
It's recommended to download it in your home directory.

On terminal, go to your root directory
```
twine upload dist/*
cd ~
```

To pip install local package created in previous steps
And run installer
```
python3 -m pip install --no-index --find-links=package_directory_path + "/dist" psyneulinkview
sudo bash -i mac_installer.sh
```

# PsyNeuLinkView Installing from PyPI
The application should open up after succesfully installing psyneulinkviewer.


To install from PyPi
# Installation process inside script

The scripts above run the following commands in order:

Firs installs the python module 'psyneulinkviewer' from PyPi
```
pip install psyneulinkview --extra-index-url https://pypi.org/project/psyneulinkview
sudo pip install psyneulinkviewer
```
This commands installs required libraries and packages. Also creates a conda enviroment where the needed packages are installed.

To run psyneulinkviewer
After successfully installing the python package above, it reset the user's bash profile to apply the settings changes
- Linux
```
source ~/.profile
```

- Mac
```
source ~/.bash_profile
```

Then, the conda environment created is activated with command below:
```
conda activate psyneulinkview
```

Finally, the last step of the script opens the psyneulinkviewer application:

On linux:
```
psyneulinkviewer
```

On Mac:
```
open /usr/local/bin/psyneulinkviewer-darwin-x64/psyneulinkviewer.app
```

The psyneulinkviewer application is installed on user directory:
```
/usr/local/bin/
```

# Psyneulinkviewer Requirements

Psyneulinkviewer requires:

- Python 3.11 and pip
- Pip packages : psyneulink, graphviz, wget, packaging and requests
- Conda 4.9.1 or above
- Node 4.19.0 or above
- Rosetta ( on Mac)

All of these are downloaded and installed as part of psyneulinkviewer installation process.

# Testing Models

If all went well with installation, you should see the application running as in screenshot below :
![image](https://github.com/user-attachments/assets/ec84044c-287a-4e39-bdf7-aa27cdc486f9)

To test models, download [these models](https://github.com/MetaCell/PsyNeuLinkView/tree/feature/PSYNEU-140/test_models) and import one at a time to test. Each time a Model is open, the previous one will disappear. I recommend you start with the models inside 'working_tests', as those are the ones we know for sure should we working.

To import go to File -> Open Models

# PsyNeuLinkView Package Building

To build pip package
```
cd package
python3 -m pip install build
python3 -m build --sdist
```

To test local build
```
pip install dist/psyneulinkviewer-VERSIOn.tar.gz
```

To upload to distribution server. You will need token shared privately to be able to upload.
```
python3 -m twine upload dist/*
```

To upload to test Pypi server
```
python3 -m twine upload --repository testpypi dist/*
```
Binary file removed package/dist/psyneulinkview-0.0.5-py3-none-any.whl
Binary file not shown.
Binary file removed package/dist/psyneulinkview-0.0.5.tar.gz
Binary file not shown.
Binary file added package/dist/psyneulinkviewer-0.3.0.tar.gz
Binary file not shown.
2 changes: 2 additions & 0 deletions package/linux_installer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env bash -l
pip install -vv psyneulinkviewer && source ~/.profile && conda activate psyneulinkview && psyneulinkviewer
2 changes: 2 additions & 0 deletions package/mac_installer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env bash -l
pip install -vv psyneulinkviewer --break-system-packages && source ~/.bash_profile && conda activate psyneulinkview && open /usr/local/bin/psyneulinkviewer-darwin-x64/psyneulinkviewer.app/
147 changes: 112 additions & 35 deletions package/psyneulinkviewer/conda.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,91 @@
import sys
import subprocess
import logging
import configuration
import wget
import platform
import re
from setuptools import setup, find_packages
from setuptools.command.install import install
from packaging.version import Version
from psyneulinkviewer import configuration

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)

def activate_env():
logging.info("Creating conda environment ")
subprocess.run(configuration.create_env, shell=True)
conda_installed = False

logging.info("Activating conda ")
subprocess.run(configuration.activate_env, shell=True)
def create_env():
env_name = None
try:
envs = subprocess.run(
["conda", "env","list"],
capture_output = True,
text = True
).stdout
if envs is not None:
envs = envs.splitlines()
env_name = list(filter(lambda s: configuration.env_name in str(s), envs))[0]
env_name = str(env_name).split()[0]
logging.info("Environment found %s", env_name)
if env_name == configuration.env_name:
logging.info("Conda environment found %s", env_name)
except Exception as error:
logging.info("Conda environment not found")

if env_name is None:
command = get_conda_installed_path() + configuration.create_env
logging.info("Creating conda environment %s", command)
subprocess.run(command, shell=True)


def shell_source(script):
"""Sometime you want to emulate the action of "source" in bash,
settings some environment variables. Here is a way to do it."""
import subprocess, os
pipe = subprocess.Popen(". %s; env" % script, stdout=subprocess.PIPE, shell=True)
output = pipe.communicate()[0]
logging.info("Output %s", output)
env = dict((line.split("=", 1) for line in output.splitlines()))
os.environ.update(env)

def install_conda():
if os.name == 'posix':
bash_file = wget.download(configuration.linux_conda_bash, out="psyneulinkviewer")
import wget
if platform.system() == 'Linux':
bash_file = wget.download(configuration.linux_conda_bash, out="tmp")
elif platform.system() == 'Darwin':
bash_file = wget.download(configuration.mac_conda_bashf)
bash_file = wget.download(configuration.mac_conda_bash)

logging.info("Installing conda %s", bash_file)
logging.info(bash_file)
subprocess.run("chmod +x " + bash_file, shell=True)
subprocess.run(bash_file + " -b -u -p ~/miniconda3", shell=True)
subprocess.run("bash " + bash_file + " -b -u -p " + configuration.conda_installation_path, shell=True)
subprocess.run(configuration.conda_binary + " init bash", shell=True)
subprocess.run(configuration.conda_binary + " init zsh", shell=True)

activate_env()
logging.info("Clean up ")
subprocess.run("rm -rf " + bash_file, shell=True)

conda_installed = True

def get_conda_installed_path():
installation_path = detect_activated_conda_location()
logging.info("installation_path %s ", installation_path)
if installation_path is None:
if platform.system() == "Darwin":
installation_path = configuration.conda_installation_path_mac_default
logging.info("installation_path %s ", conda_installed)
installation_path = configuration.conda_installation_path

return installation_path.strip()

def conda_binary_path():
installation_path = detect_activated_conda_location()
if conda_installed:
installation_path = configuration.conda_installation_path
else:
if installation_path is None:
if platform.system() == "Darwin":
installation_path = configuration.conda_installation_path_mac_default

return installation_path

def check_conda_installation():
conda_version = None
Expand All @@ -54,35 +107,59 @@ def check_conda_installation():

if conda_version is None:
logging.info("Conda is not installed")
user_input = input("Do you want to continue with conda installation? (yes/no): ")
if user_input.lower() in ["yes", "y"]:
logging.info("Continuing with conda installation...")
install_conda()
install_conda()
else:
from packaging.version import Version
if Version(conda_version) > Version(configuration.conda_required_version):
logging.info("Conda version exists and valid, %s", conda_version)
else:
logging.error("Exiting, conda must be installed to continue...")
sys.exit()
logging.info("Conda version not up to date, updating version")
install_conda()

if Version(conda_version) > Version(configuration.conda_required_version):
logging.info("Conda version exists and valid, %s", conda_version)
env_name = detect_activated_conda()

if env_name is not None:
logging.info("Conda environment found and activated %s", env_name)
else:
logging.error("Conda version not up to date, update required")
install_conda()
create_env()

def detect_activated_conda() :
env_name = None
try:
envs = subprocess.run(
["conda", "env","list"],
env_name = subprocess.run(
["conda", "info"],
capture_output = True,
text = True
).stdout
if envs is not None:
envs = envs.splitlines()
active_env = list(filter(lambda s: '*' in str(s), envs))[0]
env_name = str(active_env).split()[0]
if env_name:
env_name = re.search('(?<=active environment : )(\w+)', env_name)
env_name = env_name.group(1)
if env_name == "None":
logging.info("Conda environment not detected active : %s", env_name)
env_name = None
else:
if env_name == configuration.env_name:
logging.info("Conda environment detected active : %s", env_name)
else:
logging.info("Active environment not matching : %s", configuration.env_name)
env_name = None
except Exception as error:
logging.error("Environment not found active: %s ", error)
logging.info("Environment not found active: %s ", error)

return env_name

if env_name is not None:
logging.info("Conda environment found and activated %s", env_name)
else:
activate_env()
def detect_activated_conda_location() :
env_location = None
try:
env_location = subprocess.run(
["conda", "info"],
capture_output = True,
text = True
).stdout
if env_location:
env_location = re.search('(?<=base environment : )(/[a-zA-Z0-9\./]*[\s]?)', env_location)
env_location = env_location.group(0)
except Exception as error:
logging.info("Environment not found active: %s ", error)

return env_location
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,28 @@

releases_url = 'https://api.github.com/repos/MetaCell/PsyNeuLinkView/releases'
application_url = "psyneulinkviewer-linux-x64/psyneulinkviewer"
application_url_mac = "psyneulinkviewer-linux-x64/psyneulinkviewer.app"


#Symlink
symlink = "/usr/local/bin/psyneulinkviewer"
extract_location = "/usr/local/bin"

linux_conda_bash = "https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh"
mac_conda_bash = "https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh"

env_name = "psyneulinkviewer"
create_env = "conda create --name " + env_name + " python=3.11"
activate_env = "conda activate " + env_name
env_name = "psyneulinkview"

conda_installation_path = "~/miniconda3"
conda_installation_path_mac_default = "/opt/miniconda3"

conda_binary = "~/miniconda3/bin/conda"
conda_binary_mac_default = "/opt/miniconda3/bin/conda"

create_env = "/bin/conda create --name " + env_name + " python=3.11"

binary_commands = " --verbose --no-capture-output --live-stream python -c 'from psyneulinkviewer.start import continue_on_conda; continue_on_conda()'"
continue_on_conda_new_env = "/bin/conda run -n " + env_name + binary_commands

rosetta_installation = "softwareupdate --install-rosetta --agree-to-license"

Expand Down
Loading

0 comments on commit 57fb424

Please sign in to comment.