Пример #1
0
    def update(self, area_key):
        # Select all cells in this area and derive a bounding box for them
        cell_query = (self.cell_model.querykey(self.session, area_key)
                                     .filter(self.cell_model.lat.isnot(None))
                                     .filter(self.cell_model.lon.isnot(None)))
        cells = cell_query.all()

        area_query = self.cell_area_model.querykey(self.session, area_key)
        if len(cells) == 0:
            # If there are no more underlying cells, delete the area entry
            area_query.delete()
        else:
            # Otherwise update the area entry based on all the cells
            area = area_query.first()

            points = [(c.lat, c.lon) for c in cells]
            min_lat = min([c.min_lat for c in cells])
            min_lon = min([c.min_lon for c in cells])
            max_lat = max([c.max_lat for c in cells])
            max_lon = max([c.max_lon for c in cells])

            bbox_points = [(min_lat, min_lon),
                           (min_lat, max_lon),
                           (max_lat, min_lon),
                           (max_lat, max_lon)]

            ctr = centroid(points)
            rng = range_to_points(ctr, bbox_points)

            # Switch units back to meters
            ctr_lat = ctr[0]
            ctr_lon = ctr[1]
            rng = int(round(rng * 1000.0))

            # Now create or update the area
            num_cells = len(cells)
            avg_cell_range = int(sum(
                [cell.range for cell in cells]) / float(num_cells))
            if area is None:
                area = self.cell_area_model(
                    created=self.utcnow,
                    modified=self.utcnow,
                    lat=ctr_lat,
                    lon=ctr_lon,
                    range=rng,
                    avg_cell_range=avg_cell_range,
                    num_cells=num_cells,
                    **area_key.__dict__)
                self.session.add(area)
            else:
                area.modified = self.utcnow
                area.lat = ctr_lat
                area.lon = ctr_lon
                area.range = rng
                area.avg_cell_range = avg_cell_range
                area.num_cells = num_cells
Пример #2
0
def update_lac(self, radio, mcc, mnc, lac):

    with self.db_session() as session:

        # Select all the cells in this LAC that aren't the virtual
        # cell itself, and derive a bounding box for them.

        q = session.query(Cell).filter(Cell.radio == radio).filter(
            Cell.mcc == mcc).filter(Cell.mnc == mnc).filter(
                Cell.lac == lac).filter(Cell.cid != CELLID_LAC)

        cells = q.all()
        points = [(to_degrees(c.lat), to_degrees(c.lon)) for c in cells]
        min_lat = to_degrees(min([c.min_lat for c in cells]))
        min_lon = to_degrees(min([c.min_lon for c in cells]))
        max_lat = to_degrees(max([c.max_lat for c in cells]))
        max_lon = to_degrees(max([c.max_lon for c in cells]))

        bbox_points = [(min_lat, min_lon), (min_lat, max_lon),
                       (max_lat, min_lon), (max_lat, max_lon)]

        ctr = centroid(points)
        rng = range_to_points(ctr, bbox_points)

        # switch units back to DB preferred centimicrodegres angle
        # and meters distance.
        ctr_lat = from_degrees(ctr[0])
        ctr_lon = from_degrees(ctr[1])
        rng = int(round(rng * 1000.0))

        # Now create or update the LAC virtual cell

        q = session.query(Cell).filter(Cell.radio == radio).filter(
            Cell.mcc == mcc).filter(Cell.mnc == mnc).filter(
                Cell.lac == lac).filter(Cell.cid == CELLID_LAC)

        lac = q.first()

        if lac is None:
            lac = Cell(radio=radio,
                       mcc=mcc,
                       mnc=mnc,
                       lac=lac,
                       cid=CELLID_LAC,
                       lat=ctr_lat,
                       lon=ctr_lon,
                       range=rng)
        else:
            lac.new_measures = 0
            lac.lat = ctr_lat
            lac.lon = ctr_lon
            lac.range = rng

        session.commit()
