Example #1
0
def wrap_computer_stats(query, dataset_name, lon_values):

    #determine east or west wrap
    if any(p > 180 for p in lon_values):        #points to the east of the east dateline 
        wrap_val=180
    elif any(p < -180 for p in lon_values):     #points to the west of the west dateline
        wrap_val=-180
    else:
        raise ClientError(gettext("something went wrong. It seems you are trying to create a plot across the international date line." + 
                                "While we do support this function it must be done within 360 deg of the default map view. Try refreshing the page and try again"))
    
    variables = query.get('variable')

    if isinstance(variables, str) or isinstance(variables, unicode):
        variables = variables.split(',')
    
    area_data = Stats(query)
    area_data.set_lons(lon_values)

    area_data.split_area(wrap_val)

    area_data.names, area_data.inner_area.all_rings = get_names_rings(area_data.inner_area.area_query)
    _, area_data.outter_area.all_rings = get_names_rings(area_data.outter_area.area_query)

    area_data.inner_area.bounds = compute_bounds(area_data.inner_area.all_rings)
    area_data.outter_area.bounds = compute_bounds(area_data.outter_area.all_rings)

    area_data.inner_area.area_polys, area_data.inner_area.output = fill_polygons(area_data.inner_area.area_query)
    area_data.outter_area.area_polys, area_data.outter_area.output = fill_polygons(area_data.outter_area.area_query)

    area_data.inner_area.width = area_data.inner_area.bounds[3] - area_data.inner_area.bounds[1] 
    area_data.outter_area.width = area_data.outter_area.bounds[3] - area_data.outter_area.bounds[1]

    spacing = math.floor((area_data.inner_area.width/(area_data.inner_area.width+area_data.outter_area.width))*50)
    area_data.inner_area.spaced_points = np.linspace(area_data.inner_area.bounds[1], area_data.inner_area.bounds[3], spacing)
    area_data.outter_area.spaced_points = np.linspace(area_data.outter_area.bounds[1], area_data.outter_area.bounds[3], 50-spacing)

    area_data.get_values(area_data.inner_area , dataset_name, variables)
    area_data.get_values(area_data.outter_area, dataset_name, variables)
    area_data.combine_stats()    

    if int(area_data.area.stats[0]['variables'][0]['num']) == 0:
        raise ClientError(gettext("there are no datapoints in the area you selected. \
                                            You may have selected a area on land or you may \
                                            have an ara that is too small. \
                                            Try selection a different area or \
                                            a larger area"))
    return json.dumps(sorted(area_data.area.stats, key=itemgetter('name')))
Example #2
0
def stats(dataset_name, query):
    try:
        area = query.get('area')
        data = None

        for idx, a in enumerate(area):
            if isinstance(a, str):
                sp = a.split('/', 1)
                if data is None:
                    data = list_areas(sp[0], simplify=False)

                b = [x for x in data if x.get('key') == a]
                a = b[0]
                area[idx] = a
                
        points_lat =[]
        for p in area[0]['polygons'][0]:
            points_lat.append(p[1])
    except Exception as e:
        raise ServerError(gettext("Unknown Error: you have tried something that we did not expect. \
                                Please try again or try something else. If you would like to report \
                                this error please contact [email protected]. ") + str(e))
    
    if (max(points_lat)-min(points_lat))>360:
        raise ClientError(gettext("Error: you are trying to create a plot that is wider than the world. \
        The desired information is ambiguous please select a smaller area and try again"))
    elif any((p > 180 or p < -180) for p in points_lat) and any(-180 <= p <= 180 for p in points_lat): #if there area points on both sides of the date line 
        return wrap_computer_stats(query, dataset_name, points_lat)
    else:   # no world wrap
        return computer_stats(area, query, dataset_name)   

    raise ServerError(gettext("Unknown Error: you have tried something that we did not expect. \
                        Please try again or try something else. If you would like to report \
                        this error please contact [email protected]"))
Example #3
0
def computer_stats(area, query, dataset_name):
    area_data = Stats(query)
    lon_values = []
    for p in area_data.area.area_query[0]['polygons'][0]:
        p[1] = convert_to_bounded_lon(p[1])
        lon_values.append(p[1])
    area_data.set_lons(lon_values)

    variables = query.get('variable')
    if isinstance(variables, str) or isinstance(variables, unicode):
        variables = variables.split(',')

    area_data.names, area_data.area.all_rings = get_names_rings(area_data.area.area_query)
    area_data.area.bounds = compute_bounds(area_data.area.all_rings)
    area_data.area.area_polys, area_data.area.output = fill_polygons(area_data.area.area_query)
    area_data.area.spaced_points = np.linspace(area_data.area.bounds[1], area_data.area.bounds[3], 50)

    area_data.get_values(area_data.area, dataset_name, variables)

    if int(area_data.area.stats[0]['variables'][0]['num']) == 0:
        raise ClientError(gettext("there are no datapoints in the area you selected. \
                                            You may have selected a area on land or you may \
                                            have an ara that is too small. \
                                            Try selection a different area or \
                                            a larger area"))
    return json.dumps(sorted(area_data.area.stats, key=itemgetter('name')))
Example #4
0
    def load_data(self):
        with open_dataset(get_dataset_url(self.dataset_name)) as d:
            if self.time < 0:
                self.time += len(d.timestamps)
            time = np.clip(self.time, 0, len(d.timestamps) - 1)
            timestamp = d.timestamps[time]

            try:
                self.load_misc(d, self.variables)
            except IndexError as e:
                raise ClientError(
                    gettext(
                        "The selected variable(s) were not found in the dataset. \
                Most likely, this variable is a derived product from existing dataset variables. \
                Please select another variable. ") + str(e))

            point_data, point_depths = self.get_data(d, self.variables, time)
            point_data = self.apply_scale_factors(point_data)

            self.variable_units, point_data = self.kelvin_to_celsius(
                self.variable_units, point_data)

        self.data = self.subtract_other(point_data)
        self.depths = point_depths
        self.timestamp = timestamp
Example #5
0
    def load_data(self):

        with open_dataset(self.dataset_config,
                          timestamp=self.time,
                          variable=self.variables) as ds:

            try:
                self.load_misc(ds, self.variables)
            except IndexError as e:
                raise ClientError(
                    gettext(
                        "The selected variable(s) were not found in the dataset. \
                Most likely, this variable is a derived product from existing dataset variables. \
                Please select another variable. ") + str(e))

            point_data, point_depths = self.get_data(ds, self.variables,
                                                     self.time)

            self.iso_timestamp = ds.nc_data.timestamp_to_iso_8601(self.time)

        self.data = self.subtract_other(point_data)
        self.depths = point_depths
Example #6
0
from plotting.sound import SoundSpeedPlotter
from plotting.stats import stats as areastats
from plotting.stick import StickPlotter
from plotting.timeseries import TimeseriesPlotter
from plotting.transect import TransectPlotter
from plotting.ts import TemperatureSalinityPlotter
from utils.errors import APIError, ClientError, ErrorBase

