Beispiel #1
0
def get_coords(map_name, layer):
    ## Load the vector with the points in it.
    data = vector.VectorTopo(map_name)  # Create a VectorTopo object
    data.open('r', layer=int(layer))  # Open this object for reading
    coords = []
    for i in range(len(data)):
        coords.append(data.read(i + 1).coords())  # gives a tuple
    data.close()
    return coords
Beispiel #2
0
def get_coords(map_name,layer):
    ## Load the vector with the points in it.
    data = vector.VectorTopo(map_name.split('@')[0]) # Create a VectorTopo object
    data.open('r', layer = int(layer)) # Open this object for reading
    coords = {}
    for i in range(len(data)):
        cat_number = data.read(i+1).attrs['cat']
        coords[cat_number] = map(str, data.read(i+1).coords())
    data.close()
    return coords
Beispiel #3
0
def get_points_xy(vect_name):
    """
    to find x and y using pygrass, see my (A. Wickert's) StackOverflow answer:
    http://gis.stackexchange.com/questions/28061/how-to-access-vector-coordinates-in-grass-gis-from-python
    """
    points = vector.VectorTopo(vect_name)
    points.open('r')
    coords = []
    for i in range(len(points)):
        coords.append(points.read(i + 1).coords())
    coords = np.array(coords)
    return coords[:, 0], coords[:, 1]  # x, y
Beispiel #4
0
def get_table_name(map_name, layer):
    ### Test to make sure the vector has the correct layer - and get the table name from it
    data = vector.VectorTopo(map_name.split('@')[0]) # Create a VectorTopo object
    try:
        data.open('r', layer = int(layer)) # Open this object for reading
    except:
        grass.fatal("Map <%s> does not have a layer number %s" % (map_name.split('@')[0],layer))
    try:
        table_name = data.table.name
    except:
        grass.fatal("Map <%s> does not have a table in layer %s" % (map_name.split('@')[0],layer))
    data.close()
    return table_name
Beispiel #5
0
def get_xEN(cat, x0=0., streams=streams):
    """
    """
    data = vector.VectorTopo(streams) # Create a VectorTopo object
    data.open('r') # Open this object for reading

    coords = data.cat(cat_id=cat, vtype='lines')[0]

    x_downstream = [x0]
    E = [ coords[0].x ]
    N = [ coords[0].y ]
    for _i in range(1, len(coords)):
        x_downstream.append(coords[_i-1].distance(coords[_i]))
        E.append(coords[_i].x)
        N.append(coords[_i].y)
    x_downstream = np.cumsum(x_downstream)[::-1]
    
    data.close()
    
    return x_downstream, E, N