Пример #3
0
    def update(self, area_key):
        # Select all cells in this area and derive a bounding box for them
        cell_query = (self.cell_model.querykey(self.session, area_key).filter(
            self.cell_model.lat.isnot(None)).filter(
                self.cell_model.lon.isnot(None)))
        cells = cell_query.all()

        area_query = self.cell_area_model.querykey(self.session, area_key)
        if len(cells) == 0:
            # If there are no more underlying cells, delete the area entry
            area_query.delete()
        else:
            # Otherwise update the area entry based on all the cells
            area = area_query.first()

            points = [(c.lat, c.lon) for c in cells]
            min_lat = min([c.min_lat for c in cells])
            min_lon = min([c.min_lon for c in cells])
            max_lat = max([c.max_lat for c in cells])
            max_lon = max([c.max_lon for c in cells])

            bbox_points = [(min_lat, min_lon), (min_lat, max_lon),
                           (max_lat, min_lon), (max_lat, max_lon)]

            ctr = centroid(points)
            rng = range_to_points(ctr, bbox_points)

            # Switch units back to meters
            ctr_lat = ctr[0]
            ctr_lon = ctr[1]
            rng = int(round(rng * 1000.0))

            # Now create or update the area
            num_cells = len(cells)
            avg_cell_range = int(
                sum([cell.range for cell in cells]) / float(num_cells))
            if area is None:
                area = self.cell_area_model(created=self.utcnow,
                                            modified=self.utcnow,
                                            lat=ctr_lat,
                                            lon=ctr_lon,
                                            range=rng,
                                            avg_cell_range=avg_cell_range,
                                            num_cells=num_cells,
                                            **area_key.__dict__)
                self.session.add(area)
            else:
                area.modified = self.utcnow
                area.lat = ctr_lat
                area.lon = ctr_lon
                area.range = rng
                area.avg_cell_range = avg_cell_range
                area.num_cells = num_cells
Пример #4
0
def update_lac(self, radio, mcc, mnc, lac):

    with self.db_session() as session:

        # Select all the cells in this LAC that aren't the virtual
        # cell itself, and derive a bounding box for them.

        q = session.query(Cell).filter(
            Cell.radio == radio).filter(
            Cell.mcc == mcc).filter(
            Cell.mnc == mnc).filter(
            Cell.lac == lac).filter(
            Cell.cid != CELLID_LAC).filter(
            Cell.new_measures == 0).filter(
            Cell.lat.isnot(None)).filter(
            Cell.lon.isnot(None))

        cells = q.all()
        if len(cells) == 0:
            return

        points = [(to_degrees(c.lat),
                   to_degrees(c.lon)) for c in cells]
        min_lat = to_degrees(min([c.min_lat for c in cells]))
        min_lon = to_degrees(min([c.min_lon for c in cells]))
        max_lat = to_degrees(max([c.max_lat for c in cells]))
        max_lon = to_degrees(max([c.max_lon for c in cells]))

        bbox_points = [(min_lat, min_lon),
                       (min_lat, max_lon),
                       (max_lat, min_lon),
                       (max_lat, max_lon)]

        ctr = centroid(points)
        rng = range_to_points(ctr, bbox_points)

        # switch units back to DB preferred centimicrodegres angle
        # and meters distance.
        ctr_lat = from_degrees(ctr[0])
        ctr_lon = from_degrees(ctr[1])
        rng = int(round(rng * 1000.0))

        # Now create or update the LAC virtual cell

        q = session.query(Cell).filter(
            Cell.radio == radio).filter(
            Cell.mcc == mcc).filter(
            Cell.mnc == mnc).filter(
            Cell.lac == lac).filter(
            Cell.cid == CELLID_LAC)

        lac = q.first()

        if lac is None:
            lac = Cell(radio=radio,
                       mcc=mcc,
                       mnc=mnc,
                       lac=lac,
                       cid=CELLID_LAC,
                       lat=ctr_lat,
                       lon=ctr_lon,
                       range=rng)
        else:
            lac.new_measures = 0
            lac.lat = ctr_lat
            lac.lon = ctr_lon
            lac.range = rng

        session.commit()
