Exemplo n.º 1
0
def plot_gasflow(gf, vent=None, scale=100., **kargs):
    if vent is None:
        raise VizException("Please provide a vent location (lon, lat)")

    pos = gf.position[:]
    vx = gf.vx[:]
    vy = gf.vy[:]
    lon_min = vent[0] - 0.03
    lon_max = vent[0] + 0.03
    lat_min = vent[1] - 0.03
    lat_max = vent[1] + 0.03
    tiler = StamenTerrain()
    mercator = tiler.crs
    fig = plt.figure(figsize=(10, 10))
    ax = plt.axes(projection=mercator)
    fig.add_axes(ax)
    ax.add_image(tiler, 11)
    p = ccrs.PlateCarree()
    g = pyproj.Geod(ellps='WGS84')
    for lon, lat, _vx, _vy in zip(pos[:, 0], pos[:, 1], vx, vy):
        wd = vec2bearing(_vx, _vy)
        ws = np.sqrt(_vx * _vx + _vy * _vy)*scale
        elon, elat, _ = g.fwd(lon, lat, wd, ws)
        x, y = p.transform_points(ccrs.Geodetic(),
                                  np.array([lon, elon]),
                                  np.array([lat, elat]))
        dx = y[0] - x[0]
        dy = y[1] - x[1]
        ax.quiver(np.array([x[0]]), np.array([x[1]]), np.array([dx]),
                  np.array([dy]), transform=ccrs.PlateCarree())
    ax.scatter(vent[0], vent[1], marker='^', color='red', s=50,
               transform=ccrs.Geodetic())
    ax.set_extent([lon_min, lon_max, lat_min, lat_max])
    return fig
 def test_wind(self):
     """
     Test handling of wind data files with different numbers
     of entries for wind speed and wind direction.
     """
     d = Dataset(tempfile.mktemp(), 'w')
     windd_filepath = os.path.join(self.data_dir, '20170515_WD_00.txt')
     winds_filepath = os.path.join(self.data_dir, '20170515_WS_00.txt')
     e = d.read({'direction': windd_filepath,
                 'speed': winds_filepath},
                ftype='minidoas-wind', timeshift=13)
     gfb = e['GasFlowBuffer']
     dates = gfb.datetime[:].astype('datetime64[s]')
     dates += np.timedelta64(13, 'h')
     self.assertEqual(dates.size, 5)
     self.assertEqual(int(vec2bearing(gfb.vx[0], gfb.vy[0])), 240)
     self.assertAlmostEqual(np.sqrt(gfb.vx[0]**2 + gfb.vy[0]**2), 2.5, 1)
     self.assertEqual(int(vec2bearing(gfb.vx[-1], gfb.vy[-1])), 240)
     self.assertAlmostEqual(np.sqrt(gfb.vx[-1]**2 + gfb.vy[-1]**2), 4.2, 1)
