pyrolite 0.0.14__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__init__.py +10 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/__init__.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/_version.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/alteration.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/classification.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/compositions.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/geochem.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/melts.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/norm.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/normalisation.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/__pycache__/plot.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/_version.py +21 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/alteration.py +66 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/classification.py +222 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__init__.py +9 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/__init__.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/aggregate.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/codata.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/impute.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/__pycache__/renorm.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/aggregate.py +391 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/codata.py +266 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/impute.py +82 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/comp/renorm.py +40 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/compositions.py +524 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_CFB_Dataset_List.csv +42 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_Convergent_Dataset_List.csv +42 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OBFB_Dataset_List.csv +5 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OIB_Dataset_List.csv +49 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/GEOROC_OceanicPlateau_Dataset_List.csv +18 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/georoc/contents.json +1 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/__pycache__/env.cpython-35.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/__pycache__/env.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/melts/env.py +1063 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Ba.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Bs.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.F.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O1.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O2.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.O3.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Pc.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.Ph.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.R.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S1.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S2.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.S3.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.T1.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.T2.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U1.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U2.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.U3.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.modelfields +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.nan.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS/TAS.none.modelfield +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/TAS.clsf.gz +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/aphanitic.clsf.gz +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/gabbroic.clsf.gz +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/peralkalinity.clsf.gz +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/phaneritic.clsf.gz +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/models/ultramafic.clsf.gz +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/CH_PalmeONeill2014.csv +95 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DDMM_WorkmanHart2005.csv +105 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DMM_WorkmanHart2005.csv +105 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/DM_SaltersStrake2004.csv +95 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/EDMM_WorkmanHart2005.csv +105 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/refcomp/PM_PalmeONeill2014.csv +95 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/data/timescale/geotimescale_spans.csv +180 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/geochem.py +821 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/melts.py +92 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__init__.py +10 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/__init__.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/db.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/ions.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/mineral.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/__pycache__/sites.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/db.py +88 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/ions.py +78 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/mineral.py +587 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/mineral/sites.py +134 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/norm.py +224 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/normalisation.py +204 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/plot.py +514 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__init__.py +13 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/__init__.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/database.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/env.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/general.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/georoc.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/math.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/melts.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/multip.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/multiprocessing.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/pd.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/plot.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/skl.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/spatial.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/text.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/time.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/__pycache__/wfs.cpython-36.pyc +0 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/database.py +88 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/env.py +81 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/general.py +266 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/georoc.py +444 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/math.py +371 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/melts.py +397 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/multip.py +29 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/multiprocessing.py +29 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/pd.py +214 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/plot.py +345 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/skl.py +847 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/spatial.py +91 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/text.py +207 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/time.py +224 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite/util/wfs.py +10 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/PKG-INFO +61 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/SOURCES.txt +83 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/dependency_links.txt +1 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/requires.txt +47 -0
- ProgramData/Anaconda3_64/Lib/site-packages/pyrolite-0.0.14-py3.6.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os, sys
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from .general import iscollection
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@contextmanager
|
|
11
|
+
def environment_manager(env):
|
|
12
|
+
"""
|
|
13
|
+
Temporarily set environment variables inside the context manager and
|
|
14
|
+
fully restore previous environment afterwards.
|
|
15
|
+
"""
|
|
16
|
+
original_env = {key: os.getenv(key) for key in env}
|
|
17
|
+
os.environ.update(env)
|
|
18
|
+
try:
|
|
19
|
+
yield
|
|
20
|
+
finally:
|
|
21
|
+
for key, value in original_env.items():
|
|
22
|
+
if value is None:
|
|
23
|
+
del os.environ[key]
|
|
24
|
+
else:
|
|
25
|
+
os.environ[key] = value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def validate_value(value, validator):
|
|
29
|
+
"""Validates a value based on one or a series of validator functions."""
|
|
30
|
+
|
|
31
|
+
if iscollection(validator):
|
|
32
|
+
return all([f(value) for f in validator if callable(f)])
|
|
33
|
+
else:
|
|
34
|
+
return validator(value)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def validate_update_envvar(
|
|
38
|
+
key, value=None, prefix="", force_active=False, variable_model={}, formatter=str
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Updates an environment variable after validation.
|
|
42
|
+
|
|
43
|
+
parameters
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
schema = variable_model.get(key, None)
|
|
47
|
+
if schema is not None: # some potential validation
|
|
48
|
+
if value is not None:
|
|
49
|
+
if schema.get("validator", None) is not None:
|
|
50
|
+
valid = validate_value(value, schema["validator"])
|
|
51
|
+
assert valid, "Invalid value for parameter {}: {}".format(var, value)
|
|
52
|
+
|
|
53
|
+
if schema.get("overridden_by", None) is not None:
|
|
54
|
+
# check for overriders
|
|
55
|
+
overriders = [prefix + k for k in schema.get("overridden_by")]
|
|
56
|
+
|
|
57
|
+
if any([over in os.environ for over in overriders]):
|
|
58
|
+
if force_active:
|
|
59
|
+
for k in [key for key in overriders if key in os.environ]:
|
|
60
|
+
del os.environ[key]
|
|
61
|
+
else:
|
|
62
|
+
# try to set to default
|
|
63
|
+
if schema.get("default", None) is not None:
|
|
64
|
+
if schema.get("dependent_on", None) is None:
|
|
65
|
+
default = schema["default"]
|
|
66
|
+
else:
|
|
67
|
+
conditions = {
|
|
68
|
+
k: variable_model[k]["default"]
|
|
69
|
+
for k in schema["dependent_on"]
|
|
70
|
+
if variable_model[k]["default"] is not None
|
|
71
|
+
}
|
|
72
|
+
default = schema["default"](conditions)
|
|
73
|
+
value = default
|
|
74
|
+
|
|
75
|
+
if value is not None:
|
|
76
|
+
logging.debug("EnvVar {} set to {}.".format(prefix + key, value))
|
|
77
|
+
os.environ[prefix + key] = formatter(value)
|
|
78
|
+
else: # Remove the environment variable if it exists
|
|
79
|
+
if prefix + key in os.environ:
|
|
80
|
+
logging.debug("EnvVar {} removed.".format(prefix + key))
|
|
81
|
+
del os.environ[prefix + key]
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import os, sys
|
|
2
|
+
import re
|
|
3
|
+
import time
|
|
4
|
+
import subprocess, shutil
|
|
5
|
+
from tempfile import mkdtemp
|
|
6
|
+
import operator
|
|
7
|
+
import inspect
|
|
8
|
+
import zipfile
|
|
9
|
+
import timeit
|
|
10
|
+
from collections import Mapping
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import numpy as np
|
|
13
|
+
import pandas as pd
|
|
14
|
+
import datetime
|
|
15
|
+
import logging
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
import httplib
|
|
20
|
+
except:
|
|
21
|
+
import http.client as httplib
|
|
22
|
+
import pyrolite # required for introspection/data folder
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
_FLAG_FIRST = object()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Timewith:
|
|
32
|
+
def __init__(self, name=""):
|
|
33
|
+
self.name = name
|
|
34
|
+
self.start = time.time()
|
|
35
|
+
self.checkpoints = []
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def elapsed(self):
|
|
39
|
+
return time.time() - self.start
|
|
40
|
+
|
|
41
|
+
def checkpoint(self, name=""):
|
|
42
|
+
elapsed = self.elapsed
|
|
43
|
+
msg = "{time} {timer}: {checkpoint} in {elapsed:.3f} s.".format(
|
|
44
|
+
timer=self.name,
|
|
45
|
+
time=datetime.datetime.now().strftime("%H:%M:%S"),
|
|
46
|
+
checkpoint=name,
|
|
47
|
+
elapsed=elapsed,
|
|
48
|
+
).strip()
|
|
49
|
+
logger.info(msg)
|
|
50
|
+
self.checkpoints.append((name, elapsed))
|
|
51
|
+
|
|
52
|
+
def __enter__(self):
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def __exit__(self, type, value, traceback):
|
|
56
|
+
self.checkpoint("Finished")
|
|
57
|
+
self.checkpoints.append(("Finished", self.elapsed))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def stream_log(package_name, level="INFO"):
|
|
61
|
+
"""
|
|
62
|
+
Stream the log from a specific package or subpackage.
|
|
63
|
+
"""
|
|
64
|
+
logger = logging.getLogger(package_name)
|
|
65
|
+
ch = logging.StreamHandler()
|
|
66
|
+
fmt = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
|
|
67
|
+
ch.setFormatter(fmt)
|
|
68
|
+
logger.addHandler(ch)
|
|
69
|
+
logger.setLevel(getattr(logging, level))
|
|
70
|
+
return logger
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def pyrolite_datafolder(subfolder=None):
|
|
74
|
+
"""Returns the path of the pyrolite data folder."""
|
|
75
|
+
pth = Path(inspect.getfile(pyrolite)).parent / "data"
|
|
76
|
+
if subfolder:
|
|
77
|
+
pth /= subfolder
|
|
78
|
+
return pth
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def pathify(path):
|
|
82
|
+
"""Converts strings to pathlib.Path objects."""
|
|
83
|
+
if not isinstance(path, Path):
|
|
84
|
+
path = Path(path)
|
|
85
|
+
return path
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def urlify(url):
|
|
89
|
+
"""Strip a string to return a valid URL."""
|
|
90
|
+
return url.strip().replace(" ", "_")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def internet_connection(target="www.google.com"):
|
|
94
|
+
"""
|
|
95
|
+
Tests for an active internet connection, based on an optionally specified
|
|
96
|
+
target.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
target: url
|
|
101
|
+
URL to check connectivity, defaults to www.google.com
|
|
102
|
+
"""
|
|
103
|
+
conn = httplib.HTTPConnection(target, timeout=5)
|
|
104
|
+
try:
|
|
105
|
+
conn.request("HEAD", "/")
|
|
106
|
+
conn.close()
|
|
107
|
+
return True
|
|
108
|
+
except:
|
|
109
|
+
conn.close()
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def temp_path(suffix=""):
|
|
114
|
+
"""Return the path of a temporary directory."""
|
|
115
|
+
dir = mkdtemp(suffix=suffix)
|
|
116
|
+
return Path(dir)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def iscollection(obj):
|
|
120
|
+
"""Checks whether an object is an interable collection"""
|
|
121
|
+
|
|
122
|
+
for ty in [list, np.ndarray, set, tuple, dict, pd.Series]:
|
|
123
|
+
if isinstance(obj, ty):
|
|
124
|
+
return True
|
|
125
|
+
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def check_perl():
|
|
130
|
+
"""Checks whether perl is installed on the system."""
|
|
131
|
+
try:
|
|
132
|
+
p = subprocess.check_output("perl -v")
|
|
133
|
+
returncode = 0
|
|
134
|
+
except subprocess.CalledProcessError as e:
|
|
135
|
+
output = e.output
|
|
136
|
+
returncode = e.returncode
|
|
137
|
+
except FileNotFoundError:
|
|
138
|
+
returncode = 1.0
|
|
139
|
+
|
|
140
|
+
return returncode == 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def flatten_dict(d, climb=False, safemode=False):
|
|
144
|
+
"""
|
|
145
|
+
Flattens a nested dictionary containing only string keys.
|
|
146
|
+
|
|
147
|
+
This will work for dictionaries which don't have two equivalent
|
|
148
|
+
keys at the same level. If you're worried about this, use safemode=True.
|
|
149
|
+
|
|
150
|
+
Partially taken from https://stackoverflow.com/a/6043835.
|
|
151
|
+
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
climb: True | False, False
|
|
155
|
+
Whether to keep trunk or leaf-values, for items with the same key.
|
|
156
|
+
safemode: True | False, False
|
|
157
|
+
Whether to keep all keys as a tuple index, to avoid issues with
|
|
158
|
+
conflicts.
|
|
159
|
+
"""
|
|
160
|
+
lift = lambda x: (x,)
|
|
161
|
+
join = operator.add
|
|
162
|
+
results = []
|
|
163
|
+
|
|
164
|
+
def visit(subdict, results, partialKey):
|
|
165
|
+
for k, v in subdict.items():
|
|
166
|
+
if partialKey == _FLAG_FIRST:
|
|
167
|
+
newKey = lift(k)
|
|
168
|
+
else:
|
|
169
|
+
newKey = join(partialKey, lift(k))
|
|
170
|
+
if isinstance(v, Mapping):
|
|
171
|
+
visit(v, results, newKey)
|
|
172
|
+
else:
|
|
173
|
+
results.append((newKey, v))
|
|
174
|
+
|
|
175
|
+
visit(d, results, _FLAG_FIRST)
|
|
176
|
+
|
|
177
|
+
if safemode:
|
|
178
|
+
pick_key = lambda keys: keys
|
|
179
|
+
else:
|
|
180
|
+
pick_key = lambda keys: keys[-1]
|
|
181
|
+
|
|
182
|
+
sort = map(
|
|
183
|
+
lambda x: x[:2],
|
|
184
|
+
sorted([(pick_key(k), v, len(k)) for k, v in results], key=lambda x: x[-1]),
|
|
185
|
+
) # sorted by depth
|
|
186
|
+
|
|
187
|
+
if not climb:
|
|
188
|
+
# We go down the tree, and prioritise the trunk values
|
|
189
|
+
items = sort
|
|
190
|
+
else:
|
|
191
|
+
# We prioritise the leaf values
|
|
192
|
+
items = [i for i in sort][::-1]
|
|
193
|
+
return dict(items)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def swap_item(list: list, pull: str, push: str):
|
|
197
|
+
"""
|
|
198
|
+
Swap a specified item in a list for another.
|
|
199
|
+
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
list: List to replace item within.
|
|
203
|
+
pull: Item to replace in the list.
|
|
204
|
+
push: Item to add into the list.
|
|
205
|
+
"""
|
|
206
|
+
return [[i, push][i == pull] for i in list]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def copy_file(src, dst, ext=None):
|
|
210
|
+
"""
|
|
211
|
+
Copy a file from one place to another.
|
|
212
|
+
Uses the full filepath including name.
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
src: str | Path
|
|
217
|
+
Source filepath.
|
|
218
|
+
dst: str | Path
|
|
219
|
+
Destination filepath.
|
|
220
|
+
ext: extension, None
|
|
221
|
+
Optional file extension specification.
|
|
222
|
+
"""
|
|
223
|
+
src = Path(src)
|
|
224
|
+
dst = Path(dst)
|
|
225
|
+
if ext is not None:
|
|
226
|
+
src = src.with_suffix(ext)
|
|
227
|
+
dst = dst.with_suffix(ext)
|
|
228
|
+
logger.debug("Copying from {} to {}".format(src, dst))
|
|
229
|
+
with open(str(src), "rb") as fin:
|
|
230
|
+
with open(str(dst), "wb") as fout:
|
|
231
|
+
shutil.copyfileobj(fin, fout)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def remove_tempdir(directory):
|
|
235
|
+
"""
|
|
236
|
+
Remove a specific directory, contained files and sub-directories.
|
|
237
|
+
|
|
238
|
+
Parameters
|
|
239
|
+
----------
|
|
240
|
+
directory: str, Path
|
|
241
|
+
Path to directory.
|
|
242
|
+
"""
|
|
243
|
+
directory = Path(directory)
|
|
244
|
+
shutil.rmtree(str(directory))
|
|
245
|
+
assert not directory.exists()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def extract_zip(zipfile, output_dir):
|
|
249
|
+
"""
|
|
250
|
+
Extracts a zipfile without the uppermost folder.
|
|
251
|
+
|
|
252
|
+
Parameters
|
|
253
|
+
----------
|
|
254
|
+
zipfile: zipfile object
|
|
255
|
+
Zipfile object to extract.
|
|
256
|
+
output_dir: str | Path
|
|
257
|
+
Directory to extract files to.
|
|
258
|
+
"""
|
|
259
|
+
output_dir = Path(output_dir)
|
|
260
|
+
if zipfile.testzip() is None:
|
|
261
|
+
for m in zipfile.namelist():
|
|
262
|
+
fldr, name = re.split("/", m, maxsplit=1)
|
|
263
|
+
if name:
|
|
264
|
+
content = zipfile.open(m, "r").read()
|
|
265
|
+
with open(str(output_dir / name), "wb") as out:
|
|
266
|
+
out.write(content)
|