예제 #1
0
    def post_process_of_delineated_data(cfg):
        """Do some necessary transfer for subbasin, stream, and flow direction raster."""
        # inputs
        stream_net_file = cfg.taudems.streamnet_shp
        subbasin_file = cfg.taudems.subbsn_m
        flow_dir_file_tau = cfg.taudems.d8flow_m
        stream_raster_file = cfg.taudems.stream_m
        # outputs
        # -- shapefile
        shp_dir = cfg.dirs.geoshp
        UtilClass.mkdir(shp_dir)
        # ---- outlet, copy from DirNameUtils.TauDEM
        FileClass.copy_files(cfg.taudems.outlet_m, cfg.vecs.outlet)
        # ---- reaches
        output_reach_file = cfg.vecs.reach
        # ---- subbasins
        subbasin_vector_file = cfg.vecs.subbsn
        # -- raster file
        output_subbasin_file = cfg.spatials.subbsn
        output_flow_dir_file = cfg.spatials.d8flow
        output_stream_link_file = cfg.spatials.stream_link
        output_hillslope_file = cfg.spatials.hillslope

        id_map = StreamnetUtil.serialize_streamnet(stream_net_file,
                                                   output_reach_file)
        RasterUtilClass.raster_reclassify(subbasin_file, id_map,
                                          output_subbasin_file, GDT_Int32)
        StreamnetUtil.assign_stream_id_raster(stream_raster_file,
                                              output_subbasin_file,
                                              output_stream_link_file)

        # Convert D8 encoding rule to ArcGIS
        D8Util.convert_code(flow_dir_file_tau, output_flow_dir_file)

        # convert raster to shapefile (for subbasin and basin)
        print('Generating subbasin vector...')
        VectorUtilClass.raster2shp(output_subbasin_file, subbasin_vector_file,
                                   'subbasin', FieldNames.subbasin_id)
        mask_file = cfg.spatials.mask
        basin_vector = cfg.vecs.bsn
        print('Generating basin vector...')
        VectorUtilClass.raster2shp(mask_file, basin_vector, 'basin',
                                   FieldNames.basin)
        # delineate hillslope
        DelineateHillslope.downstream_method_whitebox(output_stream_link_file,
                                                      flow_dir_file_tau,
                                                      output_hillslope_file)
예제 #2
0
    def post_process_of_delineated_data(cfg):
        """Do some necessary transfer for subbasin, stream, and flow direction raster."""
        # inputs
        stream_net_file = cfg.taudems.streamnet_shp
        subbasin_file = cfg.taudems.subbsn_m
        flow_dir_file_tau = cfg.taudems.d8flow_m
        stream_raster_file = cfg.taudems.stream_m
        # outputs
        # -- shapefile
        shp_dir = cfg.dirs.geoshp
        UtilClass.mkdir(shp_dir)
        # ---- outlet, copy from DirNameUtils.TauDEM
        FileClass.copy_files(cfg.taudems.outlet_m, cfg.vecs.outlet)
        # ---- reaches
        output_reach_file = cfg.vecs.reach
        # ---- subbasins
        subbasin_vector_file = cfg.vecs.subbsn
        # -- raster file
        output_subbasin_file = cfg.spatials.subbsn
        output_flow_dir_file = cfg.spatials.d8flow
        output_stream_link_file = cfg.spatials.stream_link
        output_hillslope_file = cfg.spatials.hillslope

        id_map = StreamnetUtil.serialize_streamnet(stream_net_file, output_reach_file)
        RasterUtilClass.raster_reclassify(subbasin_file, id_map, output_subbasin_file, GDT_Int32)
        StreamnetUtil.assign_stream_id_raster(stream_raster_file, output_subbasin_file,
                                              output_stream_link_file)

        # Convert D8 encoding rule to ArcGIS
        D8Util.convert_code(flow_dir_file_tau, output_flow_dir_file)

        # convert raster to shapefile (for subbasin and basin)
        print('Generating subbasin vector...')
        VectorUtilClass.raster2shp(output_subbasin_file, subbasin_vector_file, 'subbasin',
                                   FieldNames.subbasin_id)
        mask_file = cfg.spatials.mask
        basin_vector = cfg.vecs.bsn
        print('Generating basin vector...')
        VectorUtilClass.raster2shp(mask_file, basin_vector, 'basin', FieldNames.basin)
        # delineate hillslope
        DelineateHillslope.downstream_method_whitebox(output_stream_link_file, flow_dir_file_tau,
                                                      output_hillslope_file)