bp_v1_0 = Blueprint('api_v1_0', __name__)

# ~~~~~~~~~~~~~~~~~~~~~~~
# API INTERFACE V1.0
# ~~~~~~~~~~~~~~~~~~~~~~~

MAX_CACHE = 315360000
FAILURE = ClientError("Bad API usage")


@bp_v1_0.errorhandler(ErrorBase)
def handle_error_v1(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response


@bp_v1_0.route('/api/')
def info_v1():
    raise APIError(
        "This is the Ocean Navigator API - Additional Parameters are required to complete a request, help can be found at ..."
    )
def _map_plot(points, path=True, quiver=True):
    minlat = np.min(points[0, :])
    maxlat = np.max(points[0, :])
    minlon = np.min(points[1, :])
    maxlon = np.max(points[1, :])
    lat_d = max(maxlat - minlat, 20)
    lon_d = max(maxlon - minlon, 20)
    minlat -= lat_d / 3
    minlon -= lon_d / 3
    maxlat += lat_d / 3
    maxlon += lon_d / 3
    if minlat < -90:
        minlat = -90
    if maxlat > 90:
        maxlat = 90

    m = Basemap(
        llcrnrlon=minlon,
        llcrnrlat=minlat,
        urcrnrlon=maxlon,
        urcrnrlat=maxlat,
        lat_0=np.mean(points[0, :]),
        lon_0=np.mean(points[1, :]),
        resolution='c',
        projection='merc',
        rsphere=(6378137.00, 6356752.3142),
    )

    if path:
        marker = ''
        if (np.round(points[1, :], 2) == np.round(points[1, 0], 2)).all() and \
                (np.round(points[0, :], 2) == np.round(points[0, 0], 2)).all():
            marker = '.'
        m.plot(points[1, :],
               points[0, :],
               latlon=True,
               color='r',
               linestyle='-',
               marker=marker)
        if quiver:
            qx, qy = m([points[1, -1]], [points[0, -1]])
            qu = points[1, -1] - points[1, -2]
            qv = points[0, -1] - points[0, -2]
            qmag = np.sqrt(qu**2 + qv**2)
            qu /= qmag
            qv /= qmag
            m.quiver(qx,
                     qy,
                     qu,
                     qv,
                     pivot='tip',
                     scale=8,
                     width=0.25,
                     minlength=0.25,
                     color='r')
    else:
        for idx in range(0, points.shape[1]):
            m.plot(points[1, idx], points[0, idx], 'o', latlon=True, color='r')

    # Draw a realistic background "blue marble"
    try:
        m.bluemarble()

        m.drawparallels(np.arange(round(minlat), round(maxlat),
                                  round(lat_d / 1.5)),
                        labels=[0, 1, 0, 0])
        m.drawmeridians(np.arange(round(minlon), round(maxlon),
                                  round(lon_d / 1.5)),
                        labels=[0, 0, 0, 1])
    except:
        raise ClientError(
            "Plot is too close to pole. Changing your projection may solve this - Return to the main page, under settings, then Projection"
        )
    def load_data(self):
        if isinstance(self.observation[0], numbers.Number):
            self.observation_variable_names = []
            self.observation_variable_units = []

            self.data = []
            self.timestamps = []
            self.observation_times = []
            self.names = []
            for idx, o in enumerate(self.observation):
                station = db.session.query(Station).get(o)
                observation = {
                    'time': station.time.isoformat(),
                    'longitude': station.longitude,
                    'latitude': station.latitude,
                }
                self.observation_time = station.time
                self.observation_times.append(station.time)

                if station.name:
                    self.names.append(station.name)
                else:
                    self.names.append(
                        f"({station.latitude:.4f}, {station.longitude:.4f})")
                datatype_keys = [
                    k[0] for k in db.session.query(
                        db.func.distinct(Sample.datatype_key)).filter(
                            Sample.station == station).all()
                ]

                datatypes = db.session.query(DataType).filter(
                    DataType.key.in_(datatype_keys)).order_by(
                        DataType.key).all()

                observation['datatypes'] = [
                    f"{dt.name} [{dt.unit}]" for dt in datatypes
                ]

                data = []
                for dt in datatypes:
                    data.append(
                        db.session.query(Sample.depth, Sample.value).filter(
                            Sample.station == station,
                            Sample.datatype == dt).all())

                    if idx == 0:
                        self.observation_variable_names.append(dt.name)
                        self.observation_variable_units.append(dt.unit)

                observation['data'] = np.ma.array(data)  #.transpose()
                self.observation[idx] = observation

                self.points = [[o['latitude'], o['longitude']]
                               for o in self.observation]

        cftime = datetime_to_timestamp(station.time,
                                       self.dataset_config.time_dim_units)

        with open_dataset(
                self.dataset_config,
                variable=self.variables,
                timestamp=int(cftime),
                nearest_timestamp=True,
        ) as dataset:
            ts = dataset.nc_data.timestamps

            observation_times = []
            timestamps = []
            for o in self.observation:
                observation_time = dateutil.parser.parse(
                    o['time']).replace(tzinfo=pytz.UTC)
                observation_times.append(observation_time)

                deltas = [(x - observation_time).total_seconds() for x in ts]

                time = np.abs(deltas).argmin()
                timestamp = ts[time]
                timestamps.append(timestamp)

            try:
                self.load_misc(dataset, self.variables)
            except IndexError as e:
                raise ClientError(
                    gettext(
                        "The selected variable(s) were not found in the dataset. \
                Most likely, this variable is a derived product from existing dataset variables. \
                Please select another variable.") + str(e))

            point_data, self.depths = self.get_data(
                dataset, self.variables,
                datetime_to_timestamp(timestamps[0],
                                      self.dataset_config.time_dim_units))
            point_data = np.ma.array(point_data)

        self.data = point_data
        self.observation_time = observation_time
        self.observation_times = observation_times
        self.timestamps = timestamps
        self.timestamp = timestamp
    def load_data(self):
        if isinstance(self.observation[0], numbers.Number):
            self.observation_variable_names = []
            self.observation_variable_units = []
            with Dataset(current_app.config["OBSERVATION_AGG_URL"], 'r') as ds:
                t = netcdftime.utime(ds['time'].units)
                for idx, o in enumerate(self.observation):
                    observation = {}
                    ts = t.num2date(ds['time'][o]).replace(tzinfo=pytz.UTC)
                    observation['time'] = ts.isoformat()
                    observation['longitude'] = ds['lon'][o]
                    observation['latitude'] = ds['lat'][o]

                    observation['depth'] = ds['z'][:]
                    observation['depthunit'] = ds['z'].units

                    observation['datatypes'] = []
                    data = []
                    for v in sorted(ds.variables):
                        if v in ['z', 'lat', 'lon', 'profile', 'time']:
                            continue
                        var = ds[v]
                        if var.datatype == '|S1':
                            continue

                        observation['datatypes'].append("%s [%s]" % (
                            var.long_name,
                            var.units
                        ))
                        data.append(var[o, :])

                        if idx == 0:
                            self.observation_variable_names.append(
                                var.long_name)
                            self.observation_variable_units.append(var.units)

                    observation['data'] = np.ma.array(data).transpose()
                    self.observation[idx] = observation

                self.points = [[o['latitude'], o['longitude']] for o in self.observation]

        with open_dataset(self.dataset_config) as dataset:
            ts = dataset.timestamps

            observation_times = []
            timestamps = []
            for o in self.observation:
                observation_time = dateutil.parser.parse(o['time'])
                observation_times.append(observation_time)

                deltas = [
                    (x.replace(tzinfo=pytz.UTC) -
                     observation_time).total_seconds()
                    for x in ts]

                time = np.abs(deltas).argmin()
                timestamp = ts[time]
                timestamps.append(timestamp)

            try:
                self.load_misc(dataset, self.variables)
            except IndexError as e:
                raise ClientError(gettext("The selected variable(s) were not found in the dataset. \
                Most likely, this variable is a derived product from existing dataset variables. \
                Please select another variable.") + str(e))
                
            point_data, self.depths = self.get_data(dataset, self.variables, time)
            point_data = np.ma.array(point_data)

            point_data = self.apply_scale_factors(point_data)

        self.data = point_data
        self.observation_time = observation_time
        self.observation_times = observation_times
        self.timestamps = timestamps
        self.timestamp = timestamp
    def parse_query(self, query):
        super().parse_query(query)

        if len(self.variables) > 1:
            raise ClientError(
                f"MapPlotter only supports 1 variable. Received multiple: {self.variables}"
            )

        self.projection = query.get('projection')

        self.area = query.get('area')

        names = []
        centroids = []
        all_rings = []
        data = None
        for idx, a in enumerate(self.area):
            if isinstance(a, str):

                sp = a.split('/', 1)
                if data is None:
                    data = list_areas(sp[0], simplify=False)

                b = [x for x in data if x.get('key') == a]
                a = b[0]
                self.area[idx] = a
            else:
                self.points = copy.deepcopy(np.array(a['polygons']))
                a['polygons'] = self.points.tolist()
                a['name'] = " "

            rings = [LinearRing(po) for po in a['polygons']]
            if len(rings) > 1:
                u = cascaded_union(rings)
            else:
                u = rings[0]

            all_rings.append(u)
            if a.get('name'):
                names.append(a.get('name'))
                centroids.append(u.centroid)
        nc = sorted(zip(names, centroids))
        self.names = [n for (n, c) in nc]
        self.centroids = [c for (n, c) in nc]
        data = None

        if len(all_rings) > 1:
            combined = cascaded_union(all_rings)
        else:
            combined = all_rings[0]

        self.combined_area = combined
        combined = combined.envelope

        self.centroid = list(combined.centroid.coords)[0]
        self.bounds = combined.bounds

        self.show_bathymetry = bool(query.get('bathymetry'))
        self.show_area = bool(query.get('showarea'))

        self.quiver = query.get('quiver')

        self.contour = query.get('contour')
    def load_data(self):
        distance = VincentyDistance()
        height = distance.measure(
            (self.bounds[0], self.centroid[1]),
            (self.bounds[2], self.centroid[1])) * 1000 * 1.25
        width = distance.measure(
            (self.centroid[0], self.bounds[1]),
            (self.centroid[0], self.bounds[3])) * 1000 * 1.25

        if self.projection == 'EPSG:32661':  # north pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = min(self.bounds[0], self.bounds[2])
            blat = 5 * np.floor(blat / 5)

            if self.centroid[0] > 80 or near_pole or covers_pole:
                self.basemap = basemap.load_map(
                    'npstere', self.centroid, height, width,
                    min(self.bounds[0], self.bounds[2]))
            else:
                self.basemap = basemap.load_map('lcc', self.centroid, height,
                                                width)
        elif self.projection == 'EPSG:3031':  # south pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = max(self.bounds[0], self.bounds[2])
            blat = 5 * np.ceil(blat / 5)
            # is centerered close to the south pole
            if ((self.centroid[0] < -80 or self.bounds[1] < -80
                 or self.bounds[3] < -80) or covers_pole) or near_pole:
                self.basemap = basemap.load_map(
                    'spstere', self.centroid, height, width,
                    max(self.bounds[0], self.bounds[2]))
            else:
                self.basemap = basemap.load_map('lcc', self.centroid, height,
                                                width)
        elif abs(self.centroid[1] - self.bounds[1]) > 90:

            height_bounds = [self.bounds[0], self.bounds[2]]
            width_bounds = [self.bounds[1], self.bounds[3]]
            height_buffer = (abs(height_bounds[1] - height_bounds[0])) * 0.1
            width_buffer = (abs(width_bounds[0] - width_bounds[1])) * 0.1

            if abs(width_bounds[1] - width_bounds[0]) > 360:
                raise ClientError(
                    gettext(
                        "You have requested an area that exceeds the width of the world. \
                                        Thinking big is good but plots need to be less than 360 deg wide."
                    ))

            if height_bounds[1] < 0:
                height_bounds[1] = height_bounds[1] + height_buffer
            else:
                height_bounds[1] = height_bounds[1] + height_buffer
            if height_bounds[0] < 0:
                height_bounds[0] = height_bounds[0] - height_buffer
            else:
                height_bounds[0] = height_bounds[0] - height_buffer

            new_width_bounds = []
            new_width_bounds.append(width_bounds[0] - width_buffer)

            new_width_bounds.append(width_bounds[1] + width_buffer)

            if abs(new_width_bounds[1] - new_width_bounds[0]) > 360:
                width_buffer = np.floor(
                    (360 - abs(width_bounds[1] - width_bounds[0])) / 2)
                new_width_bounds[0] = width_bounds[0] - width_buffer
                new_width_bounds[1] = width_bounds[1] + width_buffer

            if new_width_bounds[0] < -360:
                new_width_bounds[0] = -360
            if new_width_bounds[1] > 720:
                new_width_bounds[1] = 720

            self.basemap = basemap.load_map(
                'merc', self.centroid, (height_bounds[0], height_bounds[1]),
                (new_width_bounds[0], new_width_bounds[1]))
        else:
            self.basemap = basemap.load_map('lcc', self.centroid, height,
                                            width)

        if self.basemap.aspect < 1:
            gridx = 500
            gridy = int(500 * self.basemap.aspect)
        else:
            gridy = 500
            gridx = int(500 / self.basemap.aspect)

        self.longitude, self.latitude = self.basemap.makegrid(gridx, gridy)
        variables_to_load = self.variables[:]  # we don't want to change self,variables so copy it
        if self.__load_quiver():
            variables_to_load.append(self.quiver['variable'])

        with open_dataset(self.dataset_config,
                          variable=variables_to_load,
                          timestamp=self.time) as dataset:

            self.variable_unit = self.get_variable_units(
                dataset, self.variables)[0]
            self.variable_name = self.get_variable_names(
                dataset, self.variables)[0]

            if self.cmap is None:
                self.cmap = colormap.find_colormap(self.variable_name)

            if self.depth == 'bottom':
                depth_value_map = 'Bottom'
            else:
                self.depth = np.clip(int(self.depth), 0,
                                     len(dataset.depths) - 1)
                depth_value = dataset.depths[self.depth]
                depth_value_map = depth_value

            data = []
            var = dataset.variables[self.variables[0]]
            if self.filetype in ['csv', 'odv', 'txt']:
                d, depth_value_map = dataset.get_area(np.array(
                    [self.latitude, self.longitude]),
                                                      self.depth,
                                                      self.time,
                                                      self.variables[0],
                                                      self.interp,
                                                      self.radius,
                                                      self.neighbours,
                                                      return_depth=True)
            else:
                d = dataset.get_area(np.array([self.latitude, self.longitude]),
                                     self.depth, self.time, self.variables[0],
                                     self.interp, self.radius, self.neighbours)

            data.append(d)
            if self.filetype not in ['csv', 'odv', 'txt']:
                if len(var.dimensions) == 3:
                    self.depth_label = ""
                elif self.depth == 'bottom':
                    self.depth_label = " at Bottom"
                else:
                    self.depth_label = " at " + \
                        str(int(np.round(depth_value_map))) + " m"

            self.data = data[0]

            quiver_data = []
            # Store the quiver data on the same grid as the main variable. This
            # will only be used for CSV export.
            quiver_data_fullgrid = []

            if self.__load_quiver():
                var = dataset.variables[self.quiver['variable']]
                quiver_unit = self.dataset_config.variable[var].unit
                quiver_name = self.dataset_config.variable[var].name
                quiver_x_var = self.dataset_config.variable[
                    var].east_vector_component
                quiver_y_var = self.dataset_config.variable[
                    var].north_vector_component
                quiver_lon, quiver_lat = self.basemap.makegrid(50, 50)

                x_vals = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    quiver_x_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data.append(x_vals)

                y_vals = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    quiver_y_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data.append(y_vals)

                mag_data = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    self.quiver['variable'],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                self.quiver_magnitude = mag_data

                # Get the quiver data on the same grid as the main
                # variable.
                x_vals = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    quiver_x_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data_fullgrid.append(x_vals)

                y_vals = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    quiver_y_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data_fullgrid.append(y_vals)

                self.quiver_name = self.get_variable_names(
                    dataset, [self.quiver['variable']])[0]
                self.quiver_longitude = quiver_lon
                self.quiver_latitude = quiver_lat
                self.quiver_unit = quiver_unit
            self.quiver_data = quiver_data
            self.quiver_data_fullgrid = quiver_data_fullgrid

            if all([
                    dataset.variables[v].is_surface_only()
                    for v in variables_to_load
            ]):
                self.depth = 0

            contour_data = []
            if self.contour is not None and \
                self.contour['variable'] != '' and \
                    self.contour['variable'] != 'none':
                d = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.contour['variable'],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                vc = self.dataset_config.variable[self.contour['variable']]
                contour_unit = vc.unit
                contour_name = vc.name
                contour_data.append(d)
                self.contour_unit = contour_unit
                self.contour_name = contour_name

            self.contour_data = contour_data

            self.timestamp = dataset.nc_data.timestamp_to_iso_8601(self.time)

        if self.compare:
            self.variable_name += " Difference"
            compare_config = DatasetConfig(self.compare['dataset'])
            with open_dataset(compare_config,
                              variable=self.compare['variables'],
                              timestamp=self.compare['time']) as dataset:
                data = []
                for v in self.compare['variables']:
                    var = dataset.variables[v]
                    d = dataset.get_area(
                        np.array([self.latitude, self.longitude]),
                        self.compare['depth'],
                        self.compare['time'],
                        v,
                        self.interp,
                        self.radius,
                        self.neighbours,
                    )
                    data.append(d)

                data = data[0]

                self.data -= data
        # Load bathymetry data
        self.bathymetry = overlays.bathymetry(self.basemap,
                                              self.latitude,
                                              self.longitude,
                                              blur=2)

        if self.depth != 'bottom' and self.depth != 0:
            if quiver_data:
                quiver_bathymetry = overlays.bathymetry(
                    self.basemap, quiver_lat, quiver_lon)

            self.data[np.where(
                self.bathymetry < depth_value_map)] = np.ma.masked
            for d in self.quiver_data:
                d[np.where(quiver_bathymetry < depth_value)] = np.ma.masked
            for d in self.contour_data:
                d[np.where(self.bathymetry < depth_value_map)] = np.ma.masked
        else:
            mask = maskoceans(self.longitude, self.latitude, self.data, True,
                              'h', 1.25).mask
            self.data[~mask] = np.ma.masked
            for d in self.quiver_data:
                mask = maskoceans(self.quiver_longitude, self.quiver_latitude,
                                  d).mask
                d[~mask] = np.ma.masked
            for d in contour_data:
                mask = maskoceans(self.longitude, self.latitude, d).mask
                d[~mask] = np.ma.masked

        if self.area and self.filetype in ['csv', 'odv', 'txt', 'geotiff']:
            area_polys = []
            for a in self.area:
                rings = [LinearRing(p) for p in a['polygons']]
                innerrings = [LinearRing(p) for p in a['innerrings']]

                polygons = []
                for r in rings:
                    inners = []
                    for ir in innerrings:
                        if r.contains(ir):
                            inners.append(ir)

                    polygons.append(Poly(r, inners))

                area_polys.append(MultiPolygon(polygons))

            points = [
                Point(p)
                for p in zip(self.latitude.ravel(), self.longitude.ravel())
            ]

            indicies = []
            for a in area_polys:
                indicies.append(
                    np.where(
                        list(map(lambda p, poly=a: poly.contains(p),
                                 points)))[0])

            indicies = np.unique(np.array(indicies).ravel())
            newmask = np.ones(self.data.shape, dtype=bool)
            newmask[np.unravel_index(indicies, newmask.shape)] = False
            self.data.mask |= newmask

        self.depth_value_map = depth_value_map
Example #12
0
    def get_values(self, area_info, dataset_name, variables):
        config = DatasetConfig(dataset_name)
        with open_dataset(config) as dataset:

            if self.time is None or (type(self.time) == str and
                                            len(self.time) == 0):
                time = -1
            else:
                time = int(self.time)

            if time < 0:
                time += len(dataset.nc_data.timestamps)
            time = np.clip(time, 0, len(dataset.nc_data.timestamps) - 1)

            depth = 0
            depthm = 0

            if self.depth:
                if self.depth == 'bottom':
                    depth = 'bottom'
                    depthm = 'Bottom'
                if len(self.depth) > 0 and \
                        self.depth != 'bottom':
                    depth = int(self.depth)

                    depth = np.clip(depth, 0, len(dataset.depths) - 1)
                    depthm = dataset.depths[depth]

            lat, lon = np.meshgrid(
                np.linspace(area_info.bounds[0], area_info.bounds[2], 50),
                area_info.spaced_points
            )

            output_fmtstr = "%6.5g"
            for v_idx, v in enumerate(variables):
                var = dataset.variables[v]

                variable_name = config.variable[var].name
                variable_unit = config.variable[var].unit

                lat, lon, d = dataset.get_raw_point(
                    lat.ravel(),
                    lon.ravel(),
                    depth,
                    time,
                    v
                )

                lon[np.where(lon > 180)] -= 360

                if len(var.dimensions) == 3:
                    variable_depth = ""
                elif depth == 'bottom':
                    variable_depth = "(@ Bottom)"
                else:
                    variable_depth = "(@%d m)" % np.round(depthm)

                points = [Point(p) for p in zip(lat.values.ravel(), lon.values.ravel())]

                for i, a in enumerate(area_info.area_query):
                    indices = np.where(
                        map(
                            lambda p, poly=area_info.area_polys[i]: poly.contains(p),
                            points
                        )
                    )

                    selection = np.ma.array(d.values.ravel()[indices])
                    if len(selection) > 0 and not selection.mask.all():
                        area_info.output[i]['variables'].append({
                            'name': ("%s %s" % (variable_name,
                                                variable_depth)).strip(),
                            'unit': variable_unit,
                            'min': output_fmtstr % (
                                np.ma.amin(selection).astype(float)
                            ),
                            'max': output_fmtstr % (
                                np.ma.amax(selection).astype(float)
                            ),
                            'mean': output_fmtstr % (
                                np.ma.mean(selection).astype(float)
                            ),
                            'median': output_fmtstr % (
                                np.ma.median(selection).astype(float)
                            ),
                            'stddev': output_fmtstr % (
                                np.ma.std(selection).astype(float)
                            ),
                            'num': "%d" % selection.count(),
                        })
                    else:
                        area_info.output[i]['variables'].append({
                            'name': ("%s %s" % (variable_name,
                                                variable_depth)).strip(),
                            'unit': variable_unit,
                            'min': gettext("No Data"),
                            'max': gettext("No Data"),
                            'mean': gettext("No Data"),
                            'median': gettext("No Data"),
                            'stddev': gettext("No Data"),
                            'num': "0",
                        })
                        ClientError(gettext("there are no datapoints in the area you selected. \
                                                you may have selected a area on land or you may \
                                                have an ara that is smallenough to fit between \
                                                the datapoints try selection a different area or \
                                                a larger area"))

            area_info.stats = area_info.output
            return

        raise ServerError(gettext("An Error has occurred. When opening the dataset. \
                                Please try again or try a different dataset. \
                                If you would like to report this error please \
                                contact [email protected]"))
    def load_data(self):

        width_scale = 1.25
        height_scale = 1.25

        if self.projection == "EPSG:32661":  # north pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = min(self.bounds[0], self.bounds[2])
            blat = 5 * np.floor(blat / 5)

            if self.centroid[0] > 80 or near_pole or covers_pole:
                self.plot_projection = ccrs.Stereographic(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )
                width_scale = 1.5
            else:
                self.plot_projection = ccrs.LambertConformal(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )
        elif self.projection == "EPSG:3031":  # south pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = max(self.bounds[0], self.bounds[2])
            blat = 5 * np.ceil(blat / 5)
            # is centerered close to the south pole
            if ((self.centroid[0] < -80 or self.bounds[1] < -80
                 or self.bounds[3] < -80) or covers_pole) or near_pole:
                self.plot_projection = ccrs.Stereographic(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )
                width_scale = 1.5
            else:
                self.plot_projection = ccrs.LambertConformal(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )

        elif abs(self.centroid[1] - self.bounds[1]) > 90:

            if abs(self.bounds[3] - self.bounds[1]) > 360:
                raise ClientError(
                    gettext(
                        "You have requested an area that exceeds the width \
                        of the world. Thinking big is good but plots need to \
                        be less than 360 deg wide."))
            self.plot_projection = ccrs.Mercator(
                central_longitude=self.centroid[1])

        else:
            self.plot_projection = ccrs.LambertConformal(
                central_latitude=self.centroid[0],
                central_longitude=self.centroid[1])

        proj_bounds = self.plot_projection.transform_points(
            self.pc_projection,
            np.array([self.bounds[1], self.bounds[3]]),
            np.array([self.bounds[0], self.bounds[2]]),
        )
        proj_size = np.diff(proj_bounds, axis=0)

        width = proj_size[0][0] * width_scale
        height = proj_size[0][1] * height_scale

        aspect_ratio = height / width
        if aspect_ratio < 1:
            gridx = 500
            gridy = int(500 * aspect_ratio)
        else:
            gridy = 500
            gridx = int(500 / aspect_ratio)

        self.plot_res = basemap.get_resolution(height, width)

        x_grid, y_grid, self.plot_extent = cimg_transform.mesh_projection(
            self.plot_projection,
            gridx,
            gridy,
            x_extents=(-width / 2, width / 2),
            y_extents=(-height / 2, height / 2),
        )

        latlon_grid = self.pc_projection.transform_points(
            self.plot_projection, x_grid, y_grid)

        self.longitude = latlon_grid[:, :, 0]
        self.latitude = latlon_grid[:, :, 1]

        variables_to_load = self.variables[:]  # we don't want to change self,variables so copy it
        if self.__load_quiver():
            variables_to_load.append(self.quiver["variable"])

        with open_dataset(self.dataset_config,
                          variable=variables_to_load,
                          timestamp=self.time) as dataset:

            self.variable_unit = self.get_variable_units(
                dataset, self.variables)[0]
            self.variable_name = self.get_variable_names(
                dataset, self.variables)[0]

            if self.cmap is None:
                self.cmap = colormap.find_colormap(self.variable_name)

            if self.depth == "bottom":
                depth_value_map = "Bottom"
            else:
                self.depth = np.clip(int(self.depth), 0,
                                     len(dataset.depths) - 1)
                depth_value = dataset.depths[self.depth]
                depth_value_map = depth_value

            data = []
            var = dataset.variables[self.variables[0]]
            if self.filetype in ["csv", "odv", "txt"]:
                d, depth_value_map = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.variables[0],
                    self.interp,
                    self.radius,
                    self.neighbours,
                    return_depth=True,
                )
            else:
                d = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.variables[0],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )

            data.append(d)
            if self.filetype not in ["csv", "odv", "txt"]:
                if len(var.dimensions) == 3:
                    self.depth_label = ""
                elif self.depth == "bottom":
                    self.depth_label = " at Bottom"
                else:
                    self.depth_label = (" at " +
                                        str(int(np.round(depth_value_map))) +
                                        " m")

            self.data = data[0]

            quiver_data = []
            # Store the quiver data on the same grid as the main variable. This
            # will only be used for CSV export.
            quiver_data_fullgrid = []

            if self.__load_quiver():
                var = dataset.variables[self.quiver["variable"]]
                quiver_unit = self.dataset_config.variable[var].unit
                quiver_name = self.dataset_config.variable[var].name
                quiver_x_var = self.dataset_config.variable[
                    var].east_vector_component
                quiver_y_var = self.dataset_config.variable[
                    var].north_vector_component
                quiver_x, quiver_y, _ = cimg_transform.mesh_projection(
                    self.plot_projection,
                    50,
                    50,
                    self.plot_extent[:2],
                    self.plot_extent[2:],
                )
                quiver_coords = self.pc_projection.transform_points(
                    self.plot_projection, quiver_x, quiver_y)
                quiver_lon = quiver_coords[:, :, 0]
                quiver_lat = quiver_coords[:, :, 1]

                x_vals = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    quiver_x_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data.append(x_vals)

                y_vals = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    quiver_y_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data.append(y_vals)

                mag_data = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    self.quiver["variable"],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                self.quiver_magnitude = mag_data

                # Get the quiver data on the same grid as the main
                # variable.
                x_vals = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    quiver_x_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data_fullgrid.append(x_vals)

                y_vals = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    quiver_y_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data_fullgrid.append(y_vals)

                self.quiver_name = self.get_variable_names(
                    dataset, [self.quiver["variable"]])[0]
                self.quiver_longitude = quiver_lon
                self.quiver_latitude = quiver_lat
                self.quiver_unit = quiver_unit
            self.quiver_data = quiver_data
            self.quiver_data_fullgrid = quiver_data_fullgrid

            if all([
                    dataset.variables[v].is_surface_only()
                    for v in variables_to_load
            ]):
                self.depth = 0

            contour_data = []
            if (self.contour is not None and self.contour["variable"] != ""
                    and self.contour["variable"] != "none"):
                d = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.contour["variable"],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                vc = self.dataset_config.variable[self.contour["variable"]]
                contour_unit = vc.unit
                contour_name = vc.name
                contour_data.append(d)
                self.contour_unit = contour_unit
                self.contour_name = contour_name

            self.contour_data = contour_data

            self.timestamp = dataset.nc_data.timestamp_to_iso_8601(self.time)

        if self.compare:
            self.variable_name += " Difference"
            compare_config = DatasetConfig(self.compare["dataset"])
            with open_dataset(
                    compare_config,
                    variable=self.compare["variables"],
                    timestamp=self.compare["time"],
            ) as dataset:
                data = []
                for v in self.compare["variables"]:
                    var = dataset.variables[v]
                    d = dataset.get_area(
                        np.array([self.latitude, self.longitude]),
                        self.compare["depth"],
                        self.compare["time"],
                        v,
                        self.interp,
                        self.radius,
                        self.neighbours,
                    )
                    data.append(d)

                data = data[0]

                self.data -= data
        # Load bathymetry data
        self.bathymetry = overlays.bathymetry(self.latitude,
                                              self.longitude,
                                              blur=2)

        if self.depth != "bottom" and self.depth != 0:
            if quiver_data:
                quiver_bathymetry = overlays.bathymetry(quiver_lat, quiver_lon)

            self.data[np.where(
                self.bathymetry < depth_value_map)] = np.ma.masked
            for d in self.quiver_data:
                d[np.where(quiver_bathymetry < depth_value)] = np.ma.masked
            for d in self.contour_data:
                d[np.where(self.bathymetry < depth_value_map)] = np.ma.masked
        else:
            mask = maskoceans(self.longitude, self.latitude, self.data, True,
                              "h", 1.25).mask
            self.data[~mask] = np.ma.masked
            for d in self.quiver_data:
                mask = maskoceans(self.quiver_longitude, self.quiver_latitude,
                                  d).mask
                d[~mask] = np.ma.masked
            for d in contour_data:
                mask = maskoceans(self.longitude, self.latitude, d).mask
                d[~mask] = np.ma.masked

        if self.area and self.filetype in ["csv", "odv", "txt", "geotiff"]:
            area_polys = []
            for a in self.area:
                rings = [LinearRing(p) for p in a["polygons"]]
                innerrings = [LinearRing(p) for p in a["innerrings"]]

                polygons = []
                for r in rings:
                    inners = []
                    for ir in innerrings:
                        if r.contains(ir):
                            inners.append(ir)

                    polygons.append(Poly(r, inners))

                area_polys.append(MultiPolygon(polygons))

            points = [
                Point(p)
                for p in zip(self.latitude.ravel(), self.longitude.ravel())
            ]

            indicies = []
            for a in area_polys:
                indicies.append(
                    np.where(
                        list(map(lambda p, poly=a: poly.contains(p),
                                 points)))[0])

            indicies = np.unique(np.array(indicies).ravel())
            newmask = np.ones(self.data.shape, dtype=bool)
            newmask[np.unravel_index(indicies, newmask.shape)] = False
            self.data.mask |= newmask

        self.depth_value_map = depth_value_map
