Skip to content

Commit

Permalink
GitHub Actions (DarkEnergySurvey#89)
Browse files Browse the repository at this point in the history
Closes DarkEnergySurvey#83.

* setup github action
* convert imf steps to int
* yaml safe_load
* testing actions
  • Loading branch information
kadrlica authored Jul 14, 2021
1 parent b350ce5 commit 311e1ca
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 13 deletions.
67 changes: 67 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
# For more information on conda actions see: https://autobencoder.com/2020-08-24-conda-actions/
# Starter workflow for conda: https://github.com/actions/starter-workflows/blob/main/ci/python-package-conda.yml

name: build

on:
push:
branches: [ master, actions ]
pull_request:
branches: [ master ]

jobs:
build:
runs-on: ubuntu-latest
strategy:
max-parallel: 3
matrix:
python-version: [2.7, 3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Setup conda
run: |
# Add $CONDA/bin to built-in path
echo $CONDA/bin >> $GITHUB_PATH
conda update -q conda
conda info
- name: Create conda environment
run: |
conda create -q -n env python=${{ matrix.python-version }} numpy scipy matplotlib astropy healpy pyyaml emcee fitsio corner -c conda-forge -c kadrlica
- name: Install package
run: |
source activate env
export UGALIDIR="$HOME/.ugali"
python setup.py -q install --isochrones --catalogs
- name: Install test data
run: |
wget https://github.com/DarkEnergySurvey/ugali/releases/download/v1.7.0/ugali-test-data.tar.gz -O ugali-test-data.tar.gz
tar -xzf ugali-test-data.tar.gz
- name: Lint with flake8
if: ${{ false }}
run: |
source activate env
conda install -q flake8 -c conda-forge
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with nose
run: |
source activate env
conda install -q nose -c conda-forge
export MPLBACKEND=Agg
# Exclude notebook tests
nosetests -v -I test_notebook.py;
- name: Test notebooks
if: ${{ matrix.python-version == '2.7' }}
run: |
source activate env
conda install -q jupyter nbconvert -c conda-forge
# Run notebook tests
nosetests -v tests/test_notebook.py
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Build](https://img.shields.io/travis/DarkEnergySurvey/ugali.svg)](https://travis-ci.org/DarkEnergySurvey/ugali)
[![Build](https://github.com/DarkEnergySurvey/ugali/actions/workflows/python-package.yml/badge.svg)](https://github.com/DarkEnergySurvey/ugali/actions/workflows/python-package.yml)
[![PyPI](https://img.shields.io/pypi/v/ugali.svg)](https://pypi.python.org/pypi/ugali)
[![Release](https://img.shields.io/github/release/DarkEnergySurvey/ugali.svg)](../../releases)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](../../)
Expand Down
8 changes: 5 additions & 3 deletions ugali/analysis/imf.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@ def __call__(self, mass, **kwargs):
""" Call the pdf of the mass function """
return self.pdf(mass,**kwargs)

def integrate(self, mass_min, mass_max, log_mode=True, weight=False, steps=1e4):
def integrate(self, mass_min, mass_max, log_mode=True, weight=False, steps=10000):
""" Numerical Riemannn integral of the IMF (stupid simple).
Parameters:
-----------
mass_min: minimum mass bound for integration (solar masses)
mass_max: maximum mass bound for integration (solar masses)
log_mode[True]: use logarithmic steps in stellar mass as oppose to linear
weight[False]: weight the integral by stellar mass
steps: number of numerical integration steps
weight[False]: weight the integral by stellar mass
steps: number of numerical integration steps
Returns:
--------
result of integral
"""
steps = int(steps)
if log_mode:
d_log_mass = (np.log10(mass_max) - np.log10(mass_min)) / float(steps)
log_mass = np.linspace(np.log10(mass_min), np.log10(mass_max), steps)
Expand Down Expand Up @@ -73,6 +74,7 @@ def sample(self, n, mass_min=0.1, mass_max=10., steps=10000, seed=None):
mass : array of randomly sampled mass values
"""
if seed is not None: np.random.seed(seed)
steps = int(steps)
d_mass = (mass_max - mass_min) / float(steps)
mass = np.linspace(mass_min, mass_max, steps)
cdf = np.insert(np.cumsum(d_mass * self.pdf(mass[1:], log_mode=False)), 0, 0.)
Expand Down
2 changes: 1 addition & 1 deletion ugali/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _load(self, config):
"""
if isstring(config):
self.filename = config
params = yaml.load(open(config))
params = yaml.safe_load(open(config))
elif isinstance(config, Config):
# This is the copy constructor...
self.filename = config.filename
Expand Down
16 changes: 8 additions & 8 deletions ugali/utils/parabola.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ def profileUpperLimit(self, delta = 2.71):

return max((np.sqrt(b**2 - 4. * a * c) - b) / (2. * a), (-1. * np.sqrt(b**2 - 4. * a * c) - b) / (2. * a))

def bayesianUpperLimit(self, alpha, steps=1.e5, plot=False):
def bayesianUpperLimit(self, alpha, steps=1e5, plot=False):
"""
Compute one-sided upper limit using Bayesian Method of Helene.
Several methods of increasing numerical stability have been implemented.
"""
x_dense, y_dense = self.densify()
y_dense -= np.max(y_dense) # Numeric stability
f = scipy.interpolate.interp1d(x_dense, y_dense, kind='linear')
x = np.linspace(0., np.max(x_dense), steps)
x = np.linspace(0., np.max(x_dense), int(steps))
pdf = np.exp(f(x) / 2.)
cut = (pdf / np.max(pdf)) > 1.e-10
x = x[cut]
Expand All @@ -147,7 +147,7 @@ def bayesianUpperLimit(self, alpha, steps=1.e5, plot=False):

return cdf_reflect(alpha)

def bayesianUpperLimit2(self, alpha, steps=1.e5, plot=False):
def bayesianUpperLimit2(self, alpha, steps=1e5, plot=False):
"""
Compute one-sided upper limit using Bayesian Method of Helene.
"""
Expand All @@ -156,7 +156,7 @@ def bayesianUpperLimit2(self, alpha, steps=1.e5, plot=False):
f = scipy.interpolate.interp1d(self.x[cut], self.y[cut], kind='cubic')
except:
f = scipy.interpolate.interp1d(self.x[cut], self.y[cut], kind='linear')
x = np.linspace(0., np.max(self.x[cut]), steps)
x = np.linspace(0., np.max(self.x[cut]), int(steps))
y = np.exp(f(x) / 2.)
#forbidden = np.nonzero((y / np.exp(self.vertex_y / 2.)) < 1.e-10)[0]
forbidden = np.nonzero((y / self.vertex_y) < 1.e-10)[0]
Expand All @@ -171,17 +171,17 @@ def bayesianUpperLimit2(self, alpha, steps=1.e5, plot=False):
return cdf_reflect(alpha)


def confidenceInterval(self, alpha=0.6827, steps=1.e5, plot=False):
def confidenceInterval(self, alpha=0.6827, steps=1e5, plot=False):
"""
Compute two-sided confidence interval by taking x-values corresponding to the largest PDF-values first.
"""
x_dense, y_dense = self.densify()
y_dense -= np.max(y_dense) # Numeric stability
f = scipy.interpolate.interp1d(x_dense, y_dense, kind='linear')
x = np.linspace(0., np.max(x_dense), steps)
x = np.linspace(0., np.max(x_dense), int(steps))
# ADW: Why does this start at 0, which often outside the input range?
# Wouldn't starting at xmin be better:
#x = np.linspace(np.min(x_dense), np.max(x_dense), steps)
#x = np.linspace(np.min(x_dense), np.max(x_dense), int(steps))
pdf = np.exp(f(x) / 2.)
cut = (pdf / np.max(pdf)) > 1.e-10
x = x[cut]
Expand All @@ -206,7 +206,7 @@ def upperLimitsDeltaTS(confidence_level, one_sided=True, degrees_of_freedom=1):
ts_min = 0 # TS = Test Statistic
ts_max = 5
ts_steps = 1000
x = np.linspace(ts_min, ts_max, ts_steps)
x = np.linspace(ts_min, ts_max, int(ts_steps))
y = (0.5 * scipy.stats.chi2.sf(x, degrees_of_freedom) - (1. - confidence_level))**2
return x[np.argmin(y)]

Expand Down

0 comments on commit 311e1ca

Please sign in to comment.