|
POST
|
In the OP's code, he has for the expression: 'format( !HT_FT! ) + " Feet"' So, assuming the value is 5 in the field HT_FT (or another field as selected by the script's parameter), I think "5 Feet" would be the desired result. And field calculator was happy to put that value in the field. I just wasn't sure if there was a more efficient/readable way of writing the expression.
... View more
08-30-2018
11:17 PM
|
0
|
0
|
7280
|
|
POST
|
As Brittney White is suggesting, you should use the ToolValidator (Validation tab in tool's properties). See Programming a ToolValidator class and related documentation for additional information. For my test I pasted Brittney's code in the updateParameters section with no changes. For the tools Parameters, I defined them as a feature class and a string. I used the following script for my tests. The expression used in the field calculator is interesting to code (line 22 below) as you need to escape curly braces and watch your quote marks so that when the expression is passed, it has the proper values. the first .format will work with the escaped curly braces in field calculator, and the second .format will insert the field name used for the calculation. Perhaps Dan Patterson can suggest alternative ways of formatting the expression. import arcpy
from arcpy import env
import os, sys, traceback
feature = arcpy.GetParameterAsText(0)
field = arcpy.GetParameterAsText(1)
arcpy.AddMessage("Feature: {}".format(feature))
arcpy.AddMessage("Field: {}".format(field))
env.workspace = feature
# arcpy.env.overwriteOutput = True
# env.transferDomains = True
# add a new field to feature
newField = 'HT_FT_txt'
arcpy.AddField_management(feature, newField, 'TEXT', '', '', '50', 'Buffer_field', 'NULLABLE')
# calculate HT_FT_txt field
arcpy.CalculateField_management(feature, newField,
expression="'{{}} Feet'.format(!{}!)".format(field),
expression_type="PYTHON_9.3", code_block="") My version of the tool looks like the following. The red x indicates that the feature class needs to be entered. I have not checked your code for the buffer calculation.
... View more
08-30-2018
09:29 PM
|
0
|
2
|
7280
|
|
POST
|
When creating a feature service on AGOL, the fields (with or without domains) allow nulls. You can add a feature and delete the default value (ignoring the error message) and save the feature with a null value in the field. In my usual workflow, I create my feature class with desktop. For a field that uses a domain, I will set it to not allow nulls. As I recall, when I allowed domain fields to use nulls, that was a selectable option to the field crews. If a field does not allow nulls, it cannot be hidden in the view definition I wanted to create a non-editable view and hide some of the domain fields from public view. The pop-up can be configured to hide the field, but it is possible to navigate to the public view and see the values in the domains that are only hidden via the pop-up.
... View more
08-29-2018
10:06 PM
|
0
|
1
|
2947
|
|
POST
|
One way: from datetime import datetime as DT
oldDate = '2018-08-29 12:05:35'
epoch = DT(1970, 1, 1)
epoch_time = int((DT.strptime(oldDate, '%Y-%m-%d %H:%M:%S') - epoch).total_seconds())
# use '%Y-%m-%d %H:%M:%S %p' in format if using AM/PM
print epoch_time # UTC
# prints: 1535544335
... View more
08-29-2018
11:56 AM
|
1
|
0
|
1580
|
|
POST
|
If there is date information in the parent record, it can be used to rename the photo. Is this what you were thinking? Perhaps you can attach a screen shot of a popup so I understand what you want to do. Also, can an individual feature have multiple photos over several years attached to it? I have experimented with Collector and found that the current version allows you to rename attached photos: Work with attachments. This seems to work by downloading the photo to Collector, renaming the photo, and then uploading it to the same spot in the attachment file. I found the Update Attachment page in the REST API reference. When used with the Query Attachments (Feature Service/Layer), it should be possible to develop a script to rename the photos. The workflow would be something like: Log into your account and get a token Verify that the feature is set up for attachments Use query attachments to get a list of all the photos in the feature Working through the list, download each photo, examine the exif data and extract the date If a date is found, use it to rename the photo file and use update attachment to upload the renamed file to AGOL (the attachment name should pick up the new name) If no date is found in the exif data, use data from the parent table if possible to date and rename the photo.
... View more
08-26-2018
10:57 AM
|
0
|
0
|
2891
|
|
POST
|
You can see most of (perhaps all of) the information in your attachment table Foto__ATTACH. I have yet to find a way to edit the attachment table. To view the information, log into your AGOL account. At the top of the page select "Content". On the next page, under "Layers", select the layer that has your attachments. This will take you to the REST Services Directory page for your layer. At the bottom of the page, click the link "Query Attachments". (This link is only available if the layer has attachments.) The form will look like the following image. In the box "Definition Expression" enter "OBJECTID > 0". This will basically create a where clause: "where the OBJECTID of the parent table is greater than zero" and select all attachments. You can limit the attachment types to "image/jpeg" if there are other types of attachments you do not need. You should get links for the selected images which you can click and save the target. It appears that all photos are renamed to "attachment##" when Collector attaches them to the parent table. I do not know if this field can be edited. You should see the information in the attachment table for each photo, but it will not be in a table format. ID is the number of each row in the table; and there is a global ID for the attachment. You can also see the parent's ObjectID and GlobalID. The above process can be scripted in Python, although I have not done it yet. For additional information see this section in the REST API: Query Attachments (Feature Service/Layer). If you are wanting to export all photos and rename them, it may be easier to click "Export Data" option on the feature's page that shows the layers. You can save it as a file geodatabase (zipped) and work with it in desktop. This way you can work with the Foto_ATTACH table directly. I have used the following script to export and rename jpeg's from the related attachment table. import arcpy, os, exifread
masterFC = r'C:\path\to\file.gdb\parent'
masterFlds = ['GlobalID', 'OBJECTID', 'Note'] # can grab a short text field for use if needed
# Use list comprehension to build a dictionary from a da SearchCursor
masterDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(masterFC, masterFlds)}
# print masterDict
relatedTbl = r'C:\path\to\file.gdb\photo__ATTACH' # note 2 underscores in table name
relatedFlds = ['REL_GLOBALID', 'ATTACHMENTID', 'DATA', 'CONTENT_TYPE']
fileLocation = r'C:\path\to\attachments\folder'
with arcpy.da.SearchCursor(relatedTbl, relatedFlds) as cursor:
for item in cursor:
if item[3] == 'image/jpeg': # process only images
# item[0] is related GlobalID; take first item in masterDict tuple with that key
f1 = masterDict[item[0]][0] # this is the ObjectID of parent record
f2 = item[1] # this is the Attachment ID
# make new filename
filename = "ATT_{}_{}".format(f1, f2)
# print filename
# we need to write to temporary file for exifread to work
tempname = os.path.join(fileLocation, '{}.jpg'.format(filename))
f = open(tempname, 'wb').write(item[2].tobytes())
f = open(tempname, 'rb')
tags = exifread.process_file(f) # has to be a file to process
f.close()
if tags['Image DateTime'] is not None: # may need to also check length in case of error
theDate = str(tags['Image DateTime']).split(' ')[0].replace(':','')
newname = os.path.join(fileLocation, "{}_{}.jpg".format(filename, theDate))
print "ObjectID: {} \tNotes: {} \tFile: {}".format(f1, masterDict[item[0]][1], newname)
os.rename(tempname, newname) # should have unique name by using IDs from both parent and child table
else: # keep the temporary name
print "ObjectID: {} \tNotes: {} \tFile: {}".format(f1, masterDict[item[0]][1], tempname)
del cursor
del item For my test, the results were: ObjectID: 263 Notes: attachment test File: C:\attachments\ATT_263_1_20170910.jpg
ObjectID: 263 Notes: attachment test File: C:\attachments\ATT_263_2_20170910.jpg
ObjectID: 264 Notes: attach test File: C:\attachments\ATT_264_3_20170627.jpg
Please note that I have not worked with missing exif information so I don't know how exifread will respond. It should be possible to include a few lines of code to use the attachment's ID to change the filename in the attachment table.
... View more
08-25-2018
10:11 PM
|
1
|
3
|
2891
|
|
POST
|
You might try the exifread module at https://pypi.org/project/ExifRead/. Sample code would be like: import os, glob
import exifread
# info on exifread at https://pypi.org/project/ExifRead/
path = r'C:\Path\to\photo\folder'
for filename in glob.glob(os.path.join(path, '*.jpg')):
print filename
f = open(filename, 'rb') # open read only, binary
tags = exifread.process_file(f)
f.close()
print tags['Image DateTime']
newname = os.path.join(path, '{}.jpg'.format(str(tags['Image DateTime']).replace(':','-').replace(' ','_')))
os.rename(filename, newname) # assumes that all date/times are different, otherwise an error will occur You would need to add some code to deal with errors such as missing exif tags and possible duplicate dates. You may also want to adjust the date/time format in your file name, perhaps appending it to the original filename. Another option to read exif is with the pillow module; information at https://github.com/python-pillow/Pillow. You may also want to look at two arcpy tools at An overview of the Photos toolset. These tools can assist in matching photos to points or place them on a map using exif data. I will try to answer your questions about working with photos that are still online. Are you using your own server portal or are you using AGOL?
... View more
08-24-2018
10:35 PM
|
1
|
1
|
2891
|
|
POST
|
I have read some comments about the removal of exif data by Collector, but that was a while ago. Can you check whether the exif data is intact when you work with the photo in Pro? If that is the case, there must be a way to rename the file using python and exif data. Via google: Ik heb wat opmerkingen gelezen over het verwijderen van exif-gegevens door Collector, maar dat was een tijdje geleden. Kun je controleren of de exif-gegevens intact zijn als je met de foto in Pro werkt? Als dat het geval is, moet er een manier zijn om het bestand te hernoemen met behulp van python- en exif-gegevens.
... View more
08-24-2018
02:40 PM
|
0
|
1
|
2891
|
|
POST
|
Approximate translation via google: rename the photo to the date the photo was taken (exif) On Arcgis online photos are taken via the collector at various objects. They now want to be able to rename the photos via ArcgisPro to the date (and time) on which the photos were taken (info is in Exif on the photo) Is this possible via Python?
... View more
08-24-2018
02:34 PM
|
0
|
2
|
2891
|
|
POST
|
The only issue I have with views is that you cannot hide some fields (those that cannot be set to null) from sophisticated users. You can only hide the field from the map's pop-up display. It is possible for someone to navigate to the view layer for a look. I have been looking for a way to completely hide these fields: Hosted feature layer views and domains.
... View more
08-24-2018
09:48 AM
|
1
|
1
|
2100
|
|
POST
|
Here's a sample script using ideas in my previous posts: import arcpy
gdb = r"C:\Path\To\file.gdb"
arcpy.env.workspace = gdb # set environment for arcpy
# gdb domains to dictionary # # # # # # #
domDict = {} # empty dictionary
domains = arcpy.da.ListDomains(gdb)
for domain in domains:
if domain.domainType == 'CodedValue':
if domain.name not in domDict:
vList = [] # empty list
coded_values = domain.codedValues
for val, desc in coded_values.items():
vList.append({val:desc})
domDict[domain.name] = vList
# print domDict
# read feature's fields and domains information # # # # # # #
fc = 'MyFeature' # a feature in the geodatabase
fields = arcpy.ListFields(fc)
fldDict = {} # empty dictionary
for field in fields:
if len(field.domain):
fldDict[field.name] = field.domain
# print fldDict
# count values in fields with domains # # # # # # #
domCount = {}
fldList = list(fldDict.keys())
with arcpy.da.SearchCursor(fc, fldList) as rows:
for row in rows:
for i, f in enumerate(fldList):
# print i, fldList, row # index, field name, field value
if fldList[i] not in domCount:
domCount[fldList[i]] = {}
if row[i] not in domCount[fldList[i]]:
domCount[fldList[i]][row[i]] = 1
else:
domCount[fldList[i]][row[i]] += 1
del rows # release any locks
# print domCount
# output the results # # # # # # #
for k, v in domCount.iteritems():
print "Field: {}".format(k)
print " Domain: {}".format(fldDict[k])
for dLst in domDict[fldDict[k]]:
for k1, v1 in dLst.iteritems():
if k1 in v:
print " Key: {} - Description: {} - Count: {}".format(k1, v1, v[k1])
else:
print " Key: {} - Description: {} - Count: {}".format(k1, v1, 0)
# may need to add code to check for invalid codes in fields ? And my test results: Field: MyType
Domain: MyCode
Key: 1234 - Description: One - Count: 3
Key: 2345 - Description: Two - Count: 2
Key: 3456 - Description: Three - Count: 0
Key: 6789 - Description: Six - Count: 0
Key: 4567 - Description: Four - Count: 0
Key: 5678 - Description: Five - Count: 0
Key: 7890 - Description: Seven - Count: 1
Field: MyColor
Domain: MyColor
Key: Y - Description: Yellow - Count: 1
Key: P - Description: Purple - Count: 0
Key: B - Description: Blue - Count: 1
Key: R - Description: Red - Count: 2
Key: G - Description: Green - Count: 2
... View more
08-23-2018
09:51 PM
|
1
|
0
|
2357
|
|
POST
|
And in place of TableToDomain/DomainToTable, see ListDomains on how to get a list of domains and coded/max/min values. You can use something like ListFields to get the domain name a field uses (field.domain).
... View more
08-23-2018
02:34 PM
|
0
|
1
|
2357
|
|
POST
|
Similar to Forest's approach, I would load the feature's field with the domains you are interested in into a dictionary using code such as: import arcpy
fc = <your feature>
field = <domain field>
d = {}
with arcpy.da.SearchCursor(fc, (field)) as rows:
for row in rows:
if row[0] not in d:
d[row[0]] = 1
else:
d[row[0]] += 1
for k, v in d.iteritems():
# something like if k not in domainTable ....
# or if domainTable[value] not in d.keys() ... And then you can compare with the table to domain information. This would also count the number of rows with specific values.
... View more
08-23-2018
11:47 AM
|
1
|
2
|
2357
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 10-27-2016 02:23 PM | |
| 1 | 09-09-2017 08:27 PM | |
| 2 | 08-20-2020 06:15 PM | |
| 1 | 10-21-2021 09:15 PM | |
| 1 | 07-19-2018 12:33 PM |
| Online Status |
Offline
|
| Date Last Visited |
02-12-2026
07:13 PM
|