Exemplo n.º 3
0
 def test_read_wind(self):
     d = Dataset(tempfile.mktemp(), 'w')
     fin = os.path.join(self.data_dir, 'TOFP04', 'wind', '2017_06_14.txt')
     gf = d.read(fin, ftype='flyspecwind', timeshift=13)
     vx = gf.vx[0]
     vy = gf.vy[0]
     dt = gf.datetime[0]
     v = np.sqrt(vx * vx + vy * vy)
     self.assertAlmostEqual(v, 10.88, 2)
     self.assertAlmostEqual(vec2bearing(vx, vy), 255, 6)
     self.assertEqual(dt, np.datetime64('2017-06-13T17:00:00'))
 def test_read(self):
     d = Dataset(tempfile.mktemp(), 'w')
     d.read(os.path.join(self.data_dir,
                         'gns_wind_model_data_ecmwf_20160921_0630.txt'),
            ftype='NZMETSERVICE')
     gf = d.elements['GasFlow'][0]
     res = get_wind_speed(gf, 174.735, -36.890, 1000,
                          '2016-09-21T06:00:00+12:00')
     (lon, lat, hght, time, vx, vx_error, vy, vy_error, vz, vz_error,
      dist) = res
     self.assertEqual(lon, 174.735)
     self.assertEqual(lat, -36.890)
     self.assertEqual(hght, 1000)
     v = math.sqrt(vx * vx + vy * vy)
     self.assertAlmostEqual(v / 0.514444, 17, 6)
     self.assertAlmostEqual(70., vec2bearing(vx, vy), 6)
     m = gf.methods[0]
     self.assertEqual(m.name, 'gfs')
     d.read(os.path.join(self.data_dir,
                         'gns_wind_model_data_ecmwf_20160921_0630.txt'),
            ftype='NZMETSERVICE',
            preferred_model='ecmwf')
     gf1 = d.elements['GasFlow'][1]
     res = get_wind_speed(gf1, 174.755, -36.990, 1000,
                          '2016-09-21T06:00:00+12:00')
     (lon, lat, hght, time, vx, vx_error, vy, vy_error, vz, vz_error,
      dist) = res
     v = math.sqrt(vx * vx + vy * vy)
     self.assertEqual(lon, 174.735)
     self.assertEqual(lat, -36.890)
     self.assertEqual(hght, 1000)
     v = math.sqrt(vx * vx + vy * vy)
     self.assertAlmostEqual(v / 0.514444, 19, 6)
     self.assertAlmostEqual(65., vec2bearing(vx, vy), 6)
     self.assertEqual(gf1.methods[0].name, 'ecmwf')
     self.assertEqual(gf1.unit, 'm/s')
    def test_read(self):
        d = Dataset(tempfile.mktemp(), 'w')
        e = d.read(os.path.join(self.data_dir, 'minidoas', 'NE_20161101.csv'),
                   ftype='minidoas-raw')
        rb = e['RawDataBuffer']
        self.assertEqual(rb.d_var.shape, (7615, 482))
        self.assertEqual(rb.d_var[0, 0], 78)
        self.assertEqual(rb.datetime[0],
                         np.datetime64('2016-11-01T09:00:00.070'))
        self.assertEqual(rb.datetime[-1],
                         np.datetime64('2016-11-01T16:29:54.850'))

        with self.assertRaises(MiniDoasException):
            e1 = d.read(os.path.join(self.data_dir, 'minidoas',
                                     'NE_2016_11_01_Spectra.csv'),
                        ftype='minidoas-spectra')
        e1 = d.read(os.path.join(self.data_dir, 'minidoas',
                                 'NE_2016_11_01_Spectra.csv'),
                    date='2016-11-01', ftype='minidoas-spectra', timeshift=13)
        cb = e1['ConcentrationBuffer']
        self.assertEqual(cb.datetime[-1],
                         np.datetime64('2016-11-01T03:28:07.410'))

        fn_wd = os.path.join(self.data_dir, 'minidoas', 'wind',
                             '20161101_WD_00.txt')
        fn_ws = os.path.join(self.data_dir, 'minidoas', 'wind',
                             '20161101_WS_00.txt')

        e2 = d.read({'direction': fn_wd, 'speed': fn_ws}, timeshift=13,
                    ftype='minidoas-wind')
        gfb = e2['GasFlowBuffer']
        self.assertEqual(int(vec2bearing(gfb.vx[0], gfb.vy[0])), 240)
        self.assertAlmostEqual(np.sqrt(gfb.vx[0]**2 + gfb.vy[0]**2), 3.2, 1)
        self.assertEqual(gfb.datetime[0],
                         np.datetime64("2016-10-31T19:10:00.000"))
        e3 = d.read(os.path.join(self.data_dir, 'minidoas',
                                 'XX_2016_11_01_Combined.csv'),
                    date='2016-11-01', ftype='minidoas-scan', station='NE',
                    timeshift=13)
        fb = e3['FluxBuffer']
        np.testing.assert_array_almost_equal(fb.value[:],
                                             np.array([3.8, 1.2]), 1)
        self.assertEqual(fb.datetime[0],
                         np.datetime64('2016-10-31T23:15:04'))
Exemplo n.º 6
0
def flux_ah(pf, perror_thresh=0.5, smoothing=False):
    """
    Compute the flux for assumed height.
    """

    f = pf.fluxes[0]
    c = f.concentration
    errors = []
    for i, fidx in enumerate(pf.flux_indices[0][:]):
        idx0, idx1 = f.concentration_indices[fidx]
        so2_raw = c.value[idx0:idx1]
        r = c.rawdata
        ridx = c.rawdata_indices[idx0:idx1]
        angles = r[0].inc_angle[ridx]
        bearing = r[0].bearing[0]

        if smoothing:
            so2_smooth = binomial_filter(so2_raw, [1, 2, 1], 5)
            p = fit_gaussian(angles, so2_smooth)
            so2 = gaussian_pts(angles, p)
        else:
            so2 = so2_raw

        # Get the wind direction
        gf = f.gasflow
        gf_times = f.gasflow.datetime[:].astype('datetime64[s]')
        gf_idx = np.argmin(np.abs(gf_times - np.datetime64(f.datetime[fidx])))
        vx, vy = gf.vx[gf_idx], gf.vy[gf_idx]
        wd = vec2bearing(vx, vy)
        ws = np.sqrt(vx * vx + vy * vy)

        t_angle = np.cos(np.deg2rad(bearing - wd - 90.))

        _, _, elev0 = gf.position[gf_idx]
        _, _, elev2 = gf.position[gf_idx + 2]
        plumewidth = elev2 - elev0

        plmax = np.argmax(so2)
        edge = 0.05 * so2.max()
        pidx = np.where(so2 >= edge)
        plstart = pidx[0][0]
        plend = pidx[0][-1]
        plrange = np.abs(
            np.deg2rad(angles[plstart]) - np.deg2rad(angles[plend]))
        # calculate distance between measurements assuming dx = r * theta
        int_time = r[0].integration_time[ridx] / 1000.
        dx = (np.ones(angles.size) * 0.015707963 * 1000. / 992 * int_time *
              plumewidth / plrange)

        col_amt = dx[plstart:plend + 1] * so2[plstart:plend + 1]
        ica = np.sum(col_amt)

        # correct for a non-perpendicular transect through the plume
        ica = abs(t_angle * ica)
        flux = ica * ws * 0.000230688
        # Compute percentage error
        x = pf.value[i] * 86.4
        x0 = flux
        p_error = 100. * abs(x0 - x) / x
        if p_error > perror_thresh:
            msg = "ERROR 03: Error of {:.3f} exceeds threshold"
            msg += " for assumed height flux.\n"
            msg += "Date: {:s}\n"
            msg += "Expected flux (FITS): {:.3f}; Original flux: {:.3f}; "
            msg += "Estimated flux: {:.3f}\n"
            msg += "Plume geometry: start={:.3f}, max={:.3f}, end={:.3f}"
            msg += ", width={:.3f}\n"
            msg += "Wind: track={:.3f} sp={:.3f}\n"
            msg = msg.format(p_error, f.datetime[fidx], x,
                             f.value[fidx] * 86.4, x0,
                             np.deg2rad(angles[plstart]),
                             np.deg2rad(angles[plmax]),
                             np.deg2rad(angles[plend]), plumewidth, wd, ws)
            errors.append(msg)
    if len(errors) > 0:
        raise MDOASException(''.join(errors))
