├── .gitignore ├── README.md ├── doc ├── index.rst ├── keyrefs.rst ├── modules.rst └── swmmoutputapi.rst ├── license.txt ├── setup.py ├── swmmoutputapi ├── __init__.py ├── _toolkitpyswmm.py ├── src │ ├── datetime.c │ ├── datetime.h │ ├── main.c │ ├── outputAPI.c │ └── outputAPI.h └── swmmbinreader.py └── testing ├── OutputTestModel522_SHORT.inp ├── OutputTestModel_LargeOutput.inp ├── PySWMMReadOutput.py ├── QuickWrapperTesting.py ├── QuickWrapperTesting_LargeFile.py └── __init__.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | *.o 9 | 10 | # Models: 11 | *.out 12 | *.rpt 13 | 14 | # Distribution / packaging 15 | .pyc 16 | .Python 17 | env/ 18 | build/ 19 | develop-eggs/ 20 | dist/ 21 | downloads/ 22 | eggs/ 23 | .eggs/ 24 | lib/ 25 | lib64/ 26 | parts/ 27 | sdist/ 28 | var/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *,cover 52 | .hypothesis/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | 61 | # Sphinx documentation 62 | docs/_build/ 63 | 64 | # PyBuilder 65 | target/ 66 | 67 | #Ipython Notebook 68 | .ipynb_checkpoints 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SWMMOutputAPI 2 | SWMM Binary Output Reader - Python Wrapper for SWMM 3 | 4 | This package provides a Pythonic interface to a binary output file generated by USEPA Stormwater Management Model (SWMM5). This tool has proven to be useful in post-processing applications with both large and small output files. The Python wrapper (SWMMOutputAPI.swmmbinreader) calls on a compiled object library which handles seeking though the binary output file. Taking this approach increases the rate at which data can be read from a binary output file. With a simpler collection of tools to access binary output, the user can spend more time on data analysis, visualization, and prototyping than plumbing. 5 | 6 | ## Docs 7 | 8 | [Python Hosted Docs](http://pythonhosted.org/SWMMOutputAPI/index.html) 9 | 10 | ## Installing 11 | 12 | `pip install SWMMOutputAPI` 13 | 14 | 15 | ## Basic Tutorial 16 | 17 | ```python 18 | from swmmbinreader import * 19 | 20 | #Create and instance of SWMMBinReader 21 | OutputObject = SWMMBinReader() 22 | 23 | #Open Outputfile 24 | OutputObject.OpenBinFile(r"C:\PROJECTCODE\SWMMOutputAPI\testing\outputfile.out") 25 | 26 | #Get Link IDs 27 | LinkIDs = OutputObject.get_IDs(SM_link) 28 | print(LinkIDs) 29 | >>> ['C3', 'C2', 'C1'] 30 | 31 | #Get Time Series 32 | Times = OutputObject.get_TimeSeries() 33 | print(Times) 34 | >>> [datetime.datetime(2015, 11, 29, 14, 0), datetime.datetime(2015, 11, 29, 14, 1), ..., datetime.datetime(2015, 11, 29, 14, 9)] 35 | 36 | #Get Data Series 37 | Series = OutputObject.get_Series(SM_link, flow_rate_link, 'C2') 38 | print(series) 39 | >>> [3.908519983291626, 4.6215434074401855, 4.594745635986328, 4.595311641693115, ..., 4.595311641693115] 40 | 41 | #Close Binary File 42 | OutputObject.CloseBinFile() 43 | 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | 2 | 3 | SWMMOutputAPI 4 | ============= 5 | 6 | This package provides a Pythonic interface to a binary output file generated by USEPA Stormwater Management Model (SWMM5). This tool has proven to be useful in post-processing applications with both large and small output files. The Python wrapper (SWMMOutputAPI.swmmbinreader) calls on a compiled object library which handles seeking though the binary output file. Taking this approach increases the rate at which data can be read from a binary output file. 7 | 8 | 9 | Documentation 10 | ============= 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | 15 | modules 16 | keyrefs 17 | 18 | 19 | 20 | Indices and tables 21 | ================== 22 | 23 | * :ref:`genindex` 24 | * :ref:`modindex` 25 | * :ref:`search` 26 | 27 | Acknowledgements 28 | ================ 29 | Thanks to: 30 | 31 | * Colleen Barr 32 | * Ian Endres 33 | * Fred Myers 34 | * Michael Tryby 35 | 36 | -------------------------------------------------------------------------------- /doc/keyrefs.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | Key References 3 | ============== 4 | 5 | 6 | SMO_elementIDType 7 | ----------------- 8 | 9 | +-------------------+-----+ 10 | | SMO_elementIDType | val | 11 | +===================+=====+ 12 | | subcatchCount | 0 | 13 | +-------------------+-----+ 14 | | nodeCount | 1 | 15 | +-------------------+-----+ 16 | | linkCount | 2 | 17 | +-------------------+-----+ 18 | | pollutantCount | 3 | 19 | +-------------------+-----+ 20 | 21 | 22 | SMO_unit 23 | -------- 24 | 25 | +---------------+-----+ 26 | | SMO_unit | val | 27 | +===============+=====+ 28 | | flow_rate | 0 | 29 | +---------------+-----+ 30 | | concentration | 1 | 31 | +---------------+-----+ 32 | 33 | 34 | SMO_timeElementType 35 | ------------------- 36 | 37 | +------------------------+-----+ 38 | | SMO_timeElementType | val | 39 | +========================+=====+ 40 | | reportStep, | 0 | 41 | +------------------------+-----+ 42 | | numPeriods | 1 | 43 | +------------------------+-----+ 44 | 45 | SMO_elementCount 46 | ---------------- 47 | 48 | +------------------+-----+ 49 | | SMO_elementCount | val | 50 | +==================+=====+ 51 | | subcatchCount | 0 | 52 | +------------------+-----+ 53 | | nodeCount | 1 | 54 | +------------------+-----+ 55 | | linkCount | 2 | 56 | +------------------+-----+ 57 | | pollutantCount | 3 | 58 | +------------------+-----+ 59 | 60 | 61 | 62 | SMO_elementType 63 | --------------- 64 | 65 | +-----------------+-----+ 66 | | SMO_elementType | val | 67 | +=================+=====+ 68 | | SM_subcatch | 0 | 69 | +-----------------+-----+ 70 | | SM_node | 1 | 71 | +-----------------+-----+ 72 | | SM_link | 2 | 73 | +-----------------+-----+ 74 | | SM_sys | 3 | 75 | +-----------------+-----+ 76 | 77 | 78 | SMO_Attribute 79 | ------------- 80 | 81 | +-------------------------+-------------------------+-----+------------------------------------------+ 82 | | | SMO_Attribute | val | Unit | 83 | | | | | | 84 | +=========================+=========================+=====+==========================================+ 85 | | Subcatchment Attributes | rainfall_subcatch | 0 | (in/hr or mm/hr) | 86 | | | | | | 87 | +-------------------------+-------------------------+-----+------------------------------------------+ 88 | | | snow_depth_subcatch | 1 | (in or mm) | 89 | +-------------------------+-------------------------+-----+------------------------------------------+ 90 | | | evap_loss | 2 | (in/hr or mm/hr) | 91 | +-------------------------+-------------------------+-----+------------------------------------------+ 92 | | | infil_loss | 3 | (in/hr or mm/hr) | 93 | +-------------------------+-------------------------+-----+------------------------------------------+ 94 | | | runoff_rate | 4 | (flow units) | 95 | +-------------------------+-------------------------+-----+------------------------------------------+ 96 | | | gwoutflow_rate | 5 | (flow units) | 97 | +-------------------------+-------------------------+-----+------------------------------------------+ 98 | | | gwtable_elev | 6 | (ft or m) | 99 | +-------------------------+-------------------------+-----+------------------------------------------+ 100 | | | soil_moisture | 7 | unsaturated zone moisture content (-) | 101 | +-------------------------+-------------------------+-----+------------------------------------------+ 102 | | | pollutant_conc_subcatch | 8 | first pollutant | 103 | +-------------------------+-------------------------+-----+------------------------------------------+ 104 | | Node Attributes | invert_depth | 0 | (ft or m) | 105 | | | | | | 106 | +-------------------------+-------------------------+-----+------------------------------------------+ 107 | | | hydraulic_head | 1 | (ft or m) | 108 | +-------------------------+-------------------------+-----+------------------------------------------+ 109 | | | stored_ponded_volume | 2 | (ft3 or m3) | 110 | +-------------------------+-------------------------+-----+------------------------------------------+ 111 | | | lateral_inflow | 3 | (flow units) | 112 | +-------------------------+-------------------------+-----+------------------------------------------+ 113 | | | total_inflow | 4 | lateral + upstream (flow units) | 114 | +-------------------------+-------------------------+-----+------------------------------------------+ 115 | | | flooding_losses | 5 | (flow units) | 116 | +-------------------------+-------------------------+-----+------------------------------------------+ 117 | | | pollutant_conc_node | 6 | first pollutant | 118 | +-------------------------+-------------------------+-----+------------------------------------------+ 119 | | Link Attributes | flow_rate_link | 0 | (flow units) | 120 | | | | | | 121 | +-------------------------+-------------------------+-----+------------------------------------------+ 122 | | | flow_depth | 1 | (ft or m) | 123 | +-------------------------+-------------------------+-----+------------------------------------------+ 124 | | | flow_velocity | 2 | (ft/s or m/s) | 125 | +-------------------------+-------------------------+-----+------------------------------------------+ 126 | | | flow_volume | 3 | (ft3 or m3) | 127 | +-------------------------+-------------------------+-----+------------------------------------------+ 128 | | | capacity | 4 | (fraction of conduit filled) | 129 | +-------------------------+-------------------------+-----+------------------------------------------+ 130 | | | pollutant_conc_link | 5 | first pollutant | 131 | +-------------------------+-------------------------+-----+------------------------------------------+ 132 | | System Attributes | air_temp | 0 | (deg. F or deg. C) | 133 | | | | | | 134 | +-------------------------+-------------------------+-----+------------------------------------------+ 135 | | | rainfall_system | 1 | (in/hr or mm/hr) | 136 | +-------------------------+-------------------------+-----+------------------------------------------+ 137 | | | snow_depth_system | 2 | (in or mm) | 138 | +-------------------------+-------------------------+-----+------------------------------------------+ 139 | | | evap_infil_loss | 3 | (in/hr or mm/hr) | 140 | +-------------------------+-------------------------+-----+------------------------------------------+ 141 | | | runoff_flow | 4 | (flow units) | 142 | +-------------------------+-------------------------+-----+------------------------------------------+ 143 | | | dry_weather_inflow | 5 | (flow units) | 144 | +-------------------------+-------------------------+-----+------------------------------------------+ 145 | | | groundwater_inflow | 6 | (flow units) | 146 | +-------------------------+-------------------------+-----+------------------------------------------+ 147 | | | RDII_inflow | 7 | (flow units) | 148 | +-------------------------+-------------------------+-----+------------------------------------------+ 149 | | | direct_inflow | 8 | user defined (flow units) | 150 | +-------------------------+-------------------------+-----+------------------------------------------+ 151 | | | total_lateral_inflow | 9 | (sum of variables 4 to 8) //(flow units) | 152 | +-------------------------+-------------------------+-----+------------------------------------------+ 153 | | | flood_losses | 10 | (flow units) | 154 | +-------------------------+-------------------------+-----+------------------------------------------+ 155 | | | outfall_flows | 11 | (flow units) | 156 | +-------------------------+-------------------------+-----+------------------------------------------+ 157 | | | volume_stored | 12 | (ft3 or m3) | 158 | +-------------------------+-------------------------+-----+------------------------------------------+ 159 | | | evap_rate | 13 | (in/day or mm/day) | 160 | +-------------------------+-------------------------+-----+------------------------------------------+ 161 | 162 | -------------------------------------------------------------------------------- /doc/modules.rst: -------------------------------------------------------------------------------- 1 | swmmoutputapi 2 | ============= 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | swmmoutputapi 8 | -------------------------------------------------------------------------------- /doc/swmmoutputapi.rst: -------------------------------------------------------------------------------- 1 | swmmoutputapi package 2 | ===================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | swmmoutputapi.swmmbinreader module 8 | ---------------------------------- 9 | 10 | .. automodule:: swmmoutputapi.swmmbinreader 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | 16 | Module contents 17 | --------------- 18 | 19 | .. automodule:: swmmoutputapi 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Bryant E. McDonnell 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | 2 | from setuptools import setup, find_packages 3 | 4 | 5 | 6 | VERSION = '0.2.1' 7 | AUTHOR_NAME = 'Bryant E. McDonnell (EmNet LLC)' 8 | AUTHOR_EMAIL = 'bemcdonnell@gmail.com' 9 | 10 | 11 | 12 | setup(name='SWMMOutputAPI', 13 | version=VERSION, 14 | description='Python Wrapper for SWMM5 Binary Output File', 15 | author=AUTHOR_NAME, 16 | url='https://github.com/bemcdonnell/SWMMOutputAPI.git', 17 | author_email=AUTHOR_EMAIL, 18 | 19 | package_dir = {'':'swmmoutputapi'}, 20 | packages=[''], 21 | package_data = {'': 22 | ['src/*.c',\ 23 | 'src/*.h',\ 24 | 'data/outputAPI_winx86.dll',\ 25 | 'license.txt']}, 26 | include_package_data=True, 27 | license="BSD2 License", 28 | keywords = "swmm5, swmm, binary output, hydraulics, hydrology, modeling, collection system", 29 | classifiers=[ 30 | "Topic :: Scientific/Engineering", 31 | "Topic :: Documentation :: Sphinx", 32 | "Operating System :: Microsoft :: Windows", 33 | "License :: OSI Approved :: BSD License", 34 | "Programming Language :: Python :: 2.7", 35 | "Programming Language :: C", 36 | "Development Status :: 4 - Beta", 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /swmmoutputapi/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /swmmoutputapi/_toolkitpyswmm.py: -------------------------------------------------------------------------------- 1 | ''' PySWMM Output API Toolkit enumerations Author: Bryant E. McDonnell Date: 11/20/2015 ''' DLLErrorKeys=\ {\ 411:"Input Error 411: no memory allocated for results.",\ 412:"Input Error 412: no results; binary file hasn't been opened.",\ 421:"Input Error 421: invalid parameter code.",\ 434:"File Error 434: unable to open binary output file.",\ 435:"File Error 435: run terminated; no results in binary file.",\ 441:"Error 441: need to call SMR_open before calling this function"\ } #SMO_elementCount subcatchCount = 0 nodeCount = 1 linkCount = 2 pollutantCount = 3 #SMO_unit flow_rate = 0 concentration = 1 #SMO_apiFunction getAttribute = 0 getResult = 1 #SMO_elementType SM_subcatch = 0 SM_node = 1 SM_link = 2 SM_sys = 3 #SMO_time reportStep = 0 numPeriods = 1 #SMO_subcatchAttribute rainfall_subcatch = 0 snow_depth_subcatch = 1 evap_loss = 2 infil_loss = 3 runoff_rate = 4 gwoutflow_rate = 5 gwtable_elev = 6 soil_moisture = 7 pollutant_conc_subcatch = 8 #SMO_nodeAttribute invert_depth = 0 hydraulic_head = 1 stored_ponded_volume = 2 lateral_inflow = 3 total_inflow = 4 flooding_losses = 5 pollutant_conc_node = 6 #SMO_linkAttribute flow_rate_link = 0 flow_depth = 1 flow_velocity = 2 flow_volume = 3 capacity = 4 pollutant_conc_link = 5 #SMO_systemAttribute air_temp = 0 rainfall_system = 1 snow_depth_system = 2 evap_infil_loss = 3 runoff_flow = 4 dry_weather_inflow = 5 groundwater_inflow = 6 RDII_inflow = 7 direct_inflow = 8 total_lateral_inflow = 9 flood_losses = 10 outfall_flows = 11 volume_stored = 12 evap_rate = 13 -------------------------------------------------------------------------------- /swmmoutputapi/src/datetime.c: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // datetime.c 3 | // 4 | // Project: EPA SWMM5 5 | // Version: 5.1 6 | // Date: 03/20/14 (Build 5.1.001) 7 | // Author: L. Rossman 8 | // 9 | // DateTime functions. 10 | //----------------------------------------------------------------------------- 11 | #define _CRT_SECURE_NO_DEPRECATE 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "datetime.h" 18 | 19 | // Macro to convert charcter x to upper case 20 | #define UCHAR(x) (((x) >= 'a' && (x) <= 'z') ? ((x)&~32) : (x)) 21 | 22 | //----------------------------------------------------------------------------- 23 | // Constants 24 | //----------------------------------------------------------------------------- 25 | static const char* MonthTxt[] = 26 | {"JAN", "FEB", "MAR", "APR", 27 | "MAY", "JUN", "JUL", "AUG", 28 | "SEP", "OCT", "NOV", "DEC"}; 29 | static const int DaysPerMonth[2][12] = // days per month 30 | {{31, 28, 31, 30, 31, 30, // normal years 31 | 31, 31, 30, 31, 30, 31}, 32 | {31, 29, 31, 30, 31, 30, // leap years 33 | 31, 31, 30, 31, 30, 31}}; 34 | static const int DateDelta = 693594; // days since 01/01/00 35 | static const double SecsPerDay = 86400.; // seconds per day 36 | 37 | //----------------------------------------------------------------------------- 38 | // Shared variables 39 | //----------------------------------------------------------------------------- 40 | static int DateFormat; 41 | 42 | 43 | //============================================================================= 44 | 45 | void divMod(int n, int d, int* result, int* remainder) 46 | 47 | // Input: n = numerator 48 | // d = denominator 49 | // Output: result = integer part of n/d 50 | // remainder = remainder of n/d 51 | // Purpose: finds integer part and remainder of n/d. 52 | 53 | { 54 | if (d == 0) 55 | { 56 | *result = 0; 57 | *remainder = 0; 58 | } 59 | else 60 | { 61 | *result = n/d; 62 | *remainder = n - d*(*result); 63 | } 64 | } 65 | 66 | //============================================================================= 67 | 68 | int isLeapYear(int year) 69 | 70 | // Input: year = a year 71 | // Output: returns 1 if year is a leap year, 0 if not 72 | // Purpose: determines if year is a leap year. 73 | 74 | { 75 | if ((year % 4 == 0) 76 | && ((year % 100 != 0) 77 | || (year % 400 == 0))) return 1; 78 | else return 0; 79 | } 80 | 81 | //============================================================================= 82 | 83 | int datetime_findMonth(char* month) 84 | 85 | // Input: month = month of year as character string 86 | // Output: returns: month of year as a number (1-12) 87 | // Purpose: finds number (1-12) of month. 88 | 89 | { 90 | int i; 91 | for (i = 0; i < 12; i++) 92 | { 93 | if (UCHAR(month[0]) == MonthTxt[i][0] 94 | && UCHAR(month[1]) == MonthTxt[i][1] 95 | && UCHAR(month[2]) == MonthTxt[i][2]) return i+1; 96 | } 97 | return 0; 98 | } 99 | 100 | //============================================================================= 101 | 102 | DateTime datetime_encodeDate(int year, int month, int day) 103 | 104 | // Input: year = a year 105 | // month = a month (1 to 12) 106 | // day = a day of month 107 | // Output: returns encoded value of year-month-day 108 | // Purpose: encodes year-month-day to a DateTime value. 109 | 110 | { 111 | int i, j; 112 | i = isLeapYear(year); 113 | if ((year >= 1) 114 | && (year <= 9999) 115 | && (month >= 1) 116 | && (month <= 12) 117 | && (day >= 1) 118 | && (day <= DaysPerMonth[i][month-1])) 119 | { 120 | for (j = 0; j < month-1; j++) day += DaysPerMonth[i][j]; 121 | i = year - 1; 122 | return i*365 + i/4 - i/100 + i/400 + day - DateDelta; 123 | } 124 | else return -DateDelta; 125 | } 126 | 127 | //============================================================================= 128 | 129 | DateTime datetime_encodeTime(int hour, int minute, int second) 130 | 131 | // Input: hour = hour of day (0-24) 132 | // minute = minute of hour (0-60) 133 | // second = seconds of minute (0-60) 134 | // Output: returns time encoded as fractional part of a day 135 | // Purpose: encodes hour:minute:second to a DateTime value 136 | 137 | { 138 | int s; 139 | if ((hour >= 0) 140 | && (minute >= 0) 141 | && (second >= 0)) 142 | { 143 | s = (hour * 3600 + minute * 60 + second); 144 | return (double)s/SecsPerDay; 145 | } 146 | else return 0.0; 147 | } 148 | 149 | //============================================================================= 150 | 151 | void datetime_decodeDate(DateTime date, int* year, int* month, int* day) 152 | 153 | // Input: date = encoded date/time value 154 | // Output: year = 4-digit year 155 | // month = month of year (1-12) 156 | // day = day of month 157 | // Purpose: decodes DateTime value to year-month-day. 158 | 159 | { 160 | int D1, D4, D100, D400; 161 | int y, m, d, i, k, t; 162 | 163 | D1 = 365; //365 164 | D4 = D1 * 4 + 1; //1461 165 | D100 = D4 * 25 - 1; //36524 166 | D400 = D100 * 4 + 1; //146097 167 | 168 | t = (int)(floor (date)) + DateDelta; 169 | if (t <= 0) 170 | { 171 | *year = 0; 172 | *month = 1; 173 | *day = 1; 174 | } 175 | else 176 | { 177 | t--; 178 | y = 1; 179 | while (t >= D400) 180 | { 181 | t -= D400; 182 | y += 400; 183 | } 184 | divMod(t, D100, &i, &d); 185 | if (i == 4) 186 | { 187 | i--; 188 | d += D100; 189 | } 190 | y += i*100; 191 | divMod(d, D4, &i, &d); 192 | y += i*4; 193 | divMod(d, D1, &i, &d); 194 | if (i == 4) 195 | { 196 | i--; 197 | d += D1; 198 | } 199 | y += i; 200 | k = isLeapYear(y); 201 | m = 1; 202 | for (;;) 203 | { 204 | i = DaysPerMonth[k][m-1]; 205 | if (d < i) break; 206 | d -= i; 207 | m++; 208 | } 209 | *year = y; 210 | *month = m; 211 | *day = d + 1; 212 | } 213 | } 214 | 215 | //============================================================================= 216 | 217 | void datetime_decodeTime(DateTime time, int* h, int* m, int* s) 218 | 219 | // Input: time = decimal fraction of a day 220 | // Output: h = hour of day (0-23) 221 | // m = minute of hour (0-59) 222 | // s = second of minute (0-59) 223 | // Purpose: decodes DateTime value to hour:minute:second. 224 | 225 | { 226 | int secs; 227 | int mins; 228 | secs = (int)(floor((time - floor(time))*SecsPerDay + 0.5)); 229 | divMod(secs, 60, &mins, s); 230 | divMod(mins, 60, h, m); 231 | if ( *h > 23 ) *h = 0; 232 | } 233 | 234 | //============================================================================= 235 | 236 | void DLLEXPORT datetime_dateToStr(DateTime date, char* s) 237 | 238 | // Input: date = encoded date/time value 239 | // Output: s = formatted date string 240 | // Purpose: represents DateTime date value as a formatted string. 241 | 242 | { 243 | int y, m, d; 244 | char dateStr[DATE_STR_SIZE]; 245 | datetime_decodeDate(date, &y, &m, &d); 246 | switch (DateFormat) 247 | { 248 | case Y_M_D: 249 | sprintf(dateStr, "%4d-%3s-%02d", y, MonthTxt[m-1], d); 250 | break; 251 | 252 | case M_D_Y: 253 | sprintf(dateStr, "%3s-%02d-%4d", MonthTxt[m-1], d, y); 254 | break; 255 | 256 | default: 257 | sprintf(dateStr, "%02d-%3s-%4d", d, MonthTxt[m-1], y); 258 | } 259 | strcpy(s, dateStr); 260 | } 261 | 262 | //============================================================================= 263 | 264 | void DLLEXPORT datetime_timeToStr(DateTime time, char* s) 265 | 266 | // Input: time = decimal fraction of a day 267 | // Output: s = time in hr:min:sec format 268 | // Purpose: represents DateTime time value as a formatted string. 269 | 270 | { 271 | int hr, min, sec; 272 | char timeStr[TIME_STR_SIZE]; 273 | datetime_decodeTime(time, &hr, &min, &sec); 274 | sprintf(timeStr, "%02d:%02d:%02d", hr, min, sec); 275 | strcpy(s, timeStr); 276 | } 277 | 278 | //============================================================================= 279 | 280 | int datetime_strToDate(char* s, DateTime* d) 281 | 282 | // Input: s = date as string 283 | // Output: d = encoded date; 284 | // returns 1 if conversion successful, 0 if not 285 | // Purpose: converts string date s to DateTime value. 286 | // 287 | { 288 | int yr = 0, mon = 0, day = 0, n; 289 | char month[4]; 290 | char sep1, sep2; 291 | *d = -DateDelta; 292 | if (strchr(s, '-') || strchr(s, '/')) 293 | { 294 | switch (DateFormat) 295 | { 296 | case Y_M_D: 297 | n = sscanf(s, "%d%c%d%c%d", &yr, &sep1, &mon, &sep2, &day); 298 | if ( n < 3 ) 299 | { 300 | mon = 0; 301 | n = sscanf(s, "%d%c%3s%c%d", &yr, &sep1, month, &sep2, &day); 302 | if ( n < 3 ) return 0; 303 | } 304 | break; 305 | 306 | case D_M_Y: 307 | n = sscanf(s, "%d%c%d%c%d", &day, &sep1, &mon, &sep2, &yr); 308 | if ( n < 3 ) 309 | { 310 | mon = 0; 311 | n = sscanf(s, "%d%c%3s%c%d", &day, &sep1, month, &sep2, &yr); 312 | if ( n < 3 ) return 0; 313 | } 314 | break; 315 | 316 | default: // M_D_Y 317 | n = sscanf(s, "%d%c%d%c%d", &mon, &sep1, &day, &sep2, &yr); 318 | if ( n < 3 ) 319 | { 320 | mon = 0; 321 | n = sscanf(s, "%3s%c%d%c%d", month, &sep1, &day, &sep2, &yr); 322 | if ( n < 3 ) return 0; 323 | } 324 | } 325 | if (mon == 0) mon = datetime_findMonth(month); 326 | *d = datetime_encodeDate(yr, mon, day); 327 | } 328 | if (*d == -DateDelta) return 0; 329 | else return 1; 330 | } 331 | 332 | //============================================================================= 333 | 334 | int datetime_strToTime(char* s, DateTime* t) 335 | 336 | // Input: s = time as string 337 | // Output: t = encoded time, 338 | // returns 1 if conversion successful, 0 if not 339 | // Purpose: converts a string time to a DateTime value. 340 | // Note: accepts time as hr:min:sec or as decimal hours. 341 | 342 | { 343 | int n, hr, min = 0, sec = 0; 344 | char *endptr; 345 | 346 | // Attempt to read time as decimal hours 347 | *t = strtod(s, &endptr); 348 | if ( *endptr == 0 ) 349 | { 350 | *t /= 24.0; 351 | return 1; 352 | } 353 | 354 | // Read time in hr:min:sec format 355 | *t = 0.0; 356 | n = sscanf(s, "%d:%d:%d", &hr, &min, &sec); 357 | if ( n == 0 ) return 0; 358 | *t = datetime_encodeTime(hr, min, sec); 359 | if ( (hr >= 0) && (min >= 0) && (sec >= 0) ) return 1; 360 | else return 0; 361 | } 362 | 363 | //============================================================================= 364 | 365 | void datetime_setDateFormat(int fmt) 366 | 367 | // Input: fmt = date format code 368 | // Output: none 369 | // Purpose: sets date format 370 | 371 | { 372 | if ( fmt >= Y_M_D && fmt <= M_D_Y) DateFormat = fmt; 373 | } 374 | 375 | //============================================================================= 376 | 377 | DateTime datetime_addSeconds(DateTime date1, double seconds) 378 | 379 | // Input: date1 = an encoded date/time value 380 | // seconds = number of seconds to add to date1 381 | // Output: returns updated value of date1 382 | // Purpose: adds a given number of seconds to a date/time. 383 | 384 | { 385 | double d = floor(date1); 386 | int h, m, s; 387 | datetime_decodeTime(date1, &h, &m, &s); 388 | return d + (3600.0*h + 60.0*m + s + seconds)/SecsPerDay; 389 | } 390 | 391 | //============================================================================= 392 | 393 | DateTime datetime_addDays(DateTime date1, DateTime date2) 394 | 395 | // Input: date1 = an encoded date/time value 396 | // date2 = decimal days to be added to date1 397 | // Output: returns date1 + date2 398 | // Purpose: adds a given number of decimal days to a date/time. 399 | 400 | { 401 | double d1 = floor(date1); 402 | double d2 = floor(date2); 403 | int h1, m1, s1; 404 | int h2, m2, s2; 405 | datetime_decodeTime(date1, &h1, &m1, &s1); 406 | datetime_decodeTime(date2, &h2, &m2, &s2); 407 | return d1 + d2 + datetime_encodeTime(h1+h2, m1+m2, s1+s2); 408 | } 409 | 410 | //============================================================================= 411 | 412 | long datetime_timeDiff(DateTime date1, DateTime date2) 413 | 414 | // Input: date1 = an encoded date/time value 415 | // date2 = an encoded date/time value 416 | // Output: returns date1 - date2 in seconds 417 | // Purpose: finds number of seconds between two dates. 418 | 419 | { 420 | double d1 = floor(date1); 421 | double d2 = floor(date2); 422 | int h, m, s; 423 | long s1, s2, secs; 424 | datetime_decodeTime(date1, &h, &m, &s); 425 | s1 = 3600*h + 60*m + s; 426 | datetime_decodeTime(date2, &h, &m, &s); 427 | s2 = 3600*h + 60*m + s; 428 | secs = (int)(floor((d1 - d2)*SecsPerDay + 0.5)); 429 | secs += (s1 - s2); 430 | return secs; 431 | } 432 | 433 | //============================================================================= 434 | 435 | int datetime_monthOfYear(DateTime date) 436 | 437 | // Input: date = an encoded date/time value 438 | // Output: returns index of month of year (1..12) 439 | // Purpose: finds month of year (Jan = 1 ...) for a given date. 440 | 441 | { 442 | int year, month, day; 443 | datetime_decodeDate(date, &year, &month, &day); 444 | return month; 445 | } 446 | 447 | //============================================================================= 448 | 449 | int datetime_dayOfYear(DateTime date) 450 | 451 | // Input: date = an encoded date/time value 452 | // Output: returns day of year (1..365) 453 | // Purpose: finds day of year (Jan 1 = 1) for a given date. 454 | 455 | { 456 | int year, month, day; 457 | DateTime startOfYear; 458 | datetime_decodeDate(date, &year, &month, &day); 459 | startOfYear = datetime_encodeDate(year, 1, 1); 460 | return (int)(floor(date - startOfYear)) + 1; 461 | } 462 | 463 | //============================================================================= 464 | 465 | int datetime_dayOfWeek(DateTime date) 466 | 467 | // Input: date = an encoded date/time value 468 | // Output: returns index of day of week (1..7) 469 | // Purpose: finds day of week (Sun = 1, ... Sat = 7) for a given date. 470 | 471 | { 472 | int t = (int)(floor(date)) + DateDelta; 473 | return (t % 7) + 1; 474 | } 475 | 476 | //============================================================================= 477 | 478 | int datetime_hourOfDay(DateTime date) 479 | 480 | // Input: date = an encoded date/time value 481 | // Output: returns hour of day (0..23) 482 | // Purpose: finds hour of day (0 = 12 AM, ..., 23 = 11 PM) for a given date. 483 | 484 | { 485 | int hour, min, sec; 486 | datetime_decodeTime(date, &hour, &min, &sec); 487 | return hour; 488 | } 489 | 490 | //============================================================================= 491 | 492 | int datetime_daysPerMonth(int year, int month) 493 | 494 | // Input: year = year in which month falls 495 | // month = month of year (1..12) 496 | // Output: returns number of days in the month 497 | // Purpose: finds number of days in a given month of a specified year. 498 | 499 | { 500 | if ( month < 1 || month > 12 ) return 0; 501 | return DaysPerMonth[isLeapYear(year)][month-1]; 502 | } 503 | 504 | //============================================================================= 505 | -------------------------------------------------------------------------------- /swmmoutputapi/src/datetime.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // datetime.h 3 | // 4 | // Project: EPA SWMM5 5 | // Version: 5.1 6 | // Date: 03/20/14 (Build 5.1.001) 7 | // Author: L. Rossman 8 | // 9 | // The DateTime type is used to store date and time values. It is 10 | // equivalent to a double floating point type. 11 | // 12 | // The integral part of a DateTime value is the number of days that have 13 | // passed since 12/31/1899. The fractional part of a DateTime value is the 14 | // fraction of a 24 hour day that has elapsed. 15 | //----------------------------------------------------------------------------- 16 | #undef WINDOWS 17 | #ifdef _WIN32 18 | #define WINDOWS 19 | #endif 20 | #ifdef __WIN32__ 21 | #define WINDOWS 22 | #endif 23 | 24 | /* 25 | #ifdef WINDOWS 26 | //#define DLLEXPORT __declspec(dllexport) __cdecl 27 | #define DLLEXPORT __declspec(dllexport) 28 | #else 29 | #define DLLEXPORT 30 | #endif 31 | */ 32 | #define DLLEXPORT __declspec(dllexport) __cdecl 33 | 34 | typedef double DateTime; 35 | 36 | #define Y_M_D 0 37 | #define M_D_Y 1 38 | #define D_M_Y 2 39 | #define NO_DATE -693594 // 1/1/0001 40 | #define DATE_STR_SIZE 12 41 | #define TIME_STR_SIZE 9 42 | 43 | // Functions for encoding a date or time value to a DateTime value 44 | DateTime datetime_encodeDate(int year, int month, int day); 45 | DateTime datetime_encodeTime(int hour, int minute, int second); 46 | 47 | // Functions for decoding a DateTime value to a date and time 48 | void datetime_decodeDate(DateTime date, int* y, int* m, int* d); 49 | void datetime_decodeTime(DateTime time, int* h, int* m, int* s); 50 | 51 | // Function for finding day of week for a date (1 = Sunday) 52 | // month of year, days per month, and hour of day 53 | int datetime_monthOfYear(DateTime date); 54 | int datetime_dayOfYear(DateTime date); 55 | int datetime_dayOfWeek(DateTime date); 56 | int datetime_hourOfDay(DateTime date); 57 | int datetime_daysPerMonth(int year, int month); 58 | 59 | // Functions for converting a DateTime value to a string 60 | void DLLEXPORT datetime_dateToStr(DateTime date, char* s); 61 | void DLLEXPORT datetime_timeToStr(DateTime time, char* s); 62 | 63 | // Functions for converting a string date or time to a DateTime value 64 | int datetime_findMonth(char* s); 65 | int datetime_strToDate(char* s, DateTime* d); 66 | int datetime_strToTime(char* s, DateTime* t); 67 | 68 | // Function for setting date format 69 | void datetime_setDateFormat(int fmt); 70 | 71 | // Functions for adding and subtracting dates 72 | DateTime datetime_addSeconds(DateTime date1, double seconds); 73 | DateTime datetime_addDays(DateTime date1, DateTime date2); 74 | long datetime_timeDiff(DateTime date1, DateTime date2); 75 | -------------------------------------------------------------------------------- /swmmoutputapi/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * TODO 4 | * Error handling from getID functions (and check other error handling) 5 | * 6 | */ 7 | 8 | #define _CRTDBG_MAP_ALLOC 9 | #include 10 | //#include 11 | 12 | 13 | 14 | #include 15 | //#include 16 | #include 17 | #include "outputAPI.h" 18 | 19 | 20 | 21 | 22 | #undef WINDOWS 23 | #ifdef _WIN32 24 | #define WINDOWS 25 | #endif 26 | #ifdef __WIN32__ 27 | #define WINDOWS 28 | #endif 29 | 30 | // #ifdef WINDOWS 31 | // #define DLLEXPORT __declspec(dllimport) __cdecl 32 | // #else 33 | // #define DLLEXPORT 34 | // #endif 35 | 36 | #undef DLLEXPORT 37 | 38 | int main(int argc, char* argv[]) 39 | { 40 | SMOutputAPI* smoapi = NULL; 41 | //char path[MAXFNAME] = "C:\\Users\\cbarr02\\Desktop\\GitHub\\Storm-Water-Plugin\\outputAPI\\Example3.out"; // no pollutants 42 | //char path[MAXFNAME] = "C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\OutputTestModel_LargeOutput.out"; 43 | char path[MAXFNAME] = "C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\OutputTestModel522_SHORT.out"; 44 | 45 | char pathout[MAXFNAME] = "C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\testingexeout.txt"; 46 | FILE *FOut; 47 | 48 | int count, count2, count3; 49 | //int units; 50 | //puts("Here"); 51 | //double time; 52 | int numperiods; 53 | 54 | float* array0; 55 | float* series0; 56 | //double* arraytime; 57 | //int errortime; 58 | //long alength0; 59 | long length; 60 | int error0;//, error1, error2, error3; 61 | //puts("Here1"); 62 | struct IDentry *subcatchids; 63 | //struct IDentry *nodeids; 64 | //struct IDentry *linkids; 65 | //struct IDentry *pollutids; 66 | 67 | int errBEM = SMR_open(path, &smoapi); 68 | printf("Here2 %i\n", errBEM); 69 | SMO_getProjectSize(smoapi, subcatchCount, &count); // 7 subcatchments 70 | printf("Subcatch Count: %i\n", count); 71 | SMO_getProjectSize(smoapi, nodeCount, &count2); // 12 junctions + 1 outfall + 1 storage 72 | printf("Node Count: %i\n", count2); 73 | SMO_getProjectSize(smoapi, linkCount, &count3); // 12 conduits + 3 orifices + 1 weir 74 | printf("Link Count: %i\n", count3); 75 | 76 | //SMO_getUnits(smoapi, flow_rate, &units); // 0 corresponds to CFS 77 | 78 | //SMO_getStartTime(smoapi, &time); // decimal days since 12 AM on 12/30/1899 79 | SMO_getTimes(smoapi, numPeriods, &numperiods); // report time step is 60 seconds 80 | //arraytime = SMO_newOutTimeList(smoapi, &errortime); 81 | //SMO_getTimeList(smoapi, arraytime); // first value will be start time + one reporting period (in decimal days) 82 | //puts("Here3"); 83 | series0 = SMO_newOutValueSeries(smoapi, 0, numperiods, &length, &error0); 84 | SMO_getLinkSeries(smoapi, 0, 0, 0, numperiods, series0); 85 | 86 | array0 = SMO_newOutValueArray(smoapi, getAttribute, link, &length, &error0); 87 | SMO_getLinkAttribute(smoapi, 1, 0, array0); 88 | 89 | //subcatchids = SMO_getSubcatchIDs(smoapi, &error0); 90 | //printf("Subcatch %i\n", error0); 91 | 92 | 93 | FOut = fopen(pathout,"w"); 94 | int i = 0; 95 | for(i = 0; i < numperiods; i++) 96 | { 97 | fprintf(FOut, "%d\t%f\n", i, series0[i]); 98 | } 99 | fclose(FOut); 100 | 101 | //nodeids = SMO_getNodeIDs(smoapi, &error1); 102 | //linkids = SMO_getLinkIDs(smoapi, &error2); 103 | //pollutids = SMO_getPollutIDs(smoapi, &error3); 104 | 105 | //SMO_free(array0); 106 | //puts("Here4"); 107 | //SMO_freeIDList(subcatchids); 108 | //SMO_freeIDList(nodeids); 109 | //SMO_freeIDList(linkids); 110 | //SMO_freeIDList(pollutids); 111 | 112 | //SMO_freeTimeList(arraytime); 113 | 114 | SMO_free(series0); 115 | 116 | SMO_close(smoapi); 117 | //puts("Here5"); 118 | //#ifdef WINDOWS 119 | // _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); 120 | // _CrtDumpMemoryLeaks(); 121 | // return 0; 122 | 123 | //#else 124 | 125 | return 0; 126 | 127 | //#endif 128 | } 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /swmmoutputapi/src/outputAPI.c: -------------------------------------------------------------------------------- 1 | /* 2 | * outputAPI.c 3 | * 4 | * Author: Colleen Barr 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "outputAPI.h" 13 | #include "datetime.h" 14 | 15 | 16 | // NOTE: These depend on machine data model and may change when porting 17 | #define F_OFF off64_t // Must be a 8 byte / 64 bit integer for large file support 18 | #define INT4 int // Must be a 4 byte / 32 bit integer type 19 | #define REAL4 float // Must be a 4 byte / 32 bit real type 20 | 21 | #define RECORDSIZE 4 // Memory alignment 4 byte word size for both int and real 22 | #define DATESIZE 8 // Dates are stored as 8 byte word size 23 | 24 | #define MEMCHECK(x) (((x) == NULL) ? 411 : 0 ) 25 | 26 | struct IDentry { 27 | char* IDname; 28 | int length; 29 | }; 30 | typedef struct IDentry idEntry; 31 | 32 | //----------------------------------------------------------------------------- 33 | // Shared variables 34 | //----------------------------------------------------------------------------- 35 | 36 | struct SMOutputAPI { 37 | char name[MAXFILENAME + 1]; // file path/name 38 | FILE* file; // FILE structure pointer 39 | 40 | struct IDentry *elementNames; // array of pointers to element names 41 | 42 | long Nperiods; // number of reporting periods 43 | int FlowUnits; // flow units code 44 | 45 | int Nsubcatch; // number of subcatchments 46 | int Nnodes; // number of drainage system nodes 47 | int Nlinks; // number of drainage system links 48 | int Npolluts; // number of pollutants tracked 49 | 50 | int SubcatchVars; // number of subcatch reporting variables 51 | int NodeVars; // number of node reporting variables 52 | int LinkVars; // number of link reporting variables 53 | int SysVars; // number of system reporting variables 54 | 55 | double StartDate; // start date of simulation 56 | int ReportStep; // reporting time step (seconds) 57 | 58 | F_OFF IDPos; // file position where object ID names start 59 | F_OFF ObjPropPos; // file position where object properties start 60 | F_OFF ResultsPos; // file position where results start 61 | F_OFF BytesPerPeriod; // bytes used for results in each period 62 | }; 63 | 64 | //----------------------------------------------------------------------------- 65 | // Local functions 66 | //----------------------------------------------------------------------------- 67 | int validateFile(SMOutputAPI* smoapi); 68 | void initElementNames(SMOutputAPI* smoapi); 69 | 70 | double getTimeValue(SMOutputAPI* smoapi, long timeIndex); 71 | float getSubcatchValue(SMOutputAPI* smoapi, long timeIndex, int subcatchIndex, SMO_subcatchAttribute attr); 72 | float getNodeValue(SMOutputAPI* smoapi, long timeIndex, int nodeIndex, SMO_nodeAttribute attr); 73 | float getLinkValue(SMOutputAPI* smoapi, long timeIndex, int linkIndex, SMO_linkAttribute attr); 74 | float getSystemValue(SMOutputAPI* smoapi, long timeIndex, SMO_systemAttribute attr); 75 | 76 | //void AddIDentry(struct IDentry* head, char* idname, int numChar); 77 | 78 | 79 | SMOutputAPI* DLLEXPORT SMO_init(void) 80 | // 81 | // Purpose: Returns an initialized pointer for the opaque SMOutputAPI 82 | // structure. 83 | // 84 | { 85 | SMOutputAPI *smoapi = malloc(sizeof(struct SMOutputAPI)); 86 | smoapi->elementNames = NULL; 87 | 88 | return smoapi; 89 | } 90 | 91 | int DLLEXPORT SMO_open(SMOutputAPI* smoapi, const char* path) 92 | // 93 | // Purpose: Open the output binary file and read epilogue. 94 | // 95 | { 96 | int version, err, errorcode = 0; 97 | F_OFF offset; 98 | 99 | strncpy(smoapi->name, path, MAXFILENAME); 100 | 101 | // --- open the output file 102 | if ((smoapi->file = fopen(path, "rb")) == NULL) errorcode = 434; 103 | // --- validate the output file 104 | else if ((err = validateFile(smoapi)) != 0) errorcode = err; 105 | 106 | else { 107 | // --- otherwise read additional parameters from start of file 108 | fread(&version, RECORDSIZE, 1, smoapi->file); 109 | fread(&(smoapi->FlowUnits), RECORDSIZE, 1, smoapi->file); 110 | fread(&(smoapi->Nsubcatch), RECORDSIZE, 1, smoapi->file); 111 | fread(&(smoapi->Nnodes), RECORDSIZE, 1, smoapi->file); 112 | fread(&(smoapi->Nlinks), RECORDSIZE, 1, smoapi->file); 113 | fread(&(smoapi->Npolluts), RECORDSIZE, 1, smoapi->file); 114 | 115 | // Skip over saved subcatch/node/link input values 116 | offset = (smoapi->Nsubcatch + 2) * RECORDSIZE // Subcatchment area 117 | + (3 * smoapi->Nnodes + 4) * RECORDSIZE // Node type, invert & max depth 118 | + (5 * smoapi->Nlinks + 6) * RECORDSIZE; // Link type, z1, z2, max depth & length 119 | offset += smoapi->ObjPropPos; 120 | 121 | fseeko64(smoapi->file, offset, SEEK_SET); 122 | 123 | // Read number & codes of computed variables 124 | fread(&(smoapi->SubcatchVars), RECORDSIZE, 1, smoapi->file); // # Subcatch variables 125 | fseeko64(smoapi->file, smoapi->SubcatchVars*RECORDSIZE, SEEK_CUR); 126 | fread(&(smoapi->NodeVars), RECORDSIZE, 1, smoapi->file); // # Node variables 127 | fseeko64(smoapi->file, smoapi->NodeVars*RECORDSIZE, SEEK_CUR); 128 | fread(&(smoapi->LinkVars), RECORDSIZE, 1, smoapi->file); // # Link variables 129 | fseeko64(smoapi->file, smoapi->LinkVars*RECORDSIZE, SEEK_CUR); 130 | fread(&(smoapi->SysVars), RECORDSIZE, 1, smoapi->file); // # System variables 131 | 132 | // --- read data just before start of output results 133 | offset = smoapi->ResultsPos - 3 * RECORDSIZE; 134 | fseeko64(smoapi->file, offset, SEEK_SET); 135 | fread(&(smoapi->StartDate), DATESIZE, 1, smoapi->file); 136 | fread(&(smoapi->ReportStep), RECORDSIZE, 1, smoapi->file); 137 | 138 | // --- compute number of bytes of results values used per time period 139 | smoapi->BytesPerPeriod = DATESIZE + // date value (a double) 140 | (smoapi->Nsubcatch*smoapi->SubcatchVars + 141 | smoapi->Nnodes*smoapi->NodeVars + 142 | smoapi->Nlinks*smoapi->LinkVars + 143 | smoapi->SysVars)*RECORDSIZE; 144 | } 145 | 146 | if (errorcode) SMO_close(smoapi); 147 | 148 | return errorcode; 149 | 150 | } 151 | 152 | 153 | int DLLEXPORT SMO_getProjectSize(SMOutputAPI* smoapi, SMO_elementCount code, int* count) 154 | // 155 | // Purpose: Returns project size. 156 | // 157 | { 158 | int errorcode = 0; 159 | 160 | *count = -1; 161 | if (smoapi->file == NULL) errorcode = 412; 162 | else 163 | { 164 | switch (code) 165 | { 166 | case subcatchCount: *count = smoapi->Nsubcatch; 167 | break; 168 | case nodeCount: *count = smoapi->Nnodes; 169 | break; 170 | case linkCount: *count = smoapi->Nlinks; 171 | break; 172 | case pollutantCount: *count = smoapi->Npolluts; 173 | break; 174 | default: errorcode = 421; 175 | } 176 | } 177 | 178 | return errorcode; 179 | } 180 | 181 | 182 | int DLLEXPORT SMO_getUnits(SMOutputAPI* smoapi, SMO_unit code, int* unitFlag) 183 | // 184 | // Purpose: Returns flow rate units. 185 | // 186 | // Note: Concentration units are located after the pollutant ID names and before the object properties start, 187 | // and can differ for each pollutant. They're stored as 4-byte integers with the following codes: 188 | // 0: mg/L 189 | // 1: ug/L 190 | // 2: counts/L 191 | // Probably the best way to do this would not be here -- instead write a function that takes 192 | // NPolluts and ObjPropPos, jump to ObjPropPos, count backward (NPolluts * 4), then read forward 193 | // to get the units for each pollutant 194 | // 195 | { 196 | int errorcode = 0; 197 | 198 | *unitFlag = -1; 199 | if (smoapi->file == NULL) errorcode = 412; 200 | else 201 | { 202 | switch (code) 203 | { 204 | case flow_rate: *unitFlag = smoapi->FlowUnits; 205 | break; 206 | // case concentration: *unitFlag = ConcUnits; 207 | // break; 208 | default: errorcode = 421; 209 | } 210 | } 211 | 212 | return errorcode; 213 | } 214 | 215 | int DLLEXPORT SMO_getStartTime(SMOutputAPI* smoapi, double* time) 216 | // 217 | // Purpose: Returns start date. 218 | // 219 | { 220 | int errorcode = 0; 221 | 222 | *time = -1; 223 | if (smoapi->file == NULL) errorcode = 412; 224 | else 225 | *time = smoapi->StartDate; 226 | 227 | return errorcode; 228 | } 229 | 230 | 231 | int DLLEXPORT SMO_getTimes(SMOutputAPI* smoapi, SMO_time code, int* time) 232 | // 233 | // Purpose: Returns step size and number of periods. 234 | // 235 | { 236 | int errorcode = 0; 237 | 238 | *time = -1; 239 | if (smoapi->file == NULL) errorcode = 412; 240 | else 241 | { 242 | switch (code) 243 | { 244 | case reportStep: *time = smoapi->ReportStep; 245 | break; 246 | case numPeriods: *time = smoapi->Nperiods; 247 | break; 248 | default: errorcode = 421; 249 | } 250 | } 251 | 252 | return errorcode; 253 | } 254 | 255 | int DLLEXPORT SMO_getElementName(SMOutputAPI* smoapi, SMO_elementType type, 256 | int index, char* name, int* length) 257 | // 258 | // Purpose: Given an element index returns the element name. 259 | // 260 | // Note: The caller is responsible for allocating memory for the char array 261 | // name. The caller passes the length of the array allocated and the length 262 | // of the name requested is returned. The name may be truncated if an array of 263 | // adequate length is not passed. 264 | // 265 | { 266 | int idx, errorcode = 0; 267 | 268 | // Initialize the name array if necessary 269 | if (smoapi->elementNames == NULL) initElementNames(smoapi); 270 | 271 | switch (type) 272 | { 273 | case subcatch: if (index < 0 || index >= smoapi->Nsubcatch) errorcode = 423; 274 | else idx = index; 275 | break; 276 | case node: if (index < 0 || index >= smoapi->Nnodes) errorcode = 423; 277 | else idx = smoapi->Nsubcatch + index; 278 | break; 279 | case link: if (index < 0 || index >= smoapi->Nlinks) errorcode = 423; 280 | else idx = smoapi->Nsubcatch + smoapi->Nnodes + index; 281 | break; 282 | case sys: if (index < 0 || index >= smoapi->Npolluts) errorcode = 423; 283 | else idx = smoapi->Nsubcatch + smoapi->Nnodes + smoapi->Nlinks + index; 284 | break; 285 | default: errorcode = 421; 286 | } 287 | 288 | if (!errorcode) { 289 | strncpy(name, smoapi->elementNames[idx].IDname, *length); 290 | 291 | *length = smoapi->elementNames[idx].length; 292 | } 293 | return errorcode; 294 | } 295 | 296 | 297 | float* DLLEXPORT SMO_newOutValueSeries(SMOutputAPI* smoapi, long seriesStart, 298 | long seriesLength, long* length, int* errcode) 299 | // 300 | // Purpose: Allocates memory for outValue Series. 301 | // 302 | // Warning: Caller must free memory allocated by this function using SMO_free(). 303 | // 304 | { 305 | long size; 306 | float* array; 307 | 308 | if (smoapi->file == NULL) *errcode = 412; 309 | else 310 | { 311 | size = seriesLength - seriesStart; 312 | if (size > smoapi->Nperiods) 313 | size = smoapi->Nperiods; 314 | 315 | array = (float*)calloc(size, sizeof(float)); 316 | *errcode = (MEMCHECK(array)); 317 | 318 | *length = size; 319 | return array; 320 | } 321 | 322 | return NULL; 323 | } 324 | 325 | 326 | float* DLLEXPORT SMO_newOutValueArray(SMOutputAPI* smoapi, SMO_apiFunction func, 327 | SMO_elementType type, long* length, int* errcode) 328 | // 329 | // Purpose: Allocates memory for outValue Array. 330 | // 331 | // Warning: Caller must free memory allocated by this function using SMO_free(). 332 | // 333 | { 334 | long size; 335 | float* array; 336 | 337 | if (smoapi->file == NULL) *errcode = 412; 338 | else 339 | { 340 | switch (func) 341 | { 342 | case getAttribute: 343 | if (type == subcatch) 344 | size = smoapi->Nsubcatch; 345 | else if (type == node) 346 | size = smoapi->Nnodes; 347 | else if (type == link) 348 | size = smoapi->Nlinks; 349 | else // system 350 | size = 1; 351 | break; 352 | 353 | case getResult: 354 | if (type == subcatch) 355 | size = smoapi->SubcatchVars; 356 | else if (type == node) 357 | size = smoapi->NodeVars; 358 | else if (type == link) 359 | size = smoapi->LinkVars; 360 | else // system 361 | size = smoapi->SysVars; 362 | break; 363 | 364 | default: *errcode = 421; 365 | return NULL; 366 | } 367 | 368 | // Allocate memory for outValues 369 | array = (float*)calloc(size, sizeof(float)); 370 | *errcode = (MEMCHECK(array)); 371 | 372 | *length = size; 373 | return array; 374 | } 375 | 376 | return NULL; 377 | } 378 | 379 | 380 | int DLLEXPORT SMO_getSubcatchSeries(SMOutputAPI* smoapi, int subcatchIndex, 381 | SMO_subcatchAttribute attr, long timeIndex, long length, float* outValueSeries) 382 | // 383 | // Purpose: Get time series results for particular attribute. Specify series 384 | // start and length using timeIndex and length respectively. 385 | // 386 | { 387 | int errorcode = 0; 388 | 389 | long k; 390 | 391 | if (smoapi->file == NULL) errorcode = 412; 392 | else if (outValueSeries == NULL) errorcode = 411; 393 | else 394 | { 395 | // loop over and build time series 396 | for (k = 0; k < length; k++) 397 | outValueSeries[k] = getSubcatchValue(smoapi, timeIndex + k, 398 | subcatchIndex, attr); 399 | } 400 | 401 | return errorcode; 402 | } 403 | 404 | 405 | int DLLEXPORT SMO_getNodeSeries(SMOutputAPI* smoapi, int nodeIndex, SMO_nodeAttribute attr, 406 | long timeIndex, long length, float* outValueSeries) 407 | // 408 | // Purpose: Get time series results for particular attribute. Specify series 409 | // start and length using timeIndex and length respectively. 410 | // 411 | { 412 | int errorcode = 0; 413 | 414 | long k; 415 | 416 | if (smoapi->file == NULL) errorcode = 412; 417 | else if (outValueSeries == NULL) errorcode = 411; 418 | else 419 | { 420 | // loop over and build time series 421 | for (k = 0; k < length; k++) 422 | outValueSeries[k] = getNodeValue(smoapi, timeIndex + k, 423 | nodeIndex, attr); 424 | } 425 | 426 | return errorcode; 427 | } 428 | 429 | 430 | int DLLEXPORT SMO_getLinkSeries(SMOutputAPI* smoapi, int linkIndex, SMO_linkAttribute attr, 431 | long timeIndex, long length, float* outValueSeries) 432 | // 433 | // Purpose: Get time series results for particular attribute. Specify series 434 | // start and length using timeIndex and length respectively. 435 | // 436 | { 437 | int errorcode = 0; 438 | 439 | long k; 440 | 441 | if (smoapi->file == NULL) errorcode = 412; 442 | else if (outValueSeries == NULL) errorcode = 411; 443 | else 444 | { 445 | // loop over and build time series 446 | for (k = 0; k < length; k++) 447 | outValueSeries[k] = getLinkValue(smoapi, timeIndex + k, linkIndex, attr); 448 | } 449 | 450 | return errorcode; 451 | } 452 | 453 | 454 | 455 | int DLLEXPORT SMO_getSystemSeries(SMOutputAPI* smoapi, SMO_systemAttribute attr, 456 | long timeIndex, long length, float *outValueSeries) 457 | // 458 | // Purpose: Get time series results for particular attribute. Specify series 459 | // start and length using timeIndex and length respectively. 460 | // 461 | { 462 | int errorcode = 0; 463 | 464 | long k; 465 | 466 | if (smoapi->file == NULL) errorcode = 412; 467 | else if (outValueSeries == NULL) errorcode = 411; 468 | else 469 | { 470 | // loop over and build time series 471 | for (k = 0; k < length; k++) 472 | outValueSeries[k] = getSystemValue(smoapi, timeIndex + k, attr); 473 | } 474 | 475 | return errorcode; 476 | } 477 | 478 | int DLLEXPORT SMO_getSubcatchAttribute(SMOutputAPI* smoapi, long timeIndex, 479 | SMO_subcatchAttribute attr, float* outValueArray) 480 | // 481 | // Purpose: For all subcatchments at given time, get a particular attribute. 482 | // 483 | { 484 | int errorcode = 0; 485 | 486 | long k; 487 | 488 | if (smoapi->file == NULL) errorcode = 412; 489 | else if (outValueArray == NULL) errorcode = 411; 490 | else 491 | { 492 | // loop over and pull result 493 | for (k = 0; k < smoapi->Nsubcatch; k++) 494 | outValueArray[k] = getSubcatchValue(smoapi, timeIndex, k, attr); 495 | } 496 | 497 | return errorcode; 498 | } 499 | 500 | 501 | 502 | int DLLEXPORT SMO_getNodeAttribute(SMOutputAPI* smoapi, long timeIndex, 503 | SMO_nodeAttribute attr, float* outValueArray) 504 | // 505 | // Purpose: For all nodes at given time, get a particular attribute. 506 | // 507 | { 508 | int errorcode = 0; 509 | 510 | long k; 511 | 512 | if (smoapi->file == NULL) errorcode = 412; 513 | else if (outValueArray == NULL) errorcode = 411; 514 | else 515 | { 516 | // loop over and pull result 517 | for (k = 0; k < smoapi->Nnodes; k++) 518 | outValueArray[k] = getNodeValue(smoapi, timeIndex, k, attr); 519 | } 520 | 521 | return errorcode; 522 | } 523 | 524 | int DLLEXPORT SMO_getLinkAttribute(SMOutputAPI* smoapi, long timeIndex, 525 | SMO_linkAttribute attr, float* outValueArray) 526 | // 527 | // Purpose: For all links at given time, get a particular attribute. 528 | // 529 | { 530 | int errorcode = 0; 531 | 532 | long k; 533 | 534 | if (smoapi->file == NULL) errorcode = 412; 535 | else if (outValueArray == NULL) errorcode = 411; 536 | else 537 | { 538 | // loop over and pull result 539 | for (k = 0; k < smoapi->Nlinks; k++) 540 | outValueArray[k] = getLinkValue(smoapi, timeIndex, k, attr); 541 | } 542 | 543 | return errorcode; 544 | } 545 | 546 | 547 | int DLLEXPORT SMO_getSystemAttribute(SMOutputAPI* smoapi, long timeIndex, 548 | SMO_systemAttribute attr, float* outValueArray) 549 | // 550 | // Purpose: For the system at given time, get a particular attribute. 551 | // 552 | { 553 | int errorcode = 0; 554 | 555 | if (smoapi->file == NULL) errorcode = 412; 556 | else if (outValueArray == NULL) errorcode = 411; 557 | else 558 | { 559 | // don't need to loop since there's only one system 560 | outValueArray[0] = getSystemValue(smoapi, timeIndex, attr); 561 | } 562 | 563 | return errorcode; 564 | } 565 | 566 | int DLLEXPORT SMO_getSubcatchResult(SMOutputAPI* smoapi, long timeIndex, int subcatchIndex, 567 | float* outValueArray) 568 | // 569 | // Purpose: For a subcatchment at given time, get all attributes. 570 | // 571 | { 572 | int errorcode = 0; 573 | 574 | F_OFF offset; 575 | 576 | if (smoapi->file == NULL) errorcode = 412; 577 | else if (outValueArray == NULL) errorcode = 411; 578 | else 579 | { 580 | // --- compute offset into output file 581 | offset = smoapi->ResultsPos + (timeIndex)*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 582 | // add offset for subcatchment 583 | offset += (subcatchIndex*smoapi->SubcatchVars)*RECORDSIZE; 584 | 585 | fseeko64(smoapi->file, offset, SEEK_SET); 586 | fread(outValueArray, RECORDSIZE, smoapi->SubcatchVars, smoapi->file); 587 | } 588 | 589 | return errorcode; 590 | } 591 | 592 | 593 | int DLLEXPORT SMO_getNodeResult(SMOutputAPI* smoapi, long timeIndex, int nodeIndex, 594 | float* outValueArray) 595 | // 596 | // Purpose: For a node at given time, get all attributes. 597 | // 598 | { 599 | int errorcode = 0; 600 | 601 | F_OFF offset; 602 | 603 | if (smoapi->file == NULL) errorcode = 412; 604 | else if (outValueArray == NULL) errorcode = 411; 605 | else 606 | { 607 | // calculate byte offset to start time for series 608 | offset = smoapi->ResultsPos + (timeIndex)*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 609 | // add offset for subcatchment and node 610 | offset += (smoapi->Nsubcatch*smoapi->SubcatchVars + nodeIndex*smoapi->NodeVars)*RECORDSIZE; 611 | 612 | fseeko64(smoapi->file, offset, SEEK_SET); 613 | fread(outValueArray, RECORDSIZE, smoapi->NodeVars, smoapi->file); 614 | } 615 | 616 | return errorcode; 617 | } 618 | 619 | 620 | int DLLEXPORT SMO_getLinkResult(SMOutputAPI* smoapi, long timeIndex, int linkIndex, 621 | float* outValueArray) 622 | // 623 | // Purpose: For a link at given time, get all attributes. 624 | // 625 | { 626 | int errorcode = 0; 627 | 628 | F_OFF offset; 629 | 630 | if (smoapi->file == NULL) errorcode = 412; 631 | else if (outValueArray == NULL) errorcode = 411; 632 | else 633 | { 634 | // calculate byte offset to start time for series 635 | offset = smoapi->ResultsPos + (timeIndex)*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 636 | // add offset for subcatchment and node and link 637 | offset += (smoapi->Nsubcatch*smoapi->SubcatchVars 638 | + smoapi->Nnodes*smoapi->NodeVars + linkIndex*smoapi->LinkVars)*RECORDSIZE; 639 | 640 | fseeko64(smoapi->file, offset, SEEK_SET); 641 | fread(outValueArray, RECORDSIZE, smoapi->LinkVars, smoapi->file); 642 | } 643 | 644 | return errorcode; 645 | } 646 | 647 | int DLLEXPORT SMO_getSystemResult(SMOutputAPI* smoapi, long timeIndex, float* outValueArray) 648 | // 649 | // Purpose: For the system at given time, get all attributes. 650 | // 651 | { 652 | int errorcode = 0; 653 | 654 | F_OFF offset; 655 | 656 | if (smoapi->file == NULL) errorcode = 412; 657 | else if (outValueArray == NULL) errorcode = 411; 658 | { 659 | // calculate byte offset to start time for series 660 | offset = smoapi->ResultsPos + (timeIndex)*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 661 | // add offset for subcatchment and node and link (system starts after the last link) 662 | offset += (smoapi->Nsubcatch*smoapi->SubcatchVars + smoapi->Nnodes*smoapi->NodeVars 663 | + smoapi->Nlinks*smoapi->LinkVars)*RECORDSIZE; 664 | 665 | fseeko64(smoapi->file, offset, SEEK_SET); 666 | fread(outValueArray, RECORDSIZE, smoapi->SysVars, smoapi->file); 667 | } 668 | 669 | return errorcode; 670 | } 671 | 672 | void DLLEXPORT SMO_free(float *array) 673 | // 674 | // Purpose: frees memory allocated using SMO_newOutValueSeries() or 675 | // SMO_newOutValueArray(). 676 | // 677 | { 678 | if (array != NULL) 679 | free(array); 680 | } 681 | 682 | 683 | int DLLEXPORT SMO_close(SMOutputAPI* smoapi) 684 | // 685 | // Purpose: Clean up after and close Output API 686 | // 687 | { 688 | int i, n, errorcode = 0; 689 | 690 | if (smoapi->file == NULL) errorcode = 412; 691 | else 692 | { 693 | if (smoapi->elementNames != NULL) 694 | { 695 | n = smoapi->Nsubcatch + smoapi->Nnodes + smoapi->Nlinks + smoapi->Npolluts; 696 | 697 | for(i = 0; i < n; i++) 698 | free(smoapi->elementNames[i].IDname); 699 | } 700 | 701 | fclose(smoapi->file); 702 | free(smoapi); 703 | smoapi = NULL; 704 | } 705 | 706 | return errorcode; 707 | } 708 | 709 | int DLLEXPORT SMO_errMessage(int errcode, char* errmsg, int n) 710 | // 711 | // Purpose: takes error code returns error message 712 | // 713 | // Input Error 411: no memory allocated for results 714 | // Input Error 412: no results binary file hasn't been opened 715 | // Input Error 421: invalid parameter code 716 | // File Error 434: unable to open binary output file 717 | // File Error 435: run terminated no results in binary file 718 | { 719 | switch (errcode) 720 | { 721 | case 411: strncpy(errmsg, ERR411, n); break; 722 | case 412: strncpy(errmsg, ERR412, n); break; 723 | case 421: strncpy(errmsg, ERR421, n); break; 724 | case 434: strncpy(errmsg, ERR434, n); break; 725 | case 435: strncpy(errmsg, ERR435, n); break; 726 | default: return 421; 727 | } 728 | 729 | return 0; 730 | } 731 | 732 | 733 | // Local functions: 734 | int validateFile(SMOutputAPI* smoapi) 735 | { 736 | INT4 magic1, magic2, errcode; 737 | int errorcode = 0; 738 | 739 | // --- fast forward to end and read epilogue 740 | fseeko64(smoapi->file, -6 * RECORDSIZE, SEEK_END); 741 | fread(&(smoapi->IDPos), RECORDSIZE, 1, smoapi->file); 742 | fread(&(smoapi->ObjPropPos), RECORDSIZE, 1, smoapi->file); 743 | fread(&(smoapi->ResultsPos), RECORDSIZE, 1, smoapi->file); 744 | fread(&(smoapi->Nperiods), RECORDSIZE, 1, smoapi->file); 745 | fread(&errcode, RECORDSIZE, 1, smoapi->file); 746 | fread(&magic2, RECORDSIZE, 1, smoapi->file); 747 | 748 | // --- read magic number from beginning of the file 749 | fseeko64(smoapi->file, 0L, SEEK_SET); 750 | fread(&magic1, RECORDSIZE, 1, smoapi->file); 751 | 752 | // Is this a valid SWMM binary output file? 753 | if (magic1 != magic2) errorcode = 435; 754 | // Does the binary file contain results? 755 | else if (smoapi->Nperiods <= 0) errorcode = 436; 756 | // Were there problems with the model run? 757 | else if (errcode != 0) errorcode = 435; 758 | 759 | return errorcode; 760 | } 761 | 762 | void initElementNames(SMOutputAPI* smoapi) 763 | { 764 | int j, numNames; 765 | 766 | numNames = smoapi->Nsubcatch + smoapi->Nnodes + smoapi->Nlinks + smoapi->Npolluts; 767 | 768 | // allocate memory for array of idEntries 769 | smoapi->elementNames = (idEntry*)calloc(numNames, sizeof(idEntry)); 770 | 771 | // Position the file to the start of the ID entries 772 | fseeko64(smoapi->file, smoapi->IDPos, SEEK_SET); 773 | 774 | for(j=0;jelementNames[j].length), RECORDSIZE, 1, smoapi->file); 777 | smoapi->elementNames[j].IDname = calloc(smoapi->elementNames[j].length + 1, sizeof(char)); 778 | fread(smoapi->elementNames[j].IDname, sizeof(char), smoapi->elementNames[j].length, smoapi->file); 779 | } 780 | } 781 | 782 | double getTimeValue(SMOutputAPI* smoapi, long timeIndex) 783 | { 784 | F_OFF offset; 785 | double value; 786 | 787 | // --- compute offset into output file 788 | offset = smoapi->ResultsPos + timeIndex*smoapi->BytesPerPeriod; 789 | 790 | // --- re-position the file and read the result 791 | fseeko64(smoapi->file, offset, SEEK_SET); 792 | fread(&value, RECORDSIZE * 2, 1, smoapi->file); 793 | 794 | return value; 795 | } 796 | 797 | float getSubcatchValue(SMOutputAPI* smoapi, long timeIndex, int subcatchIndex, 798 | SMO_subcatchAttribute attr) 799 | { 800 | F_OFF offset; 801 | float value; 802 | 803 | // --- compute offset into output file 804 | offset = smoapi->ResultsPos + timeIndex*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 805 | // offset for subcatch 806 | offset += RECORDSIZE*(subcatchIndex*smoapi->SubcatchVars + attr); 807 | 808 | // --- re-position the file and read the result 809 | fseeko64(smoapi->file, offset, SEEK_SET); 810 | fread(&value, RECORDSIZE, 1, smoapi->file); 811 | 812 | return value; 813 | } 814 | 815 | float getNodeValue(SMOutputAPI* smoapi, long timeIndex, int nodeIndex, 816 | SMO_nodeAttribute attr) 817 | { 818 | F_OFF offset; 819 | float value; 820 | 821 | // --- compute offset into output file 822 | offset = smoapi->ResultsPos + timeIndex*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 823 | // offset for node 824 | offset += RECORDSIZE*(smoapi->Nsubcatch*smoapi->SubcatchVars + nodeIndex*smoapi->NodeVars + attr); 825 | 826 | // --- re-position the file and read the result 827 | fseeko64(smoapi->file, offset, SEEK_SET); 828 | fread(&value, RECORDSIZE, 1, smoapi->file); 829 | 830 | return value; 831 | } 832 | 833 | 834 | float getLinkValue(SMOutputAPI* smoapi, long timeIndex, int linkIndex, 835 | SMO_linkAttribute attr) 836 | { 837 | F_OFF offset; 838 | float value; 839 | 840 | // --- compute offset into output file 841 | offset = smoapi->ResultsPos + timeIndex*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 842 | // offset for link 843 | offset += RECORDSIZE*(smoapi->Nsubcatch*smoapi->SubcatchVars + smoapi->Nnodes*smoapi->NodeVars + 844 | linkIndex*smoapi->LinkVars + attr); 845 | 846 | // --- re-position the file and read the result 847 | fseeko64(smoapi->file, offset, SEEK_SET); 848 | fread(&value, RECORDSIZE, 1, smoapi->file); 849 | 850 | return value; 851 | } 852 | 853 | float getSystemValue(SMOutputAPI* smoapi, long timeIndex, 854 | SMO_systemAttribute attr) 855 | { 856 | F_OFF offset; 857 | float value; 858 | 859 | // --- compute offset into output file 860 | offset = smoapi->ResultsPos + timeIndex*smoapi->BytesPerPeriod + 2 * RECORDSIZE; 861 | // offset for system 862 | offset += RECORDSIZE*(smoapi->Nsubcatch*smoapi->SubcatchVars + smoapi->Nnodes*smoapi->NodeVars + 863 | smoapi->Nlinks*smoapi->LinkVars + attr); 864 | 865 | // --- re-position the file and read the result 866 | fseeko64(smoapi->file, offset, SEEK_SET); 867 | fread(&value, RECORDSIZE, 1, smoapi->file); 868 | 869 | return value; 870 | } 871 | -------------------------------------------------------------------------------- /swmmoutputapi/src/outputAPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * outputAPI.h 3 | * 4 | * Author: Colleen Barr 5 | * 6 | * 7 | */ 8 | 9 | #ifndef OUTPUTAPI_H_ 10 | #define OUTPUTAPI_H_ 11 | 12 | #undef WINDOWS 13 | #ifdef _WIN32 14 | #define WINDOWS 15 | #endif 16 | #ifdef __WIN32__ 17 | #define WINDOWS 18 | #endif 19 | 20 | /* 21 | //#define DLLEXPORT __declspec(dllexport) __cdecl 22 | #ifdef WINDOWS 23 | #define DLLEXPORT __declspec(dllexport) 24 | #else 25 | #define DLLEXPORT 26 | #endif 27 | */ 28 | #define DLLEXPORT __declspec(dllexport) __cdecl 29 | 30 | #define MAXFILENAME 259 // 31 | #define MAXELENAME 45 // Max characters in element name 32 | 33 | #include 34 | 35 | 36 | /*------------------- Error Messages --------------------*/ 37 | #define ERR411 "Input Error 411: no memory allocated for results." 38 | #define ERR412 "Input Error 412: no results; binary file hasn't been opened." 39 | #define ERR421 "Input Error 421: invalid parameter code." 40 | #define ERR434 "File Error 434: unable to open binary output file." 41 | #define ERR435 "File Error 435: run terminated; no results in binary file." 42 | #define ERR441 "Error 441: need to call SMO_open before calling this function" 43 | 44 | typedef struct SMOutputAPI SMOutputAPI; // opaque pointer 45 | 46 | typedef enum { 47 | subcatchCount, 48 | nodeCount, 49 | linkCount, 50 | pollutantCount 51 | 52 | } SMO_elementCount; 53 | 54 | typedef enum { 55 | flow_rate, 56 | concentration 57 | 58 | } SMO_unit; 59 | 60 | typedef enum { 61 | //getSeries, 62 | getAttribute, 63 | getResult 64 | 65 | } SMO_apiFunction; 66 | 67 | typedef enum { 68 | subcatch, 69 | node, 70 | link, 71 | sys 72 | 73 | } SMO_elementType; 74 | 75 | typedef enum { 76 | // reportStart, 77 | reportStep, 78 | numPeriods 79 | 80 | } SMO_time; 81 | 82 | typedef enum { 83 | rainfall_subcatch, // (in/hr or mm/hr), 84 | snow_depth_subcatch, // (in or mm), 85 | evap_loss, // (in/hr or mm/hr), 86 | infil_loss, // (in/hr or mm/hr), 87 | runoff_rate, // (flow units), 88 | gwoutflow_rate, // (flow units), 89 | gwtable_elev, // (ft or m), 90 | soil_moisture, // unsaturated zone moisture content (-), 91 | pollutant_conc_subcatch // first pollutant 92 | 93 | } SMO_subcatchAttribute; 94 | 95 | typedef enum { 96 | invert_depth, // (ft or m), 97 | hydraulic_head, // (ft or m), 98 | stored_ponded_volume, // (ft3 or m3), 99 | lateral_inflow, // (flow units), 100 | total_inflow, // lateral + upstream (flow units), 101 | flooding_losses, // (flow units), 102 | pollutant_conc_node // first pollutant, 103 | 104 | } SMO_nodeAttribute; 105 | 106 | typedef enum { 107 | flow_rate_link, // (flow units), 108 | flow_depth, // (ft or m), 109 | flow_velocity, // (ft/s or m/s), 110 | flow_volume, // (ft3 or m3), 111 | capacity, // (fraction of conduit filled), 112 | pollutant_conc_link // first pollutant, 113 | 114 | } SMO_linkAttribute; 115 | 116 | typedef enum { 117 | air_temp, // (deg. F or deg. C), 118 | rainfall_system, // (in/hr or mm/hr), 119 | snow_depth_system, // (in or mm), 120 | evap_infil_loss, // (in/hr or mm/hr), 121 | runoff_flow, // (flow units), 122 | dry_weather_inflow, // (flow units), 123 | groundwater_inflow, // (flow units), 124 | RDII_inflow, // (flow units), 125 | direct_inflow, // user defined (flow units), 126 | total_lateral_inflow, // (sum of variables 4 to 8) //(flow units), 127 | flood_losses, // (flow units), 128 | outfall_flows, // (flow units), 129 | volume_stored, // (ft3 or m3), 130 | evap_rate // (in/day or mm/day), 131 | //p_evap_rate // (in/day or mm/day) 132 | } SMO_systemAttribute; 133 | 134 | 135 | SMOutputAPI* DLLEXPORT SMO_init(void); 136 | int DLLEXPORT SMO_open(SMOutputAPI* smoapi, const char* path); 137 | 138 | 139 | DLLEXPORT int SMO_getProjectSize(SMOutputAPI* smoapi, SMO_elementCount code, int* count); 140 | DLLEXPORT int SMO_getUnits(SMOutputAPI* smoapi, SMO_unit code, int* unitFlag); 141 | DLLEXPORT int SMO_getStartTime(SMOutputAPI* smoapi, double* time); 142 | DLLEXPORT int SMO_getTimes(SMOutputAPI* smoapi, SMO_time code, int* time); 143 | 144 | int DLLEXPORT SMO_getElementName(SMOutputAPI* smoapi, SMO_elementType type, 145 | int elementIndex, char* elementName, int* length); 146 | 147 | DLLEXPORT float* SMO_newOutValueSeries(SMOutputAPI* smoapi, long seriesStart, 148 | long seriesLength, long* length, int* errcode); 149 | DLLEXPORT float* SMO_newOutValueArray(SMOutputAPI* smoapi, SMO_apiFunction func, 150 | SMO_elementType type, long* length, int* errcode); 151 | 152 | DLLEXPORT int SMO_getSubcatchSeries(SMOutputAPI* smoapi, int subcatchIndex, 153 | SMO_subcatchAttribute attr, long timeIndex, long length, float* outValueSeries); 154 | DLLEXPORT int SMO_getNodeSeries(SMOutputAPI* smoapi, int nodeIndex, SMO_nodeAttribute attr, 155 | long timeIndex, long length, float* outValueSeries); 156 | DLLEXPORT int SMO_getLinkSeries(SMOutputAPI* smoapi, int linkIndex, SMO_linkAttribute attr, 157 | long timeIndex, long length, float* outValueSeries); 158 | DLLEXPORT int SMO_getSystemSeries(SMOutputAPI* smoapi, SMO_systemAttribute attr, 159 | long timeIndex, long length, float *outValueSeries); 160 | 161 | DLLEXPORT int SMO_getSubcatchAttribute(SMOutputAPI* smoapi, long timeIndex, 162 | SMO_subcatchAttribute attr, float* outValueArray); 163 | DLLEXPORT int SMO_getNodeAttribute(SMOutputAPI* smoapi, long timeIndex, 164 | SMO_nodeAttribute attr, float* outValueArray); 165 | DLLEXPORT int SMO_getLinkAttribute(SMOutputAPI* smoapi, long timeIndex, 166 | SMO_linkAttribute attr, float* outValueArray); 167 | DLLEXPORT int SMO_getSystemAttribute(SMOutputAPI* smoapi, long timeIndex, 168 | SMO_systemAttribute attr, float* outValueArray); 169 | 170 | DLLEXPORT int SMO_getSubcatchResult(SMOutputAPI* smoapi, long timeIndex, int subcatchIndex, 171 | float* outValueArray); 172 | DLLEXPORT int SMO_getNodeResult(SMOutputAPI* smoapi, long timeIndex, int nodeIndex, 173 | float* outValueArray); 174 | DLLEXPORT int SMO_getLinkResult(SMOutputAPI* smoapi, long timeIndex, int linkIndex, 175 | float* outValueArray); 176 | DLLEXPORT int SMO_getSystemResult(SMOutputAPI* smoapi, long timeIndex, float* outValueArray); 177 | 178 | DLLEXPORT void SMO_free(float *array); 179 | 180 | DLLEXPORT int SMO_close(SMOutputAPI* smoapi); 181 | DLLEXPORT int SMO_errMessage(int errcode, char* errmsg, int n); 182 | 183 | 184 | #endif /* OUTPUTAPI_H_ */ 185 | -------------------------------------------------------------------------------- /swmmoutputapi/swmmbinreader.py: -------------------------------------------------------------------------------- 1 | """ 2 | SWMM Output File Wrapper for the New OutputAPI. 3 | 4 | Author: Bryant E. McDonnell 5 | Date: 1/10/2016 6 | 7 | """ 8 | from ctypes import * 9 | from _toolkitpyswmm import * 10 | from datetime import datetime, timedelta 11 | import os 12 | 13 | __author__ = 'Bryant E. McDonnell (bemcdonnell@gmail.com)' 14 | __copyright__ = 'Copyright (c) 2016 Bryant E. McDonnell' 15 | __license__ = 'BSD2' 16 | __version__ = '0.2.1' 17 | 18 | 19 | 20 | 21 | 22 | class _Opaque(Structure): 23 | """ 24 | Used soley for passing the pointer to the smoapu struct to API 25 | """ 26 | pass 27 | 28 | class SWMMBinReader: 29 | 30 | def __init__(self): 31 | """ 32 | Instantiate python Wrapper Object and build Wrapper functions. 33 | """ 34 | def get_pkgpath(): 35 | import _toolkitpyswmm as tkp 36 | return os.path.dirname(tkp.__file__.replace('\\','/')) 37 | 38 | try: 39 | #Later Check for OS Type 40 | dllname = 'outputAPI_winx86.dll' 41 | #when platform detection is enabled, dllname can be changed 42 | dllLoc = get_pkgpath() + '/data/'+ dllname 43 | self.swmmdll = CDLL(dllLoc) 44 | 45 | except: 46 | raise Exception('Failed to Open Linked Library') 47 | 48 | 49 | #### Initializing DLL Function List 50 | #Initialize Pointer to smoapi 51 | self._initsmoapi = self.swmmdll.SMO_init 52 | self._initsmoapi.restype = POINTER(_Opaque) 53 | 54 | #Open File Function Handle 55 | self._openBinFile = self.swmmdll.SMO_open 56 | self._free = self.swmmdll.SMO_free 57 | self._close = self.swmmdll.SMO_close 58 | 59 | #Project Data 60 | self._getProjectSize = self.swmmdll.SMO_getProjectSize 61 | self._getTimes = self.swmmdll.SMO_getTimes 62 | self._getStartTime = self.swmmdll.SMO_getStartTime 63 | self._getUnits = self.swmmdll.SMO_getUnits 64 | 65 | #Object ID Function Handles 66 | self._getIDs = self.swmmdll.SMO_getElementName 67 | 68 | #Object Series Function Handles 69 | self._getSubcatchSeries = self.swmmdll.SMO_getSubcatchSeries 70 | self._getNodeSeries = self.swmmdll.SMO_getNodeSeries 71 | self._getLinkSeries = self.swmmdll.SMO_getLinkSeries 72 | self._getSystemSeries = self.swmmdll.SMO_getSystemSeries 73 | 74 | #Object Attribure Function Handles 75 | self._getSubcatchAttribute = self.swmmdll.SMO_getSubcatchAttribute 76 | self._getNodeAttribute = self.swmmdll.SMO_getNodeAttribute 77 | self._getLinkAttribute = self.swmmdll.SMO_getLinkAttribute 78 | self._getSystemAttribute = self.swmmdll.SMO_getSystemAttribute 79 | 80 | #Object Result Function Handles 81 | self._getSubcatchResult = self.swmmdll.SMO_getSubcatchResult 82 | self._getNodeResult = self.swmmdll.SMO_getNodeResult 83 | self._getLinkResult = self.swmmdll.SMO_getLinkResult 84 | self._getSystemResult = self.swmmdll.SMO_getSystemResult 85 | 86 | #Array Builder 87 | self._newOutValueArray = self.swmmdll.SMO_newOutValueArray 88 | self._newOutValueArray.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_int), POINTER(c_int)] 89 | self._newOutValueArray.restype = POINTER(c_float) 90 | 91 | #Series Builder 92 | self._newOutValueSeries = self.swmmdll.SMO_newOutValueSeries 93 | self._newOutValueSeries.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_int), POINTER(c_int)] 94 | self._newOutValueSeries.restype = POINTER(c_float) 95 | 96 | #SWMM Date num 2 String 97 | self.SWMMdateToStr = self.swmmdll.datetime_dateToStr 98 | 99 | #SWMM Time num 2 String 100 | self.SWMMtimeToStr = self.swmmdll.datetime_timeToStr 101 | 102 | def OpenBinFile(self, OutLoc): 103 | """Opens SWMM5 binary output file. 104 | 105 | :param str OutLoc: Path to Binary output file 106 | 107 | :return: None 108 | 109 | Examples: 110 | 111 | >>> OutputFile = SWMMBinReader() 112 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 113 | """ 114 | 115 | self.smoapi = self._initsmoapi() 116 | ErrNo = self._openBinFile(self.smoapi,OutLoc) 117 | if ErrNo != 0: 118 | raise Exception("API ErrNo {0}:{1}".format(ErrNo, DLLErrorKeys[ErrNo])) 119 | 120 | 121 | def CloseBinFile(self): 122 | """Closes binary output file and cleans up member variables. 123 | 124 | :returns: None 125 | 126 | Examples: 127 | 128 | >>> OutputFile = SWMMBinReader() 129 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 130 | >>> OutputFile.CloseBinFile() 131 | """ 132 | 133 | ErrNo = self._close(self.smoapi) 134 | 135 | if hasattr(self, 'SubcatchmentIDs'): delattr(self,'SubcatchmentIDs') 136 | if hasattr(self, 'NodeIDs'): delattr(self,'NodeIDs') 137 | if hasattr(self, 'LinkIDs'): delattr(self,'LinkIDs') 138 | if hasattr(self, 'PollutantIDs'): delattr(self,'PollutantIDs') 139 | 140 | if ErrNo != 0: 141 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value, DLLErrorKeys[ErrNo.value]) ) 142 | 143 | def _get_SubcatchIDs(self): 144 | """ 145 | 146 | Purpose: Generates member Element IDs dictionary for Subcatchments 147 | 148 | """ 149 | 150 | self.SubcatchmentIDs = {} 151 | for i in range(self.get_ProjectSize(subcatchCount)): 152 | NAME = create_string_buffer(46) 153 | LEN = c_int(46) 154 | ErrNo1 = self._getIDs(self.smoapi, SM_subcatch, i, byref(NAME), byref(LEN)) 155 | if ErrNo1 != 0: 156 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value, DLLErrorKeys[ErrNo1.value]) ) 157 | self.SubcatchmentIDs[str(NAME.value)] = i 158 | 159 | def _get_NodeIDs(self): 160 | """ 161 | Internal 162 | Purpose: Generates member Element IDs dictionary for Nodes 163 | 164 | """ 165 | self.NodeIDs = {} 166 | for i in range(self.get_ProjectSize(nodeCount)): 167 | NAME = create_string_buffer(46) 168 | LEN = c_int(46) 169 | ErrNo1 = self._getIDs(self.smoapi, SM_node, i, byref(NAME), byref(LEN)) 170 | if ErrNo1 != 0: 171 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value, DLLErrorKeys[ErrNo1.value]) ) 172 | self.NodeIDs[str(NAME.value)] = i 173 | 174 | def _get_LinkIDs(self): 175 | """ 176 | Internal 177 | Purpose: Generates member Element IDs dictionary for Links 178 | 179 | """ 180 | self.LinkIDs = {} 181 | for i in range(self.get_ProjectSize(linkCount)): 182 | NAME = create_string_buffer(46) 183 | LEN = c_int(46) 184 | ErrNo1 = self._getIDs(self.smoapi, SM_link, i, byref(NAME), byref(LEN)) 185 | if ErrNo1 != 0: 186 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value, DLLErrorKeys[ErrNo1.value]) ) 187 | self.LinkIDs[str(NAME.value)] = i 188 | 189 | def _get_PollutantIDs(self): 190 | """ 191 | Internal 192 | Purpose: Generates member Element IDs dictionary for Pollutants 193 | 194 | """ 195 | self.PollutantIDs = {} 196 | for i in range(self.get_ProjectSize(pollutantCount)): 197 | NAME = create_string_buffer(46) 198 | LEN = c_int(46) 199 | ErrNo1 = self._getIDs(self.smoapi, SM_sys, i, byref(NAME), byref(LEN)) 200 | if ErrNo1 != 0: 201 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value, DLLErrorKeys[ErrNo1.value]) ) 202 | self.PollutantIDs[str(NAME.value)] = i 203 | 204 | def get_IDs(self, SMO_elementIDType): 205 | """Returns List Type of Element IDs 206 | 207 | :param int SMO_elementCount: element ID type :doc:`/keyrefs` 208 | 209 | :return: list ordered List of IDs 210 | :rtype: list 211 | 212 | Examples: 213 | 214 | >>> OutputFile = SWMMBinReader() 215 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 216 | >>> Test.get_IDs(SM_subcatch) 217 | >>> ['S3', 'S2', 'S1'] 218 | >>> Test.get_IDs(SM_node) 219 | >>> ['J4', 'J1', 'J2', 'J3'] 220 | >>> Test.get_IDs(SM_link) 221 | >>> ['C3', 'C2', 'C1'] 222 | """ 223 | if SMO_elementIDType == subcatchCount: 224 | if not hasattr(self, 'SubcatchmentIDs'): 225 | self._get_SubcatchIDs() 226 | IDlist = self.SubcatchmentIDs.keys() 227 | elif SMO_elementIDType == SM_node: 228 | if not hasattr(self, 'NodeIDs'): 229 | self._get_NodeIDs() 230 | IDlist = self.NodeIDs.keys() 231 | elif SMO_elementIDType == SM_link: 232 | if not hasattr(self, 'LinkIDs'): 233 | self._get_LinkIDs() 234 | IDlist = self.LinkIDs.keys() 235 | elif SMO_elementIDType == SM_sys: 236 | if not hasattr(self, 'PollutantIDs'): 237 | self._get_PollutantIDs() 238 | IDlist = self.PollutantIDs.keys() 239 | else: 240 | raise Exception("SMO_elementType: {} Outside Valid Types".format(SMO_elementType)) 241 | return 0 242 | # Do not sort lists 243 | return IDlist 244 | 245 | def get_Units(self, SMO_unit): 246 | """Returns flow units and Concentration 247 | 248 | :param int SMO_unit: element ID type :doc:`/keyrefs` 249 | 250 | :return: Unit Type 251 | :rtype: str 252 | 253 | Examples: 254 | 255 | >>> OutputFile = SWMMBinReader() 256 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 257 | >>> OutputFile.get_Units(flow_rate) 258 | >>> 'CFS' 259 | 260 | """ 261 | FlowUnitsType = ['CFS','GPM', 'MGD','CMS', 'LPS', 'MLD'] 262 | # cubic feet per second 263 | # gallons per minute 264 | # million gallons per day 265 | # cubic meters per second 266 | # liters per second 267 | # million liters per day 268 | 269 | ConcUnitsType = ['mg','ug','COUNT'] 270 | # Milligrams / L 271 | # Micrograms / L 272 | # Counts / L 273 | 274 | x = c_int() 275 | ErrNo1 = self._getUnits(self.smoapi, SMO_unit, byref(x)) 276 | if ErrNo1 != 0: 277 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1, DLLErrorKeys[ErrNo1]) ) 278 | if SMO_unit == flow_rate: 279 | return FlowUnitsType[x.value] 280 | elif SMO_unit == concentration: 281 | return ConcUnitsType[x.value] 282 | else: 283 | raise Exception("SMO_unit: {} Outside Valid Types".format(SMO_unit)) 284 | 285 | def get_Times(self, SMO_timeElementType): 286 | """Returns report and simulation time related parameters. 287 | 288 | :param int SMO_timeElementType: element ID type :doc:`/keyrefs` 289 | 290 | :return: Report Step (seconds) or Number of Time Steps 291 | :rtype: int 292 | 293 | Examples: 294 | 295 | >>> OutputFile = SWMMBinReader() 296 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 297 | >>> OutputFile.get_Times(reportStep) 298 | >>> 300 299 | """ 300 | timeElement = c_int() 301 | ErrNo1 = self._getTimes(self.smoapi, SMO_timeElementType, byref(timeElement)) 302 | if ErrNo1 != 0: 303 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1, DLLErrorKeys[ErrNo1]) ) 304 | return timeElement.value 305 | 306 | def _get_StartTimeSWMM(self): 307 | """ 308 | Internal 309 | Purpose: Returns the simulation start datetime as double. 310 | """ 311 | 312 | StartTime = c_double() 313 | ErrNo1 = self._getStartTime(self.smoapi, byref(StartTime)) 314 | if ErrNo1 != 0: 315 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1, DLLErrorKeys[ErrNo1]) ) 316 | return StartTime.value 317 | 318 | def get_StartTime(self): 319 | """Uses SWMM5 Conversion Functions to Pull DateTime String and converts to Python datetime format 320 | 321 | :return: Simulation start time. 322 | :rtype: datetime 323 | 324 | Examples: 325 | 326 | >>> OutputFile = SWMMBinReader() 327 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 328 | >>> OutputFile.get_StartTime() 329 | >>> datetime.datetime(2016,10,4,12,4,0) 330 | """ 331 | _StartTime = self._get_StartTimeSWMM() 332 | _date = int(_StartTime) 333 | _time = _StartTime - _date 334 | 335 | #Pull Date String 336 | DateStr = create_string_buffer(50) 337 | self.SWMMdateToStr(c_double(_date), byref(DateStr)) 338 | DATE = DateStr.value 339 | 340 | #Pull Time String 341 | TimeStr = create_string_buffer(50) 342 | self.SWMMtimeToStr(c_double(_time), byref(TimeStr)) 343 | TIME = TimeStr.value 344 | DTime = datetime.strptime(DATE+' '+TIME,'%Y-%b-%d %H:%M:%S') 345 | return DTime 346 | 347 | def get_TimeSeries(self): 348 | """ Gets simulation start time and builds timeseries array based on the reportStep 349 | 350 | :return: Simulation time series. 351 | :rtype: list of datetime 352 | 353 | Examples: 354 | 355 | >>> OutputFile = SWMMBinReader() 356 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 357 | >>> OutputFile.get_TimeSeries() 358 | >>> [datetime.datetime(2015, 11, 29, 14, 0), datetime.datetime(2015, 11, 29, 14, 1), ..., datetime.datetime(2015, 11, 29, 14, 9)] 359 | """ 360 | return [self.get_StartTime() + timedelta(seconds = ind*self.get_Times(reportStep))\ 361 | for ind in range(self.get_Times(numPeriods))] 362 | 363 | def get_ProjectSize(self, SMO_elementCount): 364 | """Returns number of elements of a specific element type. 365 | 366 | :param int SMO_elementCount: element ID type :doc:`/keyrefs` 367 | 368 | :return: Number of Objects 369 | :rtype: int 370 | 371 | Examples: 372 | 373 | >>> OutputFile = SWMMBinReader() 374 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 375 | >>> OutputFile.get_ProjectSize(nodeCount) 376 | >>> 10 377 | """ 378 | numel = c_int() 379 | ErrNo1 = self._getProjectSize(self.smoapi, SMO_elementCount, byref(numel)) 380 | if ErrNo1 != 0: 381 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1,DLLErrorKeys[ErrNo1]) ) 382 | return numel.value 383 | 384 | def get_Series(self, SMO_elementType, SMO_Attribute, IDName = None, TimeStartInd = 0, TimeEndInd = -1): 385 | """Get time series results for particular attribute for an object. Specify series start and length using TimeStartInd and TimeEndInd respectively. 386 | 387 | :param int SMO_elementType: Element type :doc:`/keyrefs`. 388 | :param int SMO_Attribute: Attribute Type :doc:`/keyrefs`. 389 | :param str IDName: Element ID name (Default is None for to reach sys variables) (ID Names are case sensitive). 390 | :param int TimeStartInd: Starting index for the time series data period (default is 0). 391 | :param int TimeEndInd: Array index for the time series data period (defualt is -1 for end). 392 | 393 | :return: data series 394 | :rtype: list 395 | 396 | Examples: 397 | 398 | >>> OutputFile = SWMMBinReader() 399 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 400 | >>> OutputFile.get_Series(SM_subcatch, runoff_rate, 'S3', 0, 50) 401 | >>> [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, .... 0.0] 402 | 403 | >>> OutputFile.get_Series(SM_node, invert_depth, 'J1', 0, 50) 404 | >>> [3.908519983291626, 4.6215434074401855, 4.594745635986328, 4.595311641693115, ..., 4.595311641693115] 405 | 406 | >>> OutputFile.get_Series(SM_link, rainfall_subcatch, 'C2', 0, 50) 407 | >>> [10.2869873046875, 10.04793643951416, 9.997148513793945, 10.000744819641113, ..., 10.011372566223145] 408 | 409 | >>> OutputFile.get_Series(SM_sys, rainfall_system, TimeStartInd = 0, TimeEndInd = 50) 410 | >>> [0.017500000074505806, 0.017500000074505806, 0.017500000074505806, 0.017500000074505806, ..., 0.017500000074505806] 411 | """ 412 | 413 | if TimeEndInd > self.get_Times(numPeriods): 414 | raise Exception("Outside Number of TimeSteps") 415 | elif TimeEndInd == -1: 416 | TimeEndInd = self.get_Times(numPeriods) + 1 - TimeEndInd 417 | 418 | 419 | sLength = c_int() 420 | ErrNo1 = c_int() 421 | SeriesPtr = self._newOutValueSeries(self.smoapi, TimeStartInd,\ 422 | TimeEndInd, byref(sLength), byref(ErrNo1)) 423 | if ErrNo1.value != 0: 424 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value,DLLErrorKeys[ErrNo1.value]) ) 425 | 426 | if SMO_elementType == SM_subcatch: 427 | if not hasattr(self, 'SubcatchmentIDs'): 428 | self._get_SubcatchIDs() 429 | ErrNo2 = self._getSubcatchSeries(self.smoapi, self.SubcatchmentIDs[IDName], SMO_Attribute, \ 430 | TimeStartInd, sLength.value, SeriesPtr) 431 | elif SMO_elementType == SM_node: 432 | if not hasattr(self, 'NodeIDs'): 433 | self._get_NodeIDs() 434 | ErrNo2 = self._getNodeSeries(self.smoapi, self.NodeIDs[IDName], SMO_Attribute, \ 435 | TimeStartInd, sLength.value, SeriesPtr) 436 | elif SMO_elementType == SM_link: 437 | if not hasattr(self, 'LinkIDs'): 438 | self._get_LinkIDs() 439 | ErrNo2 = self._getLinkSeries(self.smoapi, self.LinkIDs[IDName], SMO_Attribute, \ 440 | TimeStartInd, sLength.value, SeriesPtr) 441 | ## Add Pollutants Later 442 | elif SMO_elementType == SM_sys: 443 | ErrNo2 = self._getSystemSeries(self.smoapi, SMO_Attribute, \ 444 | TimeStartInd, sLength.value, SeriesPtr) 445 | else: 446 | raise Exception("SMO_elementType: {} Outside Valid Types".format(SMO_elementType)) 447 | 448 | if ErrNo2 != 0: 449 | raise Exception("API ErrNo {0}:{1}".format(ErrNo2,DLLErrorKeys[ErrNo2]) ) 450 | 451 | BldArray = [SeriesPtr[i] for i in range(sLength.value)] 452 | self._free(SeriesPtr) 453 | return BldArray 454 | 455 | def get_Attribute(self, SMO_elementType, SMO_Attribute, TimeInd): 456 | """Get results for particular attribute for all elements at a specific time index. 457 | 458 | :param int SMO_elementType: Element type :doc:`/keyrefs`. 459 | :param int SMO_Attribute: Attribute Type :doc:`/keyrefs`. 460 | :param int TimeInd: TimeInd 461 | 462 | :return: data list in order of the IDs of the SMO_elementType 463 | :rtype: list 464 | 465 | Examples: 466 | 467 | >>> OutputFile = SWMMBinReader() 468 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 469 | >>> OutputFile.get_Attribute(SM_subcatch, rainfall_subcatch, 0) 470 | >>> [0.017500000074505806, 0.017500000074505806, 0.017500000074505806] 471 | 472 | >>> OutputFile.get_Attribute(SM_node, invert_depth, 10) 473 | >>> [4.596884250640869, 0.720202624797821, 0.6315776705741882, 0.6312257051467896] 474 | 475 | >>> OutputFile.get_Attribute(SM_link, flow_rate_link, 50) 476 | >>> [9.00419807434082, 10.011459350585938, 11.020767211914062] 477 | """ 478 | if TimeInd > self.get_Times(numPeriods)-1: 479 | raise Exception("Outside Number of TimeSteps") 480 | 481 | aLength = c_int() 482 | ErrNo1 = c_int() 483 | ValArrayPtr = self._newOutValueArray(self.smoapi, getAttribute,\ 484 | SMO_elementType, byref(aLength), byref(ErrNo1)) 485 | if ErrNo1.value != 0: 486 | raise Exception("API ErrNo {0}:{1}".format(ErrNo1.value,DLLErrorKeys[ErrNo1.value]) ) 487 | 488 | if SMO_elementType == SM_subcatch: 489 | ErrNo2 = self._getSubcatchAttribute(self.smoapi, TimeInd, SMO_Attribute, ValArrayPtr) 490 | elif SMO_elementType == SM_link: 491 | ErrNo2 = self._getLinkAttribute(self.smoapi, TimeInd, SMO_Attribute, ValArrayPtr) 492 | elif SMO_elementType == SM_node: 493 | ErrNo2 = self._getNodeAttribute(self.smoapi, TimeInd, SMO_Attribute, ValArrayPtr) 494 | ## Add Pollutants Later 495 | else: 496 | raise Exception("SMO_elementType: {} Outside Valid Types".format(SMO_elementType)) 497 | 498 | if ErrNo2 != 0: 499 | raise Exception("API ErrNo {0}:{1}".format(ErrNo2,DLLErrorKeys[ErrNo2]) ) 500 | 501 | BldArray = [ValArrayPtr[i] for i in range(aLength.value)] 502 | self._free(ValArrayPtr) 503 | return BldArray 504 | 505 | def get_Result(self, SMO_elementType, TimeInd, IDName = None): 506 | """For a element ID at given time, get all attributes 507 | 508 | :param int SMO_elementType: Element type :doc:`/keyrefs`. 509 | :param int TimeInd: Time Index 510 | :param int IDName: IDName (default None for System Variables) 511 | 512 | Examples: 513 | 514 | >>> OutputFile = SWMMBinReader() 515 | >>> OutputFile.OpenBinFile(r"C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\outputfile.out") 516 | >>> OutputFile.get_Result(SM_subcatch,3000,'S3') 517 | >>> [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 518 | 519 | >>> OutputFile.get_Result(SM_node,3000,'J1') 520 | >>> [4.594789505004883, 25.322790145874023, 0.0, 9.000000953674316, 9.000000953674316, 0.0] 521 | 522 | >>> OutputFile.get_Result(SM_link,9000,'C3') 523 | >>> [11.0, 0.6312892436981201, 12.93112564086914, 185.72474670410156, 0.270773708820343] 524 | 525 | >>> OutputFile.get_Result(SM_sys,3000,'S3') 526 | >>> [70.0, 0.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 3.0, 11.0, 0.0, 11.000021934509277, 532.2583618164062, 0.0, 0.0] 527 | """ 528 | if TimeInd > self.get_Times(numPeriods)-1: 529 | raise Exception("Outside Number of TimeSteps") 530 | 531 | alength = c_int() 532 | ErrNo1 = c_int() 533 | ValArrayPtr = self._newOutValueArray(self.smoapi, getResult,\ 534 | SMO_elementType, byref(alength), byref(ErrNo1)) 535 | 536 | if SMO_elementType == SM_subcatch: 537 | if not hasattr(self, 'SubcatchmentIDs'): 538 | self._get_SubcatchIDs() 539 | ErrNo2 = self._getSubcatchResult(self.smoapi, TimeInd, self.SubcatchmentIDs[IDName], ValArrayPtr) 540 | elif SMO_elementType == SM_node: 541 | if not hasattr(self, 'NodeIDs'): 542 | self._get_NodeIDs() 543 | ErrNo2 = self._getNodeResult(self.smoapi, TimeInd, self.NodeIDs[IDName], ValArrayPtr) 544 | elif SMO_elementType == SM_link: 545 | if not hasattr(self, 'LinkIDs'): 546 | self._get_LinkIDs() 547 | ErrNo2 = self._getLinkResult(self.smoapi, TimeInd, self.LinkIDs[IDName], ValArrayPtr) 548 | ## Add Pollutants Later 549 | elif SMO_elementType == SM_sys: 550 | ErrNo2 = self._getSystemResult(self.smoapi, TimeInd, ValArrayPtr) 551 | else: 552 | raise Exception("SMO_elementType: {} Outside Valid Types".format(SMO_elementType)) 553 | 554 | BldArray = [ValArrayPtr[i] for i in range(alength.value)] 555 | self._free(ValArrayPtr) 556 | return BldArray 557 | 558 | 559 | if __name__ in "__main__": 560 | ## Run Tests 561 | 562 | ## Open 563 | Test = SWMMBinReader() 564 | Test.OpenBinFile(r"C:\PROJECTCODE\SWMMOutputAPI\testing\OutputTestModel522_SHORT.out") 565 | 566 | ## Get IDs 567 | print("\nProject Element ID Info") 568 | print(Test.get_IDs(SM_subcatch)) 569 | print(Test.get_IDs(SM_node)) 570 | print(Test.get_IDs(SM_link)) 571 | 572 | print("\nGet Units") 573 | print('flow_rate: {}'.format(Test.get_Units(flow_rate))) 574 | print('concentration: {}'.format(Test.get_Units(concentration))) 575 | 576 | 577 | ## Get Project Size 578 | print("\nProject Size Info") 579 | print("Subcatchments: {}".format(Test.get_ProjectSize(subcatchCount))) 580 | print("Nodes: {}".format(Test.get_ProjectSize(nodeCount))) 581 | print("Links: {}".format(Test.get_ProjectSize(linkCount))) 582 | print("Pollutants: {}".format(Test.get_ProjectSize(pollutantCount))) 583 | 584 | ## Project Time Steps 585 | print("\nProject Time Info") 586 | print("Report Step: {}".format(Test.get_Times(reportStep))) 587 | print("Periods: {}".format(Test.get_Times(numPeriods))) 588 | 589 | ## Get Time Series 590 | print("\nGet Time Series") 591 | TimeSeries = Test.get_TimeSeries() 592 | print(TimeSeries[:10]) 593 | 594 | ## Get Series 595 | print("\nSeries Tests") 596 | SubcSeries = Test.get_Series(SM_subcatch, runoff_rate, 'S3', 0, 50) 597 | print(SubcSeries) 598 | NodeSeries = Test.get_Series(SM_node, invert_depth, 'J1', 0, 50) 599 | print(NodeSeries) 600 | LinkSeries = Test.get_Series(SM_link, rainfall_subcatch, 'C2', 0, 50) 601 | print(LinkSeries) 602 | SystSeries = Test.get_Series(SM_sys, rainfall_system, TimeStartInd = 0, TimeEndInd = 50) 603 | print(SystSeries) 604 | 605 | ## Get Attributes 606 | print("\nAttributes Tests") 607 | SubcAttributes = Test.get_Attribute(SM_subcatch, rainfall_subcatch, 0) #<- Check Values.. Might be issue here 608 | print(SubcAttributes) 609 | NodeAttributes = Test.get_Attribute(SM_node, invert_depth, 10) 610 | print(NodeAttributes) 611 | LinkAttributes = Test.get_Attribute(SM_link, flow_rate_link, 50) 612 | print(LinkAttributes) 613 | 614 | ## Get Results 615 | print("\nResult Tests") 616 | SubcResults = Test.get_Result(SM_subcatch,3000,'S3') 617 | print(SubcResults) 618 | NodeResults = Test.get_Result(SM_node,3000,'J1') 619 | print(NodeResults) 620 | LinkResults = Test.get_Result(SM_link,9000,'C3') 621 | print(LinkResults) 622 | SystResults = Test.get_Result(SM_sys,3000,'S3') 623 | print(SystResults) 624 | 625 | ## Close Output File 626 | Test.CloseBinFile() 627 | 628 | 629 | help(SWMMBinReader) 630 | -------------------------------------------------------------------------------- /testing/OutputTestModel522_SHORT.inp: -------------------------------------------------------------------------------- 1 | [TITLE] 2 | ;;Project Title/Notes 3 | 4 | [OPTIONS] 5 | ;;Option Value 6 | FLOW_UNITS CFS 7 | INFILTRATION HORTON 8 | FLOW_ROUTING DYNWAVE 9 | LINK_OFFSETS DEPTH 10 | MIN_SLOPE 0 11 | ALLOW_PONDING NO 12 | SKIP_STEADY_STATE NO 13 | 14 | START_DATE 11/29/2015 15 | START_TIME 14:00:00 16 | REPORT_START_DATE 11/29/2015 17 | REPORT_START_TIME 00:00:00 18 | END_DATE 12/28/2015 19 | END_TIME 00:00:00 20 | SWEEP_START 01/01 21 | SWEEP_END 12/31 22 | DRY_DAYS 0 23 | REPORT_STEP 00:01:00 24 | WET_STEP 00:05:00 25 | DRY_STEP 00:05:00 26 | ROUTING_STEP 0:00:01 27 | 28 | INERTIAL_DAMPING NONE 29 | NORMAL_FLOW_LIMITED BOTH 30 | FORCE_MAIN_EQUATION H-W 31 | VARIABLE_STEP 0.75 32 | LENGTHENING_STEP 0 33 | MIN_SURFAREA 12.557 34 | MAX_TRIALS 8 35 | HEAD_TOLERANCE 0.005 36 | SYS_FLOW_TOL 5 37 | LAT_FLOW_TOL 5 38 | MINIMUM_STEP 0.5 39 | THREADS 1 40 | 41 | [EVAPORATION] 42 | ;;Data Source Parameters 43 | ;;-------------- ---------------- 44 | CONSTANT 0.0 45 | DRY_ONLY NO 46 | 47 | [RAINGAGES] 48 | ;;Name Format Interval SCF Source 49 | ;;-------------- --------- ------ ------ ---------- 50 | SCS_24h_Type_I_1in INTENSITY 0:15 1.0 TIMESERIES SCS_24h_Type_I_1in 51 | 52 | [SUBCATCHMENTS] 53 | ;;Name Rain Gage Outlet Area %Imperv Width %Slope CurbLen SnowPack 54 | ;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- ---------------- 55 | S1 SCS_24h_Type_I_1in J1 1 100 500 0.5 0 56 | S2 SCS_24h_Type_I_1in J2 2 100 500 0.5 0 57 | S3 SCS_24h_Type_I_1in j3 3 100 500 0.5 0 58 | 59 | [SUBAREAS] 60 | ;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted 61 | ;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 62 | S1 0.01 0.1 0.05 0.05 25 OUTLET 63 | S2 0.01 0.1 0.05 0.05 25 OUTLET 64 | S3 0.01 0.1 0.05 0.05 25 OUTLET 65 | 66 | [INFILTRATION] 67 | ;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil 68 | ;;-------------- ---------- ---------- ---------- ---------- ---------- 69 | S1 3 0.5 4 7 0 70 | S2 3 0.5 4 7 0 71 | S3 3 0.5 4 7 0 72 | 73 | [JUNCTIONS] 74 | ;;Name Elevation MaxDepth InitDepth SurDepth Aponded 75 | ;;-------------- ---------- ---------- ---------- ---------- ---------- 76 | J1 20.728 15 0 0 0 77 | J2 13.392 15 0 0 0 78 | J3 6.547 15 0 0 0 79 | 80 | [OUTFALLS] 81 | ;;Name Elevation Type Stage Data Gated Route To 82 | ;;-------------- ---------- ---------- ---------------- -------- ---------------- 83 | J4 0 FREE NO 84 | 85 | [CONDUITS] 86 | ;;Name From Node To Node Length Roughness InOffset OutOffset InitFlow MaxFlow 87 | ;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- 88 | C1:C2 J1 J2 244.63 0.01 0 0 0 0 89 | C2 J2 J3 228.28 0.01 0 0 0 0 90 | C3 J3 J4 218.33 0.01 0 0 0 0 91 | 92 | [XSECTIONS] 93 | ;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels Culvert 94 | ;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- ---------- 95 | C1:C2 CIRCULAR 1 0 0 0 1 96 | C2 CIRCULAR 1.5 0 0 0 1 97 | C3 CIRCULAR 2 0 0 0 1 98 | 99 | [INFLOWS] 100 | ;;Node Constituent Time Series Type Mfactor Sfactor Baseline Pattern 101 | ;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- 102 | J1 FLOW "" FLOW 1.0 1 1 103 | J2 Flow "" FLOW 1.0 1 1 104 | J3 Flow "" FLOW 1.0 1 1 105 | 106 | [DWF] 107 | ;;Node Constituent Baseline Patterns 108 | ;;-------------- ---------------- ---------- ---------- 109 | J1 FLOW 8 110 | 111 | [TIMESERIES] 112 | ;;Name Date Time Value 113 | ;;-------------- ---------- ---------- ---------- 114 | ;SCS_24h_Type_I_1in design storm, total rainfall = 1 in, rain units = in/hr. 115 | SCS_24h_Type_I_1in 0:00 0.0175 116 | SCS_24h_Type_I_1in 0:15 0.0175 117 | SCS_24h_Type_I_1in 0:30 0.0175 118 | SCS_24h_Type_I_1in 0:45 0.0175 119 | SCS_24h_Type_I_1in 1:00 0.0175 120 | SCS_24h_Type_I_1in 1:15 0.0175 121 | SCS_24h_Type_I_1in 1:30 0.0175 122 | SCS_24h_Type_I_1in 1:45 0.0175 123 | SCS_24h_Type_I_1in 2:00 0.0205 124 | SCS_24h_Type_I_1in 2:15 0.0205 125 | SCS_24h_Type_I_1in 2:30 0.0205 126 | SCS_24h_Type_I_1in 2:45 0.0205 127 | SCS_24h_Type_I_1in 3:00 0.0205 128 | SCS_24h_Type_I_1in 3:15 0.0205 129 | SCS_24h_Type_I_1in 3:30 0.0205 130 | SCS_24h_Type_I_1in 3:45 0.0205 131 | SCS_24h_Type_I_1in 4:00 0.0245 132 | SCS_24h_Type_I_1in 4:15 0.0245 133 | SCS_24h_Type_I_1in 4:30 0.0245 134 | SCS_24h_Type_I_1in 4:45 0.0245 135 | SCS_24h_Type_I_1in 5:00 0.0245 136 | SCS_24h_Type_I_1in 5:15 0.0245 137 | SCS_24h_Type_I_1in 5:30 0.0245 138 | SCS_24h_Type_I_1in 5:45 0.0245 139 | SCS_24h_Type_I_1in 6:00 0.031 140 | SCS_24h_Type_I_1in 6:15 0.031 141 | SCS_24h_Type_I_1in 6:30 0.031 142 | SCS_24h_Type_I_1in 6:45 0.031 143 | SCS_24h_Type_I_1in 7:00 0.038 144 | SCS_24h_Type_I_1in 7:15 0.038 145 | SCS_24h_Type_I_1in 7:30 0.038 146 | SCS_24h_Type_I_1in 7:45 0.038 147 | SCS_24h_Type_I_1in 8:00 0.05 148 | SCS_24h_Type_I_1in 8:15 0.05 149 | SCS_24h_Type_I_1in 8:30 0.07 150 | SCS_24h_Type_I_1in 8:45 0.07 151 | SCS_24h_Type_I_1in 9:00 0.098 152 | SCS_24h_Type_I_1in 9:15 0.098 153 | SCS_24h_Type_I_1in 9:30 0.236 154 | SCS_24h_Type_I_1in 9:45 0.612 155 | SCS_24h_Type_I_1in 10:00 0.136 156 | SCS_24h_Type_I_1in 10:15 0.136 157 | SCS_24h_Type_I_1in 10:30 0.082 158 | SCS_24h_Type_I_1in 10:45 0.082 159 | SCS_24h_Type_I_1in 11:00 0.06 160 | SCS_24h_Type_I_1in 11:15 0.06 161 | SCS_24h_Type_I_1in 11:30 0.06 162 | SCS_24h_Type_I_1in 11:45 0.052 163 | SCS_24h_Type_I_1in 12:00 0.048 164 | SCS_24h_Type_I_1in 12:15 0.048 165 | SCS_24h_Type_I_1in 12:30 0.042 166 | SCS_24h_Type_I_1in 12:45 0.042 167 | SCS_24h_Type_I_1in 13:00 0.042 168 | SCS_24h_Type_I_1in 13:15 0.042 169 | SCS_24h_Type_I_1in 13:30 0.038 170 | SCS_24h_Type_I_1in 13:45 0.038 171 | SCS_24h_Type_I_1in 14:00 0.0315 172 | SCS_24h_Type_I_1in 14:15 0.0315 173 | SCS_24h_Type_I_1in 14:30 0.0315 174 | SCS_24h_Type_I_1in 14:45 0.0315 175 | SCS_24h_Type_I_1in 15:00 0.0315 176 | SCS_24h_Type_I_1in 15:15 0.0315 177 | SCS_24h_Type_I_1in 15:30 0.0315 178 | SCS_24h_Type_I_1in 15:45 0.0315 179 | SCS_24h_Type_I_1in 16:00 0.024 180 | SCS_24h_Type_I_1in 16:15 0.024 181 | SCS_24h_Type_I_1in 16:30 0.024 182 | SCS_24h_Type_I_1in 16:45 0.024 183 | SCS_24h_Type_I_1in 17:00 0.024 184 | SCS_24h_Type_I_1in 17:15 0.024 185 | SCS_24h_Type_I_1in 17:30 0.024 186 | SCS_24h_Type_I_1in 17:45 0.024 187 | SCS_24h_Type_I_1in 18:00 0.024 188 | SCS_24h_Type_I_1in 18:15 0.024 189 | SCS_24h_Type_I_1in 18:30 0.024 190 | SCS_24h_Type_I_1in 18:45 0.024 191 | SCS_24h_Type_I_1in 19:00 0.024 192 | SCS_24h_Type_I_1in 19:15 0.024 193 | SCS_24h_Type_I_1in 19:30 0.024 194 | SCS_24h_Type_I_1in 19:45 0.024 195 | SCS_24h_Type_I_1in 20:00 0.0185 196 | SCS_24h_Type_I_1in 20:15 0.0185 197 | SCS_24h_Type_I_1in 20:30 0.0185 198 | SCS_24h_Type_I_1in 20:45 0.0185 199 | SCS_24h_Type_I_1in 21:00 0.0185 200 | SCS_24h_Type_I_1in 21:15 0.0185 201 | SCS_24h_Type_I_1in 21:30 0.0185 202 | SCS_24h_Type_I_1in 21:45 0.0185 203 | SCS_24h_Type_I_1in 22:00 0.0185 204 | SCS_24h_Type_I_1in 22:15 0.0185 205 | SCS_24h_Type_I_1in 22:30 0.0185 206 | SCS_24h_Type_I_1in 22:45 0.0185 207 | SCS_24h_Type_I_1in 23:00 0.0185 208 | SCS_24h_Type_I_1in 23:15 0.0185 209 | SCS_24h_Type_I_1in 23:30 0.0185 210 | SCS_24h_Type_I_1in 23:45 0.0185 211 | SCS_24h_Type_I_1in 24:00 0 212 | 213 | [REPORT] 214 | ;;Reporting Options 215 | INPUT YES 216 | CONTROLS NO 217 | SUBCATCHMENTS ALL 218 | NODES ALL 219 | LINKS ALL 220 | 221 | [TAGS] 222 | 223 | [MAP] 224 | DIMENSIONS -100.036 -181.979 708.126 213.879 225 | Units Feet 226 | 227 | [COORDINATES] 228 | ;;Node X-Coord Y-Coord 229 | ;;-------------- ------------------ ------------------ 230 | J1 0.000 0.000 231 | J2 238.750 -53.332 232 | J3 459.058 -113.145 233 | J4 671.391 -163.985 234 | 235 | [VERTICES] 236 | ;;Link X-Coord Y-Coord 237 | ;;-------------- ------------------ ------------------ 238 | 239 | [Polygons] 240 | ;;Subcatchment X-Coord Y-Coord 241 | ;;-------------- ------------------ ------------------ 242 | S1 110.154 195.885 243 | S1 110.154 47.351 244 | S1 -56.323 42.367 245 | S1 -63.301 181.928 246 | S1 110.154 195.885 247 | S2 394.261 131.088 248 | S2 410.211 -20.436 249 | S2 245.728 -19.439 250 | S2 235.759 110.154 251 | S2 394.261 131.088 252 | S3 660.425 55.326 253 | S3 657.435 -104.173 254 | S3 519.867 -96.198 255 | S3 509.898 50.342 256 | S3 660.425 55.326 257 | 258 | [SYMBOLS] 259 | ;;Gage X-Coord Y-Coord 260 | ;;-------------- ------------------ ------------------ 261 | 262 | -------------------------------------------------------------------------------- /testing/OutputTestModel_LargeOutput.inp: -------------------------------------------------------------------------------- 1 | [TITLE] 2 | 3 | [OPTIONS] 4 | ;;Options Value 5 | ;;------------------ ------------ 6 | FLOW_UNITS CFS 7 | INFILTRATION HORTON 8 | FLOW_ROUTING DYNWAVE 9 | START_DATE 11/29/2015 10 | START_TIME 00:00:00 11 | REPORT_START_DATE 11/29/2015 12 | REPORT_START_TIME 00:00:00 13 | END_DATE 11/28/2016 14 | END_TIME 00:00:00 15 | SWEEP_START 01/01 16 | SWEEP_END 12/31 17 | DRY_DAYS 0 18 | REPORT_STEP 00:00:01 19 | WET_STEP 00:05:00 20 | DRY_STEP 00:05:00 21 | ROUTING_STEP 1 22 | ALLOW_PONDING NO 23 | INERTIAL_DAMPING NONE 24 | VARIABLE_STEP 0.75 25 | LENGTHENING_STEP 0 26 | MIN_SURFAREA 12.557 27 | NORMAL_FLOW_LIMITED BOTH 28 | SKIP_STEADY_STATE NO 29 | FORCE_MAIN_EQUATION H-W 30 | LINK_OFFSETS DEPTH 31 | MIN_SLOPE 0 32 | MAX_TRIALS 8 33 | HEAD_TOLERANCE 0.005 34 | SYS_FLOW_TOL 5 35 | LAT_FLOW_TOL 5 36 | MINIMUM_STEP 0.5 37 | THREADS 1 38 | 39 | [EVAPORATION] 40 | ;;Type Parameters 41 | ;;------------- ---------- 42 | CONSTANT 0.0 43 | DRY_ONLY NO 44 | 45 | [RAINGAGES] 46 | ;; Rain Time Snow Data 47 | ;;Name Type Intrvl Catch Source 48 | ;;---------------- --------- ------ ------ ---------- 49 | SCS_24h_Type_I_1in INTENSITY 0:15 1.0 TIMESERIES SCS_24h_Type_I_1in 50 | 51 | [SUBCATCHMENTS] 52 | ;; Total Pcnt. Pcnt. Curb Snow 53 | ;;Name Raingage Outlet Area Imperv Width Slope Length Pack 54 | ;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- -------- 55 | S1 SCS_24h_Type_I_1in J1 1 100 500 0.5 0 56 | S2 SCS_24h_Type_I_1in J2 2 100 500 0.5 0 57 | S3 SCS_24h_Type_I_1in j3 3 100 500 0.5 0 58 | 59 | [SUBAREAS] 60 | ;;Subcatchment N-Imperv N-Perv S-Imperv S-Perv PctZero RouteTo PctRouted 61 | ;;-------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 62 | S1 0.01 0.1 0.05 0.05 25 OUTLET 63 | S2 0.01 0.1 0.05 0.05 25 OUTLET 64 | S3 0.01 0.1 0.05 0.05 25 OUTLET 65 | 66 | [INFILTRATION] 67 | ;;Subcatchment MaxRate MinRate Decay DryTime MaxInfil 68 | ;;-------------- ---------- ---------- ---------- ---------- ---------- 69 | S1 3 0.5 4 7 0 70 | S2 3 0.5 4 7 0 71 | S3 3 0.5 4 7 0 72 | 73 | [JUNCTIONS] 74 | ;; Invert Max. Init. Surcharge Ponded 75 | ;;Name Elev. Depth Depth Depth Area 76 | ;;-------------- ---------- ---------- ---------- ---------- ---------- 77 | J1 20.728 15 0 0 0 78 | J2 13.392 15 0 0 0 79 | J3 6.547 15 0 0 0 80 | 81 | [OUTFALLS] 82 | ;; Invert Outfall Stage/Table Tide 83 | ;;Name Elev. Type Time Series Gate Route To 84 | ;;-------------- ---------- ------------ ---------------- ---- ---------------- 85 | J4 0 FREE NO 86 | 87 | [CONDUITS] 88 | ;; Inlet Outlet Manning Inlet Outlet Init. Max. 89 | ;;Name Node Node Length N Offset Offset Flow Flow 90 | ;;-------------- ---------------- ---------------- ---------- ---------- ---------- ---------- ---------- ---------- 91 | C1 J1 J2 244.63 0.01 0 0 0 0 92 | C2 J2 J3 228.28 0.01 0 0 0 0 93 | C3 J3 J4 218.33 0.01 0 0 0 0 94 | 95 | [XSECTIONS] 96 | ;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels 97 | ;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- 98 | C1 CIRCULAR 1 0 0 0 1 99 | C2 CIRCULAR 1.5 0 0 0 1 100 | C3 CIRCULAR 2 0 0 0 1 101 | 102 | [LOSSES] 103 | ;;Link Inlet Outlet Average Flap Gate SeepageRate 104 | ;;-------------- ---------- ---------- ---------- ---------- ---------- 105 | 106 | [INFLOWS] 107 | ;; Param Units Scale Baseline Baseline 108 | ;;Node Parameter Time Series Type Factor Factor Value Pattern 109 | ;;-------------- ---------------- ---------------- -------- -------- -------- -------- -------- 110 | J1 FLOW "" FLOW 1.0 1 1 111 | J2 Flow "" FLOW 1.0 1 1 112 | J3 Flow "" FLOW 1.0 1 1 113 | 114 | [DWF] 115 | ;; Average Time 116 | ;;Node Parameter Value Patterns 117 | ;;-------------- ---------------- ---------- ---------- 118 | J1 FLOW 8 "" "" "" "" 119 | 120 | [TIMESERIES] 121 | ;;Name Date Time Value 122 | ;;-------------- ---------- ---------- ---------- 123 | ;SCS_24h_Type_I_1in design storm, total rainfall = 1 in, rain units = in/hr. 124 | SCS_24h_Type_I_1in 0:00 0.0175 125 | SCS_24h_Type_I_1in 0:15 0.0175 126 | SCS_24h_Type_I_1in 0:30 0.0175 127 | SCS_24h_Type_I_1in 0:45 0.0175 128 | SCS_24h_Type_I_1in 1:00 0.0175 129 | SCS_24h_Type_I_1in 1:15 0.0175 130 | SCS_24h_Type_I_1in 1:30 0.0175 131 | SCS_24h_Type_I_1in 1:45 0.0175 132 | SCS_24h_Type_I_1in 2:00 0.0205 133 | SCS_24h_Type_I_1in 2:15 0.0205 134 | SCS_24h_Type_I_1in 2:30 0.0205 135 | SCS_24h_Type_I_1in 2:45 0.0205 136 | SCS_24h_Type_I_1in 3:00 0.0205 137 | SCS_24h_Type_I_1in 3:15 0.0205 138 | SCS_24h_Type_I_1in 3:30 0.0205 139 | SCS_24h_Type_I_1in 3:45 0.0205 140 | SCS_24h_Type_I_1in 4:00 0.0245 141 | SCS_24h_Type_I_1in 4:15 0.0245 142 | SCS_24h_Type_I_1in 4:30 0.0245 143 | SCS_24h_Type_I_1in 4:45 0.0245 144 | SCS_24h_Type_I_1in 5:00 0.0245 145 | SCS_24h_Type_I_1in 5:15 0.0245 146 | SCS_24h_Type_I_1in 5:30 0.0245 147 | SCS_24h_Type_I_1in 5:45 0.0245 148 | SCS_24h_Type_I_1in 6:00 0.031 149 | SCS_24h_Type_I_1in 6:15 0.031 150 | SCS_24h_Type_I_1in 6:30 0.031 151 | SCS_24h_Type_I_1in 6:45 0.031 152 | SCS_24h_Type_I_1in 7:00 0.038 153 | SCS_24h_Type_I_1in 7:15 0.038 154 | SCS_24h_Type_I_1in 7:30 0.038 155 | SCS_24h_Type_I_1in 7:45 0.038 156 | SCS_24h_Type_I_1in 8:00 0.05 157 | SCS_24h_Type_I_1in 8:15 0.05 158 | SCS_24h_Type_I_1in 8:30 0.07 159 | SCS_24h_Type_I_1in 8:45 0.07 160 | SCS_24h_Type_I_1in 9:00 0.098 161 | SCS_24h_Type_I_1in 9:15 0.098 162 | SCS_24h_Type_I_1in 9:30 0.236 163 | SCS_24h_Type_I_1in 9:45 0.612 164 | SCS_24h_Type_I_1in 10:00 0.136 165 | SCS_24h_Type_I_1in 10:15 0.136 166 | SCS_24h_Type_I_1in 10:30 0.082 167 | SCS_24h_Type_I_1in 10:45 0.082 168 | SCS_24h_Type_I_1in 11:00 0.06 169 | SCS_24h_Type_I_1in 11:15 0.06 170 | SCS_24h_Type_I_1in 11:30 0.06 171 | SCS_24h_Type_I_1in 11:45 0.052 172 | SCS_24h_Type_I_1in 12:00 0.048 173 | SCS_24h_Type_I_1in 12:15 0.048 174 | SCS_24h_Type_I_1in 12:30 0.042 175 | SCS_24h_Type_I_1in 12:45 0.042 176 | SCS_24h_Type_I_1in 13:00 0.042 177 | SCS_24h_Type_I_1in 13:15 0.042 178 | SCS_24h_Type_I_1in 13:30 0.038 179 | SCS_24h_Type_I_1in 13:45 0.038 180 | SCS_24h_Type_I_1in 14:00 0.0315 181 | SCS_24h_Type_I_1in 14:15 0.0315 182 | SCS_24h_Type_I_1in 14:30 0.0315 183 | SCS_24h_Type_I_1in 14:45 0.0315 184 | SCS_24h_Type_I_1in 15:00 0.0315 185 | SCS_24h_Type_I_1in 15:15 0.0315 186 | SCS_24h_Type_I_1in 15:30 0.0315 187 | SCS_24h_Type_I_1in 15:45 0.0315 188 | SCS_24h_Type_I_1in 16:00 0.024 189 | SCS_24h_Type_I_1in 16:15 0.024 190 | SCS_24h_Type_I_1in 16:30 0.024 191 | SCS_24h_Type_I_1in 16:45 0.024 192 | SCS_24h_Type_I_1in 17:00 0.024 193 | SCS_24h_Type_I_1in 17:15 0.024 194 | SCS_24h_Type_I_1in 17:30 0.024 195 | SCS_24h_Type_I_1in 17:45 0.024 196 | SCS_24h_Type_I_1in 18:00 0.024 197 | SCS_24h_Type_I_1in 18:15 0.024 198 | SCS_24h_Type_I_1in 18:30 0.024 199 | SCS_24h_Type_I_1in 18:45 0.024 200 | SCS_24h_Type_I_1in 19:00 0.024 201 | SCS_24h_Type_I_1in 19:15 0.024 202 | SCS_24h_Type_I_1in 19:30 0.024 203 | SCS_24h_Type_I_1in 19:45 0.024 204 | SCS_24h_Type_I_1in 20:00 0.0185 205 | SCS_24h_Type_I_1in 20:15 0.0185 206 | SCS_24h_Type_I_1in 20:30 0.0185 207 | SCS_24h_Type_I_1in 20:45 0.0185 208 | SCS_24h_Type_I_1in 21:00 0.0185 209 | SCS_24h_Type_I_1in 21:15 0.0185 210 | SCS_24h_Type_I_1in 21:30 0.0185 211 | SCS_24h_Type_I_1in 21:45 0.0185 212 | SCS_24h_Type_I_1in 22:00 0.0185 213 | SCS_24h_Type_I_1in 22:15 0.0185 214 | SCS_24h_Type_I_1in 22:30 0.0185 215 | SCS_24h_Type_I_1in 22:45 0.0185 216 | SCS_24h_Type_I_1in 23:00 0.0185 217 | SCS_24h_Type_I_1in 23:15 0.0185 218 | SCS_24h_Type_I_1in 23:30 0.0185 219 | SCS_24h_Type_I_1in 23:45 0.0185 220 | SCS_24h_Type_I_1in 24:00 0 221 | 222 | [REPORT] 223 | INPUT YES 224 | CONTROLS NO 225 | SUBCATCHMENTS ALL 226 | NODES ALL 227 | LINKS ALL 228 | 229 | [TAGS] 230 | 231 | [MAP] 232 | DIMENSIONS -100.0356 -181.9785 708.1256 213.8785 233 | UNITS Feet 234 | 235 | [COORDINATES] 236 | ;;Node X-Coord Y-Coord 237 | ;;-------------- ---------------- ---------------- 238 | J1 0 0 239 | J2 238.75 -53.332 240 | J3 459.058 -113.145 241 | J4 671.391 -163.985 242 | 243 | [VERTICES] 244 | ;;Link X-Coord Y-Coord 245 | ;;-------------- ---------------- ---------------- 246 | 247 | [POLYGONS] 248 | ;;Subcatchment X-Coord Y-Coord 249 | ;;-------------- ---------------- ---------------- 250 | S1 110.154 195.885 251 | S1 110.154 47.351 252 | S1 -56.323 42.367 253 | S1 -63.301 181.928 254 | S1 110.154 195.885 255 | S2 394.261 131.088 256 | S2 410.211 -20.436 257 | S2 245.728 -19.439 258 | S2 235.759 110.154 259 | S2 394.261 131.088 260 | S3 660.425 55.326 261 | S3 657.435 -104.173 262 | S3 519.867 -96.198 263 | S3 509.898 50.342 264 | S3 660.425 55.326 265 | 266 | [SYMBOLS] 267 | ;;Gage X-Coord Y-Coord 268 | ;;-------------- ---------------- ---------------- 269 | -------------------------------------------------------------------------------- /testing/PySWMMReadOutput.py: -------------------------------------------------------------------------------- 1 | from ctypes import * import sys sys.path.append("..") from _toolkitpyswmm import * #Used just to pull the Pointer of the SMOutputAPI struct class _Opaque(Structure): pass FileLoc = 'C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\OutputTestModel522_SHORT.out' ## READ DLL TestDLL = CDLL('C:\\PROJECTCODE\\SWMMOutputAPI\\data\\outputAPI_winx86.dll') ## Pointer to SMOutputAPI struct opaque_ptr = POINTER(_Opaque) smoapi = pointer(_Opaque()) #OPEN FILE FUNCTION HANDLE OpenFunc = TestDLL.SMR_open OpenFunc.argtypes = [POINTER(c_char), POINTER(POINTER(_Opaque))] OpenFunc.restype = c_int OpaqueStruc = c_long ret = OpenFunc(FileLoc, byref(smoapi)) print "Function Returns: "+ str(ret) SMO_getProjectSize = TestDLL.SMO_getProjectSize SMO_getProjectSize.argtypes = [POINTER(_Opaque), c_int, POINTER(c_int)] SMO_getProjectSize.restype = c_int ######################## ##SMO_getProjectSize(SMOutputAPI* smoapi, SMO_elementCount code, int* count); x = c_int() Ret2 = SMO_getProjectSize(smoapi, subcatchCount, byref(x)) print Ret2 print "Subcatchments: " + str(x.value) x = c_int() Ret2 = SMO_getProjectSize(smoapi, nodeCount, byref(x)) print Ret2 print "Nodes: " + str(x.value) x = c_int() Ret2 = SMO_getProjectSize(smoapi, linkCount, byref(x)) print Ret2 print "Links: " + str(x.value) x = c_int() Ret2 = SMO_getProjectSize(smoapi, pollutantCount, byref(x)) print Ret2 print "Pollutants: " + str(x.value) ######################### print "\n\nTesting Times" ###int DLLEXPORT SMO_getTimes(SMOutputAPI* smoapi, SMO_time code, int* time); SMO_getTimes = TestDLL.SMO_getTimes SMO_getTimes.argtypes = [POINTER(_Opaque), c_int, POINTER(c_int)] SMO_getTimes.restype = c_int StartTime = c_int() Ret2 = SMO_getTimes(smoapi, reportStart, byref(StartTime)) print Ret2 print "StartTime: " + str(StartTime.value) NPeriods = c_int() Ret2 = SMO_getTimes(smoapi, numPeriods, byref(NPeriods)) print Ret2 print "Number of Periods:" + str(NPeriods.value) ################################# class _ReturnIDS(Structure): pass _ReturnIDS._fields_ = [ ("ID", c_char_p), ("next", POINTER(_ReturnIDS))] _getSubcatchIDs = TestDLL.SMO_getSubcatchIDs _getSubcatchIDs.restype = POINTER(_ReturnIDS) ErrNo1 = c_int() id_List = _getSubcatchIDs(smoapi, byref(ErrNo1)) print ErrNo1.value ############################ ##int DLLEXPORT SMO_getUnits(SMOutputAPI* smoapi, SMO_unit code, int* unitFlag); ############################# print "\n\nTesting Build Array" ##float* DLLEXPORT SMO_newOutValueArray(SMOutputAPI* smoapi, SMO_apiFunction func, ## SMO_elementType type, int* length, int* errcode); SMO_newOutValueArray = TestDLL.SMO_newOutValueArray SMO_newOutValueArray.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_int), POINTER(c_int)] SMO_newOutValueArray.restype = POINTER(c_float) ##int DLLEXPORT SMO_getSubcatchResult(SMOutputAPI* smoapi, int timeIndex, int subcatchIndex, ## float* outValueArray); SMO_getSubcatchResult = TestDLL.SMO_getSubcatchResult SMO_getSubcatchResult.argtypes = [POINTER(_Opaque), c_int, c_int,\ POINTER(c_float)] SMO_getSubcatchResult.restype = c_int ##int DLLEXPORT SMO_getNodeResult(SMOutputAPI* smoapi, int timeIndex, int nodeIndex, ## float* outValueArray); SMO_getNodeResult = TestDLL.SMO_getNodeResult SMO_getNodeResult.argtypes = [POINTER(_Opaque), c_int, c_int,\ POINTER(c_float)] SMO_getNodeResult.restype = c_int ##int DLLEXPORT SMO_getLinkResult(SMOutputAPI* smoapi, int timeIndex, int linkIndex, ## float* outValueArray); SMO_getLinkResult = TestDLL.SMO_getLinkResult SMO_getLinkResult.argtypes = [POINTER(_Opaque), c_int, c_int,\ POINTER(c_float)] SMO_getLinkResult.restype = c_int ##int DLLEXPORT SMO_getSystemResult(SMOutputAPI* smoapi, int timeIndex, float* outValueArray); SMO_getSystemResult = TestDLL.SMO_getSystemResult SMO_getSystemResult.argtypes = [POINTER(_Opaque), c_int, POINTER(c_float)] SMO_getSystemResult.restype = c_int alength = c_int() aerror = c_int() Array0 = SMO_newOutValueArray(smoapi, getResult, SM_subcatch, byref(alength), byref(aerror)) print "Error: "+str(aerror.value) print "Array Length: " + str(alength.value) ##print Array0 SMO_getSubcatchResult(smoapi, 0, 0, Array0) NewArray = [float]*alength.value for i in range(alength.value): print Array0[i] NewArray[i] = Array0[i] SMO_free = TestDLL.SMO_free SMO_free.argtypes = [POINTER(_Opaque),POINTER(c_float)] SMO_free.restype = c_int SMO_free(smoapi, Array0) print "\n\nTesting Free Memory" for i in range(alength.value): print Array0[i] ####################################### print "\n\nTesting Build Series" ##float* DLLEXPORT SMO_newOutValueSeries(SMOutputAPI* smoapi, int seriesStart, ## int seriesLength, int* length, int* errcode); SMO_newOutValueSeries = TestDLL.SMO_newOutValueSeries SMO_newOutValueSeries.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_int), POINTER(c_int)] SMO_newOutValueSeries.restype = POINTER(c_float) ##int DLLEXPORT SMO_getSubcatchSeries(SMOutputAPI* smoapi, int subcatchIndex, ## SMO_subcatchAttribute attr, int timeIndex, int length, float* outValueSeries); SMO_getSubcatchSeries = TestDLL.SMO_getSubcatchSeries SMO_getSubcatchSeries.argtypes = [POINTER(_Opaque), c_int, c_int, c_int, c_int, POINTER(c_float)] SMO_getSubcatchSeries.restype = c_int ##int DLLEXPORT SMO_getSubcatchSeries(SMOutputAPI* smoapi, int subcatchIndex, ## SMO_subcatchAttribute attr, int timeIndex, int length, float* outValueSeries); SMO_getNodeSeries = TestDLL.SMO_getNodeSeries SMO_getNodeSeries.argtypes = [POINTER(_Opaque), c_int, c_int, c_int, c_int, POINTER(c_float)] SMO_getNodeSeries.restype = c_int ##int DLLEXPORT SMO_getSubcatchSeries(SMOutputAPI* smoapi, int subcatchIndex, ## SMO_subcatchAttribute attr, int timeIndex, int length, float* outValueSeries); SMO_getLinkSeries = TestDLL.SMO_getLinkSeries SMO_getLinkSeries.argtypes = [POINTER(_Opaque), c_int, c_int, c_int, c_int, POINTER(c_float)] SMO_getLinkSeries.restype = c_int ##int DLLEXPORT SMO_getSystemSeries(SMOutputAPI* smoapi, SMO_systemAttribute attr, ## int timeIndex, int length, float *outValueSeries); SMO_getSystemSeries = TestDLL.SMO_getSystemSeries SMO_getSystemSeries.argtypes = [POINTER(_Opaque), c_int, c_int, c_int, POINTER(c_float)] SMO_getSystemSeries.restype = c_int slength = c_int() aerror = c_int() seriesStart = 0 seriesLength = 100000 Series0 = SMO_newOutValueSeries(smoapi, seriesStart, seriesLength, byref(slength), byref(aerror)) ret = SMO_getSubcatchSeries(smoapi, 0, runoff_rate, 0, slength.value, Series0) NewSeries = [float]*slength.value print "\n\n\nTesting Series " for i in range(slength.value): NewSeries[i] = Series0[i] ## print NewSeries[i] SMO_free(smoapi, Series0) ####################################### print "\n\nTesting Series for one TS for one Attr for all Objects" ##int DLLEXPORT SMO_getSubcatchAttribute(SMOutputAPI* smoapi, int timeIndex, ## SMO_subcatchAttribute attr, float* outValueArray); SMO_getSubcatchAttribute = TestDLL.SMO_getSubcatchAttribute SMO_getSubcatchAttribute.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_float)] SMO_getSubcatchAttribute.restype = c_int ##int DLLEXPORT SMO_getNodeAttribute(SMOutputAPI* smoapi, int timeIndex, ## SMO_nodeAttribute attr, float* outValueArray); SMO_getNodeAttribute = TestDLL.SMO_getNodeAttribute SMO_getNodeAttribute.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_float)] SMO_getNodeAttribute.restype = c_int ##int DLLEXPORT SMO_getLinkAttribute(SMOutputAPI* smoapi, int timeIndex, ## SMO_linkAttribute attr, float* outValueArray); SMO_getLinkAttribute = TestDLL.SMO_getLinkAttribute SMO_getLinkAttribute.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_float)] SMO_getLinkAttribute.restype = c_int ##int DLLEXPORT SMO_getSystemAttribute(SMOutputAPI* smoapi, int timeIndex, ## SMO_systemAttribute attr, float* outValueArray); SMO_getSystemAttribute = TestDLL.SMO_getSystemAttribute SMO_getSystemAttribute.argtypes = [POINTER(_Opaque), c_int, c_int, POINTER(c_float)] SMO_getSystemAttribute.restype = c_int alength = c_int() aerror = c_int() Array12 = SMO_newOutValueArray(smoapi, getAttribute, SM_subcatch, byref(alength), byref(aerror)) print "Error: "+str(aerror.value) print "Array Length: " + str(alength.value) ##print Array0 SMO_getNodeAttribute(smoapi, 19, hydraulic_head, Array12) NewArray = [float]*alength.value for i in range(alength.value): NewArray[i] = Array12[i] print NewArray[i] SMO_free(smoapi, Array12) ######################### Close Test SMO_close = TestDLL.SMO_close SMO_close.argtypes = [POINTER(_Opaque)] SMO_close.restype = c_int Ret2 = SMO_close(smoapi) print "Closed funct" + str(Ret2) -------------------------------------------------------------------------------- /testing/QuickWrapperTesting.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('..') 3 | 4 | from datetime import datetime, timedelta 5 | from SWMMOutputReader import * 6 | import matplotlib.pyplot as plt 7 | 8 | OutputCollections = SwmmOutputObjects('../data/outputAPI_winx86.dll') 9 | OutputCollections.OpenBinFile('C:/PROJECTCODE/SWMMOutputAPI/testing/OutputTestModel522_SHORT.out') 10 | 11 | Periods = OutputCollections.get_Times(numPeriods) 12 | StartTime = OutputCollections.get_StartTime() 13 | DeltaT = OutputCollections.get_Times(reportStep)#seconds 14 | OutputCollections.get_ProjectSize(SM_subcatch) 15 | ##SUBC = OutputCollections.get_SubcatchIDs() 16 | ##NODE = OutputCollections.get_NodeIDs() 17 | ##LINK = OutputCollections.get_LinkIDs() 18 | ## 19 | ##TM =OutputCollections.get_StrStartTime() 20 | ##DTime = datetime.strptime(TM,'%Y-%b-%d %H:%M:%S') 21 | ## 22 | ##DateSeries = [DTime +timedelta(seconds = ind*DeltaT) for ind in range(Periods)] 23 | ##DataSeries1 = OutputCollections.get_LinkSeries(LINK['C1:C2'],flow_rate_link) 24 | ##DataSeries2= OutputCollections.get_LinkSeries(LINK['C2'],flow_rate_link) 25 | ##DataSeries3 = OutputCollections.get_LinkSeries(LINK['C3'],flow_rate_link) 26 | ## 27 | ##fig = plt.figure() 28 | ##ax1 = fig.add_subplot(111) 29 | ##ax1.plot(DateSeries, DataSeries1, label = 'C1:C2') 30 | ##ax1.plot(DateSeries, DataSeries2, label = 'C2') 31 | ##ax1.plot(DateSeries, DataSeries3, label = 'C3') 32 | ##ax1.legend() 33 | ##plt.show() 34 | 35 | 36 | OutputCollections.CloseBinFile() 37 | -------------------------------------------------------------------------------- /testing/QuickWrapperTesting_LargeFile.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append('..') 3 | 4 | from datetime import datetime, timedelta 5 | from SWMMOutputReader import * 6 | import matplotlib.pyplot as plt 7 | 8 | OutputCollections = SwmmOutputObjects('../data/outputAPI_winx86.dll') 9 | OUTFILES = ['C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\OutputTestModel_LargeOutput.out']#,\ 10 | ## 'C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\OutputTestModel522_SHORT.out',\ 11 | ## 'C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\SSCM12_RPM_BAS_wRT-DSS_6Storm_NoCEPT330_01-03.out'] 12 | 13 | for indMAIN, val in enumerate(OUTFILES): 14 | OutputCollections.OpenBinFile(val) 15 | 16 | Periods = OutputCollections.get_Times(numPeriods, OutInd = indMAIN) 17 | print Periods 18 | StartTime = OutputCollections.get_StartTime(OutInd = indMAIN) 19 | DeltaT = OutputCollections.get_Times(reportStep,OutInd = indMAIN)#seconds 20 | ProjectSize = OutputCollections.get_ProjectSize(SM_node,OutInd = indMAIN) 21 | SUBC = OutputCollections.get_SubcatchIDs(OutInd = indMAIN) 22 | NODE = OutputCollections.get_NodeIDs(OutInd = indMAIN) 23 | LINK = OutputCollections.get_LinkIDs(OutInd = indMAIN) 24 | print len(NODE) 25 | TM =OutputCollections.get_StrStartTime(OutInd = indMAIN) 26 | DTime = datetime.strptime(TM,'%Y-%b-%d %H:%M:%S') 27 | 28 | #DateSeries = [DTime +timedelta(seconds = ind*DeltaT) for ind in range(Periods)] 29 | 30 | # OutputCollections.OpenBinFile('C:\\PROJECTCODE\\SWMMOutputAPI\\testing\\SSCM12_RPM_BAS_wRT-DSS_6Storm_NoCEPT330_01-03.out') 31 | 32 | ##SUBC1 = OutputCollections.get_SubcatchIDs(1) 33 | ##NODE1 = OutputCollections.get_NodeIDs(1) 34 | ##LINK1 = OutputCollections.get_LinkIDs(1) 35 | 36 | 37 | ##print "in" 38 | ##DataSeries1 = OutputCollections.get_NodeSeries(NODE['0034S0264'],invert_depth) 39 | ##DataSeries2= OutputCollections.get_LinkSeries(LINK['C2'],flow_rate_link) 40 | ##DataSeries3 = OutputCollections.get_LinkSeries(LINK['C3'],flow_rate_link) 41 | ##print "out" 42 | ##fig = plt.figure() 43 | ##ax1 = fig.add_subplot(111) 44 | ##ax1.plot(DateSeries, DataSeries1, label = 'C1:C2') 45 | ##ax1.plot(DateSeries, DataSeries2, label = 'C2') 46 | ##ax1.plot(DateSeries, DataSeries3, label = 'C3') 47 | ##ax1.legend() 48 | ##plt.show() 49 | 50 | 51 | 52 | 53 | 54 | 55 | ##OutputCollections.CloseBinFile() 56 | -------------------------------------------------------------------------------- /testing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bemcdonnell/SWMMOutputAPI/5e6154f36e0d55c25ef40726a852d8a31d4a7d28/testing/__init__.py --------------------------------------------------------------------------------