예제 #3
0
 def assign_uniqueid_slppos_units(self):
     """Get unique ID by multiply slope position value and hillslope ID"""
     for m in range(self.nrows):
         for n in range(self.ncols):
             if self.data_slppos[m][n] == self.nodata_slppos or \
                 self.data_hillslp[m][n] == self.nodata_hillslp:
                 continue
             cur_slppos = int(self.data_slppos[m][n])
             cur_spname = self.slppos_tags.get(cur_slppos).get('name')
             cur_hs = int(self.data_hillslp[m][n])
             if cur_hs <= self.subbsin_num:  # which is stream
                 continue
             cur_subbsn = DelineateHillslope.get_subbasin_from_hillslope_id(
                 cur_hs, self.subbsin_num)
             if cur_subbsn <= 0:
                 continue
             if cur_slppos not in self.slppos_tags:
                 continue
             cur_unit = cur_hs * cur_slppos
             self.slppos_ids[m][n] = cur_unit
             # calculate theoretical downslope and upslope unit ID (check later)
             down_id = self.slppos_tags.get(cur_slppos).get(
                 'downslope') * cur_hs
             up_id = self.slppos_tags.get(cur_slppos).get(
                 'upslope') * cur_hs
             if down_id < 0:
                 down_id = -1
             if up_id < 0:
                 up_id = -1
             if cur_unit not in self.units_updwon.get(cur_spname):
                 self.units_updwon.get(cur_spname)[cur_unit] = {
                     'area': 1,
                     'downslope': down_id,
                     'upslope': up_id,
                     'hillslope': [cur_hs],
                     'subbasin': [cur_subbsn],
                     'landuse': dict()
                 }
             else:
                 self.units_updwon.get(cur_spname)[cur_unit]['area'] += 1
             # add landuse statistics
             cur_lu = self.data_landuse[m][n]
             if cur_lu != self.nodata_landuse and cur_lu > 0:
                 cur_lu = int(cur_lu)
                 if cur_lu not in self.units_updwon.get(
                         cur_spname)[cur_unit]['landuse']:
                     self.units_updwon.get(
                         cur_spname)[cur_unit]['landuse'][cur_lu] = 1
                 else:
                     self.units_updwon.get(
                         cur_spname)[cur_unit]['landuse'][cur_lu] += 1
예제 #4
0
 def assign_uniqueid_slppos_units(self):
     """Get unique ID by multiply slope position value and hillslope ID"""
     for m in range(self.nrows):
         for n in range(self.ncols):
             if self.data_slppos[m][n] == self.nodata_slppos or \
                             self.data_hillslp[m][n] == self.nodata_hillslp:
                 continue
             cur_slppos = int(self.data_slppos[m][n])
             cur_spname = self.slppos_tags.get(cur_slppos).get('name')
             cur_hs = int(self.data_hillslp[m][n])
             if cur_hs <= self.subbsin_num:  # which is stream
                 continue
             cur_subbsn = DelineateHillslope.get_subbasin_from_hillslope_id(cur_hs,
                                                                            self.subbsin_num)
             if cur_subbsn <= 0:
                 continue
             if cur_slppos not in self.slppos_tags:
                 continue
             cur_unit = cur_hs * cur_slppos
             self.slppos_ids[m][n] = cur_unit
             # calculate theoretical downslope and upslope unit ID (check later)
             down_id = self.slppos_tags.get(cur_slppos).get('downslope') * cur_hs
             up_id = self.slppos_tags.get(cur_slppos).get('upslope') * cur_hs
             if down_id < 0:
                 down_id = -1
             if up_id < 0:
                 up_id = -1
             if cur_unit not in self.units_updwon.get(cur_spname):
                 self.units_updwon.get(cur_spname)[cur_unit] = {'area': 1,
                                                                'downslope': down_id,
                                                                'upslope': up_id,
                                                                'hillslope': [cur_hs],
                                                                'subbasin': [cur_subbsn],
                                                                'landuse': dict()}
             else:
                 self.units_updwon.get(cur_spname)[cur_unit]['area'] += 1
             # add landuse statistics
             cur_lu = self.data_landuse[m][n]
             if cur_lu != self.nodata_landuse and cur_lu > 0:
                 cur_lu = int(cur_lu)
                 if cur_lu not in self.units_updwon.get(cur_spname)[cur_unit]['landuse']:
                     self.units_updwon.get(cur_spname)[cur_unit]['landuse'][cur_lu] = 1
                 else:
                     self.units_updwon.get(cur_spname)[cur_unit]['landuse'][cur_lu] += 1