def write_testfile(d, date, time, fin):
    """
    This will write a file that is identical to the input file
    but taking all the information from the GasFlow element.
    """
    gf = d.elements['GasFlow'][0]
    mod = gf.methods[0].name
    year, month, day = int(date[0:4]), int(date[4:6]), int(date[6:8])
    hour, minute = int(time[0:2]), int(time[2:4])
    lines = []
    # Write the header
    _h, _s = re.match('(\d+)(\S+)', ampm(hour)).groups()
    line = 'Forecast issued by MetService at '
    line += '{:02d}:{:02d}{:s} '.format(int(_h), minute, _s)
    line += '{:02d}-{:02d}-{:4d}\n\n'.format(day, month, year)
    line += 'For GNS Wairakei Research Centre - Volcano Watch All times NZDT '
    line += 'e.g. {:02d}{:02d}00 '.format(day, hour)
    line += 'is {:s} on {:s}. '.format(ampm(hour), ord(day))
    line += 'Winds in degrees/knots, heights in metres.\n'
    line += 'Model of the day is {:s}\n\n'.format(mod.upper())
    line += 'Data for model {:s}\n'.format(mod.upper())
    lines.append(line)
    # Cycle through all points
    for point in volc_dict_keys:
        # Write header for each point
        lines.append('{:s}\n'.format(point))
        times = []
        ntimes = len(np.unique(gf.datetime[:]))
        line = 'Height  '
        for i in range(ntimes):
            line += 'Valid at      '
        line += '\n'
        lines.append(line)
        line = '{:8}'.format('')
        # Write datetimes
        dt = (nztz.localize(datetime.datetime(year, month,
                                              day, hour)).astimezone(
                                                  timezone('UTC')))
        otimes = np.unique(gf.datetime[:])
        otimes.sort()
        for t in otimes.astype(np.str_):
            dt = timezone('UTC').localize(parse_iso_8601(t))
            times.append(dt)
            line += '{:<14s}'.format(dt.astimezone(nztz).strftime('%d%H%M'))
        line += '\n'
        lines.append(line)
        ln, lt = volc_dict[point]
        # Write actual wind data
        for height in [1000, 2000, 3000, 4000, 6000, 8000, 10000, 12000]:
            line = ''
            line += '{:<8d}'.format(height)
            for i, dt in enumerate(times):
                res = get_wind_speed(gf, ln, lt, height,
                                     dt.astimezone(pytz.utc))
                (lon, lat, hght, time, vx, vx_error, vy, vy_error, vz,
                 vz_error, dist) = res
                if dist > 0.0001:
                    line += '{0:<14s}'.format('-')
                else:
                    try:
                        v = int(round(math.sqrt(vx * vx + vy * vy) / 0.514444))
                        vd = int(round(vec2bearing(vx, vy)))
                        if vd == 0:
                            vd = 360
                    except Exception as e:
                        print(point, hght, time)
                        raise e
                    line += '{0:03d}/{1:02d}{2:8}'.format(vd, v, '')
            line += '\n'
            lines.append(line)
        lines.append('\n')
    fin = fin.replace('ecmwf', mod)
    fout = os.path.basename(fin)
    fout = os.path.join('/tmp', fout.replace('.txt', '_test.txt'))
    fh = open(fout, 'w')
    fh.writelines(lines)
    fh.close()
    # Now compare with the original
    if not filecmp.cmp(fout, fin, shallow=False):
        raise Exception('Files %s and %s are not identical!' % (fin, fout))
    else:
        os.unlink(fout)