def preparationBatiOCS(urbanatlas_input, ucz_output, emprise_file, mask_file,
                       enter_with_mask, image_file, mnh_file, built_files_list,
                       hydrography_file, roads_files_list, rpg_file,
                       indicators_method, ucz_method, dbms_choice,
                       threshold_ndvi, threshold_ndvi_water, threshold_ndwi2,
                       threshold_bi_bottom, threshold_bi_top, path_time_log,
                       temp_directory, format_vector, extension_raster,
                       extension_vector):

    print(bold + yellow +
          "Début de la préparation du bâti issu de la classif OCS." + endC)
    step = "    Début de la préparation du bâti issu de la classif OCS : "
    timeLine(path_time_log, step)

    built_classif = temp_directory + os.sep + "bati_classif" + extension_raster
    built_polygonize = temp_directory + os.sep + "bati_polygonize" + extension_vector
    built_clean = temp_directory + os.sep + "bati_clean" + extension_vector
    built_simplify = temp_directory + os.sep + "bati_simplify" + extension_vector
    built_ready = temp_directory + os.sep + "bati" + extension_vector

    print(bold + cyan +
          "    Extraction du bâti du fichier de classification '%s' :" %
          (image_file) + endC)
    os.system(
        "otbcli_BandMath -il %s -out %s uint8 -exp 'im1b1==11100 ? 10 : 1'" %
        (image_file, built_classif))  # Extraction du bâti de la classif
    print(
        bold + cyan +
        "    Vectorisation du bâti (attention, cette étape peut être extrêmement longue !) :"
        + endC)
    os.system(
        "gdal_polygonize.py -mask %s %s -f 'ESRI Shapefile' %s built_classif id"
        % (built_classif, built_classif,
           built_polygonize))  # Vectorisation du bâti précédemment extrait
    print(bold + cyan + "    Nettoyage du bâti :" + endC)
    cleanMiniAreaPolygons(
        built_polygonize, built_clean, 20, format_vector
    )  # Nettoyage du bâti vectorisé (élimination des petits polygones) - Surface de nettoyage par défaut : 20
    print(bold + cyan + "    Simplification du bâti :" + endC)
    simplifyVector(
        built_clean, built_simplify, 1, format_vector
    )  # Simplification du bâti vectorisé (suppression de l'effet "marches d'escalier" dû aux pixels) - Indice de lissage par défaut : 1
    print(bold + cyan +
          "    Découpage du bâti final à l'emprise du fichier '%s' :" %
          (emprise_file) + endC)
    os.system(
        "ogr2ogr -progress -f 'ESRI Shapefile' %s %s -clipsrc %s" %
        (built_ready, built_simplify, emprise_file)
    )  # Découpage du fichier nettoyé et simplifié à l'emprise érodée de la zone d'étude

    step = "    Fin de la préparation du bâti issu de la classif OCS : "
    timeLine(path_time_log, step)
    print(bold + yellow +
          "Fin de la préparation du bâti issu de la classif OCS." + endC)
    print("\n")

    return
