-
Notifications
You must be signed in to change notification settings - Fork 23
/
setup.py
240 lines (211 loc) · 7.44 KB
/
setup.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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Instaseis: Instant Global Broadband Seismograms Based on a Waveform Database
Instaseis calculates broadband seismograms from Green’s function databases
generated with AxiSEM and allows for near instantaneous (on the order of
milliseconds) extraction of seismograms. Using the 2.5D axisymmetric
spectral element method, the generation of these databases, based on
reciprocity of the Green’s functions, is very efficient and is approximately
half as expensive as a single AxiSEM forward run. Thus this enables the
computation of full databases at half the cost of the computation of
seismograms for a single source in the previous scheme and hence allows to
compute databases at the highest frequencies globally observed. By storing
the basis coefficients of the numerical scheme (Lagrange polynomials),
the Green’s functions are 4th order accurate in space and the spatial
discretization respects discontinuities in the velocity model exactly. On
top, AxiSEM allows to include 2D structure in the source receiver plane and
readily includes other planets such as Mars.
For more information visit http://www.instaseis.net.
:copyright:
The Instaseis Development Team ([email protected]), 2014-2020
:license:
GNU Lesser General Public License, Version 3 [non-commercial/academic use]
(http://www.gnu.org/copyleft/lgpl.html)
"""
from distutils.ccompiler import CCompiler
from distutils.errors import DistutilsExecError, CompileError
from distutils.unixccompiler import UnixCCompiler
from setuptools import find_packages, setup
from setuptools.extension import Extension
import inspect
import os
from subprocess import Popen, PIPE
import sys
# Import the version string.
path = os.path.join(
os.path.abspath(os.path.dirname(inspect.getfile(inspect.currentframe()))),
"instaseis",
)
sys.path.insert(0, path)
from version import get_git_version # noqa
# Monkey patch the compilers to treat Fortran files like C files.
CCompiler.language_map[".f90"] = "c"
UnixCCompiler.src_extensions.append(".f90")
DOCSTRING = __doc__.strip().split("\n")
def get_package_data():
"""
Returns a list of all files needed for the installation relativ to the
"instaseis" subfolder.
"""
filenames = []
# The lasif root dir.
root_dir = os.path.join(
os.path.dirname(
os.path.abspath(inspect.getfile(inspect.currentframe()))
),
"instaseis",
)
# Recursively include all files in these folders:
folders = [
os.path.join(root_dir, "tests", "data"),
os.path.join(root_dir, "gui", "data"),
os.path.join(root_dir, "server", "data"),
]
for folder in folders:
for directory, _, files in os.walk(folder):
for filename in files:
# Exclude hidden files.
if filename.startswith("."):
continue
filenames.append(
os.path.relpath(
os.path.join(directory, filename), root_dir
)
)
filenames.append("RELEASE-VERSION")
return filenames
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
compiler_so = self.compiler_so
if ext == ".f90":
if sys.platform == "darwin" or sys.platform == "linux2":
compiler_so = ["gfortran"]
cc_args = ["-O", "-fPIC", "-c", "-ffree-form"]
try:
self.spawn(compiler_so + cc_args + [src, "-o", obj] + extra_postargs)
except DistutilsExecError as msg:
raise CompileError(msg)
UnixCCompiler._compile = _compile
# Hack to prevent build_ext from trying to append "init" to the export symbols.
class finallist(list):
def append(self, object):
return
class MyExtension(Extension):
def __init__(self, *args, **kwargs):
Extension.__init__(self, *args, **kwargs)
self.export_symbols = finallist(self.export_symbols)
def get_libgfortran_dir():
"""
Helper function returning the library directory of libgfortran. Useful
on OSX where the C compiler oftentimes has no knowledge of the library
directories of the Fortran compiler. I don't think it can do any harm on
Linux.
"""
for ending in [".3.dylib", ".dylib", ".3.so", ".so"]:
try:
p = Popen(
["gfortran", "-print-file-name=libgfortran" + ending],
stdout=PIPE,
stderr=PIPE,
)
p.stderr.close()
line = p.stdout.readline().decode().strip()
p.stdout.close()
if os.path.exists(line):
return [os.path.dirname(line)]
except:
continue
return []
src = os.path.join("instaseis", "src")
lib = MyExtension(
"instaseis",
libraries=["gfortran"],
library_dirs=get_libgfortran_dir(),
# Be careful with the order.
sources=[
os.path.join(src, "global_parameters.f90"),
os.path.join(src, "finite_elem_mapping.f90"),
os.path.join(src, "spectral_basis.f90"),
os.path.join(src, "sem_derivatives.f90"),
],
)
INSTALL_REQUIRES = [
"h5py",
"numpy",
"obspy >= 1.2.1",
"tornado>=6.0.0",
"requests",
"geographiclib",
"jsonschema >= 2.4.0",
]
EXTRAS_REQUIRE = {
"tests": [
"click",
"netCDF4",
"pytest-xdist",
"flake8>=3",
"pytest>=5.0",
"responses",
]
}
# Add mock for Python 2.x. Starting with Python 3 it is part of the standard
# library.
if sys.version_info[0] == 2:
INSTALL_REQUIRES.append("mock")
setup_config = dict(
name="instaseis",
version=get_git_version(),
description=DOCSTRING[0],
long_description="\n".join(DOCSTRING[2:]),
author="Lion Krischer, Martin van Driel, and Simon Stähler",
author_email="[email protected]",
url="http://instaseis.net",
packages=find_packages(),
package_data={
"instaseis": [os.path.join("lib", "instaseis.so")]
+ [os.path.join("gui", "qt_window.ui")]
+ get_package_data()
},
license="GNU Lesser General Public License, version 3 (LGPLv3) for "
"non-commercial/academic use",
platforms="OS Independent",
install_requires=INSTALL_REQUIRES,
extras_require=EXTRAS_REQUIRE,
ext_package="instaseis.lib",
ext_modules=[lib],
# this is needed for "pip install instaseis==dev"
download_url=(
"https://github.com/krischer/instaseis/zipball/master"
"#egg=instaseis=dev"
),
python_requires=">=3.6",
classifiers=[
# complete classifier list:
# http://pypi.python.org/pypi?%3Aaction=list_classifiers
"Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"Operating System :: Unix",
"Operating System :: POSIX",
"Operating System :: MacOS",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Physics",
],
)
if __name__ == "__main__":
setup(**setup_config)
# Attempt to remove the mod files once again.
for filename in [
"finite_elem_mapping.mod",
"global_parameters.mod",
"sem_derivatives.mod",
"spectral_basis.mod",
]:
try:
os.remove(filename)
except:
pass