Exemple #1
0
def trajectory_from_dictionary(dictionary):
    """Returns a trajectory constructed from the given dictionary.
    Args:
       dictionary: the dictionary to convert into a trajectory
    """

    #verify domain is valid and import appropriate domain
    try:
        domain = importlib.import_module("tracktable.domain."+
                                         dictionary['domain'].lower())
    except ImportError:
        raise ValueError("Error: invalid domain name: "+dictionary['domain'].lower())

    dimension = domain.DIMENSION

    #verify each coordinate matches dimension
    points = []
    numPoints = len(dictionary['coordinates'])
    for point in dictionary['coordinates']:
        if len(point) != dimension:
            raise ValueError("Error: point " + str(point) + " has "+ str(len(point)) + " coordinate(s), expected " + str(dimension)+".")

    #verify point properties values lists are of equal length
    for (name, attributes) in dictionary['point_properties'].items():
        if len(attributes['values']) != numPoints:
            raise ValueError("Error: "+name+" property has only " + str(len(attributes['values'])) + " values, but there are " + str(numPoints) + " points in the trajectory.")

    #verify there are the right number of timestamps
    if len(dictionary['timestamps']) != numPoints:
        raise ValueError("Error: Only " + str(len(dictionary['timestamps'])) + " timestamp values, but there are " + str(numPoints) + " points in the trajectory.")

    #verify object_id is a string
    if not isinstance(dictionary['object_id'], str):
        raise ValueError("Error: object_id must be a string, but got a value of type "+type(dictionary['object_id']).__name__)

    #generate points / position list
    for i in range(numPoints):
        point = domain.TrajectoryPoint(dictionary['coordinates'][i])
        point.object_id = dictionary['object_id']
        point.timestamp = Timestamp.from_string(dictionary['timestamps'][i])
        for (name, attributes) in dictionary['point_properties'].items():
            if attributes['type'] == "datetime" or attributes['type'] == "timestamp":  #okay to support both?  todo
                point.set_property(name, Timestamp.from_string(attributes['values'][i], format_string='%Y-%m-%d %H:%M:%S'))
            else:
                point.set_property(name, attributes['values'][i])
        points.append(point)

    #make trajectory
    trajectory = domain.Trajectory.from_position_list(points)

    #add trajectory properties
    for (name, attributes) in dictionary['trajectory_properties'].items():
        if attributes['type'] == "datetime" or attributes['type'] == "timestamp":  #okay to support both?  todo
            trajectory.set_property(name, Timestamp.from_string(attributes['value'], format_string='%Y-%m-%d %H:%M:%S'))
        else:
            trajectory.set_property(name, attributes['value'])

    return trajectory
    def test_no_time_zone_iso(self):
        timestring = '2014-12-25T13:12:45'
        parsed_timestamp = Timestamp.from_string(timestring)
        constructed_timestamp = datetime(2014, 12, 25,
                                         hour=13, minute=12, second=45,
                                         tzinfo=pytz.utc)

        self.assertTrue(parsed_timestamp.tzinfo is not None)
        self.assertTrue(parsed_timestamp == constructed_timestamp)
    def test_with_time_zone_iso(self):
        timestring = '2014-12-25T10:12:45-0300'
        parsed_timestamp = Timestamp.from_string(
            timestring,
            format_string='%Y-%m-%dT%H:%M:%S%z')
        constructed_timestamp = datetime(2014, 12, 25,
                                         hour=13, minute=12, second=45,
                                         tzinfo=pytz.utc)

        self.assertTrue(parsed_timestamp.tzinfo is not None)
        self.assertTrue(parsed_timestamp == constructed_timestamp)