Пример #5
0
def calculate_new_position(station, measures, moving_stations,
                           max_dist_km, backfill=True):
    # if backfill is true, we work on older measures for which
    # the new/total counters where never updated
    length = len(measures)
    latitudes = [w[0] for w in measures]
    longitudes = [w[1] for w in measures]
    new_lat = sum(latitudes) // length
    new_lon = sum(longitudes) // length

    if station.lat and station.lon:
        latitudes.append(station.lat)
        longitudes.append(station.lon)
        existing_station = True
    else:
        station.lat = new_lat
        station.lon = new_lon
        existing_station = False

    # calculate extremes of measures, existing location estimate
    # and existing extreme values
    def extreme(vals, attr, function):
        new = function(vals)
        old = getattr(station, attr, None)
        if old is not None:
            return function(new, old)
        else:
            return new

    min_lat = extreme(latitudes, 'min_lat', min)
    min_lon = extreme(longitudes, 'min_lon', min)
    max_lat = extreme(latitudes, 'max_lat', max)
    max_lon = extreme(longitudes, 'max_lon', max)

    # calculate sphere-distance from opposite corners of
    # bounding box containing current location estimate
    # and new measurements; if too big, station is moving
    box_dist = distance(to_degrees(min_lat), to_degrees(min_lon),
                        to_degrees(max_lat), to_degrees(max_lon))

    if existing_station:

        if box_dist > max_dist_km:
            # add to moving list, return early without updating
            # station since it will be deleted by caller momentarily
            moving_stations.add(station)
            return

        if backfill:
            new_total = station.total_measures + length
            old_length = station.total_measures
            # update total to account for new measures
            # new counter never got updated to include the measures
            station.total_measures = new_total
        else:
            new_total = station.total_measures
            old_length = new_total - length

        station.lat = ((station.lat * old_length) +
                       (new_lat * length)) // new_total
        station.lon = ((station.lon * old_length) +
                       (new_lon * length)) // new_total

    if not backfill:
        # decrease new counter, total is already correct
        # in the backfill case new counter was never increased
        station.new_measures = station.new_measures - length

    # update max/min lat/lon columns
    station.min_lat = min_lat
    station.min_lon = min_lon
    station.max_lat = max_lat
    station.max_lon = max_lon

    # give radio-range estimate between extreme values and centroid
    ctr = (to_degrees(station.lat), to_degrees(station.lon))
    points = [(to_degrees(min_lat), to_degrees(min_lon)),
              (to_degrees(min_lat), to_degrees(max_lon)),
              (to_degrees(max_lat), to_degrees(min_lon)),
              (to_degrees(max_lat), to_degrees(max_lon))]

    station.range = range_to_points(ctr, points) * 1000.0
Пример #6
0
    def calculate_new_position(self, station, observations):
        # This function returns True if the station was found to be moving.
        length = len(observations)
        latitudes = [obs.lat for obs in observations]
        longitudes = [obs.lon for obs in observations]
        new_lat = sum(latitudes) / length
        new_lon = sum(longitudes) / length

        if station.lat and station.lon:
            latitudes.append(station.lat)
            longitudes.append(station.lon)
            existing_station = True
        else:
            station.lat = new_lat
            station.lon = new_lon
            existing_station = False

        # calculate extremes of observations, existing location estimate
        # and existing extreme values
        def extreme(vals, attr, function):
            new = function(vals)
            old = getattr(station, attr, None)
            if old is not None:
                return function(new, old)
            else:
                return new

        min_lat = extreme(latitudes, 'min_lat', min)
        min_lon = extreme(longitudes, 'min_lon', min)
        max_lat = extreme(latitudes, 'max_lat', max)
        max_lon = extreme(longitudes, 'max_lon', max)

        # calculate sphere-distance from opposite corners of
        # bounding box containing current location estimate
        # and new observations; if too big, station is moving
        box_dist = distance(min_lat, min_lon, max_lat, max_lon)

        if existing_station:

            if box_dist > self.max_dist_km:
                # Signal a moving station and return early without updating
                # the station since it will be deleted by caller momentarily
                return True

            # limit the maximum weight of the old station estimate
            old_weight = min(station.total_measures - length,
                             self.MAX_OLD_OBSERVATIONS)
            new_weight = old_weight + length

            station.lat = ((station.lat * old_weight) +
                           (new_lat * length)) / new_weight
            station.lon = ((station.lon * old_weight) +
                           (new_lon * length)) / new_weight

        # decrease new counter, total is already correct
        station.new_measures = station.new_measures - length

        # update max/min lat/lon columns
        station.min_lat = min_lat
        station.min_lon = min_lon
        station.max_lat = max_lat
        station.max_lon = max_lon

        # give radio-range estimate between extreme values and centroid
        ctr = (station.lat, station.lon)
        points = [(min_lat, min_lon), (min_lat, max_lon), (max_lat, min_lon),
                  (max_lat, max_lon)]

        station.range = range_to_points(ctr, points) * 1000.0
        station.modified = util.utcnow()
