Esempio n. 1
0
def _response_to_query(query, reply_to, subject=None, url=None):
    """
    Takes a parsed query string fetches the forecast,
    compresses it and replies to the sender.

    Parameters
    ----------
    query : dict
        An dictionary query
    reply_to : string
        The email address of the sender.  The compressed forecast is sent
        to this person.
    subject : string (optional)
        The subject of the email that is sent. If none, a summary of
        the query is used.
    url : string (optional)
        A path to the forecast that should be used.  This is mostly used
        for debugging and testing.

    Returns
    ----------
    forecast_attachment : file-like
        A file-like object holding the forecast that was sent
    """
    compressed_forecast = process_query(query, url=url)
    logging.debug("Compressed Size: %d" % len(compressed_forecast))
    # create a file-like forecast attachment
    logging.debug('Obtained the forecast')

    file_fmt = '%Y-%m-%d_%H%m'
    filename = datetime.datetime.today().strftime(file_fmt)
    filename = '_'.join([query['type'], query['model'], filename])
    if query.get('send-image', False):
        logging.debug('Sending an image of the forecast')
        fcst = compress.decompress_dataset(compressed_forecast)
        visualize.plot_spot(fcst)
        import matplotlib.pyplot as plt
        png = BytesIO()
        plt.savefig(png)
        png.seek(0)
        attachments = {'%s.png' % filename: png}
    else:
        logging.debug('Sending the compressed forecasts')
        forecast_attachment = BytesIO(compressed_forecast)
        ext = decide_extension(reply_to)
        attachment_name = '%s.%s' % (filename, ext)
        logging.debug("Attaching forecast as %s" % attachment_name)
        attachments = {attachment_name: forecast_attachment}
    # Make sure the forecast file isn't too large for sailmail
    if 'sailmail' in reply_to and len(compressed_forecast) > 25000:
        raise utils.BadQuery("Forecast was too large (%d bytes) for sailmail!"
                             % len(compressed_forecast))
    # creates the new mime email
    weather_email = emaillib.create_email(reply_to, _query_email,
                              _email_body,
                              subject=subject or query_summary(query),
                              attachments=attachments)
    return weather_email
Esempio n. 2
0
 def test_version_assert(self):
     # create a forecast that looks like its from a newer version
     # and make sure an assertion is raised.
     ds = create_data()
     original_version = compress._VERSION
     compress._VERSION = np.array(compress._VERSION + 1, dtype=np.uint8)
     beaufort = compress.compress_dataset(ds)
     compress._VERSION = original_version
     self.assertRaises(ValueError,
                       lambda: compress.decompress_dataset(beaufort))
Esempio n. 3
0
def main():
    fcst = test_data()
    fcst = compress.decompress_dataset(compress.compress_dataset(fcst))

    for vn in ['current', 'wind']:
        variable = query_utils.get_variable(vn)
        if isinstance(variable, schemes.VelocityVariable):
            interactive.InteractiveVelocity(fcst, variable)

    plt.show()
Esempio n. 4
0
    def test_compress_dataset(self):
        ds = create_data()
        compressed = compress.compress_dataset(ds)
        actual = compress.decompress_dataset(compressed)

        np.testing.assert_allclose(actual['x_wind'].values, ds['x_wind'].values,
                                   atol=1e-4, rtol=1e-4)
        np.testing.assert_allclose(actual['y_wind'].values, ds['y_wind'].values,
                                   atol=1e-4, rtol=1e-4)
        np.testing.assert_allclose(actual['air_pressure_at_sea_level'].values,
                                   ds['air_pressure_at_sea_level'].values,
                                   atol=1e-4, rtol=1e-4)
        # pass it through the system again, it should be idempotent.
        compressed = compress.compress_dataset(ds)
        actual = compress.decompress_dataset(compressed)
        np.testing.assert_allclose(actual['x_wind'].values, ds['x_wind'].values,
                                   atol=1e-4, rtol=1e-4)
        np.testing.assert_allclose(actual['y_wind'].values, ds['y_wind'].values,
                                   atol=1e-4, rtol=1e-4)
        np.testing.assert_allclose(actual['air_pressure_at_sea_level'].values,
                                   ds['air_pressure_at_sea_level'].values,
                                   atol=1e-4, rtol=1e-4)
