コード例 #1
0
def arcg_mean_time_WByPop2(netDt,
                           rdv,
                           infraestruturas,
                           unidades,
                           conjuntos,
                           popf,
                           w,
                           output,
                           oneway=None):
    """
    Tempo medio ponderado pela populacao residente a infra-estrutura mais
    proxima (min)
    
    * netDt = Path to Network Dataset
    * infraestruturas = Points of destiny
    * unidades = BGRI; Freg; Concelhos
    * conjuntos = Freg; Concelhos; NUT - field
    * popf = Field with the population of the statistic unity
    * w = Workspace
    * output = Path to store the final output
    * rdv = Name of feature class with the streets network
    """

    import arcpy
    import os
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.mng.feat import feat_to_pnt
    from glass.cpu.arcg.mng.fld import add_field, calc_fld
    from glass.cpu.arcg.mng.joins import join_table
    from glass.mng.genze import dissolve
    from glass.mng.gen import copy_feat
    from glass.mob.arctbx.closest import closest_facility
    from glass.dct import tbl_to_obj

    def get_freg_denominator(shp, groups, population, fld_time="Total_Minu"):
        cursor = arcpy.SearchCursor(shp)

        groups_sum = {}
        for lnh in cursor:
            group = lnh.getValue(groups)
            nrInd = float(lnh.getValue(population))
            time = float(lnh.getValue(fld_time))

            if group not in groups_sum.keys():
                groups_sum[group] = time * nrInd

            else:
                groups_sum[group] += time * nrInd

        del cursor, lnh

        return groups_sum

    if not os.path.exists(w):
        from glass.oss.ops import create_folder
        w = create_folder(w, overwrite=False)

    arcpy.env.overwriteOutput = True
    arcpy.env.workspace = w

    # Start Procedure #
    # Create copy of statitic unities to preserve the original data
    copy_unities = copy_feat(unidades,
                             os.path.join(w, os.path.basename(unidades)),
                             gisApi='arcpy')

    # Generate centroids of the statistic unities - unidades
    lyr_unidades = feat_lyr(copy_unities)
    pnt_unidades = feat_to_pnt(lyr_unidades, 'pnt_unidades.shp')

    # Network Processing - Distance between CENTROID and Destiny points
    closest_facility(netDt,
                     rdv,
                     infraestruturas,
                     pnt_unidades,
                     os.path.join(w, "cls_table.dbf"),
                     oneway_restriction=oneway)
    add_field("cls_table.dbf", 'j', "SHORT", "6")
    calc_fld("cls_table.dbf", 'j', "[IncidentID]-1")
    join_table(lyr_unidades, "FID", "cls_table.dbf", "j", "Total_Minu")
    del lyr_unidades

    # Calculo dos somatorios por freguesia (conjunto)
    # To GeoDf
    unidadesDf = tbl_to_obj(copy_unities)
    """
    groups = get_freg_denominator(lyr_unidades, conjuntos, popf)
    add_field(lyr_unidades, "tm", "FLOAT", "10", "3")
    
    cs = arcpy.UpdateCursor(lyr_unidades)
    linha = cs.next()
    while linha:
        group = linha.getValue(conjuntos)
        t = float(linha.getValue("Total_Minu"))
        p = int(linha.getValue(popf))
        total = groups[group]
        indi = ((t * p) / total) * t
        linha.setValue("tm", indi)
        cs.updateRow(linha)
        linha = cs.next()
    
    return dissolve(lyr_unidades, output, conjuntos, "tm SUM")"""
    return unidadesDf
