Source code for oasislmf.pytools.converters.csvtobin.utils.damagebin

import numpy as np
from oasislmf.pytools.converters.csvtobin.utils.common import iter_csv_as_ndarray
from oasislmf.pytools.converters.data import TOOL_INFO
from oasislmf.pytools.gulmc.common import VALID_DAMAGE_TYPE
from oasislmf.utils.exceptions import OasisException


def _validate_chunk(data, logger, first_chunk, prev_last_bin_index, row_offset):
    if len(data) == 0:
        return

    # Check first bin
    if first_chunk:
        if data[0]["bin_from"] != 0:
            logger.warning(f"Warning: Lower limit of first bin is not 0. Are you sure this is what you want?: bin_from={data[0]['bin_from']}")
        if data[0]["bin_index"] != 1:
            raise OasisException(f"Error: First bin index must be 1, bin_index found: {data[0]['bin_index']}")

    # Check contiguous bin_index
    if prev_last_bin_index is not None and data[0]["bin_index"] != prev_last_bin_index + 1:
        raise OasisException(f"Error: Non-contiguous bin_indices found in csv. ({prev_last_bin_index}, {data[0]['bin_index']})")

    if len(data) > 1:
        indices = data["bin_index"]
        diffs = np.diff(indices)
        if not np.all(diffs == 1):
            idx = np.where(diffs != 1)[0][0]
            v1, v2 = indices[idx], indices[idx + 1]
            raise OasisException(f"Error: Non-contiguous bin_indices found in csv. ({v1}, {v2})")

    # Check interpolation damage values within range
    bin_froms = data["bin_from"]
    bin_tos = data["bin_to"]
    interpolations = data["interpolation"]
    mask_low = interpolations < bin_froms
    mask_high = interpolations > bin_tos
    mask_invalid = mask_low | mask_high
    if np.any(mask_invalid):
        bad_rows = np.where(mask_invalid)[0]
        error_msg = "\n".join(
            f"\tRow {row_offset + i}: interpolation={interpolations[i]}, bin_from={bin_froms[i]}, bin_to={bin_tos[i]}"
            for i in bad_rows
        )
        raise OasisException(f"Error: Interpolation damage value outside of range.\n {error_msg}")

    # Check valid damage_type
    damages = data['damage_type']
    invalid_mask = ~np.isin(damages, list(VALID_DAMAGE_TYPE))
    if invalid_mask.any():
        invalid_indices = np.where(invalid_mask)[0]
        invalid_values = damages[invalid_mask]
        warning_msg = "\n".join(
            f"Row {row_offset + i}: damage_type={val}, damage_type must be in {VALID_DAMAGE_TYPE}"
            for i, val in zip(invalid_indices, invalid_values)
        )
        logger.warning(f"Error: Invalid damage_type values found:\n{warning_msg}")


[docs] def damagebin_tobin(stack, file_in, file_out, file_type, no_validation): from oasislmf.pytools.converters.csvtobin.manager import logger dtype = TOOL_INFO[file_type]["dtype"] first_chunk = True prev_last_bin_index = None last_row = None row_offset = 0 for chunk in iter_csv_as_ndarray(stack, file_in, dtype): if not no_validation: _validate_chunk(chunk, logger, first_chunk, prev_last_bin_index, row_offset) chunk.tofile(file_out) first_chunk = False if len(chunk) > 0: prev_last_bin_index = int(chunk["bin_index"][-1]) last_row = chunk[-1:] row_offset += len(chunk) # Check last bin if not no_validation and last_row is not None: if last_row[0]["bin_to"] != 1: logger.warning(f"Warning: Upper limit of last bin is not 1. Are you sure this is what you want?: bin_to={last_row[0]['bin_to']}")