예제 #5
0
    def merge_slopeposition_units(self):
        """Merge hillslope/subbasin with incomplete slope position sequences"""
        all_units_ids = list()
        for sp in self.slppos_tags:
            name = self.slppos_tags.get(sp).get('name')
            all_units_ids += list(self.units_updwon.get(name).keys())
        # loop each slope position units
        hillslp_elim = dict()
        for sp, spdict in self.slppos_tags.items():
            name = spdict.get('name')
            for unitid, unitdict in self.units_updwon.get(name).items():
                flag = True  # complete sequences or not
                if spdict.get('upslope') > 0 > unitdict.get('upslope'):
                    flag = False
                if spdict.get('downslope') > 0 > unitdict.get('downslope'):
                    flag = False
                cur_hillslp_id = unitdict.get('hillslope')[0]
                if not flag:
                    if cur_hillslp_id not in hillslp_elim:
                        hillslp_elim[cur_hillslp_id] = [unitid]
                if cur_hillslp_id in hillslp_elim and unitid not in hillslp_elim[
                        cur_hillslp_id]:
                    hillslp_elim[cur_hillslp_id].append(unitid)
        print('Hillslope with incomplete slope position sequences: %s' %
              hillslp_elim.__str__())
        # Basic procedure:
        #   1. if header is incomplete, search left and right;
        #      if left/right is incomplete, search header and right/left;
        #   2. if still not incomplete, check the subbasin,
        #   3. if still not satisfied, merge the left and right to the left or right of downstream
        #      (or upstream for outlet subbasin). The header always with the left hillslope.
        hillslope_merge_order = {0: [1, 2], 1: [0, 2], 2: [0, 1]}
        hillslopes_pair = dict()  # TODO. ljzhu.
        units_pair = dict(
        )  # unit id pairs, key is merged unit, value is destination unit.
        for hillid, unitids in hillslp_elim.items():
            subbsnid = DelineateHillslope.get_subbasin_from_hillslope_id(
                hillid, self.subbsin_num)
            hillids = DelineateHillslope.cal_hs_codes(self.subbsin_num,
                                                      subbsnid)
            idx = hillids.index(hillid)
            # slope positions that existed in current hillslope
            sp_seq = list()
            for _id in unitids:
                _id //= hillid
                if _id not in sp_seq:
                    sp_seq.append(_id)

            satisfied = False
            cur_units_pair = dict()
            for curidx in hillslope_merge_order[idx]:
                dst_hillid = hillids[curidx]
                for _id in sp_seq:
                    dst_unit = _id * dst_hillid
                    if dst_unit in all_units_ids:
                        cur_units_pair[_id * hillid] = dst_unit
                for sp in self.slppos_tags:
                    _uid = sp * dst_hillid
                    if _uid in all_units_ids and sp not in sp_seq:
                        sp_seq.append(sp)
                if SlopePositionUnits.check_slppos_sequence(
                        sp_seq, self.slppos_tags):
                    satisfied = True
                    break
            if satisfied:
                units_pair.update(cur_units_pair)
            else:  # means the current subbasin should be merged to downstream
                downstream_merge_idx = {0: 1, 1: 1, 2: 2}
                cur_units_pair = dict()
                dst_subbsn = self.subbsin_tree.get(subbsnid)
                if dst_subbsn < 0:  # outlet subbasin
                    for k, v in self.subbsin_tree.items():
                        if v == subbsnid:
                            dst_subbsn = k
                            break
                # although dst_subbsn may not less than 0, just make sure that!
                if dst_subbsn > 0:
                    dst_hillids = DelineateHillslope.cal_hs_codes(
                        self.subbsin_num, dst_subbsn)
                    dst_downstream_hs = dst_hillids[downstream_merge_idx[idx]]
                    for _id in sp_seq:
                        dst_unit = _id * dst_downstream_hs
                        if dst_unit in all_units_ids:
                            cur_units_pair[_id * hillid] = dst_unit
                units_pair.update(cur_units_pair)

        print('Slope position unit merge-destination pairs: %s' %
              units_pair.__str__())

        # begin to merge
        for srcid, dstid in units_pair.items():
            # replace values in slope position units raster
            for k, v in units_pair.items():
                self.slppos_ids[self.slppos_ids == k] = v

            for sp in self.slppos_tags:
                name = self.slppos_tags.get(sp).get('name')
                if srcid in list(self.units_updwon.get(
                        name).keys()):  # dstid MUST be here too.
                    srcdict = self.units_updwon.get(name)[srcid]
                    self.units_updwon[name][dstid]['area'] += srcdict['area']
                    for luid in srcdict['landuse']:
                        if luid not in self.units_updwon.get(
                                name)[dstid]['landuse']:
                            self.units_updwon[name][dstid]['landuse'][luid] = \
                                srcdict['landuse'][luid]
                        else:
                            self.units_updwon[name][dstid]['landuse'][luid] += \
                                srcdict['landuse'][luid]
                    if srcdict['hillslope'][0] not in self.units_updwon[name][
                            dstid]['hillslope']:
                        self.units_updwon[name][dstid]['hillslope'].append(
                            srcdict['hillslope'][0])
                    if srcdict['subbasin'][0] not in self.units_updwon[name][
                            dstid]['subbasin']:
                        self.units_updwon[name][dstid]['subbasin'].append(
                            srcdict['subbasin'][0])
                    self.units_updwon.get(name).pop(srcid)
                    break

        # rewrite the overview
        units_count = 0
        for sp in self.slppos_tags:
            name = self.slppos_tags.get(sp).get('name')
            cur_units_count = len(list(self.units_updwon.get(name).keys()))
            self.units_updwon.get('overview')[name] = cur_units_count
            units_count += cur_units_count
        self.units_updwon.get('overview')['all_units'] = units_count