Beispiel #6
0
def main(options, flags):

    # Get the options
    points = options["points"]
    strds = options["strds"]
    output = options["output"]
    where = options["where"]
    order = options["order"]
    column = options["column"]
    separator = options["separator"]
    coordinates = options["coordinates"]

    # Setup separator
    if separator == "pipe":
        separator = "|"
    if separator == "comma":
        separator = ","
    if separator == "space":
        separator = " "
    if separator == "tab":
        separator = "\t"
    if separator == "newline":
        separator = "\n"

    use_cats = False

    write_header = flags["n"]
    use_raster_region = flags["r"]

    overwrite = gscript.overwrite()

    if points and coordinates:
        gscript.fatal(_("points and coordinates are mutually exclusive"))

    if not points and not coordinates:
        gscript.fatal(_("You must specify points or coordinates"))

    # Make sure the temporal database exists
    tgis.init()
    # We need a database interface
    dbif = tgis.SQLDatabaseInterfaceConnection()
    dbif.connect()

    sp = tgis.open_old_stds(strds, "strds", dbif)
    maps = sp.get_registered_maps_as_objects(where=where, order=order,
                                             dbif=dbif)
    dbif.close()

    if not maps:
        gscript.fatal(_("Space time raster dataset <%s> is empty") % sp.get_id())

    # The list of sample points
    p_list = []

    if not coordinates:
        # Check if the chosen header column is in the vector map
        vname = points
        vmapset= ""
        if "@" in points:
            vname, vmapset = points.split("@")

        v = pyvect.VectorTopo(vname, vmapset)
        v.open("r")

        col_index = 0

        if v.exist() is False:
            gscript.fatal(_("Vector map <%s> does not exist" %(points)))

        if not v.table:
            use_cats = True
            gscript.warning(_("Vector map <%s> does not have an attribute table, using cats as header column." %(points)))

        if v.table and column not in v.table.columns:
            gscript.fatal(_("Vector map <%s> has no column named %s" %(points, column)))

        if use_cats is False:
            col_index = list(v.table.columns.names()).index(column)

        # Create the point list
        for line in v:
            if line.gtype == libvect.GV_POINT:
                if use_cats is False:
                    p = SamplePoint(line.x, line.y, line.cat, line.attrs.values()[col_index])
                elif use_cats is True:
                    p = SamplePoint(line.x, line.y, line.cat)

                p_list.append(p)

        v.close()
    else:
        # Convert the coordinates into sample points
        coord_list = coordinates.split(",")
        use_cats = True

        count = 0
        cat = 1
        while count < len(coord_list):
            x = coord_list[count]
            count += 1
            y = coord_list[count]
            count += 1

            p = SamplePoint(float(x), float(y), cat)
            p_list.append(p)
            cat += 1

    if output:
        out_file = open(output, "w")
    else:
        out_file = sys.stdout

    # Write the header
    if write_header:
        out_file.write("start_time")
        out_file.write(separator)
        out_file.write("end_time")
        out_file.write(separator)
        count = 0
        for p in p_list:
            count += 1
            if use_cats is True:
                out_file.write(str(p.cat))
            else:
                out_file.write(str(p.column))
            if count != len(p_list):
                out_file.write(separator)
        out_file.write("\n")

    # Sorting the points by y-coordinate to make use of the single row cache and read direction
    sorted_p_list = sorted(p_list, key=SamplePointComparisonY)

    # Sample the raster maps
    num = 0
    for map in maps:
        num += 1
        sys.stderr.write("Sample map <%s> number  %i out of %i\n" %(map.get_name(), num, len(maps)))

        start, end = map.get_temporal_extent_as_tuple()
        out_file.write(str(start))
        out_file.write(separator)
        if not end:
            out_file.write(str(start))
        else:
            out_file.write(str(end))
        out_file.write(separator)

        r = pyrast.RasterRow(map.get_name(), map.get_mapset())
        if r.exist() is False:
            gscript.fatal(_("Raster map <%s> does not exist" %(map.get_id())))

        region = None
        if use_raster_region is True:
            r.set_region_from_rast()
            region = pyregion.Region()
            region.from_rast(map.get_name())
        # Open the raster layer after the region settings
        r.open("r")

        # Sample the raster maps with the sorted points
        for p in sorted_p_list:
            p.value = r.get_value(point=p, region=region)

        # Write the point values from the original list
        count = 0
        for p in p_list:
            count += 1
            out_file.write(str(p.value))
            if count != len(p_list):
                out_file.write(separator)
        out_file.write("\n")

        r.close()

    out_file.close()

# START TESTS
"""
# DOWNSTREAM
selected_cats = []
segment = int(options['cat'])
selected_cats.append(segment)
while selected_cats[-1] != 0:
    selected_cats.append(int(tostream[cats == selected_cats[-1]]))
if selected_cats[-1] == 0:
    selected_cats = selected_cats[:-1] # remove 0 at end if flow is offmap
"""

# Extract x points in network
data = vector.VectorTopo(options['streams'])  # Create a VectorTopo object
data.open('r')  # Open this object for reading
segments = []
for cat in selected_cats:
    points_with_cat = data.cat(cat_id=cat, vtype='lines')[0]
    subcoords = []
    for point in points_with_cat:
        subcoords.append([point.x, point.y])
    segments.append(rn.Segment(_id=cat, to_ids=tostream[cats == cat]))
    segments[-1].set_EastingNorthing(ENarray=subcoords)
    segments[-1].calc_x_from_EastingNorthing()
data.close()

net = rn.Network(segments)