Пример #7
0
    def calculate_new_position(self, station, observations):
        # This function returns True if the station was found to be moving.
        length = len(observations)
        latitudes = [obs.lat for obs in observations]
        longitudes = [obs.lon for obs in observations]
        new_lat = sum(latitudes) / length
        new_lon = sum(longitudes) / length

        if station.lat and station.lon:
            latitudes.append(station.lat)
            longitudes.append(station.lon)
            existing_station = True
        else:
            station.lat = new_lat
            station.lon = new_lon
            existing_station = False

        # calculate extremes of observations, existing location estimate
        # and existing extreme values
        def extreme(vals, attr, function):
            new = function(vals)
            old = getattr(station, attr, None)
            if old is not None:
                return function(new, old)
            else:
                return new

        min_lat = extreme(latitudes, 'min_lat', min)
        min_lon = extreme(longitudes, 'min_lon', min)
        max_lat = extreme(latitudes, 'max_lat', max)
        max_lon = extreme(longitudes, 'max_lon', max)

        # calculate sphere-distance from opposite corners of
        # bounding box containing current location estimate
        # and new observations; if too big, station is moving
        box_dist = distance(min_lat, min_lon, max_lat, max_lon)

        if existing_station:

            if box_dist > self.max_dist_km:
                # Signal a moving station and return early without updating
                # the station since it will be deleted by caller momentarily
                return True

            # limit the maximum weight of the old station estimate
            old_weight = min(station.total_measures - length,
                             self.MAX_OLD_OBSERVATIONS)
            new_weight = old_weight + length

            station.lat = ((station.lat * old_weight) +
                           (new_lat * length)) / new_weight
            station.lon = ((station.lon * old_weight) +
                           (new_lon * length)) / new_weight

        # decrease new counter, total is already correct
        station.new_measures = station.new_measures - length

        # update max/min lat/lon columns
        station.min_lat = min_lat
        station.min_lon = min_lon
        station.max_lat = max_lat
        station.max_lon = max_lon

        # give radio-range estimate between extreme values and centroid
        ctr = (station.lat, station.lon)
        points = [(min_lat, min_lon),
                  (min_lat, max_lon),
                  (max_lat, min_lon),
                  (max_lat, max_lon)]

        station.range = range_to_points(ctr, points) * 1000.0
        station.modified = util.utcnow()
Пример #8
0
def calculate_new_position(station,
                           measures,
                           moving_stations,
                           max_dist_km,
                           backfill=True):
    # if backfill is true, we work on older measures for which
    # the new/total counters where never updated
    length = len(measures)
    latitudes = [w[0] for w in measures]
    longitudes = [w[1] for w in measures]
    new_lat = sum(latitudes) // length
    new_lon = sum(longitudes) // length

    if station.lat and station.lon:
        latitudes.append(station.lat)
        longitudes.append(station.lon)
        existing_station = True
    else:
        station.lat = new_lat
        station.lon = new_lon
        existing_station = False

    # calculate extremes of measures, existing location estimate
    # and existing extreme values
    def extreme(vals, attr, function):
        new = function(vals)
        old = getattr(station, attr, None)
        if old is not None:
            return function(new, old)
        else:
            return new

    min_lat = extreme(latitudes, 'min_lat', min)
    min_lon = extreme(longitudes, 'min_lon', min)
    max_lat = extreme(latitudes, 'max_lat', max)
    max_lon = extreme(longitudes, 'max_lon', max)

    # calculate sphere-distance from opposite corners of
    # bounding box containing current location estimate
    # and new measurements; if too big, station is moving
    box_dist = distance(to_degrees(min_lat), to_degrees(min_lon),
                        to_degrees(max_lat), to_degrees(max_lon))

    if existing_station:

        if box_dist > max_dist_km:
            # add to moving list, return early without updating
            # station since it will be deleted by caller momentarily
            moving_stations.add(station)
            return

        if backfill:
            new_total = station.total_measures + length
            old_length = station.total_measures
            # update total to account for new measures
            # new counter never got updated to include the measures
            station.total_measures = new_total
        else:
            new_total = station.total_measures
            old_length = new_total - length

        station.lat = ((station.lat * old_length) +
                       (new_lat * length)) // new_total
        station.lon = ((station.lon * old_length) +
                       (new_lon * length)) // new_total

    if not backfill:
        # decrease new counter, total is already correct
        # in the backfill case new counter was never increased
        station.new_measures = station.new_measures - length

    # update max/min lat/lon columns
    station.min_lat = min_lat
    station.min_lon = min_lon
    station.max_lat = max_lat
    station.max_lon = max_lon

    # give radio-range estimate between extreme values and centroid
    ctr = (to_degrees(station.lat), to_degrees(station.lon))
    points = [(to_degrees(min_lat), to_degrees(min_lon)),
              (to_degrees(min_lat), to_degrees(max_lon)),
              (to_degrees(max_lat), to_degrees(min_lon)),
              (to_degrees(max_lat), to_degrees(max_lon))]

    station.range = range_to_points(ctr, points) * 1000.0