Example #14
0
    def load_data(self):
        distance = VincentyDistance()
        height = distance.measure(
            (self.bounds[0], self.centroid[1]),
            (self.bounds[2], self.centroid[1])) * 1000 * 1.25
        width = distance.measure(
            (self.centroid[0], self.bounds[1]),
            (self.centroid[0], self.bounds[3])) * 1000 * 1.25

        if self.projection == 'EPSG:32661':  # north pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = min(self.bounds[0], self.bounds[2])
            blat = 5 * np.floor(blat / 5)

            if self.centroid[0] > 80 or near_pole or covers_pole:
                self.basemap = basemap.load_map(
                    'npstere', self.centroid, height, width,
                    min(self.bounds[0], self.bounds[2]))
            else:
                self.basemap = basemap.load_map('lcc', self.centroid, height,
                                                width)
        elif self.projection == 'EPSG:3031':  # south pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = max(self.bounds[0], self.bounds[2])
            blat = 5 * np.ceil(blat / 5)
            if ((self.centroid[0] < -80 or self.bounds[1] < -80
                 or self.bounds[3] < -80) or covers_pole
                ) or near_pole:  # is centerered close to the south pole
                self.basemap = basemap.load_map(
                    'spstere', self.centroid, height, width,
                    max(self.bounds[0], self.bounds[2]))
            else:
                self.basemap = basemap.load_map('lcc', self.centroid, height,
                                                width)
        elif abs(self.centroid[1] - self.bounds[1]) > 90:

            height_bounds = [self.bounds[0], self.bounds[2]]
            width_bounds = [self.bounds[1], self.bounds[3]]
            height_buffer = (abs(height_bounds[1] - height_bounds[0])) * 0.1
            width_buffer = (abs(width_bounds[0] - width_bounds[1])) * 0.1

            if abs(width_bounds[1] - width_bounds[0]) > 360:
                raise ClientError(
                    gettext(
                        "You have requested an area that exceeds the width of the world. \
                                        Thinking big is good but plots need to be less than 360 deg wide."
                    ))

            if height_bounds[1] < 0:
                height_bounds[1] = height_bounds[1] + height_buffer
            else:
                height_bounds[1] = height_bounds[1] + height_buffer
            if height_bounds[0] < 0:
                height_bounds[0] = height_bounds[0] - height_buffer
            else:
                height_bounds[0] = height_bounds[0] - height_buffer

            new_width_bounds = []
            new_width_bounds.append(width_bounds[0] - width_buffer)

            new_width_bounds.append(width_bounds[1] + width_buffer)

            if abs(new_width_bounds[1] - new_width_bounds[0]) > 360:
                width_buffer = np.floor(
                    (360 - abs(width_bounds[1] - width_bounds[0])) / 2)
                new_width_bounds[0] = width_bounds[0] - width_buffer
                new_width_bounds[1] = width_bounds[1] + width_buffer

            if new_width_bounds[0] < -360:
                new_width_bounds[0] = -360
            if new_width_bounds[1] > 720:
                new_width_bounds[1] = 720

            self.basemap = basemap.load_map(
                'merc', self.centroid, (height_bounds[0], height_bounds[1]),
                (new_width_bounds[0], new_width_bounds[1]))
        else:
            self.basemap = basemap.load_map('lcc', self.centroid, height,
                                            width)

        if self.basemap.aspect < 1:
            gridx = 500
            gridy = int(500 * self.basemap.aspect)
        else:
            gridy = 500
            gridx = int(500 / self.basemap.aspect)

        self.longitude, self.latitude = self.basemap.makegrid(gridx, gridy)

        with open_dataset(get_dataset_url(self.dataset_name)) as dataset:
            if self.time < 0:
                self.time += len(dataset.timestamps)
            self.time = np.clip(self.time, 0, len(dataset.timestamps) - 1)

            self.variable_unit = self.get_variable_units(
                dataset, self.variables)[0]
            self.variable_name = self.get_variable_names(
                dataset, self.variables)[0]
            scale_factor = self.get_variable_scale_factors(
                dataset, self.variables)[0]

            if self.cmap is None:
                if len(self.variables) == 1:
                    self.cmap = colormap.find_colormap(self.variable_name)
                else:
                    self.cmap = colormap.colormaps.get('speed')

            if len(self.variables) == 2:
                self.variable_name = self.vector_name(self.variable_name)

            if self.depth == 'bottom':
                depth_value = 'Bottom'
            else:
                self.depth = np.clip(int(self.depth), 0,
                                     len(dataset.depths) - 1)
                depth_value = dataset.depths[self.depth]

            data = []
            allvars = []
            for v in self.variables:
                var = dataset.variables[v]
                allvars.append(v)
                if self.filetype in ['csv', 'odv', 'txt']:
                    d, depth_value = dataset.get_area(np.array(
                        [self.latitude, self.longitude]),
                                                      self.depth,
                                                      self.time,
                                                      v,
                                                      self.interp,
                                                      self.radius,
                                                      self.neighbours,
                                                      return_depth=True)
                else:
                    d = dataset.get_area(
                        np.array([self.latitude,
                                  self.longitude]), self.depth, self.time, v,
                        self.interp, self.radius, self.neighbours)

                d = np.multiply(d, scale_factor)
                self.variable_unit, d = self.kelvin_to_celsius(
                    self.variable_unit, d)

                data.append(d)
                if self.filetype not in ['csv', 'odv', 'txt']:
                    if len(var.dimensions) == 3:
                        self.depth_label = ""
                    elif self.depth == 'bottom':
                        self.depth_label = " at Bottom"
                    else:
                        self.depth_label = " at " + \
                            str(int(np.round(depth_value))) + " m"

            if len(data) == 2:
                data[0] = np.sqrt(data[0]**2 + data[1]**2)

            self.data = data[0]

            quiver_data = []
            # Store the quiver data on the same grid as the main variable. This
            # will only be used for CSV export.
            quiver_data_fullgrid = []

            if self.quiver is not None and \
                self.quiver['variable'] != '' and \
                    self.quiver['variable'] != 'none':
                for v in self.quiver['variable'].split(','):
                    allvars.append(v)
                    var = dataset.variables[v]
                    quiver_unit = get_variable_unit(self.dataset_name, var)
                    quiver_name = get_variable_name(self.dataset_name, var)
                    quiver_lon, quiver_lat = self.basemap.makegrid(50, 50)
                    d = dataset.get_area(
                        np.array([quiver_lat, quiver_lon]),
                        self.depth,
                        self.time,
                        v,
                        self.interp,
                        self.radius,
                        self.neighbours,
                    )
                    quiver_data.append(d)
                    # Get the quiver data on the same grid as the main
                    # variable.
                    d = dataset.get_area(
                        np.array([self.latitude, self.longitude]),
                        self.depth,
                        self.time,
                        v,
                        self.interp,
                        self.radius,
                        self.neighbours,
                    )
                    quiver_data_fullgrid.append(d)

                self.quiver_name = self.vector_name(quiver_name)
                self.quiver_longitude = quiver_lon
                self.quiver_latitude = quiver_lat
                self.quiver_unit = quiver_unit
            self.quiver_data = quiver_data
            self.quiver_data_fullgrid = quiver_data_fullgrid

            if all(
                [len(dataset.variables[v].dimensions) == 3 for v in allvars]):
                self.depth = 0

            contour_data = []
            if self.contour is not None and \
                self.contour['variable'] != '' and \
                    self.contour['variable'] != 'none':
                d = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.contour['variable'],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                contour_unit = get_variable_unit(
                    self.dataset_name,
                    dataset.variables[self.contour['variable']])
                contour_name = get_variable_name(
                    self.dataset_name,
                    dataset.variables[self.contour['variable']])
                contour_factor = get_variable_scale_factor(
                    self.dataset_name,
                    dataset.variables[self.contour['variable']])
                contour_unit, d = self.kelvin_to_celsius(contour_unit, d)
                d = np.multiply(d, contour_factor)
                contour_data.append(d)
                self.contour_unit = contour_unit
                self.contour_name = contour_name

            self.contour_data = contour_data

            self.timestamp = dataset.timestamps[self.time]

        if self.compare:
            self.variable_name += " Difference"
            with open_dataset(get_dataset_url(
                    self.compare['dataset'])) as dataset:
                data = []
                for v in self.compare['variables']:
                    var = dataset.variables[v]
                    d = dataset.get_area(
                        np.array([self.latitude, self.longitude]),
                        self.compare['depth'],
                        self.compare['time'],
                        v,
                        self.interp,
                        self.radius,
                        self.neighbours,
                    )
                    data.append(d)

                if len(data) == 2:
                    data = np.sqrt(data[0]**2 + data[1]**2)
                else:
                    data = data[0]

                u, data = self.kelvin_to_celsius(
                    dataset.variables[self.compare['variables'][0]].unit, data)

                self.data -= data

        # Load bathymetry data
        self.bathymetry = overlays.bathymetry(self.basemap,
                                              self.latitude,
                                              self.longitude,
                                              blur=2)

        if self.depth != 'bottom' and self.depth != 0:
            if len(quiver_data) > 0:
                quiver_bathymetry = overlays.bathymetry(
                    self.basemap, quiver_lat, quiver_lon)

            self.data[np.where(self.bathymetry < depth_value)] = np.ma.masked
            for d in self.quiver_data:
                d[np.where(quiver_bathymetry < depth_value)] = np.ma.masked
            for d in self.contour_data:
                d[np.where(self.bathymetry < depth_value)] = np.ma.masked
        else:
            mask = maskoceans(self.longitude, self.latitude, self.data, True,
                              'h', 1.25).mask
            self.data[~mask] = np.ma.masked
            for d in self.quiver_data:
                mask = maskoceans(self.quiver_longitude, self.quiver_latitude,
                                  d).mask
                d[~mask] = np.ma.masked
            for d in contour_data:
                mask = maskoceans(self.longitude, self.latitude, d).mask
                d[~mask] = np.ma.masked

        if self.area and self.filetype in ['csv', 'odv', 'txt', 'geotiff']:
            area_polys = []
            for a in self.area:
                rings = [LinearRing(p) for p in a['polygons']]
                innerrings = [LinearRing(p) for p in a['innerrings']]

                polygons = []
                for r in rings:
                    inners = []
                    for ir in innerrings:
                        if r.contains(ir):
                            inners.append(ir)

                    polygons.append(Poly(r, inners))

                area_polys.append(MultiPolygon(polygons))

            points = [
                Point(p)
                for p in zip(self.latitude.ravel(), self.longitude.ravel())
            ]

            indicies = []
            for a in area_polys:
                indicies.append(
                    np.where(
                        list(map(lambda p, poly=a: poly.contains(p),
                                 points)))[0])

            indicies = np.unique(np.array(indicies).ravel())
            newmask = np.ones(self.data.shape, dtype=bool)
            newmask[np.unravel_index(indicies, newmask.shape)] = False
            self.data.mask |= newmask

        self.depth_value = depth_value
