def _props(a_shape, prn=True): """Get some basic shape geometry properties. Note: ---- `a_shape`, is a single shape. A searchcursor will return a list of geometries, so you should slice even if there is only one shape. """ if not hasattr(a_shape, '__geo_interface__'): tweet("Requires a 'shape', your provided a {}".format(type(a_shape))) return None coords = a_shape.__geo_interface__['coordinates'] SR = a_shape.spatialReference props = ['type', 'isMultipart', 'partCount', 'pointCount', 'area', 'length', 'length3D', 'centroid', 'trueCentroid', 'firstPoint', 'lastPoint', 'labelPoint'] props2 = [['SR Name', SR.name], ['SR Factory code', SR.factoryCode]] t = "\n".join(["{!s:<12}: {}".format(i, a_shape.__getattribute__(i)) for i in props]) t = t + "\n" + "\n".join(["{!s:<12}: {}".format(*i) for i in props2]) tc = '{!r:}'.format(np.array(coords)) tt = t + "\nCoordinates\n" + indent(tc, '....') if prn: print(tt) else: return tt
def shapes_fc(shps, out_fc): """Create a featureclass/shapefile from poly* shapes. Requires: --------- - shps : geometry Point geometry objects needed to create the featureclass - out_fc : string Full path and name to the output container (gdb or folder) """ msg0 = "\nCreated..\n{}".format(out_fc) msg1 = "\nCan't overwrite the {}... rename it".format(out_fc) arcpy.overwriteOutput = True try: if arcpy.Exists(out_fc): arcpy.Delete_management(out_fc) arcpy.CopyFeatures_management(shps, out_fc) tweet(msg0) except ValueError: tweet(msg1)
def arr_pnts(a, out_fc, shp_fld, SR): """Make point features from a structured array. Requires: -------- `a` : structured/recarray `out_fc` : featureclass full path and name `shp_fld` : the table field which contains the geometry `SR` : the spatial reference/coordinate system of the geometry """ msg0 = "\nCreated..\n{}".format(out_fc) msg1 = "\nCan't overwrite {}... rename it".format(out_fc) try: if arcpy.Exists(out_fc): arcpy.Delete_management(out_fc) arcpy.da.NumPyArrayToFeatureClass(a, out_fc, shp_fld, SR) tweet(msg0) except Exception as e: tweet(msg1 + str(e))
def to_fc(out_fc, a, b=None, dim=2, flds=['Id', 'X', 'Y'], SR_code=None): """Reconstruct a featureclass from a deconstructed pair of arrays. This function reverses the functionality of to_array which splits a featureclass into an array of geometry and one of attributes. One can perform operations on one or the other or both, then reassemble into a new file. Requires: -------- `out_fc` : filename full path and name for the output featureclass `a` : geometry array the array of geometry objects `b` : attribute array the array of attributes for 'a' `dim` : geometry type - 0 (point) - 1 (polyline) or - 2 (polygon) `fld` : id and shape field(s) normally ['Id, 'X', 'Y'] if deconstructed using 'to_array' `SR_code` : The spatial reference code of the output geometry - 4326 for GCS WGS84 - 2951 for MTM 9 References: ---------- Spatial reference http://spatialreference.org/ """ args = [to_fc.__module__, dedent(to_fc.__doc__)] msg = "\n...to_fc ... in {} failed\n{}".format(*args) try: SR = arcpy.SpatialReference(SR_code) except ValueError: tweet("Spatial reference is in error") tweet(msg) return None if (dim not in (0, 1, 2)) or (len(flds) not in (2, 3)): tweet(msg) return None if len(flds) == 2: oid_fld, shp_fld = flds else: oid_fld, shp_fld = flds[0], flds[1:3] if dim == 0: arr_pnts(a, out_fc, shp_fld, SR) # geom = _split_array(a, fld=oid_fld) geom = np.split(a, np.where(np.diff(a[oid_fld]))[0] + 1) prts = [i[['Xs', 'Ys']].tolist() for i in geom] if dim == 1: arr_polyline_fc(geom, out_fc, oid_fld, shp_fld, SR) else: # arr_polygon_fc(geom, out_fc, oid_fld, shp_fld, SR) # pts = _arr_common(a, oid_fld, shp_fld) f = [] for pt in prts: # g f.append( arcpy.Polygon(arcpy.Array([arcpy.Point(*p) for p in pt]), SR)) # _shapes_fc(f, out_fc) # arcpy.da.ExtendTable(out_fc, table_match_field=oid_fld, # in_array=b, array_match_field=oid_fld) return f
def fc_array(in_fc, flds="*", allpnts=True): """Convert a featureclass to an ndarray...with optional fields besides the FID/OIDName and Shape fields. Parameters: ----------- in_fc : text Full path to the geodatabase and the featureclass name flds : text or list - ``'' : just an object id and shape field`` - ``'*' : all fields in the featureclass or`` - ``list : specific fields ['OBJECTID','Shape','SomeClass', etc]`` allpnts : boolean - True `explodes` geometry to individual points. - False returns the centroid Requires: --------- fc_info(in_fc) function See also: --------- FeatureClassToNumPyArray, ListFields for more information in current arcpy documentation """ out_flds = [] shp_fld, oid_fld, shp_type, SR = fc_info(in_fc) # get the base information flds_all = arcpy.ListFields(in_fc) flds_oth = [f for f in flds_all if f.type not in ('OID', 'Geometry')] fld_names = [f.name for f in flds_oth] oid_geom = [oid_fld, 'SHAPE@X', 'SHAPE@Y'] nulls = { 'Double': np.nan, 'Single': np.nan, 'Short': np.iinfo(np.int16).min, 'SmallInteger': np.iinfo(np.int16).min, 'Long': np.iinfo(np.int32).min, 'Float': np.nan, 'Integer': np.iinfo(np.int32).min, 'String': str(None), 'Text': str(None) } fld_dict = {i.name: i.type for i in flds_oth} null_dict = {f: nulls[fld_dict[f]] for f in fld_names} if flds == "": # return just OID and Shape values out_flds = oid_geom # FID and Shape X, Y elif flds == "*": # all fields out_flds = oid_geom + fld_names else: out_flds = [oid_fld, 'SHAPE@X', 'SHAPE@Y'] for f in flds_oth: if f.name in flds: out_flds.append(f.name) frmt = """\nRunning 'fc_array' with .... \nfeatureclass... {}\nFields... {}\nAll pnts... {}\nSR... {} """ args = [in_fc, out_flds, allpnts, SR.name] msg = dedent(frmt).format(*args) tweet(msg) a = arcpy.da.FeatureClassToNumPyArray(in_fc, field_names=out_flds, where_clause="", spatial_reference=SR, explode_to_points=allpnts, skip_nulls=False, null_value=null_dict) # out it goes in array format return a
in_tbl, all_flds, cls_flds, sum_flds = _testing() else: testing = False in_tbl, out_tbl, cls_flds, sum_flds = _tool_() cls_flds = cls_flds.split(";") # tidy up the two field inputs sum_flds = sum_flds.split(";") a = arcpy.da.TableToNumPyArray(in_tbl, "*") # use the full array's data uni, first, clas, cases, count, vals = freq(a, cls_flds) # do freq analysis # perform the summary results new_vals = [vals] new_names = ['count'] tweet("sum flds = {}".format(sum_flds)) if sum_flds[0] not in ('#', None, 'None', "", ''): for i in sum_flds: fld_sums = summ(a, cls_flds, uni, i) # do the sums using summ new_names.append('sum_' + i) new_vals.append(fld_sums) ## create the output array and return the table #b = rfn.append_fields(uni, names=new_names, data=new_vals, usemask=False) # #msg = "\nSummary array...\n" #tweet(msg + prn_rec(b, prn=False)) # use arraytools.frmts.frmt_rec # #if not testing: # arcpy.da.NumPyArrayToTable(b, out_tbl)
in_tbl, all_flds, cls_flds, sum_flds = _testing() else: testing = False in_tbl, out_tbl, cls_flds, sum_flds = _tool_() cls_flds = cls_flds.split(";") # tidy up the two field inputs sum_flds = sum_flds.split(";") a = arcpy.da.TableToNumPyArray(in_tbl, "*") # use the full array's data uni, first, clas, cases, count, vals = freq(a, cls_flds) # do freq analysis # perform the summary results new_vals = [vals] new_names = ['count'] tweet("sum flds = {}".format(sum_flds)) if sum_flds[0] not in ('#', None, 'None', "", ''): for i in sum_flds: fld_sums = summ(a, cls_flds, uni, i) # do the sums using summ new_names.append('sum_' + i) new_vals.append(fld_sums) ## create the output array and return the table #b = rfn.append_fields(uni, names=new_names, data=new_vals, usemask=False) # #msg = "\nSummary array...\n" #tweet(msg + prn_rec(b, prn=False)) # use arraytools.frmts.frmt_rec # #if not testing: # arcpy.da.NumPyArrayToTable(b, out_tbl)