Exemple #4
0
    def gen_json_and_trajectory(self):
        domain = tracktable.domain.terrestrial
        json = "{\"coordinates\": [[26.995, -81.9731], [27.0447, -81.9844], [27.1136, -82.0458]], \"domain\": \"terrestrial\", \"object_id\": \"AAA001\", \"point_properties\": {\"altitude\": {\"type\": \"int\", \"values\": [2700, 4200, 6700]}, \"heading\": {\"type\": \"float\", \"values\": [108.1, 108.2, 225.3]}, \"note\": {\"type\": \"str\", \"values\": [\"hello\", \"world\", \"!\"]}, \"time2\": {\"type\": \"datetime\", \"values\": [\"2004-01-01 00:00:01\", \"2004-01-01 00:00:02\", \"2004-01-01 00:00:03\"]}}, \"timestamps\": [\"2004-12-07 11:36:18\", \"2004-12-07 11:37:56\", \"2004-12-07 11:39:18\"], \"trajectory_properties\": {\"percent\": {\"type\": \"float\", \"value\": 33.333}, \"platform\": {\"type\": \"str\", \"value\": \"Boeing 747\"}, \"start\": {\"type\": \"datetime\", \"value\": \"2004-12-07 11:36:00\"}, \"tailNum\": {\"type\": \"int\", \"value\": 3878}}}"

        # Manually set up a matching Trajectory object
        p1 = domain.TrajectoryPoint()
        p1[0] = 26.995
        if domain.DIMENSION > 1:
            p1[1] = -81.9731
        if domain.DIMENSION > 2:
            p1[2] = -100.0
        p1.set_property('altitude', 2700)
        p1.set_property('heading', 108.1)
        p1.set_property('note', "hello")
        p1.set_property('time2', Timestamp.from_string('2004-01-01 00:00:01'))
        p1.object_id = 'AAA001'
        p1.timestamp = Timestamp.from_string('2004-12-07 11:36:18',
                                             format_string='%Y-%m-%d %H:%M:%S')

        p2 = domain.TrajectoryPoint()
        p2[0] = 27.0447
        if domain.DIMENSION > 1:
            p2[1] = -81.9844
        if domain.DIMENSION > 2:
            p2[2] = -101.0
        p2.set_property('altitude', 4200)
        p2.set_property('heading', 108.2)
        p2.set_property('note', "world")
        p2.set_property('time2', Timestamp.from_string('2004-01-01 00:00:02'))
        p2.object_id = 'AAA001'
        p2.timestamp = Timestamp.from_string('2004-12-07 11:37:56',
                                             format_string='%Y-%m-%d %H:%M:%S')

        p3 = domain.TrajectoryPoint()
        p3[0] = 27.1136
        if domain.DIMENSION > 1:
            p3[1] = -82.0458
        if domain.DIMENSION > 2:
            p3[2] = -102.0
        p3.set_property('altitude', 6700)
        p3.set_property('heading', 225.3)
        p3.set_property('note', "!")
        p3.set_property('time2', Timestamp.from_string('2004-01-01 00:00:03'))
        p3.object_id = 'AAA001'
        p3.timestamp = Timestamp.from_string('2004-12-07 11:39:18',
                                             format_string='%Y-%m-%d %H:%M:%S')

        trajectory = domain.Trajectory.from_position_list([p1, p2, p3])
        trajectory.set_property('percent', 33.333)
        trajectory.set_property('platform', "Boeing 747")
        trajectory.set_property('start',
                                Timestamp.from_string('2004-12-07 11:36:00'))
        trajectory.set_property('tailNum', 3878)

        return json, trajectory
    def test_no_time_zone_iso(self):
        timestring = '2014-12-25T13:12:45'
        parsed_timestamp = Timestamp.from_string(timestring)
        constructed_timestamp = datetime(2014,
                                         12,
                                         25,
                                         hour=13,
                                         minute=12,
                                         second=45,
                                         tzinfo=pytz.utc)

        self.assertTrue(parsed_timestamp.tzinfo is not None)
        self.assertTrue(parsed_timestamp == constructed_timestamp)
