Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ language: generic
matrix:
include:
- os: linux
env: PYTHON="3.5"
env: PYTHON="3.7"

- os: linux
env: PYTHON="3.6"
env: PYTHON="3.9"

- os: osx
env: PYTHON="3.5"
env: PYTHON="3.7"

- os: osx
env: PYTHON="3.6"
env: PYTHON="3.9"

# Install packages
install:
Expand All @@ -43,7 +43,7 @@ install:
conda env create -qf test-environment.yaml;
conda activate py${PYTHON};
else
if [[ "$PYTHON" == "3.6" && "$TRAVIS_OS_NAME" == "linux" ]]; then
if [[ "$PYTHON" == "3.9" && "$TRAVIS_OS_NAME" == "linux" ]]; then
conda env update -qn base -f build-environment.yaml;
fi
fi
Expand All @@ -56,7 +56,7 @@ script:
- set -e
- if [[ -z "$TRAVIS_TAG" ]]; then
pytest -vv --cov=./;
if [[ "$PYTHON" == "3.6" && "$TRAVIS_OS_NAME" == "linux" ]]; then
if [[ "$PYTHON" == "3.9" && "$TRAVIS_OS_NAME" == "linux" ]]; then
git checkout -- test-environment.yaml;
conda install -q sphinx doctr nbsphinx ipython;
python setup.py install;
Expand All @@ -66,7 +66,7 @@ script:
doctr deploy devel;
fi
else
if [[ "$PYTHON" == "3.6" && "$TRAVIS_OS_NAME" == "linux" ]]; then
if [[ "$PYTHON" == "3.9" && "$TRAVIS_OS_NAME" == "linux" ]]; then
conda build conda.recipe;
anaconda -t $ANACONDA_TOKEN upload $HOME/miniconda/conda-bld/*/pyteck*.tar.bz2;
python setup.py install;
Expand All @@ -91,6 +91,6 @@ deploy:
secure: "vaCCwVyZ8m+PDWub0kpPWYwwAUrtgnFQxU9qKc6VwIp3cCtYyEAZjTbAUzBfc/DsqmpCoLI62hYrQWqq0PwFfs4/1Ho+ppJuuiPvcIs0Syh8iv37YKnQG5Yjc9OjEGOY3ZScIUz57X67dst8HBiNHZnovwh5yxoGCTYrP0HdPlQbMkU6byzpXJ/+gzZaRiXXCPElEMf7HRuOZCkoDUIxypcBAvRHjyqI5TLecfkZBllkA3MFfEMT2mDurU4fmSsS7ndcKONaW9OKWSpSEItGle1Yq68qLN3xJIDSVfWg+vAUANuNAZJwo3CyfwPdxfWq4zth9+fY56ZJg3rz2QhC4kVJIOyNfyHyLdKXCQpCg2A0zcTMItnHafKm8eN2IPKNkO+HN1mpE6+G0UTnGfQtsA3FWQvedvA/WH5f226JJ1RNlJAsMDpf08WK7tTtc4rQ0Rm9TtKiblcZ+AxQMyZCdO3UxKCzqpusZmueIbr4koPFczaQYDsldWihboWp6ToAymI1XwcsSQTQTTcqGqt5ADuI9Ae0egWqpsAe72aiTYUR/FrIXD2ylSQl0E3UobjkYl+5kT4pJtF3TknJqN4VZDAbRP1IxPGcpNXLuZXekLpNaaDxJFepAnytWtIGd/W2vt+Afv5vt5VvGLFS56uuxOkLlIFebw0NfXnT1citLLM="
on:
tags: true
condition: $TRAVIS_OS_NAME == "linux" && $PYTHON == "3.6"
condition: $TRAVIS_OS_NAME == "linux" && $PYTHON == "3.9"
distributions: "sdist bdist_wheel"
skip_upload_docs: true
18 changes: 9 additions & 9 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
version: 1.0.{build}
environment:
PYTHON_LOC: "C:\\Miniconda36-x64"
PYTHON_LOC: "C:\\Miniconda3-x64"

skip_tags: true

Expand All @@ -10,20 +10,20 @@ install:
- cmd: conda config --append channels conda-forge
- cmd: conda update conda
- cmd: conda update -q --all
- ps: (get-content test-environment.yaml) | %{$_ -replace "\$\{PYTHON\}","3.5"} | set-content test-environment.yaml
- ps: (get-content test-environment.yaml) | %{$_ -replace "\$\{PYTHON\}","3.7"} | set-content test-environment.yaml
- cmd: conda env create -qf test-environment.yaml
- cmd: git checkout -- test-environment.yaml
- ps: (get-content test-environment.yaml) | %{$_ -replace "\$\{PYTHON\}","3.6"} | set-content test-environment.yaml
- ps: (get-content test-environment.yaml) | %{$_ -replace "\$\{PYTHON\}","3.9"} | set-content test-environment.yaml
- cmd: conda env create -qf test-environment.yaml
- cmd: conda info -a
- ps: Write-Host "Packages in py3.5 Environment:"
- cmd: conda list -n py3.5
- ps: Write-Host "Packages in py3.6 Environment:"
- cmd: conda list -n py3.6
- ps: Write-Host "Packages in py3.7 Environment:"
- cmd: conda list -n py3.7
- ps: Write-Host "Packages in py3.9 Environment:"
- cmd: conda list -n py3.9

build_script:
- cmd: call %PYTHON_LOC%\Scripts\activate.bat py3.5
- cmd: call %PYTHON_LOC%\Scripts\activate.bat py3.7
- cmd: pytest -vv --cov=./ --cov-append
- cmd: call %PYTHON_LOC%\Scripts\activate.bat py3.6
- cmd: call %PYTHON_LOC%\Scripts\activate.bat py3.9
- cmd: pytest -vv --cov=./ --cov-append
- cmd: codecov -X gcov
4 changes: 2 additions & 2 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ build:

requirements:
build:
- python >=3.5
- python >=3.7,<3.10
- setuptools
- pip

run:
- python
- python >=3.7,<3.10
- pyyaml >=3.12,<4.0
Comment on lines +17 to 23
- numpy >=1.13.1
- scipy >=1.0.0
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
napoleon_numpy_docstring = True
napoleon_google_docstring = False
intersphinx_mapping = {
'python': ('https://docs.python.org/3.6', None),
'python': ('https://docs.python.org/3', None),
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
}

Expand Down
58 changes: 37 additions & 21 deletions pyteck/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,51 +96,67 @@ def create_volume_history(mech, temp, pres, reactants, pres_rise, time_end):
def get_ignition_delay(time, target, target_name, ignition_type):
"""Identify ignition delay based on time, target, and type of detection.
"""
no_ignition_delay = np.array([0.0])

Comment on lines +99 to +100
if ignition_type == 'max':
# Get indices of peaks
peak_inds = detect_peaks(target, edge=None, mph=1.e-9*np.max(target))

# Get index of largest peak (overall ignition delay)
max_ind = peak_inds[np.argmax(target[peak_inds])]

#ign_delays = time[peak_inds[np.where((time[peak_inds[peak_inds <= max_ind]]) > 0.0)]]

ign_delays = time[peak_inds[peak_inds <= max_ind]]
if peak_inds.size == 0:
return no_ignition_delay
else:
# Get index of largest peak (overall ignition delay)
Comment thread
LekiaAnonim marked this conversation as resolved.
max_ind = peak_inds[np.argmax(target[peak_inds])]
ign_delays = time[peak_inds[peak_inds <= max_ind]]
Comment thread
LekiaAnonim marked this conversation as resolved.

elif ignition_type == 'd/dt max':
target = first_derivative(time, target)
# Get indices of peaks. Set a minimum peak height of 1e-7% of the
# maximum value to avoid noise peaks.
peak_inds = detect_peaks(target, edge=None, mph=1.e-9*np.max(target))

# Get index of largest peak (overall ignition delay)
max_ind = peak_inds[np.argmax(target[peak_inds])]

ign_delays = time[peak_inds[np.where((time[peak_inds[peak_inds <= max_ind]]) > 0.0)]]
if peak_inds.size == 0:
return no_ignition_delay
else:
# Get index of largest peak (overall ignition delay)
max_ind = peak_inds[np.argmax(target[peak_inds])]
ign_delays = time[peak_inds[np.where((time[peak_inds[peak_inds <= max_ind]]) > 0.0)]]

elif ignition_type == '1/2 max':
# maximum value, and associated index
max_val = np.max(target)
peak_inds = detect_peaks(target, edge=None, mph=1.e-9*np.max(target))
max_ind = peak_inds[np.argmax(target[peak_inds])]

# TODO: interpolate for actual half-max value
# Find index associated with the 1/2 max value, but only consider
# points before the peak
half_idx = (np.abs(target[0:max_ind] - 0.5 * max_val)).argmin()
ign_delays = np.array([time[half_idx]])
if peak_inds.size == 0:
return no_ignition_delay
else:
max_ind = peak_inds[np.argmax(target[peak_inds])]
# TODO: interpolate for actual half-max value
# Find index associated with the 1/2 max value, but only consider
# points before the peak
half_idx = (np.abs(target[0:max_ind] - 0.5 * max_val)).argmin()
ign_delays = np.array([time[half_idx]])

elif ignition_type == 'd/dt max extrapolated':
# First need to evaluate derivative of the target
target_derivative = first_derivative(time, target)
max_derivative = np.max(target_derivative)

if not np.isfinite(max_derivative) or max_derivative <= 0.0:
return no_ignition_delay

# Get indices of peaks, and index of largest peak, which corresponds to
# the point of maximum deriative
peak_inds = detect_peaks(target_derivative, edge=None, mph=1.e-9*np.max(target))
max_ind = peak_inds[np.argmax(target_derivative[peak_inds])]
# the point of maximum derivative
peak_inds = detect_peaks(target_derivative, edge=None, mph=1.e-9*max_derivative)

# use slope to extrapolate to intercept with baseline value (0 by default)
ign_delays = np.array([time[max_ind] - (target[max_ind] / target_derivative[max_ind])])
if peak_inds.size == 0:
return no_ignition_delay
else:
max_ind = peak_inds[np.argmax(target_derivative[peak_inds])]
Comment thread
LekiaAnonim marked this conversation as resolved.
if target_derivative[max_ind] <= 0.0:
return no_ignition_delay
# use slope to extrapolate to intercept with baseline value (0 by default)
ign_delays = np.array([time[max_ind] - (target[max_ind] / target_derivative[max_ind])])

# TODO: handle target with nonzero baseline?
else:
Expand Down
47 changes: 47 additions & 0 deletions pyteck/tests/test_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,53 @@ def test_derivative_max_extrapolated(self):
rtol=1e-4
)

def test_derivative_max_extrapolated_nonpositive_derivative_returns_zero(self, monkeypatch):
"""Do not extrapolate when the derivative maximum is not positive.
"""
times = np.linspace(0, 1, 3)
target = np.ones_like(times)
derivative = np.array([-1.0, 0.0, -1.0])

monkeypatch.setattr(
simulation, 'first_derivative',
lambda time, target: derivative
)

ignition_delays = simulation.get_ignition_delay(
times, target, 'species', 'd/dt max extrapolated'
)

assert ignition_delays[0] == 0.0

@pytest.mark.parametrize('ignition_type', [
'max',
'd/dt max',
'1/2 max',
'd/dt max extrapolated',
])
def test_flat_signal_returns_zero_without_dumping_target_data(self, ignition_type):
"""Flat signals are expected non-ignitions, not debug-dump cases.
"""
times = np.linspace(0, 1, 100)
target = np.zeros_like(times)

cwd = os.getcwd()
with TemporaryDirectory() as temp_dir:
os.chdir(temp_dir)
try:
ignition_delays = simulation.get_ignition_delay(
times, target, 'species', ignition_type
)
dumped_files = [
filename for filename in os.listdir(temp_dir)
if filename.startswith('target-data-') and filename.endswith('.out')
]
finally:
os.chdir(cwd)
Comment on lines +334 to +346

assert ignition_delays[0] == 0.0
assert dumped_files == []

def test_not_supported_type(self):
"""Test that a non-supported type raises a warning and returns zero.
"""
Expand Down
12 changes: 7 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
long_description = readme + '\n\n' + changelog + '\n\n' + citation

install_requires = [
'pyyaml>=3.12,<4.0',
'pint>=0.7.2,<0.9',
'numpy>=1.13.0,<2.0',
'pyyaml>=3.12',
'pint>=0.7.2',
'numpy>=1.13.0',
'tables',
'pyked>=0.4.1',
'scipy>=1.0.0',
Expand Down Expand Up @@ -60,6 +60,7 @@
package_data={'pyteck': ['tests/*.xml', 'tests/*.yaml', 'tests/dataset_file.txt', 'tests/*.cti']},
install_requires=install_requires,
zip_safe=False,
python_requires='>=3.7,<3.10',

license='MIT License',

Expand All @@ -76,8 +77,9 @@
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python :: 3',
Comment thread
LekiaAnonim marked this conversation as resolved.
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Topic :: Scientific/Engineering :: Chemistry',
],
keywords='chemical_kinetics',
Expand Down
Loading