Esempio n. 5
0
    def test_query(self):
        some_email = "*****@*****.**"
        msg = emaillib.create_email(
            to="*****@*****.**", fr=some_email, body="send GFS:30s,35s,175e,175w|0.5,0.5|0,3..12|WIND"
        )

        emails = []
        # use a mocked emaillib to make sure an email was sent
        with self.get_request(emails) as request:
            request.process_email(msg.as_string(), fail_hard=True)
        assert len(emails) == 1
        parser = Parser.Parser()
        email = parser.parsestr(emails.pop().args[0].as_string())

        # make sure we are sending responses from ensembleweather
        self.assertEqual(email["From"], "*****@*****.**")

        # make sure we are responding to the right person
        self.assertEqual(email["To"], some_email)

        # here we pull out the expected attachment
        body, attach = email.get_payload()
        bytes = attach.get_payload()

        # inflate it back into an xray Dataset
        fcst = compress.decompress_dataset(base64.b64decode(bytes))

        # make sure we're actually compressing the file.
        self.assertLessEqual(len(bytes), len(zlib.compress(fcst.to_netcdf())))

        # make sure the lats are what we expect
        expected_lats = np.linspace(-35.0, -30.0, 11)
        np.testing.assert_array_equal(fcst["latitude"].values, expected_lats)
        self.assertEqual(fcst["latitude"].attrs["units"].lower(), "degrees north")
        # and the lons
        expected_lons = np.mod(np.linspace(175.0, 185.0, 21) + 180, 360) - 180
        np.testing.assert_array_equal(fcst["longitude"].values, expected_lons)
        self.assertEqual(fcst["longitude"].attrs["units"].lower(), "degrees east")
        # and the time
        expected_time = np.linspace(0, 12, 5)
        expected_time = xray.conventions.decode_cf_datetime(expected_time, fcst["time"].encoding["units"])
        np.testing.assert_array_equal(fcst["time"].values, expected_time)
        self.assertIn("hours", fcst["time"].encoding["units"])
Esempio n. 6
0
    def test_spot_forecast(self):
        some_email = "*****@*****.**"
        msg = emaillib.create_email(
            to="*****@*****.**", fr=some_email, body="send spot:gefs:8.53S,115.54E|8,6|wind"
        )

        emails = []
        # use a mocked emaillib to make sure an email was sent
        with self.get_request(emails) as request:
            request.process_email(msg.as_string(), fail_hard=True)
        assert len(emails) == 1
        parser = Parser.Parser()
        email = parser.parsestr(emails.pop().args[0].as_string())

        # make sure we are sending responses from ensembleweather
        self.assertEqual(email["From"], "*****@*****.**")

        # make sure we are responding to the right person
        self.assertEqual(email["To"], some_email)

        # here we pull out the expected attachment
        body, attach = email.get_payload()
        bytes = attach.get_payload()

        # inflate it back into an xray Dataset
        fcst = compress.decompress_dataset(base64.b64decode(bytes))

        # make sure we're actually compressing the file.
        self.assertLessEqual(len(bytes), len(zlib.compress(fcst.to_netcdf())))

        # make sure the lats are what we expect
        np.testing.assert_array_almost_equal(fcst["latitude"].values, np.array([-8.53]), 3)
        self.assertEqual(fcst["latitude"].attrs["units"].lower(), "degrees north")
        # and the lons
        np.testing.assert_array_almost_equal(fcst["longitude"].values, np.array([115.54]), 3)
        self.assertEqual(fcst["longitude"].attrs["units"].lower(), "degrees east")
        # and the time
        expected_time = np.linspace(0, 192, 33)
        expected_time = xray.conventions.decode_cf_datetime(expected_time, fcst["time"].encoding["units"])
        np.testing.assert_array_equal(fcst["time"].values, expected_time)
        self.assertIn("hours", fcst["time"].encoding["units"])
Esempio n. 7
0
    def test_gfs(self):
        query = {'hours': [0., 3., 9., 24.],
                 'model': 'gfs',
                 'domain': {'N': 39.,
                            'S': 35,
                            'E': -120,
                            'W': -124},
                 'grid_delta': (1., 1.),
                 'variables': ['wind']}

        model = grads.GFS()
        gfs = model.fetch(self.temporary_fcst_path)
        expected = subset.subset_dataset(gfs, query)
        compressed = request.process_query(query, url=self.temporary_fcst_path)
        actual = compress.decompress_dataset(compressed)

        np.testing.assert_array_almost_equal(actual['x_wind'].values,
                                             expected['x_wind'].values,
                                             4)
        np.testing.assert_array_almost_equal(actual['y_wind'].values,
                                             expected['y_wind'].values,
                                             4)