From 14c47ea3df2dc888937c2130cc312e685cd3ff30 Mon Sep 17 00:00:00 2001 From: jwhite Date: Thu, 26 Dec 2024 12:32:23 -0700 Subject: [PATCH] refactored par and obs en access, added initial exploring results notebook --- autotest/pst_tests_2.py | 28 +- examples/exploring_results_handlers.ipynb | 580 ++++++++++++++++++++++ pyemu/pst/pst_handler.py | 18 +- pyemu/pst/result_handler.py | 61 ++- 4 files changed, 648 insertions(+), 39 deletions(-) create mode 100644 examples/exploring_results_handlers.ipynb diff --git a/autotest/pst_tests_2.py b/autotest/pst_tests_2.py index 69727380..424e3ac0 100644 --- a/autotest/pst_tests_2.py +++ b/autotest/pst_tests_2.py @@ -923,7 +923,7 @@ def results_ies_1_test(): assert df is not None # weights - df = r.ies.weight_en + df = r.ies.weights #print(df) assert df is not None @@ -938,16 +938,16 @@ def results_ies_1_test(): df = r.ies.phi_meas assert df is not None # noise - df = r.ies.noise_en + df = r.ies.noise assert df is not None # get the prior par en - df = r.ies.par_en0 + df = r.ies.paren0 assert df is not None # get the 1st iter obs en - df = r.ies.obs_ensemble1 + df = r.ies.obsen1 assert df is not None # get the combined par en across all iters - df = r.ies.par_en + df = r.ies.paren assert df is not None #print(df) @@ -974,8 +974,14 @@ def results_ies_3_test(): else: raise Exception("should have failed...") + pst = pyemu.Pst(os.path.join(m_d1, "pest.pst")) + pst.add_results([m_d1,m_d2],cases=["pest","test"]) + print(pst.r0.ies.paren) + #print(pst.r0.ies.obsen) + #print(pst.r1.ies.files_loaded) + #print(pst.r1.ies.obsen) - + #print(pst.r1.ies.files_loaded) def results_ies_2_test(): import pyemu @@ -993,7 +999,7 @@ def results_ies_2_test(): assert df is not None # weights - df = r.ies.weight_en + df = r.ies.weights assert df is not None # various phi dfs @@ -1006,16 +1012,16 @@ def results_ies_2_test(): df = r.ies.phi_meas assert df is not None # noise - df = r.ies.noise_en + df = r.ies.noise assert df is not None # get the prior par en - df = r.ies.par_en0 + df = r.ies.paren0 assert df is not None # get the 1st iter obs en - df = r.ies.obs_ensemble1 + df = r.ies.obsen1 assert df is not None # get the combined par en across all iters - df = r.ies.par_en + df = r.ies.paren assert df is not None def results_mou_1_test(): diff --git a/examples/exploring_results_handlers.ipynb b/examples/exploring_results_handlers.ipynb new file mode 100644 index 00000000..7662276d --- /dev/null +++ b/examples/exploring_results_handlers.ipynb @@ -0,0 +1,580 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0b2bb650-0924-49d2-9475-a6b688d9a73a", + "metadata": {}, + "source": [ + "# Exploring `pyemu.Pst.Results`\n", + "\n", + "To make processing the insane amount of output generated by pestpp-ies and pestpp-mou, pyemu includes a results-handling helper class to hide all of the nastiness associated with finding specific iteration/generation results. Let see how this works... " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73b92513-aa21-487f-af06-a1034e3c1a39", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import pyemu" + ] + }, + { + "cell_type": "markdown", + "id": "b3245573-a62b-41f6-8556-acbc09af0217", + "metadata": {}, + "source": [ + "The results handler is based on having a stand-alone directory that holds the results of a completed pestpp-ies/pestpp-mou run. We have added a few of these directories to the pyemu repo for testing and for this example - your welcome!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "09ac362d-0f77-42ea-aa01-16a33af7723a", + "metadata": {}, + "outputs": [], + "source": [ + "m_d_ies1 = os.path.join(\"..\",\"autotest\",\"pst\",\"master_ies1\")\n", + "m_d_ies2 = os.path.join(\"..\",\"autotest\",\"pst\",\"master_ies2\")\n", + "m_d_mou1 = os.path.join(\"..\",\"autotest\",\"pst\",\"zdt1_bin\")\n", + "m_d_mou2 = os.path.join(\"..\",\"autotest\",\"pst\",\"zdt1_ascii\")\n", + "assert os.path.exists(m_d_ies1)\n", + "assert os.path.exists(m_d_ies2)\n", + "assert os.path.exists(m_d_mou1)\n", + "assert os.path.exists(m_d_mou2)\n", + "print([f for f in os.listdir(m_d_ies1) if f.endswith(\".pst\")])\n", + "print([f for f in os.listdir(m_d_ies2) if f.endswith(\".pst\")])" + ] + }, + { + "cell_type": "markdown", + "id": "e92e70bc-2ce4-4b4e-8035-05f4bc51610a", + "metadata": {}, + "source": [ + "We see the `m_d_ies11` contains a single control file, while `m_d_ies2` has many...\n", + "\n", + "Like usual, we need to load the control file into a `Pst` instance. We can assume that even tho `m_d_ies2` has lots of control files, they have the same numbers of pars and obs:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac90be50-dea4-4395-b608-90596f9c8b60", + "metadata": {}, + "outputs": [], + "source": [ + "pst = pyemu.Pst(os.path.join(m_d_ies1,\"pest.pst\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c12b1cd5-7db4-4ed3-aa4f-a7564c8d2dbb", + "metadata": {}, + "outputs": [], + "source": [ + "print(pst)" + ] + }, + { + "cell_type": "markdown", + "id": "90b4736e-2a6e-4800-9e1a-f8931f6151c0", + "metadata": {}, + "source": [ + "To use the result-handler, we need to register one or more results directories with `Pst`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fca66c2-bcd5-4757-8fe0-b145b6f9dfd4", + "metadata": {}, + "outputs": [], + "source": [ + "pst.add_results(m_d_ies1)\n" + ] + }, + { + "cell_type": "markdown", + "id": "36b12c07-dc4a-4d1a-9750-2dce263de2ac", + "metadata": {}, + "source": [ + "Now for the fun part! with only a single a results directory registered, we can access the pestpp-ies results in that directory via the `.ies` attribute:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5af2f7f5-78f0-4044-ae9e-af05c13b44dc", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies" + ] + }, + { + "cell_type": "markdown", + "id": "a6159ae6-e2cb-4ac7-a697-6a63144f15ff", + "metadata": {}, + "source": [ + "Lets say we want to see the prior parameter ensemble:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e65c70f-f65b-470b-b4b8-fc12e933e68b", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.paren0.head()" + ] + }, + { + "cell_type": "markdown", + "id": "55ed8eca-3f72-499d-bb43-ebfdc4bdcde9", + "metadata": {}, + "source": [ + "The result handler uses lazy evaluation and holds previously access files in memory:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "418c9353-f767-443a-994b-1baabf3907fd", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.files_loaded" + ] + }, + { + "cell_type": "markdown", + "id": "20fa7a08-f071-44f7-88de-f89f45430f8e", + "metadata": {}, + "source": [ + "How about the correspoding obs ensemble:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e82caab-458b-458a-a17c-0ada5d28f2bb", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.obsen0.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "59237d6a-6a87-4a23-8dcc-bbbebe0c31bf", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.files_loaded" + ] + }, + { + "cell_type": "markdown", + "id": "8f79fabf-aedd-4973-8292-cc2eff709374", + "metadata": {}, + "source": [ + "What if we want to see all of the par and obs ensembles across all iterations? " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cbe8229-2051-43e2-979d-c9ab9bfd91ff", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.paren" + ] + }, + { + "cell_type": "markdown", + "id": "45940042-a06b-4958-86bb-35b3138b6203", + "metadata": {}, + "source": [ + "How about noise and weight ensembles?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c7acc72b-61d7-409c-949e-943f628f5f43", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.noise.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e6d7017-87f1-4511-b98a-c54b5ea4c99e", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.weights.head()" + ] + }, + { + "cell_type": "markdown", + "id": "85cb7454-be3d-4478-95bc-7ea341b8bba4", + "metadata": {}, + "source": [ + "yeah, thats pretty awesome....\n", + "\n", + "we can also access the parameter-change summaries:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06873355-1ea1-4c39-adbc-c447ecb5fcef", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.pcs" + ] + }, + { + "cell_type": "markdown", + "id": "c89c7a98-3b6a-49a6-a73c-b0972f65a690", + "metadata": {}, + "source": [ + "And the phi summary information:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee6644da-b0e1-47bd-b785-c182a5d1f983", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.phi_actual.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6df45ff5-2d00-424f-9c77-0e75b426358f", + "metadata": {}, + "outputs": [], + "source": [ + "pst.ies.phi_meas.head()" + ] + }, + { + "cell_type": "markdown", + "id": "dba94de9-71ce-444b-b18a-1649256de39c", + "metadata": {}, + "source": [ + "Things work in a similar way for pestpp-mou:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76ebf403-6cb4-4a14-bd3f-226b7ea33516", + "metadata": {}, + "outputs": [], + "source": [ + "print([f for f in os.listdir(m_d_mou1) if f.endswith(\".pst\")])\n", + "print([f for f in os.listdir(m_d_mou2) if f.endswith(\".pst\")])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc6e9fa6-ef31-4190-8358-61a2ba954c13", + "metadata": {}, + "outputs": [], + "source": [ + "pst = pyemu.Pst(os.path.join(m_d_mou1,\"zdt1.pst\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "530184ae-b514-41a8-921c-fa8f6f0fb02e", + "metadata": {}, + "outputs": [], + "source": [ + "pst.add_results(m_d_mou1)" + ] + }, + { + "cell_type": "markdown", + "id": "0b6b7b93-09fb-464c-be57-bc695620a1a6", + "metadata": {}, + "source": [ + "Like with the pestpp-ies handler, we can access the individual populations or the combined populations:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31a44b14-e281-4a2a-a1ac-a73f73457df7", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.obspop0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b751d90-f698-45d2-bc80-ca4bc2737074", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.dvpop" + ] + }, + { + "cell_type": "markdown", + "id": "b502c4e5-df26-4386-ac9e-bece6b023d59", + "metadata": {}, + "source": [ + "and the archives:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23ae8ea1-55e5-4be6-b2d0-8ea5411edbe9", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.archivedvpop0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45528894-9936-469a-bcc0-630c4beda6d8", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.archivedvpop" + ] + }, + { + "cell_type": "markdown", + "id": "82a341b3-38cf-44d6-bc99-eaf8c9531aac", + "metadata": {}, + "source": [ + "The pareto summary and pareto archive summaries are accessible like this:" + ] + }, + { + "cell_type": "markdown", + "id": "b6b77234-f139-4a6b-9dba-257ea53d916c", + "metadata": {}, + "source": [ + "And the chance populations (if applicable) are also available:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f73c17ca-c7a9-49be-82cb-858f3a027797", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.chanceobspop" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17892cc6-f1c1-4a93-a621-7bfa6152898f", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.paretosum" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aae711d8-164a-42bd-bd66-1c5ab4dafef2", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.paretosum_archive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64ddeff9-b61c-4d4b-81fb-ba71c119af17", + "metadata": {}, + "outputs": [], + "source": [ + "pst.mou.files_loaded" + ] + }, + { + "cell_type": "markdown", + "id": "5b02e4c9-eeea-407b-a48b-7ce710935728", + "metadata": {}, + "source": [ + "## Dealing with multiple results diretories\n", + "\n", + "This is getting deep!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb65518f-be75-41a0-af9b-3db5297b2f23", + "metadata": {}, + "outputs": [], + "source": [ + "print([f for f in os.listdir(m_d_ies1) if f.endswith(\".pst\")])\n", + "print([f for f in os.listdir(m_d_ies2) if f.endswith(\".pst\")])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7620e381-3463-4e15-87cc-fcef218cd6df", + "metadata": {}, + "outputs": [], + "source": [ + "pst = pyemu.Pst(os.path.join(m_d_ies1,\"pest.pst\"))" + ] + }, + { + "cell_type": "markdown", + "id": "8f812287-4a50-4078-8ef7-d9255f76a12b", + "metadata": {}, + "source": [ + "When using multiple directories, you can pass an optional \"cases\" argument in the case where you have named the control file a different name in different results directories:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9ca61bc-fc5c-4365-ae72-9478b02f0bfd", + "metadata": {}, + "outputs": [], + "source": [ + "pst.add_results([m_d_ies1,m_d_ies2],cases=[\"pest\",\"test\"])" + ] + }, + { + "cell_type": "markdown", + "id": "6185ecd3-729b-47fa-88fb-a9f3b9e0f5fd", + "metadata": {}, + "source": [ + "The results directories are now accessible via the `r` prefix attribute, where `r0` the first dir, `r1 is the second, etc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e79c345-7987-46b9-8ddd-4d44df3c49ac", + "metadata": {}, + "outputs": [], + "source": [ + "pst.r0.ies.paren" + ] + }, + { + "cell_type": "markdown", + "id": "294d991a-73ae-4b72-b3e4-cbadbbf8651d", + "metadata": {}, + "source": [ + "You can also access the results via the directory name:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e145ea7e-b086-479c-bb40-aca614bf7809", + "metadata": {}, + "outputs": [], + "source": [ + "pst.master_ies2.ies.obsen" + ] + }, + { + "cell_type": "markdown", + "id": "9f3726c9-5aa7-4b48-92ca-2fa2415e310f", + "metadata": {}, + "source": [ + "Or you can get a list of the ies or mou specific handlers for all the directories (in the ordered they were passed to `Pst.add_results()`):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18036e6c-431d-4f1f-a30b-42e418777f5e", + "metadata": {}, + "outputs": [], + "source": [ + "ies_all = pst.ies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "361b2cdb-c215-46f6-87ce-4fd1d1e3078b", + "metadata": {}, + "outputs": [], + "source": [ + "ies_all" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a4bd6b7-0439-47f3-b103-bf6b3f1f04dd", + "metadata": {}, + "outputs": [], + "source": [ + "ies_all[0].phi_actual" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "303b233a-e66f-4798-9470-098b35c1e233", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyemu/pst/pst_handler.py b/pyemu/pst/pst_handler.py index b907a76a..d135f57e 100644 --- a/pyemu/pst/pst_handler.py +++ b/pyemu/pst/pst_handler.py @@ -141,6 +141,10 @@ def __init__(self, filename, load=True, resfile=None, parse_metadata=True): self.load(filename, parse_metadata=parse_metadata) + def __repr__(self): + return "npar:{0}, npar_adj:{1}, nobs:{2}, nnzobs:{3}, filename:{4}".\ + format(self.npar, self.npar_adj,self.nobs,self.nnz_obs,self.filename) + def __setattr__(self, key, value): if key == "model_command": if isinstance(value, str): @@ -176,13 +180,21 @@ def __getattr__(self,tag): raise Exception("Pst has no attribute: '{0}'".format(tag)) - def add_results(self,m_ds): + def add_results(self,m_ds,cases=None): if not isinstance(m_ds,list): m_ds = [m_ds] - for m_d in m_ds: + if cases is not None and not isinstance(cases,list): + cases = [cases] + if cases is not None: + if len(cases) != len(m_ds): + raise Exception("len(cases) != len(m_ds)") + for i,m_d in enumerate(m_ds): if m_d in self.results: raise Exception("results directory '{0}' already registered") - self.results[m_d] = Results(m_d,case=os.path.split(self.filename)[1].replace(".pst","")) + case = os.path.split(self.filename)[1].replace(".pst","") + if cases is not None: + case = cases[i] + self.results[m_d] = Results(m_d,case=case) self.result_dirs.append(m_d) @classmethod diff --git a/pyemu/pst/result_handler.py b/pyemu/pst/result_handler.py index d1c9d898..0be60ffe 100644 --- a/pyemu/pst/result_handler.py +++ b/pyemu/pst/result_handler.py @@ -1,11 +1,6 @@ import os import pandas as pd -import pyemu -# class ResultFile(object): -# def __init__(self,resulttype): -# if resulttype == "par_ensembles": -# print(resulttype) -# #print(stuff) +import pyemu class ResultHandler(object): @@ -18,6 +13,12 @@ def __init__(self,m_d,case): #todo: check that m_ds are infact valid master dirs + @property + def files_loaded(self): + files = list(self.results_loaded.keys()) + files.sort() + return files + def get_or_load_csv_file(self,filename,index_col=None): if len(os.path.split(filename)[0]) == 0: @@ -78,7 +79,8 @@ def parse_iter_from_tag(self,tag): if len(digits) == 0: return None digits = digits[::-1] - itr = int(''.join(digits)) + #itr = int(''.join(digits)) + itr = ''.join(digits) return itr class ResultIesHandler(ResultHandler): @@ -104,15 +106,16 @@ def get_files(self,tag): def __getattr__(self,tag): tag = tag.lower().strip() - if tag.startswith("par_en") or tag.startswith("obs_en"): + if tag.startswith("paren") or tag.startswith("obsen"): itr = self.parse_iter_from_tag(tag) - ttag = tag.split("_")[0] + ttag = tag[:3] #load the combined ensemble if itr is None: file_tag = ".{0}.".format(ttag) files = self.get_files(file_tag) if len(files) == 0: - raise Exception() + raise Exception("ResultsIesHandler: no files found for tag '{0}' using file_tag '{1}'".\ + format(tag,file_tag)) itrs = [int(os.path.split(f)[1].split('.')[1]) for f in files] self.check_dup_iters(itrs,files) d = {i:f for i,f in zip(itrs,files)} @@ -129,7 +132,7 @@ def __getattr__(self,tag): df = dfs[0] return df else: - file_tag = ".{0}.{1}.".format(itr,ttag) + file_tag = ".{0}.{1}.".format(int(itr),ttag) files = self.get_files(file_tag) if len(files) != 1: #todo something here... @@ -146,22 +149,26 @@ def __getattr__(self,tag): df = self.get_or_load_csv_file(csv_filename) return df - elif tag.startswith("noise_en"): + elif tag.startswith("noise"): files = self.get_files(".obs+noise.") if len(files) != 1: - raise Exception() + raise Exception("expected 1 noise ensemble file, found {0}: {1}".\ + format(len(files),','.join(files))) df = self.get_or_load_ensemble_file(files[0]) return df - elif tag.startswith("weight_en"): + elif tag.startswith("weights"): files = self.get_files(".weights.") if len(files) != 1: - raise Exception() + raise Exception("expected 1 weight ensemble file, found {0}: {1}". \ + format(len(files), ','.join(files))) df = self.get_or_load_ensemble_file(files[0]) return df elif tag.startswith("pdc"): itr = self.parse_iter_from_tag(tag) - ttag = tag.split("_")[0] + ttag = tag + if itr is not None: + ttag = tag.replace(itr,"") # load the combined ensemble if itr is None: file_tag = ".{0}.".format(ttag) @@ -184,18 +191,22 @@ def __getattr__(self,tag): df = dfs[0] return df else: - file_tag = ".{0}.{1}.".format(itr, ttag) + file_tag = ".{0}.{1}.".format(int(itr), ttag) files = self.get_files(file_tag) if len(files) != 1: # todo something here... - raise Exception() + print(files) + raise Exception("expecting to find 1 file for tag '{0}', iter {1} (org tag {2})"\ + .format(ttag,itr,tag)) df = self.get_or_load_ensemble_file(files[0]) return df elif tag.startswith("pcs"): itr = self.parse_iter_from_tag(tag) - ttag = tag.split("_")[0] + ttag = tag + if itr is not None: + ttag = tag.replace(itr, "") # load the combined ensemble if itr is None: file_tag = ".{0}.".format(ttag) @@ -218,7 +229,7 @@ def __getattr__(self,tag): df = dfs[0] return df else: - file_tag = ".{0}.{1}.".format(itr, ttag) + file_tag = ".{0}.{1}.".format(int(itr), ttag) files = self.get_files(file_tag) if len(files) != 1: # todo something here... @@ -230,7 +241,7 @@ def __getattr__(self,tag): else: - raise Exception("tag: '{0}' not recognized".format(tag)) + raise Exception("ResultIesHandler has no attribute '{0}'".format(tag)) @@ -298,7 +309,7 @@ def __getattr__(self,tag): df = dfs[0] return df else: - file_tag = ".{0}.{1}.".format(itr, ttag) + file_tag = ".{0}.{1}.".format(int(itr), ttag) files = self.get_files(file_tag) if len(files) != 1: # todo something here... @@ -356,7 +367,7 @@ def __getattr__(self,tag): return df else: - file_tag = ".{0}.{1}.".format(itr, ttag) + file_tag = ".{0}.{1}.".format(int(itr), ttag) files = self.get_files(file_tag) if len(files) != 1: # todo something here... @@ -395,7 +406,7 @@ def __getattr__(self,tag): df = dfs[0] return df else: - file_tag = ".{0}.{1}.".format(itr, ttag) + file_tag = ".{0}.{1}.".format(int(itr), ttag) files = self.get_files(file_tag) if len(files) != 1: # todo something here... @@ -405,7 +416,7 @@ def __getattr__(self,tag): return df else: - raise Exception("tag: '{0}' not recognized".format(tag)) + raise Exception("ResultMouHandler has no attribute '{0}'".format(tag)) class Results(object):