Exemple #6
0
    def test_with_time_zone_iso(self):
        timestring = '2014-12-25T10:12:45-0300'
        parsed_timestamp = Timestamp.from_string(
            timestring, format_string='%Y-%m-%dT%H:%M:%S%z')
        constructed_timestamp = datetime(2014,
                                         12,
                                         25,
                                         hour=13,
                                         minute=12,
                                         second=45,
                                         tzinfo=pytz.utc)

        self.assertTrue(parsed_timestamp.tzinfo is not None)
        self.assertTrue(parsed_timestamp == constructed_timestamp)
    def gen_json_and_trajectory(self):
        domain = tracktable.domain.terrestrial
        json = "{\"coordinates\": [[26.995, -81.9731], [27.0447, -81.9844], [27.1136, -82.0458]], \"domain\": \"terrestrial\", \"object_id\": \"AAA001\", \"point_properties\": {\"altitude\": {\"type\": \"int\", \"values\": [2700, 4200, 6700]}, \"heading\": {\"type\": \"float\", \"values\": [108.1, 108.2, 225.3]}, \"note\": {\"type\": \"str\", \"values\": [\"hello\", \"world\", \"!\"]}, \"time2\": {\"type\": \"datetime\", \"values\": [\"2004-01-01 00:00:01\", \"2004-01-01 00:00:02\", \"2004-01-01 00:00:03\"]}}, \"timestamps\": [\"2004-12-07 11:36:18\", \"2004-12-07 11:37:56\", \"2004-12-07 11:39:18\"], \"trajectory_properties\": {\"percent\": {\"type\": \"float\", \"value\": 33.333}, \"platform\": {\"type\": \"str\", \"value\": \"Boeing 747\"}, \"start\": {\"type\": \"datetime\", \"value\": \"2004-12-07 11:36:00\"}, \"tailNum\": {\"type\": \"int\", \"value\": 3878}}}"

        # Manually set up a matching Trajectory object
        p1 = domain.TrajectoryPoint()
        p1[0] = 26.995;
        if domain.DIMENSION > 1:
            p1[1] = -81.9731
        if domain.DIMENSION > 2:
            p1[2] = -100.0
        p1.set_property('altitude', 2700)
        p1.set_property('heading', 108.1)
        p1.set_property('note', "hello")
        p1.set_property('time2', Timestamp.from_string('2004-01-01 00:00:01'))
        p1.object_id = 'AAA001'
        p1.timestamp = Timestamp.from_string('2004-12-07 11:36:18', format_string='%Y-%m-%d %H:%M:%S')

        p2 = domain.TrajectoryPoint()
        p2[0] = 27.0447;
        if domain.DIMENSION > 1:
            p2[1] = -81.9844
        if domain.DIMENSION > 2:
            p2[2] = -101.0
        p2.set_property('altitude', 4200)
        p2.set_property('heading', 108.2)
        p2.set_property('note', "world")
        p2.set_property('time2', Timestamp.from_string('2004-01-01 00:00:02'))
        p2.object_id = 'AAA001'
        p2.timestamp = Timestamp.from_string('2004-12-07 11:37:56', format_string='%Y-%m-%d %H:%M:%S')

        p3 = domain.TrajectoryPoint()
        p3[0] = 27.1136;
        if domain.DIMENSION > 1:
            p3[1] = -82.0458
        if domain.DIMENSION > 2:
            p3[2] = -102.0
        p3.set_property('altitude', 6700)
        p3.set_property('heading', 225.3)
        p3.set_property('note', "!")
        p3.set_property('time2', Timestamp.from_string('2004-01-01 00:00:03'))
        p3.object_id = 'AAA001'
        p3.timestamp = Timestamp.from_string('2004-12-07 11:39:18', format_string='%Y-%m-%d %H:%M:%S')

        trajectory = domain.Trajectory.from_position_list([p1,p2,p3])
        trajectory.set_property('percent', 33.333)
        trajectory.set_property('platform', "Boeing 747")
        trajectory.set_property('start', Timestamp.from_string('2004-12-07 11:36:00'))
        trajectory.set_property('tailNum', 3878)

        return json, trajectory
    def test_with_time_zone_iso(self):
        if sys.version_info[0] == 3:
            timestring = '2014-12-25T10:12:45-0300'
            parsed_timestamp = Timestamp.from_string(
                timestring, format_string='%Y-%m-%dT%H:%M:%S%z')
            constructed_timestamp = datetime(2014,
                                             12,
                                             25,
                                             hour=13,
                                             minute=12,
                                             second=45,
                                             tzinfo=pytz.utc)

            self.assertTrue(parsed_timestamp.tzinfo is not None)
            self.assertTrue(parsed_timestamp == constructed_timestamp)
        else:
            print("Time zone parsing is only supported in Python 3")
            self.assertTrue(True)
    def gen_dictionary_and_trajectory(self, domainString):
        domain = importlib.import_module("tracktable.domain." +
                                         domainString.lower())

        # Manually set up a dictionary which contains trajectory info
        dictionary = {
            'domain':
            domainString.lower(),
            'object_id':
            'AAA001',
            'trajectory_properties': {
                'percent': {
                    'type': 'float',
                    'value': 33.333
                },
                'platform': {
                    'type': 'str',
                    'value': "Boeing 747"
                },
                'start': {
                    'type': 'datetime',
                    'value': "2004-12-07 11:36:00"
                },
                'tailNum': {
                    'type': 'str',
                    'value': '3878'
                }
            },
            'timestamps': [
                '2004-12-07 11:36:18', '2004-12-07 11:37:56',
                '2004-12-07 11:39:18'
            ],
            'point_properties': {
                'altitude': {
                    'type': 'float',
                    'values': [2700, 4200, 6700]
                },
                'heading': {
                    'type': 'float',
                    'values': [108.1, 108.2, 225.3]
                },
                'note': {
                    'type': 'str',
                    'values': ["hello", "world", "!"]
                },
                'time2': {
                    'type':
                    'datetime',
                    'values': [
                        "2004-01-01 00:00:01", "2004-01-01 00:00:02",
                        "2004-01-01 00:00:03"
                    ]
                }
            }
        }
        if domain.DIMENSION == 1:
            dictionary.update(
                {'coordinates': [(26.995), (27.0447), (27.1136)]})
        if domain.DIMENSION == 2:
            dictionary.update({
                'coordinates': [(26.995, -81.9731), (27.0447, -81.9844),
                                (27.1136, -82.0458)]
            })
        if domain.DIMENSION == 3:
            dictionary.update({
                'coordinates': [(26.995, -81.9731, -100.0),
                                (27.0447, -81.9844, -101.0),
                                (27.1136, -82.0458, -102.0)]
            })

        # Manually set up a matching Trajectory object
        p1 = domain.TrajectoryPoint()
        p1[0] = 26.995
        if domain.DIMENSION > 1:
            p1[1] = -81.9731
        if domain.DIMENSION > 2:
            p1[2] = -100.0
        p1.set_property('altitude', 2700)
        p1.set_property('heading', 108.1)
        p1.set_property('note', "hello")
        p1.set_property('time2', Timestamp.from_string('2004-01-01 00:00:01'))
        p1.object_id = 'AAA001'
        p1.timestamp = Timestamp.from_string('2004-12-07 11:36:18',
                                             format_string='%Y-%m-%d %H:%M:%S')

        p2 = domain.TrajectoryPoint()
        p2[0] = 27.0447
        if domain.DIMENSION > 1:
            p2[1] = -81.9844
        if domain.DIMENSION > 2:
            p2[2] = -101.0
        p2.set_property('altitude', 4200)
        p2.set_property('heading', 108.2)
        p2.set_property('note', "world")
        p2.set_property('time2', Timestamp.from_string('2004-01-01 00:00:02'))
        p2.object_id = 'AAA001'
        p2.timestamp = Timestamp.from_string('2004-12-07 11:37:56',
                                             format_string='%Y-%m-%d %H:%M:%S')

        p3 = domain.TrajectoryPoint()
        p3[0] = 27.1136
        if domain.DIMENSION > 1:
            p3[1] = -82.0458
        if domain.DIMENSION > 2:
            p3[2] = -102.0
        p3.set_property('altitude', 6700)
        p3.set_property('heading', 225.3)
        p3.set_property('note', "!")
        p3.set_property('time2', Timestamp.from_string('2004-01-01 00:00:03'))
        p3.object_id = 'AAA001'
        p3.timestamp = Timestamp.from_string('2004-12-07 11:39:18',
                                             format_string='%Y-%m-%d %H:%M:%S')

        trajectory = domain.Trajectory.from_position_list([p1, p2, p3])
        trajectory.set_property('percent', 33.333)
        trajectory.set_property('platform', "Boeing 747")
        trajectory.set_property('start',
                                Timestamp.from_string('2004-12-07 11:36:00'))
        trajectory.set_property('tailNum', '3878')

        return dictionary, trajectory
    def gen_dictionary_and_trajectory(self, domainString):
        domain = importlib.import_module("tracktable.domain."+domainString.lower())

        # Manually set up a dictionary which contains trajectory info
        dictionary = {'domain'                : domainString.lower(),
                      'object_id'             : 'AAA001',
                      'trajectory_properties' : {'percent' : {'type': 'float',    'value': 33.333},
                                                 'platform': {'type': 'str',      'value': "Boeing 747"},
                                                 'start'   : {'type': 'datetime', 'value': "2004-12-07 11:36:00"},
                                                 'tailNum' : {'type': 'int',      'value': 3878}},
                      'timestamps'            : ['2004-12-07 11:36:18',#-0000',
                                                 '2004-12-07 11:37:56',#-0000',
                                                 '2004-12-07 11:39:18'],#-0000'],
                      'point_properties'      : {'altitude': {'type': 'int',      'values': [2700, 4200, 6700]},
                                                 'heading' : {'type': 'float',    'values': [108.1, 108.2, 225.3]},
                                                 'note'    : {'type': 'str',      'values': ["hello", "world", "!"]},
                                                 'time2'   : {'type': 'datetime', 'values': ["2004-01-01 00:00:01",
                                                                                             "2004-01-01 00:00:02",
                                                                                             "2004-01-01 00:00:03"]} }
        }
        if domain.DIMENSION == 1:
            dictionary.update({'coordinates' : [(26.995), (27.0447), (27.1136)]})
        if domain.DIMENSION == 2:
            dictionary.update({'coordinates' : [(26.995, -81.9731), (27.0447, -81.9844), (27.1136, -82.0458)]})
        if domain.DIMENSION == 3:
            dictionary.update({'coordinates' : [(26.995, -81.9731, -100.0), (27.0447, -81.9844, -101.0), (27.1136, -82.0458, -102.0)]})

        # Manually set up a matching Trajectory object
        p1 = domain.TrajectoryPoint()
        p1[0] = 26.995;
        if domain.DIMENSION > 1:
            p1[1] = -81.9731
        if domain.DIMENSION > 2:
            p1[2] = -100.0
        p1.set_property('altitude', 2700)
        p1.set_property('heading', 108.1)
        p1.set_property('note', "hello")
        p1.set_property('time2', Timestamp.from_string('2004-01-01 00:00:01'))
        p1.object_id = 'AAA001'
        p1.timestamp = Timestamp.from_string('2004-12-07 11:36:18', format_string='%Y-%m-%d %H:%M:%S')

        p2 = domain.TrajectoryPoint()
        p2[0] = 27.0447;
        if domain.DIMENSION > 1:
            p2[1] = -81.9844
        if domain.DIMENSION > 2:
            p2[2] = -101.0
        p2.set_property('altitude', 4200)
        p2.set_property('heading', 108.2)
        p2.set_property('note', "world")
        p2.set_property('time2', Timestamp.from_string('2004-01-01 00:00:02'))
        p2.object_id = 'AAA001'
        p2.timestamp = Timestamp.from_string('2004-12-07 11:37:56', format_string='%Y-%m-%d %H:%M:%S')

        p3 = domain.TrajectoryPoint()
        p3[0] = 27.1136;
        if domain.DIMENSION > 1:
            p3[1] = -82.0458
        if domain.DIMENSION > 2:
            p3[2] = -102.0
        p3.set_property('altitude', 6700)
        p3.set_property('heading', 225.3)
        p3.set_property('note', "!")
        p3.set_property('time2', Timestamp.from_string('2004-01-01 00:00:03'))
        p3.object_id = 'AAA001'
        p3.timestamp = Timestamp.from_string('2004-12-07 11:39:18', format_string='%Y-%m-%d %H:%M:%S')

        trajectory = domain.Trajectory.from_position_list([p1,p2,p3])
        trajectory.set_property('percent', 33.333)
        trajectory.set_property('platform', "Boeing 747")
        trajectory.set_property('start', Timestamp.from_string('2004-12-07 11:36:00'))
        trajectory.set_property('tailNum', 3878)

        return dictionary, trajectory
