コード例 #1
0
ファイル: models.py プロジェクト: nens/threedigrid
class Orifices(Lines):
    display_name = ArrayField()
    sewerage = ArrayField()
    friction_type = ArrayField()
    friction_value = ArrayField()
    crest_type = ArrayField()
    crest_level = ArrayField()
    discharge_coefficient_negative = ArrayField()
    discharge_coefficient_positive = ArrayField()
    connection_node_start_pk = ArrayField()
    connection_node_end_pk = ArrayField()
コード例 #2
0
ファイル: models.py プロジェクト: nens/threedigrid
class Pumps(Model):
    display_name = ArrayField()
    content_pk = ArrayField()
    type = ArrayField()
    node1_id = ArrayField()
    node2_id = ArrayField()
    bottom_level = ArrayField()
    start_level = ArrayField()
    lower_stop_level = ArrayField()
    capacity = ArrayField()
    coordinates = PointArrayField()
    # coordinates is the centroid of
    # node_coordinates if both set, else
    # the one that is set.
    node_coordinates = LineArrayField()
    # [ [node1_x], [node1_y], [node2_x], [node2_y]]
    # Note: -9999 if nodeX_id is -9999 (not set)
    zoom_category = ArrayField()
コード例 #3
0
ファイル: models.py プロジェクト: nens/threedigrid
class CrossSections(Model):
    code = ArrayField()
    shape = ArrayField()
    content_pk = ArrayField()
    width_1d = ArrayField()
    offset = ArrayField()
    count = ArrayField()
    tables = ArrayField()
コード例 #4
0
ファイル: models.py プロジェクト: nens/threedigrid
class Manholes(ConnectionNodes):
    bottom_level = ArrayField()
    display_name = ArrayField()
    surface_level = ArrayField()
    shape = ArrayField()
    width = ArrayField()
    manhole_indicator = ArrayField()
コード例 #5
0
ファイル: models.py プロジェクト: nens/threedigrid
class Channels(Lines):
    code = ArrayField()
    calculation_type = ArrayField()
    dist_calc_points = ArrayField()
    connection_node_start_pk = ArrayField()
    connection_node_end_pk = ArrayField()
    discharge_coefficient = ArrayField()
コード例 #6
0
class Levees(Model):

    crest_level = ArrayField()
    max_breach_depth = ArrayField()
    coords = MultiLineArrayField()

    def __init__(self, *args,  **kwargs):
        super(Levees, self).__init__(*args, **kwargs)

        self._geoms = []
        self.current_epsg = None
        self._exporters = [
            exporters.LeveeOgrExporter(self),
        ]

    @property
    def geoms(self):
        if not self._geoms:
            self.load_geoms()
        return self._geoms

    def load_geoms(self):
        """
        load levee geometries originating
        from model DB
        """

        # works on premise of ogr install
        if ogr is None:
            raise_import_exception('ogr')

        if self._geoms:
            return
        for line_coords in self.coords:
            line = ogr.Geometry(ogr.wkbLineString)
            linepoints = reshape_flat_array(line_coords).T
            for x in linepoints:
                line.AddPoint(x[0], x[1])
            self._geoms.append(line)
コード例 #7
0
ファイル: models.py プロジェクト: nens/threedigrid
class Breaches(Model):
    """
    fields originating from threedicore:

        - levbr (breach width)
        - levmat (material code)
        - levl (exchange level)
        - kcu (type field 55 or 56)

    added fields from spatialite database:

        - content_pk (primary key database)
        - seq_ids (sequence ids generated during input file generation)

    """
    content_pk = ArrayField()
    seq_ids = ArrayField()
    levbr = ArrayField()
    levl = IndexArrayField(to='Lines')
    levmat = ArrayField()
    kcu = ArrayField()

    coordinates = PointArrayField()

    OBJECT_TYPE = constants.TYPE_V2_BREACH

    def __init__(self, *args, **kwargs):
        logger.warning(
            "Deprecation warning: This model is going to be removed "
            " in the near future, "
            "please use breaches under lines (lines.breaches) instead"
        )
        super(Breaches, self).__init__(*args, **kwargs)

        self._exporters = [
            exporters.BreachesOgrExporter(self),
        ]
コード例 #8
0
ファイル: models.py プロジェクト: nens/threedigrid
class EmbeddedNodes(Nodes):
    embedded_in = ArrayField()