bbox = BoundingBox(points_xy=net.segments_xy_flattened())
Beispiel #8
0
def main():
    """
    Superposition of analytical solutions in gFlex for flexural isostasy in
    GRASS GIS
    """

    options, flags = grass.parser()
    # if just interface description is requested, it will not get to this point
    # so gflex will not be needed

    # GFLEX
    # try to import gflex only after we know that
    # we will actually do the computation
    try:
        import gflex
    except:
        print("")
        print("MODULE IMPORT ERROR.")
        print(
            "In order to run r.flexure or g.flexure, you must download and install"
        )
        print("gFlex. The most recent development version is available from")
        print("https://github.com/awickert/gFlex")
        print("Installation instructions are available on the page.")
        grass.fatal("Software dependency must be installed.")

    ##########
    # SET-UP #
    ##########

    # This code is for 2D flexural isostasy
    flex = gflex.F2D()
    # And show that it is coming from GRASS GIS
    flex.grass = True

    # Method
    flex.Method = 'SAS_NG'

    # Parameters that are often changed for the solution
    ######################################################

    # x, y, q
    flex.x, flex.y = get_points_xy(options['input'])
    # xw, yw: gridded output
    if len(
            grass.parse_command('g.list',
                                type='vect',
                                pattern=options['output'])):
        if not grass.overwrite():
            grass.fatal("Vector map '" + options['output'] +
                        "' already exists. Use '--o' to overwrite.")
    # Just check raster at the same time if it exists
    if len(
            grass.parse_command('g.list',
                                type='rast',
                                pattern=options['raster_output'])):
        if not grass.overwrite():
            grass.fatal("Raster map '" + options['raster_output'] +
                        "' already exists. Use '--o' to overwrite.")
    grass.run_command('v.mkgrid',
                      map=options['output'],
                      type='point',
                      overwrite=grass.overwrite(),
                      quiet=True)
    grass.run_command('v.db.addcolumn',
                      map=options['output'],
                      columns='w double precision',
                      quiet=True)
    flex.xw, flex.yw = get_points_xy(
        options['output'])  # gridded output coordinates
    vect_db = grass.vector_db_select(options['input'])
    col_names = np.array(vect_db['columns'])
    q_col = (col_names == options['column'])
    if np.sum(q_col):
        col_values = np.array(list(vect_db['values'].values())).astype(float)
        flex.q = col_values[:, q_col].squeeze(
        )  # Make it 1D for consistency w/ x, y
    else:
        grass.fatal("provided column name, " + options['column'] +
                    " does not match\nany column in " + options['q0'] + ".")
    # Elastic thickness
    flex.Te = float(options['te'])
    if options['te_units'] == 'km':
        flex.Te *= 1000
    elif options['te_units'] == 'm':
        pass
    else:
        grass.fatal(
            "Inappropriate te_units. How? Options should be limited by GRASS.")
    flex.rho_fill = float(options['rho_fill'])

    # Parameters that often stay at their default values
    ######################################################
    flex.g = float(options['g'])
    flex.E = float(options['ym']
                   )  # Can't just use "E" because reserved for "east", I think
    flex.nu = float(options['nu'])
    flex.rho_m = float(options['rho_m'])

    # Set verbosity
    if grass.verbosity() >= 2:
        flex.Verbose = True
    if grass.verbosity() >= 3:
        flex.Debug = True
    elif grass.verbosity() == 0:
        flex.Quiet = True

    # Check if lat/lon and let user know if verbosity is True
    if grass.region_env()[6] == '3':
        flex.latlon = True
        flex.PlanetaryRadius = float(
            grass.parse_command('g.proj', flags='j')['+a'])
        if flex.Verbose:
            print("Latitude/longitude grid.")
            print("Based on r_Earth = 6371 km")
            print(
                "Computing distances between load points using great circle paths"
            )

    ##########
    # SOLVE! #
    ##########

    flex.initialize()
    flex.run()
    flex.finalize()

    # Now to use lower-level GRASS vector commands to work with the database
    # table and update its entries
    # See for help:
    # http://nbviewer.ipython.org/github/zarch/workshop-pygrass/blob/master/02_Vector.ipynb
    w = vector.VectorTopo(options['output'])
    w.open('rw')  # Get ready to read and write
    wdb = w.dblinks[0]
    wtable = wdb.table()
    col = int((np.array(
        wtable.columns.names()) == 'w').nonzero()[0])  # update this column
    for i in range(1, len(w) + 1):
        # ignoring 1st column: assuming it will be category (always true here)
        wnewvalues = list(w[i].attrs.values())[1:col] + tuple(
            [flex.w[i - 1]]) + list(w[i].attrs.values())[col + 1:]
        wtable.update(key=i, values=wnewvalues)
    wtable.conn.commit()  # Save this
    w.close(build=False)  # don't build here b/c it is always verbose
    grass.run_command('v.build', map=options['output'], quiet=True)

    # And raster export
    # "w" vector defined by raster resolution, so can do direct v.to.rast
    # though if this option isn't selected, the user can do a finer-grained
    # interpolation, which shouldn't introduce much error so long as these
    # outputs are spaced at << 1 flexural wavelength.
    if options['raster_output']:
        grass.run_command('v.to.rast',
                          input=options['output'],
                          output=options['raster_output'],
                          use='attr',
                          attribute_column='w',
                          type='point',
                          overwrite=grass.overwrite(),
                          quiet=True)
        # And create a nice colormap!
        grass.run_command('r.colors',
                          map=options['raster_output'],
                          color='differences',
                          quiet=True)