コード例 #2
0
ファイル: fmfile.py プロジェクト: jasp382/glass
def files_to_map(main_mxd,
                 lyr_to_change,
                 dataFrame,
                 lyr_folder,
                 layout_elm_table,
                 outDir,
                 exportMap=None,
                 lyr_extent_name=None,
                 maps_format='.jpg',
                 extentTolerance=200):
    """
    Create a map for every file in a folder
    
    Only works for Feature Classes
    
    * main_mxd = path to a mxd template (all maps produced will be like
    this template);
    
    * lyr_to_change is a table as:
       | lyr_1_name | ... | lyr_n_name 
     0 | some_name  | ... | some_name
     1 | some_name  | ... | some_name
     
    * lyr_folder = {
        lyr_1_name : '/path/to/files/to/be/used/as/lyr_1_name',
        lyr_2_name : '/path/to/files/to/be/used/as/lyr_2_name'
    
    * layout_elm_table = file with the indication of what text should appear
    in each text element of the layout when some column is used as value
    field;
    
                   | id_element_1 | ... | id_element_n
    file_lyr_name1 |  some_text   | ... |  some_text
    file_lyr_name2 |  some_text   | ... |  some_text
    """

    import os
    from glass.pys.oss import lst_ff
    from glass.dct import tbl_to_obj
    from glass.maps.arctbx.lyrs import lst_layers
    from glass.maps.arctbx.dframe import lst_dataframe
    from glass.maps.arctbx.graph import get_elem_by_name
    from glass.maps.arctbx.wmap import mxd_saveas
    from glass.maps.arctbx.wmap import write_map

    # Prepare global variables
    mxdDir = outDir
    mapsDir = exportMap if os.path.isdir(exportMap) else outDir

    # List files to be used in each map by layer name
    filesByLyr = tbl_to_obj(lyr_to_change,
                            useFirstColAsIndex=True,
                            output='dict')

    # List graphic elements to be changed
    files_and_element = tbl_to_obj(layout_elm_table,
                                   useFirstColAsIndex=True,
                                   output='dict')

    # Produce maps
    for __map in filesByLyr:
        print "Producing {} Map".format(str(__map))

        # Open mxd and change it
        mxd = arcpy.mapping.MapDocument(main_mxd)

        # Get Text elements in the main mxd to be changed
        elem_names = files_and_element[files_and_element.keys()[0]].keys()
        text_elem = get_elem_by_name(mxd, elem_names)

        if not text_elem:
            print 'No Graphic/Text element was finded'

        # Change every text elements
        for elem_name in text_elem:
            text_elem[elem_name].text = files_and_element[__map][elem_name]

        # Change layer datasource
        lyrs = lst_layers(mxd, lyrNames=filesByLyr[__map].keys())

        df = lst_dataframe(mxd, dfNames=dataFrame)

        for lyr in lyrs:
            lyr.replaceDataSource(lyr_folder[str(lyr.name)], "NONE",
                                  filesByLyr[__map][str(lyr.name)], True)

        # Set new map extension
        if not lyr_extent_name:
            lyr_extent_name = str(lyrs[0].name)

        for lyr in lyrs:
            if str(lyr.name) != lyr_extent_name:
                continue
            else:
                ext = lyr.getExtent()

                newExtent = df.extent
                newExtent.XMin = ext.XMin - extentTolerance
                newExtent.YMin = ext.YMin - extentTolerance
                newExtent.XMax = ext.XMax + extentTolerance
                newExtent.YMax = ext.YMax + extentTolerance

                df.extent = newExtent

        outmap = write_map(
            mxd,
            os.path.join(mapsDir, 'map_{}{}'.format(str(__map), maps_format)))

        # Create a new mxd
        mxd_saveas(mxd, os.path.join(mxdDir, 'map_{}.mxd'.format(str(__map))))

        # Close mxd
        del mxd

        print "Map {} is done!".format(str(__map))
コード例 #3
0
def population_within_point_buffer(netDataset,
                                   rdvName,
                                   pointShp,
                                   populationShp,
                                   popField,
                                   bufferDist,
                                   epsg,
                                   output,
                                   workspace=None,
                                   bufferIsTimeMinutes=None,
                                   useOneway=None):
    """
    Assign to points the population within a certain distance (metric or time)
    
    * Creates a Service Area Polygon for each point in pointShp;
    * Intersect the Service Area Polygons with the populationShp;
    * Count the number of persons within each Service Area Polygon
    (this number will be weighted by the area % of the statistic unit
    intersected with the Service Area Polygon).
    """

    import arcpy
    import os
    from geopandas import GeoDataFrame
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.cpu.arcg.anls.ovlay import intersect
    from glass.mng.gen import copy_feat
    from glass.cpu.arcg.mng.fld import add_geom_attr
    from glass.cpu.arcg.mng.fld import add_field
    from glass.cpu.arcg.mng.fld import calc_fld
    from glass.mng.genze import dissolve
    from glass.mob.arctbx.svarea import service_area_use_meters
    from glass.mob.arctbx.svarea import service_area_polygon
    from glass.fm import tbl_to_obj
    from glass.toshp import df_to_shp

    workspace = os.path.dirname(pointShp) if not workspace else workspace

    if not os.path.exists(workspace):
        from glass.oss.ops import create_folder
        workspace = create_folder(workspace, overwrite=False)

    # Copy population layer
    populationShp = copy_feat(
        populationShp,
        os.path.join(workspace,
                     'cop_{}'.format(os.path.basename(populationShp))),
        gisApi='arcpy')

    # Create layer
    pntLyr = feat_lyr(pointShp)
    popLyr = feat_lyr(populationShp)

    # Create Service Area
    if not bufferIsTimeMinutes:
        servArea = service_area_use_meters(
            netDataset,
            rdvName,
            bufferDist,
            pointShp,
            os.path.join(workspace,
                         'servare_{}'.format(os.path.basename(pointShp))),
            OVERLAP=False,
            ONEWAY=useOneway)

    else:
        servArea = service_area_polygon(
            netDataset,
            rdvName,
            bufferDist,
            pointShp,
            os.path.join(workspace,
                         "servare_{}".format(os.path.basename(pointShp))),
            ONEWAY_RESTRICTION=useOneway,
            OVERLAP=None)

    servAreaLyr = feat_lyr(servArea)

    # Add Column with Polygons area to Feature Class population
    add_geom_attr(popLyr, "total", geom_attr="AREA")

    # Intersect buffer and Population Feature Class
    intSrc = intersect([servAreaLyr, popLyr],
                       os.path.join(workspace, "int_servarea_pop.shp"))

    intLyr = feat_lyr(intSrc)

    # Get area of intersected statistical unities with population
    add_geom_attr(intLyr, "partarea", geom_attr="AREA")

    # Get population weighted by area intersected
    calc_fld(intLyr, "population",
             "((([partarea] * 100) / [total]) * [{}]) / 100".format(popField),
             {
                 "TYPE": "DOUBLE",
                 "LENGTH": "10",
                 "PRECISION": "3"
             })

    # Dissolve service area by Facility ID
    diss = dissolve(intLyr,
                    os.path.join(workspace, 'diss_servpop.shp'),
                    "FacilityID",
                    statistics="population SUM")

    # Get original Point FID from FacilityID
    calc_fld(diss, "pnt_fid", "[FacilityID] - 1", {
        "TYPE": "INTEGER",
        "LENGTH": "5",
        "PRECISION": None
    })

    dfPnt = tbl_to_obj(pointShp)
    dfDiss = tbl_to_obj(diss)

    dfDiss.rename(columns={"SUM_popula": "n_pessoas"}, inplace=True)

    resultDf = dfPnt.merge(dfDiss,
                           how='inner',
                           left_index=True,
                           right_on="pnt_fid")

    resultDf.drop('geometry_y', axis=1, inplace=True)

    resultDf = GeoDataFrame(resultDf,
                            crs={'init': 'epsg:{}'.format(epsg)},
                            geometry='geometry_x')

    df_to_shp(resultDf, output)

    return output
コード例 #4
0
ファイル: fmfile.py プロジェクト: jasp382/glass
def maps_by_extent(extentSource,
                   baseMxd,
                   MAIN_DATAFRAME,
                   EXTENT_LYR_NAME,
                   CONTEXT_DATAFRAME,
                   MAP_GRAPH_ELEM,
                   outputMxd,
                   outputMaps=None,
                   mapsFormat='.pdf'):
    """
    Export a new map for each "Extent".
    
    Extent is a bounding box file
    
    * extentSource - path to the folder with the bounding boxes files.
    A new map will be generated for every file in this folder.
    
    * baseMxd - path to an template MXD file. The new maps will have the same
    structure.
    
    * MAIN_DATAFRAME - name of the dataframe in the baseMxd that will have
    it extent changed from map to map.
    
    * EXTENT_LYR_NAME - name of the layer that will have it extent changed
    from map to map.
    
    * CONTEXT_DATAFRAME - dict with metainfo about other dataframe with
    data about the geographic context.
    E.g.
    CONTEXT_DATAFRAME = {
        "zoom_pt" : {
            "PATHDATA" : r'D:\TRENMO_JASP\SITIOS_FATIMA\acf_versao_final\lmt_conc',
            "LAYERS" : {
                # LAYER NAME : FIELD IN EXTENT_LAYER WITH THE NAME OF THE FILE
                # THAT SOULD BE USED IN THE LAYER WITH KEY NAME
                "ref_concelho" : "concelho"
            }
        },
        "zoom_concelho" : {
            "PATHDATA" : r'D:\TRENMO_JASP\SITIOS_FATIMA\acf_versao_final\lmt_conc',
            "LAYERS" : {
                "ref_concelho" : "concelho",
                "ref_grid" : "EXTENTFILE"
            },
            "ISZOOM" : "ref_concelho",
            "EXTENT_TOLERANCE" : 1000
        }
    }
    
    MAP_GRAPH_ELEM - file with the indication of what text should appear
    in each text element of the layout when some file is used as data source
    of the EXTENT_LYR;
    
                   | id_element_1 | ... | id_element_n
    file_lyr_name1 |  some_text   | ... |  some_text
    file_lyr_name2 |  some_text   | ... |  some_text
    """

    import os
    from glass.dct import tbl_to_obj
    from glass.pys.oss import get_filename
    from glass.cpu.arcg.mng.fld import list_fields
    from glass.maps.arctbx.lyrs import lst_layers
    from glass.maps.arctbx.lyrs import get_layers_by_dataframe
    from glass.maps.arctbx.dframe import lst_dataframe
    from glass.maps.arctbx.graph import get_elem_by_name
    from glass.maps.arctbx.wmap import write_map
    from glass.maps.arctbx.wmap import mxd_saveas

    outputMaps = outputMxd if not os.path.isdir(outputMaps) else outputMaps
    mapsFormat = mapsFormat if mapsFormat[0] == '.' else '.' + mapsFormat

    # List extent files
    arcpy.env.workspace = extentSource
    maps_ext = arcpy.ListFeatureClasses()

    attrs_data = {}
    for extFile in maps_ext:
        cursor = arcpy.SearchCursor(os.path.join(extentSource, extFile))

        lnh = cursor.next()

        fields = list_fields(os.path.join(extentSource, extFile))

        c = 0
        while lnh:
            if c:
                break

            fdata = {
                field : lnh.getValue(
                    field
                ) for field in fields if field != 'Shape' and \
                    field != "FID" and field != "Id"
            }

            c += 1
            lnh = cursor.next()

        attrs_data[extFile] = fdata

    # List graphic elements to be changed
    files_and_element = tbl_to_obj(MAP_GRAPH_ELEM,
                                   useFirstColAsIndex=True,
                                   output='dict')
    """
    For each extent file, open the main mxd and change extent
    of the main dataframe and change some layers in contextual dataframes
    """
    for extFile in maps_ext:
        # Open mxd
        mxd = arcpy.mapping.MapDocument(baseMxd)

        # Get Text elements in the main mxd to be changed
        elem_names = files_and_element[files_and_element.keys()[0]].keys()
        text_elem = get_elem_by_name(mxd, elem_names)

        if not text_elem:
            print 'No Graphic/Text element was finded'

        # Change every text elements
        for elem_name in text_elem:
            text_elem[elem_name].text = files_and_element[os.path.splitext(
                extFile)[0]][elem_name]

        # Set new map extension
        refDf = lst_dataframe(mxd, dfNames=[MAIN_DATAFRAME])
        refLyr = lst_layers_by_name(mxd,
                                    dataFrames=MAIN_DATAFRAME,
                                    lyrNames=EXTENT_LYR_NAME)

        refLyr.replaceDataSource(extentSource, "NONE",
                                 os.path.splitext(extFile)[0], True)

        ext = refLyr.getExtent()

        newExtent = refDf.extent
        newExtent.XMin, newExtent.YMin = ext.XMin, ext.YMin
        newExtent.XMax, newExtent.YMax = ext.XMax, ext.YMax

        refDf.extent = newExtent

        # Change Context Dataframes
        lyrByDf = get_layers_by_dataframe(mxd)
        for df in CONTEXT_DATAFRAME:
            for mlyr in CONTEXT_DATAFRAME[df]["LAYERS"]:
                if CONTEXT_DATAFRAME[df]["LAYERS"][mlyr] != "EXTENTFILE":
                    mlyrsrc = os.path.join(
                        CONTEXT_DATAFRAME[df]["PATHDATA"], attrs_data[extFile][
                            CONTEXT_DATAFRAME[df]["LAYERS"][mlyr]])
                else:
                    mlyrsrc = os.path.join(extentSource, extFile)

                lyrByDf[df][mlyr].replaceDataSource(
                    os.path.dirname(mlyrsrc), "NONE",
                    os.path.splitext(os.path.basename(mlyrsrc))[0], True)

                if "ISZOOM" in CONTEXT_DATAFRAME[df]:
                    if mlyr == CONTEXT_DATAFRAME[df]["ISZOOM"]:
                        cdf = list_dataframe_by_name(mxd, [df])[0]

                        if "EXTENT_TOLERANCE" in CONTEXT_DATAFRAME[df]:
                            extTol = CONTEXT_DATAFRAME[df]["EXTENT_TOLERANCE"]
                        else:
                            extTol = 0

                        lext = lyrByDf[df][mlyr].getExtent()
                        nExt = cdf.extent
                        nExt.XMin = lext.XMin - extTol
                        nExt.YMin = lext.YMin - extTol
                        nExt.XMax = lext.XMax + extTol
                        nExt.YMax = lext.YMax + extTol

                        cdf.extent = nExt

        # Create a new mxd and export map
        outmap = write_map(
            mxd, os.path.join(outputMaps,
                              get_filename(extFile) + mapsFormat))

        mxd_saveas(
            os.path.join(outputMxd, '{}.mxd'.format(get_filename(extFile))))

        del mxd
コード例 #5
0
ファイル: fmcols.py プロジェクト: jasp382/glass
def col_to_map_v1(main_mxd, lyrs_to_change, layout_elm_file, symbology_to_apply,
              outDir, exportMap=None, maps_format='.jpg'):
    """
    TODO: ADD A MORE DETAILED DESCRIPTION
    
    Create a map for every column in a layer - Useful if you want
    to mantain layers symbology (colors) and inverval breaks.
    
    * main_mxd = path to a mxd template (all maps produced will be like
    this template);
    
    * lyrs_to_change = name of the layers to be changed from map to map;
    
    * layout_elm_file = file with the indication of what text should appear
    in each text element of the layout when some column is used as value
    field;
    eg.,
    
                    | id_element_1 | ... | id_element_n
    col_value_name1 |  some_text   | ... |  some_text
    col_value_name2 |  some_text   | ... |  some_text
    
    -> The goal is to mantain classes values and number of classes and colors
     - change only value field.
    
    NOT WORKING DO A ARCGIS BUG:
    When changing value field, symbology is automaticaly reseted.
    See col_to_map_v2 to a work around!
    Another work around could be the utilization of a custom ramp color
    """
    
    import os
    from glass.pys                import obj_to_lst
    from glass.dct                import tbl_to_obj
    from gesri.maps.arctbx.fields import list_fields
    from gesri.maps.arctbx.lyrs   import lst_layers
    from gesri.maps.arctbx.graph  import get_elem_by_name
    from gesri.maps.arctbx.wmap   import mxd_saveas
    
    if exportMap:
        from gesri.arcg.maps.wmap import write_map
    
    # List Cols to be maped and graphic elements to be changed
    cols_and_elements = tbl_to_obj(
        layout_elm_file, useFirstColAsIndex=True, output='dict'
    )
    
    # Prepare list of layers to modify
    lyrs_to_change = obj_to_lst(lyrs_to_change)
    
    if not lyrs_to_change: raise ValueError(
        'lyrs_to_change should by of type str, unicode or list'
    )
    
    # Open mxd and change it
    mxd = arcpy.mapping.MapDocument(main_mxd)
    
    # List layers objects to be modified on mxd
    lyr_objs = lst_layers(mxd, lyrNames=lyrs_to_change, storeDfs=True)
    lyr_objs = [lyr_objs] if type(lyr_objs) != list else lyr_objs
    
    if not len(lyr_objs):
        raise ValueError(
            'Cannot find any layer to be changed in the given mxd project'
        )
    
    # Get Text elements in mxd to be changed
    elem_names = cols_and_elements[cols_and_elements.keys()[0]].keys()
    text_elem  = get_elem_by_name(mxd, elem_names)
    
    if not text_elem:
        raise ValueError(
            'No Graphic/Text element was finded'
        )
    
    # For every column, export a new map
    for col in cols_and_elements:
        # Change layer value field and symbology
        for lyr in lyr_objs:
            # TODO: Add more symbology type
            if lyr[1].symbologyType == "GRADUATED_COLORS":
                if col in list_fields(lyr[1]):
                    lyr[1].symbology.valueField = col
                
                else:
                    print '{c} is not in the layer {l}'.format(
                        c=col, l=str(lyr[1].name)
                    )
            
            else:
                print (
                    'Symbology type of layer {} cannot be processed '
                    'by this script.'
                ).format(str(lyr[1].name))
        
        # Change every text elements
        for elm_name in text_elem:
            text_elem[elm_name].text = cols_and_elements[col][elm_name]
        
        if exportMap:
            outmap = write_map(mxd, os.path.join(outDir, col + maps_format))
        
        # Create new mxd
        mxd_saveas(mxd, col + '.mxd')
コード例 #6
0
ファイル: fmcols.py プロジェクト: jasp382/glass
def col_to_map_equalIntervals(main_mxd, lyrs_to_change,
        layout_elm_file, prefix_interval_label, outMaps,
        saveMxd=None, nr_intervals=7, min_max_file=None,
        intervals_file=None, maps_format='.jpg', intLabelSingle=True):
    """
    TODO: ADD A MORE PROPER DESCRIPTION
    
    Create a map for every column in a layer - Use if you want to mantain
    layers colors and change the interval breaks.
    
    * main_mxd = path to a mxd template (all maps produced will be like
    this template);
    
    * lyrs_to_change = name of the layers to be changed from map to map
    (should be the same layer but with different names);
    
    * layout_elm_file = file with the indication of what text should appear
    in each text element of the layout when some column is used as value
    field;
    eg.,
    
                    | id_element_1 | ... | id_element_n
    col_value_name1 |  some_text   | ... |  some_text
    col_value_name2 |  some_text   | ... |  some_text
    
    * prefix_interval_label = label classes elements name prefix
    (label elements should be like this 'legend_1;legend_2');
    
    * min_max_file = file with the indication of the minimum and maximum
    values to consider when calculating the intervals for each column
    eg.,
                    | min | max
    col_value_name1 |  x  |  y
    col_value_name2 |  x  |  y
    
    * intervals_file = file with the intervals
    
    You can not use min_max_file and intervals_file at the
    same time
    
    -> Change only intervals values and labels in the legend.
    New intervals that will be used will be calculated using
    equal interval method.
    
    Note: Legend graphic elements must be ungrouped.
    """
    
    import os
    
    from glass.pys                import obj_to_lst
    from glass.dct                 import tbl_to_obj
    from glass.maps.arctbx.fields import list_fields
    from glass.maps.arctbx.graph  import get_elem_by_name
    from glass.maps.arctbx.graph  import get_elem_by_prefix
    from glass.maps.arctbx.lyrs   import lst_layers
    from glass.maps.arctbx.wmap   import mxd_saveas
    from glass.cpu.arcg.mng.fld   import get_equal_int
    from glass.datacat            import _get_equal_int_
    from glass.maps.arctbx.wmap   import write_map
    
    if min_max_file and intervals_file:
        raise ValueError(
            'min_max_file and intervals_file are not allowed together'
        )
    
    maps_format = maps_format if maps_format[0] == '.' else '.' + maps_format
    
    # List Cols to be maped and graphic elements to be changed
    cols_and_elements = tbl_to_obj(
        layout_elm_file, useFirstColAsIndex=True, output='dict'
    )
    
    # Prepare list of layers to modify
    lyrs_to_change = obj_to_lst(lyrs_to_change)
    
    if not lyrs_to_change: raise ValueError(
        'lyrs_to_change should by of type str, unicode or list'
    )
    
    # Open mxd and change it
    mxd = arcpy.mapping.MapDocument(main_mxd)
    
    # List layers objects to be modified from mxd
    lyr_objs = lst_layers(mxd, lyrNames=lyrs_to_change, storeDfs=True)
    lyr_objs = [lyr_objs] if type(lyr_objs) != list else lyr_objs
    
    if not len(lyr_objs):
        raise ValueError(
            'Cannot find any layer to be changed in the given mxd project'
        )
    
    # Get Text elements in mxd to be changed
    elem_names = cols_and_elements[cols_and_elements.keys()[0]].keys()
    text_elem = get_elem_by_name(mxd, elem_names)
    
    if not text_elem:
        raise ValueError(
            'We can not find any text element with names given'
        )
    
    # Get text elements from the map legend
    leg_elements = get_elem_by_prefix(mxd, prefix_interval_label)
    leg_elm = {e.name: e for e in leg_elements}
    del leg_elements
    leg_elm_names = leg_elm.keys()
    leg_elm_names.sort()
    
    # There is a file with the indication of minimum and max values to be
    # used?
    col_min_max = tbl_to_obj(
        min_max_file, useFirstColAsIndex=True, output='dict'
    ) if min_max_file else None
    
    # There is a file with the intevals to be used?
    intervals_dict = tbl_to_obj(
        intervals_file, useFirstColAsIndex=True, output='dict'
    ) if intervals_file else None
    
    # For every column, export a new map
    for col in cols_and_elements:
        print "Producing {} Map".format(col)
        # Change layer value field and adjust intervals
        if intervals_dict:
            int_breaks = [
                intervals_dict[col][i] for i in range(nr_intervals+1)]
        else:
            int_breaks = get_equal_int(
                lyr_objs[0][1].dataSource, col, nr_intervals
            ) if not col_min_max else _get_equal_int_(
                col_min_max[col]['max'], col_min_max[col]['min'],
                nr_intervals
            )
        
        if not intLabelSingle:
            breaks_label = [
                "{} - {}".format(int_breaks[i-1], int_breaks[i])
                for i in range(1, len(int_breaks))
            ]
            
        else:
            breaks_label = [str(i) for i in int_breaks]
        
        for lyr in lyr_objs:
            # TODO: Add more symbology types
            if lyr[1].symbologyType == "GRADUATED_COLORS":
                if col in list_fields(lyr[1]):
                    lyr[1].symbology.valueField = col
                    lyr[1].symbology.classBreakValues = int_breaks
                
                else:
                    print '{c} is not in the layer {l}'.format(
                        c=col, l=str(lyr[1].name)
                    )
            
            else:
                print (
                    'Symbology type of layer {} cannot be processed '
                    'by this script.'
                ).format(str(lyr[1].name))
        
        # Change every text elements
        #print intervals_dict
        #print leg_elm_names
        for elm_name in text_elem:
            text_elem[elm_name].text = cols_and_elements[col][elm_name]
        
        # Change intervals labels in the legend
        for i in range(len(leg_elm_names)):
            # TODO: here we have a problem
            # Round values are used in labeling but not in the classification
            # Think about that
            leg_elm[leg_elm_names[i]].text = breaks_label[i]
        
        
        outmap = write_map(mxd, os.path.join(outMaps, col + maps_format))
        
        # Create a new mxd
        if saveMxd:
            mxd_saveas(mxd, os.path.join(saveMxd, col + '.mxd'))
        
        print "{} Map is done!".format(col)
コード例 #7
0
ファイル: fmcols.py プロジェクト: jasp382/glass
def col_to_map_mlyr(main_mxd, lyrs_src, lyrs_joker, mapColsTbl, graphicsTbl,
                    out_maps, mapsFormat='.jpg', out_mxd=None):
    """
    Same as col_to_map, but this one allows multiple layers chaging
    
    lyrs_src = {
        "lyr1_name" : r'/path/to/datasource.shp',
        "lyr2_name" : r'/path/to/datasource.shp'
        ...
    }
    
    lyrs_joker = {
        "lyr1_name" : "joker_field_name",
        "lyr2_name" : "joker_field_name"
    }
    
    mapColsTbl = path to table with the relation between columns and map
                | lyr_1_name | ... | lyr_n_name 
     map_alias1 |  col_name  | ... |  col_name
     map_alias2 |  col_name  | ... |  col_name
     
    graphicsTbl = path to table with relation between maps and values to assign
    to graphic elements
                | element_1 | ... | element_n
     map_alias1 | some_text | ... | some_text
     map_alias2 | some_text | ... | some_text
    """
    
    import os
    from glass.dct               import tbl_to_obj
    from glass.cpu.arcg.mng.fld  import calc_fld
    from glass.maps.arctbx.graph import get_elem_by_name
    from glass.maps.arctbx.wmap  import mxd_saveas
    from glass.maps.arctbx.wmap  import write_map
    
    mapsFormat = mapsFormat if mapsFormat[0] == '.' else '.' + mapsFormat
    
    # Get maps to do
    mapsToDo = tbl_to_obj(
        mapColsTbl, useFirstColAsIndex=True, output='dict'
    )
    
    # Get dict with association between maps and graphics elements
    graphicElem = tbl_to_obj(
        graphicsTbl, useFirstColAsIndex=True, output='dict'
    )
    
    # Create new maps
    for newMap in mapsToDo:
        print "Producing {} Map".format(newMap)
        
        # Update JOKER's FIELD's
        for lyr in mapsToDo[newMap]:
            calc_fld(
                lyrs_src[lyr], lyrs_joker[lyr],
                "[{}]".format(str(mapsToDo[newMap][lyr]))
            )
        
        # Open mxd and change it
        mxd = arcpy.mapping.MapDocument(main_mxd)
        
        # Get Text elements in the main mxd to be changed
        elem_names = graphicElem[newMap].keys()
        text_elem  = get_elem_by_name(mxd, elem_names)
        
        if not text_elem:
            print 'No Graphic/Text element was finded'
        
        for e in text_elem:
            text_elem[e].text = graphicElem[newMap][e]
        
        outmap = write_map(mxd, os.path.join(out_maps, newMap + mapsFormat))
        
        # Create a new mxd only because
        if out_mxd:
            mxd_saveas(mxd, os.path.join(out_mxd, newMap + '.mxd'))
        
        # Close mxd
        del mxd
        
        print "{} Map is done!".format(newMap)