コード例 #9
0
ファイル: models.py プロジェクト: nens/threedigrid
class Nodes(Model):
    content_pk = ArrayField()
    seq_id = ArrayField()
    calculation_type = ArrayField()
    coordinates = PointArrayField()
    cell_coords = BboxArrayField()
    zoom_category = ArrayField()
    node_type = ArrayField()
    is_manhole = BooleanArrayField()
    sumax = ArrayField()
    drain_level = ArrayField()
    storage_area = ArrayField()
    dmax = ArrayField()
    initial_waterlevel = ArrayField()
    dimp = ArrayField()

    SUBSETS = NODE_SUBSETS

    @property
    def connectionnodes(self):
        return self._filter_as(ConnectionNodes, content_pk__ne=0)

    @property
    def manholes(self):
        return self._filter_as(Manholes, is_manhole=True)

    @property
    def added_calculationnodes(self):
        return self._filter_as(AddedCalculationNodes, content_pk=0)

    def __init__(self, *args, **kwargs):

        super(Nodes, self).__init__(*args, **kwargs)

        self._exporters = [
            exporters.NodesOgrExporter(self),
        ]

    @property
    def locations_2d(self):
        data = self.subset('2D_open_water').data
        # x0 = 0, y0 = 0
        # Translate
        # data['coordinates'][0] += x0
        # data['coordinates'][1] += y0

        # Return [[node_id, coordinate_x + x0, coordinate_y + y0]]
        return list(zip(
            data['id'].tolist(),
            data['coordinates'][0].tolist(),
            data['coordinates'][1].tolist()))
コード例 #10
0
ファイル: models.py プロジェクト: nens/threedigrid
class Grid(Model):
    """
    Implemented fields:

    - nodm: the horizintal index of the cell within its refinement level
    - nodn: the vertical index of the cell within its refinement level
    - nodk: the refinement level, 1 being the smallest cell

    They all have the same size as nodes and cells, which is why this
    model lives in the nodes/model module. In fact they are attributes
    of the cell coordinates
    """

    nodm = ArrayField()
    nodn = ArrayField()
    nodk = ArrayField()
    ip = ArrayField()
    jp = ArrayField()

    def __init__(self, *args, **kwargs):
        super(Grid, self).__init__(*args, **kwargs)
        self.class_kwargs["n2dtot"] = kwargs["n2dtot"]

    @property
    def n2dtot(self):
        return self.class_kwargs["n2dtot"]

    @property
    def dx(self):
        """Return size of the grid cell for each refinement level, in meters.
        """
        return self._datasource["dx"][:]

    @property
    def transform(self):
        """Return the transformation that maps pixel_coords to coordinates.

        The six returned values (a, b, c, d, e, f) define the (affine)
        transform between coordinates (x, y) and pixel indices (i, j)
        as follows::

        >>> x = a * i + b * j + c
        >>> y = d * i + e * j + f

        Note that for a 3Di grid, the vertical pixel size is positive, while
        for most raster files this is negative. This means that you should flip
        the vertical axis of the raster when using the pixel coordinates.
        """
        size = float(self._datasource["dxp"][()])
        origin_x = float(self._datasource["x0p"][()])
        origin_y = float(self._datasource["y0p"][()])
        return size, 0.0, origin_x, 0.0, size, origin_y

    def get_pixel_map(self, dem_pixelsize, dem_shape):
        """
        get the node grid to pixel map

        :param dem_pixelsize: pixelsize of the geo tiff
        :param dem_shape: shape of the numpy representation of the geo tiff

        :return: flipped array of the dem_shape that matches the geotiff
        """

        # Convert nod_grid to smallest uint type possible
        dtype = get_smallest_uint_dtype(maxval=self.n2dtot)
        grid_arr = np.zeros(dem_shape, dtype=dtype)

        # applies for for 2D nodes only
        _k = self.nodk[0:self.n2dtot + 1] - 1
        _m = self.nodm[0:self.n2dtot + 1] - 1
        _n = self.nodn[0:self.n2dtot + 1] - 1

        # the size in pixels of each grid cell
        _size = self.dx[_k] / dem_pixelsize
        # corresponding node index
        _ind = np.arange(0, self.n2dtot + 1, dtype='int')

        n_slice_start = np.array(_n * _size, dtype='int')
        n_slice_end = np.array((_n * _size) + _size, dtype='int')
        n_slice = list(zip(n_slice_start, n_slice_end))
        m_slice_start = np.array(_m * _size, dtype='int')
        m_slice_end = np.array((_m * _size) + _size, dtype='int')
        m_slice = list(zip(m_slice_start, m_slice_end))

        for ns, ms, idx in zip(n_slice, m_slice, _ind):
            axis_x = slice(*ns)
            axis_y = slice(*ms)
            grid_arr[axis_x, axis_y] = idx

        # flip upside-down to match geotiff
        return grid_arr[::-1, ::]