def run_test():
    # Define three sets of points: ABQ to San Diego, San Diego to
    # Seattle, Denver to NYC.  ABQ->SAN->SEA should break into two
    # trajectories because of a timestamp break in San Diego.  The
    # flight to Denver will begin right when the flight to Seattle
    # ends so we expect to break that one based on the distance
    # threshold.

    print("Beginning run_test()")

    from tracktable.domain.terrestrial import TrajectoryPoint

    albuquerque = TrajectoryPoint( -106.5, 35.25 )
    albuquerque.timestamp = Timestamp.from_string('2010-01-01 12:00:00')
    albuquerque.object_id = 'flight1'

    san_diego1 = TrajectoryPoint( -117.16, 32.67 )
    san_diego1.timestamp = Timestamp.from_string('2010-01-01 15:00:00')
    san_diego1.object_id = 'flight1'

    san_diego2 = TrajectoryPoint( -117.16, 32.67 )
    san_diego2.timestamp = Timestamp.from_string('2010-01-01 16:00:00')
    san_diego2.object_id = 'flight1'

    seattle = TrajectoryPoint( -122.31, 47.60 )
    seattle.timestamp = Timestamp.from_string('2010-01-01 19:00:00')
    seattle.object_id = 'flight1'

    denver = TrajectoryPoint( -104.98, 39.79 )
    denver.timestamp = Timestamp.from_string('2010-01-01 19:01:00')
    denver.object_id = 'flight1'

    new_york = TrajectoryPoint( -74.02, 40.71 )
    new_york.timestamp = Timestamp.from_string('2010-01-02 00:00:00')
    new_york.object_id = 'flight1'

    # Now we want sequences of points for each flight.
    abq_to_sd = TrajectoryPointSource()
    abq_to_sd.start_point = albuquerque
    abq_to_sd.end_point = san_diego1
    abq_to_sd.num_points = 180

    sd_to_sea = TrajectoryPointSource()
    sd_to_sea.start_point = san_diego2
    sd_to_sea.end_point = seattle
    sd_to_sea.num_points = 360 # flying very slowly

    denver_to_nyc = TrajectoryPointSource()
    denver_to_nyc.start_point = denver
    denver_to_nyc.end_point = new_york
    denver_to_nyc.num_points = 600 # wow, very densely sampled

    print("Done creating point sources")

    all_points = list(itertools.chain( abq_to_sd.points(),
                                       sd_to_sea.points(),
                                       denver_to_nyc.points() ))

    trajectory_assembler = AssembleTrajectoryFromPoints()
    trajectory_assembler.input = all_points
    trajectory_assembler.separation_time = timedelta(minutes=30)
    trajectory_assembler.separation_distance = 100 
    trajectory_assembler_minimum_length = 10

    print("Done instantiating assembler")

    all_trajectories = list(trajectory_assembler.trajectories())
    print("Assembler statistics: {} points, {} valid trajectories, {} invalid trajectories".format(
        trajectory_assembler.valid_trajectory_count,
        trajectory_assembler.invalid_trajectory_count,
        trajectory_assembler.points_processed_count
        ))

    print("Done creating trajectories.  Found {}.".format(len(all_trajectories)))

    test_point_proximity = geomath.sanity_check_distance_less_than(1)
    def test_timestamp_proximity(time1, time2):
        return ( (time2 - time1).total_seconds() < 1 )

    error_count = 0
    if len(all_trajectories) != 3:
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected 3 trajectories but got {}\n'.format(len(all_trajectories)))
        error_count += 1

    if not test_point_proximity(all_trajectories[0][0], albuquerque):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected point 0 of first trajectory to be Albuquerque ({}) but it is instead {}\n'.format(albuquerque, str(all_trajectories[0][0])))
        error_count += 1

    if not test_point_proximity(all_trajectories[0][-1], san_diego1):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected last point of first trajectory to be San Diego ({}) but it is instead {}\n'.format(san_diego, str(all_trajectories[0][-1])))
        error_count += 1

    if not test_point_proximity(all_trajectories[1][0], san_diego2):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected point 0 of second trajectory to be San Diego ({}) but it is instead {}\n'.format(san_diego, str(all_trajectories[1][0])))
        error_count += 1

    if not test_point_proximity(all_trajectories[1][-1], seattle):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected last point of second trajectory to be Seattle ({}) but it is instead {}\n'.format(seattle, str(all_trajectories[1][-1])))
        error_count += 1

    if not test_point_proximity(all_trajectories[2][0], denver):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected first point of third trajectory to be Denver ({}) but it is instead {}\n'.format(denver, str(all_trajectories[2][0])))
        error_count += 1

    if not test_point_proximity(all_trajectories[2][-1], new_york):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected last point of third trajectory to be New York ({}) but it is instead {}\n'.format(new_york, str(all_trajectories[2][-1])))
        error_count += 1

    if not test_timestamp_proximity(all_trajectories[0][0].timestamp, albuquerque.timestamp):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected timestamp at beginning of trajectory 0 to be {} but it is instead {}\n'.format(albuquerque.timestamp, all_trajectories[0][0].timestamp))
        error_count += 1

    if not test_timestamp_proximity(all_trajectories[0][-1].timestamp, san_diego1.timestamp):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected timestamp at end of trajectory 0 to be {} but it is instead {}\n'.format(san_diego1.timestamp, all_trajectories[0][-1].timestamp))
        error_count += 1

    if not test_timestamp_proximity(all_trajectories[1][0].timestamp, san_diego2.timestamp):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected timestamp at beginning of trajectory 1 to be {} but it is instead {}\n'.format(san_diego2.timestamp, all_trajectories[1][0].timestamp))
        error_count += 1

    if not test_timestamp_proximity(all_trajectories[1][-1].timestamp, seattle.timestamp):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected end at beginning of trajectory 1 to be {} but it is instead {}\n'.format(seattle.timestamp, all_trajectories[1][-1].timestamp))
        error_count += 1

    if not test_timestamp_proximity(all_trajectories[2][0].timestamp, denver.timestamp):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected timestamp at beginning of trajectory 2 to be {} but it is instead {}\n'.format(denver.timestamp, all_trajectories[2][0].timestamp))
        error_count += 1

    if not test_timestamp_proximity(all_trajectories[2][-1].timestamp, new_york.timestamp):
        sys.stdout.write('ERROR: test_trajectory_assembly: Expected timestamp at end of trajectory 2 to be {} but it is instead {}\n'.format(new_york.timestamp, all_trajectories[2][-1].timestamp))
        error_count += 1

    print("Done checking proximities")

    return error_count