diff --git a/forest/jasmine/data2mobmat.py b/forest/jasmine/data2mobmat.py index cadcd0bf..9b3f5c30 100644 --- a/forest/jasmine/data2mobmat.py +++ b/forest/jasmine/data2mobmat.py @@ -619,6 +619,21 @@ def gps_to_mobmat( return mobmat +def force_valid_longitude(longitude: float) -> float: + """Forces a longitude coordinate to be within -180 and 180 + + In some cases, the imputation code seems to yield out-of-range + GPS coordinates. This function wrps longitude coordinates to be back + in the correct range so an error isn't thrown. + + For example, 190 would get transformed into -170. + + Args: + longitude: float. The longitude to be coerced + """ + return (longitude + 180) % 360 - 180 + + def compute_flight_positions( index: int, mobmat: np.ndarray, interval: float ) -> np.ndarray: @@ -660,8 +675,8 @@ def compute_flight_positions( # Update the mobility matrix with the new start and end positions mobmat[index, 1] = start_x mobmat[index, 4] = end_x - mobmat[index, 2] = start_y - mobmat[index, 5] = end_y + mobmat[index, 2] = force_valid_longitude(start_y) + mobmat[index, 5] = force_valid_longitude(end_y) return mobmat @@ -708,8 +723,8 @@ def compute_future_flight_positions( # Update the mobility matrix with the new start and end positions mobmat[index, 1] = start_x mobmat[index, 4] = end_x - mobmat[index, 2] = start_y - mobmat[index, 5] = end_y + mobmat[index, 2] = force_valid_longitude(start_y) + mobmat[index, 5] = force_valid_longitude(end_y) return mobmat diff --git a/forest/jasmine/traj2stats.py b/forest/jasmine/traj2stats.py index a67388af..43852c59 100644 --- a/forest/jasmine/traj2stats.py +++ b/forest/jasmine/traj2stats.py @@ -1660,6 +1660,34 @@ def gps_stats_main( participant_id, study_folder, "gps", tz_str, time_start, time_end, ) + # If the data comes from a study thata hada GPS fuzzing, + # and the study was prior to March 2023, the longitude + # coordinates may be outside of the required range of + # (-180, 180). This chunk of code wraps out of range + # coordinates to be in that range + if ( + ("longitude" in data.columns) + and ( + (data["longitude"].max() > 180) + or (data["longitude"].min() < -180) + ) + ): + logger.info("Reconciled bad longitude data for user %s", + participant_id) + data["longitude"] = (data["longitude"] + 180) % 360 - 180 + if ((places_of_interest is not None) + or (osm_tags is not None)): + logger.warning("Warning: user %s had longitude values " + "outside the valid range [-180, 180] " + "but OSM location summaries were " + "requested. Longitude values outside " + "the valid range may signify that GPS " + "fuzzing was directed to be used in " + "the study setup file. If GPS " + "coordinates were fuzzed, OSM " + "location summaries are meaningless", + participant_id) + if data.shape == (0, 0): logger.info("No data available.") continue