def secure_filename(filename):
    r"""Borrowed from :mod:`werkzeug.utils`, under the BSD 3-clause license.

    Pass it a filename and it will return a secure version of it.  This
    filename can then safely be stored on a regular file system and passed
    to :func:`os.path.join`.  The filename returned is an ASCII only string
    for maximum portability.

    On windows systems the function also makes sure that the file is not
    named after one of the special device files.

    >>> secure_filename("My cool movie.mov")
    'My_cool_movie.mov'
    >>> secure_filename("../../../etc/passwd")
    'etc_passwd'
    >>> secure_filename(u'i contain cool \xfcml\xe4uts.txt')
    'i_contain_cool_umlauts.txt'

    The function might return an empty filename.  It's your responsibility
    to ensure that the filename is unique and that you generate random
    filename if the function returned an empty one.

    :param filename: the filename to secure
    """
    _filename_ascii_strip_re = re.compile(r'[^A-Za-z0-9_.-]')
    _windows_device_files = ('CON', 'AUX', 'COM1', 'COM2', 'COM3', 'COM4',
                             'LPT1', 'LPT2', 'LPT3', 'PRN', 'NUL')
    if isinstance(filename, text_type):
        from unicodedata import normalize
        filename = normalize('NFKD', filename).encode('ascii', 'ignore')
        if not PY2:
            filename = filename.decode('ascii')
    for sep in os.path.sep, os.path.altsep:
        if sep:
            filename = filename.replace(sep, ' ')
    filename = str(_filename_ascii_strip_re.sub('', '_'.join(
                   filename.split()))).strip('._')

    # on nt a couple of special files are present in each folder.  We
    # have to ensure that the target file is not such a filename.  In
    # this case we prepend an underline
    if os.name == 'nt' and filename and \
       filename.split('.')[0].upper() in _windows_device_files:
        filename = '_' + filename

    return filename
def _create_2d3d_examples_myrorss(
        azimuthal_shear_file_names, reflectivity_file_names,
        full_id_strings, storm_times_unix_sec, target_matrix,
        sounding_file_name=None, sounding_field_names=None):
    """Creates hybrid 2D-3D examples for one file time.

    Fields in 2-D images: low-level and mid-level azimuthal shear
    Field in 3-D images: reflectivity

    :param azimuthal_shear_file_names: length-2 list of paths to storm-centered
        azimuthal-shear images.  The first (second) file should be (low)
        mid-level azimuthal shear.  Files will be read by
        `storm_images.read_storm_images`.
    :param reflectivity_file_names: length-H list of paths to storm-centered
        reflectivity images, where H = number of reflectivity heights.  Files
        will be read by `storm_images.read_storm_images`.
    :param full_id_strings: See doc for `_create_2d_examples`.
    :param storm_times_unix_sec: Same.
    :param target_matrix: Same.
    :param sounding_file_name: Same.
    :param sounding_field_names: Same.
    :return: example_dict: Same.
    """

    orig_full_id_strings = copy.deepcopy(full_id_strings)
    orig_storm_times_unix_sec = storm_times_unix_sec + 0

    print('Reading data from: "{0:s}"...'.format(reflectivity_file_names[0]))
    this_radar_image_dict = storm_images.read_storm_images(
        netcdf_file_name=reflectivity_file_names[0],
        full_id_strings_to_keep=full_id_strings,
        valid_times_to_keep_unix_sec=storm_times_unix_sec)

    if this_radar_image_dict is None:
        return None

    if sounding_file_name is None:
        sounding_matrix = None
        sounding_field_names = None
        sounding_heights_m_agl = None
    else:
        sounding_dict, this_radar_image_dict = _read_soundings(
            sounding_file_name=sounding_file_name,
            sounding_field_names=sounding_field_names,
            radar_image_dict=this_radar_image_dict)

        if this_radar_image_dict is None:
            return None
        if len(this_radar_image_dict[storm_images.FULL_IDS_KEY]) == 0:
            return None

        sounding_matrix = sounding_dict[soundings.SOUNDING_MATRIX_KEY]
        sounding_field_names = sounding_dict[soundings.FIELD_NAMES_KEY]
        sounding_heights_m_agl = sounding_dict[soundings.HEIGHT_LEVELS_KEY]

    full_id_strings = this_radar_image_dict[storm_images.FULL_IDS_KEY]
    storm_times_unix_sec = this_radar_image_dict[storm_images.VALID_TIMES_KEY]

    these_indices = tracking_utils.find_storm_objects(
        all_id_strings=orig_full_id_strings,
        all_times_unix_sec=orig_storm_times_unix_sec,
        id_strings_to_keep=full_id_strings,
        times_to_keep_unix_sec=storm_times_unix_sec, allow_missing=False)

    target_matrix = target_matrix[these_indices, :]

    azimuthal_shear_field_names = [
        storm_images.image_file_name_to_field(f)
        for f in azimuthal_shear_file_names
    ]
    reflectivity_heights_m_agl = numpy.array([
        storm_images.image_file_name_to_height(f)
        for f in reflectivity_file_names
    ], dtype=int)

    num_reflectivity_heights = len(reflectivity_file_names)
    tuple_of_image_matrices = ()

    for j in range(num_reflectivity_heights):
        if j != 0:
            print('Reading data from: "{0:s}"...'.format(
                reflectivity_file_names[j]
            ))

            this_radar_image_dict = storm_images.read_storm_images(
                netcdf_file_name=reflectivity_file_names[j],
                full_id_strings_to_keep=full_id_strings,
                valid_times_to_keep_unix_sec=storm_times_unix_sec)

        this_matrix = numpy.expand_dims(
            this_radar_image_dict[storm_images.STORM_IMAGE_MATRIX_KEY], axis=-1
        )
        tuple_of_image_matrices += (this_matrix,)

    example_dict = {
        FULL_IDS_KEY: full_id_strings,
        STORM_TIMES_KEY: storm_times_unix_sec,
        RADAR_FIELDS_KEY: azimuthal_shear_field_names,
        RADAR_HEIGHTS_KEY: reflectivity_heights_m_agl,
        ROTATED_GRIDS_KEY:
            this_radar_image_dict[storm_images.ROTATED_GRIDS_KEY],
        ROTATED_GRID_SPACING_KEY:
            this_radar_image_dict[storm_images.ROTATED_GRID_SPACING_KEY],
        REFL_IMAGE_MATRIX_KEY: dl_utils.stack_radar_heights(
            tuple_of_image_matrices),
        TARGET_MATRIX_KEY: target_matrix
    }

    if sounding_file_name is not None:
        example_dict.update({
            SOUNDING_FIELDS_KEY: sounding_field_names,
            SOUNDING_HEIGHTS_KEY: sounding_heights_m_agl,
            SOUNDING_MATRIX_KEY: sounding_matrix
        })

    num_az_shear_fields = len(azimuthal_shear_file_names)
    tuple_of_image_matrices = ()

    for j in range(num_az_shear_fields):
        print('Reading data from: "{0:s}"...'.format(
            azimuthal_shear_file_names[j]
        ))

        this_radar_image_dict = storm_images.read_storm_images(
            netcdf_file_name=azimuthal_shear_file_names[j],
            full_id_strings_to_keep=full_id_strings,
            valid_times_to_keep_unix_sec=storm_times_unix_sec)

        tuple_of_image_matrices += (
            this_radar_image_dict[storm_images.STORM_IMAGE_MATRIX_KEY],
        )

    example_dict.update({
        AZ_SHEAR_IMAGE_MATRIX_KEY: dl_utils.stack_radar_fields(
            tuple_of_image_matrices)
    })

    return example_dict