# The Hazard Library
# Copyright (C) 2012-2014, GEM Foundation
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Module :mod:`openquake.hazardlib.imt` defines different intensity measure
types.
"""
import re
import operator
import functools
# NB: (MS) the management of the IMTs implemented here is horrible and will
# be thrown away when we will need to introduce a new IMT.
__all__ = ('PGA', 'PGV', 'PGD', 'SA', 'IA', 'CAV', 'RSD', 'MMI')
DEFAULT_SA_DAMPING = 5.0
def from_string(imt):
"""
Convert an IMT string into a hazardlib object.
:param str imt:
Intensity Measure Type.
"""
if 'SA' in imt:
match = re.match(r'^SA\(([^)]+?)\)$', imt)
period = float(match.group(1))
return SA(period, DEFAULT_SA_DAMPING)
else:
try:
imt_class = globals()[imt]
except KeyError:
raise ValueError('Unknown IMT: %s' % imt)
return imt_class(None, None)
@functools.total_ordering
class _IMT(tuple):
"""
Base class for intensity measure type.
Subclasses may define class attribute ``_fields`` as a tuple with names
of parameters the specific intensity measure type requires (if there
are any).
"""
_fields = ()
class __metaclass__(type):
def __new__(mcs, name, bases, dct):
dct['__slots__'] = ()
cls = type.__new__(mcs, name, bases, dct)
for index, field in enumerate(cls._fields):
setattr(cls, field, property(operator.itemgetter(index + 1)))
return cls
def __new__(cls, sa_period=None, sa_damping=None):
return tuple.__new__(cls, (cls.__name__, sa_period, sa_damping))
def __getnewargs__(self):
return tuple(getattr(self, field) for field in self._fields)
def __str__(self):
if self[0] == 'SA':
return 'SA(%s)' % self[1]
return self[0]
def __lt__(self, other):
return str(self) < str(other)
def __repr__(self):
return '%s(%s)' % (type(self).__name__,
', '.join('%s=%s' % (field, getattr(self, field))
for field in type(self)._fields))
[docs]class PGA(_IMT):
"""
Peak ground acceleration during an earthquake measured in units
of ``g``, times of gravitational acceleration.
"""
[docs]class PGV(_IMT):
"""
Peak ground velocity during an earthquake measured in units of ``cm/sec``.
"""
[docs]class PGD(_IMT):
"""
Peak ground displacement during an earthquake measured in units of ``cm``.
"""
[docs]class SA(_IMT):
"""
Spectral acceleration, defined as the maximum acceleration of a damped,
single-degree-of-freedom harmonic oscillator. Units are ``g``, times
of gravitational acceleration.
:param period:
The natural period of the oscillator in seconds.
:param damping:
The degree of damping for the oscillator in percents.
:raises ValueError:
if period or damping is not positive.
"""
_fields = ('period', 'damping')
def __new__(cls, period, damping=DEFAULT_SA_DAMPING):
if not period > 0:
raise ValueError('period must be positive')
if not damping > 0:
raise ValueError('damping must be positive')
return _IMT.__new__(cls, period, damping)
[docs]class IA(_IMT):
"""
Arias intensity. Determines the intensity of shaking by measuring
the acceleration of transient seismic waves. Units are ``m/s``.
"""
[docs]class CAV(_IMT):
"""
Cumulative Absolute Velocity. Defins the integral of the absolute
acceleration time series. Units are "g-sec"
"""
[docs]class RSD(_IMT):
"""
Relative significant duration, 5-95% of :class:`Arias intensity
<IA>`, in seconds.
"""
[docs]class MMI(_IMT):
"""
Modified Mercalli intensity, a Roman numeral describing the severity
of an earthquake in terms of its effects on the earth's surface
and on humans and their structures.
"""