예제 #1
0
def tracks2point(tracks, outputFile):
    """
    Writes tracks to a shapefile as a collection of point features.

    :type  tracks: list of :class:`Track` objects
    :param tracks: :class:`Track` features to store in a shape file

    :param str outputFile: Path to output file destination

    :raises: :mod:`shapefile.ShapefileException` if there is an error
             when attempting to save the file.

    """
    LOG.info("Writing point shape file: {0}".format(outputFile))
    sf = shapefile.Writer(shapefile.POINT)
    sf.fields = OBSFIELDS

    LOG.debug("Processing {0} tracks".format(len(tracks)))

    for track in tracks:
        track.data = recdropfields(track.data, ['Datetime'])
        for lon, lat, rec in zip(track.Longitude, track.Latitude, track.data):
            sf.point(lon, lat)
            sf.record(*rec)

    try:
        sf.save(outputFile)
    except shapefile.ShapefileException:
        LOG.exception("Cannot save shape file: {0}".format(outputFile))
        raise

    return
예제 #2
0
def tracks2line(tracks, outputFile, dissolve=False, netcdf_format=False):
    """
    Writes tracks to a shapefile as a collection of line features

    If dissolve==True, then each track feature is written as a
    single polyline feature, otherwise each track segment is
    stored as a separate feature.

    :type  tracks: list of :class:`Track` objects
    :param tracks: :class:`Track` features to store in a shape file

    :type  outputFile: str
    :param outputFile: Path to output file destination

    :type  dissolve: boolean
    :param dissolve: Store track features or track segments.

    :param bool netcdf_format: Whether tracks are in TCRM format

    :raises: :mod:`shapefile.ShapefileException` if there is an error
             when attempting to save the file.
    """
    LOG.info("Writing line shape file: {0}".format(outputFile))
    sf = shapefile.Writer(shapefile.POLYLINE)
    if netcdf_format:
        sf.fields = TCRM_FIELDS
    elif dissolve:
        sf.fields = EVENTFIELDS
    else:
        sf.fields = OBSFIELDS

    LOG.debug("Processing {0} tracks".format(len(tracks)))

    for track in tracks:
        track.data = recdropfields(track.data, ['Datetime'])
        if dissolve:
            if len(track.data) > 1:
                dlon = np.diff(track.Longitude)
                if dlon.min() < -180:
                    # Track crosses 0E longitude - split track
                    # into multiple parts:
                    idx = np.argmin(dlon)
                    parts = []
                    lines = zip(track.Longitude[:idx], track.Latitude[:idx])

                    parts.append(lines)
                    lines = zip(track.Longitude[idx + 1:],
                                track.Latitude[idx + 1:])

                    parts.append(lines)
                    sf.line(parts)
                else:
                    lines = zip(track.Longitude, track.Latitude)
                    sf.line([lines])
            else:
                lines = zip(track.Longitude, track.Latitude)
                sf.line([lines])

            if netcdf_format:
                sf.record(*track.data[0])
            else:
                minPressure = track.trackMinPressure
                maxWind = track.trackMaxWind

                age = track.TimeElapsed.max()

                startYear = track.Year[0]
                startMonth = track.Month[0]
                startDay = track.Day[0]
                startHour = track.Hour[0]
                startMin = track.Minute[0]
                record = [
                    track.CycloneNumber[0], startYear, startMonth, startDay,
                    startHour, startMin, age, minPressure, maxWind
                ]
                sf.record(*record)

        else:
            if len(track.data) == 1:
                line = [[[track.Longitude, track.Latitude],
                         [track.Longitude, track.Latitude]]]
                sf.line(line)
                sf.record(*track.data[0])
            else:
                for n in range(len(track.data) - 1):
                    dlon = track.Longitude[n + 1] - track.Longitude[n]
                    if dlon < -180.:
                        # case where the track crosses 0E:
                        segment = [[[track.Longitude[n], track.Latitude[n]],
                                    [track.Longitude[n], track.Latitude[n]]]]
                    else:
                        segment = [[[track.Longitude[n], track.Latitude[n]],
                                    [
                                        track.Longitude[n + 1],
                                        track.Latitude[n + 1]
                                    ]]]
                    sf.line(segment)
                    sf.record(*track.data[n])

                # Last point in the track:
                sf.line([[[track.Longitude[n + 1], track.Latitude[n + 1]],
                          [track.Longitude[n + 1], track.Latitude[n + 1]]]])
                sf.record(*track.data[n + 1])

    try:
        sf.save(outputFile)
    except shapefile.ShapefileException:
        LOG.exception("Cannot save shape file: {0}".format(outputFile))
        raise