コード例 #8
0
ファイル: fmcols.py プロジェクト: jasp382/glass
def col_to_map(main_mxd, lyrs_sourcedata, joker_field, layout_elm_file,
               mapsDir, mxdDir=None, maps_format='.jpg', includeMxdNameInMap=None):
    """
    TODO: ADD A MORE DETAILED DESCRIPTION
    
    WORK AROUND for col_to_map_v1
    if we change the valueField, the symbology will be reseted. So, lets
    change the values of the valueField
    
    GOAL: Create a map for every column in a layer - Use if you want
    to mantain layers symbology including colors and inverval breaks.
    
    * main_mxd = path to a mxd template (all maps produced will be like
    this template);
    
    * lyrs_sourcedata = path to the data source of the layers
    that will be changed from map to map;
    
    * joker_field = name of the field that will store the values to be
    mapped (same field but different values);
    
    * layout_elm_file = file with the indication of what text should appear
    in each text element of the layout when some column is used as value
    field;
    eg.,
    
                    | id_element_1 | ... | id_element_n
    col_value_name1 |  some_text   | ... |  some_text
    col_value_name2 |  some_text   | ... |  some_text
    
    -> The goal is to mantain classes values and number of classes and colors
     - change only value field.
    """
    
    import os
    from glass.dct               import tbl_to_obj
    from glass.cpu.arcg.mng.fld  import calc_fld
    from glass.maps.arctbx.graph import get_elem_by_name
    from glass.maps.arctbx.wmap  import mxd_saveas
    from glass.maps.arctbx.wmap  import write_map
    
    if includeMxdNameInMap:
        from glass.pyt.oss import fprop
        mapBaseName = fprop(main_mxd, forceLower=True) + "_"
    
    else:
        mapBaseName = ""
    
    maps_format = '.' + maps_format if maps_format[0] != '.' else maps_format
    
    # List Cols to be maped and graphic elements to be changed
    cols_and_elements = tbl_to_obj(
        layout_elm_file, useFirstColAsIndex=True, output='dict'
    )
    
    for col in cols_and_elements:
        print "Producing {} Map".format(col)
        # Update JOKER FIELD
        calc_fld(
            lyrs_sourcedata, joker_field, "[{}]".format(str(col))
        )
        
        # Open mxd and change it
        mxd = arcpy.mapping.MapDocument(main_mxd)
        
        # Get Text elements in the main mxd to be changed
        elem_names = cols_and_elements[cols_and_elements.keys()[0]].keys()
        text_elem  = get_elem_by_name(mxd, elem_names)
        
        if not text_elem:
            print 'No Graphic/Text element was finded'
        
        # Change every text elements
        for elm_name in text_elem:
            text_elem[elm_name].text = cols_and_elements[col][elm_name]
        
        outmap = write_map(mxd, os.path.join(
            mapsDir, "{}{}{}".format(mapBaseName, col, maps_format)
        ))
        
        # Create a new mxd
        if mxdDir:
            mxd_saveas(os.path.join(mxdDir, "{}{}{}".format(
                mapBaseName, col, '.mxd'
            )))
        
        # Close mxd
        del mxd
        
        print "{} Map is done!".format(col)