def test_speed_and_direction_to_uv_without_nan(self):
        """Ensures correct output from speed_and_direction_to_uv.

        In this case, input directions do not include NaN.
        """

        these_u_winds_m_s01, these_v_winds_m_s01 = (
            raw_wind_io.speed_and_direction_to_uv(
                MAX_WIND_SPEEDS_M_S01, MAX_WIND_DIRECTIONS_DEG))

        self.assertTrue(numpy.allclose(
            these_u_winds_m_s01, EXPECTED_MAX_U_WINDS_M_S01, atol=TOLERANCE))
        self.assertTrue(numpy.allclose(
            these_v_winds_m_s01, EXPECTED_MAX_V_WINDS_M_S01, atol=TOLERANCE))
def read_thunderstorm_wind_reports(csv_file_name):
    """Reads thunderstorm-wind reports from file.

    This file should contain all storm reports for one year.

    :param csv_file_name: Path to input file.
    :return: wind_table: pandas DataFrame with the following columns.
    wind_table.latitude_deg: Latitude (deg N).
    wind_table.longitude_deg: Longitude (deg E).
    wind_table.unix_time_sec: Valid time.
    wind_table.u_wind_m_s01: u-component of wind (metres per second).
    wind_table.v_wind_m_s01: v-component of wind (metres per second).
    """

    error_checking.assert_file_exists(csv_file_name)
    storm_event_table = pandas.read_csv(csv_file_name, header=0, sep=',')

    thunderstorm_wind_flags = numpy.array([
        _is_event_thunderstorm_wind(s)
        for s in storm_event_table[EVENT_TYPE_COLUMN_ORIG].values
    ])

    bad_rows = numpy.where(numpy.invert(thunderstorm_wind_flags))[0]
    storm_event_table.drop(storm_event_table.index[bad_rows],
                           axis=0,
                           inplace=True)

    num_reports = len(storm_event_table.index)
    unix_times_sec = numpy.full(num_reports, -1, dtype=int)
    for i in range(num_reports):
        this_utc_offset_hours = _time_zone_string_to_utc_offset(
            storm_event_table[TIME_ZONE_COLUMN_ORIG].values[i])
        if numpy.isnan(this_utc_offset_hours):
            continue

        unix_times_sec[i] = _local_time_string_to_unix_sec(
            storm_event_table[START_TIME_COLUMN_ORIG].values[i],
            this_utc_offset_hours)

    wind_speeds_m_s01 = KT_TO_METRES_PER_SECOND * storm_event_table[
        WIND_SPEED_COLUMN_ORIG].values
    wind_directions_deg = numpy.full(num_reports,
                                     raw_wind_io.WIND_DIR_DEFAULT_DEG)
    u_winds_m_s01, v_winds_m_s01 = raw_wind_io.speed_and_direction_to_uv(
        wind_speeds_m_s01, wind_directions_deg)

    station_ids = _create_fake_station_ids_for_wind(num_reports)

    wind_dict = {
        raw_wind_io.TIME_COLUMN:
        unix_times_sec,
        raw_wind_io.LATITUDE_COLUMN:
        storm_event_table[START_LATITUDE_COLUMN_ORIG].values,
        raw_wind_io.LONGITUDE_COLUMN:
        storm_event_table[START_LONGITUDE_COLUMN_ORIG].values,
        raw_wind_io.STATION_ID_COLUMN:
        station_ids,
        raw_wind_io.STATION_NAME_COLUMN:
        station_ids,
        raw_wind_io.ELEVATION_COLUMN:
        numpy.full(num_reports, numpy.nan),
        raw_wind_io.U_WIND_COLUMN:
        u_winds_m_s01,
        raw_wind_io.V_WIND_COLUMN:
        v_winds_m_s01
    }

    wind_table = pandas.DataFrame.from_dict(wind_dict)
    return _remove_invalid_wind_reports(wind_table)
def read_wind_reports_from_raw_file(csv_file_name):
    """Reads straight-line-wind reports from raw file.

    This file should contain all storm reports for one year.

    :param csv_file_name: Path to input file.
    :return: wind_table: pandas DataFrame with the following columns.
    wind_table.latitude_deg: Latitude (deg N).
    wind_table.longitude_deg: Longitude (deg E).
    wind_table.unix_time_sec: Observation time (seconds since 0000 UTC 1 Jan
        1970).
    wind_table.u_wind_m_s01: u-component of wind (m/s).
    wind_table.v_wind_m_s01: v-component of wind (m/s).
    """

    error_checking.assert_file_exists(csv_file_name)
    report_table = pandas.read_csv(csv_file_name, header=0, sep=',')

    num_reports = len(report_table.index)
    thunderstorm_wind_flags = numpy.full(num_reports, False, dtype=bool)
    for i in range(num_reports):
        thunderstorm_wind_flags[i] = _is_event_thunderstorm_wind(
            report_table[EVENT_TYPE_COLUMN_ORIG].values[i])

    non_tstorm_wind_indices = (numpy.where(
        numpy.invert(thunderstorm_wind_flags))[0])
    report_table.drop(report_table.index[non_tstorm_wind_indices],
                      axis=0,
                      inplace=True)

    num_reports = len(report_table.index)
    unix_times_sec = numpy.full(num_reports, -1, dtype=int)
    for i in range(num_reports):
        this_utc_offset_hours = _time_zone_string_to_utc_offset(
            report_table[TIME_ZONE_COLUMN_ORIG].values[i])
        if numpy.isnan(this_utc_offset_hours):
            continue

        unix_times_sec[i] = _local_time_string_to_unix_sec(
            report_table[TIME_COLUMN_ORIG].values[i], this_utc_offset_hours)

    wind_speeds_m_s01 = KT_TO_METRES_PER_SECOND * report_table[
        WIND_SPEED_COLUMN_ORIG].values
    wind_directions_deg = numpy.full(num_reports,
                                     raw_wind_io.WIND_DIR_DEFAULT_DEG)
    (u_winds_m_s01, v_winds_m_s01) = raw_wind_io.speed_and_direction_to_uv(
        wind_speeds_m_s01, wind_directions_deg)

    station_ids = _generate_fake_station_ids(num_reports)

    wind_dict = {
        raw_wind_io.TIME_COLUMN: unix_times_sec,
        raw_wind_io.LATITUDE_COLUMN: report_table[LATITUDE_COLUMN_ORIG].values,
        raw_wind_io.LONGITUDE_COLUMN:
        report_table[LONGITUDE_COLUMN_ORIG].values,
        raw_wind_io.STATION_ID_COLUMN: station_ids,
        raw_wind_io.STATION_NAME_COLUMN: station_ids,
        raw_wind_io.ELEVATION_COLUMN: numpy.full(num_reports, numpy.nan),
        raw_wind_io.U_WIND_COLUMN: u_winds_m_s01,
        raw_wind_io.V_WIND_COLUMN: v_winds_m_s01
    }

    wind_table = pandas.DataFrame.from_dict(wind_dict)
    return _remove_invalid_wind_rows(wind_table)