Beispiel #9
0
def main():
    """
    Links each river segment to the next downstream segment in a tributary
    network by referencing its category (cat) number in a new column. "0"
    means that the river exits the map.
    """
    import matplotlib  # required by windows
    matplotlib.use('wxAGG')  # required by windows
    from matplotlib import pyplot as plt

    options, flags = gscript.parser()

    # Parsing
    window = float(options['window'])
    accum_mult = float(options['accum_mult'])
    if options['units'] == 'm2':
        accum_label = 'Drainage area [m$^2$]'
    elif options['units'] == 'km2':
        accum_label = 'Drainage area [km$^2$]'
    elif options['units'] == 'cumecs':
        accum_label = 'Water discharge [m$^3$ s$^{-1}$]'
    elif options['units'] == 'cfs':
        accum_label = 'Water discharge [cfs]'
    else:
        accum_label = 'Flow accumulation [$-$]'
    plots = options['plots'].split(',')

    # Attributes of streams
    colNames = np.array(vector_db_select(options['streams'])['columns'])
    colValues = np.array(
        vector_db_select(options['streams'])['values'].values())
    tostream = colValues[:, colNames == 'tostream'].astype(int).squeeze()
    cats = colValues[:,
                     colNames == 'cat'].astype(int).squeeze()  # = "fromstream"

    # We can loop over this list to get the shape of the full river network.
    selected_cats = []
    segment = int(options['cat'])
    selected_cats.append(segment)
    x = []
    z = []
    if options['direction'] == 'downstream':
        # Get network
        gscript.message("Network")
        while selected_cats[-1] != 0:
            selected_cats.append(int(tostream[cats == selected_cats[-1]]))
        x.append(selected_cats[-1])
        selected_cats = selected_cats[:-1]  # remove 0 at end

        # Extract x points in network
        data = vector.VectorTopo(
            options['streams'])  # Create a VectorTopo object
        data.open('r')  # Open this object for reading

        coords = []
        _i = 0
        for i in range(len(data)):
            if isinstance(data.read(i + 1), vector.geometry.Line):
                if data.read(i + 1).cat in selected_cats:
                    coords.append(data.read(i + 1).to_array())
                    gscript.core.percent(_i, len(selected_cats),
                                         100. / len(selected_cats))
                    _i += 1
        gscript.core.percent(1, 1, 1)
        coords = np.vstack(np.array(coords))

        _dx = np.diff(coords[:, 0])
        _dy = np.diff(coords[:, 1])
        x_downstream_0 = np.hstack((0, np.cumsum((_dx**2 + _dy**2)**.5)))
        x_downstream = x_downstream_0.copy()

    elif options['direction'] == 'upstream':
        #terminalCATS = list(options['cat'])
        #while terminalCATS:
        #
        print("Upstream direction not yet active!")
        return
        """
        # Add new lists for each successive upstream river
        river_is_upstream =
        while
        full_river_cats
        """

    # Network extraction
    if options['outstream'] is not '':
        selected_cats_str = list(np.array(selected_cats).astype(str))
        selected_cats_csv = ','.join(selected_cats_str)
        v.extract(input=options['streams'],
                  output=options['outstream'],
                  cats=selected_cats_csv,
                  overwrite=gscript.overwrite())

    # Analysis
    gscript.message("Elevation")
    if options['elevation']:
        _include_z = True
        DEM = RasterRow(options['elevation'])
        DEM.open('r')
        z = []
        _i = 0
        _lasti = 0
        for row in coords:
            z.append(DEM.get_value(Point(row[0], row[1])))
            if float(_i) / len(coords) > float(_lasti) / len(coords):
                gscript.core.percent(_i, len(coords), np.floor(_i - _lasti))
            _lasti = _i
            _i += 1
        DEM.close()
        z = np.array(z)
        if options['window'] is not '':
            x_downstream, z = moving_average(x_downstream_0, z, window)
        gscript.core.percent(1, 1, 1)
    else:
        _include_z = False
    gscript.message("Slope")
    if options['slope']:
        _include_S = True
        slope = RasterRow(options['slope'])
        slope.open('r')
        S = []
        _i = 0
        _lasti = 0
        for row in coords:
            S.append(slope.get_value(Point(row[0], row[1])))
            if float(_i) / len(coords) > float(_lasti) / len(coords):
                gscript.core.percent(_i, len(coords), np.floor(_i - _lasti))
            _lasti = _i
            _i += 1
        slope.close()
        S = np.array(S)
        S_0 = S.copy()
        if options['window'] is not '':
            x_downstream, S = moving_average(x_downstream_0, S, window)
        gscript.core.percent(1, 1, 1)
    else:
        _include_S = False
    gscript.message("Accumulation")
    if options['accumulation']:
        _include_A = True
        accumulation = RasterRow(options['accumulation'])
        accumulation.open('r')
        A = []
        _i = 0
        _lasti = 0
        for row in coords:
            A.append(
                accumulation.get_value(Point(row[0], row[1])) * accum_mult)
            if float(_i) / len(coords) > float(_lasti) / len(coords):
                gscript.core.percent(_i, len(coords), np.floor(_i - _lasti))
            _lasti = _i
            _i += 1
        accumulation.close()
        A = np.array(A)
        A_0 = A.copy()
        if options['window'] is not '':
            x_downstream, A = moving_average(x_downstream_0, A, window)
        gscript.core.percent(1, 1, 1)
    else:
        _include_A = False

    # Plotting
    if 'LongProfile' in plots:
        plt.figure()
        plt.plot(x_downstream / 1000., z, 'k-', linewidth=2)
        plt.xlabel('Distance downstream [km]', fontsize=16)
        plt.ylabel('Elevation [m]', fontsize=20)
        plt.tight_layout()
    if 'SlopeAccum' in plots:
        plt.figure()
        plt.loglog(A, S, 'ko', linewidth=2)
        plt.xlabel(accum_label, fontsize=20)
        plt.ylabel('Slope [$-$]', fontsize=20)
        plt.tight_layout()
    if 'SlopeDistance' in plots:
        plt.figure()
        plt.plot(x_downstream / 1000., S, 'k-', linewidth=2)
        plt.xlabel('Distance downstream [km]', fontsize=16)
        plt.ylabel('Slope [$-$]', fontsize=20)
        plt.tight_layout()
    if 'AccumDistance' in plots:
        plt.figure()
        plt.plot(x_downstream / 1000., A, 'k-', linewidth=2)
        plt.xlabel('Distance downstream [km]', fontsize=16)
        plt.ylabel(accum_label, fontsize=20)
        plt.tight_layout()
    plt.show()

    # Saving data
    if options['outfile_original'] is not '':
        header = ['x_downstream', 'E', 'N']
        outfile = np.hstack((np.expand_dims(x_downstream_0, axis=1), coords))
        if _include_S:
            header.append('slope')
            outfile = np.hstack((outfile, np.expand_dims(S_0, axis=1)))
        if _include_A:
            if (options['units'] == 'm2') or (options['units'] == 'km2'):
                header.append('drainage_area_' + options['units'])
            elif (options['units'] == 'cumecs') or (options['units'] == 'cfs'):
                header.append('water_discharge_' + options['units'])
            else:
                header.append('flow_accumulation_arbitrary_units')
            outfile = np.hstack((outfile, np.expand_dims(A_0, axis=1)))
        header = np.array(header)
        outfile = np.vstack((header, outfile))
        np.savetxt(options['outfile_original'], outfile, '%s')
    if options['outfile_smoothed'] is not '':
        header = ['x_downstream', 'E', 'N']
        # E, N on smoothed grid
        x_downstream, E = moving_average(x_downstream_0, coords[:, 0], window)
        x_downstream, N = moving_average(x_downstream_0, coords[:, 1], window)
        # Back to output
        outfile = np.hstack((np.expand_dims(x_downstream,
                                            axis=1), np.expand_dims(E, axis=1),
                             np.expand_dims(N, axis=1)))
        if _include_S:
            header.append('slope')
            outfile = np.hstack((outfile, np.expand_dims(S, axis=1)))
        if _include_A:
            if (options['units'] == 'm2') or (options['units'] == 'km2'):
                header.append('drainage_area_' + options['units'])
            elif (options['units'] == 'cumecs') or (options['units'] == 'cfs'):
                header.append('water_discharge_' + options['units'])
            else:
                header.append('flow_accumulation_arbitrary_units')
            outfile = np.hstack((outfile, np.expand_dims(A, axis=1)))
        header = np.array(header)
        outfile = np.vstack((header, outfile))
        np.savetxt(options['outfile_smoothed'], outfile, '%s')
