Skip to content
Snippets Groups Projects
Commit 39fa9b51 authored by Christoph Knote's avatar Christoph Knote
Browse files

Switch to Poetry, package clean up.

parent e37272f6
No related branches found
No related tags found
No related merge requests found
boxmox.egg-info/dependency_links.txt
boxmox.egg-info/entry_points.txt
boxmox.egg-info/not-zip-safe
boxmox.egg-info/PKG-INFO
boxmox.egg-info/requires.txt
boxmox.egg-info/SOURCES.txt
boxmox.egg-info/top_level.txt
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
Changelog
=========
# Changelog
1.1.0 (2020-09-16)
------------------
## 1.2.0 (2022-03-08)
- Updates to be compatible with BOXMOX 1.8
## 1.1.0 (2020-09-16)
- Python 3 compatible
1.0.0 (2017-12-19)
------------------
## 1.0.0 (2017-12-19)
- Peer-reviewed version to be published in Knote et al., GMD
0.1.0 (2017-08-12)
------------------
## 0.1.0 (2017-08-12)
- Initial release
```
pip install boxmox
```
The BOXMOX chemical box model needs to be installed and usable,
and the KPP_HOME environment variable has to be set.
Set the BOXMOX environmental variable in ~/.bashrc or similar for your shell:
```
export BOXMOX_WORK_PATH=/where/you/want/boxmox/to/write/stuff/to/
```
Remember to close the shell and log in again for these changes to take effect.
::
pip install boxmox
Set the BOXMOX environmental variable in ~/.bashrc::
export BOXMOX_WORK_PATH=/where/you/want/boxmox/to/write/stuff/to/
Remember to close the shell and log in again for these changes to take effect.
exclude boxmox/hub.py
exclude boxmox/_site_specific.py
exclude src/boxmox/_site_specific.py
recursive-include examples *
include CHANGES.rst
include INSTALL.rst
include CHANGES.md
include INSTALL.md
include README.md
include LICENSE.txt
include README.rst
.Phony: coverage
coverage:
coverage run --source=tests -m unittest discover
======
boxmox
======
# BOXMOX
``boxmox`` is the Python wrapper for the chemical box model BOXMOX (a standalone
C/Fortran executable)
Documentation
=============
## Documentation
maintained at https://boxmodeling.meteo.physik.uni-muenchen.de/documentation
maintained at http://mbees.med.uni-augsburg.de/boxmodeling/
Installation
============
## Installation
The chemical box model BOXMOX is required. See the documentation for
detailed instructions on how to install it.
\ No newline at end of file
import sys
def _plotExperimentParser():
from argparse import ArgumentParser
parser = ArgumentParser(description='BOXMOX experiment plotter.')
parser.add_argument('species', type=str,
help='One or several (comma separated) species names to be plotted')
parser.add_argument('-e', '--experimentPath', type=str, default="./",
help='Path to the experiment to be used. Defaults to current directory.')
parser.add_argument('-f', '--outputFile', type=str, default='plot.png',
help='Name (or full path) of the output (png) file')
parser.add_argument('--timeLimits', type=str, default=None,
help='Time axis limits (as "min,max") in time units.')
return parser
def plotExperiment(args=None):
if args is None:
args = sys.argv[1:]
parser = _plotExperimentParser()
args = parser.parse_args()
import boxmox
try:
from . import ExperimentPlotter as ep
except:
import warnings
warnings.warn("Plotting disabled - is matplotlib installed?")
return
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
exp = boxmox.ExperimentFromExistingRun(args.experimentPath)
tmin = tmax = None
if not args.timeLimits is None:
tmin = float(args.timeLimits.split(",")[0])
tmax = float(args.timeLimits.split(",")[1])
exp.plot(args.species.split(","), tmin=tmin, tmax=tmax)
plt.savefig(args.outputFile)
import os
import sys
if os.name == 'posix' and sys.version_info[0] < 3:
import subprocess32 as s
else:
import subprocess as s
def validate():
# 1) BOXMOX is installed and working
if 'KPP_HOME' in os.environ.keys():
try:
res = s.check_call("validate_BOXMOX_installation")
except:
print("BOXMOX installation broken!")
return None
else:
print('$KPP_HOME not found in environment - is BOXMOX installed?')
return None
# 2) an work directory has been defined and is useable
if 'BOXMOX_WORK_PATH' in os.environ.keys():
work_path = os.environ['BOXMOX_WORK_PATH']
try:
if not os.path.isdir(work_path):
os.makedirs(work_path)
except:
print("Could not create work directory " + work_path)
return None
else:
print('BOXMOX_WORK_PATH not found in environment - set it to a path were BOXMOX can write stuff to.')
return None
return work_path
#import os
#import pwd
#user=pwd.getpwuid(os.getuid()) # full /etc/passwd info
# possibly, www-data needs to know where BOXMOX is
#KPP_HOME="/var/www/inBOX/boxmox/bin/boxmox"
#
#if not 'KPP_HOME' in os.environ.keys() or user.pw_name == "www-data" or user.pw_name == "apache":
# os.environ["KPP_HOME"] = KPP_HOME
# os.environ["PATH"] += ":"+KPP_HOME+"/bin:"+KPP_HOME+"/boxmox/bin"
# os.environ["BOXMOX_WORK_PATH"] = "/var/www/inBOX/boxmox/tmp"
#
# Author: Christoph Knote <christoph.knote@physik.uni-muenchen.de>
# Copyright: GNU General Public License Version 3, 29 June 2007
"""
A python interface for the chemistry box model BOXMOX
How to use this module
======================
1. Import it: ``import boxmox.model``
2. Create a new experiment either from scratch or from
one of the examples provided
3. Run the experiment
4. Use the output
Notes
=====
- BOXMOX needs to be installed and working
(http://boxmodeling.meteo.physik.uni-muenchen.de)
- Any chemical mechanism you want to use must have been
prepared for BOXMOX (see BOXMOX documentation)
"""
__docformat__ = 'restructuredtext'
import os
import shutil
import sys
import tempfile
if os.name == 'posix' and sys.version_info[0] < 3:
import subprocess32 as s
else:
import subprocess as s
import f90nml
from . import experiment
class Hub(object):
def __init__(self):
self.workPath = validateInstall()
if self.workPath is None:
raise
self.boxmoxPath = os.path.join(os.environ['KPP_HOME'], "boxmox")
self.jobs = {}
def _get_job_id(self):
import random
return random.randint(0, 2**16-1)
def list_examples(self):
'''
List examples that come with your BOXMOX installation.
'''
return experiment.examples.keys()
def list_compiled_mechs(self, includeAdjoints=False):
'''
List compiled BOXMOX mechanisms.
Parameters
- `includeAdjoints: a boolean, whether to include the adjoint versions
of mechanisms
'''
mechsPath=os.path.join(os.environ['KPP_HOME'], "boxmox", "compiled_mechs")
mechs=os.listdir(mechsPath)
if not includeAdjoints:
mechs = [ x for x in mechs if not "_adjoint" in x ]
mechs.sort()
return mechs
def list_experiment_input_files(self, id):
'''
List input files that exist for a given BOXMOX experiment
Parameters:
- `exp`: a string, the name of the experiment
'''
return self.jobs[id].input.keys()
def list_experiment_output_files(self, id):
'''
List output files that exist for a given BOXMOX experiment
Parameters:
- `exp`: a string, the name of the experiment
'''
return self.jobs[id].output.keys()
# Translation functions
def __translate_fromto_mechanism(self, mechanism, species, dir):
xfrom = 0
xto = 1
if dir == 'from':
xfrom = 1
xto = 0
equiv_path=os.path.join(os.environ['KPP_HOME'], "examples", mechanism + "_wrfkpp.equiv")
if isinstance(species, (str, unicode)):
species = [ species ]
species_out = species
if os.path.exists(equiv_path):
f = open(equiv_path, "r")
thes = [ i.split() for i in f.readlines() if not "!" in i ]
f.close()
species_out = []
for spec in species:
new_spec = spec
for pair in thes:
if pair[xfrom].lower() == spec.lower():
new_spec = pair[xto]
species_out.append(new_spec)
return species_out
def translate_to_mechanism(self, mechanism, species):
'''
Translate from WRF species name to mechanism species name
Parameters:
- `mechanism`: a string, the name of the chemical mechanism
- `species`: a string, the name of the species to translate
'''
return self.__translate_fromto_mechanism(mechanism, species, dir='to')
def translate_from_mechanism(self, mechanism, species):
'''
Translate from mechanism species name to WRF species name
Parameters:
- `mechanism`: a string, the name of the chemical mechanism
- `species`: a string, the name of the species to translate
'''
return self.__translate_fromto_mechanism(mechanism, species, dir='from')
# namelists
def new_namelist(self):
'''
Create a BOXMOX namelist object
'''
return experiment.Namelist()
def read_namelist(self, id):
'''
Read BOXMOX namelist for experiment
Parameters:
- `exp`: a string, the name of the experiment
'''
return self.jobs[id].namelist
def write_namelist(self, id, input_dict):
'''
Write BOXMOX namelist object to experiment directory
Parameters:
- `exp`: a string, the name of the experiment
- `input_dict`: a dictionary to be written to the namelist
file in the experiment directory
- `exp_path`: a string, the path to the experiment (optional)
'''
nml = self.jobs[id].namelist
input_dict_lower = dict((k.lower(), k) for k in input_dict.keys())
for key in nml.keys():
if key in input_dict_lower.keys():
val = input_dict[input_dict_lower[key]]
if isinstance(nml[key], float):
val = float(val)
elif isinstance(nml[key], bool):
val = val.lower() in ['t', 'true', '.true.'] # note that bools are instances of int as well!
elif isinstance(nml[key], int):
val = int(val)
else:
val = val.encode('ascii', 'ignore')
nml[key] = val
# Experiment creation
def new_experiment_from_example(self, example):
'''
Create new BOXMOX experiment based on example
Parameters:
- `example`: a string, the name of the example used to create the experiment
- `exp`: a string, the name of the experiment
'''
id = self._get_job_id()
self.jobs[id] = experiment.ExperimentFromExample(example)
return id
def new_experiment(self, mechanism):
'''
Create new BOXMOX experiment
Parameters:
- `exp`: a string, the name of the experiment
- `mechanism`: a string, the chemical mechanism to use
- `exp_path`: a string, the path where to create the experiment (optional)
'''
id = self._get_job_id()
self.jobs[id] = experiment.Experiment(mechanism)
return id
def get_file_contents(exp, filename, f=sys.stdout):
'''
Reads the contents of a text file in the experiment directory into the argument 'f'
Parameters:
- `exp`: a string, the name of the experiment
- `filename`: a string, path to the file to read
- `f`: the output object (defaults to sys.stdout)
'''
file_path = os.path.join(make_exp_path(exp), filename)
if os.path.isfile(file_path):
with open(file_path, 'r') as e:
f.write(e.read())
def put_file_contents(exp, filename, input_file_path, overwrite=False):
'''
Saves the contents of an input (text) file into a file in the experiment directory
Parameters:
- `exp`: a string, the name of the experiment
- `filename`: a string, the target filename
- `input_file_path`: a string, the path to the input file
- `overwrite`: a boolean, whether to overwrite the target file if it already exists
'''
file_path = os.path.join(make_exp_path(exp), filename)
if os.path.isfile(input_file_path):
if overwrite and os.path.exists(file_path):
os.remove(file_path)
if not os.path.exists(file_path):
shutil.copy(input_file_path, file_path)
else:
raise IOError('Destination file {:s} already exists.'.format(file_path))
# BOXMOX'in
def __get_mechanism(self, id):
return self.jobs[id].mechanism
def run_experiment(self, id):
'''
Run a previously prepared BOXMOX experiment
Parameters:
- `exp`: a string, the name of the experiment
'''
return self.jobs[id].run()
def run_experiment_async(exp, id=None):
'''
Run a previously prepared BOXMOX experiment asynchronous
Parameters:
- `exp`: a string, the name of the experiment
- `id`: an integer, use this ID to keep track of the experiment (optional)
'''
exp_path = make_exp_path(exp)
if not os.path.isdir(exp_path):
raise IOError('BOXMOX experiment path does not exist: ' + exp_path)
mechanism = __get_mechanism(exp)
if id is None:
id = __get_job_id()
try:
command = "./" + mechanism + ".exe > " + mechanism + ".log"
job_roster[id] = s.Popen(command,
shell=True,
cwd=exp_path,
universal_newlines=True)
return id, job_roster[id]
except Exception as exxy:
raise exxy("Running BOXMOX failed.")
def poll_experiment(id):
'''
Check for the current state of a running BOXMOX experiment
Parameters:
- `id`: an integer, the id of the experiment run
'''
result = False
if id in job_roster.keys():
tmp = job_roster[id].poll()
result = tmp == None
return result
# Work with output
def get_experiment_log(exp):
'''
Returns the BOXMOX experiment log
Parameters:
- `exp`: a string, the name of the experiment
'''
exp_path = make_exp_path(exp)
mechanism = __get_mechanism(exp)
log_file = os.path.join(exp_path, mechanism + ".log")
log = ""
if os.path.exists(log_file):
with open(log_file, "r") as f:
log = f.read()
return log
def read_concentrations(exp, variables=None):
"""
Return an np.array containing the concentration time series which are
the result of a BOXMOX experiment run
Parameters:
- `exp`: a string, the name of the experiment
- `variables`: a list of strings, the variable names to return (defaults to all variables)
"""
exp_path = make_exp_path(exp)
mechanism = __get_mechanism(exp)
return data.read_concentrations_from_file(os.path.join(exp_path, mechanism + ".conc"), variables)
def read_rates(exp):
"""
Return a dict containing the reaction rate coefficient time series which are
the result of a BOXMOX experiment run
Parameters:
- `exp`: a string, the name of the experiment
"""
exp_path = make_exp_path(exp)
mechanism = __get_mechanism(exp)
return data.read_rates_from_file(os.path.join(exp_path, mechanism + ".rates"))
def read_adjoint(exp, variables):
"""
Return an np.array containing the adjoint matrix which is
the result of a BOXMOX experiment run
Parameters:
- `exp`: a string, the name of the experiment
- `variables`: a list of strings, the variables to return
"""
exp_path = make_exp_path(exp)
mechanism = __get_mechanism(exp)
return data.read_adjoint_from_file(os.path.join(exp_path, mechanism + ".adjoint"), variables)
# Removing stuff
def remove_file(exp, filename):
'''
Remove a file in the experiment directory
Parameters:
- `exp`: a string, the name of the experiment
- `filename`: the file to remove
'''
file_path = os.path.join(make_exp_path(exp), filename)
if os.path.isfile(file_path):
os.remove(file_path)
def remove_experiment(exp):
'''
Remove BOXMOX experiment
Parameters:
- `exp`: a string, the name of the experiment
'''
exp_path = make_exp_path(exp)
if os.path.isdir(exp_path):
shutil.rmtree(exp_path, ignore_errors=False)
def cleanup_experiment(self, id):
'''
Clean up an existing BOXMOX experiment, so it can be re-run
'''
self.jobs[id]
# output files
nul = [ remove_file(exp, f) for f in list_experiment_output_files(exp) ]
# log files
log_file = os.path.join(make_exp_path(exp), __get_mechanism(exp), ".log")
remove_file(exp, log_file)
# saving the results
def archive(exp, archive_path):
'''
Archive BOXMOX experiment
'''
exp_path = make_exp_path(exp)
if os.path.isdir( archive_path ):
raise Exception('Target path {:s} already exists. Stopping.'.format(archive_path))
shutil.move( exp_path, archive_path )
[build-system]
requires = [
"numpy", "f90nml", "pyparsing", "setuptools"
]
build-backend = "setuptools.build_meta"
[metadata]
name = boxmox
version = 1.2.0
author = Christoph Knote
author_email = christoph.knote@med.uni-augsburg.de
description = BOXMOX python interface
long_description = file: README.md, INSTALL.md, CHANGES.md
long_description_content_type = text/markdown
url = https://mbees.med.uni-augsburg.de
project_urls =
Bug Tracker = http://mbees.med.uni-augsburg.de/gitlab/mbees/boxmox_pypackage/issues
classifiers =
Programming Language :: Python :: 3
Development Status :: 5 - Production/Stable
Environment :: Console
Intended Audience :: Developers
Intended Audience :: Education
Intended Audience :: End Users/Desktop
Intended Audience :: Science/Research
License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Operating System :: POSIX
Topic :: Education
Topic :: Scientific/Engineering
Topic :: Utilities
[options]
package_dir =
= src
packages = find:
python_requires = >=3.0
include_package_data = True
[options.packages.find]
where = src
[options.entry_points]
console_scripts =
plot_BOXMOX_experiment = boxmox._console:plotExperiment
import os
from setuptools import setup
def read(filename):
with open(os.path.join(os.path.dirname(__file__), filename)) as f:
return f.read()
setup(name='boxmox',
description='Python wrapper for the chemical box model BOXMOX',
long_description=read('README.rst') + '\n\n' + read('INSTALL.rst') + '\n\n' + read('CHANGES.rst'),
version='1.1.0',
url='https://boxmodeling.meteo.physik.uni-muenchen.de',
author='Christoph Knote',
author_email='christoph.knote@physik.uni-muenchen.de',
license='GPLv3',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: Education',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Operating System :: POSIX',
'Programming Language :: Python',
'Topic :: Education',
'Topic :: Scientific/Engineering',
'Topic :: Utilities'
],
keywords='',
packages=['boxmox'],
install_requires=['numpy', 'f90nml', 'pyparsing' ],
entry_points={
'console_scripts':
[
'plot_BOXMOX_experiment=boxmox._console:plotExperiment'
]
},
include_package_data=True,
zip_safe=False)
File moved
try:
from ._site_specific import *
except:
pass
import os
import subprocess as s
from . import _installation
# 1) BOXMOX is installed and working
if 'KPP_HOME' in os.environ.keys():
try:
res = s.check_call("validate_BOXMOX_installation")
except:
raise OSError("Cannot validate BOXMOX installation using validate_BOXMOX_installation!")
else:
raise OSError('$KPP_HOME not found in environment - is BOXMOX installed?')
from .data import InputFile, InputFileOrig, InputFile17, Output, ConcentrationOutput, RatesOutput, AdjointOutput, JacobianOutput, HessianOutput
from .fluxes import FluxParser
# 2) an work directory has been defined and is useable
work_path = "/does/not/exist"
if 'BOXMOX_WORK_PATH' in os.environ.keys():
work_path = os.environ['BOXMOX_WORK_PATH']
try:
if not os.path.isdir(work_path):
os.makedirs(work_path)
except:
raise OSError("Could not create work directory " + work_path)
else:
raise OSError('$BOXMOX_WORK_PATH not found in environment - set it to a path were BOXMOX can write stuff to.')
work_path = _installation.validate()
if work_path is None:
if not os.path.isdir(work_path):
import warnings
warnings.warn("BOXMOX unusable - experiment execution disabled.")
warnings.warn("BOXMOX model unusable - experiment execution disabled.")
else:
from .experiment import Experiment, ExperimentFromExample, ExperimentFromExistingRun, Namelist, examples, compiledMechs
from .data import InputFile, InputFileOrig, InputFile17, Output, ConcentrationOutput, RatesOutput, AdjointOutput, JacobianOutput, HessianOutput
from .fluxes import FluxParser
try:
import matplotlib
from .plotter import ExperimentPlotter
except:
import warnings
warnings.warn('matplotlib not found - plotting disabled.')
from . import _console
import os
import sys
import shutil
try:
from StringIO import StringIO ## for Python 2
except ImportError:
from io import StringIO ## for Python 3
from io import StringIO
import csv
import numpy as np
def _mygenfromtxt2(f):
curpos = f.tell()
try:
dialect = csv.Sniffer().sniff(f.read(1048576), delimiters=";, ")
dialect.skipinitialspace = True
f.seek(curpos)
spamreader = csv.reader(f, dialect)
except:
# could not determine dialect, falling back to default.
f.seek(curpos)
spamreader = csv.reader(f, skipinitialspace = True, delimiter=" ")
# twice as fast as np.genfromtxt(..., names=True)
hdr = next(spamreader)
dat = []
for row in spamreader:
dat.append( tuple(map(float, row)) )
return dat, hdr
def _mygenfromtxt(f):
curpos = f.tell()
try:
dialect = csv.Sniffer().sniff(f.read(1048576), delimiters=";, ")
dialect.skipinitialspace = True
f.seek(curpos)
spamreader = csv.reader(f, dialect)
except:
# could not determine dialect, falling back to default.
f.seek(curpos)
spamreader = csv.reader(f, skipinitialspace = True, delimiter=" ")
# twice as fast as np.genfromtxt(..., names=True)
hdr = next(spamreader)
dat = []
for row in spamreader:
dat.append( tuple(map(float, row)) )
return np.array(dat, dtype=[(_, float) for _ in hdr])
def InputFile(fpath=None, version=1.7):
'''
Returns an instance of a BOXMOX input file class, either old format if
version < 1.7 (class InputFileOrig), or the current file format
(class InputFile17).
'''
if not fpath is None:
# file format discovery: 3 lines with numbers ==> 1.7
with open(fpath, 'r') as f:
one = f.readline()
two = f.readline()
tre = f.readline()
try:
test = int(tre)
version = 1.7
except:
version = 1.0
pass
if version >= 1.7:
return InputFile17(fpath=fpath, version=version)
else:
return InputFileOrig(fpath=fpath)
class InputFile17:
class InputFile:
'''
A generic BOXMOX input file (>= v 1.7). Getting and setting of values
works like a dictionary::
......@@ -109,7 +46,22 @@ class InputFile17:
nvar = int(f.readline().replace(',', ''))
nanc = int(f.readline().replace(',', ''))
self.timeFormat = int(f.readline().replace(',', ''))
dmp, hdr = _mygenfromtxt2(f)
curpos = f.tell()
try:
dialect = csv.Sniffer().sniff(f.read(1048576), delimiters=";, ")
dialect.skipinitialspace = True
f.seek(curpos)
spamreader = csv.reader(f, dialect)
except:
# could not determine dialect, falling back to default.
f.seek(curpos)
spamreader = csv.reader(f, skipinitialspace = True, delimiter=" ")
# twice as fast as np.genfromtxt(..., names=True)
hdr = next(spamreader)
dmp = []
for row in spamreader:
dmp.append( tuple(map(float, row)) )
ntime = 0
if not self.timeFormat == 0:
......@@ -124,16 +76,13 @@ class InputFile17:
self.write(f)
return(f.getvalue())
def write(self, f=sys.stdout, version=1.7):
def write(self, f=sys.stdout):
'''
Write to <f>. <f> can be file handle or other connection. Defaults to sys.stdout.
'''
# possibility to create old version output from new version data
if version >= 1.7:
f.write('{0:1d}'.format(self.nvar) +'\n')
f.write('{0:1d}'.format(self.nanc) +'\n')
else:
f.write('{0:1d}'.format(self.nanc+self.nvar) +'\n')
f.write('{0:1d}'.format(self.nvar) +'\n')
f.write('{0:1d}'.format(self.nanc) +'\n')
f.write('{0:1d}'.format(self.timeFormat) +'\n')
data_names = [ key for key in self.keys() ]
......@@ -158,7 +107,7 @@ class InputFile17:
data_line = '{0:e}'.format(float(self.time)) + ' ' + data_line
f.write(data_line)
def __init__(self, fpath=None, version=1.7):
def __init__(self, fpath=None, version=1.8):
#: Time format (0: constant, 1: seconds since start, 2: hour of diurnal cycle)
self.timeFormat = 0
self.timeVar = 'time'
......@@ -173,95 +122,7 @@ class InputFile17:
#: File path of the underlying file (if it exists (yet))
self.fpath = fpath
if not self.fpath is None:
# try:
self.read(self.fpath)
# except Exception as e:
# print("Reading input file {:s} failed: {:s}".format(self.fpath, str(e)))
class InputFileOrig:
'''
A generic BOXMOX input file (< 1.7). Getting and setting of values
works like a dictionary::
print(inp['O3'])
inp['O3'] = 0.040
'''
@property
def nvar(self):
'''
Number of variables.
'''
return len( [ x for x in self.keys() if not x is self._timeVar ] )
def __getitem__(self, item):
return [ self._data[i] for i in item ] if isinstance(item, list) else self._data[item]
def __setitem__(self, item, values):
if isinstance(item, list):
for i, v in zip(item, values):
self._data[i] = v
else:
self._data[item] = values
def keys(self):
return self._data.keys()
def read(self, fpath):
'''
Read input file from path.
'''
with open(fpath, 'r') as f:
self.nvar = int(f.readline().replace(',', ''))
self.timeFormat = int(f.readline().replace(',', ''))
dmp = _mygenfromtxt(f)
if not self.timeFormat == 0:
self._timeVar = dmp.dtype.names[0]
self._data = { x: dmp[x] for x in dmp.dtype.names }
def __str__(self):
f = StringIO()
self.write(f)
return(f.getvalue())
def write(self, f=sys.stdout, version=1.0):
'''
Write to <f>. <f> can be file handle or other connection. Defaults to sys.stdout.
'''
f.write('{0:1d}'.format(self.nvar) +'\n')
if version >= 1.7:
f.write('{0:1d}'.format(0) +'\n')
f.write('{0:1d}'.format(self.timeFormat) +'\n')
column_names = [ key for key in self.keys() if key != self._timeVar ]
if self._timeVar in self.keys() and str(self.timeFormat) != "0" :
f.write('{0:s}' .format(' '.join([self._timeVar] + column_names)) + '\n')
for itime, xtime in enumerate(self._data[self._timeVar]):
line = [ xtime ] + [ self._data[key][itime] for key in column_names ]
f.write(' '.join('{0:e}'.format(x) for x in line) + '\n')
else:
f.write('{0:s}' .format(' '.join( column_names)) +'\n')
def _data_fix(key):
if isinstance(self._data[key], list):
return self._data[key][0]
else:
return self._data[key]
f.write(' '.join( '{0:e}'.format(float(_data_fix(x))) for x in self.keys() ) + '\n')
def __init__(self, fpath=None):
#: Time format (0: constant, 1: seconds since start, 2: hour of diurnal cycle)
self.timeFormat = 0
self._timeVar = 'time'
self._data = {}
self.version = 0.0
#: File path of the underlying file (if it exists (yet))
self.fpath = fpath
if not self.fpath is None:
try:
self.read(self.fpath)
except Exception as e:
print("Reading input file {:s} failed: {:s}".format(self.fpath, str(e)))
class Output(object):
'''
......@@ -318,8 +179,6 @@ class ConcentrationOutput(Output):
out = np.zeros( ( len(self.times), len(items) ) )
for i in range(len(items)):
out[:,i] = self.data[items[i]]
# old code - raises warning that it will break in the future (of numpy)
# out = self.data[items].view(dtype=np.float, type=np.ndarray).reshape((len(self.times), len(items)))
else:
out = self.data
return out
......@@ -515,7 +374,3 @@ class AdjointOutput(Output):
print("Problem reading adjoint value <{:s}>: {:s}".format(data[xstate_ind][ystate_ind], str(e)))
self.matrix = adj_mat
import os
import sys
if os.name == 'posix' and sys.version_info[0] < 3:
import subprocess32 as s
else:
import subprocess as s
import subprocess as s
import threading
import shutil
import fnmatch
......@@ -22,7 +18,7 @@ from . import FluxParser
work_path = _installation.validate()
examplesPath=os.path.join(os.environ['KPP_HOME'], "boxmox", "boxmox_examples")
examplesPath=os.path.join(os.environ['KPP_HOME'], "case_studies")
class ExampleData:
def __getitem__(self, name):
......@@ -40,7 +36,7 @@ class ExampleData:
except:
pass
compiledMechsPath=os.path.join(os.environ['KPP_HOME'], "boxmox", "compiled_mechs")
compiledMechsPath=os.path.join(os.environ['KPP_HOME'], "compiled_mechs")
compiledMechs = []
try:
......@@ -90,8 +86,7 @@ class Namelist:
def __init__(self, path = None):
self._namelist = None
firstExample = examples[list(examples.keys())[0]]
self.read(os.path.join(firstExample.path, "BOXMOX.nml"))
self.read(os.path.join(examplesPath, "BOXMOX.nml"))
if not path is None:
if os.path.exists(path):
self.read(path)
......@@ -135,7 +130,7 @@ class Experiment:
self.version = self._determineVersion(self.path)
def _determineVersion(self, path):
version = 1.0
version = 1.8
versionFile = os.path.join(path, 'VERSION')
if os.path.exists(versionFile):
try:
......@@ -144,10 +139,10 @@ class Experiment:
line = ".".join(line.split(".")[0:min(2, len(line.split(".")))])
# for development only:
if line == "__BOXMOX_VERSION__":
line = 1.7
line = 1.8
version = float(line)
except:
version = 1.0
version = 1.8
pass
return version
......
File moved
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment