1

I have a time that indicates a ship was detected at a certain point. I want to go through a list of the tracks of ships in the area(id'ed by their mmsi) and find the closest time right before the detection time and after the detection for each ship. This will help me ID which ship in the area was responsible for that detection at that time. The problem I have though is that I don't know how to find the closest time points.

import arcpy, os, datetime
arcpy.env.overwriteOutput = True

Source_File = "L:\\gathr\\indonesia\\Sara\\SAISData\\AAAS\\SAIS2.gdb\\AIS_Jan2016_CorrectTIme"
field = "mmsi"
mmsi_List = [row[0] for row in arcpy.da.SearchCursor(Source_File,"mmsi")]
mmsi_List1 = [x.encode('UTF8') for x in mmmsi_List]
UniqueMmsi = set(mmsi_List1)
UniqueMmsi_List = list(UniqueMmsi)
print UniqueMmsi_List
for mmsi_query in UniqueMmsi_List:
    out_layer = str(mmsi_query)
    in_features = "L:\\gathr\\indonesia\\Sara\\SAISData\\AAAS\\SAIS2.gdb\\AIS_Jan2016_CorrectTIme"
    #need 2 where clauses, one for the closest time before the detection time
    #and the other for the closest time after the detection time
    where_clause1 =???????????
    where_str1 = str(where_clause1)
    arcpy.MakeFeatureLayer_management(in_features, out_layer)
    arcpy.SelectLayerByAttribute_management(out_layer, "NEW_SELECTION", where1_str)
0

Here's an example with times and bisect that might be useful:

import datetime,bisect

# Here's times for the current ship, note they are sorted ascending
times =  [datetime.datetime(2016, 10, 7, 13, 44, 34),
          datetime.datetime(2016, 10, 7, 14, 24, 10),
          datetime.datetime(2016, 10, 7, 14, 59, 28),
          datetime.datetime(2016, 10, 7, 15, 53, 17),
          datetime.datetime(2016, 10, 7, 16, 27, 14),
          datetime.datetime(2016, 10, 7, 16, 55, 21),
          datetime.datetime(2016, 10, 7, 16, 57, 2),
          datetime.datetime(2016, 10, 7, 18, 0, 19)]

# The incident occured at 3pm
incident = datetime.datetime(2016, 10, 7, 15, 0, 0)

# If this time were to be inserted, where would it be placed?
i = bisect.bisect(times, incident)

# max and min take care of start and end of list, respectively
start = times[(max(0, i-1))]
end = times[min(len(times)-1, i)]

# FGDB-style date query
startTime = "date '{}'".format(datetime.datetime.strftime(start, "%Y-%m-%d %H:%M:%S"))
endTime = "date '{}'".format(datetime.datetime.strftime(end, "%Y-%m-%d %H:%M:%S"))

# SQL Query
query = "mmsi = {} AND dateField IN ({}, {})".format(1, startTime, endTime)

>>>query
mmsi = 1 AND dateField IN (date '2016-10-07 14:59:28', date '2016-10-07 15:53:17')

Applying this to your sample code then (untested):

from collections import defaultdict    

# This dictionary is the form {mmsi_1 : [time_1, time_2, time_n], mmsi_2 : [...]}
mmsiTimes = defaultdict(list)
for row in arcpy.da.SearchCursor(Source_File, ["mmsi", "dateField"]):
    mmsiTimes[row[0].encode('UTF8')].append(row[1])


incident = None # your incident time here

print mmsiTimes.keys()
for mmsi, shipTimes in mmsiTimes.iteritems():
    shipTimes.sort()
    i = bisect.bisect(shipTimes, incident)
    start = shipTimes[(max(0, i-1))]
    end = shipTimes[min(len(times)-1, i)]
    startTime = "date '{}'".format(datetime.datetime.strftime(start, "%Y-%m-%d %H:%M:%S"))
    endTime = "date '{}'".format(datetime.datetime.strftime(end, "%Y-%m-%d %H:%M:%S"))
    query = "mmsi = {} AND dateField IN ({}, {})".format(mmsi, startTime, endTime)

    arcpy.MakeFeatureLayer_management(in_features, out_layer, query)
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.