From 12a5ef901fc4226e84dcb11ba5f2d5ce50efcb66 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 16:52:12 -0800 Subject: [PATCH 01/19] Udpated build options, added additional versions of Python --- .github/workflows/build_tests.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index bb2d178..2d912f2 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -10,7 +10,9 @@ on: pull_request: branches: - '**' - + schedule: + - cron: '0 0 1 * *' + jobs: build: @@ -18,9 +20,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies run: | python --version @@ -32,7 +34,7 @@ jobs: python setup.py bdist_wheel ls dist/* - name: Save wheel - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: wheel path: dist/chama*.whl @@ -67,7 +69,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9, 3.10, 3.11] os: [ubuntu-latest] steps: - uses: actions/checkout@v2 @@ -103,7 +105,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.8 - uses: actions/checkout@v2 @@ -151,7 +153,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: 3.9 - uses: actions/checkout@v2 - name: Install coverage run: | From 9aac2ecec8b42d37ff65d53dbb0af1b87bd97c7f Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 16:54:48 -0800 Subject: [PATCH 02/19] minor update --- .github/workflows/build_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index 2d912f2..3dc8601 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -69,7 +69,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.7, 3.8, 3.9, 3.10, 3.11] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] os: [ubuntu-latest] steps: - uses: actions/checkout@v2 @@ -107,7 +107,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - uses: actions/checkout@v2 - name: Install coverage run: | From 8e65fb6b0287276eca019bfbd9600b685a162b5f Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 17:00:20 -0800 Subject: [PATCH 03/19] revert to older versions of python --- .github/workflows/build_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index 3dc8601..e1fb17f 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -69,7 +69,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + python-version: ['3.7', '3.8', '3.9'] os: [ubuntu-latest] steps: - uses: actions/checkout@v2 From 5bad82ff55c55b6be5fc44766d38c86d26207f7b Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 17:19:22 -0800 Subject: [PATCH 04/19] updated versions on actions --- .github/workflows/build_tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index e1fb17f..fc53d27 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -49,11 +49,11 @@ jobs: # os: [ubuntu-latest] # steps: # - name: Set up Python - # uses: actions/setup-python@v2 + # uses: actions/setup-python@v4 # with: # python-version: ${{ matrix.python-version }} # - name: Download wheel - # uses: actions/download-artifact@v2 + # uses: actions/download-artifact@v3 # with: # name: wheel # - name: Install chama @@ -95,7 +95,7 @@ jobs: env: COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - name: Save coverage - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: coverage path: .coverage.${{ matrix.python-version }}.${{ matrix.os }} @@ -116,7 +116,7 @@ jobs: pip install coveralls python setup.py develop - name: Download coverage artifacts from test matrix - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: coverage - name: Setup coverage and combine reports @@ -135,12 +135,12 @@ jobs: coverage json --pretty-print coverage html --show-contexts - name: Save coverage JSON - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: coverage path: coverage.json - name: Save coverage html - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: coverage path: htmlcov @@ -151,7 +151,7 @@ jobs: continue-on-error: true steps: - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.9 - uses: actions/checkout@v2 @@ -162,7 +162,7 @@ jobs: pip install -r requirements.txt python setup.py develop - name: Download coverage artifacts from test matrix - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: coverage - name: Setup coverage and combine reports From 4c95be152fe8751d2383c0e21d1d75637ebed09e Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 17:30:19 -0800 Subject: [PATCH 05/19] Test pandas to <2.0 --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 676de91..c1e2935 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Required pyomo -pandas +pandas<2.0 numpy scipy diff --git a/setup.py b/setup.py index cfc1aef..0833e3b 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ MAINTAINER_EMAIL = 'kaklise@sandia.gov' LICENSE = 'Revised BSD' URL = 'https://github.com/sandialabs/chama' -DEPENDENCIES = ['pyomo', 'pandas', 'numpy', 'scipy'] +DEPENDENCIES = ['pyomo', 'pandas<2.0', 'numpy', 'scipy'] # use README file as the long description file_dir = os.path.abspath(os.path.dirname(__file__)) From c4616caeba5fa08d64ade627c9a9151132546252 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 18:33:53 -0800 Subject: [PATCH 06/19] updated to solution with the same objective --- documentation/optimization.rst | 2 +- examples/plume_example.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/optimization.rst b/documentation/optimization.rst index 502806f..af7f3c9 100644 --- a/documentation/optimization.rst +++ b/documentation/optimization.rst @@ -326,7 +326,7 @@ by the sensor placement (listed as 'scenario-time'). ... use_sensor_cost=True) >>> print(results['Sensors']) - ['A', 'B', 'D'] + ['A', 'B', 'C'] >>> print(results['Objective']) 11.0 >>> print(round(results['FractionDetected'],2)) diff --git a/examples/plume_example.py b/examples/plume_example.py index 6251ca4..c150177 100644 --- a/examples/plume_example.py +++ b/examples/plume_example.py @@ -94,4 +94,4 @@ # Simple test to ensure results don't change assert results['Objective'] == 99.0 -assert results['Sensors'] == ['Sensor384', 'Sensor551', 'Sensor575', 'Sensor731', 'Sensor797'] \ No newline at end of file +assert results['Sensors'] == ['Sensor384', 'Sensor551', 'Sensor575', 'Sensor681', 'Sensor751'] From 6392aea6f0b9d8b2829f548c3a8ce8e09beb98c5 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 18:37:03 -0800 Subject: [PATCH 07/19] added back in additional python versions --- .github/workflows/build_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index fc53d27..9b1db49 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -69,7 +69,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ['3.7', '3.8', '3.9'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] os: [ubuntu-latest] steps: - uses: actions/checkout@v2 From ab4636e61eae71f12242fe91c442e09196809e4f Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 18:54:51 -0800 Subject: [PATCH 08/19] remove dependency on nose --- .github/workflows/build_tests.yml | 5 ++++- documentation/developers.rst | 4 ++-- documentation/installation.rst | 2 +- requirements.txt | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index 9b1db49..be660d9 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -91,7 +91,10 @@ jobs: run: | export PATH=/usr/share/miniconda/bin:$PATH coverage erase - coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m nose -v --nologcapture --with-doctest --doctest-extension=.rst --traverse-namespace documentation/*.rst chama + #coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m nose -v --nologcapture --with-doctest --doctest-extension=.rst --traverse-namespace documentation/*.rst chama + coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m pytest --doctest-modules --doctest-glob="*.rst" chama + coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" --append -m pytest --doctest-glob="*.rst" documentation + env: COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - name: Save coverage diff --git a/documentation/developers.rst b/documentation/developers.rst index 58f6608..48a2613 100644 --- a/documentation/developers.rst +++ b/documentation/developers.rst @@ -24,9 +24,9 @@ The latest stable version is hosted on PyPI at https://pypi.python.org/pypi/cham **Testing:** Automated testing is run using TravisCI at https://travis-ci.org/sandialabs/chama. Test coverage statistics are collected using Coveralls at https://coveralls.io/github/sandialabs/chama. -Tests can be run locally using nosetests:: +Tests can be run locally using pytest:: - nosetests -v --with-coverage --cover-package=chama chama + pytest chama **Documentation:** Documentation is built using Read the Docs and hosted at https://chama.readthedocs.io. diff --git a/documentation/installation.rst b/documentation/installation.rst index ca27b7b..c497159 100644 --- a/documentation/installation.rst +++ b/documentation/installation.rst @@ -39,7 +39,7 @@ Optional Python package dependencies include: * Matplotlib [Hunt07]_: Used to produce graphics, http://matplotlib.org. -* nose: Used to run software tests, http://nose.readthedocs.io. +* pytest: Used to run software tests, https://docs.pytest.org/. Required Pyomo supported MIP solver: diff --git a/requirements.txt b/requirements.txt index c1e2935..bb75005 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,5 +5,5 @@ numpy scipy # Optional -nose +pytest matplotlib From 86c7c1a19295626357806e840d1c63c9c708b807 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Fri, 17 Nov 2023 19:08:48 -0800 Subject: [PATCH 09/19] ensure matplotlib is optional by removing plt colormap from input args --- chama/graphics.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/chama/graphics.py b/chama/graphics.py index e9e416a..478cc50 100644 --- a/chama/graphics.py +++ b/chama/graphics.py @@ -19,7 +19,7 @@ from matplotlib.collections import PatchCollection from matplotlib.animation import FuncAnimation except: - pass + plt = None from scipy.spatial import ConvexHull import numpy as np @@ -27,7 +27,7 @@ def signal_convexhull(signal, scenarios, threshold, timesteps=None, - colormap=plt.cm.viridis, + colormap=None, x_range=(None, None), y_range=(None, None), z_range=(None, None)): """ @@ -54,6 +54,11 @@ def signal_convexhull(signal, scenarios, threshold, timesteps=None, z_range: tuple (optional) The z-axis limits for the plot """ + if plt is None: + raise ImportError('matplotlib is required for graphics') + if colormap is None: + colormap = plt.get_cmap('viridis') + t_col = 'T' x_col = 'X' y_col = 'Y' @@ -104,7 +109,7 @@ def signal_convexhull(signal, scenarios, threshold, timesteps=None, def signal_xsection(signal, signal_name, threshold=None, timesteps=None, x_value=None, y_value=None, z_value=None, log_flag=False, - colormap=plt.cm.viridis, alpha=0.7, N=5, + colormap=None, alpha=0.7, N=5, x_range=(None, None), y_range=(None, None), z_range=(None, None)): """ @@ -147,7 +152,11 @@ def signal_xsection(signal, signal_name, threshold=None, timesteps=None, z_range: tuple (optional) The z-axis limits for the plot """ - + if plt is None: + raise ImportError('matplotlib is required for graphics') + if colormap is None: + colormap = plt.get_cmap('viridis') + t_col = 'T' x_col = 'X' y_col = 'Y' @@ -318,7 +327,10 @@ def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): if c is not None: plt.sci(collection) return collection - + + if plt is None: + raise ImportError('matplotlib is required for graphics') + fig, ax = plt.subplots() # ln, = plt.plot([],[],animated=True) @@ -371,7 +383,9 @@ def sensor_locations(sensors, x_range=(None, None), y_range=(None, None), sensor. The key:value pairs are {'sensor name' : String representing the marker to be passed to the plot function) """ - + if plt is None: + raise ImportError('matplotlib is required for graphics') + fig = plt.figure() ax = fig.add_subplot(111, projection='3d') From 9a288a97a58384ebc75772339f30d502aaa958b2 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Sat, 18 Nov 2023 10:45:25 -0800 Subject: [PATCH 10/19] Remove deprecated pandas lookup --- chama/impact.py | 11 +++++++---- requirements.txt | 2 +- setup.py | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/chama/impact.py b/chama/impact.py index 4e99640..8072b23 100644 --- a/chama/impact.py +++ b/chama/impact.py @@ -153,10 +153,13 @@ def detection_time_to_impact(detection_time, impact_data): impact_data.interpolate(inplace=True) det_damage = detection_time.copy() - det_damage['T'] = impact_data.lookup(detection_time['T'], - detection_time['Scenario']) - det_damage.rename(columns={'T': 'Impact'}, inplace=True) - + times = detection_time['T'] + scenarios = detection_time['Scenario'] + impact_vals = impact_data.to_numpy()[impact_data.index.get_indexer(times), + impact_data.columns.get_indexer(scenarios)] + det_damage['Impact'] = impact_vals + del det_damage['T'] + return det_damage diff --git a/requirements.txt b/requirements.txt index bb75005..e4fb280 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Required pyomo -pandas<2.0 +pandas numpy scipy diff --git a/setup.py b/setup.py index 0833e3b..cfc1aef 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ MAINTAINER_EMAIL = 'kaklise@sandia.gov' LICENSE = 'Revised BSD' URL = 'https://github.com/sandialabs/chama' -DEPENDENCIES = ['pyomo', 'pandas<2.0', 'numpy', 'scipy'] +DEPENDENCIES = ['pyomo', 'pandas', 'numpy', 'scipy'] # use README file as the long description file_dir = os.path.abspath(os.path.dirname(__file__)) From fccc342316d47ec254af8ddfccfc29b4a7009c2b Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Sat, 18 Nov 2023 11:31:21 -0800 Subject: [PATCH 11/19] udpated build workflow --- .github/workflows/build_tests.yml | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index be660d9..1a6beff 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -1,4 +1,4 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python +# This workflow will install Python dependencies, run tests and coverage # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions name: build @@ -16,13 +16,17 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + os: [ubuntu-latest] steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python --version @@ -36,8 +40,8 @@ jobs: - name: Save wheel uses: actions/upload-artifact@v3 with: - name: wheel - path: dist/chama*.whl + name: chama_${{ matrix.python-version }}_${{ matrix.os }}.whl + path: dist/chama* #test: # name: Import test @@ -45,7 +49,7 @@ jobs: # runs-on: ${{ matrix.os }} # strategy: # matrix: - # python-version: [3.7, 3.8, 3.9] + # python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] # os: [ubuntu-latest] # steps: # - name: Set up Python @@ -65,7 +69,7 @@ jobs: # run: | # python -c "import chama" - linux: + create_coverage_reports: runs-on: ${{ matrix.os }} strategy: matrix: @@ -86,13 +90,12 @@ jobs: pip install -r requirements.txt conda install -y -c conda-forge glpk pip install coverage coveralls wntr - python setup.py develop + python -m pip install -e . - name: Run Tests run: | export PATH=/usr/share/miniconda/bin:$PATH coverage erase - #coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m nose -v --nologcapture --with-doctest --doctest-extension=.rst --traverse-namespace documentation/*.rst chama - coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m pytest --doctest-modules --doctest-glob="*.rst" chama + coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m pytest --doctest-modules --doctest-glob="*.rst" chama coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" --append -m pytest --doctest-glob="*.rst" documentation env: @@ -103,8 +106,8 @@ jobs: name: coverage path: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - coverage: - needs: [ linux ] + combine_reports: + needs: [ create_coverage_reports ] runs-on: ubuntu-latest steps: - name: Set up Python @@ -148,8 +151,8 @@ jobs: name: coverage path: htmlcov - coveralls: - needs: [ linux ] + combine_reports_upload_coveralls: + needs: [ create_coverage_reports ] runs-on: ubuntu-latest continue-on-error: true steps: @@ -163,7 +166,7 @@ jobs: python -m pip install --upgrade pip pip install coveralls pip install -r requirements.txt - python setup.py develop + python -m pip install -e . - name: Download coverage artifacts from test matrix uses: actions/download-artifact@v3 with: From 01ff73f3e4e948def74453bf6711f59850a61891 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Sat, 18 Nov 2023 12:10:21 -0800 Subject: [PATCH 12/19] Removed animation function, not compatible with GaussianPuff simulation, use static graphics options --- chama/graphics.py | 230 +++++++++++++++++------------------ chama/tests/test_graphics.py | 3 - 2 files changed, 115 insertions(+), 118 deletions(-) diff --git a/chama/graphics.py b/chama/graphics.py index 478cc50..6da2a5c 100644 --- a/chama/graphics.py +++ b/chama/graphics.py @@ -7,21 +7,16 @@ signal_convexhull signal_xsection - animate_puffs sensor_locations """ from __future__ import print_function, division try: import matplotlib.pyplot as plt from matplotlib import ticker - from mpl_toolkits.mplot3d import Axes3D - from matplotlib.patches import Circle, Ellipse, Rectangle - from matplotlib.collections import PatchCollection - from matplotlib.animation import FuncAnimation except: plt = None - -from scipy.spatial import ConvexHull + +from scipy.spatial import ConvexHull import numpy as np from chama.sensors import Mobile @@ -247,114 +242,6 @@ def contour_data(temp, threshold, log_flag): fig.show() -def animate_puffs(puff, x_range=(None, None), y_range=(None, None)): - """ - Plots the horizontal movement of puffs from a GaussianPuff simulation - over time. Each puff is represented as a circle centered at the puff - center location with radius equal to the standard deviation in the - horizontal direction (sigmaY). - - Parameters - ------------------ - puff: pandas DataFrame - The puff DataFrame created by a GaussianPuff object - x_range: tuple (xmin, xmax) (optional) - The x-axis limits for the plot - y_range: tuple (ymin, ymax) (optional) - The y-axis limits for the plot - """ - - def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): - """ - Make a scatter plot of circles. - Similar to plt.scatter, but the size of circles are in data scale. - - Parameters - ---------- - x, y : scalar or array_like, shape (n, ) - Input data - s : scalar or array_like, shape (n, ) - Radius of circles. - c : color or sequence of color, optional, default : 'b' - `c` can be a single color format string, or a sequence of color - specifications of length `N`, or a sequence of `N` numbers to be - mapped to colors using the `cmap` and `norm` specified via kwargs. - Note that `c` should not be a single numeric RGB or RGBA sequence - because that is indistinguishable from an array of values - to be colormapped. (If you insist, use `color` instead.) - `c` can be a 2-D array in which the rows are RGB or RGBA, however. - vmin, vmax : scalar, optional, default: None - `vmin` and `vmax` are used in conjunction with `norm` to normalize - luminance data. If either are `None`, the min and max of the - color array is used. - kwargs : `~matplotlib.collections.Collection` properties - Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), - linestyle(ls), norm, cmap, transform, etc. - - Returns - ------- - paths : `~matplotlib.collections.PathCollection` - """ - - if np.isscalar(c): - kwargs.setdefault('color', c) - c = None - - if 'fc' in kwargs: - kwargs.setdefault('facecolor', kwargs.pop('fc')) - if 'ec' in kwargs: - kwargs.setdefault('edgecolor', kwargs.pop('ec')) - if 'ls' in kwargs: - kwargs.setdefault('linestyle', kwargs.pop('ls')) - if 'lw' in kwargs: - kwargs.setdefault('linewidth', kwargs.pop('lw')) - # You can set `facecolor` with an array for each patch, - # while you can only set `facecolors` with a value for all. - - zipped = np.broadcast(x, y, s) - patches = [Circle((x_, y_), s_) - for x_, y_, s_ in zipped] - collection = PatchCollection(patches, **kwargs) - if c is not None: - c = np.broadcast_to(c, zipped.shape).ravel() - collection.set_array(c) - collection.set_clim(vmin, vmax) - - ax = plt.gca() - ax.add_collection(collection) - ax.autoscale_view() - plt.draw_if_interactive() - if c is not None: - plt.sci(collection) - return collection - - if plt is None: - raise ImportError('matplotlib is required for graphics') - - fig, ax = plt.subplots() - # ln, = plt.plot([],[],animated=True) - - def update(time): - plt.cla() - ax.set_xlim(x_range[0], x_range[1]) - ax.set_ylim(y_range[0], y_range[1]) - ax.set_title('T = %6.2f' % time) - ax.set_xlabel('X') - ax.set_ylabel('Y') - - temp = puff.loc[puff['T'] == time] - out = circles(temp['X'], temp['Y'], temp['sigmaY'], alpha=0.5, - edgecolor='none') - return out - - ani = FuncAnimation(fig, update, frames=puff['T'].unique()) - - # Need a coder like ffmpeg installed in order to save - # ani.save('puff.mp4') - - plt.show() - - def sensor_locations(sensors, x_range=(None, None), y_range=(None, None), z_range=(None, None), legend=False, colors=None, markers=None): @@ -415,3 +302,116 @@ def sensor_locations(sensors, x_range=(None, None), y_range=(None, None), if legend: ax.legend() fig.show() + +# Animation function is no longer working +# Use convex hull or xsection on individual timesteps +# def animate_puffs(puff, x_range=(None, None), y_range=(None, None)): +# """ +# Plots the horizontal movement of puffs from a GaussianPuff simulation +# over time. Each puff is represented as a circle centered at the puff +# center location with radius equal to the standard deviation in the +# horizontal direction (sigmaY). + +# Parameters +# ------------------ +# puff: pandas DataFrame +# The puff DataFrame created by a GaussianPuff object +# x_range: tuple (xmin, xmax) (optional) +# The x-axis limits for the plot +# y_range: tuple (ymin, ymax) (optional) +# The y-axis limits for the plot +# """ + +# def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): +# """ +# Make a scatter plot of circles. +# Similar to plt.scatter, but the size of circles are in data scale. + +# Parameters +# ---------- +# x, y : scalar or array_like, shape (n, ) +# Input data +# s : scalar or array_like, shape (n, ) +# Radius of circles. +# c : color or sequence of color, optional, default : 'b' +# `c` can be a single color format string, or a sequence of color +# specifications of length `N`, or a sequence of `N` numbers to be +# mapped to colors using the `cmap` and `norm` specified via kwargs. +# Note that `c` should not be a single numeric RGB or RGBA sequence +# because that is indistinguishable from an array of values +# to be colormapped. (If you insist, use `color` instead.) +# `c` can be a 2-D array in which the rows are RGB or RGBA, however. +# vmin, vmax : scalar, optional, default: None +# `vmin` and `vmax` are used in conjunction with `norm` to normalize +# luminance data. If either are `None`, the min and max of the +# color array is used. +# kwargs : `~matplotlib.collections.Collection` properties +# Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), +# linestyle(ls), norm, cmap, transform, etc. + +# Returns +# ------- +# paths : `~matplotlib.collections.PathCollection` +# """ + +# if np.isscalar(c): +# kwargs.setdefault('color', c) +# c = None + +# if 'fc' in kwargs: +# kwargs.setdefault('facecolor', kwargs.pop('fc')) +# if 'ec' in kwargs: +# kwargs.setdefault('edgecolor', kwargs.pop('ec')) +# if 'ls' in kwargs: +# kwargs.setdefault('linestyle', kwargs.pop('ls')) +# if 'lw' in kwargs: +# kwargs.setdefault('linewidth', kwargs.pop('lw')) +# # You can set `facecolor` with an array for each patch, +# # while you can only set `facecolors` with a value for all. + +# zipped = np.broadcast(x, y, s) +# patches = [Circle((x_, y_), s_) +# for x_, y_, s_ in zipped] +# collection = PatchCollection(patches, **kwargs) +# if c is not None: +# c = np.broadcast_to(c, zipped.shape).ravel() +# collection.set_array(c) +# collection.set_clim(vmin, vmax) + +# ax = plt.gca() +# ax.add_collection(collection) +# ax.autoscale_view() +# plt.draw_if_interactive() +# if c is not None: +# plt.sci(collection) +# return collection + +# if plt is None: +# raise ImportError('matplotlib is required for graphics') + +# from matplotlib.patches import Circle, Ellipse, Rectangle +# from matplotlib.collections import PatchCollection +# from matplotlib.animation import FuncAnimation + +# fig, ax = plt.subplots() +# # ln, = plt.plot([],[],animated=True) + +# def update(time): +# plt.cla() +# ax.set_xlim(x_range[0], x_range[1]) +# ax.set_ylim(y_range[0], y_range[1]) +# ax.set_title('T = %6.2f' % time) +# ax.set_xlabel('X') +# ax.set_ylabel('Y') + +# temp = puff.loc[puff['T'] == time] +# out = circles(temp['X'], temp['Y'], temp['sigmaY'], alpha=0.5, +# edgecolor='none') +# return out + +# ani = FuncAnimation(fig, update, frames=puff['T'].unique()) + +# # Need a coder like ffmpeg installed in order to save +# # ani.save('puff.mp4') + +# plt.show() \ No newline at end of file diff --git a/chama/tests/test_graphics.py b/chama/tests/test_graphics.py index abca0ca..93b6f53 100644 --- a/chama/tests/test_graphics.py +++ b/chama/tests/test_graphics.py @@ -58,9 +58,6 @@ def test_signal_xsection(self): self.assertTrue(isfile(filename)) - def test_signal_animate(self): - pass - class TestSensorGraphics(unittest.TestCase): From 42847b5d365bac7f9122df01f5fd097969072628 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Sat, 18 Nov 2023 12:10:33 -0800 Subject: [PATCH 13/19] minor update --- documentation/installation.rst | 2 +- readthedocs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/installation.rst b/documentation/installation.rst index c497159..b8cb540 100644 --- a/documentation/installation.rst +++ b/documentation/installation.rst @@ -5,7 +5,7 @@ Installation ====================================== -Chama requires Python (tested on 3.7, 3.8, and 3.9) along with several Python package dependencies. +Chama requires Python (tested on 3.7-3.11) along with several Python package dependencies. Information on installing and using Python can be found at https://www.python.org/. Python distributions, such as Anaconda, are recommended to manage the Python interface. diff --git a/readthedocs.yml b/readthedocs.yml index 1e9ad4d..1060976 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -1,5 +1,5 @@ conda: file: documentation/environment.yml python: - version: 3.8 + version: 3.9 setup_py_install: true \ No newline at end of file From d7f42d182911f544849333292c8582b75013f106 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Mon, 20 Nov 2023 07:40:39 -0800 Subject: [PATCH 14/19] Added animate_puffs back in with a test --- chama/graphics.py | 251 +++++++++++++++++------------------ chama/tests/test_graphics.py | 22 +++ 2 files changed, 145 insertions(+), 128 deletions(-) diff --git a/chama/graphics.py b/chama/graphics.py index 6da2a5c..26ac682 100644 --- a/chama/graphics.py +++ b/chama/graphics.py @@ -69,20 +69,15 @@ def signal_convexhull(signal, scenarios, threshold, timesteps=None, for scenario in scenarios: i = 0 for timestep in timesteps: + color = colormap(i) + i += 1 / float(len(timesteps)) + + signal_t = signal[signal[t_col] == timestep] + conc_filter = signal_t[scenario] > threshold + + data = signal_t[[x_col, y_col, z_col]][conc_filter] + data = data.values try: - color = colormap(i) - i += 1 / float(len(timesteps)) - - signal_t = signal[signal[t_col] == timestep] - conc_filter = signal_t[scenario] > threshold - - # plot points - # data = signal_t[[x_col,y_col,z_col,scenario]][conc_filter] - # data = data.as_matrix() - # ax.scatter(data[:,0], data[:,1], data[:,2], c=data[:,3],s=30) - - data = signal_t[[x_col, y_col, z_col]][conc_filter] - data = data.as_matrix() hull = ConvexHull(data) ax.plot_trisurf(data[:, 0], data[:, 1], data[:, 2], triangles=hull.simplices, @@ -90,8 +85,8 @@ def signal_convexhull(signal, scenarios, threshold, timesteps=None, shade=False, color=color) except: - pass - + print('Convex Hull not created for scenario %s timestep %d' % (scenario, timestep)) + ax.set_xlabel(x_col) ax.set_ylabel(y_col) ax.set_zlabel(z_col) @@ -242,6 +237,119 @@ def contour_data(temp, threshold, log_flag): fig.show() +def animate_puffs(puff, repeat=True): + """ + Plots the horizontal movement of puffs from a GaussianPuff simulation + over time. Each puff is represented as a circle centered at the puff + center location with radius equal to the standard deviation in the + horizontal direction (sigmaY). + + Parameters + ------------------ + puff: pandas DataFrame + The puff DataFrame created by a GaussianPuff object + repeat : bool, optional + If True, the animation will repeat + """ + + def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): + """ + Make a scatter plot of circles. + Similar to plt.scatter, but the size of circles are in data scale. + + Parameters + ---------- + x, y : scalar or array_like, shape (n, ) + Input data + s : scalar or array_like, shape (n, ) + Radius of circles. + c : color or sequence of color, optional, default : 'b' + `c` can be a single color format string, or a sequence of color + specifications of length `N`, or a sequence of `N` numbers to be + mapped to colors using the `cmap` and `norm` specified via kwargs. + Note that `c` should not be a single numeric RGB or RGBA sequence + because that is indistinguishable from an array of values + to be colormapped. (If you insist, use `color` instead.) + `c` can be a 2-D array in which the rows are RGB or RGBA, however. + vmin, vmax : scalar, optional, default: None + `vmin` and `vmax` are used in conjunction with `norm` to normalize + luminance data. If either are `None`, the min and max of the + color array is used. + kwargs : `~matplotlib.collections.Collection` properties + Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), + linestyle(ls), norm, cmap, transform, etc. + + Returns + ------- + paths : `~matplotlib.collections.PathCollection` + """ + + if np.isscalar(c): + kwargs.setdefault('color', c) + c = None + + if 'fc' in kwargs: + kwargs.setdefault('facecolor', kwargs.pop('fc')) + if 'ec' in kwargs: + kwargs.setdefault('edgecolor', kwargs.pop('ec')) + if 'ls' in kwargs: + kwargs.setdefault('linestyle', kwargs.pop('ls')) + if 'lw' in kwargs: + kwargs.setdefault('linewidth', kwargs.pop('lw')) + # You can set `facecolor` with an array for each patch, + # while you can only set `facecolors` with a value for all. + + zipped = np.broadcast(x, y, s) + patches = [Circle((x_, y_), s_) + for x_, y_, s_ in zipped] + collection = PatchCollection(patches, **kwargs) + if c is not None: + c = np.broadcast_to(c, zipped.shape).ravel() + collection.set_array(c) + collection.set_clim(vmin, vmax) + + ax = plt.gca() + ax.add_collection(collection) + ax.autoscale_view() + plt.draw_if_interactive() + if c is not None: + plt.sci(collection) + return collection + + if plt is None: + raise ImportError('matplotlib is required for graphics') + buffer = puff['sigmaY'].max() + puff['sigmaY'].max()/5 + x_range = (puff['X'].min() - buffer, puff['X'].max() + buffer) + y_range = (puff['Y'].min() - buffer, puff['Y'].max() + buffer) + + from matplotlib.patches import Circle, Ellipse, Rectangle + from matplotlib.collections import PatchCollection + from matplotlib.animation import FuncAnimation, FFMpegWriter + + fig, ax = plt.subplots() + # ln, = plt.plot([],[],animated=True) + + def update(time): + plt.cla() + ax.set_xlim(x_range[0], x_range[1]) + ax.set_ylim(y_range[0], y_range[1]) + ax.set_title('T = %6.2f' % time) + ax.set_xlabel('X') + ax.set_ylabel('Y') + + temp = puff.loc[puff['T'] == time] + out = circles(temp['X'], temp['Y'], temp['sigmaY'], alpha=0.5, + edgecolor='none') + return out + + anim = FuncAnimation(fig, update, frames=puff['T'].unique(), interval=50, + blit=False, repeat=repeat) + + plt.show() + + return anim + + def sensor_locations(sensors, x_range=(None, None), y_range=(None, None), z_range=(None, None), legend=False, colors=None, markers=None): @@ -302,116 +410,3 @@ def sensor_locations(sensors, x_range=(None, None), y_range=(None, None), if legend: ax.legend() fig.show() - -# Animation function is no longer working -# Use convex hull or xsection on individual timesteps -# def animate_puffs(puff, x_range=(None, None), y_range=(None, None)): -# """ -# Plots the horizontal movement of puffs from a GaussianPuff simulation -# over time. Each puff is represented as a circle centered at the puff -# center location with radius equal to the standard deviation in the -# horizontal direction (sigmaY). - -# Parameters -# ------------------ -# puff: pandas DataFrame -# The puff DataFrame created by a GaussianPuff object -# x_range: tuple (xmin, xmax) (optional) -# The x-axis limits for the plot -# y_range: tuple (ymin, ymax) (optional) -# The y-axis limits for the plot -# """ - -# def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): -# """ -# Make a scatter plot of circles. -# Similar to plt.scatter, but the size of circles are in data scale. - -# Parameters -# ---------- -# x, y : scalar or array_like, shape (n, ) -# Input data -# s : scalar or array_like, shape (n, ) -# Radius of circles. -# c : color or sequence of color, optional, default : 'b' -# `c` can be a single color format string, or a sequence of color -# specifications of length `N`, or a sequence of `N` numbers to be -# mapped to colors using the `cmap` and `norm` specified via kwargs. -# Note that `c` should not be a single numeric RGB or RGBA sequence -# because that is indistinguishable from an array of values -# to be colormapped. (If you insist, use `color` instead.) -# `c` can be a 2-D array in which the rows are RGB or RGBA, however. -# vmin, vmax : scalar, optional, default: None -# `vmin` and `vmax` are used in conjunction with `norm` to normalize -# luminance data. If either are `None`, the min and max of the -# color array is used. -# kwargs : `~matplotlib.collections.Collection` properties -# Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), -# linestyle(ls), norm, cmap, transform, etc. - -# Returns -# ------- -# paths : `~matplotlib.collections.PathCollection` -# """ - -# if np.isscalar(c): -# kwargs.setdefault('color', c) -# c = None - -# if 'fc' in kwargs: -# kwargs.setdefault('facecolor', kwargs.pop('fc')) -# if 'ec' in kwargs: -# kwargs.setdefault('edgecolor', kwargs.pop('ec')) -# if 'ls' in kwargs: -# kwargs.setdefault('linestyle', kwargs.pop('ls')) -# if 'lw' in kwargs: -# kwargs.setdefault('linewidth', kwargs.pop('lw')) -# # You can set `facecolor` with an array for each patch, -# # while you can only set `facecolors` with a value for all. - -# zipped = np.broadcast(x, y, s) -# patches = [Circle((x_, y_), s_) -# for x_, y_, s_ in zipped] -# collection = PatchCollection(patches, **kwargs) -# if c is not None: -# c = np.broadcast_to(c, zipped.shape).ravel() -# collection.set_array(c) -# collection.set_clim(vmin, vmax) - -# ax = plt.gca() -# ax.add_collection(collection) -# ax.autoscale_view() -# plt.draw_if_interactive() -# if c is not None: -# plt.sci(collection) -# return collection - -# if plt is None: -# raise ImportError('matplotlib is required for graphics') - -# from matplotlib.patches import Circle, Ellipse, Rectangle -# from matplotlib.collections import PatchCollection -# from matplotlib.animation import FuncAnimation - -# fig, ax = plt.subplots() -# # ln, = plt.plot([],[],animated=True) - -# def update(time): -# plt.cla() -# ax.set_xlim(x_range[0], x_range[1]) -# ax.set_ylim(y_range[0], y_range[1]) -# ax.set_title('T = %6.2f' % time) -# ax.set_xlabel('X') -# ax.set_ylabel('Y') - -# temp = puff.loc[puff['T'] == time] -# out = circles(temp['X'], temp['Y'], temp['sigmaY'], alpha=0.5, -# edgecolor='none') -# return out - -# ani = FuncAnimation(fig, update, frames=puff['T'].unique()) - -# # Need a coder like ffmpeg installed in order to save -# # ani.save('puff.mp4') - -# plt.show() \ No newline at end of file diff --git a/chama/tests/test_graphics.py b/chama/tests/test_graphics.py index 93b6f53..dd0acb0 100644 --- a/chama/tests/test_graphics.py +++ b/chama/tests/test_graphics.py @@ -28,7 +28,12 @@ def setUpClass(self): gauss_plume = chama.simulation.GaussianPlume(self.grid, self.source, self.atm) + gauss_puff = chama.simulation.GaussianPuff(self.grid, self.source, + self.atm, tpuff=0.5, + tend=30) self.signal = gauss_plume.conc + self.puff = gauss_puff.puff + @classmethod def tearDownClass(self): @@ -58,6 +63,23 @@ def test_signal_xsection(self): self.assertTrue(isfile(filename)) + def test_puff_animation(self): + filename = abspath(join(testdir, 'plot_puff_animation.gif')) + if isfile(filename): + os.remove(filename) + + anim = chama.graphics.animate_puffs(self.puff) + + from matplotlib.animation import FuncAnimation, writers + try: + writer = writers.list()[0] + anim.save(filename, writer=writer) + self.assertTrue(isfile(filename)) + except: + pass + + self.assertTrue(isinstance(anim, FuncAnimation)) + class TestSensorGraphics(unittest.TestCase): From 12cb2cca5221db097747fa519988443187cce35f Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Mon, 20 Nov 2023 08:23:29 -0800 Subject: [PATCH 15/19] cleanup --- .github/workflows/build_tests.yml | 62 +++++++++++++++---------------- chama/graphics.py | 12 +++--- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index 1a6beff..c7d8bbd 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -43,33 +43,33 @@ jobs: name: chama_${{ matrix.python-version }}_${{ matrix.os }}.whl path: dist/chama* - #test: - # name: Import test - # needs: build - # runs-on: ${{ matrix.os }} - # strategy: - # matrix: - # python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] - # os: [ubuntu-latest] - # steps: - # - name: Set up Python - # uses: actions/setup-python@v4 - # with: - # python-version: ${{ matrix.python-version }} - # - name: Download wheel - # uses: actions/download-artifact@v3 - # with: - # name: wheel - # - name: Install chama - # run: | - # python -m pip install --upgrade pip - # pip install wheel - # pip install --find-links=. chama - # - name: Import test - # run: | - # python -c "import chama" + install: + name: Import test + needs: build + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + os: [ubuntu-latest] + steps: + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Download wheel + uses: actions/download-artifact@v3 + with: + name: wheel + - name: Install chama + run: | + python -m pip install --upgrade pip + pip install wheel + pip install --find-links=. chama + - name: Import test + run: | + python -c "import chama" - create_coverage_reports: + pytest_coverage: runs-on: ${{ matrix.os }} strategy: matrix: @@ -106,8 +106,8 @@ jobs: name: coverage path: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - combine_reports: - needs: [ create_coverage_reports ] + coverage_reports: + needs: [ pytest_coverage ] runs-on: ubuntu-latest steps: - name: Set up Python @@ -120,7 +120,7 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt pip install coveralls - python setup.py develop + python -m pip install -e . - name: Download coverage artifacts from test matrix uses: actions/download-artifact@v3 with: @@ -151,8 +151,8 @@ jobs: name: coverage path: htmlcov - combine_reports_upload_coveralls: - needs: [ create_coverage_reports ] + coveralls: + needs: [ pytest_coverage ] runs-on: ubuntu-latest continue-on-error: true steps: diff --git a/chama/graphics.py b/chama/graphics.py index 26ac682..03cddba 100644 --- a/chama/graphics.py +++ b/chama/graphics.py @@ -13,6 +13,9 @@ try: import matplotlib.pyplot as plt from matplotlib import ticker + from matplotlib.patches import Circle + from matplotlib.collections import PatchCollection + from matplotlib.animation import FuncAnimation except: plt = None @@ -21,8 +24,8 @@ from chama.sensors import Mobile -def signal_convexhull(signal, scenarios, threshold, timesteps=None, - colormap=None, +def signal_convexhull(signal, scenarios, threshold, timesteps=None, + colormap=None, x_range=(None, None), y_range=(None, None), z_range=(None, None)): """ @@ -318,13 +321,10 @@ def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): if plt is None: raise ImportError('matplotlib is required for graphics') + buffer = puff['sigmaY'].max() + puff['sigmaY'].max()/5 x_range = (puff['X'].min() - buffer, puff['X'].max() + buffer) y_range = (puff['Y'].min() - buffer, puff['Y'].max() + buffer) - - from matplotlib.patches import Circle, Ellipse, Rectangle - from matplotlib.collections import PatchCollection - from matplotlib.animation import FuncAnimation, FFMpegWriter fig, ax = plt.subplots() # ln, = plt.plot([],[],animated=True) From 9e79d36913f288ce5346365783997e5df2e65113 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Mon, 20 Nov 2023 08:41:26 -0800 Subject: [PATCH 16/19] minor update to build script --- .github/workflows/build_tests.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index c7d8bbd..07fcce6 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -43,8 +43,7 @@ jobs: name: chama_${{ matrix.python-version }}_${{ matrix.os }}.whl path: dist/chama* - install: - name: Import test + import: needs: build runs-on: ${{ matrix.os }} strategy: @@ -59,7 +58,7 @@ jobs: - name: Download wheel uses: actions/download-artifact@v3 with: - name: wheel + name: chama_${{ matrix.python-version }}_${{ matrix.os }}.whl - name: Install chama run: | python -m pip install --upgrade pip From 940ba087f567cd274fa97f849219c1196fe89df8 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Mon, 20 Nov 2023 12:24:47 -0800 Subject: [PATCH 17/19] minor update --- .github/workflows/build_tests.yml | 11 +++++------ chama/graphics.py | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml index 07fcce6..692b0b9 100644 --- a/.github/workflows/build_tests.yml +++ b/.github/workflows/build_tests.yml @@ -62,9 +62,9 @@ jobs: - name: Install chama run: | python -m pip install --upgrade pip - pip install wheel - pip install --find-links=. chama - - name: Import test + pip install wheel pyomo pandas numpy scipy + pip install --no-index --pre --find-links=. chama + - name: Import chama run: | python -c "import chama" @@ -90,13 +90,12 @@ jobs: conda install -y -c conda-forge glpk pip install coverage coveralls wntr python -m pip install -e . - - name: Run Tests + - name: Run tests and coverage run: | export PATH=/usr/share/miniconda/bin:$PATH coverage erase coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" -m pytest --doctest-modules --doctest-glob="*.rst" chama coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=chama --omit="*/tests/*" --append -m pytest --doctest-glob="*.rst" documentation - env: COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - name: Save coverage @@ -120,7 +119,7 @@ jobs: pip install -r requirements.txt pip install coveralls python -m pip install -e . - - name: Download coverage artifacts from test matrix + - name: Download coverage artifacts uses: actions/download-artifact@v3 with: name: coverage diff --git a/chama/graphics.py b/chama/graphics.py index 03cddba..0d79839 100644 --- a/chama/graphics.py +++ b/chama/graphics.py @@ -7,6 +7,7 @@ signal_convexhull signal_xsection + animate_puffs sensor_locations """ from __future__ import print_function, division From 1e7769458f839c5a71b66e2db1aa547b0f87948d Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Mon, 20 Nov 2023 13:25:58 -0800 Subject: [PATCH 18/19] Added the x and y range input args back to puff animation --- chama/graphics.py | 16 ++++++++++++---- chama/tests/test_graphics.py | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/chama/graphics.py b/chama/graphics.py index 0d79839..0e2d530 100644 --- a/chama/graphics.py +++ b/chama/graphics.py @@ -241,7 +241,7 @@ def contour_data(temp, threshold, log_flag): fig.show() -def animate_puffs(puff, repeat=True): +def animate_puffs(puff, x_range=(None, None), y_range=(None, None), repeat=True): """ Plots the horizontal movement of puffs from a GaussianPuff simulation over time. Each puff is represented as a circle centered at the puff @@ -252,6 +252,10 @@ def animate_puffs(puff, repeat=True): ------------------ puff: pandas DataFrame The puff DataFrame created by a GaussianPuff object + x_range: tuple (xmin, xmax) (optional) + The x-axis limits for the plot + y_range: tuple (ymin, ymax) (optional) + The y-axis limits for the plot repeat : bool, optional If True, the animation will repeat """ @@ -322,10 +326,14 @@ def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs): if plt is None: raise ImportError('matplotlib is required for graphics') - + buffer = puff['sigmaY'].max() + puff['sigmaY'].max()/5 - x_range = (puff['X'].min() - buffer, puff['X'].max() + buffer) - y_range = (puff['Y'].min() - buffer, puff['Y'].max() + buffer) + xmin = min([v for v in [puff['X'].min() - buffer, x_range[0]] if v is not None]) + xmax = max([v for v in [puff['X'].max() + buffer, x_range[1]] if v is not None]) + ymin = min([v for v in [puff['Y'].min() - buffer, y_range[0]] if v is not None]) + ymax = max([v for v in [puff['Y'].max() + buffer, y_range[1]] if v is not None]) + x_range = (xmin, xmax) + y_range = (ymin, ymax) fig, ax = plt.subplots() # ln, = plt.plot([],[],animated=True) diff --git a/chama/tests/test_graphics.py b/chama/tests/test_graphics.py index dd0acb0..9530a7e 100644 --- a/chama/tests/test_graphics.py +++ b/chama/tests/test_graphics.py @@ -68,7 +68,9 @@ def test_puff_animation(self): if isfile(filename): os.remove(filename) - anim = chama.graphics.animate_puffs(self.puff) + anim = chama.graphics.animate_puffs(self.puff, + x_range=(-60,None), + y_range=(None,60)) from matplotlib.animation import FuncAnimation, writers try: From bc2bbe6419ff615ceebe95a2f53e8d86424615d9 Mon Sep 17 00:00:00 2001 From: Katherine Klise Date: Mon, 20 Nov 2023 15:21:36 -0800 Subject: [PATCH 19/19] bump version number --- chama/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chama/__init__.py b/chama/__init__.py index eca15b2..baaf6fe 100644 --- a/chama/__init__.py +++ b/chama/__init__.py @@ -4,7 +4,7 @@ from chama import optimize from chama import graphics -__version__ = '0.2.0' +__version__ = '0.3.0' __copyright__ = """Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract