Repository: Breakthrough-Energy/PostREISE (language: python)

Issue:
Remove issue and pull request template so default takes effect
### Purpose
Remove issue and pull request template so the default from .github repo takes effect

### Time estimate
5min

ci: trigger stable image build
### Purpose
Automatically build and push the `postreise:stable` image when we release a new package to PyPI. 

### What the code is doing
Add the step to the workflow to trigger the docker build workflow in plug. 

### Testing
Tested the workflow in my test-ci repo. What I'm not totally sure of is if there is a delay, cache, etc somewhere that could cause the docker build to still pick up the old package. We'll see when we run this, and worst case will have to run the workflow again manually.

### Where to look
For reference, the workflow id comes from the api: https://api.github.com/repos/Breakthrough-Energy/plug/actions/workflows

### Time estimate
5 min

Update PowerSimData version
[Pull Request doc](https://breakthrough-energy.github.io/docs/user/git_guide.html#d-pull-request)

### Purpose
Update PowerSimData version and fix subsequent error raised

### What the code is doing
Propagate changes made  to check functions of PowerSimData following refactor to make them independent of grid models. Some warnings raised when running the tests were fixed.

### Testing
Existing unit tests

### Where to look
Several analysis and plot modules were affected.

### Usage Example/Visuals
N/A

### Time estimate
10min



Discussion / hints:

Fix patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 3e610fbd..00000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,47 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: Bug report
-labels: bug
-assignees: BainanXia, danielolsen, jon-hagg, rouille
-
----
-
-# :beetle:
-
-- [ ] I have checked that this issue has not already been reported.
-
-
-### Bug summary
-A short 1-2 sentences that succinctly describes the bug.
-
-### Code for reproduction
-A minimum code snippet required to reproduce the bug. Please make sure to minimize the
-number of dependencies required.
-```python
-# Paste your code here
-#
-#
-```
-
-### Actual outcome
-The output produced by the above code, which may be a screenshot, console output, etc.
-```shell
-# If applicable, paste the console output here
-#
-#
-```
-
-### Expected outcome
-A description of the expected outcome from the code snippet.
-
-### Environment
-Please specify your platform and versions of the relevant libraries you are using:
-* Operating system:
-* PostREISE revision (run `git rev-parse origin/HEAD`):
-* Python version:
-* Jupyter version (if applicable):
-* Other libraries:
-
-### Additional context
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/data-intake.md b/.github/ISSUE_TEMPLATE/data-intake.md
deleted file mode 100644
index 4b5b95bf..00000000
--- a/.github/ISSUE_TEMPLATE/data-intake.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-name: Data Intake
-about: Investigate the use of external data
-title: Data Intake
-labels: data intake
-assignees: danielolsen, rouille
-
----
-
-### Source
-* Name: ***e.g.*** Form EIA-923
-* Author: ***e.g.*** EIA
-* Description: ***e.g.*** Electric power data -- monthly and annually -- on electricity generation, fuel consumption, fossil fuel stocks, and receipts at the power plant and prime mover level for 2016
-* Source: ***e.g.*** https://www.eia.gov
-* Exact source location: ***e.g.*** https://www.eia.gov/electricity/data/eia923/
-* Terms (if specified): ***e.g.*** https://www.eia.gov/about/copyrights_reuse.php where it is written that we may use and/or distribute any of their data, files, databases, reports, graphs, charts, and other information products that are on their website
-
-### Destination
-* Modifications to source files(s): ***e.g.*** None
-* Location: postreise/...
-
-### General Purpose
-The data are used to ...
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 5f3ec88d..00000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: Feature request
-labels: feature request
-assignees: BainanXia, danielolsen, jon-hagg, rouille
-
----
-
- # :rocket:
-
-- [ ] Is your feature request essential for your project?
-
-
-### Describe the workflow you want to enable
-A clear and concise description of what can be enhanced, e.g., "I wish I could do [...]"
-
-### Describe your proposed implementation
-This should provide a description of the feature request, e.g.:
-* "The class `Foo` should have a new method `bar` that allows to [...]"
-* "Function `foo` needs a new arguments `bar` to set [...]"
-* "Create a new function `foo` to calculate [...]"
-
-If applicable, try to write a docstring for the desired feature. To illustrate, if you would like to add a new function in a module, provide:
-* the name of the function
-* a description of the task accomplished by the function
-* a list of the input and output parameters together with their types (e.g., `int`,
-  `str`, `pandas.DataFrame`, etc.) and a short description of its/their meaning
-
-### Describe alternatives you've considered, if relevant
-This should provide a description of any alternative solutions or features you've
-considered.
-
-### Additional context
-Add any other context or screenshots in this section, e.g., a plot from an article you
-believe would clearly communicate results.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
deleted file mode 100644
index 85a10562..00000000
--- a/.github/pull_request_template.md
+++ /dev/null
@@ -1,21 +0,0 @@
-[Pull Request doc](https://breakthrough-energy.github.io/docs/user/git_guide.html#d-pull-request)
-
-### Purpose
-What is the larger goal of this change?
-
-### What the code is doing
-How is the purpose executed?
-
-### Testing
-How did you test this change (unit/functional testing, manual testing, etc.)? 
-
-### Where to look
-* It's helpful to clarify where your new code lives if you moved files around or there could be confusion/
-
-* What files are most important?
-
-### Usage Example/Visuals
-How the code can be used and/or images of any graphs, tables or other visuals (not always applicable). 
-
-### Time estimate
-How long will it take for reviewers and observers to understand this code change?
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c07c370b..b5a58b19 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -26,3 +26,11 @@ jobs:
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
           password: ${{ secrets.PYPI_API_TOKEN }}
+
+      - name: Build and publish docker image
+        uses: Breakthrough-Energy/actions/workflow-trigger@main
+        with:
+          repo: plug
+          workflow_id: 12413223
+          token: ${{ secrets.CI_TOKEN_CLONE_REPO }}
+          inputs: '{"imageTags": "stable"}'
diff --git a/Pipfile b/Pipfile
index 7d4db49d..b7334455 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,11 +4,11 @@ url = "https://pypi.org/simple"
 verify_ssl = true
 
 [packages]
-bokeh = "==2.0.2"
+bokeh = "~=2.0"
 matplotlib = "~=3.3"
 numpy = "~=1.20"
 pandas = "~=1.4.0"
-powersimdata = "~=0.5.0"
+powersimdata = "~=0.5.4"
 pyproj = "~=3.0"
 
 [dev-packages]
diff --git a/Pipfile.lock b/Pipfile.lock
index 9624259f..55461e09 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "a11bea392c576fc98b6cb85e3a0b3ba83e784d99738ed3508c009ef8401f7cd5"
+            "sha256": "b0bfd58aa5bf13de4d64027c3136458e6ac537c1f365c8b4e94d17d532e1f1a2"
         },
         "pipfile-spec": 6,
         "requires": {},
@@ -23,137 +23,165 @@
         },
         "azure-core": {
             "hashes": [
-                "sha256:582699ad709f9b29870db41364bc3e46eac2a02368e336dc779b87772a6a227e",
-                "sha256:a342ebe9866e59a998e4098c65dd0b543cea06a9a5d4cc19c23a239c568bbb60"
+                "sha256:c26ad5f3612b8a2207cf2be0ef67e478a74acfa450b8d25d778c939921f650dc",
+                "sha256:c4a7d0d9e63a70dbde502b5d0cbe58b52244db4fbf247cca6768899e45fa3336"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==1.22.0"
+            "markers": "python_version >= '3.7'",
+            "version": "==1.25.0"
         },
         "azure-storage-blob": {
             "hashes": [
-                "sha256:e74c2c49fd04b80225f5b9734f1dbd417d89f280abfedccced3ac21509e1659d",
-                "sha256:eb37b50ddfb6e558b29f6c8c03b0666514e55d6170bf4624e7261a3af93c6401"
+                "sha256:726b86f733dc76218ce45b7a3254b61ba4f0cc3d68b7621be4985248c92ee483",
+                "sha256:899c4b8e2671812d2cf78f107556a27dbb128caaa2bb06094e72a3d5836740af"
+            ],
+            "markers": "python_version >= '3.6'",
+            "version": "==12.13.1"
+        },
+        "azure-storage-file-datalake": {
+            "hashes": [
+                "sha256:12e6306e5efb5ca28e0ccd9fa79a2c61acd589866d6109fe5601b18509da92f4",
+                "sha256:b6cf5733fe794bf3c866efbe3ce1941409e35b6b125028ac558b436bf90f2de7"
             ],
-            "version": "==12.8.1"
+            "markers": "python_version >= '3.6'",
+            "version": "==12.8.0"
         },
         "bcrypt": {
             "hashes": [
-                "sha256:56e5da069a76470679f312a7d3d23deb3ac4519991a0361abc11da837087b61d",
-                "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29",
-                "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7",
-                "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34",
-                "sha256:a0584a92329210fcd75eb8a3250c5a941633f8bfaf2a18f81009b097732839b7",
-                "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55",
-                "sha256:b589229207630484aefe5899122fb938a5b017b0f4349f769b8c13e78d99a8fd",
-                "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6",
-                "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1",
-                "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"
+                "sha256:2b02d6bfc6336d1094276f3f588aa1225a598e27f8e3388f4db9948cb707b521",
+                "sha256:433c410c2177057705da2a9f2cd01dd157493b2a7ac14c8593a16b3dab6b6bfb",
+                "sha256:4e029cef560967fb0cf4a802bcf4d562d3d6b4b1bf81de5ec1abbe0f1adb027e",
+                "sha256:61bae49580dce88095d669226d5076d0b9d927754cedbdf76c6c9f5099ad6f26",
+                "sha256:6d2cb9d969bfca5bc08e45864137276e4c3d3d7de2b162171def3d188bf9d34a",
+                "sha256:7180d98a96f00b1050e93f5b0f556e658605dd9f524d0b0e68ae7944673f525e",
+                "sha256:7d9ba2e41e330d2af4af6b1b6ec9e6128e91343d0b4afb9282e54e5508f31baa",
+                "sha256:7ff2069240c6bbe49109fe84ca80508773a904f5a8cb960e02a977f7f519b129",
+                "sha256:88273d806ab3a50d06bc6a2fc7c87d737dd669b76ad955f449c43095389bc8fb",
+                "sha256:a2c46100e315c3a5b90fdc53e429c006c5f962529bc27e1dfd656292c20ccc40",
+                "sha256:cd43303d6b8a165c29ec6756afd169faba9396a9472cdff753fe9f19b96ce2fa"
             ],
             "markers": "python_version >= '3.6'",
-            "version": "==3.2.0"
+            "version": "==3.2.2"
         },
         "bokeh": {
             "hashes": [
-                "sha256:d9248bdb0156797abf6d04b5eac581dcb121f5d1db7acbc13282b0609314893a"
+                "sha256:104d2f0a4ca7774ee4b11e545aa34ff76bf3e2ad6de0d33944361981b65da420",
+                "sha256:ef33801161af379665ab7a34684f2209861e3aefd5c803a21fbbb99d94874b03"
             ],
             "index": "pypi",
-            "version": "==2.0.2"
+            "version": "==2.4.3"
         },
         "certifi": {
             "hashes": [
-                "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
-                "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
+                "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d",
+                "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"
             ],
-            "version": "==2021.10.8"
+            "markers": "python_version >= '3.6'",
+            "version": "==2022.6.15"
         },
         "cffi": {
             "hashes": [
-                "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3",
-                "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2",
-                "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636",
-                "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20",
-                "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728",
-                "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27",
-                "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66",
-                "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443",
-                "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0",
-                "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7",
-                "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39",
-                "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605",
-                "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a",
-                "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37",
-                "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029",
-                "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139",
-                "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc",
-                "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df",
-                "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14",
-                "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880",
-                "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2",
-                "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a",
-                "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e",
-                "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474",
-                "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024",
-                "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8",
-                "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0",
-                "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e",
-                "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a",
-                "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e",
-                "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032",
-                "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6",
-                "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e",
-                "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b",
-                "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e",
-                "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954",
-                "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962",
-                "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c",
-                "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4",
-                "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55",
-                "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962",
-                "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023",
-                "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c",
-                "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6",
-                "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8",
-                "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382",
-                "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7",
-                "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc",
-                "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997",
-                "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"
-            ],
-            "version": "==1.15.0"
+                "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5",
+                "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef",
+                "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104",
+                "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426",
+                "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405",
+                "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375",
+                "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a",
+                "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e",
+                "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc",
+                "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf",
+                "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185",
+                "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497",
+                "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3",
+                "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35",
+                "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c",
+                "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83",
+                "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21",
+                "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca",
+                "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984",
+                "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac",
+                "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd",
+                "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee",
+                "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a",
+                "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2",
+                "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192",
+                "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7",
+                "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585",
+                "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f",
+                "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e",
+                "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27",
+                "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b",
+                "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e",
+                "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e",
+                "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d",
+                "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c",
+                "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415",
+                "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82",
+                "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02",
+                "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314",
+                "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325",
+                "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c",
+                "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3",
+                "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914",
+                "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045",
+                "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d",
+                "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9",
+                "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5",
+                "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2",
+                "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c",
+                "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3",
+                "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2",
+                "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8",
+                "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d",
+                "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d",
+                "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9",
+                "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162",
+                "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76",
+                "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4",
+                "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e",
+                "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9",
+                "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6",
+                "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b",
+                "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01",
+                "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"
+            ],
+            "version": "==1.15.1"
         },
         "charset-normalizer": {
             "hashes": [
-                "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45",
-                "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"
+                "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5",
+                "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"
             ],
-            "markers": "python_version >= '3'",
-            "version": "==2.0.11"
+            "markers": "python_version >= '3.6'",
+            "version": "==2.1.0"
         },
         "cryptography": {
             "hashes": [
-                "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3",
-                "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31",
-                "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac",
-                "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf",
-                "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316",
-                "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca",
-                "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638",
-                "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94",
-                "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12",
-                "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173",
-                "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b",
-                "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a",
-                "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f",
-                "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2",
-                "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9",
-                "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46",
-                "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903",
-                "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3",
-                "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1",
-                "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"
+                "sha256:190f82f3e87033821828f60787cfa42bff98404483577b591429ed99bed39d59",
+                "sha256:2be53f9f5505673eeda5f2736bea736c40f051a739bfae2f92d18aed1eb54596",
+                "sha256:30788e070800fec9bbcf9faa71ea6d8068f5136f60029759fd8c3efec3c9dcb3",
+                "sha256:3d41b965b3380f10e4611dbae366f6dc3cefc7c9ac4e8842a806b9672ae9add5",
+                "sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab",
+                "sha256:549153378611c0cca1042f20fd9c5030d37a72f634c9326e225c9f666d472884",
+                "sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82",
+                "sha256:6bc95ed67b6741b2607298f9ea4932ff157e570ef456ef7ff0ef4884a134cc4b",
+                "sha256:7099a8d55cd49b737ffc99c17de504f2257e3787e02abe6d1a6d136574873441",
+                "sha256:75976c217f10d48a8b5a8de3d70c454c249e4b91851f6838a4e48b8f41eb71aa",
+                "sha256:7bc997818309f56c0038a33b8da5c0bfbb3f1f067f315f9abd6fc07ad359398d",
+                "sha256:80f49023dd13ba35f7c34072fa17f604d2f19bf0989f292cedf7ab5770b87a0b",
+                "sha256:91ce48d35f4e3d3f1d83e29ef4a9267246e6a3be51864a5b7d2247d5086fa99a",
+                "sha256:a958c52505c8adf0d3822703078580d2c0456dd1d27fabfb6f76fe63d2971cd6",
+                "sha256:b62439d7cd1222f3da897e9a9fe53bbf5c104fff4d60893ad1355d4c14a24157",
+                "sha256:b7f8dd0d4c1f21759695c05a5ec8536c12f31611541f8904083f3dc582604280",
+                "sha256:d204833f3c8a33bbe11eda63a54b1aad7aa7456ed769a982f21ec599ba5fa282",
+                "sha256:e007f052ed10cc316df59bc90fbb7ff7950d7e2919c9757fd42a2b8ecf8a5f67",
+                "sha256:f2dcb0b3b63afb6df7fd94ec6fbddac81b5492513f7b0436210d390c14d46ee8",
+                "sha256:f721d1885ecae9078c3f6bbe8a88bc0786b6e749bf32ccec1ef2b18929a05046",
+                "sha256:f7a6de3e98771e183645181b3627e2563dcde3ce94a9e42a3f427d2255190327",
+                "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9"
             ],
             "markers": "python_version >= '3.6'",
-            "version": "==36.0.1"
+            "version": "==37.0.4"
         },
         "cycler": {
             "hashes": [
@@ -165,11 +193,11 @@
         },
         "fonttools": {
             "hashes": [
-                "sha256:1933415e0fbdf068815cb1baaa1f159e17830215f7e8624e5731122761627557",
-                "sha256:2b18a172120e32128a80efee04cff487d5d140fe7d817deb648b2eee023a40e4"
+                "sha256:cb91ef8d5a435d90aeb3ab814b2548c6b515df5bc13b4c5adaa23778f2f79823",
+                "sha256:e637d2fe06bddabbfc488e02ef32d04d561e3c71e9ba11abc7782ea753ceb218"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==4.29.1"
+            "version": "==4.36.0"
         },
         "fs": {
             "hashes": [
@@ -180,11 +208,11 @@
         },
         "fs-azureblob": {
             "hashes": [
-                "sha256:485f9669ac9a212a64391012c2f1689930f408f13e3d00a83a8c4fa8ce97b5c5",
-                "sha256:812049faff88d465130b6e51ea2cb0d4aa7fa5c4baa274447cdc0bf58a2c76bb"
+                "sha256:12536fc7ea5ac2a5b831d87b997475296e893006746ee2a653c56ee8ed22b0be",
+                "sha256:55245b1ff9b5fe448aec13dfa600552d5773f9a6504dcaba80d2618299659c1e"
             ],
             "markers": "python_version >= '3.8'",
-            "version": "==0.1.0"
+            "version": "==0.2.1"
         },
         "fs.sshfs": {
             "hashes": [
@@ -199,7 +227,7 @@
                 "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
                 "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
             ],
-            "markers": "python_version >= '3'",
+            "markers": "python_version >= '3.5'",
             "version": "==3.3"
         },
         "isodate": {
@@ -211,217 +239,222 @@
         },
         "jinja2": {
             "hashes": [
-                "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8",
-                "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"
+                "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
+                "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.0.3"
+            "markers": "python_version >= '3.7'",
+            "version": "==3.1.2"
         },
         "kiwisolver": {
             "hashes": [
-                "sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5",
-                "sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77",
-                "sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76",
-                "sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6",
-                "sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84",
-                "sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84",
-                "sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223",
-                "sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf",
-                "sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402",
-                "sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8",
-                "sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6",
-                "sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967",
-                "sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492",
-                "sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536",
-                "sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589",
-                "sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b",
-                "sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0",
-                "sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439",
-                "sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af",
-                "sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f",
-                "sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb",
-                "sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977",
-                "sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470",
-                "sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031",
-                "sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0",
-                "sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507",
-                "sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174",
-                "sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f",
-                "sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28",
-                "sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b",
-                "sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560",
-                "sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f",
-                "sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829",
-                "sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298",
-                "sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8",
-                "sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad",
-                "sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc",
-                "sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9",
-                "sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb",
-                "sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c",
-                "sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386",
-                "sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009",
-                "sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9",
-                "sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"
+                "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b",
+                "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166",
+                "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c",
+                "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c",
+                "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0",
+                "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4",
+                "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9",
+                "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286",
+                "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767",
+                "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c",
+                "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6",
+                "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b",
+                "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004",
+                "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf",
+                "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494",
+                "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac",
+                "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626",
+                "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766",
+                "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514",
+                "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6",
+                "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f",
+                "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d",
+                "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191",
+                "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d",
+                "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51",
+                "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f",
+                "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8",
+                "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454",
+                "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb",
+                "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da",
+                "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8",
+                "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de",
+                "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a",
+                "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9",
+                "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008",
+                "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3",
+                "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32",
+                "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938",
+                "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1",
+                "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9",
+                "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d",
+                "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824",
+                "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b",
+                "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd",
+                "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2",
+                "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5",
+                "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69",
+                "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3",
+                "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae",
+                "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597",
+                "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e",
+                "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955",
+                "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca",
+                "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a",
+                "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea",
+                "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede",
+                "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4",
+                "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6",
+                "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686",
+                "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408",
+                "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871",
+                "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29",
+                "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750",
+                "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897",
+                "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0",
+                "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2",
+                "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09",
+                "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==1.3.2"
+            "version": "==1.4.4"
         },
         "markupsafe": {
             "hashes": [
-                "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
-                "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
-                "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
-                "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194",
-                "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
-                "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
-                "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724",
-                "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
-                "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646",
-                "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
-                "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6",
-                "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a",
-                "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6",
-                "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad",
-                "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
-                "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38",
-                "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac",
-                "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
-                "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6",
-                "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047",
-                "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
-                "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
-                "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b",
-                "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
-                "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
-                "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a",
-                "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
-                "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1",
-                "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9",
-                "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864",
-                "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
-                "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee",
-                "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f",
-                "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
-                "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
-                "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
-                "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
-                "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b",
-                "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
-                "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86",
-                "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6",
-                "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
-                "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
-                "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
-                "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28",
-                "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e",
-                "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
-                "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
-                "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f",
-                "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d",
-                "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
-                "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
-                "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145",
-                "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
-                "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c",
-                "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1",
-                "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a",
-                "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207",
-                "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
-                "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53",
-                "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd",
-                "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134",
-                "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85",
-                "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9",
-                "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
-                "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
-                "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
-                "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
-                "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
+                "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
+                "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
+                "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
+                "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
+                "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
+                "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
+                "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
+                "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
+                "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
+                "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
+                "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
+                "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
+                "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
+                "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
+                "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
+                "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
+                "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
+                "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
+                "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
+                "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
+                "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
+                "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
+                "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
+                "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
+                "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
+                "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
+                "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
+                "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
+                "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
+                "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
+                "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
+                "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
+                "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
+                "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
+                "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
+                "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
+                "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
+                "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
+                "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
+                "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==2.0.1"
+            "markers": "python_version >= '3.7'",
+            "version": "==2.1.1"
         },
         "matplotlib": {
             "hashes": [
-                "sha256:14334b9902ec776461c4b8c6516e26b450f7ebe0b3ef8703bf5cdfbbaecf774a",
-                "sha256:2252bfac85cec7af4a67e494bfccf9080bcba8a0299701eab075f48847cca907",
-                "sha256:2e3484d8455af3fdb0424eae1789af61f6a79da0c80079125112fd5c1b604218",
-                "sha256:34a1fc29f8f96e78ec57a5eff5e8d8b53d3298c3be6df61e7aa9efba26929522",
-                "sha256:3e66497cd990b1a130e21919b004da2f1dc112132c01ac78011a90a0f9229778",
-                "sha256:40e0d7df05e8efe60397c69b467fc8f87a2affeb4d562fe92b72ff8937a2b511",
-                "sha256:456cc8334f6d1124e8ff856b42d2cc1c84335375a16448189999496549f7182b",
-                "sha256:506b210cc6e66a0d1c2bb765d055f4f6bc2745070fb1129203b67e85bbfa5c18",
-                "sha256:53273c5487d1c19c3bc03b9eb82adaf8456f243b97ed79d09dded747abaf1235",
-                "sha256:577ed20ec9a18d6bdedb4616f5e9e957b4c08563a9f985563a31fd5b10564d2a",
-                "sha256:6803299cbf4665eca14428d9e886de62e24f4223ac31ab9c5d6d5339a39782c7",
-                "sha256:68fa30cec89b6139dc559ed6ef226c53fd80396da1919a1b5ef672c911aaa767",
-                "sha256:6c094e4bfecd2fa7f9adffd03d8abceed7157c928c2976899de282f3600f0a3d",
-                "sha256:778d398c4866d8e36ee3bf833779c940b5f57192fa0a549b3ad67bc4c822771b",
-                "sha256:7a350ca685d9f594123f652ba796ee37219bf72c8e0fc4b471473d87121d6d34",
-                "sha256:87900c67c0f1728e6db17c6809ec05c025c6624dcf96a8020326ea15378fe8e7",
-                "sha256:8a77906dc2ef9b67407cec0bdbf08e3971141e535db888974a915be5e1e3efc6",
-                "sha256:8e70ae6475cfd0fad3816dcbf6cac536dc6f100f7474be58d59fa306e6e768a4",
-                "sha256:abf67e05a1b7f86583f6ebd01f69b693b9c535276f4e943292e444855870a1b8",
-                "sha256:b04fc29bcef04d4e2d626af28d9d892be6aba94856cb46ed52bcb219ceac8943",
-                "sha256:b19a761b948e939a9e20173aaae76070025f0024fc8f7ba08bef22a5c8573afc",
-                "sha256:b2e9810e09c3a47b73ce9cab5a72243a1258f61e7900969097a817232246ce1c",
-                "sha256:b71f3a7ca935fc759f2aed7cec06cfe10bc3100fadb5dbd9c435b04e557971e1",
-                "sha256:b8a4fb2a0c5afbe9604f8a91d7d0f27b1832c3e0b5e365f95a13015822b4cd65",
-                "sha256:bb1c613908f11bac270bc7494d68b1ef6e7c224b7a4204d5dacf3522a41e2bc3",
-                "sha256:d24e5bb8028541ce25e59390122f5e48c8506b7e35587e5135efcb6471b4ac6c",
-                "sha256:d70a32ee1f8b55eed3fd4e892f0286df8cccc7e0475c11d33b5d0a148f5c7599",
-                "sha256:e293b16cf303fe82995e41700d172a58a15efc5331125d08246b520843ef21ee",
-                "sha256:e2f28a07b4f82abb40267864ad7b3a4ed76f1b1663e81c7efc84a9b9248f672f",
-                "sha256:e3520a274a0e054e919f5b3279ee5dbccf5311833819ccf3399dab7c83e90a25",
-                "sha256:e3b6f3fd0d8ca37861c31e9a7cab71a0ef14c639b4c95654ea1dd153158bf0df",
-                "sha256:e486f60db0cd1c8d68464d9484fd2a94011c1ac8593d765d0211f9daba2bd535",
-                "sha256:e8c87cdaf06fd7b2477f68909838ff4176f105064a72ca9d24d3f2a29f73d393",
-                "sha256:edf5e4e1d5fb22c18820e8586fb867455de3b109c309cb4fce3aaed85d9468d1",
-                "sha256:fe8d40c434a8e2c68d64c6d6a04e77f21791a93ff6afe0dce169597c110d3079"
+                "sha256:0bcdfcb0f976e1bac6721d7d457c17be23cf7501f977b6a38f9d38a3762841f7",
+                "sha256:1e64ac9be9da6bfff0a732e62116484b93b02a0b4d4b19934fb4f8e7ad26ad6a",
+                "sha256:22227c976ad4dc8c5a5057540421f0d8708c6560744ad2ad638d48e2984e1dbc",
+                "sha256:2886cc009f40e2984c083687251821f305d811d38e3df8ded414265e4583f0c5",
+                "sha256:2e6d184ebe291b9e8f7e78bbab7987d269c38ea3e062eace1fe7d898042ef804",
+                "sha256:3211ba82b9f1518d346f6309df137b50c3dc4421b4ed4815d1d7eadc617f45a1",
+                "sha256:339cac48b80ddbc8bfd05daae0a3a73414651a8596904c2a881cfd1edb65f26c",
+                "sha256:35a8ad4dddebd51f94c5d24bec689ec0ec66173bf614374a1244c6241c1595e0",
+                "sha256:3b4fa56159dc3c7f9250df88f653f085068bcd32dcd38e479bba58909254af7f",
+                "sha256:43e9d3fa077bf0cc95ded13d331d2156f9973dce17c6f0c8b49ccd57af94dbd9",
+                "sha256:57f1b4e69f438a99bb64d7f2c340db1b096b41ebaa515cf61ea72624279220ce",
+                "sha256:5c096363b206a3caf43773abebdbb5a23ea13faef71d701b21a9c27fdcef72f4",
+                "sha256:6bb93a0492d68461bd458eba878f52fdc8ac7bdb6c4acdfe43dba684787838c2",
+                "sha256:6ea6aef5c4338e58d8d376068e28f80a24f54e69f09479d1c90b7172bad9f25b",
+                "sha256:6fe807e8a22620b4cd95cfbc795ba310dc80151d43b037257250faf0bfcd82bc",
+                "sha256:73dd93dc35c85dece610cca8358003bf0760d7986f70b223e2306b4ea6d1406b",
+                "sha256:839d47b8ead7ad9669aaacdbc03f29656dc21f0d41a6fea2d473d856c39c8b1c",
+                "sha256:874df7505ba820e0400e7091199decf3ff1fde0583652120c50cd60d5820ca9a",
+                "sha256:879c7e5fce4939c6aa04581dfe08d57eb6102a71f2e202e3314d5fbc072fd5a0",
+                "sha256:94ff86af56a3869a4ae26a9637a849effd7643858a1a04dd5ee50e9ab75069a7",
+                "sha256:99482b83ebf4eb6d5fc6813d7aacdefdd480f0d9c0b52dcf9f1cc3b2c4b3361a",
+                "sha256:9ab29589cef03bc88acfa3a1490359000c18186fc30374d8aa77d33cc4a51a4a",
+                "sha256:9befa5954cdbc085e37d974ff6053da269474177921dd61facdad8023c4aeb51",
+                "sha256:a206a1b762b39398efea838f528b3a6d60cdb26fe9d58b48265787e29cd1d693",
+                "sha256:ab8d26f07fe64f6f6736d635cce7bfd7f625320490ed5bfc347f2cdb4fae0e56",
+                "sha256:b28de401d928890187c589036857a270a032961411934bdac4cf12dde3d43094",
+                "sha256:b428076a55fb1c084c76cb93e68006f27d247169f056412607c5c88828d08f88",
+                "sha256:bf618a825deb6205f015df6dfe6167a5d9b351203b03fab82043ae1d30f16511",
+                "sha256:c995f7d9568f18b5db131ab124c64e51b6820a92d10246d4f2b3f3a66698a15b",
+                "sha256:cd45a6f3e93a780185f70f05cf2a383daed13c3489233faad83e81720f7ede24",
+                "sha256:d2484b350bf3d32cae43f85dcfc89b3ed7bd2bcd781ef351f93eb6fb2cc483f9",
+                "sha256:d62880e1f60e5a30a2a8484432bcb3a5056969dc97258d7326ad465feb7ae069",
+                "sha256:dacddf5bfcec60e3f26ec5c0ae3d0274853a258b6c3fc5ef2f06a8eb23e042be",
+                "sha256:f3840c280ebc87a48488a46f760ea1c0c0c83fcf7abbe2e6baf99d033fd35fd8",
+                "sha256:f814504e459c68118bf2246a530ed953ebd18213dc20e3da524174d84ed010b2"
             ],
             "index": "pypi",
-            "version": "==3.5.1"
+            "version": "==3.5.3"
         },
         "msrest": {
             "hashes": [
-                "sha256:72661bc7bedc2dc2040e8f170b6e9ef226ee6d3892e01affd4d26b06474d68d8",
-                "sha256:c840511c845330e96886011a236440fafc2c9aff7b2df9c0a92041ee2dee3782"
+                "sha256:21120a810e1233e5e6cc7fe40b474eeb4ec6f757a15d7cf86702c369f9567c32",
+                "sha256:6e7661f46f3afd88b75667b7187a92829924446c7ea1d169be8c4bb7eeb788b9"
             ],
-            "version": "==0.6.21"
+            "markers": "python_version >= '3.6'",
+            "version": "==0.7.1"
         },
         "networkx": {
             "hashes": [
-                "sha256:80b6b89c77d1dfb64a4c7854981b60aeea6360ac02c6d4e4913319e0a313abef",
-                "sha256:c0946ed31d71f1b732b5aaa6da5a0388a345019af232ce2f49c766e2d6795c51"
+                "sha256:15a7b81a360791c458c55a417418ea136c13378cfdc06a2dcdc12bd2f9cf09c1",
+                "sha256:a762f4b385692d9c3a6f2912d058d76d29a827deaedf9e63ed14d397b8030687"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.6.3"
+            "markers": "python_version >= '3.8'",
+            "version": "==2.8.5"
         },
         "numpy": {
             "hashes": [
-                "sha256:03ae5850619abb34a879d5f2d4bb4dcd025d6d8fb72f5e461dae84edccfe129f",
-                "sha256:076aee5a3763d41da6bef9565fdf3cb987606f567cd8b104aded2b38b7b47abf",
-                "sha256:0b536b6840e84c1c6a410f3a5aa727821e6108f3454d81a5cd5900999ef04f89",
-                "sha256:15efb7b93806d438e3bc590ca8ef2f953b0ce4f86f337ef4559d31ec6cf9d7dd",
-                "sha256:168259b1b184aa83a514f307352c25c56af111c269ffc109d9704e81f72e764b",
-                "sha256:2638389562bda1635b564490d76713695ff497242a83d9b684d27bb4a6cc9d7a",
-                "sha256:3556c5550de40027d3121ebbb170f61bbe19eb639c7ad0c7b482cd9b560cd23b",
-                "sha256:4a176959b6e7e00b5a0d6f549a479f869829bfd8150282c590deee6d099bbb6e",
-                "sha256:515a8b6edbb904594685da6e176ac9fbea8f73a5ebae947281de6613e27f1956",
-                "sha256:55535c7c2f61e2b2fc817c5cbe1af7cb907c7f011e46ae0a52caa4be1f19afe2",
-                "sha256:59153979d60f5bfe9e4c00e401e24dfe0469ef8da6d68247439d3278f30a180f",
-                "sha256:60cb8e5933193a3cc2912ee29ca331e9c15b2da034f76159b7abc520b3d1233a",
-                "sha256:6767ad399e9327bfdbaa40871be4254d1995f4a3ca3806127f10cec778bd9896",
-                "sha256:76a4f9bce0278becc2da7da3b8ef854bed41a991f4226911a24a9711baad672c",
-                "sha256:8cf33634b60c9cef346663a222d9841d3bbbc0a2f00221d6bcfd0d993d5543f6",
-                "sha256:94dd11d9f13ea1be17bac39c1942f527cbf7065f94953cf62dfe805653da2f8f",
-                "sha256:aafa46b5a39a27aca566198d3312fb3bde95ce9677085efd02c86f7ef6be4ec7",
-                "sha256:badca914580eb46385e7f7e4e426fea6de0a37b9e06bec252e481ae7ec287082",
-                "sha256:d76a26c5118c4d96e264acc9e3242d72e1a2b92e739807b3b69d8d47684b6677"
+                "sha256:17e5226674f6ea79e14e3b91bfbc153fdf3ac13f5cc54ee7bc8fdbe820a32da0",
+                "sha256:2bd879d3ca4b6f39b7770829f73278b7c5e248c91d538aab1e506c628353e47f",
+                "sha256:4f41f5bf20d9a521f8cab3a34557cd77b6f205ab2116651f12959714494268b0",
+                "sha256:5593f67e66dea4e237f5af998d31a43e447786b2154ba1ad833676c788f37cde",
+                "sha256:5e28cd64624dc2354a349152599e55308eb6ca95a13ce6a7d5679ebff2962913",
+                "sha256:633679a472934b1c20a12ed0c9a6c9eb167fbb4cb89031939bfd03dd9dbc62b8",
+                "sha256:806970e69106556d1dd200e26647e9bee5e2b3f1814f9da104a943e8d548ca38",
+                "sha256:806cc25d5c43e240db709875e947076b2826f47c2c340a5a2f36da5bb10c58d6",
+                "sha256:8247f01c4721479e482cc2f9f7d973f3f47810cbc8c65e38fd1bbd3141cc9842",
+                "sha256:8ebf7e194b89bc66b78475bd3624d92980fca4e5bb86dda08d677d786fefc414",
+                "sha256:8ecb818231afe5f0f568c81f12ce50f2b828ff2b27487520d85eb44c71313b9e",
+                "sha256:8f9d84a24889ebb4c641a9b99e54adb8cab50972f0166a3abc14c3b93163f074",
+                "sha256:909c56c4d4341ec8315291a105169d8aae732cfb4c250fbc375a1efb7a844f8f",
+                "sha256:9b83d48e464f393d46e8dd8171687394d39bc5abfe2978896b77dc2604e8635d",
+                "sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418",
+                "sha256:b78d00e48261fbbd04aa0d7427cf78d18401ee0abd89c7559bbf422e5b1c7d01",
+                "sha256:b8b97a8a87cadcd3f94659b4ef6ec056261fa1e1c3317f4193ac231d4df70215",
+                "sha256:bd5b7ccae24e3d8501ee5563e82febc1771e73bd268eef82a1e8d2b4d556ae66",
+                "sha256:bdc02c0235b261925102b1bd586579b7158e9d0d07ecb61148a1799214a4afd5",
+                "sha256:be6b350dfbc7f708d9d853663772a9310783ea58f6035eec649fb9c4371b5389",
+                "sha256:c403c81bb8ffb1c993d0165a11493fd4bf1353d258f6997b3ee288b0a48fce77",
+                "sha256:cf8c6aed12a935abf2e290860af8e77b26a042eb7f2582ff83dc7ed5f963340c",
+                "sha256:d98addfd3c8728ee8b2c49126f3c44c703e2b005d4a95998e2167af176a9e722",
+                "sha256:dc76bca1ca98f4b122114435f83f1fcf3c0fe48e4e6f660e07996abf2f53903c",
+                "sha256:dec198619b7dbd6db58603cd256e092bcadef22a796f778bf87f8592b468441d",
+                "sha256:df28dda02c9328e122661f399f7655cdcbcf22ea42daa3650a26bce08a187450",
+                "sha256:e603ca1fb47b913942f3e660a15e55a9ebca906857edfea476ae5f0fe9b457d5",
+                "sha256:ecfdd68d334a6b97472ed032b5b37a30d8217c097acfff15e8452c710e775524"
             ],
             "index": "pypi",
-            "version": "==1.22.2"
+            "version": "==1.23.2"
         },
         "oauthlib": {
             "hashes": [
@@ -441,86 +474,109 @@
         },
         "pandas": {
             "hashes": [
-                "sha256:0f19504f2783526fb5b4de675ea69d68974e21c1624f4b92295d057a31d5ec5f",
-                "sha256:156aac90dd7b303bf0b91bae96c0503212777f86c731e41929c571125d26c8e9",
-                "sha256:1d59c958d6b8f96fdf850c7821571782168d5acfe75ccf78cd8d1ac15fb921df",
-                "sha256:1f3b74335390dda49f5d5089fab71958812bf56f42aa27663ee4c16d19f4f1c5",
-                "sha256:23c04dab11f3c6359cfa7afa83d3d054a8f8c283d773451184d98119ef54da97",
-                "sha256:2dad075089e17a72391de33021ad93720aff258c3c4b68c78e1cafce7e447045",
-                "sha256:46a18572f3e1cb75db59d9461940e9ba7ee38967fa48dd58f4139197f6e32280",
-                "sha256:4a8d5a200f8685e7ea562b2f022c77ab7cb82c1ca5b240e6965faa6f84e5c1e9",
-                "sha256:51e5da3802aaee1aa4254108ffaf1129a15fb3810b7ce8da1ec217c655b418f5",
-                "sha256:5229c95db3a907451dacebc551492db6f7d01743e49bbc862f4a6010c227d187",
-                "sha256:5280d057ddae06fe4a3cd6aa79040b8c205cd6dd21743004cf8635f39ed01712",
-                "sha256:55ec0e192eefa26d823fc25a1f213d6c304a3592915f368e360652994cdb8d9a",
-                "sha256:73f7da2ccc38cc988b74e5400b430b7905db5f2c413ff215506bea034eaf832d",
-                "sha256:784cca3f69cfd7f6bd7c7fdb44f2bbab17e6de55725e9ff36d6f382510dfefb5",
-                "sha256:b5af258c7b090cca7b742cf2bd67ad1919aa9e4e681007366c9edad2d6a3d42b",
-                "sha256:cdd76254c7f0a1583bd4e4781fb450d0ebf392e10d3f12e92c95575942e37df5",
-                "sha256:de62cf699122dcef175988f0714678e59c453dc234c5b47b7136bfd7641e3c8c",
-                "sha256:de8f8999864399529e8514a2e6bfe00fd161f0a667903655552ed12e583ae3cb",
-                "sha256:f045bb5c6bfaba536089573bf97d6b8ccc7159d951fe63904c395a5e486fbe14",
-                "sha256:f103a5cdcd66cb18882ccdc18a130c31c3cfe3529732e7f10a8ab3559164819c",
-                "sha256:fe454180ad31bbbe1e5d111b44443258730467f035e26b4e354655ab59405871"
+                "sha256:07238a58d7cbc8a004855ade7b75bbd22c0db4b0ffccc721556bab8a095515f6",
+                "sha256:0daf876dba6c622154b2e6741f29e87161f844e64f84801554f879d27ba63c0d",
+                "sha256:16ad23db55efcc93fa878f7837267973b61ea85d244fc5ff0ccbcfa5638706c5",
+                "sha256:1d9382f72a4f0e93909feece6fef5500e838ce1c355a581b3d8f259839f2ea76",
+                "sha256:24ea75f47bbd5574675dae21d51779a4948715416413b30614c1e8b480909f81",
+                "sha256:2893e923472a5e090c2d5e8db83e8f907364ec048572084c7d10ef93546be6d1",
+                "sha256:2ff7788468e75917574f080cd4681b27e1a7bf36461fe968b49a87b5a54d007c",
+                "sha256:41fc406e374590a3d492325b889a2686b31e7a7780bec83db2512988550dadbf",
+                "sha256:48350592665ea3cbcd07efc8c12ff12d89be09cd47231c7925e3b8afada9d50d",
+                "sha256:605d572126eb4ab2eadf5c59d5d69f0608df2bf7bcad5c5880a47a20a0699e3e",
+                "sha256:6dfbf16b1ea4f4d0ee11084d9c026340514d1d30270eaa82a9f1297b6c8ecbf0",
+                "sha256:6f803320c9da732cc79210d7e8cc5c8019aad512589c910c66529eb1b1818230",
+                "sha256:721a3dd2f06ef942f83a819c0f3f6a648b2830b191a72bbe9451bcd49c3bd42e",
+                "sha256:755679c49460bd0d2f837ab99f0a26948e68fa0718b7e42afbabd074d945bf84",
+                "sha256:78b00429161ccb0da252229bcda8010b445c4bf924e721265bec5a6e96a92e92",
+                "sha256:958a0588149190c22cdebbc0797e01972950c927a11a900fe6c2296f207b1d6f",
+                "sha256:a3924692160e3d847e18702bb048dc38e0e13411d2b503fecb1adf0fcf950ba4",
+                "sha256:d51674ed8e2551ef7773820ef5dab9322be0828629f2cbf8d1fc31a0c4fed640",
+                "sha256:d5ebc990bd34f4ac3c73a2724c2dcc9ee7bf1ce6cf08e87bb25c6ad33507e318",
+                "sha256:d6c0106415ff1a10c326c49bc5dd9ea8b9897a6ca0c8688eb9c30ddec49535ef",
+                "sha256:e48fbb64165cda451c06a0f9e4c7a16b534fcabd32546d531b3c240ce2844112"
             ],
             "index": "pypi",
-            "version": "==1.4.0"
+            "version": "==1.4.3"
         },
         "paramiko": {
             "hashes": [
-                "sha256:04097dbd96871691cdb34c13db1883066b8a13a0df2afd4cb0a92221f51c2603",
-                "sha256:944a9e5dbdd413ab6c7951ea46b0ab40713235a9c4c5ca81cfe45c6f14fa677b"
+                "sha256:003e6bee7c034c21fbb051bf83dc0a9ee4106204dd3c53054c71452cc4ec3938",
+                "sha256:655f25dc8baf763277b933dfcea101d636581df8d6b9774d1fb653426b72c270"
             ],
-            "version": "==2.9.2"
+            "version": "==2.11.0"
         },
         "pillow": {
             "hashes": [
-                "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97",
-                "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049",
-                "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c",
-                "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae",
-                "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28",
-                "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030",
-                "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56",
-                "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976",
-                "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e",
-                "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e",
-                "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f",
-                "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b",
-                "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a",
-                "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e",
-                "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa",
-                "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7",
-                "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00",
-                "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838",
-                "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360",
-                "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b",
-                "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a",
-                "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd",
-                "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4",
-                "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70",
-                "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204",
-                "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc",
-                "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b",
-                "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669",
-                "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7",
-                "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e",
-                "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c",
-                "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092",
-                "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c",
-                "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5",
-                "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"
+                "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927",
+                "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14",
+                "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc",
+                "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58",
+                "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60",
+                "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76",
+                "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c",
+                "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac",
+                "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490",
+                "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1",
+                "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f",
+                "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d",
+                "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f",
+                "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069",
+                "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402",
+                "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885",
+                "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e",
+                "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be",
+                "sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8",
+                "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff",
+                "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da",
+                "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004",
+                "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f",
+                "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20",
+                "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d",
+                "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c",
+                "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544",
+                "sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9",
+                "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3",
+                "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04",
+                "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c",
+                "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5",
+                "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4",
+                "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb",
+                "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4",
+                "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c",
+                "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467",
+                "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e",
+                "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421",
+                "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b",
+                "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8",
+                "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb",
+                "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3",
+                "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf",
+                "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1",
+                "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a",
+                "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28",
+                "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0",
+                "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1",
+                "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8",
+                "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd",
+                "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4",
+                "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8",
+                "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f",
+                "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013",
+                "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59",
+                "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc",
+                "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==9.0.1"
+            "version": "==9.2.0"
         },
         "powersimdata": {
             "hashes": [
-                "sha256:151e08e39609edc8222e2bb948daafcde75268d29e1780ecc1269d53221a456e",
-                "sha256:f6052a06340448702d9fc8ca561f7e9885b5553d65208376ff9ae7de2bc418c8"
+                "sha256:1f8cbed22213f359941828ae2edb6a1bea7662916170700e3bf6a625afbf661f",
+                "sha256:a9135e60682d3481db454dd9b76d71611559aace1fd32817242ba9f3f79d9f15"
             ],
             "index": "pypi",
-            "version": "==0.5.0"
+            "version": "==0.5.4"
         },
         "property-cached": {
             "hashes": [
@@ -556,37 +612,42 @@
         },
         "pyparsing": {
             "hashes": [
-                "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
-                "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
+                "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
+                "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.0.7"
+            "markers": "python_full_version >= '3.6.8'",
+            "version": "==3.0.9"
         },
         "pyproj": {
             "hashes": [
-                "sha256:067a5c6099949edd66e9a10b139af4e2f65ebadb9f59583923a1d3feefac749a",
-                "sha256:0e1fd560b509b722db6566fa9685252f25640e93464d09e13d5190ed7ab491ba",
-                "sha256:235b52d8700ffb6be1f3638b1e25d83a9c13edcdb793236d8a98fd39227c5c27",
-                "sha256:277072176a17471c0b1d25d6cae75401d81e9b50ea625ba546f5b79acd757dfc",
-                "sha256:2c41c9b7b5e1a1b0acc2b7b2f5de65b226f7b96c870888e4f679ff96322b1ed0",
-                "sha256:3d28b84913cd849832a8f154c0e0c2ee4618057f7389ee68bfdb2145e7ed78cc",
-                "sha256:4125e6704751d0e82d8d912d9851da097e8d38599d4c45f9944faaeb21771938",
-                "sha256:44b5590c0b8dd002154916e170ef88f57abf91005b34bcb23faef97abb4d42c2",
-                "sha256:4d2fc49c73d9f34e932bf37926d56916ba1b6f2f693cd4d8cc1d0d9eacc0e537",
-                "sha256:5a105bfe37c78416d2641cd5d3368c99057d041f15f8d51ea3898953b21395c9",
-                "sha256:99f171da5f885efeec8d7fb2e2557175ffa8834eeb488842b1f52ac78a9a98e5",
-                "sha256:ab4baf781721640659db83a6b4da636fc403008f4978c668275754284c946778",
-                "sha256:b15e199c1da8fd132e11dfa68d8cf65d4812dedabc776b308df778ecd0d07658",
-                "sha256:b48dd9e5736957707fce1d9253fb0772bcf80480198c7790e21fed73fee61240",
-                "sha256:ce1adec823738e2d7c6af019fc38f58b4204bacfc782e4430373578c672f3833",
-                "sha256:ce8bfbc212729e9a643f5f5d77f7a93394e032eda1e2d8799ae902d08add747e",
-                "sha256:dbf479bd481774ad217e9db5674868eee8f01dfe3868f61753328895ae7da61a",
-                "sha256:e70a1ea6f198cace1a492397bdd0a46e640201120973293d6c48031e370d6a87",
-                "sha256:eca8ecf2b6b3225d93c723e6a2f51143d9195ac407f69e979363cdde344b93bb",
-                "sha256:fcceb6736085bf19291b707bc67c8cebe05330bd02268e9b8eba6d28a1905fce"
+                "sha256:07c9d8d7ec009bbac09e233cfc725601586fe06880e5538a3a44eaf560ba3a62",
+                "sha256:120d45ed73144c65e9677dc73ba8a531c495d179dd9f9f0471ac5acc02d7ac4b",
+                "sha256:140fa649fedd04f680a39f8ad339799a55cb1c49f6a84e1b32b97e49646647aa",
+                "sha256:1adc9ccd1bf04998493b6a2e87e60656c75ab790653b36cfe351e9ef214828ed",
+                "sha256:1ef1bfbe2dcc558c7a98e2f1836abdcd630390f3160724a6f4f5c818b2be0ad5",
+                "sha256:2fef9c1e339f25c57f6ae0558b5ab1bbdf7994529a30d8d7504fc6302ea51c03",
+                "sha256:3cc4771403db54494e1e55bca8e6d33cde322f8cf0ed39f1557ff109c66d2cd1",
+                "sha256:42eea10afc750fccd1c5c4ba56de29ab791ab4d83c1f7db72705566282ac5396",
+                "sha256:45487942c19c5a8b09c91964ea3201f4e094518e34743cae373889a36e3d9260",
+                "sha256:473961faef7a9fd723c5d432f65220ea6ab3854e606bf84b4d409a75a4261c78",
+                "sha256:52efb681647dfac185cc655a709bc0caaf910031a0390f816f5fc8ce150cbedc",
+                "sha256:531ea36519fa7b581466d4b6ab32f66ae4dadd9499d726352f71ee5e19c3d1c5",
+                "sha256:56b0f9ee2c5b2520b18db30a393a7b86130cf527ddbb8c96e7f3c837474a9d79",
+                "sha256:5ab0d6e38fda7c13726afacaf62e9f9dd858089d67910471758afd9cb24e0ecd",
+                "sha256:5ca5f32b56210429b367ca4f9a57ffe67975c487af82e179a24370879a3daf68",
+                "sha256:5dac03d4338a4c8bd0f69144c527474f517b4cbd7d2d8c532cd8937799723248",
+                "sha256:5f92d8f6514516124abb714dce912b20867831162cfff9fae2678ef07b6fcf0f",
+                "sha256:67025e37598a6bbed2c9c6c9e4c911f6dd39315d3e1148ead935a5c4d64309d5",
+                "sha256:797ad5655d484feac14b0fbb4a4efeaac0cf780a223046e2465494c767fd1c3b",
+                "sha256:aba199704c824fb84ab64927e7bc9ef71e603e483130ec0f7e09e97259b8f61f",
+                "sha256:aed1a3c0cd4182425f91b48d5db39f459bc2fe0d88017ead6425a1bc85faee33",
+                "sha256:b3d8e14d91cc95fb3dbc03a9d0588ac58326803eefa5bbb0978d109de3304fbe",
+                "sha256:b59c08aea13ee428cf8a919212d55c036cc94784805ed77c8f31a4d1f541058c",
+                "sha256:c99f7b5757a28040a2dd4a28c9805fdf13eef79a796f4a566ab5cb362d10630d",
+                "sha256:f1032e5dfb50eae06382bcc7b9011b994f7104d932fe91bd83a722275e30e8ce"
             ],
             "index": "pypi",
-            "version": "==3.3.0"
+            "version": "==3.3.1"
         },
         "python-dateutil": {
             "hashes": [
@@ -598,10 +659,10 @@
         },
         "pytz": {
             "hashes": [
-                "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c",
-                "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"
+                "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197",
+                "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"
             ],
-            "version": "==2021.3"
+            "version": "==2022.2.1"
         },
         "pyyaml": {
             "hashes": [
@@ -644,11 +705,11 @@
         },
         "requests": {
             "hashes": [
-                "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61",
-                "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"
+                "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983",
+                "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
-            "version": "==2.27.1"
+            "markers": "python_version >= '3.7' and python_version < '4'",
+            "version": "==2.28.1"
         },
         "requests-oauthlib": {
             "hashes": [
@@ -660,46 +721,40 @@
         },
         "scipy": {
             "hashes": [
-                "sha256:033ce76ed4e9f62923e1f8124f7e2b0800db533828c853b402c7eec6e9465d80",
-                "sha256:173308efba2270dcd61cd45a30dfded6ec0085b4b6eb33b5eb11ab443005e088",
-                "sha256:21b66200cf44b1c3e86495e3a436fc7a26608f92b8d43d344457c54f1c024cbc",
-                "sha256:2c56b820d304dffcadbbb6cbfbc2e2c79ee46ea291db17e288e73cd3c64fefa9",
-                "sha256:304dfaa7146cffdb75fbf6bb7c190fd7688795389ad060b970269c8576d038e9",
-                "sha256:3f78181a153fa21c018d346f595edd648344751d7f03ab94b398be2ad083ed3e",
-                "sha256:4d242d13206ca4302d83d8a6388c9dfce49fc48fdd3c20efad89ba12f785bf9e",
-                "sha256:5d1cc2c19afe3b5a546ede7e6a44ce1ff52e443d12b231823268019f608b9b12",
-                "sha256:5f2cfc359379c56b3a41b17ebd024109b2049f878badc1e454f31418c3a18436",
-                "sha256:65bd52bf55f9a1071398557394203d881384d27b9c2cad7df9a027170aeaef93",
-                "sha256:7edd9a311299a61e9919ea4192dd477395b50c014cdc1a1ac572d7c27e2207fa",
-                "sha256:8499d9dd1459dc0d0fe68db0832c3d5fc1361ae8e13d05e6849b358dc3f2c279",
-                "sha256:866ada14a95b083dd727a845a764cf95dd13ba3dc69a16b99038001b05439709",
-                "sha256:87069cf875f0262a6e3187ab0f419f5b4280d3dcf4811ef9613c605f6e4dca95",
-                "sha256:93378f3d14fff07572392ce6a6a2ceb3a1f237733bd6dcb9eb6a2b29b0d19085",
-                "sha256:95c2d250074cfa76715d58830579c64dff7354484b284c2b8b87e5a38321672c",
-                "sha256:ab5875facfdef77e0a47d5fd39ea178b58e60e454a4c85aa1e52fcb80db7babf",
-                "sha256:b0e0aeb061a1d7dcd2ed59ea57ee56c9b23dd60100825f98238c06ee5cc4467e",
-                "sha256:b78a35c5c74d336f42f44106174b9851c783184a85a3fe3e68857259b37b9ffb",
-                "sha256:c9e04d7e9b03a8a6ac2045f7c5ef741be86727d8f49c45db45f244bdd2bcff17",
-                "sha256:ca36e7d9430f7481fc7d11e015ae16fbd5575615a8e9060538104778be84addf",
-                "sha256:ceebc3c4f6a109777c0053dfa0282fddb8893eddfb0d598574acfb734a926168",
-                "sha256:e2c036492e673aad1b7b0d0ccdc0cb30a968353d2c4bf92ac8e73509e1bf212c",
-                "sha256:eb326658f9b73c07081300daba90a8746543b5ea177184daed26528273157294",
-                "sha256:eb7ae2c4dbdb3c9247e07acc532f91077ae6dbc40ad5bd5dca0bb5a176ee9bda",
-                "sha256:edad1cf5b2ce1912c4d8ddad20e11d333165552aba262c882e28c78bbc09dbf6",
-                "sha256:eef93a446114ac0193a7b714ce67659db80caf940f3232bad63f4c7a81bc18df",
-                "sha256:f7eaea089345a35130bc9a39b89ec1ff69c208efa97b3f8b25ea5d4c41d88094",
-                "sha256:f99d206db1f1ae735a8192ab93bd6028f3a42f6fa08467d37a14eb96c9dd34a3"
-            ],
-            "markers": "python_version < '3.11' and python_version >= '3.7'",
-            "version": "==1.7.3"
+                "sha256:01c2015e132774feefe059d5354055fec6b751d7a7d70ad2cf5ce314e7426e2a",
+                "sha256:0424d1bbbfa51d5ddaa16d067fd593863c9f2fb7c6840c32f8a08a8832f8e7a4",
+                "sha256:10417935486b320d98536d732a58362e3d37e84add98c251e070c59a6bfe0863",
+                "sha256:12005d30894e4fe7b247f7233ba0801a341f887b62e2eb99034dd6f2a8a33ad6",
+                "sha256:16207622570af10f9e6a2cdc7da7a9660678852477adbcd056b6d1057a036fef",
+                "sha256:45f0d6c0d6e55582d3b8f5c58ad4ca4259a02affb190f89f06c8cc02e21bba81",
+                "sha256:5d1b9cf3771fd921f7213b4b886ab2606010343bb36259b544a816044576d69e",
+                "sha256:693b3fe2e7736ce0dbc72b4d933798eb6ca8ce51b8b934e3f547cc06f48b2afb",
+                "sha256:73b704c5eea9be811919cae4caacf3180dd9212d9aed08477c1d2ba14900a9de",
+                "sha256:79dd7876614fc2869bf5d311ef33962d2066ea888bc66c80fd4fa80f8772e5a9",
+                "sha256:7bad16b91918bf3288089a78a4157e04892ea6475fb7a1d9bcdf32c30c8a3dba",
+                "sha256:8d541db2d441ef87afb60c4a2addb00c3af281633602a4967e733ef4b7050504",
+                "sha256:8f2232c9d9119ec356240255a715a289b3a33be828c3e4abac11fd052ce15b1e",
+                "sha256:97a1f1e51ea30782d7baa8d0c52f72c3f9f05cb609cf1b990664231c5102bccd",
+                "sha256:adb6c438c6ef550e2bb83968e772b9690cb421f2c6073f9c2cb6af15ee538bc9",
+                "sha256:bb687d245b6963673c639f318eea7e875d1ba147a67925586abed3d6f39bb7d8",
+                "sha256:bd490f77f35800d5620f4d9af669e372d9a88db1f76ef219e1609cc4ecdd1a24",
+                "sha256:c0dfd7d2429452e7e94904c6a3af63cbaa3cf51b348bd9d35b42db7e9ad42791",
+                "sha256:d3a326673ac5afa9ef5613a61626b9ec15c8f7222b4ecd1ce0fd8fcba7b83c59",
+                "sha256:e2004d2a3c397b26ca78e67c9d320153a1a9b71ae713ad33f4a3a3ab3d79cc65",
+                "sha256:e2ac088ea4aa61115b96b47f5f3d94b3fa29554340b6629cd2bfe6b0521ee33b",
+                "sha256:f7c3c578ff556333f3890c2df6c056955d53537bb176698359088108af73a58f",
+                "sha256:fc58c3fcb8a724b703ffbc126afdca5a8353d4d5945d5c92db85617e165299e7"
+            ],
+            "markers": "python_version < '3.12' and python_version >= '3.8'",
+            "version": "==1.9.0"
         },
         "setuptools": {
             "hashes": [
-                "sha256:a4dc3af29a67e7a45620aba43dde2c1af2dd6bc49726d78168f0cc6c4fb0c01b",
-                "sha256:c9097cbcdefe88a64da966a764f2d95feb1cfaff77cc304528a23cefe3359d9a"
+                "sha256:101bf15ca723beef42c8db91a761f3748d4d697e17fae904db60c0b619d8d094",
+                "sha256:39275e7aafa4a4f0f4308f2302c6ee384dcdacdbaacc1e30dcbb6fd824c625bb"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==60.7.1"
+            "version": "==65.0.2"
         },
         "six": {
             "hashes": [
@@ -711,168 +766,147 @@
         },
         "tornado": {
             "hashes": [
-                "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb",
-                "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c",
-                "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288",
-                "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95",
-                "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558",
-                "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe",
-                "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791",
-                "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d",
-                "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326",
-                "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b",
-                "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4",
-                "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c",
-                "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910",
-                "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5",
-                "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c",
-                "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0",
-                "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675",
-                "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd",
-                "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f",
-                "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c",
-                "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea",
-                "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6",
-                "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05",
-                "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd",
-                "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575",
-                "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a",
-                "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37",
-                "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795",
-                "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f",
-                "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32",
-                "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c",
-                "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01",
-                "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4",
-                "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2",
-                "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921",
-                "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085",
-                "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df",
-                "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102",
-                "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5",
-                "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68",
-                "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5"
+                "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca",
+                "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72",
+                "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23",
+                "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8",
+                "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b",
+                "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9",
+                "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13",
+                "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75",
+                "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac",
+                "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e",
+                "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"
             ],
-            "markers": "python_version >= '3.5'",
-            "version": "==6.1"
+            "markers": "python_version >= '3.7'",
+            "version": "==6.2"
         },
         "tqdm": {
             "hashes": [
-                "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c",
-                "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"
+                "sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d",
+                "sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"
             ],
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
-            "version": "==4.62.3"
+            "version": "==4.64.0"
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
-                "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
+                "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02",
+                "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==4.0.1"
+            "markers": "python_version >= '3.7'",
+            "version": "==4.3.0"
         },
         "urllib3": {
             "hashes": [
-                "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed",
-                "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"
+                "sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc",
+                "sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
-            "version": "==1.26.8"
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'",
+            "version": "==1.26.11"
         }
     },
     "develop": {
         "attrs": {
             "hashes": [
-                "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
-                "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
+                "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6",
+                "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"
             ],
-            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
-            "version": "==21.4.0"
+            "markers": "python_version >= '3.5'",
+            "version": "==22.1.0"
         },
         "black": {
             "hashes": [
-                "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2",
-                "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71",
-                "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6",
-                "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5",
-                "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912",
-                "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866",
-                "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d",
-                "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0",
-                "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321",
-                "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8",
-                "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd",
-                "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3",
-                "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba",
-                "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0",
-                "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5",
-                "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a",
-                "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28",
-                "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c",
-                "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1",
-                "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab",
-                "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f",
-                "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61",
-                "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"
+                "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90",
+                "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c",
+                "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78",
+                "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4",
+                "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee",
+                "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e",
+                "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e",
+                "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6",
+                "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9",
+                "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c",
+                "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256",
+                "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f",
+                "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2",
+                "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c",
+                "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b",
+                "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807",
+                "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf",
+                "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def",
+                "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad",
+                "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d",
+                "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849",
+                "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69",
+                "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"
             ],
             "index": "pypi",
-            "version": "==22.1.0"
+            "version": "==22.6.0"
         },
         "click": {
             "hashes": [
-                "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
-                "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
+                "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
+                "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==8.0.3"
+            "markers": "python_version >= '3.7'",
+            "version": "==8.1.3"
         },
         "coverage": {
             "hashes": [
-                "sha256:1245ab82e8554fa88c4b2ab1e098ae051faac5af829efdcf2ce6b34dccd5567c",
-                "sha256:1bc6d709939ff262fd1432f03f080c5042dc6508b6e0d3d20e61dd045456a1a0",
-                "sha256:25e73d4c81efa8ea3785274a2f7f3bfbbeccb6fcba2a0bdd3be9223371c37554",
-                "sha256:276b13cc085474e482566c477c25ed66a097b44c6e77132f3304ac0b039f83eb",
-                "sha256:2aed4761809640f02e44e16b8b32c1a5dee5e80ea30a0ff0912158bde9c501f2",
-                "sha256:2dd70a167843b4b4b2630c0c56f1b586fe965b4f8ac5da05b6690344fd065c6b",
-                "sha256:352c68e233409c31048a3725c446a9e48bbff36e39db92774d4f2380d630d8f8",
-                "sha256:3f2b05757c92ad96b33dbf8e8ec8d4ccb9af6ae3c9e9bd141c7cc44d20c6bcba",
-                "sha256:448d7bde7ceb6c69e08474c2ddbc5b4cd13c9e4aa4a717467f716b5fc938a734",
-                "sha256:463e52616ea687fd323888e86bf25e864a3cc6335a043fad6bbb037dbf49bbe2",
-                "sha256:482fb42eea6164894ff82abbcf33d526362de5d1a7ed25af7ecbdddd28fc124f",
-                "sha256:56c4a409381ddd7bbff134e9756077860d4e8a583d310a6f38a2315b9ce301d0",
-                "sha256:56d296cbc8254a7dffdd7bcc2eb70be5a233aae7c01856d2d936f5ac4e8ac1f1",
-                "sha256:5e15d424b8153756b7c903bde6d4610be0c3daca3986173c18dd5c1a1625e4cd",
-                "sha256:618eeba986cea7f621d8607ee378ecc8c2504b98b3fdc4952b30fe3578304687",
-                "sha256:61d47a897c1e91f33f177c21de897267b38fbb45f2cd8e22a710bcef1df09ac1",
-                "sha256:621f6ea7260ea2ffdaec64fe5cb521669984f567b66f62f81445221d4754df4c",
-                "sha256:6a5cdc3adb4f8bb8d8f5e64c2e9e282bc12980ef055ec6da59db562ee9bdfefa",
-                "sha256:6c3f6158b02ac403868eea390930ae64e9a9a2a5bbfafefbb920d29258d9f2f8",
-                "sha256:704f89b87c4f4737da2860695a18c852b78ec7279b24eedacab10b29067d3a38",
-                "sha256:72128176fea72012063200b7b395ed8a57849282b207321124d7ff14e26988e8",
-                "sha256:78fbb2be068a13a5d99dce9e1e7d168db880870f7bc73f876152130575bd6167",
-                "sha256:7bff3a98f63b47464480de1b5bdd80c8fade0ba2832c9381253c9b74c4153c27",
-                "sha256:84f2436d6742c01136dd940ee158bfc7cf5ced3da7e4c949662b8703b5cd8145",
-                "sha256:9976fb0a5709988778ac9bc44f3d50fccd989987876dfd7716dee28beed0a9fa",
-                "sha256:9ad0a117b8dc2061ce9461ea4c1b4799e55edceb236522c5b8f958ce9ed8fa9a",
-                "sha256:9e3dd806f34de38d4c01416344e98eab2437ac450b3ae39c62a0ede2f8b5e4ed",
-                "sha256:9eb494070aa060ceba6e4bbf44c1bc5fa97bfb883a0d9b0c9049415f9e944793",
-                "sha256:9fde6b90889522c220dd56a670102ceef24955d994ff7af2cb786b4ba8fe11e4",
-                "sha256:9fff3ff052922cb99f9e52f63f985d4f7a54f6b94287463bc66b7cdf3eb41217",
-                "sha256:a06c358f4aed05fa1099c39decc8022261bb07dfadc127c08cfbd1391b09689e",
-                "sha256:a4f923b9ab265136e57cc14794a15b9dcea07a9c578609cd5dbbfff28a0d15e6",
-                "sha256:c5b81fb37db76ebea79aa963b76d96ff854e7662921ce742293463635a87a78d",
-                "sha256:d5ed164af5c9078596cfc40b078c3b337911190d3faeac830c3f1274f26b8320",
-                "sha256:d651fde74a4d3122e5562705824507e2f5b2d3d57557f1916c4b27635f8fbe3f",
-                "sha256:de73fca6fb403dd72d4da517cfc49fcf791f74eee697d3219f6be29adf5af6ce",
-                "sha256:e647a0be741edbb529a72644e999acb09f2ad60465f80757da183528941ff975",
-                "sha256:e92c7a5f7d62edff50f60a045dc9542bf939758c95b2fcd686175dd10ce0ed10",
-                "sha256:eeffd96882d8c06d31b65dddcf51db7c612547babc1c4c5db6a011abe9798525",
-                "sha256:f5a4551dfd09c3bd12fca8144d47fe7745275adf3229b7223c2f9e29a975ebda",
-                "sha256:fac0bcc5b7e8169bffa87f0dcc24435446d329cbc2b5486d155c2e0f3b493ae1"
+                "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2",
+                "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820",
+                "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827",
+                "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3",
+                "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d",
+                "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145",
+                "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875",
+                "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2",
+                "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74",
+                "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f",
+                "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c",
+                "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973",
+                "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1",
+                "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782",
+                "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0",
+                "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760",
+                "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a",
+                "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3",
+                "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7",
+                "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a",
+                "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f",
+                "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e",
+                "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86",
+                "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa",
+                "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa",
+                "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796",
+                "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a",
+                "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928",
+                "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0",
+                "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac",
+                "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c",
+                "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685",
+                "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d",
+                "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e",
+                "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f",
+                "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558",
+                "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58",
+                "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781",
+                "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a",
+                "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa",
+                "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc",
+                "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892",
+                "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d",
+                "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817",
+                "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1",
+                "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c",
+                "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908",
+                "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19",
+                "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60",
+                "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"
             ],
             "index": "pypi",
-            "version": "==6.3.1"
+            "version": "==6.4.4"
         },
         "iniconfig": {
             "hashes": [
@@ -905,11 +939,11 @@
         },
         "platformdirs": {
             "hashes": [
-                "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca",
-                "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"
+                "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788",
+                "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"
             ],
             "markers": "python_version >= '3.7'",
-            "version": "==2.4.1"
+            "version": "==2.5.2"
         },
         "pluggy": {
             "hashes": [
@@ -929,19 +963,19 @@
         },
         "pyparsing": {
             "hashes": [
-                "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
-                "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
+                "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb",
+                "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"
             ],
-            "markers": "python_version >= '3.6'",
-            "version": "==3.0.7"
+            "markers": "python_full_version >= '3.6.8'",
+            "version": "==3.0.9"
         },
         "pytest": {
             "hashes": [
-                "sha256:42901e6bd4bd4a0e533358a86e848427a49005a3256f657c5c8f8dd35ef137a9",
-                "sha256:dad48ffda394e5ad9aa3b7d7ddf339ed502e5e365b1350e0af65f4a602344b11"
+                "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c",
+                "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"
             ],
             "index": "pypi",
-            "version": "==7.0.0"
+            "version": "==7.1.2"
         },
         "pytest-cov": {
             "hashes": [
@@ -953,19 +987,11 @@
         },
         "tomli": {
             "hashes": [
-                "sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224",
-                "sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1"
+                "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
+                "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
             ],
-            "markers": "python_version >= '3.7'",
-            "version": "==2.0.0"
-        },
-        "typing-extensions": {
-            "hashes": [
-                "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
-                "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
-            ],
-            "markers": "python_version >= '3.6'",
-            "version": "==4.0.1"
+            "markers": "python_full_version < '3.11.0a7'",
+            "version": "==2.0.1"
         }
     }
 }
diff --git a/docs/index.rst b/docs/index.rst
index 4fbead94..2b03aa15 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,7 +3,11 @@ PostREISE
 This tutorial focuses on the analysis and plotting of scenario output data. PostREISE
 is an open source package written in Python that is available on `GitHub <https://github.com/Breakthrough-Energy/PostREISE>`_.
 
-Note that analysis and plotting tools in this package rely extensively on our scenario framework presented in the :doc:`../powersimdata/index` tutorial.
+Note that analysis and plotting tools in this package rely extensively on our scenario
+framework presented in the :doc:`../powersimdata/index` tutorial.
+
+.. include::
+   scenario.rst
 
 .. include::
    analyze.rst
diff --git a/docs/scenario.rst b/docs/scenario.rst
new file mode 100644
index 00000000..917f2315
--- /dev/null
+++ b/docs/scenario.rst
@@ -0,0 +1,21 @@
+Scenario used
+-------------
+You will find below a short description of the scenarios that will be used across this
+tutorial:
+
+- Scenario 403 was designed to represent the Eastern interconnect in the year 2020.
+- Scenario 3287 was designed to represent the entire U.S. in the year 2030, where there
+  is a large increase in transmission capacity (but no increase across interconnection
+  seams) and carbon-free energy represents approximately 70% of total generation over
+  the course of the year.
+- Scenario 2497 was designed to represent the Western interconnect in the year 2030,
+  where 90% of the total energy could come from carbon-free sources, but the
+  transmission network has not been upgraded to accommodate these new clean generation
+  sources. Of this 90% potential, 10% could come from nuclear.
+- Scenario 1171 was designed to represent the Western interconnect in the year 2030,
+  with all states meeting their clean energy goals (with 'collaboration' via imports
+  and exports across state lines) and there are 4 GW of energy storage capacity.
+- Scenario 3101 was designed to represent the Western interconnect in the year 2030,
+  where 90% of the total energy does come from carbon-free sources, enabled by upgrades
+  in the transmission network to accommodate these new clean generation sources. Of
+  this 90% potential, 10% comes from nuclear.
diff --git a/postreise/analyze/demand.py b/postreise/analyze/demand.py
index 3613cf2d..5fecbe6b 100644
--- a/postreise/analyze/demand.py
+++ b/postreise/analyze/demand.py
@@ -16,13 +16,13 @@ def get_demand_time_series(scenario, area, area_type=None):
     :return: (*pandas.Series*) -- time series of total demand, index: time stamps,
         column: demand values
     """
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
     loadzone_set = area_to_loadzone(
         scenario.info["grid_model"], area, area_type=area_type
     )
     loadzone_id_set = {grid.zone2id[lz] for lz in loadzone_set if lz in grid.zone2id}
 
-    return scenario.state.get_demand()[loadzone_id_set].sum(axis=1)
+    return scenario.get_demand()[list(loadzone_id_set)].sum(axis=1)
 
 
 def get_net_demand_time_series(scenario, area, area_type=None):
diff --git a/postreise/analyze/generation/costs.py b/postreise/analyze/generation/costs.py
index 74b49088..ce176c74 100644
--- a/postreise/analyze/generation/costs.py
+++ b/postreise/analyze/generation/costs.py
@@ -29,8 +29,8 @@ def calculate_costs(
         raise ValueError("Either scenario XOR (pg AND gencost) must be specified")
     if scenario is not None:
         _check_scenario_is_in_analyze_state(scenario)
-        pg = scenario.state.get_pg()
-        gencost = scenario.state.get_grid().gencost["before"]
+        pg = scenario.get_pg()
+        gencost = scenario.get_grid().gencost["before"]
     else:
         _check_gencost(gencost)
         _check_time_series(pg, "PG")
diff --git a/postreise/analyze/generation/curtailment.py b/postreise/analyze/generation/curtailment.py
index 76eb86b9..46f11003 100644
--- a/postreise/analyze/generation/curtailment.py
+++ b/postreise/analyze/generation/curtailment.py
@@ -27,18 +27,18 @@ def calculate_curtailment_time_series(scenario):
     :return: (*pandas.DataFrame*) -- time series of curtailment.
     """
     _check_scenario_is_in_analyze_state(scenario)
-    grid = scenario.state.get_grid()
-    pg = scenario.state.get_pg()
-
-    plant_id = get_plant_id_for_resources(
-        grid.model_immutables.plants["renewable_resources"].intersection(
-            set(grid.plant.type)
-        ),
-        grid,
-    )
-    profiles = pd.concat(
-        [scenario.state.get_solar(), scenario.state.get_wind()], axis=1
+    grid = scenario.get_grid()
+    pg = scenario.get_pg()
+
+    plant_id = list(
+        get_plant_id_for_resources(
+            grid.model_immutables.plants["renewable_resources"].intersection(
+                set(grid.plant.type)
+            ),
+            grid,
+        )
     )
+    profiles = pd.concat([scenario.get_solar(), scenario.get_wind()], axis=1)
 
     curtailment = (profiles[plant_id] - pg[plant_id]).clip(lower=0).round(6)
     return curtailment
@@ -54,7 +54,7 @@ def calculate_curtailment_time_series_by_resources(scenario, resources=None):
         (datetime, plant id).
     """
     curtailment = calculate_curtailment_time_series(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     if resources is None:
         resources = grid.model_immutables.plants["renewable_resources"].intersection(
@@ -62,7 +62,7 @@ def calculate_curtailment_time_series_by_resources(scenario, resources=None):
         )
     else:
         resources = _check_resources_are_renewable_and_format(
-            resources, grid_model=scenario.info["grid_model"]
+            resources, mi=grid.model_immutables
         )
 
     curtailment_by_resources = decompose_plant_data_frame_into_resources(
@@ -83,7 +83,7 @@ def calculate_curtailment_time_series_by_areas(scenario, areas=None):
         (datetime, plant id).
     """
     curtailment = calculate_curtailment_time_series(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     areas = (
         _check_areas_are_in_grid_and_format(areas, grid)
@@ -109,18 +109,16 @@ def calculate_curtailment_percentage_by_resources(scenario, resources=None):
     """
     curtailment = calculate_curtailment_time_series_by_resources(scenario, resources)
     resources = set(curtailment.keys())
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     total_curtailment = {r: curtailment[r].sum().sum() for r in resources}
 
-    profiles = pd.concat(
-        [scenario.state.get_solar(), scenario.state.get_wind()], axis=1
-    )
+    profiles = pd.concat([scenario.get_solar(), scenario.get_wind()], axis=1)
     total_potential = profiles.groupby(grid.plant.type, axis=1).sum().sum()
 
     curtailment_percentage = (
         sum(v for v in total_curtailment.values())
-        / total_potential.loc[resources].sum()
+        / total_potential.loc[list(resources)].sum()
     )
 
     return curtailment_percentage
@@ -142,7 +140,7 @@ def calculate_curtailment_time_series_by_areas_and_resources(
         resources and values are data frames indexed by (datetime, plant id).
     """
     curtailment = calculate_curtailment_time_series(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     areas = (
         _check_areas_are_in_grid_and_format(areas, grid)
@@ -156,7 +154,7 @@ def calculate_curtailment_time_series_by_areas_and_resources(
         )
     else:
         resources = _check_resources_are_renewable_and_format(
-            resources, grid_model=scenario.info["grid_model"]
+            resources, mi=grid.model_immutables
         )
 
     curtailment_by_areas_and_resources = (
@@ -179,11 +177,11 @@ def calculate_curtailment_time_series_by_resources_and_areas(
     :param dict areas: keys are area types ('*loadzone*', '*state*' or
         '*interconnect*'), values are a list of areas. Default is the scenario
         interconnect(s).
-    :return: (*dict*) -- keys are areas, values are dictionaries whose keys are
-        resources and values are data frames indexed by (timestamp, plant id).
+    :return: (*dict*) -- keys are resources, values are dictionaries whose keys are
+        areas and values are data frames indexed by (timestamp, plant id).
     """
     curtailment = calculate_curtailment_time_series(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     areas = (
         _check_areas_are_in_grid_and_format(areas, grid)
@@ -197,7 +195,7 @@ def calculate_curtailment_time_series_by_resources_and_areas(
         )
     else:
         resources = _check_resources_are_renewable_and_format(
-            resources, grid_model=scenario.info["grid_model"]
+            resources, mi=grid.model_immutables
         )
 
     curtailment_by_resources_and_areas = (
@@ -216,7 +214,7 @@ def summarize_curtailment_by_bus(scenario):
         (bus: curtailment vector).
     """
     curtailment = calculate_curtailment_time_series_by_resources(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     bus_curtailment = {
         ren_type: summarize_plant_to_bus(curtailment_df, grid).sum().to_dict()
@@ -234,7 +232,7 @@ def summarize_curtailment_by_location(scenario):
         ((lat, lon): curtailment vector).
     """
     curtailment = calculate_curtailment_time_series_by_resources(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
 
     location_curtailment = {
         ren_type: summarize_plant_to_location(curtailment_df, grid).sum().to_dict()
@@ -259,9 +257,7 @@ def get_curtailment_time_series(scenario, area, area_type=None):
     curtailment = get_generation_time_series_by_resources(
         scenario, area, renewables, area_type=area_type
     )
-    renewable_profiles = pd.concat(
-        [scenario.state.get_wind(), scenario.state.get_solar()], axis=1
-    )
+    renewable_profiles = pd.concat([scenario.get_wind(), scenario.get_solar()], axis=1)
     for r in renewables:
         if r in curtailment.columns:
             plant_id = get_plant_id_for_resources_in_area(
diff --git a/postreise/analyze/generation/emissions.py b/postreise/analyze/generation/emissions.py
index 172d80d3..9c1acaf2 100644
--- a/postreise/analyze/generation/emissions.py
+++ b/postreise/analyze/generation/emissions.py
@@ -44,16 +44,16 @@ def generate_emissions_stats(scenario, pollutant="carbon", method="simple"):
         err_msg = f"method for {pollutant} must be one of: {allowed_methods[pollutant]}"
         raise ValueError(err_msg)
 
-    pg = scenario.state.get_pg()
-    grid = scenario.state.get_grid()
+    pg = scenario.get_pg()
+    grid = scenario.get_grid()
     emissions = pd.DataFrame(np.zeros_like(pg), index=pg.index, columns=pg.columns)
 
     if method == "simple":
         for fuel, val in emissions_per_mwh[pollutant].items():
             indices = (grid.plant["type"] == fuel).to_numpy()
             emissions.loc[:, indices] = pg.loc[:, indices] * val / 1000
-    elif method in ("decommit", "always-on"):
-        decommit = True if method == "decommit" else False
+    else:
+        decommit = method == "decommit"
 
         costs = calculate_costs(
             pg=pg, gencost=grid.gencost["before"], decommit=decommit
@@ -66,8 +66,6 @@ def generate_emissions_stats(scenario, pollutant="carbon", method="simple"):
                 costs.iloc[:, indices] / grid.plant["GenFuelCost"].values[indices]
             )
             emissions.loc[:, indices] = heat[:, indices] * val * 44 / 12 / 1000
-    else:
-        raise Exception("I should not be able to get here")
 
     return emissions
 
diff --git a/postreise/analyze/generation/summarize.py b/postreise/analyze/generation/summarize.py
index 29bcf9ca..ce2c1a7b 100644
--- a/postreise/analyze/generation/summarize.py
+++ b/postreise/analyze/generation/summarize.py
@@ -26,12 +26,12 @@ def sum_generation_by_type_zone(
     """
     _check_scenario_is_in_analyze_state(scenario)
 
-    pg = scenario.state.get_pg()
+    pg = scenario.get_pg().copy()
     if time_zone:
         pg = change_time_zone(pg, time_zone)
     if time_range:
         pg = slice_time_series(pg, time_range[0], time_range[1])
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
     plant = grid.plant
 
     summed_gen_series = pg.sum().groupby([plant.type, plant.zone_id]).sum()
@@ -49,7 +49,7 @@ def sum_generation_by_state(scenario: Scenario) -> pd.DataFrame:
     """
     # Start with energy by type & zone name
     energy_by_type_zoneid = sum_generation_by_type_zone(scenario)
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
     zoneid2zonename = grid.id2zone
     energy_by_type_zonename = energy_by_type_zoneid.rename(zoneid2zonename, axis=1)
     # Build lists to use for groupbys
@@ -92,11 +92,10 @@ def summarize_hist_gen(
     :return: (*pandas.DataFrame*) -- historical generation per resource.
     """
     _check_data_frame(hist_gen_raw, "PG")
-    filtered_colnames = _check_resources_and_format(
-        all_resources, grid_model=grid_model
-    )
+
     mi = ModelImmutables(grid_model)
 
+    filtered_colnames = _check_resources_and_format(all_resources, mi=mi)
     result = hist_gen_raw.copy()
 
     # Interconnection
@@ -139,7 +138,7 @@ def _groupby_state(index: str) -> str:
     result.loc["Texas interconnection"] = ercot
     result.loc["All"] = all
 
-    result = result.loc[:, filtered_colnames]
+    result = result.loc[:, list(filtered_colnames)]
     result.rename(columns=mi.plants["type2label"], inplace=True)
 
     return result
@@ -161,8 +160,8 @@ def get_generation_time_series_by_resources(scenario, area, resources, area_type
     plant_id = get_plant_id_for_resources_in_area(
         scenario, area, resources, area_type=area_type
     )
-    pg = scenario.state.get_pg()[plant_id]
-    grid = scenario.state.get_grid()
+    pg = scenario.get_pg()[plant_id]
+    grid = scenario.get_grid()
 
     return pg.groupby(grid.plant.loc[plant_id, "type"].values, axis=1).sum()
 
@@ -185,6 +184,6 @@ def get_storage_time_series(scenario, area, area_type=None, storage_e=False):
     storage_id = get_storage_id_in_area(scenario, area, area_type)
 
     if storage_e:
-        return scenario.state.get_storage_e()[storage_id].sum(axis=1)
+        return scenario.get_storage_e()[storage_id].sum(axis=1)
     else:
-        return scenario.state.get_storage_pg()[storage_id].sum(axis=1)
+        return scenario.get_storage_pg()[storage_id].sum(axis=1)
diff --git a/postreise/analyze/transmission/congestion.py b/postreise/analyze/transmission/congestion.py
index d168ce51..992508fc 100644
--- a/postreise/analyze/transmission/congestion.py
+++ b/postreise/analyze/transmission/congestion.py
@@ -1,8 +1,7 @@
 import numpy as np
 import pandas as pd
 from powersimdata.input.helpers import summarize_plant_to_bus
-from powersimdata.scenario.analyze import Analyze
-from powersimdata.scenario.scenario import Scenario
+from powersimdata.scenario.check import _check_scenario_is_in_analyze_state
 
 
 def calculate_congestion_surplus(scenario):
@@ -11,15 +10,11 @@ def calculate_congestion_surplus(scenario):
     :param powersimdata.scenario.scenario.Scenario scenario: scenario instance.
     :return: (*pandas.DataFrame*) -- congestion surplus.
     """
+    _check_scenario_is_in_analyze_state(scenario)
 
-    if not isinstance(scenario, Scenario):
-        raise TypeError("scenario must be a Scenario object")
-    if not isinstance(scenario.state, Analyze):
-        raise ValueError("scenario.state must be Analyze")
-
-    grid = scenario.state.get_grid()
-    lmp = scenario.state.get_lmp()
-    pg = scenario.state.get_pg()
+    grid = scenario.get_grid()
+    lmp = scenario.get_lmp()
+    pg = scenario.get_pg()
 
     bus_demand = scenario.get_bus_demand()
     bus_pg = summarize_plant_to_bus(pg, grid, all_buses=True)
diff --git a/postreise/analyze/transmission/upgrades.py b/postreise/analyze/transmission/upgrades.py
deleted file mode 100644
index 7b699794..00000000
--- a/postreise/analyze/transmission/upgrades.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# These imports are maintained only for backwards-compatibility purposes
-from powersimdata.design.compare.helpers import _reindex_as_necessary  # noqa: F401
-from powersimdata.design.compare.transmission import (  # noqa: F401
-    calculate_branch_difference,
-    calculate_dcline_difference,
-)
diff --git a/postreise/plot/plot_bar_generation_max_min_actual.py b/postreise/plot/plot_bar_generation_max_min_actual.py
index c9ad751d..957a9063 100644
--- a/postreise/plot/plot_bar_generation_max_min_actual.py
+++ b/postreise/plot/plot_bar_generation_max_min_actual.py
@@ -1,6 +1,6 @@
 import matplotlib.pyplot as plt
 import pandas as pd
-from powersimdata.network.model import ModelImmutables
+from powersimdata.input.check import _check_resources_are_in_grid_and_format
 
 from postreise.analyze.generation.summarize import (
     sum_generation_by_state,
@@ -32,10 +32,36 @@ def plot_bar_generation_max_min_actual(
     :param int/float fontsize: font size of the texts shown on the plot.
     :param plot_show: show the plot or not, defaults to True.
     :return: (*matplotlib.axes.Axes*) -- axes object of the plot.
+    :raises TypeError:
+        if ``interconnect`` and ``gen_type`` are not str
+        if ``fontsize`` is not an integer or a float and/or
+    :raises ValueError: if ``interconnect is not valid
     """
-    grid = scenario.state.get_grid()
+    if not isinstance(interconnect, str):
+        raise TypeError("interconnect must be a str")
+    if not isinstance(gen_type, str):
+        raise TypeError("gen_type must be a str")
+    if not isinstance(fontsize, (int, float)):
+        raise TypeError("fontsize must be either a int or a float")
+
+    grid = scenario.get_grid()
+    _check_resources_are_in_grid_and_format(gen_type, grid)
+
     plant = grid.plant[grid.plant.type == gen_type]
-    mi = ModelImmutables(scenario.info["grid_model"])
+    mi = grid.model_immutables
+    if interconnect not in mi.zones["interconnect"]:
+        raise ValueError(
+            f"interconnect must be one of {sorted(mi.zones['interconnect'])}"
+        )
+    if (
+        len(
+            mi.zones["interconnect2abv"][interconnect]
+            - mi.zones["interconnect2abv"][scenario.info["interconnect"]]
+        )
+        != 0
+    ):
+        raise ValueError("interconnect is incompatible with scenario's interconnect")
+
     hour_num = (
         pd.Timestamp(scenario.info["end_date"])
         - pd.Timestamp(scenario.info["start_date"])
@@ -53,7 +79,7 @@ def plot_bar_generation_max_min_actual(
         )
         all_actual_gen = sum_generation_by_state(scenario)[gen_type] * 1000
     else:
-        zone_list = mi.zones["interconnect2loadzone"][interconnect]
+        zone_list = list(mi.zones["interconnect2loadzone"][interconnect])
         all_max_min = plant.groupby("zone_name")[["Pmax", "Pmin"]].sum() * hour_num
         all_actual_gen = (
             sum_generation_by_type_zone(scenario)
diff --git a/postreise/plot/plot_bar_generation_stack.py b/postreise/plot/plot_bar_generation_stack.py
index ddb6435e..db2863f5 100644
--- a/postreise/plot/plot_bar_generation_stack.py
+++ b/postreise/plot/plot_bar_generation_stack.py
@@ -61,41 +61,37 @@ def plot_bar_generation_stack(
         directory if None.
     :return: (*list*) -- matplotlib.axes.Axes object of each plot in a list.
     :raises TypeError:
-        if resources is not a list/str and/or
-        if titles is provided but not in a dictionary format and/or
-        if filenames is provided but not in a dictionary format.
+        if ``resources`` is not a list or str.
+        if ``titles`` is not a dict.
+        if ``filenames`` is not a dict.
     :raises ValueError:
-        if length of area_types and areas is different and/or
-        if length of scenario_names and scenario_ids is different.
+        if length of ``area_types`` and ``areas`` is different.
+        if length of ``scenario_names`` and ``scenario_ids`` is different.
     """
     if isinstance(areas, str):
         areas = [areas]
     if isinstance(scenario_ids, (int, str)):
         scenario_ids = [scenario_ids]
     if not isinstance(scenario_ids, list):
-        raise TypeError("ERROR: scenario_ids should be a int/str/list")
+        raise TypeError("scenario_ids must be a int, str or list")
     if isinstance(resources, str):
         resources = [resources]
     if not isinstance(resources, list):
-        raise TypeError("ERROR: resources should be a list/str")
+        raise TypeError("resources must be a list or str")
     if isinstance(area_types, str):
         area_types = [area_types]
     if not area_types:
         area_types = [None] * len(areas)
     if len(areas) != len(area_types):
-        raise ValueError(
-            "ERROR: if area_types are provided, number of area_types must match number of areas"
-        )
+        raise ValueError("area_types must have same size as areas")
     if isinstance(scenario_names, str):
         scenario_names = [scenario_names]
     if scenario_names and len(scenario_names) != len(scenario_ids):
-        raise ValueError(
-            "ERROR: if scenario names are provided, number of scenario names must match number of scenario ids"
-        )
+        raise ValueError("scenario_names must have same size as scenario_ids")
     if titles is not None and not isinstance(titles, dict):
-        raise TypeError("ERROR: titles should be a dictionary if provided")
+        raise TypeError("titles must be a dictionary")
     if filenames is not None and not isinstance(filenames, dict):
-        raise TypeError("ERROR: filenames should be a dictionary if provided")
+        raise TypeError("filenames must be a dictionary")
     s_list = []
     for sid in scenario_ids:
         s_list.append(Scenario(sid))
@@ -112,7 +108,12 @@ def plot_bar_generation_stack(
     all_loadzone_data = dict()
     for sid, scenario in zip(scenario_ids, s_list):
         curtailment = calculate_curtailment_time_series_by_areas_and_resources(
-            scenario, areas={"loadzone": mi.zones["loadzone"]}
+            scenario,
+            areas={
+                "loadzone": mi.zones["interconnect2loadzone"][
+                    scenario.info["interconnect"]
+                ]
+            },
         )
         for area in curtailment:
             for r in curtailment[area]:
@@ -127,7 +128,7 @@ def plot_bar_generation_stack(
         all_loadzone_data[sid] = pd.concat(
             [
                 sum_generation_by_type_zone(scenario).T,
-                scenario.state.get_demand().sum().T.rename("load"),
+                scenario.get_demand().sum().T.rename("load"),
                 curtailment,
             ],
             axis=1,
@@ -142,10 +143,10 @@ def plot_bar_generation_stack(
             patches = []
             fuels = []
             bottom = 0
-            loadzone_set = area_to_loadzone(s.info["grid_model"], area, area_type)
+            zone_list = list(area_to_loadzone(s.info["grid_model"], area, area_type))
             data = (
                 all_loadzone_data[scenario_ids[ind]]
-                .loc[loadzone_set]
+                .loc[zone_list]
                 .sum()
                 .divide(1e6)
                 .astype("float")
@@ -196,7 +197,7 @@ def plot_bar_generation_stack(
         if scenario_names:
             labels = scenario_names
         else:
-            labels = [s.info["name'"] for s in s_list]
+            labels = [s.info["name"] for s in s_list]
         ax.set_xticks([i * x_scale for i in range(len(s_list))])
         ax.set_xticklabels(labels, fontsize=12)
         ax.set_ylabel("TWh", fontsize=12)
diff --git a/postreise/plot/plot_bar_generation_vs_capacity.py b/postreise/plot/plot_bar_generation_vs_capacity.py
index fb49f8c8..b8426946 100644
--- a/postreise/plot/plot_bar_generation_vs_capacity.py
+++ b/postreise/plot/plot_bar_generation_vs_capacity.py
@@ -18,6 +18,7 @@ def plot_bar_generation_vs_capacity(
     resource_types=None,
     resource_labels=None,
     horizontal=False,
+    plot_show=True,
 ):
     """Plot any number of scenarios as bar or horizontal bar charts with two columns per
     scenario - generation and capacity.
@@ -42,6 +43,13 @@ def plot_bar_generation_vs_capacity(
         being labels to show in the plots, defaults to None, which uses
         resource_types as labels.
     :param bool horizontal: display bars horizontally, default to False.
+    :return: (*matplotlib.axes.Axes*) -- axes object of the plot.
+    :raises TypeError:
+        if ``resource_labels`` is not a dict.
+    :raises ValueError:
+        if length of ``area_types`` and ``areas`` is different.
+        if length of ``scenario_names`` and ``scenario_ids`` is different.
+        if only one scenario is provided with no ``custom_data``.
     """
     if isinstance(areas, str):
         areas = [areas]
@@ -50,9 +58,7 @@ def plot_bar_generation_vs_capacity(
     if not area_types:
         area_types = [None] * len(areas)
     if len(areas) != len(area_types):
-        raise ValueError(
-            "ERROR: if area_types are provided, it should have the same number of entries with areas."
-        )
+        raise ValueError("area_types must have same size as areas")
 
     if not scenario_ids:
         scenario_ids = []
@@ -61,21 +67,17 @@ def plot_bar_generation_vs_capacity(
     if isinstance(scenario_names, str):
         scenario_names = [scenario_names]
     if scenario_names and len(scenario_names) != len(scenario_ids):
-        raise ValueError(
-            "ERROR: if scenario names are provided, number of scenario names must match number of scenario ids"
-        )
+        raise ValueError("scenario_names must have same size as scenario_ids")
     if not custom_data:
         custom_data = {}
     if len(scenario_ids) + len(custom_data) <= 1:
-        raise ValueError(
-            "ERROR: must include at least two scenario ids and/or custom data"
-        )
+        raise ValueError("two scenario and/or custom data must be provided")
     if isinstance(resource_types, str):
         resource_types = [resource_types]
     if not resource_labels:
         resource_labels = dict()
     if not isinstance(resource_labels, dict):
-        raise TypeError("ERROR: resource_labels should be a dictionary")
+        raise TypeError("resource_labels must be a dict")
 
     all_loadzone_data = {}
     scenario_data = {}
@@ -98,11 +100,11 @@ def plot_bar_generation_vs_capacity(
         }
     for area, area_type in zip(areas, area_types):
         for sid in scenario_ids:
-            loadzone_set = area_to_loadzone(
-                scenario_data[sid]["grid_model"], area, area_type
+            zone_list = list(
+                area_to_loadzone(scenario_data[sid]["grid_model"], area, area_type)
             )
             scenario_data[sid]["gen"]["data"][area] = (
-                all_loadzone_data[sid]["gen"][loadzone_set]
+                all_loadzone_data[sid]["gen"][zone_list]
                 .sum(axis=1)
                 .divide(1e6)
                 .astype("float")
@@ -110,7 +112,7 @@ def plot_bar_generation_vs_capacity(
                 .to_dict()
             )
             scenario_data[sid]["cap"]["data"][area] = (
-                all_loadzone_data[sid]["cap"][loadzone_set]
+                all_loadzone_data[sid]["cap"][zone_list]
                 .sum(axis=1)
                 .divide(1e3)
                 .astype("float")
@@ -152,9 +154,14 @@ def plot_bar_generation_vs_capacity(
             )
 
         if horizontal:
-            _construct_hbar_visuals(area, ax_data_list)
+            axes = _construct_hbar_visuals(area, ax_data_list)
+        else:
+            axes = _construct_bar_visuals(area, ax_data_list)
+
+        if plot_show:
+            plt.show()
         else:
-            _construct_bar_visuals(area, ax_data_list)
+            return axes
 
 
 def _construct_bar_visuals(zone, ax_data_list):
@@ -201,7 +208,7 @@ def _construct_bar_visuals(zone, ax_data_list):
             )
 
     axes[1].get_legend().remove()
-    plt.show()
+    return axes
 
 
 def _construct_hbar_visuals(zone, ax_data_list):
@@ -249,7 +256,7 @@ def _construct_hbar_visuals(zone, ax_data_list):
                 fontsize=14,
                 verticalalignment="top",
             )
-    plt.show()
+    return axes
 
 
 def _get_bar_display_val(val):
diff --git a/postreise/plot/plot_bar_renewable_max_profile_actual.py b/postreise/plot/plot_bar_renewable_max_profile_actual.py
index 0a526fa5..53af59a2 100644
--- a/postreise/plot/plot_bar_renewable_max_profile_actual.py
+++ b/postreise/plot/plot_bar_renewable_max_profile_actual.py
@@ -1,6 +1,10 @@
 import matplotlib.pyplot as plt
 import pandas as pd
-from powersimdata.network.model import ModelImmutables
+from powersimdata.input.check import (
+    _check_resources_are_in_grid_and_format,
+    _check_resources_are_renewable_and_format,
+)
+from powersimdata.scenario.check import _check_scenario_is_in_analyze_state
 
 from postreise.analyze.generation.summarize import (
     sum_generation_by_state,
@@ -31,17 +35,42 @@ def plot_bar_renewable_max_profile_actual(
     :param int/float fontsize: font size of the texts shown on the plot.
     :param plot_show: show the plot or not, defaults to True.
     :return: (*matplotlib.axes.Axes*) -- axes object of the plot.
-    :raises ValueError: if gen_type is not one of renewable resources.
+    :raises TypeError:
+        if ``interconnect`` and ``gen_type`` are not str
+        if ``fontsize`` is not a int or a float
+    :raises ValueError: if ``interconnect is not valid
     """
-    mi = ModelImmutables(scenario.info["grid_model"])
-    if gen_type not in mi.plants["renewable_resources"]:
-        raise ValueError("gen_type must be one of renewable resources")
-    grid = scenario.state.get_grid()
+    _check_scenario_is_in_analyze_state(scenario)
+    if not isinstance(interconnect, str):
+        raise TypeError("interconnect must be a str")
+    if not isinstance(gen_type, str):
+        raise TypeError("gen_type must be a str")
+    if not isinstance(fontsize, (int, float)):
+        raise TypeError("fontsize must be either a int or a float")
+
+    grid = scenario.get_grid()
+    mi = grid.model_immutables
+    _check_resources_are_in_grid_and_format(gen_type, grid)
+    _check_resources_are_renewable_and_format(gen_type, mi=mi)
+
     plant = grid.plant[grid.plant.type == gen_type]
+    if interconnect not in mi.zones["interconnect"]:
+        raise ValueError(
+            f"interconnect must be one of {sorted(mi.zones['interconnect'])}"
+        )
+    if (
+        len(
+            mi.zones["interconnect2abv"][interconnect]
+            - mi.zones["interconnect2abv"][scenario.info["interconnect"]]
+        )
+        != 0
+    ):
+        raise ValueError("interconnect is incompatible with scenario's interconnect")
+
     if "wind" in gen_type:
-        profile = scenario.state.get_wind().sum()
+        profile = scenario.get_wind().sum()
     else:
-        profile = scenario.state.get_solar().sum()
+        profile = scenario.get_solar().sum()
     hour_num = (
         pd.Timestamp(scenario.info["end_date"])
         - pd.Timestamp(scenario.info["start_date"])
@@ -56,7 +85,7 @@ def plot_bar_renewable_max_profile_actual(
         total_capacity = plant.groupby(group_criteria)["Pmax"].sum() * hour_num
         actual_gen = sum_generation_by_state(scenario)[gen_type] * 1000
     else:
-        zone_list = mi.zones["interconnect2loadzone"][interconnect]
+        zone_list = list(mi.zones["interconnect2loadzone"][interconnect])
         profile_gen = profile.groupby(plant.zone_name).sum().rename("profile")
         total_capacity = plant.groupby("zone_name")["Pmax"].sum() * hour_num
         actual_gen = (
diff --git a/postreise/plot/plot_bar_shortfall.py b/postreise/plot/plot_bar_shortfall.py
index 927fd779..e1c4b7dc 100644
--- a/postreise/plot/plot_bar_shortfall.py
+++ b/postreise/plot/plot_bar_shortfall.py
@@ -1,3 +1,4 @@
+import matplotlib.pyplot as plt
 import pandas as pd
 from powersimdata.design.generation.clean_capacity_scaling import (
     add_demand_to_targets,
@@ -16,6 +17,7 @@ def plot_bar_shortfall(
     scenario_names=None,
     baseline_scenario=None,
     baseline_scenario_name=None,
+    plot_show=True,
 ):
     """Plot a stacked bar chart of generation shortfall based on given targets for
         any number of scenarios.
@@ -36,6 +38,8 @@ def plot_bar_shortfall(
     :param str baseline_scenario_name: specify the label of the baseline scenario
         shown in the bar chart, default to None, in which case the name of the
         scenario will be used.
+    :param bool plot_show: display the generated figure or not, defaults to True.
+    :return: (*matplotlib.axes.Axes*) -- axes object of the plot.
     :raises ValueError:
         if length of scenario_names and scenario_ids is different.
     :raises TypeError:
@@ -49,23 +53,21 @@ def plot_bar_shortfall(
     if isinstance(scenario_ids, (int, str)):
         scenario_ids = [scenario_ids]
     if not isinstance(target_df, pd.DataFrame):
-        raise TypeError("ERROR: target_df must be a pandas.DataFrame")
+        raise TypeError("target_df must be a pandas.DataFrame")
     if strategy is None:
         strategy = dict()
     if not isinstance(strategy, dict):
-        raise TypeError("ERROR: strategy must be a dictionary")
+        raise TypeError("strategy must be a dict")
     if isinstance(scenario_names, str):
         scenario_names = [scenario_names]
     if scenario_names is not None and len(scenario_names) != len(scenario_ids):
-        raise ValueError(
-            "ERROR: if scenario names are provided, number of scenario names must match number of scenario ids"
-        )
+        raise ValueError("scenario_names must have same size as scenario_ids")
     if baseline_scenario is not None and not isinstance(baseline_scenario, (str, int)):
-        raise TypeError("ERROR: baseline_scenario must be a string or integer")
+        raise TypeError("baseline_scenario must be a str or int")
     if baseline_scenario_name is not None and not isinstance(
         baseline_scenario_name, str
     ):
-        raise TypeError("ERROR: baseline_scenario_name must be a string")
+        raise TypeError("baseline_scenario_name must be a str")
 
     scenarios = dict()
     targets = dict()
@@ -149,7 +151,7 @@ def plot_bar_shortfall(
             target_pct = round(100 * target_generation / target_demand, 2)
 
         if baseline_scenario:
-            _construct_shortfall_visuals(
+            axes = _construct_shortfall_visuals(
                 area,
                 ax_data,
                 target_pct,
@@ -157,11 +159,15 @@ def plot_bar_shortfall(
                 baseline_scenario_name=baseline_scenario_name,
             )
         else:
-            _construct_shortfall_visuals(
+            axes = _construct_shortfall_visuals(
                 area,
                 ax_data,
                 target_pct,
             )
+        if plot_show:
+            plt.show()
+        else:
+            return axes
 
 
 def _construct_shortfall_visuals(
diff --git a/postreise/plot/plot_carbon_bar.py b/postreise/plot/plot_carbon_bar.py
index 43ae6c8c..d5f62f5e 100644
--- a/postreise/plot/plot_carbon_bar.py
+++ b/postreise/plot/plot_carbon_bar.py
@@ -36,7 +36,7 @@ def plot_carbon_bar(*args, labels=None, labels_size=15, show_plot=True):
 
     carbon_val = {"coal": [], "ng": []}
     for i, s in enumerate(args):
-        grid = s.state.get_grid()
+        grid = s.get_grid()
         carbon_by_bus = summarize_emissions_by_bus(generate_emissions_stats(s), grid)
         carbon_val["coal"].append(sum(carbon_by_bus["coal"].values()))
         carbon_val["ng"].append(sum(carbon_by_bus["ng"].values()))
@@ -70,10 +70,10 @@ def carbon_diff(scenario_1, scenario_2):
     :return: (*float*) -- relative difference in emission in percent.
     """
     carbon_by_bus_1 = summarize_emissions_by_bus(
-        generate_emissions_stats(scenario_1), scenario_1.state.get_grid()
+        generate_emissions_stats(scenario_1), scenario_1.get_grid()
     )
     carbon_by_bus_2 = summarize_emissions_by_bus(
-        generate_emissions_stats(scenario_2), scenario_2.state.get_grid()
+        generate_emissions_stats(scenario_2), scenario_2.get_grid()
     )
 
     sum_1 = sum(carbon_by_bus_1["coal"].values()) + sum(carbon_by_bus_1["ng"].values())
diff --git a/postreise/plot/plot_carbon_map.py b/postreise/plot/plot_carbon_map.py
index 2399c348..75964e09 100644
--- a/postreise/plot/plot_carbon_map.py
+++ b/postreise/plot/plot_carbon_map.py
@@ -20,7 +20,7 @@ def combine_bus_info_and_emission(scenario):
     :param powersimdata.scenario.scenario.Scenario scenario: scenario instance.
     :return: (*pandas.DataFrame*) -- bus data frame with emission.
     """
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
     carbon_by_bus = summarize_emissions_by_bus(generate_emissions_stats(scenario), grid)
 
     selected = grid.bus.loc[pd.DataFrame.from_dict(carbon_by_bus).index]
diff --git a/postreise/plot/plot_curtailment_ts.py b/postreise/plot/plot_curtailment_ts.py
index 25e04b88..4019efc0 100644
--- a/postreise/plot/plot_curtailment_ts.py
+++ b/postreise/plot/plot_curtailment_ts.py
@@ -72,7 +72,7 @@ def plot_curtailment_time_series(
     """
     _check_scenario_is_in_analyze_state(scenario)
     resources = _check_resources_and_format(
-        resources, grid_model=scenario.info["grid_model"]
+        resources, mi=ModelImmutables(scenario.info["grid_model"])
     )
 
     mi = ModelImmutables(scenario.info["grid_model"])
diff --git a/postreise/plot/plot_energy_carbon_stack.py b/postreise/plot/plot_energy_carbon_stack.py
index 172c0e7a..43193838 100644
--- a/postreise/plot/plot_energy_carbon_stack.py
+++ b/postreise/plot/plot_energy_carbon_stack.py
@@ -27,14 +27,14 @@ def plot_n_scenarios(*args):
     scenario_numbers = [a.info["id"] for a in args]
     first_id = scenario_numbers[0]
     scenarios = {id: scen for (id, scen) in zip(scenario_numbers, args)}
-    grid = {id: scenario.state.get_grid() for id, scenario in scenarios.items()}
+    grid = {id: scenario.get_grid() for id, scenario in scenarios.items()}
     plant = {k: v.plant for k, v in grid.items()}
     # First scenario is chosen to set fuel colors
     type2color = ModelImmutables(args[0].info["grid_model"]).plants["type2color"]
     carbon_by_type, energy_by_type = {}, {}
     for id, scenario in scenarios.items():
         # Calculate raw numbers
-        annual_plant_energy = scenario.state.get_pg().sum()
+        annual_plant_energy = scenario.get_pg().sum()
         raw_energy_by_type = annual_plant_energy.groupby(plant[id].type).sum()
         annual_plant_carbon = generate_emissions_stats(scenario).sum()
         raw_carbon_by_type = annual_plant_carbon.groupby(plant[id].type).sum()
diff --git a/postreise/plot/plot_lmp_map.py b/postreise/plot/plot_lmp_map.py
index 5ece1c27..932c2adc 100644
--- a/postreise/plot/plot_lmp_map.py
+++ b/postreise/plot/plot_lmp_map.py
@@ -67,8 +67,8 @@ def map_lmp(
     if scale_factor < 0:
         raise ValueError("scale_factor must be positive")
 
-    grid = scenario.state.get_grid()
-    lmp = scenario.state.get_lmp()
+    grid = scenario.get_grid()
+    lmp = scenario.get_lmp()
     bus_with_lmp = grid.bus.copy()
     bus_with_lmp["lmp"] = lmp.mean()
 
diff --git a/postreise/plot/plot_powerflow_snapshot.py b/postreise/plot/plot_powerflow_snapshot.py
index c92737a1..d5a17a59 100644
--- a/postreise/plot/plot_powerflow_snapshot.py
+++ b/postreise/plot/plot_powerflow_snapshot.py
@@ -136,12 +136,12 @@ def plot_powerflow_snapshot(
     _check_scenario_is_in_analyze_state(scenario)
     _check_date_range_in_scenario(scenario, hour, hour)
     # Get scenario data
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
     bus = grid.bus
     plant = grid.plant
     # Augment the branch dataframe with extra info needed for plotting
     branch = grid.branch
-    branch["pf"] = scenario.state.get_pf().loc[hour]
+    branch["pf"] = scenario.get_pf().loc[hour]
     branch = branch.query("pf != 0").copy()
     branch["dist"] = branch.apply(
         lambda x: haversine((x.from_lat, x.from_lon), (x.to_lat, x.to_lon)), axis=1
@@ -150,7 +150,7 @@ def plot_powerflow_snapshot(
     branch = project_branch(branch)
     # Augment the dcline dataframe with extra info needed for plotting
     dcline = grid.dcline
-    dcline["pf"] = scenario.state.get_dcline_pf().loc[hour]
+    dcline["pf"] = scenario.get_dcline_pf().loc[hour]
     dcline["from_lat"] = dcline.apply(lambda x: bus.loc[x.from_bus_id, "lat"], axis=1)
     dcline["from_lon"] = dcline.apply(lambda x: bus.loc[x.from_bus_id, "lon"], axis=1)
     dcline["to_lat"] = dcline.apply(lambda x: bus.loc[x.to_bus_id, "lat"], axis=1)
@@ -162,7 +162,7 @@ def plot_powerflow_snapshot(
     dcline = project_branch(dcline)
     # Create a dataframe for demand plotting, if necessary
     if demand_centers is not None:
-        demand = scenario.state.get_demand()
+        demand = scenario.get_demand()
         demand_centers["demand"] = demand.loc[hour]
         demand_centers = project_bus(demand_centers)
 
@@ -281,7 +281,7 @@ def plot_powerflow_snapshot(
 
     # Aggregate solar and wind for plotting
     plant_with_pg = plant.copy()
-    plant_with_pg["pg"] = scenario.state.get_pg().loc[hour]
+    plant_with_pg["pg"] = scenario.get_pg().loc[hour]
     grouped_solar = aggregate_plant_generation(plant_with_pg.query("type == 'solar'"))
     grouped_wind = aggregate_plant_generation(plant_with_pg.query("type == 'wind'"))
     # Plot solar, wind
diff --git a/postreise/plot/plot_scatter_capacity_vs_capacity_factor.py b/postreise/plot/plot_scatter_capacity_vs_capacity_factor.py
index 3d971c7c..e3d5ea56 100644
--- a/postreise/plot/plot_scatter_capacity_vs_capacity_factor.py
+++ b/postreise/plot/plot_scatter_capacity_vs_capacity_factor.py
@@ -83,7 +83,7 @@ def plot_scatter_capacity_vs_capacity_factor(
     plant_id = get_plant_id_for_resources_in_area(
         scenario, area, resources, area_type=area_type
     )
-    plant_df = scenario.state.get_grid().plant.loc[plant_id]
+    plant_df = scenario.get_grid().plant.loc[plant_id]
     if total_cap == 0:
         data_avg = 0
     else:
diff --git a/postreise/plot/plot_scatter_capacity_vs_cost_curve_slope.py b/postreise/plot/plot_scatter_capacity_vs_cost_curve_slope.py
index 64d5376e..524d7ff2 100644
--- a/postreise/plot/plot_scatter_capacity_vs_cost_curve_slope.py
+++ b/postreise/plot/plot_scatter_capacity_vs_cost_curve_slope.py
@@ -44,7 +44,7 @@ def plot_scatter_capacity_vs_cost_curve_slope(
     plant_id = get_plant_id_for_resources_in_area(
         scenario, area, resources, area_type=area_type
     )
-    grid = scenario.state.get_grid()
+    grid = scenario.get_grid()
     plant_df = grid.plant.loc[plant_id]
     cost_df = grid.gencost["after"].loc[plant_id]
     slope = (cost_df["f2"] - cost_df["f1"]) / (cost_df["p2"] - cost_df["p1"])
diff --git a/postreise/plot/plot_scatter_capacity_vs_curtailment.py b/postreise/plot/plot_scatter_capacity_vs_curtailment.py
index ae3dc51f..23409220 100644
--- a/postreise/plot/plot_scatter_capacity_vs_curtailment.py
+++ b/postreise/plot/plot_scatter_capacity_vs_curtailment.py
@@ -2,6 +2,7 @@
 import pandas as pd
 from powersimdata.input.check import _check_resources_are_renewable_and_format
 from powersimdata.input.helpers import get_plant_id_for_resources_in_area
+from powersimdata.network.model import ModelImmutables
 
 from postreise.analyze.generation.capacity import get_capacity_by_resources
 from postreise.analyze.generation.curtailment import calculate_curtailment_time_series
@@ -64,7 +65,7 @@ def plot_scatter_capacity_vs_curtailment(
     if title is not None and not isinstance(title, str):
         raise TypeError("title should be a string")
     resources = _check_resources_are_renewable_and_format(
-        resources, grid_model=scenario.info["grid_model"]
+        resources, mi=ModelImmutables(scenario.info["grid_model"])
     )
     curtailment = calculate_curtailment_time_series(scenario)
     plant_list = get_plant_id_for_resources_in_area(
@@ -84,16 +85,14 @@ def plot_scatter_capacity_vs_curtailment(
         between_time=between_time,
         dayofweek=dayofweek,
     )
-    profiles = pd.concat(
-        [scenario.state.get_solar(), scenario.state.get_wind()], axis=1
-    )
+    profiles = pd.concat([scenario.get_solar(), scenario.get_wind()], axis=1)
     curtailment = curtailment.sum() / profiles[curtailment.columns].sum()
     if percentage:
         curtailment = (curtailment * 100).round(2)
     total_cap = get_capacity_by_resources(
         scenario, area, resources, area_type=area_type
     ).sum()
-    plant_df = scenario.state.get_grid().plant.loc[plant_list]
+    plant_df = scenario.get_grid().plant.loc[plant_list]
     if total_cap == 0:
         data_avg = 0
     else:
diff --git a/postreise/plot/plot_shadowprice_map.py b/postreise/plot/plot_shadowprice_map.py
index da2504a9..c647d29b 100644
--- a/postreise/plot/plot_shadowprice_map.py
+++ b/postreise/plot/plot_shadowprice_map.py
@@ -59,7 +59,7 @@ def _get_shadowprice_data(scenario_id):
     interconnect = s.info["interconnect"]
     interconnect = " ".join(interconnect.split("_"))
 
-    s_grid = s.state.get_grid()
+    s_grid = s.get_grid()
 
     # Get bus and add location data
     bus_map = project_bus(s_grid.bus)
@@ -68,15 +68,15 @@ def _get_shadowprice_data(scenario_id):
     branch_map = project_branch(s_grid.branch)
 
     # get congestion
-    congu = s.state.get_congu()
-    congl = s.state.get_congl()
+    congu = s.get_congu()
+    congl = s.get_congl()
     cong_abs = pd.DataFrame(
         np.maximum(congu.to_numpy(), congl.to_numpy()),
         columns=congu.columns,
         index=congu.index,
     )
 
-    return interconnect, bus_map, s.state.get_lmp(), branch_map, cong_abs
+    return interconnect, bus_map, s.get_lmp(), branch_map, cong_abs
 
 
 def _construct_bus_data(bus_map, lmp, user_set_split_points, datetime):
diff --git a/postreise/plot/plot_sim_vs_hist.py b/postreise/plot/plot_sim_vs_hist.py
index 0b4e9daf..5660d02d 100644
--- a/postreise/plot/plot_sim_vs_hist.py
+++ b/postreise/plot/plot_sim_vs_hist.py
@@ -1,7 +1,8 @@
-import warnings
-
 import matplotlib.pyplot as plt
 import numpy as np
+import pandas as pd
+
+from postreise.analyze.generation.summarize import sum_generation_by_state
 
 
 class PlotSettings:
@@ -10,41 +11,67 @@ class PlotSettings:
     size_inches = (20, 10)
 
 
-def plot_generation_sim_vs_hist(sim_gen, hist_gen, s_info, state, showmax=True):
-    """
-    Plot simulated vs historical generation of each resource in the scenario
+def plot_generation_sim_vs_hist(
+    scenario,
+    hist_gen,
+    state,
+    show_max=True,
+    plot_show=True,
+):
+    """Plot simulated vs historical generation of each resource in the scenario
     for the given state. Optionally include max generation.
 
-    :param pandas.DataFrame sim_gen: simulated generation dataframe
-    :param pandas.DataFrame hist_gen: historical generation dataframe
-    :param powersimdata.design.ScenarioInfo s_info: scenario info instance.
+    :param powersimdata.scenario.scenario.Scenario scenario: scenario instance.
+    :param pandas.DataFrame hist_gen: historical generation data frame. Columns are
+        resources and indices are state names.
     :param str state: the US state
-    :param bool showmax: determine whether to additionally plot max generation of each resource
+    :param bool show_max: determine whether to additionally plot max generation of each
+        resource.
+    :param plot_show: show the plot or not, defaults to True.
+    :return: (*matplotlib.axes.Axes*) -- axes object of the plot.
+    :raises TypeError:
+        if ``hist_gen`` is not a data frame.
+        if ``state`` is not a str.
+    :raises ValueError: if ``state`` is not in ``hist_gen`` or ``scenario``.
     """
-    labels = list(sim_gen.columns)
-    all_resources = s_info.get_available_resource("all")
+    if not isinstance(hist_gen, pd.DataFrame):
+        raise TypeError("hist_gen must be a pandas.DataFrame")
+    if not isinstance(state, str):
+        raise TypeError("state must be a str")
+
+    sim_gen = sum_generation_by_state(scenario)
+    if state not in sim_gen.index or state not in hist_gen.index:
+        raise ValueError("Invalid state")
+
+    all_resources = list(sim_gen.columns)
 
     sim = [int(round(sim_gen.loc[state, res])) for res in all_resources]
     hist = [int(round(hist_gen.loc[state, res])) for res in all_resources]
 
-    def calc_max(gen_type):
-        with warnings.catch_warnings():
-            warnings.simplefilter("ignore")
-            return int(
-                s_info.get_capacity(gen_type, state) * len(s_info.pg.index) / 1000
-            )
+    grid = scenario.get_grid()
+    pg = scenario.get_pg()
+
+    def calc_max(fuel):
+        loadzone = list(grid.model_immutables.area_to_loadzone(state, "state"))  # noqa
+        capacity = grid.plant.query("type == @fuel & zone_name == @loadzone")[
+            "Pmax"
+        ].sum()
+        if capacity == 0:
+            print(f"No {fuel} generator in {state}")
+
+        return int(capacity * pg.shape[0] / 1000)
 
     max_gen = []
-    if showmax:
+    if show_max:
         max_gen = [calc_max(res) for res in all_resources]
 
-    x = np.arange(len(labels))  # the label locations
+    x = np.arange(len(all_resources))  # the label locations
     width = PlotSettings.width
     fontsize = PlotSettings.fontsize
     size_inches_x, size_inches_y = PlotSettings.size_inches
 
     fig, ax = plt.subplots()
-    if showmax:
+    if show_max:
         rects1 = ax.bar(x - width, hist, width, label="Historical")
         rects2 = ax.bar(x, sim, width, label="Simulated")
         rects3 = ax.bar(x + width, max_gen, width, label="Max Generation")
@@ -56,7 +83,7 @@ def calc_max(gen_type):
     ax.set_ylabel("GWh", fontsize=fontsize)
     ax.set_title(state, fontsize=fontsize)
     ax.set_xticks(x)
-    ax.set_xticklabels(labels, fontsize=fontsize)
+    ax.set_xticklabels(all_resources, fontsize=fontsize)
     ax.legend(fontsize=fontsize)
 
     def autolabel(rects):
@@ -74,8 +101,10 @@ def autolabel(rects):
 
     autolabel(rects1)
     autolabel(rects2)
-    if showmax:
+    if show_max:
         autolabel(rects3)
     fig.tight_layout()
     fig.set_size_inches(size_inches_x, size_inches_y)
-    plt.show()
+    if plot_show:
+        plt.show()
+    return ax
diff --git a/postreise/plot/plot_tornado.py b/postreise/plot/plot_tornado.py
index 90eea8f4..9b77a853 100644
--- a/postreise/plot/plot_tornado.py
+++ b/postreise/plot/plot_tornado.py
@@ -3,8 +3,7 @@
 
 
 def plot_tornado(title, data, sorted=False):
-    """
-    Plots a tornado graph (horizontal bar with both positive and neg values)
+    """Plots a tornado graph (horizontal bar with both positive and neg values)
 
     :param str title: Title of the plot
     :param dict data: dictionary of data to be plotted
diff --git a/postreise/plot/plot_transmission_upgrades_map.py b/postreise/plot/plot_transmission_upgrades_map.py
index bb9ace00..1d9caadb 100644
--- a/postreise/plot/plot_transmission_upgrades_map.py
+++ b/postreise/plot/plot_transmission_upgrades_map.py
@@ -280,8 +280,8 @@ def map_transmission_upgrades(
         raise ValueError("Scenarios to compare must be same grid model & interconnect")
 
     # Pre-plot data processing
-    grid1 = scenario1.state.get_grid()
-    grid2 = scenario2.state.get_grid()
+    grid1 = scenario1.get_grid()
+    grid2 = scenario2.get_grid()
     branch_merge = calculate_branch_difference(grid1.branch, grid2.branch)
     dc_merge = calculate_dcline_difference(grid1, grid2)
 
diff --git a/postreise/plot/plot_utilization_map.py b/postreise/plot/plot_utilization_map.py
index b1a18d71..dc184b97 100644
--- a/postreise/plot/plot_utilization_map.py
+++ b/postreise/plot/plot_utilization_map.py
@@ -74,8 +74,8 @@ def map_risk_bind(
     # Check that we've appropriately specified:
     #    `scenario` XOR (`congestion_stats` AND `branch`)
     if scenario is not None:
-        branch = scenario.state.get_grid().branch
-        congestion_stats = generate_cong_stats(scenario.state.get_pf(), branch)
+        branch = scenario.get_grid().branch
+        congestion_stats = generate_cong_stats(scenario.get_pf(), branch)
     elif congestion_stats is not None and branch is not None:
         pass
     else:
@@ -207,8 +207,8 @@ def map_utilization(
     # Check that we've appropriately specified:
     #    `scenario` XOR (`utilization_df` AND `branch`)
     if scenario is not None:
-        branch = scenario.state.get_grid().branch
-        utilization_df = get_utilization(branch, scenario.state.get_pf(), median=True)
+        branch = scenario.get_grid().branch
+        utilization_df = get_utilization(branch, scenario.get_pf(), median=True)
     elif utilization_df is not None and branch is not None:
         pass
     else:
diff --git a/requirements.txt b/requirements.txt
index 406730f2..69f661a8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,8 @@
-bokeh==2.0.2
+bokeh~=2.0
 matplotlib~=3.3
 numpy~=1.19
 pandas~=1.4.0
-powersimdata~=0.5.0
+powersimdata~=0.5.4
 pyproj~=3.0
 black
 pytest
diff --git a/setup.cfg b/setup.cfg
index 9efa8223..0a8312e5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = postreise
-version = 0.5.1
+version = 0.5.2
 author = Breakthrough Energy
 author_email = sciences@breakthroughenergy.org
 description = Extract, analyze and plot data from scenario
@@ -22,7 +22,7 @@ zip_safe = False
 packages = find:
 python_requires = >=3.8
 install_requires =
-    powersimdata~=0.5.0
+    powersimdata~=0.5.4
     bokeh
     matplotlib
     pyproj
diff --git a/tox.ini b/tox.ini
index 2c8cd428..9fb5aae4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,9 +3,6 @@ envlist = pytest, format, flake8
 skipsdist = true
 
 [testenv]
-passenv =
-    CPPFLAGS
-    LDFLAGS
 deps =
     pytest: pipenv
     {format,checkformatting}: black


Test patch:
diff --git a/postreise/analyze/generation/tests/test_costs.py b/postreise/analyze/generation/tests/test_costs.py
index a4fcecf7..eeac73b7 100644
--- a/postreise/analyze/generation/tests/test_costs.py
+++ b/postreise/analyze/generation/tests/test_costs.py
@@ -76,5 +76,14 @@ def test_pass_just_gencost(mock_gencost):
 
 
 def test_pass_too_many_things(mock_gencost, mock_pg, mock_scenario):
-    with pytest.raises(ValueError):
+    with pytest.raises(ValueError) as excinfo:
         calculate_costs(gencost=mock_gencost, pg=mock_pg, scenario=mock_scenario)
+    assert "Either scenario XOR (pg AND gencost) must be specified" in str(
+        excinfo.value
+    )
+
+
+def test_negative_pg(mock_gencost, mock_pg):
+    with pytest.raises(ValueError) as excinfo:
+        calculate_costs(gencost=mock_gencost, pg=-1 * mock_pg.iloc[:, 2])
+    assert "PG must be non-negative" in str(excinfo.value)
diff --git a/postreise/analyze/generation/tests/test_curtailment.py b/postreise/analyze/generation/tests/test_curtailment.py
index 75e6c256..953e3adc 100644
--- a/postreise/analyze/generation/tests/test_curtailment.py
+++ b/postreise/analyze/generation/tests/test_curtailment.py
@@ -7,7 +7,10 @@
 
 from postreise.analyze.generation.curtailment import (
     calculate_curtailment_percentage_by_resources,
+    calculate_curtailment_time_series_by_areas,
+    calculate_curtailment_time_series_by_areas_and_resources,
     calculate_curtailment_time_series_by_resources,
+    calculate_curtailment_time_series_by_resources_and_areas,
     get_curtailment_time_series,
     summarize_curtailment_by_bus,
     summarize_curtailment_by_location,
@@ -233,3 +236,119 @@ def test_get_curtailment_time_series(self):
         ]
         for a, e in zip(arg, expected_return):
             check_dataframe_matches(get_curtailment_time_series(*a), e)
+
+
+class TestCalculateCurtailmentTimeSeriesGrouped(unittest.TestCase):
+    def test_curtailment_time_series_by_areas(self):
+        areas = {
+            "state": "Washington",
+            "loadzone": "Bay Area",
+        }
+        expected = {
+            "Washington": mock_curtailment_data[["A", "B"]],
+            "Bay Area": mock_curtailment_data[["C", "D"]],
+        }
+        curtailment = calculate_curtailment_time_series_by_areas(scenario, areas=areas)
+
+        self.assertIsInstance(curtailment, dict)
+        self.assertEqual(set(areas.values()), set(expected.keys()))
+        for key in curtailment.keys():
+            self.assertIsInstance(curtailment[key], pd.DataFrame)
+            assert_array_equal(set(curtailment[key]), set(expected[key]))
+
+    def test_curtailment_time_series_by_areas_and_resources(self):
+        areas = {
+            "state": "Washington",
+            "loadzone": "Bay Area",
+        }
+        expected = {
+            "Washington": {
+                "solar": mock_curtailment_data[["A", "B"]],
+                "wind": pd.DataFrame(index=mock_curtailment_data.index),
+                "wind_offshore": pd.DataFrame(index=mock_curtailment_data.index),
+            },
+            "Bay Area": {
+                "solar": pd.DataFrame(index=mock_curtailment_data.index),
+                "wind": mock_curtailment_data["C"].to_frame(),
+                "wind_offshore": mock_curtailment_data["D"].to_frame(),
+            },
+        }
+        curtailment = calculate_curtailment_time_series_by_areas_and_resources(
+            scenario, areas=areas
+        )
+
+        self.assertIsInstance(curtailment, dict)
+        self.assertEqual(set(areas.values()), set(expected.keys()))
+        for a in curtailment.keys():
+            self.assertIsInstance(curtailment[a], dict)
+            for r in curtailment[a]:
+                assert_array_equal(set(curtailment[a][r]), set(expected[a][r]))
+
+    def test_curtailment_time_series_by_areas_and_resource(self):
+        areas = {
+            "state": "Washington",
+            "loadzone": "Bay Area",
+        }
+        expected = {
+            "Washington": {
+                "solar": mock_curtailment_data[["A", "B"]],
+            },
+            "Bay Area": {
+                "solar": pd.DataFrame(index=mock_curtailment_data.index),
+            },
+        }
+        curtailment = calculate_curtailment_time_series_by_areas_and_resources(
+            scenario, areas=areas, resources=["solar"]
+        )
+
+        self.assertIsInstance(curtailment, dict)
+        self.assertEqual(set(areas.values()), set(expected.keys()))
+        for a in curtailment.keys():
+            self.assertIsInstance(curtailment[a], dict)
+            for r in curtailment[a]:
+                assert_array_equal(set(curtailment[a][r]), set(expected[a][r]))
+
+    def test_curtailment_time_series_by_resources_and_areas(self):
+        areas = {
+            "state": "Washington",
+            "loadzone": "Bay Area",
+        }
+        expected = {
+            "solar": {
+                "Washington": mock_curtailment_data[["A", "B"]],
+                "Bay Area": pd.DataFrame(index=mock_curtailment_data.index),
+            },
+            "wind": {
+                "Washington": pd.DataFrame(index=mock_curtailment_data.index),
+                "Bay Area": mock_curtailment_data["C"].to_frame(),
+            },
+            "wind_offshore": {
+                "Washington": pd.DataFrame(index=mock_curtailment_data.index),
+                "Bay Area": mock_curtailment_data["D"].to_frame(),
+            },
+        }
+
+        curtailment = calculate_curtailment_time_series_by_resources_and_areas(
+            scenario, areas=areas
+        )
+
+        self.assertIsInstance(curtailment, dict)
+        self.assertEqual({"solar", "wind", "wind_offshore"}, set(expected.keys()))
+        for a in curtailment.keys():
+            self.assertIsInstance(curtailment[a], dict)
+            for r in curtailment[a]:
+                assert_array_equal(set(curtailment[a][r]), set(expected[a][r]))
+
+    def test_curtailment_time_series_by_resource_and_area(self):
+        expected = {"wind": {"Bay Area": mock_curtailment_data["C"].to_frame()}}
+
+        curtailment = calculate_curtailment_time_series_by_resources_and_areas(
+            scenario, areas={"loadzone": "Bay Area"}, resources=["wind"]
+        )
+
+        self.assertIsInstance(curtailment, dict)
+        self.assertEqual({"wind"}, set(expected.keys()))
+        for a in curtailment.keys():
+            self.assertIsInstance(curtailment[a], dict)
+            for r in curtailment[a]:
+                assert_array_equal(set(curtailment[a][r]), set(expected[a][r]))
diff --git a/postreise/analyze/generation/tests/test_emissions.py b/postreise/analyze/generation/tests/test_emissions.py
index 3c904d65..f4ce8cc0 100644
--- a/postreise/analyze/generation/tests/test_emissions.py
+++ b/postreise/analyze/generation/tests/test_emissions.py
@@ -80,6 +80,23 @@ def _test_emissions_structure(emissions, mock_plant, pg):
     assert negative_emissions_count == 0, "No plant should emit negative emissions"
 
 
+class TestEmissionStatsArguments:
+    def test_pollutant_value(self, scenario):
+        with pytest.raises(ValueError) as excinfo:
+            generate_emissions_stats(scenario, pollutant="CO2")
+        assert "Unknown pollutant for generate_emissions_stats()" in str(excinfo.value)
+
+    def test_method_type(self, scenario):
+        with pytest.raises(TypeError) as excinfo:
+            generate_emissions_stats(scenario, method=1)
+        assert "method must be a str" in str(excinfo.value)
+
+    def test_method_value(self, scenario):
+        with pytest.raises(ValueError) as excinfo:
+            generate_emissions_stats(scenario, pollutant="nox", method="always-off")
+        assert "method for nox must be one of: {'simple'}" in str(excinfo.value)
+
+
 class TestCarbonCalculation:
     def test_carbon_calc_always_on(self, scenario, mock_plant):
 
@@ -177,6 +194,13 @@ def test_calculate_so2_disallowed_method(self, scenario):
 
 
 class TestEmissionsSummarization:
+    def test_emissions_is_non_negative(self, scenario):
+        carbon = generate_emissions_stats(scenario)
+        with pytest.raises(ValueError):
+            summarize_emissions_by_bus(
+                -1 * carbon, MockGrid(grid_attrs={"plant": mock_plant})
+            )
+
     def test_emissions_summarization(self, mock_pg, mock_plant):
         # setup
         pg = pd.DataFrame(mock_pg).iloc[:3, :]
diff --git a/postreise/analyze/generation/tests/test_summarize.py b/postreise/analyze/generation/tests/test_summarize.py
index c709c178..65b7a8b6 100644
--- a/postreise/analyze/generation/tests/test_summarize.py
+++ b/postreise/analyze/generation/tests/test_summarize.py
@@ -18,15 +18,15 @@
 # plant_id is the index
 mock_plant = {
     "plant_id": ["A", "B", "C", "D"],
-    "zone_id": [1, 1, 2, 2],
+    "zone_id": [201, 202, 203, 204],
     "type": ["solar", "wind", "hydro", "hydro"],
-    "zone_name": ["Washington", "Washington", "Oregon", "Oregon"],
+    "zone_name": ["Washington", "Oregon", "Northern California", "Bay Area"],
 }
 
 # bus_id is the index
 mock_bus = {
     "bus_id": [1, 2, 3, 4],
-    "zone_id": [201, 201, 202, 202],
+    "zone_id": [201, 202, 203, 204],
 }
 
 mock_storage = {
@@ -40,7 +40,8 @@
         "B": [1, 2, 4, 8],
         "C": [1, 1, 2, 3],
         "D": [1, 3, 5, 7],
-    }
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
 )
 
 mock_storage_pg = pd.DataFrame(
@@ -53,10 +54,10 @@
 
 grid_attrs = {"plant": mock_plant, "bus": mock_bus, "storage_gen": mock_storage}
 scenario = MockScenario(grid_attrs, pg=mock_pg, storage_pg=mock_storage_pg)
-scenario.state.grid.zone2id = {
-    "Washington": 201,
-    "Oregon": 202,
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
 }
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
 
 
 class TestSumGenerationByTypeZone(unittest.TestCase):
@@ -65,7 +66,13 @@ def setUp(self):
 
     def test_sum_generation(self):
         expected_return = pd.DataFrame(
-            {"type": ["hydro", "solar", "wind"], 1: [0, 10, 15], 2: [23, 0, 0]}
+            {
+                "type": ["hydro", "solar", "wind"],
+                201: [0, 10, 0],
+                202: [0, 0, 15],
+                203: [7, 0, 0],
+                204: [16, 0, 0],
+            }
         )
         expected_return.set_index("type", inplace=True)
         summed_generation = sum_generation_by_type_zone(self.scenario)
@@ -81,18 +88,64 @@ def test_with_scenario_not_analyze(self):
         with self.assertRaises(ValueError):
             sum_generation_by_type_zone(test_scenario)
 
+    def test_with_time_change(self):
+        summed_generation = sum_generation_by_type_zone(
+            self.scenario,
+            time_zone="ETC/GMT+6",
+        )
+        expected_return = pd.DataFrame(
+            {
+                "type": ["hydro", "solar", "wind"],
+                201: [0, 10, 0],
+                202: [0, 0, 15],
+                203: [7, 0, 0],
+                204: [16, 0, 0],
+            }
+        )
+        expected_return.set_index("type", inplace=True)
+        check_dataframe_matches(summed_generation, expected_return)
+
+    def test_with_time_slice(self):
+        summed_generation = sum_generation_by_type_zone(
+            self.scenario,
+            time_range=[pd.Timestamp(2016, 1, 1, 1), pd.Timestamp(2016, 1, 1, 2)],
+        )
+        expected_return = pd.DataFrame(
+            {
+                "type": ["hydro", "solar", "wind"],
+                201: [0, 5, 0],
+                202: [0, 0, 6],
+                203: [3, 0, 0],
+                204: [8, 0, 0],
+            }
+        )
+        expected_return.set_index("type", inplace=True)
+        check_dataframe_matches(summed_generation, expected_return)
+
+    def test_with_time_change_and_time_slice(self):
+        summed_generation = sum_generation_by_type_zone(
+            self.scenario,
+            time_zone="ETC/GMT+1",
+            time_range=[
+                pd.Timestamp("2016-01-01-00", tz="ETC/GMT+1"),
+                pd.Timestamp("2016-01-01-02", tz="ETC/GMT+1"),
+            ],
+        )
+        expected_return = pd.DataFrame(
+            {
+                "type": ["hydro", "solar", "wind"],
+                201: [0, 9, 0],
+                202: [0, 0, 14],
+                203: [6, 0, 0],
+                204: [15, 0, 0],
+            }
+        )
+        expected_return.set_index("type", inplace=True)
+        check_dataframe_matches(summed_generation, expected_return)
+
 
 @pytest.fixture
 def sim_gen_result():
-    scenario = MockScenario(grid_attrs, pg=mock_pg)
-    scenario.state.grid.interconnect = ["Western"]
-    scenario.state.grid.plant.zone_id = [201, 202, 203, 204]
-    scenario.state.grid.id2zone = {
-        201: "Washington",
-        202: "Oregon",
-        203: "Northern California",
-        204: "Bay Area",
-    }
     return sum_generation_by_state(scenario)
 
 
@@ -149,17 +202,17 @@ def test_summarize_hist_gen_shape(hist_gen_raw):
 
 
 def test_get_generation_time_series_by_resources():
-    arg = [(scenario, "Washington", "wind"), (scenario, "Oregon", "hydro")]
+    arg = [(scenario, "Washington", "solar"), (scenario, "Oregon", "wind")]
     expected = [
-        pd.DataFrame({"wind": mock_pg["B"]}),
-        pd.DataFrame({"hydro": mock_pg[["C", "D"]].sum(axis=1)}),
+        pd.DataFrame({"solar": mock_pg["A"]}),
+        pd.DataFrame({"wind": mock_pg[["B"]].sum(axis=1)}),
     ]
     for a, e in zip(arg, expected):
         check_dataframe_matches(get_generation_time_series_by_resources(*a), e)
 
 
 def test_get_storage_time_series():
-    arg = [(scenario, "Oregon"), (scenario, "all")]
-    expected = [mock_storage_pg[2], mock_storage_pg.sum(axis=1)]
+    arg = [(scenario, "Washington"), (scenario, "all")]
+    expected = [mock_storage_pg[0], mock_storage_pg.sum(axis=1)]
     for a, e in zip(arg, expected):
         assert_array_almost_equal(get_storage_time_series(*a), e)
diff --git a/postreise/analyze/transmission/tests/test_utilization.py b/postreise/analyze/transmission/tests/test_utilization.py
new file mode 100644
index 00000000..e817e7fa
--- /dev/null
+++ b/postreise/analyze/transmission/tests/test_utilization.py
@@ -0,0 +1,81 @@
+import pandas as pd
+from pandas.testing import assert_frame_equal
+from powersimdata.input.tests.test_helpers import check_dataframe_matches
+from powersimdata.tests.mock_grid import MockGrid
+
+from postreise.analyze.transmission.utilization import (
+    _count_hours_gt_threshold,
+    generate_cong_stats,
+    get_utilization,
+)
+
+mock_branch = {
+    "branch_id": [101, 102],
+    "branch_device_type": ["Line"] * 2,
+    "rateA": [20, 10],
+    "from_lat": [47, 47],
+    "from_lon": [122, 122],
+    "to_lat": [47.12, 46.33],
+    "to_lon": [122.23, 121.11],
+}
+
+mock_grid = MockGrid(grid_attrs={"branch": mock_branch})
+
+mock_pf = pd.DataFrame(
+    {
+        101: [12, -8, -18, 2],
+        102: [1, 8, 9, 6],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+
+def test_get_utilization():
+    expected = pd.DataFrame(
+        {101: [0.6, 0.4, 0.9, 0.1], 102: [0.1, 0.8, 0.9, 0.6]}, index=mock_pf.index
+    )
+    check_dataframe_matches(expected, get_utilization(mock_grid.branch, mock_pf))
+
+
+def test_get_utilization_median():
+    expected = pd.DataFrame({101: [0.5], 102: [0.7]})
+    check_dataframe_matches(
+        expected,
+        get_utilization(mock_grid.branch, mock_pf, median=True),
+    )
+
+
+def test_count_hours_gt_threshold():
+    threshold = 0.25
+    expected = pd.Series(data=[3, 3], index=[101, 102])
+
+    utilization = get_utilization(mock_grid.branch, mock_pf)
+    assert _count_hours_gt_threshold(utilization, threshold).equals(expected)
+
+
+def test_generate_cong_stats():
+    util = [0.5, 0.75, 0.85]
+    threshold = [0.5, 0.25, 0.05]
+    n = len(mock_pf)
+
+    expected = pd.DataFrame(
+        {
+            "capacity": [20.0, 10.0],
+            "branch_device_type": ["Line"] * 2,
+            "per_util1": [2 / n, 3 / n],
+            "per_util2": [1 / n, 2 / n],
+            "per_util3": [1 / n, 1 / n],
+            "bind": [0, 0],
+            "risk": [-18.0, 17.0],
+            "uflag1": [1, 1],
+            "uflag2": [1, 1],
+            "uflag3": [1, 1],
+            "sumflag": [3, 3],
+        },
+        index=[101, 102],
+    )
+    expected.index.name = "branch_id"
+    statistics = generate_cong_stats(
+        mock_pf, mock_grid.branch, util=util, threshold=threshold
+    )
+    assert_frame_equal(expected, statistics.drop("dist", axis=1))
diff --git a/postreise/plot/tests/test_canvas.py b/postreise/plot/tests/test_canvas.py
new file mode 100644
index 00000000..6ff30e6a
--- /dev/null
+++ b/postreise/plot/tests/test_canvas.py
@@ -0,0 +1,43 @@
+import bokeh.plotting as plt
+import pytest
+
+from postreise.plot.canvas import create_map_canvas
+
+
+def test_create_map_canvas_argument_type():
+    with pytest.raises(TypeError) as excinfo:
+        create_map_canvas(figsize=[1400, 800])
+    assert "figsize must be a tuple" in str(excinfo.value)
+
+
+def test_create_map_canvas_argument_size():
+    with pytest.raises(ValueError) as excinfo:
+        create_map_canvas(x_range=(1, 2, 3))
+    assert "x_range must have two elements" in str(excinfo.value)
+
+
+def test_create_map_canvas_figsize():
+    with pytest.raises(TypeError) as excinfo:
+        create_map_canvas(figsize=(1400.1, 800))
+    assert "all elements of figsize must be int" in str(excinfo.value)
+
+    with pytest.raises(ValueError) as excinfo:
+        create_map_canvas(figsize=(1400, -800))
+    assert "all elements of figsize must be positive" in str(excinfo.value)
+
+
+def test_create_map_canvas_range():
+    with pytest.raises(TypeError) as excinfo:
+        create_map_canvas(y_range=(-1, "1"))
+    assert "all elements of y_range must be int or float" in str(excinfo.value)
+
+    with pytest.raises(ValueError) as excinfo:
+        create_map_canvas(y_range=(100, -100))
+    assert "y_range: 1st element must be lower than 2nd" in str(excinfo.value)
+
+
+def test_create_map_canvas():
+    canvas = create_map_canvas(
+        figsize=(1200, 600), x_range=(-100, 100), y_range=(-10, 10)
+    )
+    assert isinstance(canvas, plt.Figure) is True
diff --git a/postreise/plot/tests/test_plot_bar_generation_max_min_actual.py b/postreise/plot/tests/test_plot_bar_generation_max_min_actual.py
new file mode 100644
index 00000000..8f4e3057
--- /dev/null
+++ b/postreise/plot/tests/test_plot_bar_generation_max_min_actual.py
@@ -0,0 +1,86 @@
+import pandas as pd
+import pytest
+from powersimdata.tests.mock_scenario import MockScenario
+
+from postreise.plot.plot_bar_generation_max_min_actual import (
+    plot_bar_generation_max_min_actual,
+)
+
+mock_plant = {
+    "plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
+    "zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
+    "Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
+    "Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
+    "type": ["solar", "wind", "hydro", "hydro", "wind", "coal", "ng", "wind"],
+    "zone_name": [
+        "Far West",
+        "North",
+        "West",
+        "South",
+        "North Central",
+        "South Central",
+        "Coast",
+        "East",
+    ],
+}
+
+mock_pg = pd.DataFrame(
+    {
+        "A": [80, 75, 72, 81],
+        "B": [22, 22, 25, 20],
+        "C": [130, 130, 130, 130],
+        "D": [25, 26, 27, 28],
+        "E": [10, 11, 9, 12],
+        "F": [290, 295, 295, 294],
+        "G": [190, 190, 191, 190],
+        "H": [61, 63, 65, 67],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+grid_attrs = {"plant": mock_plant}
+scenario = MockScenario(grid_attrs, pg=mock_pg)
+scenario.info["interconnect"] = "Texas"
+scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
+scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
+}
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
+
+
+def test_plot_bar_generation_max_min_actual():
+    plot_bar_generation_max_min_actual(scenario, "Texas", "wind", plot_show=False)
+    plot_bar_generation_max_min_actual(
+        scenario, "Texas", "wind", show_as_state=False, percentage=True, plot_show=False
+    )
+
+
+def test_plot_bar_generation_max_min_actual_argument_type():
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_generation_max_min_actual(scenario, ["Texas"], "wind", plot_show=False)
+    assert "interconnect must be a str" in str(excinfo.value)
+
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_generation_max_min_actual(scenario, "Texas", ["coal"], plot_show=False)
+    assert "gen_type must be a str" in str(excinfo.value)
+
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_generation_max_min_actual(
+            scenario, "Texas", "wind", fontsize="15", plot_show=False
+        )
+    assert "fontsize must be either a int or a float" in str(excinfo.value)
+
+
+def test_plot_bar_generation_max_min_actual_argument_value():
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_generation_max_min_actual(scenario, "Europe", "wind", plot_show=False)
+    assert (
+        "interconnect must be one of ['Eastern', 'Eastern_Western', 'Texas', 'Texas_Eastern', 'Texas_Western', 'USA', 'Western']"
+        in str(excinfo.value)
+    )
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_generation_max_min_actual(scenario, "Western", "wind", plot_show=False)
+    assert "interconnect is incompatible with scenario's interconnect" in str(
+        excinfo.value
+    )
diff --git a/postreise/plot/tests/test_plot_bar_generation_stack.py b/postreise/plot/tests/test_plot_bar_generation_stack.py
index 78e8690a..ed6d3250 100644
--- a/postreise/plot/tests/test_plot_bar_generation_stack.py
+++ b/postreise/plot/tests/test_plot_bar_generation_stack.py
@@ -1,62 +1,171 @@
+from unittest.mock import patch
+
+import pandas as pd
 import pytest
+from powersimdata.tests.mock_scenario import MockScenario
 
 from postreise.plot.plot_bar_generation_stack import plot_bar_generation_stack
 
+mock_plant = {
+    "plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
+    "zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
+    "Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
+    "Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
+    "type": ["solar", "wind", "solar", "wind", "wind", "solar", "solar", "wind"],
+    "zone_name": [
+        "Far West",
+        "North",
+        "West",
+        "South",
+        "North Central",
+        "South Central",
+        "Coast",
+        "East",
+    ],
+}
+
+mock_solar = pd.DataFrame(
+    {
+        "A": [95, 95, 96, 94],
+        "C": [140, 135, 136, 144],
+        "F": [299, 298, 299, 298],
+        "G": [195, 195, 193, 199],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_wind = pd.DataFrame(
+    {
+        "B": [70, 71, 70, 72],
+        "D": [29, 29, 29, 29],
+        "E": [40, 39, 38, 41],
+        "H": [71, 74, 68, 69],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_pg = pd.DataFrame(
+    {
+        "A": [80, 75, 72, 81],
+        "B": [22, 22, 25, 20],
+        "C": [130, 130, 130, 130],
+        "D": [25, 26, 27, 28],
+        "E": [10, 11, 9, 12],
+        "F": [290, 295, 295, 294],
+        "G": [190, 190, 191, 190],
+        "H": [61, 63, 65, 67],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_demand = pd.DataFrame(
+    {
+        301: [11, 12, 13, 14],
+        302: [2, 3, 8, 10],
+        303: [38, 39, 40, 40],
+        304: [20, 19, 18, 17],
+        305: [4, 3, 2, 1],
+        306: [200, 250, 225, 275],
+        307: [100, 125, 150, 175],
+        308: [36, 36, 37, 38],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+grid_attrs = {"plant": mock_plant}
+scenario = MockScenario(
+    grid_attrs, pg=mock_pg, solar=mock_solar, wind=mock_wind, demand=mock_demand
+)
+scenario.info["name"] = "Best Scenario"
+scenario.info["interconnect"] = "Texas"
+scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
+scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
+scenario.state.grid.interconnect = ["Texas"]
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
+}
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
 
-def test_plot_bar_generation_stack_throws_error_for_scenario_ids_not_a_list():
-    with pytest.raises(TypeError):
+
+@patch("postreise.plot.plot_bar_generation_stack.Scenario", return_value=scenario)
+def test_plot_bar_generation_stack(monkeypatch):
+    plot_bar_generation_stack(
+        "Texas", 1000, "wind", area_types="interconnect", plot_show=False
+    )
+    plot_bar_generation_stack(
+        "Texas",
+        1000,
+        "wind",
+        area_types="interconnect",
+        scenario_names="Worst Scenario",
+        plot_show=False,
+    )
+    plot_bar_generation_stack(
+        "Far West",
+        200,
+        "solar",
+        area_types="loadzone",
+        titles={"Far West": "Where?"},
+        t2c={"solar": "#FFBB45"},
+        t2hc={"solar_curtailment": "#996100"},
+        t2l={"solar": "shiny"},
+        curtailment_split=False,
+        plot_show=False,
+    )
+
+
+def test_plot_bar_generation_stack_argument_type():
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_generation_stack(
             "Western",
             {823, 824},
             ["wind", "solar", "coal"],
         )
+    assert "scenario_ids must be a int, str or list" in str(excinfo.value)
 
-
-def test_plot_bar_generation_stack_throws_error_for_resources_not_a_list():
-    with pytest.raises(TypeError):
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_generation_stack(
             "Western",
             [823, 824],
             {"wind", "solar", "coal"},
         )
+    assert "resources must be a list or str" in str(excinfo.value)
 
-
-def test_plot_bar_generation_stack_throws_error_for_different_length_of_areas_and_area_types():
-    with pytest.raises(ValueError):
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_generation_stack(
             ["Western", "Eastern"],
             [823, 824],
             ["wind", "solar", "coal"],
-            area_types="interconnect",
+            titles=["WECC", "EI"],
         )
+    assert "titles must be a dictionary" in str(excinfo.value)
 
-
-def test_plot_bar_generation_stack_throws_error_for_different_length_of_scenario_ids_and_scenario_names():
-    with pytest.raises(ValueError):
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_generation_stack(
             ["Western", "Eastern"],
             [823, 824],
             ["wind", "solar", "coal"],
-            scenario_names="USA Basecase",
+            save=True,
+            filenames=["WECC", "EI"],
         )
+    assert "filenames must be a dictionary" in str(excinfo.value)
 
 
-def test_plot_bar_generation_stack_throws_error_for_titles_not_a_dict():
-    with pytest.raises(TypeError):
+def test_plot_bar_generation_stack_argument_value():
+    with pytest.raises(ValueError) as excinfo:
         plot_bar_generation_stack(
             ["Western", "Eastern"],
             [823, 824],
             ["wind", "solar", "coal"],
-            titles=["WECC", "EI"],
+            area_types="interconnect",
         )
+    assert "area_types must have same size as areas" in str(excinfo.value)
 
-
-def test_plot_bar_generation_stack_throws_error_for_filenames_not_a_dict():
-    with pytest.raises(TypeError):
+    with pytest.raises(ValueError) as excinfo:
         plot_bar_generation_stack(
             ["Western", "Eastern"],
             [823, 824],
             ["wind", "solar", "coal"],
-            save=True,
-            filenames=["WECC", "EI"],
+            scenario_names="USA Basecase",
         )
+    assert "scenario_names must have same size as scenario_ids" in str(excinfo.value)
diff --git a/postreise/plot/tests/test_plot_bar_generation_vs_capacity.py b/postreise/plot/tests/test_plot_bar_generation_vs_capacity.py
index 0c67f270..c182fdec 100644
--- a/postreise/plot/tests/test_plot_bar_generation_vs_capacity.py
+++ b/postreise/plot/tests/test_plot_bar_generation_vs_capacity.py
@@ -1,10 +1,155 @@
+from unittest.mock import patch
+
 import pandas as pd
+import pytest
+from powersimdata.tests.mock_scenario import MockScenario
 
 from postreise.plot.plot_bar_generation_vs_capacity import (
     _get_bar_display_val,
     make_gen_cap_custom_data,
+    plot_bar_generation_vs_capacity,
+)
+
+mock_plant = {
+    "plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
+    "zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
+    "Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
+    "Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
+    "type": ["solar", "wind", "solar", "wind", "wind", "solar", "solar", "wind"],
+    "zone_name": [
+        "Far West",
+        "North",
+        "West",
+        "South",
+        "North Central",
+        "South Central",
+        "Coast",
+        "East",
+    ],
+}
+
+mock_solar = pd.DataFrame(
+    {
+        "A": [95, 95, 96, 94],
+        "C": [140, 135, 136, 144],
+        "F": [299, 298, 299, 298],
+        "G": [195, 195, 193, 199],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_wind = pd.DataFrame(
+    {
+        "B": [70, 71, 70, 72],
+        "D": [29, 29, 29, 29],
+        "E": [40, 39, 38, 41],
+        "H": [71, 74, 68, 69],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_pg = pd.DataFrame(
+    {
+        "A": [80, 75, 72, 81],
+        "B": [22, 22, 25, 20],
+        "C": [130, 130, 130, 130],
+        "D": [25, 26, 27, 28],
+        "E": [10, 11, 9, 12],
+        "F": [290, 295, 295, 294],
+        "G": [190, 190, 191, 190],
+        "H": [61, 63, 65, 67],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
 )
 
+mock_demand = pd.DataFrame(
+    {
+        301: [1100, 1102, 1103, 1104],
+        302: [2344, 2343, 2342, 2341],
+        303: [3875, 3876, 3877, 3878],
+        304: [4924, 4923, 4922, 4921],
+        305: [400, 300, 200, 100],
+        306: [5004, 5003, 5002, 5001],
+        307: [2504, 2503, 2502, 2501],
+        308: [3604, 3603, 3602, 1],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+grid_attrs = {"plant": mock_plant}
+scenario = MockScenario(
+    grid_attrs, pg=mock_pg, solar=mock_solar, wind=mock_wind, demand=mock_demand
+)
+scenario.info["name"] = "Best Scenario"
+scenario.info["interconnect"] = "Texas"
+scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
+scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
+scenario.state.grid.interconnect = ["Texas"]
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
+}
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
+
+
+@patch("postreise.plot.plot_bar_generation_vs_capacity.Scenario", return_value=scenario)
+def test_plot_bar_generation_stack(monkeypatch):
+    plot_bar_generation_vs_capacity(
+        areas=["Coast", "Texas"],
+        area_types=["loadzone", "interconnect"],
+        scenario_ids=[22, 44],
+        time_zone="US/Central",
+        plot_show=False,
+    )
+    plot_bar_generation_vs_capacity(
+        areas="Far West",
+        area_types="loadzone",
+        scenario_ids=[22, 44],
+        horizontal=True,
+        plot_show=False,
+    )
+
+
+def test_plot_bar_generation_stack_argument_type():
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_generation_vs_capacity(
+            areas=["South", "Far West"],
+            area_types=["loadzone", "loadzone"],
+            scenario_ids=[22, 44],
+            resource_labels=["solar", "wind"],
+            plot_show=False,
+        )
+    assert "resource_labels must be a dict" in str(excinfo.value)
+
+
+def test_plot_bar_generation_stack_argument_value():
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_generation_vs_capacity(
+            areas=["South", "East"],
+            area_types=["loadzone"],
+            scenario_ids=[22, 44],
+            plot_show=False,
+        )
+    assert "area_types must have same size as areas" in str(excinfo.value)
+
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_generation_vs_capacity(
+            areas="South Central",
+            area_types="loadzone",
+            scenario_ids=[1000, 2000],
+            scenario_names=["CaseA", "CaseB", "CaseC"],
+            plot_show=False,
+        )
+    assert "scenario_names must have same size as scenario_ids" in str(excinfo.value)
+
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_generation_vs_capacity(
+            areas="South Central",
+            area_types="loadzone",
+            scenario_ids=1000,
+            plot_show=False,
+        )
+    assert "two scenario and/or custom data must be provided" in str(excinfo.value)
+
 
 def test_get_bar_display_val_greater_than_ten():
     val = _get_bar_display_val(10.456)
diff --git a/postreise/plot/tests/test_plot_bar_renewable_max_profile_actual.py b/postreise/plot/tests/test_plot_bar_renewable_max_profile_actual.py
new file mode 100644
index 00000000..b1ab7f9d
--- /dev/null
+++ b/postreise/plot/tests/test_plot_bar_renewable_max_profile_actual.py
@@ -0,0 +1,117 @@
+import pandas as pd
+import pytest
+from powersimdata.tests.mock_scenario import MockScenario
+
+from postreise.plot.plot_bar_renewable_max_profile_actual import (
+    plot_bar_renewable_max_profile_actual,
+)
+
+mock_plant = {
+    "plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
+    "zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
+    "Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
+    "Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
+    "type": ["solar", "wind", "solar", "hydro", "wind", "solar", "ng", "wind"],
+    "zone_name": [
+        "Far West",
+        "North",
+        "West",
+        "South",
+        "North Central",
+        "South Central",
+        "Coast",
+        "East",
+    ],
+}
+
+mock_solar = pd.DataFrame(
+    {
+        "A": [95, 95, 96, 94],
+        "C": [140, 135, 136, 144],
+        "F": [299, 298, 299, 298],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_wind = pd.DataFrame(
+    {
+        "B": [70, 71, 70, 72],
+        "E": [40, 39, 38, 41],
+        "H": [71, 74, 68, 69],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_pg = pd.DataFrame(
+    {
+        "A": [80, 75, 72, 81],
+        "B": [22, 22, 25, 20],
+        "C": [130, 130, 130, 130],
+        "D": [25, 26, 27, 28],
+        "E": [10, 11, 9, 12],
+        "F": [290, 295, 295, 294],
+        "G": [190, 190, 191, 190],
+        "H": [61, 63, 65, 67],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+grid_attrs = {"plant": mock_plant}
+scenario = MockScenario(grid_attrs, pg=mock_pg, solar=mock_solar, wind=mock_wind)
+scenario.info["interconnect"] = "Texas"
+scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
+scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
+}
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
+
+
+def test_plot_bar_renewable_max_profile_actual():
+    plot_bar_renewable_max_profile_actual(scenario, "Texas", "wind", plot_show=False)
+    plot_bar_renewable_max_profile_actual(
+        scenario,
+        "Texas",
+        "solar",
+        show_as_state=False,
+        percentage=True,
+        plot_show=False,
+    )
+
+
+def test_plot_bar_renewable_max_profile_actual_argument_type():
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_renewable_max_profile_actual(
+            scenario, ["Texas"], "wind", plot_show=False
+        )
+    assert "interconnect must be a str" in str(excinfo.value)
+
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_renewable_max_profile_actual(
+            scenario, "Texas", ["coal"], plot_show=False
+        )
+    assert "gen_type must be a str" in str(excinfo.value)
+
+    with pytest.raises(TypeError) as excinfo:
+        plot_bar_renewable_max_profile_actual(
+            scenario, "Texas", "wind", fontsize="15", plot_show=False
+        )
+    assert "fontsize must be either a int or a float" in str(excinfo.value)
+
+
+def test_plot_bar_renewable_max_profile_actual_argument_value():
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_renewable_max_profile_actual(
+            scenario, "Europe", "wind", plot_show=False
+        )
+    assert (
+        "interconnect must be one of ['Eastern', 'Eastern_Western', 'Texas', 'Texas_Eastern', 'Texas_Western', 'USA', 'Western']"
+        in str(excinfo.value)
+    )
+    with pytest.raises(ValueError) as excinfo:
+        plot_bar_renewable_max_profile_actual(
+            scenario, "Western", "wind", plot_show=False
+        )
+    assert "interconnect is incompatible with scenario's interconnect" in str(
+        excinfo.value
+    )
diff --git a/postreise/plot/tests/test_plot_bar_shortfall.py b/postreise/plot/tests/test_plot_bar_shortfall.py
index 15ae624f..24b7b534 100644
--- a/postreise/plot/tests/test_plot_bar_shortfall.py
+++ b/postreise/plot/tests/test_plot_bar_shortfall.py
@@ -1,59 +1,165 @@
+from unittest.mock import patch
+
+import numpy as np
 import pandas as pd
 import pytest
+from powersimdata.tests.mock_scenario import MockScenario
 
 from postreise.plot.plot_bar_shortfall import plot_bar_shortfall
 
+mock_plant = {
+    "plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
+    "zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
+    "Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
+    "Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
+    "type": ["solar", "wind", "solar", "hydro", "wind", "solar", "ng", "wind"],
+    "zone_name": [
+        "Far West",
+        "North",
+        "West",
+        "South",
+        "North Central",
+        "South Central",
+        "Coast",
+        "East",
+    ],
+}
+
+mock_solar = pd.DataFrame(
+    {
+        "A": [95, 95, 96, 94],
+        "C": [140, 135, 136, 144],
+        "F": [299, 298, 299, 298],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_wind = pd.DataFrame(
+    {
+        "B": [70, 71, 70, 72],
+        "E": [40, 39, 38, 41],
+        "H": [71, 74, 68, 69],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_pg = pd.DataFrame(
+    {
+        "A": [80, 75, 72, 81],
+        "B": [22, 22, 25, 20],
+        "C": [130, 130, 130, 130],
+        "D": [25, 26, 27, 28],
+        "E": [10, 11, 9, 12],
+        "F": [290, 295, 295, 294],
+        "G": [190, 190, 191, 190],
+        "H": [61, 63, 65, 67],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+mock_demand = pd.DataFrame(
+    {
+        301: [11, 12, 13, 14],
+        302: [2, 3, 8, 10],
+        303: [38, 39, 40, 40],
+        304: [20, 19, 18, 17],
+        305: [4, 3, 2, 1],
+        306: [200, 250, 225, 275],
+        307: [100, 125, 150, 175],
+        308: [36, 36, 37, 38],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+grid_attrs = {"plant": mock_plant}
+scenario = MockScenario(
+    grid_attrs, pg=mock_pg, solar=mock_solar, wind=mock_wind, demand=mock_demand
+)
+scenario.info["name"] = "Best Scenario"
+scenario.info["interconnect"] = "Texas"
+scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
+scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
+scenario.state.grid.interconnect = ["Texas"]
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
+}
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
 
-def test_plot_bar_shortfall_throws_error_for_target_df_not_a_pandas_dataframe():
-    with pytest.raises(TypeError):
+target = pd.DataFrame(
+    {
+        "ce_target_fraction": [0.2437],
+        "allowed_resources": ["solar, wind"],
+        "external_ce_addl_historical_amount": [0.00],
+        "solar_percentage": [np.nan],
+        "area_type": [np.nan],
+    },
+    index=["Texas"],
+)
+target.index.name = "region_name"
+
+
+@patch("postreise.plot.plot_bar_shortfall.Scenario", return_value=scenario)
+def test_plot_bar_shortfall(monkeypatch):
+    plot_bar_shortfall("Texas", 500, target, plot_show=False)
+    plot_bar_shortfall(
+        "Texas",
+        500,
+        target,
+        baseline_scenario=1,
+        baseline_scenario_name="Baseline",
+        plot_show=False,
+    )
+
+
+def test_plot_bar_shortfall_argument_type():
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_shortfall(
             areas="all",
             scenario_ids=[823, 824],
             target_df="not a dataframe",
         )
+    assert "target_df must be a pandas.DataFrame" in str(excinfo.value)
 
-
-def test_plot_bar_shortfall_throws_error_for_strategy_not_a_dictionary():
-    with pytest.raises(TypeError):
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_shortfall(
             areas="all",
             scenario_ids=[823, 824],
             target_df=pd.DataFrame(),
             strategy="collaborative",
         )
+    assert "strategy must be a dict" in str(excinfo.value)
 
-
-def test_plot_bar_shortfall_throws_error_for_different_length_of_scenario_ids_and_scenario_names():
-    with pytest.raises(ValueError):
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_shortfall(
             areas="all",
             scenario_ids=[823, 824],
             target_df=pd.DataFrame(),
             strategy={823: "collaborative"},
-            scenario_names=["USA 2016"],
+            scenario_names=["USA 2016", "USA 2020"],
+            baseline_scenario=["1", "2", "3"],
         )
+    assert "baseline_scenario must be a str or int" in str(excinfo.value)
 
-
-def test_plot_bar_shortfall_throws_error_for_baseline_scenario_not_a_string_or_integer():
-    with pytest.raises(TypeError):
+    with pytest.raises(TypeError) as excinfo:
         plot_bar_shortfall(
             areas="all",
             scenario_ids=[823, 824],
             target_df=pd.DataFrame(),
             strategy={823: "collaborative"},
             scenario_names=["USA 2016", "USA 2020"],
-            baseline_scenario=["1", "2", "3"],
+            baseline_scenario=823,
+            baseline_scenario_name=888,
         )
+    assert "baseline_scenario_name must be a str" in str(excinfo.value)
 
 
-def test_plot_bar_shortfall_throws_error_for_baseline_scenario_name_not_a_string():
-    with pytest.raises(TypeError):
+def test_plot_bar_shortfall_argument_value():
+    with pytest.raises(ValueError) as excinfo:
         plot_bar_shortfall(
             areas="all",
             scenario_ids=[823, 824],
             target_df=pd.DataFrame(),
             strategy={823: "collaborative"},
-            scenario_names=["USA 2016", "USA 2020"],
-            baseline_scenario=823,
-            baseline_scenario_name=888,
+            scenario_names=["USA 2016"],
         )
+    assert "scenario_names must have same size as scenario_ids" in str(excinfo.value)
diff --git a/postreise/plot/tests/test_plot_sim_vs_hist.py b/postreise/plot/tests/test_plot_sim_vs_hist.py
new file mode 100644
index 00000000..1bd1c7b6
--- /dev/null
+++ b/postreise/plot/tests/test_plot_sim_vs_hist.py
@@ -0,0 +1,78 @@
+import pandas as pd
+import pytest
+from powersimdata.tests.mock_scenario import MockScenario
+
+from postreise.plot.plot_sim_vs_hist import plot_generation_sim_vs_hist
+
+mock_plant = {
+    "plant_id": ["A", "B", "C", "D", "E", "F", "G", "H"],
+    "zone_id": [301, 302, 303, 304, 305, 306, 307, 308],
+    "Pmax": [100, 75, 150, 30, 50, 300, 200, 80],
+    "Pmin": [0, 0, 0, 0, 0, 100, 10, 0],
+    "type": ["solar", "wind", "hydro", "hydro", "wind", "coal", "ng", "wind"],
+    "zone_name": [
+        "Far West",
+        "North",
+        "West",
+        "South",
+        "North Central",
+        "South Central",
+        "Coast",
+        "East",
+    ],
+}
+
+mock_pg = pd.DataFrame(
+    {
+        "A": [80, 75, 72, 81],
+        "B": [22, 22, 25, 20],
+        "C": [130, 130, 130, 130],
+        "D": [25, 26, 27, 28],
+        "E": [10, 11, 9, 12],
+        "F": [290, 295, 295, 294],
+        "G": [190, 190, 191, 190],
+        "H": [61, 63, 65, 67],
+    },
+    index=pd.date_range(start="2016-01-01", periods=4, freq="H"),
+)
+
+grid_attrs = {"plant": mock_plant}
+scenario = MockScenario(grid_attrs, pg=mock_pg)
+scenario.info["interconnect"] = "Texas"
+scenario.info["start_date"] = pd.Timestamp(2016, 1, 1)
+scenario.info["end_date"] = pd.Timestamp(2016, 1, 1, 3)
+scenario.state.grid.id2zone = {
+    k: v for k, v in zip(mock_plant["zone_id"], mock_plant["zone_name"])
+}
+scenario.state.grid.zone2id = {v: k for k, v in scenario.state.grid.id2zone.items()}
+scenario.state.grid.model = "usa_tamu"
+
+hist_gen = pd.DataFrame(
+    {
+        "solar": 100 * 4,
+        "wind": 205 * 4,
+        "hydro": 180 * 4,
+        "coal": 300 * 4,
+        "ng": 200 * 4,
+    },
+    index=["Texas"],
+)
+
+
+def test_plot_generation_sim_vs_hist_argument_type():
+    with pytest.raises(TypeError, match="hist_gen must be a pandas.DataFrame"):
+        plot_generation_sim_vs_hist(scenario, 3, "Texas")
+    with pytest.raises(TypeError, match="state must be a str"):
+        plot_generation_sim_vs_hist(scenario, pd.DataFrame(), ["Texas"])
+
+
+def test_plot_generation_sim_vs_hist_argument_value():
+    with pytest.raises(ValueError, match="Invalid state"):
+        plot_generation_sim_vs_hist(scenario, hist_gen, "Washington")
+
+
+def test_plot_generation_sim_vs_hist():
+    plot_generation_sim_vs_hist(
+        scenario, hist_gen, "Texas", show_max=False, plot_show=False
+    )
+    plot_generation_sim_vs_hist(scenario, hist_gen, "Texas", plot_show=False)