Пример #9
0
def update_lac(self, radio, mcc, mnc, lac):
    try:
        utcnow = util.utcnow()
        with self.db_session() as session:
            # Select all the cells in this LAC that aren't the virtual
            # cell itself, and derive a bounding box for them.

            cell_query = session.query(Cell).filter(
                Cell.radio == radio).filter(
                Cell.mcc == mcc).filter(
                Cell.mnc == mnc).filter(
                Cell.lac == lac).filter(
                Cell.cid != CELLID_LAC).filter(
                Cell.lat.isnot(None)).filter(
                Cell.lon.isnot(None))

            cells = cell_query.all()

            lac_query = session.query(Cell).filter(
                Cell.radio == radio).filter(
                Cell.mcc == mcc).filter(
                Cell.mnc == mnc).filter(
                Cell.lac == lac).filter(
                Cell.cid == CELLID_LAC)

            if len(cells) == 0:
                # If there are no more underlying cells, delete the lac entry
                lac_query.delete()
            else:
                # Otherwise update the lac entry based on all the cells
                lac_obj = lac_query.first()

                points = [(c.lat, c.lon) for c in cells]
                min_lat = min([c.min_lat for c in cells])
                min_lon = min([c.min_lon for c in cells])
                max_lat = max([c.max_lat for c in cells])
                max_lon = max([c.max_lon for c in cells])

                bbox_points = [(min_lat, min_lon),
                               (min_lat, max_lon),
                               (max_lat, min_lon),
                               (max_lat, max_lon)]

                ctr = centroid(points)
                rng = range_to_points(ctr, bbox_points)

                # Switch units back to DB preferred centimicrodegres angle
                # and meters distance.
                ctr_lat = ctr[0]
                ctr_lon = ctr[1]
                rng = int(round(rng * 1000.0))

                # Now create or update the LAC virtual cell
                if lac_obj is None:
                    lac_obj = Cell(radio=radio,
                                   mcc=mcc,
                                   mnc=mnc,
                                   lac=lac,
                                   cid=CELLID_LAC,
                                   lat=ctr_lat,
                                   lon=ctr_lon,
                                   created=utcnow,
                                   modified=utcnow,
                                   range=rng,
                                   total_measures=len(cells))
                    session.add(lac_obj)
                else:
                    lac_obj.total_measures = len(cells)
                    lac_obj.lat = ctr_lat
                    lac_obj.lon = ctr_lon
                    lac_obj.modified = utcnow
                    lac_obj.range = rng

            session.commit()
    except Exception as exc:  # pragma: no cover
        self.heka_client.raven('error')
        raise self.retry(exc=exc)
