def process_attachements(rows, fields, join_fc, gdb, table_name="attachments", working_folder=arcpy.env.scratchFolder): """ creates and handles the attachments Inputs: rows - list - attachments rows to insert to table fields - list - fields for insert cursor join_fc - string - path of file geodatabase feature class that will have attachments enabled. gdb - string - path to geodatabase table_name - string - name of attachments table working_folder - string - path to where attachments are stored. Output: boolean. True successful/False failed. """ tbl = arcpy.CreateTable_management(out_path=gdb, out_name=table_name)[0] arcpy.AddField_management(tbl, "ParentID", "TEXT", field_length=1320) arcpy.AddField_management(tbl, "PATH", "TEXT", field_length=1320) icur = arcpy.da.InsertCursor(tbl, ['ParentID', "PATH"]) for row in rows: icur.insertRow(__unicode_convert(row)) del row del rows del icur arcpy.EnableAttachments_management(in_dataset=join_fc) arcpy.AddAttachments_management(in_dataset=join_fc, in_join_field="GlobalID", in_match_table=tbl, in_match_join_field="ParentID", in_match_path_field="PATH", in_working_folder=working_folder) return True
def copyData(self, base, to, addPhoto, basePhoto, objectIDLabel): log('\tCopie de ' + str(base) + ' vers ' + str(to)) if not arcpy.Exists(to): try: arcpy.Copy_management(base, to) except BaseException as e: log(e) else: arcpy.Append_management(base, to, "TEST", "", "") if addPhoto and basePhoto and basePhoto != '': arcpy.EnableAttachments_management(to) arcpy.AddAttachments_management(to, objectIDLabel, basePhoto, 'objid', "img", "#")
import arcpy from arcpy import da import os feature = arcpy.GetParameterAsText(0) inTable = arcpy.GetParameterAsText(1) fileLocation = arcpy.GetParameterAsText(2) with da.SearchCursor(inTable, ['DATA', 'ATT_NAME', 'REL_GLOBALID']) as cursor: for item in cursor: attachment = item[0] filename = str(item[2]) + "_" + str(item[1]) open(fileLocation + os.sep + filename, 'wb').write(attachment.tobytes()) del item del filename del attachment arcpy.AddField_management(inTable, "NAME_FOTO", "TEXT", "", "", 100) with arcpy.da.UpdateCursor( inTable, ["NAME_FOTO", "REL_GLOBALID", "ATT_NAME"]) as cursor: for x in cursor: x[0] = str(x[1]) + "_" + str(x[2]) cursor.updateRow(x) arcpy.AddAttachments_management(feature, 'GLOBALID', inTable, 'REL_GLOBALID', 'NAME_FOTO', fileLocation)
def GeoPhotoToPoint(folder, fc, badphotostable="", addnongps="", attachphotos=""): try: # Convert text from boolean parameters to Python True | False addnongps = True if addnongps.lower() in ["true", "all_photos", "" ] else False attachphotos = True if attachphotos.lower() in [ "true", "add_attachments", "" ] else False # Get all photo files from Input Folder photolist = ExifUtils.ListPhotos(folder) # Create outputs CreateOutputs(fc, badphotostable, photolist) foundone = 0 incur = incurbad = None # Set progress bar arcpy.SetProgressor("step", "", 0, len(photolist), 1) try: with arcpy.da.Editor(os.path.dirname(fc)) as edit_session: # Open an InsertCursor to write point locations to a new feature class incur = da.InsertCursor(fc, [ "Path", "Name", "DateTime", "SHAPE@X", "SHAPE@Y", "SHAPE@Z", "Direction" ]) # Open an InsertCursor to write a list of photos with no GPS coordinates incurbad = da.InsertCursor( badphotostable, ["Photo"]) if badphotostable else None # Get GPS information from each photo for file in photolist: photo = ExifUtils.GetExifMetadata(file) # If the photo has a valid Exif header with coordinate information if (photo.x and photo.y) or addnongps: # Create the point with geometry and attributes incur.insertRow([ photo.file, os.path.basename(photo.file), photo.m, photo.x, photo.y, photo.z, photo.d ]) foundone = 1 if (not photo.x or not photo.y) and badphotostable: # Write the photo path to the Invalid Photos Table output incurbad.insertRow([photo.file]) arcpy.SetProgressorPosition() except: raise finally: if incur: del incur if incurbad: del incurbad # If none of the photos were geotagged, give the standard empty output warning if not foundone: arcpy.AddIDMessage("WARNING", 117) # Attach photos if option specified if attachphotos: if foundone or addnongps: oidfield = arcpy.Describe(fc).OIDFieldName arcpy.EnableAttachments_management(fc) arcpy.AddAttachments_management(fc, oidfield, fc, oidfield, "Path", "") except: # Delete outputs if failure occurs if arcpy.Exists(fc): arcpy.Delete_management(fc) if arcpy.Exists(badphotostable): arcpy.Delete_management(badphotostable) arcpy.AddIDMessage("ERROR", 999999) sys.exit()
else: pass if CameraInput == "Associate Photo with Parcel": arcpy.AddMessage("Step 8: Adding survey question fields") else: arcpy.AddMessage("Step 2: Adding Survey question fields") if CameraInput == 'Associate Photo with Parcel': arcpy.Append_management(ParcelPointClassHelper, ParcelPointHelper, "NO_TEST") arcpy.AddField_management(ParcelPointHelper, "REVERSE", "TEXT", "", "", "5", "", "NULLABLE", "NON_REQUIRED", "") arcpy.JoinField_management(ParcelPointHelper, ParcelPIN, PhotoFeatureClass3, ParcelPIN) arcpy.CalculateField_management(ParcelPointHelper, "REVERSE", "!REVERSE_1!", "PYTHON", "") arcpy.EnableAttachments_management(ParcelPointHelper) arcpy.AddAttachments_management(ParcelPointHelper, ParcelPIN, PhotoFeatureClass3, ParcelPIN, "Path2", "") arcpy.AddMessage("Step 9: Creating photo attachments") else: pass if CameraInput == 'Associate Geotagged Photo with Point (photo has location)': arcpy.AddMessage("Step 3: Adding application required fields") arcpy.AddField_management(ParcelPointHelper, "BSTPHOTOID", "TEXT", "", "", "25", "Best Photo Identifier", "NULLABLE", "NON_REQUIRED", "") arcpy.AddField_management(ParcelPointHelper, "SRVNAME", "TEXT", "", "", "25", "Surveyor Name", "NULLABLE", "NON_REQUIRED", "") arcpy.AddField_management(ParcelPointHelper, "Path", "TEXT","", "", "254", "Path", "NULLABLE", "NON_REQUIRED", "") arcpy.AddField_management(ParcelPointHelper, "Name", "TEXT","", "", "150", "Name", "NULLABLE", "NON_REQUIRED", "") arcpy.AddField_management(ParcelPointHelper, "DateTime", "TEXT","", "", "100", "DateTime", "NULLABLE", "NON_REQUIRED", "") arcpy.AddField_management(ParcelPointHelper, "Direction", "Double","", "", "", "Direction", "NULLABLE", "NON_REQUIRED", "") arcpy.AddMessage("Step 4: Finalizing photo survey feature class")
graphLocationDict[llosID] = graphPath deleteme.append(graphPath) # TODO: start an update cursor arcpy.AddMessage("Enabling attachments ...") arcpy.EnableAttachments_management(inputFeatures) matchTable = os.path.join(scratchGDB, "matchTable") deleteme.append(matchTable) arcpy.AddMessage("Building match table ...") arcpy.GenerateAttachmentMatchTable_management(inputFeatures, scratchFolder, matchTable, "pngname", "*.png", "ABSOLUTE") arcpy.AddMessage("Attaching graphs to lines ...") arcpy.AddAttachments_management(inputFeatures, "OID", matchTable, "MatchID", "Filename") # cleanup arcpy.AddMessage("Removing scratch data ...") for ds in deleteme: if arcpy.Exists(ds): arcpy.Delete_management(ds) if debug == True: arcpy.AddMessage(str(ds)) # output arcpy.SetParameter(1, inputFeatures) except arcpy.ExecuteError: error = True # Get the tool error messages msgs = arcpy.GetMessages()
def MatchPhotos2Rows(folder, fc, timefield, outtable, badphotostable="", attachphotos="", timetol=0, offset=0): try: # Convert text from boolean parameters to Python True | False attachphotos = True if attachphotos.lower() in [ "true", "add_attachments", "" ] else False oidfield = arcpy.Describe(fc).OIDFieldName dict = {} # Create dictionary of timestamps in Input Table for row in da.SearchCursor(fc, [oidfield, timefield]): dict[row[0]] = row[1] # Get all photo files from Input Folder photolist = ExifUtils.ListPhotos(folder) # Create outputs CreateOutputs(outtable, badphotostable, photolist) foundone = 0 icur = incurbad = None # Set progress bar arcpy.SetProgressor("step", "", 0, len(photolist), 1) try: with arcpy.da.Editor(os.path.dirname(outtable)) as edit_session: # Open an InsertCursor to write matches to the Output Table icur = da.InsertCursor( outtable, ["IN_FID", "Photo_Path", "Photo_Name", "Match_Diff"]) # Open an InsertCursor to write a list of non-matching photos incurbad = da.InsertCursor( badphotostable, ["Photo"]) if badphotostable else None # Get DateTime information from each photo for file in photolist: photo = ExifUtils.GetExifMetadata(file) # If the photo has a valid Exif header with DateTime information if photo.m: # Turn timestamp string into a Python datetime class photo.m = datetime.datetime.fromtimestamp( time.mktime( time.strptime(photo.m, '%Y:%m:%d %H:%M:%S'))) # If a time offset was specified, change the photo timestamp if offset: photo.m += datetime.timedelta(seconds=offset) # Find a match for this DateTime closestID = ClosestTime(photo.m, dict.items()) # Determine if the time difference between this photo and row is within the tolerance closestDif = abs(dict[closestID] - photo.m).total_seconds() # If the difference is within the tolerance, make a match by writing an output row if closestDif <= timetol or timetol == 0: icur.insertRow([ closestID, photo.file, os.path.basename(photo.file), closestDif ]) foundone = 1 else: # Write the photo path to the Unmatched Photos Table if badphotostable: incurbad.insertRow([photo.file]) else: # Write the photo path to the Unmatched Photos Table if badphotostable: incurbad.insertRow([photo.file]) arcpy.SetProgressorPosition() except: raise finally: if icur: del icur if incurbad: del incurbad # Attach photos if option specified if attachphotos: arcpy.EnableAttachments_management(fc) arcpy.AddAttachments_management(fc, oidfield, outtable, "IN_FID", "Photo_Path", "") # If none of the photos were matched give the standard empty output warning if not foundone: arcpy.AddIDMessage("WARNING", 117) except: if arcpy.Exists(outtable): arcpy.Delete_management(outtable) if arcpy.Exists(badphotostable): arcpy.Delete_management(badphotostable) arcpy.AddIDMessage("ERROR", 999999) sys.exit()
gaData = urllib.urlencode(gaValues) try: urllib.urlretrieve(url=gaUrl + '/' + gaName, filename=os.path.join(gaFolder, gaName),data=gaData) except: PrintException("Error Retrieving Attachments") rows = arcpy.da.InsertCursor(fc + "__ATTACH", ["GlobalID_Str", "PhotoPath"]) hasrow = False for cmtX in data['layers'][0]['attachments']: rows.insertRow((cmtX['parentGlobalId'], cwd + os.sep +cmtX['parentGlobalId'] + os.sep + cmtX['name'])) hasrow = True if hasrow == True: del rows try: arcpy.AddAttachments_management(fc, 'GlobalID_Str', fc + '__ATTACH', 'GlobalID_Str', 'PhotoPath') except: PrintException("Error Retrieving Attachments") try: arcpy.MakeTableView_management(fc + '__ATTACH', "tblView") arcpy.SelectLayerByAttribute_management("tblView", "NEW_SELECTION", "DATA_SIZE = 0") arcpy.DeleteRows_management("tblView") arcpy.DeleteField_management(fc + '__ATTACH', 'GlobalID_Str') arcpy.DeleteField_management(fc + '__ATTACH', 'PhotoPath') except Exception, e: arcpy.AddWarning("Error: " + str(e)) pass except KeyError: pass
subdirectories = [x[0] for x in os.walk(rootdir)] for folders in subdirectories[1:]: print folders try: # create a new Match Table csv file writer = csv.writer(open(matchTable, "wb"), delimiter=",") # write a header row (the table will have two columns: ParcelID and Picture) writer.writerow([matchField, pathField]) # iterate through each picture in the directory and write a row to the table for file in os.listdir(folders): if str(file).find(".pdf") > -1: writer.writerow([str(file).replace(".pdf", ""), file]) # the input feature class must first be GDB attachments enabled # arcpy.EnableAttachments_management(input) # use the match table with the Remove Attachments tool arcpy.RemoveAttachments_management(input, inputField, matchTable, matchField, pathField) # use the match table with the Add Attachments tool arcpy.AddAttachments_management(input, inputField, matchTable, matchField, pathField, folders) print "Finished Attaching Documents in " + folders except: print arcpy.GetMessages(2)
for mp_folder in os.listdir(os.path.join(rootFolder, route_folder)): cursor = arcpy.da.InsertCursor( table, [matchid_field, matchfilepath_field]) expr1 = route_field + "='" + route_folder + "' AND " + mp_field + "=" + mp_folder + "" with arcpy.da.SearchCursor(sourcePoints, ["OBJECTID", route_field, mp_field], where_clause=expr1) as cursor1: for row in cursor1: print(row[0]) for filename in os.listdir( os.path.join(rootFolder, route_folder, mp_folder)): fileUpper = filename.upper() #let's assume all of the files we want to add are jpeg files if fileUpper.endswith(".JPG"): bHasFiles = True cursor.insertRow([ row[0], os.path.join(rootFolder, route_folder, mp_folder, filename) ]) print("Inserting... " + fileUpper) del cursor #add the attachments to the feature class based on the match table arcpy.AddAttachments_management(in_dataset=sourcePoints, in_join_field="OBJECTID", in_match_table=os.path.join( sourceGDB, tempMatchTable), in_match_join_field="MatchID", in_match_path_field="Filename", in_working_folder="")
def do_analysis(inFC, outDir, uniqueNameField, googleMapsAPIKey, headingField=None, attachmentBool=True): """This is the main function call for the StreetViewGISRetrieval Tool. It interacts with the Google Maps API and the ArcGIS Arcpy library to fill a directory with street view images that correspond to an input feature's inside centroids.""" try: arcpy.env.overwriteOutput = True workspace = os.path.dirname(inFC) FileName = os.path.basename(inFC) # tempOutName = arcpy.ValidateTableName("TempBlockFC_1", workspace) # tempOutFeature = os.path.join(workspace, tempOutName) # Add New Fields arcPrint( "Adding new field for Image paths, will change if images location change.", True) featurePathField = arcpy.ValidateFieldName("UniqueFeatPaths", workspace) AddNewField(inFC, featurePathField, "TEXT") arcPrint("Gathering feature information.", True) # Get feature description and spatial reference information for tool use desc = arcpy.Describe(inFC) spatialRef = desc.spatialReference shpType = desc.shapeType srName = spatialRef.name arcPrint( "The shape type is {0}, and the current spatial reference is: {1}." .format(str(shpType), str(srName)), True) WGS_1984_MajAux = arcpy.SpatialReference( 104199 ) # http://support.esri.com/cn/knowledgebase/techarticles/detail/34749 fNames = ["SHAPE@", uniqueNameField, featurePathField] if headingField and FieldExist(inFC, headingField): fNames.append(str(headingField)) if not os.path.exists(outDir): os.makedirs(outDir) arcPrint( "Specified directory did not exist, so a new one was created.", True) counter = 1 arcPrint( "Establishing an update cursor for simultaneous image collection and feature class correspondence.", True) if shpType == "Polyline": with arcpy.da.UpdateCursor( inFC, fNames, spatial_reference=WGS_1984_MajAux) as cursor: arcPrint( "Feature class is a polyline, using midpoint along line to determine location and heading to pass to API.", True) for row in cursor: try: arcPrint("!") midPoint = row[getFIndex(fNames, "SHAPE@")].positionAlongLine( .5, True) beyondMidPoint = row[getFIndex( fNames, "SHAPE@")].positionAlongLine(.500001, True) arcPrint("!") headingParam = getAngleBetweenPoints( midPoint, beyondMidPoint, True) arcPrint("!") midpointProjected = midPoint.projectAs(WGS_1984_MajAux) fileName = "{0}.{1}".format( str(row[getFIndex(fNames, uniqueNameField)]), "jpeg") fileOutPath = os.path.join(outDir, fileName) # Lat is y, Long is x- Passed to street vew image fetch_streetview_image_and_save( (midpointProjected.centroid.Y, midpointProjected.centroid.X), headingParam, fileOutPath) counter += 1 row[getFIndex(fNames, featurePathField)] = fileName cursor.updateRow(row) print("Completed save of image and updated row.") except Exception as e: arcPrint( "Iteration {0} had a handling error and was skipped." .format((str(counter)))) print(e.args[0]) else: with arcpy.da.UpdateCursor( inFC, fNames, spatial_reference=WGS_1984_MajAux) as cursor: arcPrint( "Feature class is either point or polygon, using label point to get location only.", True) for row in cursor: try: midLabelPoint = row[getFIndex(fNames, "SHAPE@")].labelPoint midLabelPointProjected = midLabelPoint.projectAs( WGS_1984_MajAux) headingParam = row[getFIndex( fNames, headingField)] if getFIndex( fNames, headingField) else None fileName = "{0}.{1}".format( str(row[getFIndex(fNames, uniqueNameField)]), "jpeg") fileOutPath = os.path.join(outDir, fileName) if headingParam: fetch_streetview_image_and_save( (midLabelPointProjected.centroid.Y, midLabelPointProjected.centroid.X), headingParam, fileOutPath) else: fetch_streetview_image_and_save( (midLabelPointProjected.centroid.Y, midLabelPointProjected.centroid.X), path=fileOutPath) counter += 1 row[getFIndex(fNames, featurePathField)] = fileName cursor.updateRow(row) print("Completed save of image and updated row.") except Exception as e: arcPrint( "Iteration {0} had a handling error and was skipped." .format((str(counter)))) print(e.args[0]) arcPrint("Image collection cycle completed. QAQC resulting Images.", True) if attachmentBool: arcPrint( "Attempting to attach images to feature class with Add Attachment's tool.", True) arcpy.EnableAttachments_management(inFC) arcpy.AddAttachments_management( inFC, in_match_path_field=featurePathField, in_working_folder=outDir) arcPrint("Images in directory were attached to the feature class.") arcPrint("Cleaning up intermediates.", True) del spatialRef, desc, cursor, WGS_1984_MajAux except arcpy.ExecuteError: print(arcpy.GetMessages(2)) except Exception as e: print(e.args[0])
from os import listdir #Inputs: folder with attachments, the layer to attach to, the name of the attribute field the match is based on attachments_folder = arcpy.GetParameterAsText(0) attachments_layer = arcpy.GetParameterAsText(1) #Define match field on which to base join match_field = arcpy.GetParameterAsText(2) f_id_name = arcpy.GetParameterAsText(3) #Enable Attachments arcpy.EnableAttachments_management(attachments_layer) attachments_table = attachments_folder + "\\" + "attachments_Table.csv" #Parse file names to extract unique identifier (must be separated from file name structure by an '_'), then write csv table with open(attachments_table, 'wb') as output: writer = csv.writer(output, delimiter=",") writer.writerow([str(f_id_name), 'Attachment']) for f in os.listdir(attachments_folder): file_name, file_ext = os.path.splitext(f) f_file, f_id = file_name.split('_') if str(f).find('.pdf') > -1: writer.writerow([f_id, f]) #Add attachments arcpy.AddAttachments_management(attachments_layer, match_field, attachments_table, f_id_name, "Attachment", attachments_folder)