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
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))
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
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
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')
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)
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)
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)