Issue with spatially assigning assignments in Notebooks

648
6
10-05-2020 05:52 PM
by Anonymous User
Not applicable

So I've been using Notebooks in ArcOnline to do some batch assignments for a Workforce project. Quick run down of the project: Fire Dept needs to do bi annually inspections on every business in the city. I've built a survey in survey123 that'll handle all the questions. They'll use Workforce to dispatch their people to the locations. This is decided by fire station areas. I'd like to automate creating these assignments by the station area polygons so we dont have to do it by hand twice a year. 

I have their dispatch polygons hosted on arconline but can't seem to get the script to work. Here's what it looks like, it's 100% modelled off the template on github:

conda install -c esri/label/prerelease -c esri arcgis==1.8.3

conda update -n base -c defaults conda

from datetime import datetime
from arcgis.gis import GIS
from arcgis.geometry import Geometry
from arcgis.mapping import WebMap
from arcgis.apps import workforce
from datetime import datetime

gis = GIS("home")
item = gis.content.get("afca01f6dda742e69896412da860b924")
project = workforce.Project(item)

# Get Layer of City Districts

fireInspectionDistricts_layer = gis.content.get("0afccc9e48c3471f8bfc1954f4602c23").layers[0]
fireInspectionDistricts_map = gis.map("Thornton, CO", zoomlevel=10)
fireInspectionDistricts_map.add_layer(fireInspectionDistricts_layer)
fireInspectionDistricts_map

# Add Assignments to the Map

fireInspectionDistricts_map.add_layer(project.assignments_layer)


# Create a spatially enabled dataframe of the districts

fireInspectionDistricts_df = fireInspectionDistricts_layer.query(as_df=True)
print (fireInspectionDistricts_df)
#   OBJECTID ZONE  UNIT STATION   SHAPE_Length    SHAPE_Area  \
#0         1    6  None    None  169552.086294  4.020346e+08   
#1         2    2  None    None   64910.441381  7.760154e+07   
#2         3    1  None    None   49842.642184  8.343908e+07   
#3         4    3  None    None  143750.130571  2.249331e+08   
#4         5    4  None    None   57284.309928  1.412634e+08   
#5         6    5  None    None  129542.914257  3.418221e+08 

# Get all of the unassigned assignments

assignments = project.assignments.search("status=0")


# Assign Assignments Based on Which District They Intersect¶


tyler = project.workers.get(user_id="Tyler.Dunn@XXXXXX")
brandi = project.workers.get(user_id="Brandi.Rank@XXXXXXX")
for assignment in assignments:
    contains = fireInspectionDistricts_df["SHAPE"].geom.contains(Geometry(assignment.geometry))
    print (contains)
    #0    False
    #1    False
    #2    False
    #3    False
    #4    False
    #5    False
    #Name: contains, dtype: bool   
    containers = fireInspectionDistricts_df[contains]
    print (containers)
    #Empty DataFrame
    #Columns: [OBJECTID, ZONE, UNIT, STATION, SHAPE_Length, SHAPE_Area, SHAPE]
    #Index: []

    if not containers.empty:
        fireInspectionDistrict = containers['ZONE'].iloc[0]
        if fireInspectionDistrict == 4:
            assignment.worker = tyler
            assignment.status = "assigned"
            assignment.assigned_date = datetime.utcnow()
        elif fireInspectionDistrict == 2:
            assignment.worker = brandi
            assignment.status = "assigned"
            assignment.assigned_date = datetime.utcnow()     
assignments = project.assignments.batch_update(assignments)

# Verify Assignments are Assigned

webmap = gis.map("Thornton, CO", zoomlevel=11)
webmap.add_layer(project.assignments_layer)
webmap

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍



One of my concerns is that the results of containers is returning and empty dataframe and empty index. 
Not sure if that's part of the issue, but at this point I've hit a brick wall. 

Any suggestions?
0 Kudos
6 Replies
by Anonymous User
Not applicable

Hi Tyler,

So it appears that the issue is with the contains operation. It is returning False which is then causing the dataframe to select nothing (resulting in an empty dataframe). A couple things you could try:

1. Check the spatial reference of the fire inspection districts layer. If it's not web-mercator, then you may need to explicitly set out_sr=102100 in the query on line 28. The workforce layer is also using web-mercator.

2. Try running the same notebook outside the AGOL hosted notebook environment (e.g. on your own local machine).

0 Kudos
by Anonymous User
Not applicable

Alright so the out_sr worked, this is now what's printed for contains:

0    False 1    False 2    False 3    False 4    False 5     True Name: contains, dtype: bool

and printed for containers:

                                               SHAPE   5  {"rings": [[[-11677745.002824906, 4853496.4840...      OBJECTID ZONE  UNIT STATION   SHAPE_Length    SHAPE_Area  \ 5         6    5  None    None  129542.914257  3.418221e+08 

Now it's not committing the information to the assignments. When I look at the workforce project or the map that's called in the script, nothing has been updated. Any guesses?

0 Kudos
by Anonymous User
Not applicable

It should always be updating the assignments. I'm guessing it's something with the if/else not working for your zones. Can you print out the fireInspectionDistrict?

0 Kudos
by Anonymous User
Not applicable
#tyler = project.workers.get(name="Tyler Dunn")
tyler = project.workers.get(user_id="Tyler.Dunn@thorntonco.gov_cityofthornton")
brandi = project.workers.get(user_id="Brandi.Rank@thorntonco.gov_cityofthornton")
#print (tyler)
#print (brandi)
for assignment in assignments:
    contains = fireInspectionDistricts_df["SHAPE"].geom.contains(Geometry(assignment.geometry))
    #print (assignment.geometry)
    #print (contains)
    #0    False
    #1    False
    #2    False
    #3    False
    #4    False
    #5     True
    #Name: contains, dtype: bool
    #print (assignments)
    #print (fireInspectionDistricts_df)
    containers = fireInspectionDistricts_df[contains]
    #print (containers)
    #OBJECTID ZONE  UNIT STATION   SHAPE_Length    SHAPE_Area  \
    #5         6    5  None    None  129542.914257  3.418221e+08  
    #print (fireInspectionDistricts_df)

    if not containers.empty:
        fireInspectionDistrict = containers["ZONE"].iloc[0]
        print (fireInspectionDistrict)
        if fireInspectionDistrict == 4:
            assignment.worker = tyler
            assignment.status = "assigned"
            assignment.assigned_date = datetime.utcnow()
        elif fireInspectionDistrict == 2:
            assignment.worker = brandi
            assignment.update.status = "assigned"
            assignment.assigned_date = datetime.utcnow()
assignments = project.assignments.batch_update(assignments)

Prints a bunch like this:

5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 Kudos
by Anonymous User
Not applicable

Okay, yeah so you need to change line 28 and 32 to use 5 and 1 in order for those assignments to be assigned to tyler and brandi. Currently, it's not assigning it to anyone.

0 Kudos
by Anonymous User
Not applicable

So it ended up being that the ZONE field is a String data type. I created another field ZONE_INT as an integer and it worked. 

Thanks for all the help

0 Kudos