Example #1
0
    def clustering_process(self, records, zoom, pix_x, pix_y):
        """
        Iterate records and create point clusters
        We use a simple method that for every point, that is not within any
        cluster, calculate it's 'catchment' area and add it to the cluster
        If a point is within a cluster 'catchment' area increase point
        count for that cluster and recalculate clusters minimum bbox

        :param records: list of records.
        :type records: list

        :param zoom: zoom level of map
        :type zoom: int

        :param pix_x: pixel x of icon
        :type pix_x: int

        :param pix_y: pixel y of icon
        :type pix_y: int
        """

        cluster_points = []
        for record in records:
            # get x,y of site
            centroid = record.get_centroid()
            if not centroid:
                continue
            x = centroid.x
            y = centroid.y

            # check every point in cluster_points
            for pt in cluster_points:
                if 'minbbox' not in pt:
                    pt['minbbox'] = pt['bbox']

                if within_bbox((x, y), pt['minbbox']):
                    # it's in the cluster 'catchment' area
                    pt['count'] += 1
                    pt['minbbox'] = update_min_bbox((x, y), pt['minbbox'])
                    break

            else:
                # point is not in the catchment area of any cluster
                x_range, y_range = overlapping_area(zoom, pix_x, pix_y, y)
                bbox = (x - x_range * 1.5, y - y_range * 1.5,
                        x + x_range * 1.5, y + y_range * 1.5)
                serializer = LocationSiteClusterSerializer(record)
                new_cluster = {
                    'count': 1,
                    'bbox': bbox,
                    'coordinates': [x, y],
                    'record': serializer.data
                }

                cluster_points.append(new_cluster)

        return cluster_points
Example #2
0
def update_cluster(boundary):
    """
    Updating cluster in boundary. It will get all
    biological collection children and generate clustering from that

    :param boundary: boundary that will be checked
    :type boundary: Boundary
    """
    from bims.models.biological_collection_record import (
        BiologicalCollectionRecord)
    from bims.models.location_site import LocationSite
    from bims.models.survey import Survey
    from bims.serializers.location_site_serializer import (
        LocationSiteClusterSerializer)

    records = BiologicalCollectionRecord.objects.filter(validated=True).filter(
        Q(site__geometry_point__intersects=boundary.geometry)
        | Q(site__geometry_line__intersects=boundary.geometry)
        | Q(site__geometry_polygon__intersects=boundary.geometry)
        | Q(site__geometry_multipolygon__intersects=boundary.geometry))
    sites = records.values('site').distinct()

    # update boundary of site
    LocationSite.objects.filter(id__in=sites).update(boundary=boundary)

    # get all children model if no CollectionModel given
    verbose_name = LocationSite._meta.verbose_name

    surveys = Survey.objects.filter(sites__in=sites)
    # create/update new cluster count
    try:
        cluster = Cluster.objects.get(boundary=boundary, module=verbose_name)
    except Cluster.DoesNotExist:
        cluster = Cluster()

    cluster.boundary = boundary
    cluster.module = verbose_name
    cluster.site_count = sites.count()
    details = {
        'records': records.count(),
        'sites': sites.count(),
        'survey': surveys.count(),
    }
    if sites.count() == 1:
        try:
            site = LocationSite.objects.get(id=sites[0]['site'])
            details['site_detail'] = LocationSiteClusterSerializer(site).data
        except LocationSite.DoesNotExist:
            pass

    cluster.details = json.dumps(details)
    cluster.save()

    # logging
    logger.info('CLUSTER : %s, %s' % (cluster.boundary, cluster.module))
    logger.info('FOUND site_count: %s' % cluster.site_count)
    logger.info('DETAILS: %s' % details)
Example #3
0
    def clustering_process(
            collection_records,
            site_records,
            zoom,
            pix_x,
            pix_y,
            cluster_points=[],
            sites=[]):
        """
        Iterate records and create point clusters
        We use a simple method that for every point, that is not within any
        cluster, calculate it's 'catchment' area and add it to the cluster
        If a point is within a cluster 'catchment' area increase point
        count for that cluster and recalculate clusters minimum bbox

        :param collection_records: collection records.
        :type collection_records: search query set

        :param site_records: site records.
        :type site_records: search query set

        :param zoom: zoom level of map
        :type zoom: int

        :param pix_x: pixel x of icon
        :type pix_x: int

        :param pix_y: pixel y of icon
        :type pix_y: int
        """
        for collection in GetCollectionAbstract.queryset_gen(
                collection_records):
            # get x,y of site
            try:
                x = collection.site.geometry_point.x
                y = collection.site.geometry_point.y
                location_site = collection.site
                if collection.site.id in sites:
                    continue
                sites.append(collection.site_id)
            except (ValueError, AttributeError):
                continue

            # check every point in cluster_points
            for pt in cluster_points:
                if 'minbbox' not in pt:
                    pt['minbbox'] = pt['bbox']

                if within_bbox((x, y), pt['minbbox']):
                    # it's in the cluster 'catchment' area
                    pt['count'] += 1
                    pt['minbbox'] = update_min_bbox(
                        (x, y), pt['minbbox'])
                    break

            else:
                # point is not in the catchment area of any cluster
                x_range, y_range = overlapping_area(
                    zoom, pix_x, pix_y, y)
                bbox = (
                    x - x_range * 1.5, y - y_range * 1.5,
                    x + x_range * 1.5, y + y_range * 1.5
                )
                serializer = LocationSiteClusterSerializer(
                    location_site)
                new_cluster = {
                    'count': 1,
                    'bbox': bbox,
                    'coordinates': [x, y],
                    'record': serializer.data
                }

                cluster_points.append(new_cluster)

        return cluster_points, sites