예제 #6
0
    def merge_slopeposition_units(self):
        """Merge hillslope/subbasin with incomplete slope position sequences"""
        all_units_ids = list()
        for sp in self.slppos_tags:
            name = self.slppos_tags.get(sp).get('name')
            all_units_ids += list(self.units_updwon.get(name).keys())
        # loop each slope position units
        hillslp_elim = dict()
        for sp, spdict in self.slppos_tags.items():
            name = spdict.get('name')
            for unitid, unitdict in self.units_updwon.get(name).items():
                flag = True  # complete sequences or not
                if spdict.get('upslope') > 0 > unitdict.get('upslope'):
                    flag = False
                if spdict.get('downslope') > 0 > unitdict.get('downslope'):
                    flag = False
                cur_hillslp_id = unitdict.get('hillslope')[0]
                if not flag:
                    if cur_hillslp_id not in hillslp_elim:
                        hillslp_elim[cur_hillslp_id] = [unitid]
                if cur_hillslp_id in hillslp_elim and unitid not in hillslp_elim[cur_hillslp_id]:
                    hillslp_elim[cur_hillslp_id].append(unitid)
        print('Hillslope with incomplete slope position sequences: ' + hillslp_elim.__str__())
        # Basic procedure:
        #   1. if header is incomplete, search left and right;
        #      if left/right is incomplete, search header and right/left;
        #   2. if still not incomplete, check the subbasin,
        #   3. if still not satisfied, merge the left and right to the left or right of downstream
        #      (or upstream for outlet subbasin). The header always with the left hillslope.
        hillslope_merge_order = {0: [1, 2], 1: [0, 2], 2: [0, 1]}
        units_pair = dict()  # unit id pairs, key is merged unit, value is destination unit.
        for hillid, unitids in hillslp_elim.items():
            subbsnid = DelineateHillslope.get_subbasin_from_hillslope_id(hillid, self.subbsin_num)
            hillids = DelineateHillslope.cal_hs_codes(self.subbsin_num, subbsnid)
            idx = hillids.index(hillid)
            # slope positions that existed in current hillslope
            sp_seq = list()
            for _id in unitids:
                _id /= hillid
                if _id not in sp_seq:
                    sp_seq.append(_id)

            satisfied = False
            cur_units_pair = dict()
            for curidx in hillslope_merge_order[idx]:
                dst_hillid = hillids[curidx]
                for _id in sp_seq:
                    dst_unit = _id * dst_hillid
                    if dst_unit in all_units_ids:
                        cur_units_pair[_id * hillid] = dst_unit
                for sp in self.slppos_tags:
                    _uid = sp * dst_hillid
                    if _uid in all_units_ids and sp not in sp_seq:
                        sp_seq.append(sp)
                if SlopePositionUnits.check_slppos_sequence(sp_seq, self.slppos_tags):
                    satisfied = True
                    break
            if satisfied:
                units_pair.update(cur_units_pair)
            else:  # means the current subbasin should be merged to downstream
                downstream_merge_idx = {0: 1, 1: 1, 2: 2}
                cur_units_pair = dict()
                dst_subbsn = self.subbsin_tree.get(subbsnid)
                if dst_subbsn < 0:  # outlet subbasin
                    for k, v in self.subbsin_tree.items():
                        if v == subbsnid:
                            dst_subbsn = k
                            break
                if dst_subbsn > 0:  # although dst_subbsn may not less than 0, just make sure that!
                    dst_hillids = DelineateHillslope.cal_hs_codes(self.subbsin_num, dst_subbsn)
                    dst_downstream_hs = dst_hillids[downstream_merge_idx[idx]]
                    for _id in sp_seq:
                        dst_unit = _id * dst_downstream_hs
                        if dst_unit in all_units_ids:
                            cur_units_pair[_id * hillid] = dst_unit
                units_pair.update(cur_units_pair)

        print('Slope position unit merge-destination pairs: ' + units_pair.__str__())

        # begin to merge
        for srcid, dstid in units_pair.items():
            # replace values in slope position units raster
            for k, v in units_pair.items():
                self.slppos_ids[self.slppos_ids == k] = v

            for sp in self.slppos_tags:
                name = self.slppos_tags.get(sp).get('name')
                if srcid in list(self.units_updwon.get(name).keys()):  # dstid MUST be here too.
                    srcdict = self.units_updwon.get(name)[srcid]
                    self.units_updwon[name][dstid]['area'] += srcdict['area']
                    for luid in srcdict['landuse']:
                        if luid not in self.units_updwon.get(name)[dstid]['landuse']:
                            self.units_updwon[name][dstid]['landuse'][luid] = \
                                srcdict['landuse'][luid]
                        else:
                            self.units_updwon[name][dstid]['landuse'][luid] += \
                                srcdict['landuse'][luid]
                    if srcdict['hillslope'][0] not in self.units_updwon[name][dstid]['hillslope']:
                        self.units_updwon[name][dstid]['hillslope'].append(srcdict['hillslope'][0])
                    if srcdict['subbasin'][0] not in self.units_updwon[name][dstid]['subbasin']:
                        self.units_updwon[name][dstid]['subbasin'].append(srcdict['subbasin'][0])
                    self.units_updwon.get(name).pop(srcid)
                    break

        # rewrite the overview
        units_count = 0
        for sp in self.slppos_tags:
            name = self.slppos_tags.get(sp).get('name')
            cur_units_count = len(list(self.units_updwon.get(name).keys()))
            self.units_updwon.get('overview')[name] = cur_units_count
            units_count += cur_units_count
        self.units_updwon.get('overview')['all_units'] = units_count