Beispiel #10
0
      if flex.Verbose:
          print "Latitude/longitude grid."
          print "Based on r_Earth = 6371 km"
          print "Computing distances between load points using great circle paths"
  ##########
  # SOLVE! #
  ##########
  flex.initialize()
  flex.run()
  flex.finalize()
 
  # Now to use lower-level GRASS vector commands to work with the database
  # table and update its entries
  # See for help:
  # http://nbviewer.ipython.org/github/zarch/workshop-pygrass/blob/master/02_Vector.ipynb
  w = vector.VectorTopo(options['output'])
  w.open('rw') # Get ready to read and write
  wdb = w.dblinks[0]
  wtable = wdb.table()
  col = int((np.array(wtable.columns.names()) == 'w').nonzero()[0]) # update this column
  for i in range(1, len(w)+1):
      # ignoring 1st column: assuming it will be category (always true here)
      wnewvalues = w[i].attrs.values()[1:col] + tuple([flex.w[i-1]]) + w[i].attrs.values()[col+1:]
      wtable.update(key=i, values=wnewvalues)
  wtable.conn.commit() # Save this
  w.close(build=False) # don't build here b/c it is always verbose
  grass.run_command('v.build', map=options['output'], quiet=True)
 
  # And raster export
  # "w" vector defined by raster resolution, so can do direct v.to.rast
  # though if this option isn't selected, the user can do a finer-grained