예제 #2
0
def statisticsVectorRaster(image_input,
                           vector_input,
                           vector_output,
                           band_number,
                           enable_stats_all_count,
                           enable_stats_columns_str,
                           enable_stats_columns_real,
                           col_to_delete_list,
                           col_to_add_list,
                           class_label_dico,
                           path_time_log,
                           clean_small_polygons=False,
                           format_vector='ESRI Shapefile',
                           save_results_intermediate=False,
                           overwrite=True):

    # INITIALISATION
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + endC + "image_input : " +
              str(image_input) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC + "vector_input : " +
              str(vector_input) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "vector_output : " + str(vector_output) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC + "band_number : " +
              str(band_number) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "enable_stats_all_count : " + str(enable_stats_all_count) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "enable_stats_columns_str : " + str(enable_stats_columns_str) +
              endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "enable_stats_columns_real : " + str(enable_stats_columns_real) +
              endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "col_to_delete_list : " + str(col_to_delete_list) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "col_to_add_list : " + str(col_to_add_list) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "class_label_dico : " + str(class_label_dico) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "clean_small_polygons : " + str(clean_small_polygons) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "path_time_log : " + str(path_time_log) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "format_vector : " + str(format_vector) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "save_results_intermediate : " + str(save_results_intermediate) +
              endC)
        print(cyan + "statisticsVectorRaster() : " + endC + "overwrite : " +
              str(overwrite) + endC)

    # Constantes
    PREFIX_AREA_COLUMN = "S_"

    # Mise à jour du Log
    starting_event = "statisticsVectorRaster() : Compute statistic crossing starting : "
    timeLine(path_time_log, starting_event)

    # creation du fichier vecteur de sortie
    if vector_output == "":
        vector_output = vector_input  # Précisé uniquement pour l'affichage
    else:
        # Copy vector_output
        copyVectorFile(vector_input, vector_output, format_vector)

    # Vérifications
    image_xmin, image_xmax, image_ymin, image_ymax = getEmpriseImage(
        image_input)
    vector_xmin, vector_xmax, vector_ymin, vector_ymax = getEmpriseFile(
        vector_output, format_vector)
    extension_vector = os.path.splitext(vector_output)[1]

    if round(vector_xmin, 4) < round(image_xmin, 4) or round(
            vector_xmax, 4) > round(image_xmax, 4) or round(
                vector_ymin, 4) < round(image_ymin, 4) or round(
                    vector_ymax, 4) > round(image_ymax, 4):
        print(cyan + "statisticsVectorRaster() : " + bold + red +
              "image_xmin, image_xmax, image_ymin, image_ymax" + endC,
              image_xmin,
              image_xmax,
              image_ymin,
              image_ymax,
              file=sys.stderr)
        print(cyan + "statisticsVectorRaster() : " + bold + red +
              "vector_xmin, vector_xmax, vector_ymin, vector_ymax" + endC,
              vector_xmin,
              vector_xmax,
              vector_ymin,
              vector_ymax,
              file=sys.stderr)
        raise NameError(
            cyan + "statisticsVectorRaster() : " + bold + red +
            "The extend of the vector file (%s) is greater than the image file (%s)"
            % (vector_output, image_input) + endC)

    pixel_size = getPixelSizeImage(image_input)

    # Suppression des très petits polygones qui introduisent des valeurs NaN
    if clean_small_polygons:
        min_size_area = pixel_size * 2
        vector_temp = os.path.splitext(
            vector_output)[0] + "_temp" + extension_vector

        cleanMiniAreaPolygons(vector_output, vector_temp, min_size_area, '',
                              format_vector)
        removeVectorFile(vector_output, format_vector)
        renameVectorFile(vector_temp, vector_output)

    # Récuperation du driver pour le format shape
    driver = ogr.GetDriverByName(format_vector)

    # Ouverture du fichier shape en lecture-écriture
    data_source = driver.Open(vector_output,
                              1)  # 0 means read-only - 1 means writeable.
    if data_source is None:
        print(cyan + "statisticsVectorRaster() : " + bold + red +
              "Impossible d'ouvrir le fichier shape : " + vector_output + endC,
              file=sys.stderr)
        sys.exit(1)  # exit with an error code

    # Récupération du vecteur
    layer = data_source.GetLayer(
        0)  # Recuperation de la couche (une couche contient les polygones)
    layer_definition = layer.GetLayerDefn(
    )  # GetLayerDefn => returns the field names of the user defined (created) fields

    # ETAPE 1/4 : CREATION AUTOMATIQUE DU DICO DE VALEUR SI IL N'EXISTE PAS
    if enable_stats_all_count and class_label_dico == {}:
        image_values_list = identifyPixelValues(image_input)
        # Pour toutes les valeurs
        for id_value in image_values_list:
            class_label_dico[id_value] = str(id_value)
        # Suppression de la valeur no date à 0
        if 0 in class_label_dico:
            del class_label_dico[0]
    if debug >= 2:
        print(class_label_dico)

    # ETAPE 2/4 : CREATION DES COLONNES DANS LE FICHIER SHAPE
    if debug >= 2:
        print(
            cyan + "statisticsVectorRaster() : " + bold + green +
            "ETAPE 1/3 : DEBUT DE LA CREATION DES COLONNES DANS LE FICHIER VECTEUR %s"
            % (vector_output) + endC)

    # En entrée :
    # col_to_add_list = [UniqueID, majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range, all, count, all_S, count_S] - all traduisant le class_label_dico en autant de colonnes
    # Sous_listes de col_to_add_list à identifier pour des facilités de manipulations ultérieures:
    # col_to_add_inter01_list = [majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range]
    # col_to_add_inter02_list = [majority, minority, min, max, mean, median, sum, std, unique, range, all, count, all_S, count_S]
    # Construction des listes intermédiaires
    col_to_add_inter01_list = []

    # Valeurs à injecter dans des colonnes - Format String
    if enable_stats_columns_str:
        stats_columns_str_list = ['majority', 'minority']
        for e in stats_columns_str_list:
            col_to_add_list.append(e)

    # Valeurs à injecter dans des colonnes - Format Nbr
    if enable_stats_columns_real:
        stats_columns_real_list = [
            'min', 'max', 'mean', 'median', 'sum', 'std', 'unique', 'range'
        ]
        for e in stats_columns_real_list:
            col_to_add_list.append(e)

    # Valeurs à injecter dans des colonnes - Format Nbr
    if enable_stats_all_count:
        stats_all_count_list = ['all', 'count']
        for e in stats_all_count_list:
            col_to_add_list.append(e)

    # Valeurs à injecter dans des colonnes - si class_label_dico est non vide
    if class_label_dico != {}:
        stats_all_count_list = ['all', 'count']
        for e in stats_all_count_list:
            if not e in col_to_add_list:
                col_to_add_list.append(e)

    # Ajout colonne par colonne
    if "majority" in col_to_add_list:
        col_to_add_inter01_list.append("majority")
    if "DateMaj" in col_to_add_list:
        col_to_add_inter01_list.append("DateMaj")
    if "SrcMaj" in col_to_add_list:
        col_to_add_inter01_list.append("SrcMaj")
    if "minority" in col_to_add_list:
        col_to_add_inter01_list.append("minority")
    if "min" in col_to_add_list:
        col_to_add_inter01_list.append("min")
    if "max" in col_to_add_list:
        col_to_add_inter01_list.append("max")
    if "mean" in col_to_add_list:
        col_to_add_inter01_list.append("mean")
    if "median" in col_to_add_list:
        col_to_add_inter01_list.append("median")
    if "sum" in col_to_add_list:
        col_to_add_inter01_list.append("sum")
    if "std" in col_to_add_list:
        col_to_add_inter01_list.append("std")
    if "unique" in col_to_add_list:
        col_to_add_inter01_list.append("unique")
    if "range" in col_to_add_list:
        col_to_add_inter01_list.append("range")

    # Copy de col_to_add_inter01_list dans col_to_add_inter02_list
    col_to_add_inter02_list = list(col_to_add_inter01_list)

    if "all" in col_to_add_list:
        col_to_add_inter02_list.append("all")
    if "count" in col_to_add_list:
        col_to_add_inter02_list.append("count")
    if "all_S" in col_to_add_list:
        col_to_add_inter02_list.append("all_S")
    if "count_S" in col_to_add_list:
        col_to_add_inter02_list.append("count_S")
    if "DateMaj" in col_to_add_inter02_list:
        col_to_add_inter02_list.remove("DateMaj")
        col_to_add_inter02_list.insert(0, "majority")
    if "SrcMaj" in col_to_add_inter02_list:
        col_to_add_inter02_list.remove("SrcMaj")
        col_to_add_inter02_list.insert(0, "majority")

    # Valeurs à injecter dans des colonnes - Format Nbr
    if enable_stats_all_count:
        stats_all_count_list = ['all_S', 'count_S']
        for e in stats_all_count_list:
            col_to_add_list.append(e)

    # Creation de la colonne de l'identifiant unique
    if ("UniqueID" in col_to_add_list) or ("uniqueID" in col_to_add_list) or (
            "ID" in col_to_add_list):
        field_defn = ogr.FieldDefn(
            "ID", ogr.OFTInteger
        )  # Création du nom du champ dans l'objet stat_classif_field_defn
        layer.CreateField(field_defn)
        if debug >= 3:
            print(cyan + "statisticsVectorRaster() : " + endC +
                  "Creation de la colonne : ID")

    # Creation des colonnes de col_to_add_inter01_list ([majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range])
    for col in col_to_add_list:
        if layer_definition.GetFieldIndex(
                col
        ) == -1:  # Vérification de l'existence de la colonne col (retour = -1 : elle n'existe pas)
            if col == 'majority' or col == 'DateMaj' or col == 'SrcMaj' or col == 'minority':  # Identification de toutes les colonnes remplies en string
                stat_classif_field_defn = ogr.FieldDefn(
                    col, ogr.OFTString
                )  # Création du champ (string) dans l'objet stat_classif_field_defn
                layer.CreateField(stat_classif_field_defn)
            elif col == 'mean' or col == 'median' or col == 'sum' or col == 'std' or col == 'unique' or col == 'range' or col == 'max' or col == 'min':
                stat_classif_field_defn = ogr.FieldDefn(
                    col, ogr.OFTReal
                )  # Création du champ (real) dans l'objet stat_classif_field_defn
                # Définition de la largeur du champ
                stat_classif_field_defn.SetWidth(20)
                # Définition de la précision du champ valeur flottante
                stat_classif_field_defn.SetPrecision(2)
                layer.CreateField(stat_classif_field_defn)
            if debug >= 3:
                print(cyan + "statisticsVectorRaster() : " + endC +
                      "Creation de la colonne : " + str(col))

    # Creation des colonnes reliées au dictionnaire
    if ('all' in col_to_add_list) or ('count' in col_to_add_list) or (
            'all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
        for col in class_label_dico:

            # Gestion du nom de la colonne correspondant à la classe
            name_col = class_label_dico[col]
            if len(name_col) > 10:
                name_col = name_col[:10]
                print(
                    cyan + "statisticsVectorRaster() : " + bold + yellow +
                    "Nom de la colonne trop long. Il sera tronque a 10 caracteres en cas d'utilisation: "
                    + endC + name_col)

            # Gestion du nom de la colonne correspondant à la surface de la classe
            name_col_area = PREFIX_AREA_COLUMN + name_col
            if len(name_col_area) > 10:
                name_col_area = name_col_area[:10]
                if debug >= 3:
                    print(
                        cyan + "statisticsVectorRaster() : " + bold + yellow +
                        "Nom de la colonne trop long. Il sera tronque a 10 caracteres en cas d'utilisation: "
                        + endC + name_col_area)

            # Ajout des colonnes de % de répartition des éléments du raster
            if ('all' in col_to_add_list) or ('count' in col_to_add_list):
                if layer_definition.GetFieldIndex(
                        name_col
                ) == -1:  # Vérification de l'existence de la colonne name_col (retour = -1 : elle n'existe pas)
                    stat_classif_field_defn = ogr.FieldDefn(
                        name_col, ogr.OFTReal
                    )  # Création du champ (real) dans l'objet stat_classif_field_defn
                    # Définition de la largeur du champ
                    stat_classif_field_defn.SetWidth(20)
                    # Définition de la précision du champ valeur flottante
                    stat_classif_field_defn.SetPrecision(2)
                    if debug >= 3:
                        print(cyan + "statisticsVectorRaster() : " + endC +
                              "Creation de la colonne : " + str(name_col))
                    layer.CreateField(
                        stat_classif_field_defn)  # Ajout du champ

            # Ajout des colonnes de surface des éléments du raster
            if ('all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
                if layer_definition.GetFieldIndex(
                        name_col_area
                ) == -1:  # Vérification de l'existence de la colonne name_col_area (retour = -1 : elle n'existe pas)
                    stat_classif_field_defn = ogr.FieldDefn(
                        name_col_area, ogr.OFTReal
                    )  # Création du nom du champ dans l'objet stat_classif_field_defn
                    # Définition de la largeur du champ
                    stat_classif_field_defn.SetWidth(20)
                    # Définition de la précision du champ valeur flottante
                    stat_classif_field_defn.SetPrecision(2)

                    if debug >= 3:
                        print(cyan + "statisticsVectorRaster() : " + endC +
                              "Creation de la colonne : " + str(name_col_area))
                    layer.CreateField(
                        stat_classif_field_defn)  # Ajout du champ

    if debug >= 2:
        print(
            cyan + "statisticsVectorRaster() : " + bold + green +
            "ETAPE 1/3 : FIN DE LA CREATION DES COLONNES DANS LE FICHIER VECTEUR %s"
            % (vector_output) + endC)

    # ETAPE 3/4 : REMPLISSAGE DES COLONNES DU VECTEUR
    if debug >= 2:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "ETAPE 2/3 : DEBUT DU REMPLISSAGE DES COLONNES DU VECTEUR " +
              endC)

    # Calcul des statistiques col_to_add_inter02_list = [majority, minority, min, max, mean, median, sum, std, unique, range, all, count, all_S, count_S] de croisement images_raster / vecteur
    # Utilisation de la librairie rasterstat
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "Calcul des statistiques " + endC +
              "Stats : %s - Vecteur : %s - Raster : %s" %
              (col_to_add_inter02_list, vector_output, image_input) + endC)
    stats_info_list = raster_stats(vector_output,
                                   image_input,
                                   band_num=band_number,
                                   stats=col_to_add_inter02_list)

    # Decompte du nombre de polygones
    num_features = layer.GetFeatureCount()
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "Remplissage des colonnes polygone par polygone " + endC)
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + endC +
              "Nombre total de polygones : " + str(num_features))

    polygone_count = 0

    for polygone_stats in stats_info_list:  # Pour chaque polygone représenté dans stats_info_list - et il y a autant de polygone que dans le fichier vecteur

        # Extraction de feature
        feature = layer.GetFeature(polygone_stats['__fid__'])

        polygone_count = polygone_count + 1

        if debug >= 3 and polygone_count % 10000 == 0:
            print(cyan + "statisticsVectorRaster() : " + endC +
                  "Avancement : %s polygones traites sur %s" %
                  (polygone_count, num_features))
        if debug >= 5:
            print(
                cyan + "statisticsVectorRaster() : " + endC +
                "Traitement du polygone : ",
                stats_info_list.index(polygone_stats) + 1)

        # Remplissage de l'identifiant unique
        if ("UniqueID" in col_to_add_list) or (
                "uniqueID" in col_to_add_list) or ("ID" in col_to_add_list):
            feature.SetField('ID', int(stats_info_list.index(polygone_stats)))

        # Initialisation à 0 des colonnes contenant le % de répartition de la classe - Verifier ce qu'il se passe si le nom dépasse 10 caracteres
        if ('all' in col_to_add_list) or ('count' in col_to_add_list):
            for element in class_label_dico:
                name_col = class_label_dico[element]
                if len(name_col) > 10:
                    name_col = name_col[:10]
                feature.SetField(name_col, 0)

        # Initialisation à 0 des colonnes contenant la surface correspondant à la classe - Verifier ce qu'il se passe si le nom dépasse 10 caracteres
        if ('all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
            for element in class_label_dico:
                name_col = class_label_dico[element]
                name_col_area = PREFIX_AREA_COLUMN + name_col
                if len(name_col_area) > 10:
                    name_col_area = name_col_area[:10]
                feature.SetField(name_col_area, 0)

        # Remplissage des colonnes contenant le % de répartition et la surface des classes
        if ('all' in col_to_add_list) or ('count' in col_to_add_list) or (
                'all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
            # 'all' est une liste des couples : (Valeur_du_pixel_sur_le_raster, Nbr_pixel_ayant_cette_valeur) pour le polygone observe.
            # Ex : [(0,183),(803,45),(801,4)] : dans le polygone, il y a 183 pixels de valeur 0, 45 pixels de valeur 803 et 4 pixels de valeur 801
            majority_all = polygone_stats['all']

            # Deux valeurs de pixel peuvent faire référence à une même colonne. Par exemple : les pixels à 201, 202, 203 peuvent correspondre à la BD Topo
            # Regroupement des éléments de majority_all allant dans la même colonne au regard de class_label_dico
            count_for_idx_couple = 0  # Comptage du nombre de modifications (suppression de couple) de majority_all pour adapter la valeur de l'index lors de son parcours

            for idx_couple in range(
                    1, len(majority_all)
            ):  # Inutile d'appliquer le traitement au premier élément (idx_couple == 0)

                idx_couple = idx_couple - count_for_idx_couple  # Prise en compte dans le parcours de majority_all des couples supprimés
                couple = majority_all[idx_couple]  # Ex : couple = (803,45)

                if (couple is None) or (
                        couple == ""
                ):  # en cas de bug de rasterstats (erreur geometrique du polygone par exemple)
                    if debug >= 3:
                        print(
                            cyan + "statisticsVectorRaster() : " + bold + red +
                            "Probleme detecte dans la gestion du polygone %s" %
                            (polygone_count) + endC,
                            file=sys.stderr)
                    pass
                else:
                    for idx_verif in range(idx_couple):
                        # Vérification au regard des éléments présents en amont dans majority_all
                        # Cas où le nom correspondant au label a déjà été rencontré dans majority_all
                        # Vérification que les pixels de l'image sont réferncés dans le dico
                        if couple[0] in class_label_dico:

                            if class_label_dico[couple[0]] == class_label_dico[
                                    majority_all[idx_verif][0]]:
                                majority_all[idx_verif] = (
                                    majority_all[idx_verif][0],
                                    majority_all[idx_verif][1] + couple[1]
                                )  # Ajout du nombre de pixels correspondant dans le couple précédent
                                majority_all.remove(
                                    couple
                                )  # Supression du couple présentant le "doublon"
                                count_for_idx_couple = count_for_idx_couple + 1  # Mise à jour du décompte de modifications
                                break
                        else:
                            raise NameError(
                                cyan + "statisticsVectorRaster() : " + bold +
                                red +
                                "The image file (%s) contain pixel value '%d' not identified into class_label_dico"
                                % (image_input, couple[0]) + endC)

            # Intégration des valeurs de majority all dans les colonnes
            for couple_value_count in majority_all:  # Parcours de majority_all. Ex : couple_value_count = (803,45)
                if (couple_value_count is None) or (
                        couple_value_count == ""
                ):  # en cas de bug de rasterstats (erreur geometrique du polygone par exemple)
                    if debug >= 3:
                        print(
                            cyan + "statisticsVectorRaster() : " + bold + red +
                            "Probleme detecte dans la gestion du polygone %s" %
                            (polygone_count) + endC,
                            file=sys.stderr)
                    pass
                else:
                    nb_pixel_total = polygone_stats[
                        'count']  # Nbr de pixels du polygone
                    pixel_value = couple_value_count[0]  # Valeur du pixel
                    value_count = couple_value_count[
                        1]  # Nbr de pixels ayant cette valeur
                    name_col = class_label_dico[
                        pixel_value]  # Transformation de la valeur du pixel en "signification" au regard du dictionnaire. Ex : BD Topo ou 2011
                    name_col_area = PREFIX_AREA_COLUMN + name_col  # Identification du nom de la colonne en surfaces

                    if len(name_col) > 10:
                        name_col = name_col[:10]
                    if len(name_col_area) > 10:
                        name_col_area = name_col_area[:10]

                    value_area = pixel_size * value_count  # Calcul de la surface du polygone correspondant à la valeur du pixel
                    if nb_pixel_total != None and nb_pixel_total != 0:
                        percentage = (
                            float(value_count) / float(nb_pixel_total)
                        ) * 100  # Conversion de la surface en pourcentages, arondi au pourcent
                    else:
                        if debug >= 3:
                            print(
                                cyan + "statisticsVectorRaster() : " + bold +
                                red +
                                "Probleme dans l'identification du nombre de pixels du polygone %s : le pourcentage de %s est mis à 0"
                                % (polygone_count, name_col) + endC,
                                file=sys.stderr)
                        percentage = 0.0

                    if ('all' in col_to_add_list) or ('count'
                                                      in col_to_add_list):
                        feature.SetField(
                            name_col, percentage
                        )  # Injection du pourcentage dans la colonne correpondante
                    if ('all_S' in col_to_add_list) or ('count_S'
                                                        in col_to_add_list):
                        feature.SetField(
                            name_col_area, value_area
                        )  # Injection de la surface dans la colonne correpondante
        else:
            pass

        # Remplissage des colonnes statistiques demandées ( col_to_add_inter01_list = [majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range] )
        for stats in col_to_add_inter01_list:

            if stats == 'DateMaj' or stats == 'SrcMaj':  # Cas particulier de 'DateMaj' et 'SrcMaj' : le nom de la colonne est DateMaj ou SrcMaj, mais la statistique utilisée est identifiée par majority
                name_col = stats  # Nom de la colonne. Ex : 'DateMaj'
                value_statis = polygone_stats[
                    'majority']  # Valeur majoritaire. Ex : '203'
                if value_statis == None:
                    value_statis_class = 'nan'
                else:
                    value_statis_class = class_label_dico[
                        value_statis]  # Transformation de la valeur au regard du dictionnaire. Ex : '2011'
                feature.SetField(name_col,
                                 value_statis_class)  # Ajout dans la colonne

            elif (stats is None) or (stats == "") or (
                    polygone_stats[stats] is
                    None) or (polygone_stats[stats]) == "" or (
                        polygone_stats[stats]) == 'nan':
                # En cas de bug de rasterstats (erreur geometrique du polygone par exemple)
                pass

            else:
                name_col = stats  # Nom de la colonne. Ex : 'majority', 'max'
                value_statis = polygone_stats[
                    stats]  # Valeur à associer à la colonne, par exemple '2011'

                if (
                        name_col == 'majority' or name_col == 'minority'
                ) and class_label_dico != []:  # Cas où la colonne fait référence à une valeur du dictionnaire
                    value_statis_class = class_label_dico[value_statis]
                else:
                    value_statis_class = value_statis

                feature.SetField(name_col, value_statis_class)

        layer.SetFeature(feature)
        feature.Destroy()

    if debug >= 2:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "ETAPE 2/3 : FIN DU REMPLISSAGE DES COLONNES DU VECTEUR %s" %
              (vector_output) + endC)

    # ETAPE 4/4 : SUPRESSION DES COLONNES NON SOUHAITEES
    if col_to_delete_list != []:

        if debug >= 2:
            print(cyan + "statisticsVectorRaster() : " + bold + green +
                  "ETAPE 3/3 : DEBUT DES SUPPRESSIONS DES COLONNES %s" %
                  (col_to_delete_list) + endC)

        for col_to_delete in col_to_delete_list:

            if layer_definition.GetFieldIndex(
                    col_to_delete
            ) != -1:  # Vérification de l'existence de la colonne col (retour = -1 : elle n'existe pas)

                layer.DeleteField(layer_definition.GetFieldIndex(
                    col_to_delete))  # Suppression de la colonne

                if debug >= 3:
                    print(cyan + "statisticsVectorRaster() : " + endC +
                          "Suppression de %s" % (col_to_delete) + endC)

        if debug >= 2:
            print(cyan + "statisticsVectorRaster() : " + bold + green +
                  "ETAPE 3/3 : FIN DE LA SUPPRESSION DES COLONNES" + endC)

    else:
        print(cyan + "statisticsVectorRaster() : " + bold + yellow +
              "ETAPE 3/3 : AUCUNE SUPPRESSION DE COLONNE DEMANDEE" + endC)

    # Fermeture du fichier shape
    layer.SyncToDisk()
    layer = None
    data_source.Destroy()

    # Mise à jour du Log
    ending_event = "statisticsVectorRaster() : Compute statistic crossing ending : "
    timeLine(path_time_log, ending_event)

    return
def vectorsPreparation(emprise_file, classif_input, grid_input, built_input_list, roads_input_list, grid_output, grid_output_cleaned, built_output, roads_output, col_code_ua, col_item_ua, epsg, path_time_log, format_vector='ESRI Shapefile', extension_vector=".shp", save_results_intermediate=False, overwrite=True):

    print(bold + yellow + "Début de la préparation des fichiers vecteurs." + endC + "\n")
    timeLine(path_time_log, "Début de la préparation des fichiers vecteurs : ")

    if debug >= 3 :
        print(bold + green + "vectorsPreparation() : Variables dans la fonction" + endC)
        print(cyan + "vectorsPreparation() : " + endC + "emprise_file : " + str(emprise_file) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "classif_input : " + str(classif_input) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "grid_input : " + str(grid_input) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "built_input_list : " + str(built_input_list) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "roads_input_list : " + str(roads_input_list) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "grid_output : " + str(grid_output) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "grid_output_cleaned : " + str(grid_output_cleaned) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "built_output : " + str(built_output) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "roads_output : " + str(roads_output) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "col_code_ua : " + str(col_code_ua) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "col_item_ua : " + str(col_item_ua) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "epsg : " + str(epsg))
        print(cyan + "vectorsPreparation() : " + endC + "path_time_log : " + str(path_time_log) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "format_vector : " + str(format_vector) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "extension_vector : " + str(extension_vector) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "save_results_intermediate : " + str(save_results_intermediate) + endC)
        print(cyan + "vectorsPreparation() : " + endC + "overwrite : " + str(overwrite) + endC)

    FOLDER_TEMP = 'TEMP'
    SUFFIX_VECTOR_REPROJECT = '_reproject'
    SUFFIX_VECTOR_INTERSECT = '_intersect'
    SUFFIX_VECTOR_MERGE = '_merge'
    SUFFIX_VECTOR_SELECT = '_select'

    if not os.path.exists(grid_output) or not os.path.exists(built_output) or not os.path.exists(roads_output) or overwrite:

        ############################################
        ### Préparation générale des traitements ###
        ############################################

        path_grid_temp = os.path.dirname(grid_output) + os.sep + FOLDER_TEMP
        path_built_temp = os.path.dirname(built_output) + os.sep + FOLDER_TEMP
        path_roads_temp = os.path.dirname(roads_output) + os.sep + FOLDER_TEMP

        if os.path.exists(path_grid_temp):
            shutil.rmtree(path_grid_temp)
        if os.path.exists(path_built_temp):
            shutil.rmtree(path_built_temp)
        if os.path.exists(path_roads_temp):
            shutil.rmtree(path_roads_temp)

        if not os.path.exists(path_grid_temp):
            os.mkdir(path_grid_temp)
        if not os.path.exists(path_built_temp):
            os.mkdir(path_built_temp)
        if not os.path.exists(path_roads_temp):
            os.mkdir(path_roads_temp)

        basename_grid = os.path.splitext(os.path.basename(grid_output))[0]
        basename_built = os.path.splitext(os.path.basename(built_output))[0]
        basename_roads = os.path.splitext(os.path.basename(roads_output))[0]

        # Variables pour ajout colonne ID
        field_name = 'ID' # Attention ! Nom fixé en dur dans les scripts indicateurs, pas dans le script final
        field_type = ogr.OFTInteger

        ##############################################
        ### Traitements sur le vecteur Urban Atlas ###
        ##############################################

        if not os.path.exists(grid_output) or overwrite :

            if os.path.exists(grid_output):
                removeVectorFile(grid_output)
            if os.path.exists(grid_output_cleaned):
                removeVectorFile(grid_output_cleaned)

            # MAJ projection
            grid_reproject = path_grid_temp + os.sep + basename_grid + SUFFIX_VECTOR_REPROJECT + extension_vector
            updateProjection(grid_input, grid_reproject, projection=epsg)

            # Découpage du fichier Urban Atlas d'entrée à l'emprise de la zone d'étude
            grid_output_temp = os.path.splitext(grid_output)[0] + "_temp" + extension_vector
            cutVector(emprise_file, grid_reproject, grid_output_temp, overwrite, format_vector)

            # Suppression des très petits polygones qui introduisent des valeurs NaN
            pixel_size = getPixelSizeImage(classif_input)
            min_size_area = pixel_size * 2
            cleanMiniAreaPolygons(grid_output_temp, grid_output, min_size_area, '', format_vector)
            if not save_results_intermediate:
                if os.path.exists(grid_output_temp):
                    removeVectorFile(grid_output_temp, format_vector)

            # Ajout d'un champ ID
            addNewFieldVector(grid_output, field_name, field_type, 0, None, None, format_vector)
            updateIndexVector(grid_output, field_name, format_vector)

            # Suppression des polygones eau et routes (uniquement pour le calcul des indicateurs)
            column = "'%s, %s, %s'" % (field_name, col_code_ua, col_item_ua)
            expression = "%s NOT IN ('12210', '12220', '12230', '50000')" % (col_code_ua)
            ret = filterSelectDataVector(grid_output, grid_output_cleaned, column, expression, format_vector)
            if not ret :
                raise NameError (cyan + "vectorsPreparation : " + bold + red  + "Attention problème lors du filtrage des BD vecteurs l'expression SQL %s est incorrecte" %(expression) + endC)

        #########################################
        ### Traitements sur les vecteurs bâti ###
        #########################################
        if not os.path.exists(built_output) or overwrite :

            if os.path.exists(built_output):
                removeVectorFile(built_output)

            # MAJ projection
            built_reproject_list=[]
            for built_input in built_input_list:
                built_reproject = path_built_temp + os.sep + os.path.splitext(os.path.basename(built_input))[0] + SUFFIX_VECTOR_REPROJECT + extension_vector
                updateProjection(built_input, built_reproject, projection=epsg)
                built_reproject_list.append(built_reproject)

            # Sélection des entités bâti dans l'emprise de l'étude
            built_intersect_list = []
            for built_reproject in built_reproject_list:
                built_intersect = path_built_temp + os.sep + os.path.splitext(os.path.basename(built_reproject))[0] + SUFFIX_VECTOR_INTERSECT + extension_vector
                intersectVector(emprise_file, built_reproject, built_intersect, format_vector)
                built_intersect_list.append(built_intersect)

            # Fusion des couches bâti de la BD TOPO
            built_merge = path_built_temp + os.sep + basename_built + SUFFIX_VECTOR_MERGE + extension_vector
            built_select = path_built_temp + os.sep + basename_built + SUFFIX_VECTOR_SELECT + extension_vector
            fusionVectors(built_intersect_list, built_merge)

            # Suppression des polygones où la hauteur du bâtiment est à 0
            column = "HAUTEUR"
            expression = "HAUTEUR > 0"
            ret = filterSelectDataVector(built_merge, built_select, column, expression, format_vector)
            if not ret :
                raise NameError (cyan + "vectorsPreparation : " + bold + red  + "Attention problème lors du filtrage des BD vecteurs l'expression SQL %s est incorrecte" %(expression) + endC)

            # Découpage des bati d'entrée à l'emprise de la zone d'étude
            cutVector(emprise_file, built_select, built_output, overwrite, format_vector)

            # Ajout d'un champ ID
            addNewFieldVector(built_output, field_name, field_type, 0, None, None, format_vector)
            updateIndexVector(built_output, field_name, format_vector)

        ###########################################
        ### Traitements sur les vecteurs routes ###
        ###########################################

        if not os.path.exists(roads_output) or overwrite :

            if os.path.exists(roads_output):
                removeVectorFile(roads_output)

            # MAJ projection
            roads_reproject_list=[]
            for roads_input in roads_input_list:
                roads_reproject = path_roads_temp + os.sep + os.path.splitext(os.path.basename(roads_input))[0] + SUFFIX_VECTOR_REPROJECT + extension_vector
                updateProjection(roads_input, roads_reproject, projection=epsg)
                roads_reproject_list.append(roads_reproject)

            # Sélection des entités routes dans l'emprise de l'étude
            roads_intersect_list = []
            for roads_reproject in roads_reproject_list:
                roads_intersect = path_roads_temp + os.sep + os.path.splitext(os.path.basename(roads_reproject))[0] + SUFFIX_VECTOR_INTERSECT + extension_vector
                intersectVector(emprise_file, roads_reproject, roads_intersect, format_vector)
                roads_intersect_list.append(roads_intersect)

            # Fusion des couches route de la BD TOPO
            roads_merge = path_roads_temp + os.sep + basename_roads + SUFFIX_VECTOR_MERGE + extension_vector
            roads_select = path_roads_temp + os.sep + basename_roads + SUFFIX_VECTOR_SELECT + extension_vector
            fusionVectors(roads_intersect_list, roads_merge)

            # Sélection des entités suivant la nature de la route dans la couche routes de la BD TOPO
            column = "NATURE"
            expression = "NATURE IN ('Autoroute', 'Bretelle', 'Quasi-autoroute', 'Route  1 chausse', 'Route  2 chausses', 'Route a 1 chaussee', 'Route a 2 chaussees', 'Route à 1 chaussée', 'Route à 2 chaussées')"
            ret = filterSelectDataVector (roads_merge, roads_select, column, expression, format_vector)
            if not ret :
                raise NameError (cyan + "vectorsPreparation : " + bold + red  + "Attention problème lors du filtrage des BD vecteurs l'expression SQL %s est incorrecte" %(expression) + endC)

            # Découpage des routes d'entrée à l'emprise de la zone d'étude
            cutVectorAll(emprise_file, roads_select, roads_output, overwrite, format_vector)

            # Ajout d'un champ ID
            addNewFieldVector(roads_output, field_name, field_type, 0, None, None, format_vector)
            updateIndexVector(roads_output, field_name, format_vector)

        ##########################################
        ### Nettoyage des fichiers temporaires ###
        ##########################################

        if not save_results_intermediate:
            if os.path.exists(path_grid_temp):
                shutil.rmtree(path_grid_temp)
            if os.path.exists(path_built_temp):
                shutil.rmtree(path_built_temp)
            if os.path.exists(path_roads_temp):
                shutil.rmtree(path_roads_temp)

    else:
        print(bold + magenta + "La préparation des fichiers vecteurs a déjà eu lieu.\n" + endC)

    print(bold + yellow + "Fin de la préparation des fichiers vecteurs.\n" + endC)
    timeLine(path_time_log, "Fin de la préparation des fichiers vecteurs : ")

    return
def sobelToOuvrages(input_im_seuils_dico, output_dir, input_cut_vector, no_data_value, path_time_log, format_raster='GTiff', format_vector="ESRI Shapefile", extension_raster=".tif", extension_vector=".shp", save_results_intermediate=True, overwrite=True):

    # Constantes
    REPERTORY_TEMP = "temp_sobel"
    CODAGE_8B = "uint8"
    ID = "id"

    # Mise à jour du Log
    starting_event = "sobelToOuvrages() : Select Sobel to ouvrages starting : "
    timeLine(path_time_log,starting_event)

    # Création du répertoire de sortie s'il n'existe pas déjà
    if not os.path.exists(output_dir + os.sep + REPERTORY_TEMP):
        os.makedirs(output_dir + os.sep + REPERTORY_TEMP)

    # Affichage des paramètres
    if debug >= 3:
        print(bold + green + "Variables dans SobelToOuvrages - Variables générales" + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "input_im_seuils_dico : " + str(input_im_seuils_dico) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "output_dir : " + str(output_dir) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "input_cut_vector : " + str(input_cut_vector) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "path_time_log : " + str(path_time_log) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "format_raster : " + str(format_raster) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "format_vector : " + str(format_vector) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "extension_raster : " + str(extension_raster) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "extension_vector : " + str(extension_vector) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "save_results_intermediate : " + str(save_results_intermediate) + endC)
        print(cyan + "sobelToOuvrages() : " + endC + "overwrite : " + str(overwrite) + endC)

    sobel_ouvrages_shp_list = []

    for elt in input_im_seuils_dico.split():
        raw_image = elt.split(":")[0]
        sobel_image = elt.split(":")[1].split(",")[0]

        for i in range(1,len(elt.split(":")[1].split(","))):
            seuil = elt.split(":")[1].split(",")[i]

            # Initialisation des noms des fichiers en sortie
            image_name = os.path.splitext(os.path.basename(raw_image))[0]
            sobel_binary_mask = output_dir + os.sep + REPERTORY_TEMP + os.sep + "bin_mask_sobel_" + image_name + "_" + str(seuil) + extension_raster
            sobel_binary_mask_vector_name = "bin_mask_vect_sobel_" + image_name + "_" + str(seuil)
            sobel_binary_mask_vector = output_dir + os.sep + REPERTORY_TEMP + os.sep + sobel_binary_mask_vector_name + extension_vector
            sobel_binary_mask_vector_cleaned = output_dir + os.sep + REPERTORY_TEMP + os.sep + "bin_mask_vect_sobel_cleaned_" + image_name + "_" + str(seuil) + extension_vector
            sobel_decoup = output_dir + os.sep + "sobel_decoup_" + image_name + "_" + str(seuil) + extension_vector

            binary_mask_zeros_name = "b_mask_zeros_vect_" + image_name
            binary_mask_zeros_raster = output_dir + os.sep + REPERTORY_TEMP + os.sep + "b_mask_zeros_" + image_name + extension_raster
            binary_mask_zeros_vector = output_dir + os.sep + REPERTORY_TEMP + os.sep + binary_mask_zeros_name + extension_vector
            binary_mask_zeros_vector_simpl = output_dir + os.sep + REPERTORY_TEMP + os.sep + "b_mask_zeros_vect_simpl_" + image_name + extension_vector
            true_values_buffneg = output_dir + os.sep + REPERTORY_TEMP + os.sep + "true_values_buffneg_" + image_name + extension_vector
            ouvrages_decoup_final = output_dir + os.sep + "ouvrages_sobel_" + image_name + "_" + str(seuil) + extension_vector

            # Création du masque binaire
            createBinaryMask(sobel_image, sobel_binary_mask, float(seuil), True)

            # Découpe du masque binaire par le shapefile de découpe en entrée
            cutImageByVector(input_cut_vector, sobel_binary_mask, sobel_decoup, None, None, no_data_value, 0, format_raster, format_vector)

            # Vectorisation du masque binaire Sobel découpé
            polygonizeRaster(sobel_decoup, sobel_binary_mask_vector, sobel_binary_mask_vector_name)

            # Création masque binaire pour séparer les no data des vraies valeurs
            nodata_value = getNodataValueImage(raw_image)
            if no_data_value == None :
                no_data_value = 0
            createBinaryMaskMultiBand(raw_image, binary_mask_zeros_raster, no_data_value, CODAGE_8B)

            # Vectorisation du masque binaire true data/false data -> polygone avec uniquement les vraies valeurs
            if os.path.exists(binary_mask_zeros_vector):
                removeVectorFile(binary_mask_zeros_vector, format_vector)

            # Polygonisation
            polygonizeRaster(binary_mask_zeros_raster, binary_mask_zeros_vector, binary_mask_zeros_name, ID, format_vector)

            # Simplification du masque obtenu
            simplifyVector(binary_mask_zeros_vector, binary_mask_zeros_vector_simpl, 2, format_vector)

            # Buffer négatif sur ce polygone
            bufferVector(binary_mask_zeros_vector_simpl, true_values_buffneg, -2, "", 1.0, 10, format_vector)
            cleanMiniAreaPolygons(sobel_binary_mask_vector, sobel_binary_mask_vector_cleaned, 15, ID, format_vector)

            # Découpe par le buffer négatif autour des true data
            cutVectorAll(true_values_buffneg, sobel_binary_mask_vector_cleaned, ouvrages_decoup_final, overwrite, format_vector)
            sobel_ouvrages_shp_list.append(ouvrages_decoup_final)

        return sobel_ouvrages_shp_list