forked from threeML/threeML
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstall_3ML.py
255 lines (153 loc) · 8.04 KB
/
install_3ML.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
import subprocess
import sys
from distutils.util import strtobool
import re
import os
import socket
def internet_connection_is_active(host="8.8.8.8", port=53, timeout=3):
"""
Check that a internet connection is working by trying contacting the following host:
Host: 8.8.8.8 (google-public-dns-a.google.com)
OpenPort: 53/tcp
Service: domain (DNS/TCP)
"""
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
except Exception as ex:
print(ex.message)
return False
else:
return True
def discovery_message(message):
print("\n * %s\n" % message)
def fixable_problem(message):
print("\nPROBLEM: %s\n" % message)
def fatal_error(message):
print("\n\nFATAL: %s\n\n" % message)
sys.exit(-1)
def yes_or_no(prompt):
while True:
# This is only python2 compatible. Will need to change to input() instead of raw_input() with python3.
answer = raw_input(prompt)
# strtobool returns True if answer is yes,y,t,1, no if
try:
return_bool = strtobool(answer)
except ValueError:
print("Invalid answer. Please use one of yes,y,t,1 to say yes or no,n,f,0 to say no. Try again.")
else:
return return_bool
def prompt_string(message, default=None, path=False):
while True:
answer = raw_input(message)
if answer == '':
answer = default
if answer is None: # this gets triggered if there was no default
print("You have to provide an answer")
continue
else:
# validate answer
if path:
if len(re.findall("[^0-9a-zA-Z_%s~${}]" % os.path.sep, answer)) > 0:
print("Invalid path. Please use only letters, numbers and underscores (and %s)" % os.path.sep)
continue
else:
# Valid answer
return answer
else:
if len(re.findall("[^0-9a-zA-Z_]", answer)) > 0:
print("Invalid answer. Please use only letters, numbers and underscores")
continue
else:
# Valid answer
return answer
if __name__ == "__main__":
# Make sure we are running in python2, not python3
try:
assert hasattr(__builtins__, "raw_input")
except AssertionError:
message = "You tried running the install script with python3. Please use python2 instead. Usually this can " \
"be achieved with 'python2 install_3ML.py' " \
"(instead of just 'python install_3ML.py' or './install_3ML.py')"
fatal_error(message)
# Make sure we are connected to the internet
if not internet_connection_is_active():
fatal_error("Looks like you are not connected to the internet right now. Check your connection and try again.")
# Ask initial confirmation
print("\nThis script installs 3ML and astromodels (as well as cthreeML if your system supports it, and all "
"dependencies) in a new python virtual environment. This way it will not interfere with your system python "
"or other python versions you might have installed.")
print("(see http://docs.python-guide.org/en/latest/dev/virtualenvs/ for info on virtual environments)")
print("\nPLEASE NOTE: you need to have set up the environments for all experiments you want to use in 3ML *before* "
"running this script. If you didn't do so please fix this before continuing.")
choice = yes_or_no("\nContinue (yes/no)? ")
if not choice:
sys.exit(-2)
# First make sure pip is installed
try:
pip_version_string = subprocess.check_output("pip --version", shell=True)
except subprocess.CalledProcessError:
message = "Could not execute 'pip --version'. Likely you do not have pip installed. " \
"Please install pip first, then re-run this script. Use your package manager (preferred), or " \
"follow instructions at https://pip.pypa.io/en/stable/installing/"
fatal_error(message)
else:
discovery_message("Found pip with this version string: %s" % pip_version_string)
# Then make sure git is installed
try:
git_version_string = subprocess.check_output("git --version", shell=True)
except subprocess.CalledProcessError:
message = "Could not execute 'git --version'. Likely you do not have git installed. " \
"Use your package manager to install git first, then re-run this script."
fatal_error(message)
else:
discovery_message("Found git with this version string: %s" % git_version_string)
# Check that virtualenv is installed, otherwise try to install it
try:
venv_version_string = subprocess.check_output("virtualenv --version", shell=True)
# If the previous line worked, virtualenv does not need any specific path to work
virtual_env_bin = 'virtualenv'
except subprocess.CalledProcessError:
message = "virtualenv is not installed. Please install it before running this script. You can do that by " \
"running 'pip install virtualenv'. If you do not have admin rights you can still install it as " \
"'pip install --user virtualenv'. However, remember to add the path where the virtualenv executable " \
"gets installed (usually ~/.local/bin/) to your PATH evironment variable before running this " \
"script again."
fatal_error(message)
# Here we have a working pip and virtualenv
# Create the virtual environment
default_path = os.path.abspath(os.path.expanduser(os.path.join("~", "3ML_env")))
env_path = prompt_string("Please provide a path for your virtual environment "
"(hit enter to use default: %s): " % default_path,
default=default_path, path=True)
env_path = os.path.abspath(os.path.expandvars(os.path.expanduser(env_path)))
discovery_message("Creating virtual environment at %s" % env_path)
# Assert it does not exist
if os.path.exists(env_path):
fatal_error("Path %s exists. Are you sure you did not run this script already? If you want to activate the "
"environment, use 'source %s'. If you want to start from scratch, "
"remove %s first." % (env_path, os.path.join(env_path,'bin','activate'), env_path))
subprocess.check_call("virtualenv --no-site-packages %s" % env_path, shell=True)
# Write a script which will run in the new environment
temp_file = "__install_script.sh"
with open(temp_file, "w+") as f:
f.write("#/bin/bash\n")
f.write("source %s/bin/activate\n" % env_path)
f.write("pip install numpy scipy matplotlib iminuit astropy ipython ipyparallel --upgrade\n")
f.write("pip install git+https://github.com/giacomov/3ML.git --upgrade\n")
f.write("pip install git+https://github.com/giacomov/astromodels.git --upgrade\n")
f.write("pip install git+https://github.com/giacomov/cthreeML.git || "
"echo '\n\nNOTE: could not install chtreeML. Probably boost python is not available' \n")
# Execute script
subprocess.check_call("/bin/bash __install_script.sh", shell=True)
# Remove script
os.remove("__install_script.sh")
# Print final message
discovery_message("Installation complete.")
print("\n\nREMEMBER: before using 3ML you need to run 'source %s/bin/activate'. Normally this needs to "
"be done after you set up all the other packages, like AERIE, the Fermi Science Tools and so on, otherwise"
"some of the plugins might be unavailable.\n "
"If you want to uninstall, simply remove the entire directory %s "
"(no other python environment will be touched, but of course you will loose anything you have "
"installed in that environment)" % (env_path, env_path))
sys.exit(0)