Example #15
0
    def load_data(self):
        """
        Calculates and returns the depth, depth-value, and depth unit from a given dataset
        Args:
            depth: Stored depth information (self.depth or self.compare['depth'])
            clip_length: How many depth values to clip (usually len(dataset.depths) - 1)
            dataset: Opened dataset
        Returns:
            (depth, depth_value, depth_unit)
        """
        def find_depth(depth, clip_length, dataset):
            depth_value = 0
            depth_unit = "m"

            if depth:
                if depth == 'bottom':
                    depth_value = 'Bottom'
                    depth_unit = ''
                    return (depth, depth_value, depth_unit)
                else:
                    depth = np.clip(int(depth), 0, clip_length)
                    depth_value = np.round(dataset.depths[depth])
                    depth_unit = "m"
                    return (depth, depth_value, depth_unit)

            return (depth, depth_value, depth_unit)

        # Load left/Main Map
        with open_dataset(self.dataset_config) as dataset:

            latvar, lonvar = utils.get_latlon_vars(dataset)
            self.depth, self.depth_value, self.depth_unit = find_depth(
                self.depth,
                len(dataset.depths) - 1, dataset)

            self.fix_startend_times(dataset, self.starttime, self.endtime)
            time = list(range(self.starttime, self.endtime + 1))

            if len(self.variables) > 1:
                v = []
                for name in self.variables:
                    self.path_points, self.distance, t, value = dataset.get_path(
                        self.points, self.depth, time, name)
                    v.append(value**2)

                value = np.sqrt(np.ma.sum(v, axis=0))

                self.variable_name = self.get_vector_variable_name(
                    dataset, self.variables)
            else:
                self.path_points, self.distance, t, value = dataset.get_path(
                    self.points, self.depth, time, self.variables[0])
                self.variable_name = self.get_variable_names(
                    dataset, self.variables)[0]

            variable_units = self.get_variable_units(dataset, self.variables)
            scale_factors = self.get_variable_scale_factors(
                dataset, self.variables)

            self.variable_unit = variable_units[0]
            self.data = value
            self.times = dataset.timestamps[self.starttime:self.endtime + 1]
            self.data = np.multiply(self.data, scale_factors[0])
            self.data = self.data.transpose()

            # Get colourmap
            if self.cmap is None:
                self.cmap = colormap.find_colormap(self.variable_name)

        # Load data sent from Right Map (if in compare mode)
        if self.compare:
            compare_config = DatasetConfig(self.compare['dataset'])
            with open_dataset(compare_config) as dataset:
                latvar, lonvar = utils.get_latlon_vars(dataset)
                self.compare['depth'], self.compare[
                    'depth_value'], self.compare['depth_unit'] = find_depth(
                        self.compare['depth'],
                        len(dataset.depths) - 1, dataset)

                self.fix_startend_times(dataset, self.compare['starttime'],
                                        self.compare['endtime'])
                time = list(
                    range(self.compare['starttime'],
                          self.compare['endtime'] + 1))

                if len(self.compare['variables']) > 1:
                    v = []
                    for name in self.compare['variables']:
                        path, distance, t, value = dataset.get_path(
                            self.points, self.compare['depth'], time, name)
                        v.append(value**2)

                    value = np.sqrt(np.ma.sum(v, axis=0))
                    self.compare['variable_name'] = \
                            self.get_vector_variable_name(dataset,
                                    self.compare['variables'])
                else:
                    path, distance, t, value = dataset.get_path(
                        self.points, self.compare['depth'], time,
                        self.compare['variables'][0])
                    self.compare['variable_name'] = self.get_variable_names(
                        dataset, self.compare['variables'])[0]

                # Colourmap
                if (self.compare['colormap'] == 'default'):
                    self.compare['colormap'] = colormap.find_colormap(
                        self.compare['variable_name'])
                else:
                    self.compare['colormap'] = colormap.find_colormap(
                        self.compare['colormap'])

                variable_units = self.get_variable_units(
                    dataset, self.compare['variables'])
                scale_factors = self.get_variable_scale_factors(
                    dataset, self.compare['variables'])

                self.compare['variable_unit'] = variable_units[0]
                self.compare['data'] = value
                self.compare['times'] = dataset.timestamps[
                    self.compare['starttime']:self.compare['endtime'] + 1]
                self.compare['data'] = np.multiply(self.compare['data'],
                                                   scale_factors[0])
                self.compare['data'] = self.compare['data'].transpose()

                # Comparison over different time ranges makes no sense
                if self.starttime != self.compare['starttime'] or\
                    self.endtime != self.compare['endtime']:
                    raise ClientError(
                        gettext(
                            "Please ensure the Start Time and End Time for the Left and Right maps are identical."
                        ))