Пример #10
0
def update_lac(self,
               radio,
               mcc,
               mnc,
               lac,
               cell_model_key='cell',
               cell_area_model_key='cell_area'):
    utcnow = util.utcnow()
    with self.db_session() as session:
        # Select all the cells in this LAC that aren't the virtual
        # cell itself, and derive a bounding box for them.

        cell_model = CELL_MODEL_KEYS[cell_model_key]
        cell_query = (session.query(cell_model).filter(
            cell_model.radio == radio).filter(cell_model.mcc == mcc).filter(
                cell_model.mnc == mnc).filter(cell_model.lac == lac).filter(
                    cell_model.lat.isnot(None)).filter(
                        cell_model.lon.isnot(None)))

        cells = cell_query.all()

        cell_area_model = CELL_MODEL_KEYS[cell_area_model_key]
        lac_query = (session.query(cell_area_model).filter(
            cell_area_model.radio == radio).filter(
                cell_area_model.mcc == mcc).filter(
                    cell_area_model.mnc == mnc).filter(
                        cell_area_model.lac == lac))

        if len(cells) == 0:
            # If there are no more underlying cells, delete the lac entry
            lac_query.delete()
        else:
            # Otherwise update the lac entry based on all the cells
            lac_obj = lac_query.first()

            points = [(c.lat, c.lon) for c in cells]
            min_lat = min([c.min_lat for c in cells])
            min_lon = min([c.min_lon for c in cells])
            max_lat = max([c.max_lat for c in cells])
            max_lon = max([c.max_lon for c in cells])

            bbox_points = [(min_lat, min_lon), (min_lat, max_lon),
                           (max_lat, min_lon), (max_lat, max_lon)]

            ctr = centroid(points)
            rng = range_to_points(ctr, bbox_points)

            # Switch units back to DB preferred centimicrodegres angle
            # and meters distance.
            ctr_lat = ctr[0]
            ctr_lon = ctr[1]
            rng = int(round(rng * 1000.0))

            # Now create or update the LAC virtual cell
            num_cells = len(cells)
            avg_cell_range = int(
                sum([cell.range for cell in cells]) / float(num_cells))
            if lac_obj is None:
                lac_obj = cell_area_model(
                    created=utcnow,
                    modified=utcnow,
                    radio=radio,
                    mcc=mcc,
                    mnc=mnc,
                    lac=lac,
                    lat=ctr_lat,
                    lon=ctr_lon,
                    range=rng,
                    avg_cell_range=avg_cell_range,
                    num_cells=num_cells,
                )
                session.add(lac_obj)
            else:
                lac_obj.modified = utcnow
                lac_obj.lat = ctr_lat
                lac_obj.lon = ctr_lon
                lac_obj.range = rng
                lac_obj.avg_cell_range = avg_cell_range
                lac_obj.num_cells = num_cells

        session.commit()
Пример #11
0
def update_lac(self, radio, mcc, mnc, lac):
    try:
        utcnow = util.utcnow()
        with self.db_session() as session:
            # Select all the cells in this LAC that aren't the virtual
            # cell itself, and derive a bounding box for them.

            cell_query = session.query(Cell).filter(
                Cell.radio == radio).filter(Cell.mcc == mcc).filter(
                    Cell.mnc == mnc).filter(
                        Cell.lac == lac).filter(Cell.cid != CELLID_LAC).filter(
                            Cell.lat.isnot(None)).filter(Cell.lon.isnot(None))

            cells = cell_query.all()

            lac_query = session.query(Cell).filter(Cell.radio == radio).filter(
                Cell.mcc == mcc).filter(Cell.mnc == mnc).filter(
                    Cell.lac == lac).filter(Cell.cid == CELLID_LAC)

            if len(cells) == 0:
                # If there are no more underlying cells, delete the lac entry
                lac_query.delete()
            else:
                # Otherwise update the lac entry based on all the cells
                lac_obj = lac_query.first()

                points = [(c.lat, c.lon) for c in cells]
                min_lat = min([c.min_lat for c in cells])
                min_lon = min([c.min_lon for c in cells])
                max_lat = max([c.max_lat for c in cells])
                max_lon = max([c.max_lon for c in cells])

                bbox_points = [(min_lat, min_lon), (min_lat, max_lon),
                               (max_lat, min_lon), (max_lat, max_lon)]

                ctr = centroid(points)
                rng = range_to_points(ctr, bbox_points)

                # Switch units back to DB preferred centimicrodegres angle
                # and meters distance.
                ctr_lat = ctr[0]
                ctr_lon = ctr[1]
                rng = int(round(rng * 1000.0))

                # Now create or update the LAC virtual cell
                if lac_obj is None:
                    lac_obj = Cell(radio=radio,
                                   mcc=mcc,
                                   mnc=mnc,
                                   lac=lac,
                                   cid=CELLID_LAC,
                                   lat=ctr_lat,
                                   lon=ctr_lon,
                                   created=utcnow,
                                   modified=utcnow,
                                   range=rng,
                                   total_measures=len(cells))
                    session.add(lac_obj)
                else:
                    lac_obj.total_measures = len(cells)
                    lac_obj.lat = ctr_lat
                    lac_obj.lon = ctr_lon
                    lac_obj.modified = utcnow
                    lac_obj.range = rng

            session.commit()
    except Exception as exc:  # pragma: no cover
        self.heka_client.raven('error')
        raise self.retry(exc=exc)