Beispiel #11
0
def main():
    """
    Links each river segment to the next downstream segment in a tributary 
    network by referencing its category (cat) number in a new column. "0"
    means that the river exits the map.
    """

    # Parsing inside function
    _cat = int(options['cat'])
    overwrite_flag = gscript.overwrite()
    elevation = options['elevation']
    if elevation == '': elevation = None    
    slope = options['slope']
    if slope == '': slope = None    
    accumulation = options['accumulation']
    if accumulation == '': accumulation = None
    direction = options['direction']
    if direction == '': direction = None
    streams = options['streams']
    if streams == '': streams = None
    outstream = options['outstream']
    if outstream == '': outstream = None
    outfile = options['outfile']
    if outfile == '': outfile = None
    # !!!!!!!!!!!!!!!!!
    # ADD SWITCHES TO INDIVIDUALLY SMOOTH SLOPE, ACCUM, ETC.
    # !!!!!!!!!!!!!!!!!
    try:
        window = float(options['window'])
    except:
        window = None
    try:
        dx_target = float(options['dx_target'])
    except:
        dx_target = None
    accum_mult = float(options['accum_mult'])
    if options['units'] == 'm2':
        accum_label = 'Drainage area [m$^2$]'
    elif options['units'] == 'km2':
        accum_label = 'Drainage area [km$^2$]'
    elif options['units'] == 'cumecs':
        accum_label = 'Water discharge [m$^3$ s$^{-1}$]'
    elif options['units'] == 'cfs':
        accum_label = 'Water discharge [cfs]'
    else:
        accum_label = 'Flow accumulation [$-$]'
    plots = options['plots'].split(',')

    # Attributes of streams
    colNames = np.array(vector_db_select(streams)['columns'])
    colValues = np.array(vector_db_select(streams)['values'].values())
    warnings.warn('tostream is not generalized')
    tostream = colValues[:,colNames == 'tostream'].astype(int).squeeze()
    cats = colValues[:,colNames == 'cat'].astype(int).squeeze() # = "fromstream"

    # We can loop over this list to get the shape of the full river network.
    selected_cats = []
    segment = _cat
    selected_cats.append(segment)

    # Get all cats in network
    data = vector.VectorTopo(streams) # Create a VectorTopo object
    data.open('r') # Open this object for reading

    if direction == 'downstream':
        gscript.message("Extracting drainage pathway...",)
        # Get network
        while selected_cats[-1] != 0:
            selected_cats.append(int(tostream[cats == selected_cats[-1]]))
        #x.append(selected_cats[-1])
        selected_cats = selected_cats[:-1] # remove 0 at end
        gscript.message("Done.")
        
        
    elif direction == 'upstream':
        gscript.message("Extracting drainage network...",)
        # GENERALIZE COLUMN NAME!!!!!!!!
        tostream_col = np.where(np.array(data.table.columns.names())
                                == 'tostream')[0][0]
        terminalCats = [_cat]
        terminal_x_values = [0]
        netcats = []
        net_tocats = []
        while len(terminalCats) > 0:
            for cat in terminalCats:
                netcats.append(cat)
                # ALSO UNADVISABLE NAME -- NEED TO GET TOSTREAM, GENERALIZED
                #print data.table_to_dict()
                colnum = np.where( np.array(data.table.columns.names()) 
                                   == 'tostream')[0][0]
                net_tocats.append(data.table_to_dict()[cat][colnum])
            oldcats = terminalCats
            terminalCats = []
            for cat in oldcats:
                terminalCats += list(cats[tostream == cat])
        #data.close()
        netcats = np.array(netcats)
        net_tocats = np.array(net_tocats)
        
        selected_cats = netcats
        gscript.message("Done.")
        
    segments = []
    for cat in selected_cats:
        points_with_cat = data.cat(cat_id=cat, vtype='lines')[0]
        subcoords = []
        for point in points_with_cat:
            subcoords.append([point.x, point.y])
        segments.append( rn.Segment(_id=cat, to_ids=tostream[cats == cat]) )
        segments[-1].set_EastingNorthing(ENarray=subcoords)
        segments[-1].calc_x_from_EastingNorthing()
        # x grid spacing
        #print segments[-1].Easting[-1], segments[-1].Northing[-1]
        #print segments[-1].EastingNorthing[-1]
        #print ""
        if dx_target is not None:
            dx_target = float(dx_target)
            segments[-1].set_target_dx_downstream(dx_target)
            segments[-1].densify_x_E_N()
    data.close()
    
    net = rn.Network(segments)

    bbox = BoundingBox(points_xy=net.segments_xy_flattened())
    reg_to_revert = region.Region()
    reg = region.Region() # to limit region for computational efficiency
    reg.set_bbox(bbox.bbox)
    reg.write()
    
    # Network extraction
    if outstream:
        selected_cats_str = list(np.array(selected_cats).astype(str))
        selected_cats_csv = ','.join(selected_cats_str)
        v.extract( input=streams, output=outstream, \
                   cats=selected_cats_csv, overwrite=overwrite_flag )
    
    
    # All coordinates
    coords = net.segments_xy_flattened()
    #x_downstream = 
    
    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    # UPDATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    """
    ##### FIND RIGHT SPOT TO ADD CLASS STUFF HERE/BELOW ####
    
    # Extract x points in network
    data = vector.VectorTopo(streams) # Create a VectorTopo object
    data.open('r') # Open this object for reading
    
    coords = []
    _i = 0
    for i in range(len(data)):
        if type(data.read(i+1)) is vector.geometry.Line:
            if data.read(i+1).cat in selected_cats:
                coords.append(data.read(i+1).to_array())
                gscript.core.percent(_i, len(selected_cats), 100./len(selected_cats))
                _i += 1
    gscript.core.percent(1, 1, 1)
    coords = np.vstack(np.array(coords))
    
    _dx = np.diff(coords[:,0])
    _dy = np.diff(coords[:,1])
    x_downstream_0 = np.hstack((0, np.cumsum((_dx**2 + _dy**2)**.5)))
    x_downstream = x_downstream_0.copy()
    
    data.close()
    """
  
    
    # TEMPORARY!!!!
    #x_downstream = get_xEN()
    #x_downstream_0 = x_downstream[0]

    # Analysis

    # Downstream distances -- 0 at mouth
    net.compute_x_in_network()

    # Elevation
    if elevation:
        gscript.message("Elevation")
        _include_z = True
        # Load DEM
        griddata = garray.array()
        griddata.read(elevation)
        griddata = np.flipud(griddata)
        # Interpolate: nearest or linear?
        x = np.arange(reg.west + reg.ewres/2., reg.east, reg.ewres)
        y = np.arange(reg.south + reg.nsres/2., reg.north, reg.nsres)
        itp = RegularGridInterpolator( (x, y), griddata.transpose(), 
                                       method='nearest')
        _i = 0
        _lasti = 0
        _nexti = 0
        for segment in net.segment_list:
            try:
                segment.set_z( itp(segment.EastingNorthing) )
            except:
                print segment.EastingNorthing
                print np.vstack((segment.Easting_original, segment.Northing_original)).transpose()
                sys.exit()
            if _i > _nexti:
                gscript.core.percent( _i, len(net.segment_list), np.floor(_i - _lasti))
                _nexti = float(_nexti) + len(net.segment_list)/10.
                if _nexti > len(net.segment_list):
                    _nexti = len(net.segment_list) - 1
            _lasti = _i
            _i += 1
        gscript.core.percent(1, 1, 1)
        del griddata
        #warnings.warn('Need to handle window in network')
        #gscript.core.percent(1, 1, 1)
    else:
        _include_z = False

    # Slope
    if slope:
        gscript.message("Slope")
        _include_S = True
        _slope = RasterRow(slope)
        _slope.open('r')
        _i = 0
        _lasti = 0
        _nexti = 0
        for segment in net.segment_list:
            sen = segment.EastingNorthing # all E,N
            S = []
            for row in sen:
                #try:
                S.append(_slope.get_value(Point(row[0], row[1])))
                #except:
                #    print "ERROR"
                if _i > _nexti:
                    gscript.core.percent(_i, len(coords), np.floor(_i - _lasti))
                    _nexti = float(_nexti) + len(coords)/10.
                    if _nexti > len(coords):
                        _nexti = len(coords) - 1
                _lasti = _i
                _i += 1
            # MAKE SETTER FOR THIS!!!!
            segment.channel_slope = np.array(S)
        if window is not None:
            pass
            #net.smooth_window()
            #_x_downstream, _S = moving_average(x_downstream_0, S, window)
        _slope.close()
        S = np.array(S)
        S_0 = S.copy()
        gscript.core.percent(1, 1, 1)
    else:
        _include_S = False

    # Accumulation / drainage area
    if accumulation:
        gscript.message("Accumulation")
        _include_A = True
        accumulation = RasterRow(accumulation)
        accumulation.open('r')
        _i = 0
        _lasti = 0
        _nexti = 0
        for segment in net.segment_list:
            A = []
            sen = segment.EastingNorthing # all E,N
            for row in sen:
                A.append(accumulation.get_value(Point(row[0], row[1])) 
                                                          * accum_mult)
                if _i > _nexti:
                    gscript.core.percent(_i, len(coords), np.floor(_i - _lasti))
                    _nexti = float(_nexti) + len(coords)/10.
                    if _nexti > len(coords):
                        _nexti = len(coords) - 1
                _lasti = _i
                _i += 1
            # MAKE SETTER FOR THIS!!!!
            segment.channel_flow_accumulation = np.array(A)
        accumulation.close()
        A = np.array(A)
        A_0 = A.copy()
        """
        if window is not None:
            _x_downstream, A = moving_average(x_downstream_0, A, window)
        """
        gscript.core.percent(1, 1, 1)
    else:
        _include_A = False

    # Revert to original region
    reg_to_revert

    # Smoothing
    if window is not None:
        net.smooth_window(window)

    # Plotting
    if 'LongProfile' in plots:
        plt.figure()
        if window:
            for segment in net.segment_list:
                plt.plot(segment.x/1000., segment.z_smoothed, 'k-', linewidth=2)
        else:
            for segment in net.segment_list:
                plt.plot(segment.x/1000., segment.z, 'k-', linewidth=2)
        #plt.plot(x_downstream/1000., z, 'k-', linewidth=2)
        plt.xlabel('Distance from mouth [km]', fontsize=16)
        plt.ylabel('Elevation [m]', fontsize=16)
        plt.tight_layout()
    if 'SlopeAccum' in plots:
        plt.figure()
        if window:
            for segment in net.segment_list:
                _y_points = segment.channel_slope_smoothed[
                                segment.channel_flow_accumulation_smoothed > 0
                                ]
                _x_points = segment.channel_flow_accumulation_smoothed[
                                segment.channel_flow_accumulation_smoothed > 0
                                ]
                plt.loglog(_x_points, _y_points, 'k.', alpha=.5)
        else:
            for segment in net.segment_list:
                _y_points = segment.channel_slope[
                                    segment.channel_flow_accumulation > 0
                                    ]
                _x_points = segment.channel_flow_accumulation[
                                    segment.channel_flow_accumulation > 0
                                    ]
                plt.loglog(_x_points, _y_points, 'k.', alpha=.5)
        plt.xlabel(accum_label, fontsize=16)
        plt.ylabel('Slope [$-$]', fontsize=16)
        plt.tight_layout()
    if 'SlopeDistance' in plots:
        plt.figure()
        if window:
            for segment in net.segment_list:
                plt.plot(segment.x/1000., segment.channel_slope_smoothed,
                            'k-', linewidth=2)
        else:
            for segment in net.segment_list:
                plt.plot(segment.x/1000., segment.channel_slope,
                            'k-', linewidth=2)
        plt.xlabel('Distance downstream [km]', fontsize=16)
        plt.ylabel('Slope [$-$]', fontsize=20)
        plt.tight_layout()
    if 'AccumDistance' in plots:
        plt.figure()
        for segment in net.segment_list:
            _x_points = segment.x[segment.channel_flow_accumulation > 0]
            _y_points = segment.channel_flow_accumulation[
                                         segment.channel_flow_accumulation > 0
                                         ]
            plt.plot(_x_points/1000., _y_points, 'k.', alpha=.5)
        plt.xlabel('Distance downstream [km]', fontsize=16)
        plt.ylabel(accum_label, fontsize=16)
        plt.tight_layout()
    plt.show()
    
    # Saving data -- will need to update for more complex data structures!
    if outfile:
        net.compute_profile_from_starting_segment()
        _outfile = np.vstack((net.long_profile_header, net.long_profile_output))
        np.savetxt(outfile, _outfile, '%s')
    else:
        pass
        
    #print net.accum_from_headwaters[1] - net.slope_from_headwaters[1]

    """
    for segment in net.segment_list:
        print segment.channel_flow_accumulation_smoothed
        print segment.channel_slope_smoothed
        print segment.channel_flow_accumulation_smoothed - \
              segment.channel_slope_smoothed
    """
    
    """