コード例 #11
0
ファイル: models.py プロジェクト: nens/threedigrid
class Cells(Nodes):
    """
    Model that represents the threedicore calculation cells. ``Cells`` are
    a sub-class of ``Nodes`` because they share the same attributes.
    ``Cells``, however, also have a z_coordinate, the bottom level of
    the grid cell and cell_coords, the lower left and upper right coordinates
    of the cells extent.

    """

    z_coordinate = ArrayField()
    pixel_width = ArrayField()
    pixel_coords = BboxArrayField()
    has_dem_averaged = ArrayField()

    def __init__(self, *args, **kwargs):

        super(Cells, self).__init__(*args, **kwargs)
        self._exporters = [
            exporters.CellsOgrExporter(self),
        ]

    @property
    def bounds(self):
        """
        :return: coordinates of the cell bounds (counter clockwise):
                 minx, miny, maxx, miny, maxx, maxy, minx, maxy
        """
        minx, miny, maxx, maxy = self.cell_coords
        return np.vstack(
            (minx, miny,
             maxx, miny,
             maxx, maxy,
             minx, maxy))

    def get_id_from_xy(self, x, y, xy_epsg_code=None, subset_name=None):
        """
        :param x: the x coordinate in xy_epsg_code
        :param y: the y coordinate in xy_epsg_code
        :param subset_name: filter on a subset of cells

        :return: numpy array with cell id's for x, y
        """

        if xy_epsg_code and xy_epsg_code != self.epsg_code:
            xy = transform_xys(
                np.array([x]), np.array([y]),
                xy_epsg_code, self.epsg_code).flatten()
        else:
            xy = [x, y]

        inst = self
        if subset_name:
            inst = self.subset(subset_name)
        id = inst.filter(cell_coords__contains_point=xy).id
        return id.tolist()

    def get_ids_from_pix_bbox(self, bbox, subset_name='2D_OPEN_WATER'):
        """
        :param x: the x coordinate in xy_epsg_code
        :param y: the y coordinate in xy_epsg_code
        :param subset_name: filter on a subset of cells

        :return: numpy array with cell id's for x, y
        """

        inst = self
        if subset_name:
            inst = self.subset(subset_name)
        id = inst.filter(pixel_coords__intersects_bbox=bbox).id
        return id.tolist()

    def get_nodgrid(self, pix_bbox, subset_name='2D_OPEN_WATER'):
        ids = np.array(
            self.get_ids_from_pix_bbox(pix_bbox, subset_name=subset_name),
            dtype=np.int32
        )
        nodgrid = create_nodgrid(
            self.pixel_coords[:],
            ids[:],
            int(pix_bbox[2] - pix_bbox[0]),
            int(pix_bbox[3] - pix_bbox[1]),
            int(pix_bbox[0]),
            int(pix_bbox[1])
        )
        return nodgrid[::-1, ::]

    def get_extent_pixels(self):
        """Determine the extent of the cells (in pixels)

        The returned bounding box is left-inclusive; cells cover the
        the half-open intervals [xmin, xmax) and [ymin, ymax).

        :return: tuple of xmin, ymin, xmax, ymax or None
        """
        coords = self.pixel_coords
        mask = ~np.any(coords == -9999, axis=0)
        if not np.any(mask):
            return
        coords = coords[:, mask]
        xmin = coords[0].min()
        ymin = coords[1].min()
        xmax = coords[2].max()
        ymax = coords[3].max()
        return xmin, ymin, xmax, ymax

    def iter_by_tile(self, width, height):
        """Iterate over groups of cells given a tile shape (in pixels).

        The tiles are always aligned to pixel (0, 0) so that a single grid cell
        never overlaps with multiple tiles. For the the same reason, the tile
        size should be an integer multiple of the maximum cell size.

        :param width: the width of the tile in pixels
        :param height: the height of the tile in pixels

        :yield: (xmin, ymin, xmax, ymax), cells
        """
        # determine the width of the largest cell
        cell_size = self.pixel_width.max()
        if width % cell_size != 0 or height % cell_size != 0:
            raise ValueError(
                "width and height should be a multiple of {}".format(cell_size)
            )

        # determine the total extent of the 2d nodes
        xmin, ymin, xmax, ymax = self.get_extent_pixels()

        # determine the lower left and upper right corners
        i1 = int(xmin // width)
        j1 = int(ymin // height)
        i2 = int(np.ceil(float(xmax) / width))
        j2 = int(np.ceil(float(ymax) / height))

        # yield the tiles
        for i, j in itertools.product(range(i1, i2), range(j1, j2)):
            x1, y1, x2, y2 = (
                i * width,
                j * height,
                (i + 1) * width,
                (j + 1) * height,
            )
            result = self.filter(
                pixel_coords__intersects_bbox=(x1 + 1, y1 + 1, x2 - 1, y2 - 1)
            )
            yield (x1, y1, x2, y2), result

    def __repr__(self):
        return "<orm cells instance of {}>".format(self.model_name)

    def __contenttype__(self):
        return 'cells'
コード例 #12
0
ファイル: models.py プロジェクト: nens/threedigrid
class ConnectionNodes(Nodes):
    initial_waterlevel = ArrayField()
コード例 #13
0
ファイル: models.py プロジェクト: nens/threedigrid
class Lines(Model):
    """
    fields originating from threedicore:

        - kcu (line type)
        - lik ()
        - line (index of node representing start/end point)

    added fields from spatialite database:

        - content_pk (primary key database)
        - content_type (type of object as stored in
          database, e.g v2_channel, v2_weir etc)

    custom fields
        - line_coords (coordinate pairs start/end point)
        - line_geometries (geometries from content_type)

    """
    kcu = ArrayField()
    lik = ArrayField()
    line = IndexArrayField(to='Nodes')
    dpumax = ArrayField()
    flod = ArrayField()
    flou = ArrayField()
    cross1 = IndexArrayField(to='CrossSections')
    cross2 = IndexArrayField(to='CrossSections')
    ds1d = ArrayField()
    ds1d_half = ArrayField()
    cross_weight = ArrayField()
    invert_level_start_point = ArrayField()
    invert_level_end_point = ArrayField()
    content_pk = ArrayField()
    content_type = ArrayField()
    zoom_category = ArrayField()
    cross_pix_coords = LineArrayField()
    line_coords = LineArrayField()
    line_geometries = MultiLineArrayField()
    SUBSETS = LINE_SUBSETS

    def __init__(self, *args,  **kwargs):
        super(Lines, self).__init__(*args, **kwargs)

        self._exporters = [
            exporters.LinesOgrExporter(self),
        ]

    @property
    def pipes(self):
        return self._filter_as(Pipes, content_type='v2_pipe')

    @property
    def weirs(self):
        return self._filter_as(Weirs, content_type='v2_weir')

    @property
    def orifices(self):
        return self._filter_as(Orifices, content_type='v2_orifice')

    @property
    def channels(self):
        return self._filter_as(Channels, content_type='v2_channel')

    @property
    def culverts(self):
        return self._filter_as(Culverts, content_type='v2_culvert')

    @property
    def breaches(self):
        return self._filter_as(Breaches, kcu=55)

    @property
    def line_nodes(self):
        return np.dstack(self.line)[0]
コード例 #14
0
ファイル: models.py プロジェクト: nens/threedigrid
class Culverts(Lines):
    display_name = ArrayField()
    code = ArrayField()
    calculation_type = ArrayField()
    dist_calc_points = ArrayField()
    cross_section_height = ArrayField()
    cross_section_width = ArrayField()
    cross_section_shape = ArrayField()
    friction_type = ArrayField()
    friction_value = ArrayField()
    discharge_coefficient_negative = ArrayField()
    discharge_coefficient_positive = ArrayField()
    connection_node_start_pk = ArrayField()
    connection_node_end_pk = ArrayField()
コード例 #15
0
ファイル: models.py プロジェクト: nens/threedigrid
class Weirs(Lines):
    code = ArrayField()
    display_name = ArrayField()
    discharge_coefficient_negative = ArrayField()
    discharge_coefficient_positive = ArrayField()
    sewerage = ArrayField()
    friction_type = ArrayField()
    friction_value = ArrayField()
    crest_type = ArrayField()
    crest_level = ArrayField()
    connection_node_start_pk = ArrayField()
    connection_node_end_pk = ArrayField()
    cross_section_height = ArrayField()
    cross_section_width = ArrayField()
    cross_section_shape = ArrayField()

    @property
    def line_coord_angles(self):
        # Filter raw values with content_type and content_pk
        # to always get the raw (metric) values
        # and not the reprojected ones to calculate
        # the angles with.
        content_type = self._datasource['content_type'][:]
        line_content_pk = self._datasource['content_pk'][:]
        pk_mask = np.isin(line_content_pk, self.content_pk)
        raw_values = self._datasource['line_coords'][:][
            :, (content_type == b'v2_weir') & pk_mask]

        return self._get_field('line_coords').get_angles_in_degrees(
            raw_values)
コード例 #16
0
ファイル: models.py プロジェクト: nens/threedigrid
class Pipes(Lines):
    display_name = ArrayField()
    friction_type = ArrayField()
    friction_value = ArrayField()
    material = ArrayField()
    cross_section_height = ArrayField()
    cross_section_width = ArrayField()
    cross_section_shape = ArrayField()
    sewerage_type = ArrayField()
    calculation_type = ArrayField()
    connection_node_start_pk = ArrayField()
    connection_node_end_pk = ArrayField()
    discharge_coefficient = ArrayField()