This document describes the various endpoints available in the pats RESTfullAPI, their purposes, request parameters, and expected responses.
Word of warning: the code in this repository is meant to show how the endpoints can be used. There is no graceful handling of errors, when an error is raised the program will terminate with a non-zero exit code.
below is a short step-by-step plan to get started.
- Choose the server you want to use, the server url is provided as an argument to the
PatsServiceclass, and can be one of three servers.- beta_server, "https://beta.pats-c.com/". This is the default and links to the development server from pats, this server is not always in sync with production.
- main_server, "https://pats-c.com/". This is the link to the main server of pats, this is used in production. When you are ready to deploy this server is recommended.
- Make sure the login credentials are present as environment variables. The username should be named "pats_user", and the pasword should be named "pats_passw". The easiest way to add them to the environment is by adding a ".env" file to the root directory of the project.
- That is it, you are now ready to run the script!
There is a basic logger present in the script. Logging is done using the logging module. If you want to change the log level, this can be done in the logger.py file.
Retrieves the API token corresponding to the provided pats account. This token will be used for authentication in all other endpoints.
The request body for the token endpoint can be found below. Here the username, and the password are the login credentials for your pats account. They are the same credentials to log into the pats website.
{
"username": "str",
"password": "str"
}The response body can be seen below.
{
"access_token": "str"
}The header is for all GET endpoint the same, it contains the authentication in form of the API key received using the token endpoint. An example header can be found below.
{
"Authorization": "str"
}The detection classes endpoint does not have a request body.
The detection classes endpoint retrieves, not surprisingly, all available detection classes. The detection classes are all the insects (and rats, birds, etc.) that pats knows. You can find out which are available to you via the sections endpoint
The detection classes response body contains just one element, detection_classes. In this element all detection classes can be found, detection classes are mapped to the insect id which is an int. Other attributes that can be found in the response body are:
bb_labelconsidered legacy, it stands for "Biobest label", and is internally used by a partner corporation.idthis is the same id as the insect id.labellatin name of the detection class.short_nameenglish name of the detection class.
response body:
{
"detection_classes": {
"1": {
"bb_label": null,
"id": 1,
"label": "str",
"short_name": "str"
},
...
}
}The sections endpoint does not have a request body.
The sections endpoint retrieves information about the different sections. Sections contain a lot of meta data about a section.
The response body for the sections endpoint contains an array of section objects. Each section object includes several attributes like:
crop: the crop grown in this section.n_weekly_trapeye_photos: how often the trapeye's in this section make photos.detection_classesavailable_in_cflag whether this detection class is available for pats-c.available_in_trapeyeflag whether this detection class is available for trapeye's.beneficialflag whether this detection class (insect) is good or bad.c_level_xa threshold set on the website.idinsect id.trapeye_levela threshold set on the website.
{
"sections": [
{
"crop": "str",
"customer_name": "str",
"detection_classes": [
{
"available_in_c": 0,
"available_in_trapeye": 1,
"bb_label": "str",
"beneficial": 0,
"c_level_1": 5,
"c_level_2": 15,
"c_level_3": 30,
"c_level_4": 50,
"id": 1,
"label": "str",
"short_name": "str",
"trapeye_level_1": 1,
"trapeye_level_2": 5,
"trapeye_level_3": 10,
"trapeye_level_4": 15
},
],
"greenhouse_name": "str",
"hubspot_company_id": 0123456789,
"id": 123,
"label": "str",
"n_weekly_trapeye_photos": 3,
"name": "str",
"timezone": "Europe/Amsterdam"
}
]
}
N.B. that in a previous version a spelling bug was introduced: `benificial`. This has been deprecated and will be removed in a future version.The spots endpoint will return information of all the individual "c" , and "trapeye" sensors.
The request body can be found below. Here the section_id is the id of the section from which the spots will be retrieved. snapping_mode is a flag that enables to snaps the sensor locations to the map. It defaults to auto and supports:
row: Aligns rows independently by snapping posts within a row to a straight line, optimizing row positioning.
post: Aligns rows of posts along straight lines based on average post locations across rows.
auto: Automatically determines the best snapping mode (row- or post-based) based on data characteristics and GPS accuracy.
disabled: Retains raw GPS coordinates without applying any snapping or alignment adjustments.
{
"section_id": "str",
"snapping_mode": "str"
}N.B. map_snapping is deprecated in favor of snapping_mode and will be removed in a future version.
In the response body there are two elements: c and trapeye.
In the c element all pats-c sensors in the provided section will be listed. Information about the pats-c sensors is the: label, latitude, longitude, post_id, row_id and system_id.
The post id and row id correspond to the post and row the sensor is placed on.
in the trapeye element all trapeye sensors can be found. These don't have a label, and instead of a system_id they have a unit_id.
the response body can be found below.
{
"c": [
{
"label": "str",
"latitude": 12.3456789,
"longitude": 9.8765432,
"post_id": 21,
"row_id": 42,
"system_id": 123
},
],
"trapeye": [
{
"latitude": 98.76543210987654,
"longitude": 1.2345678901234,
"post_id": 42,
"row_id": 21,
"unit_id": 9876
},
]
}The counts endpoint is used to download counts from the pats servers. Counts are the number of detections of a certain detection class.
The request body can be found below. Some notes:
average_24h_bin(OPTIONAL, defaults to 0) is a boolean flag represented as an int. Whenaverage_24h_binis set to 1, you will also retrieve information about the number of detections on different hours of the day.start_dateandend_dateare string representing dates. The format should be: %Y%m%d".detection_class_ids(OPTIONAL, defaults to None)is a list of insect ids in the form of a string. The format should be "insectId1,insectId2,insectId3...".bin_mode(OPTIONAL, defaults to "D") is a string and should either beDorh(His now deprecated in favor ofh). Which stand for daily or hourly binning respectively.
{
"section_id": "str",
"start_date": "date",
"end_date": "date",
"detection_class_ids": "str",
"bin_mode": "str",
"average_24h_bin": 0
}This endpoint also returns 2 elements: c and trapeye.
In c the counts of all pats-c sensors in the provided section in between the provided time span will be returned. Every sensor has three elements:
countsthe counts on different timestamps (datetimein format "%Y%m%d%H%M%S"_). Each count contains all the insect ids that the pats-c counts in this section.post_idandrow_idform together the location of the sensor.spot_idandsystem_idnote the internal spot id, and what system id is installed (currently) at that spot.
in trapeye you get a little more information. You get the absolute_count, which contains, not at all surprisingly, the absolute count of a insect, but also the difference with the previous absolute count. There is also the new_count, which is the new count since the last count.
For the sharp reader, the new_count are indeed the same as the "diff" fields in the absolute_count element.
There are some NaN values in the response body. Both the new_count as the "diff" elements get calculated by taking the difference with the previous_absolute count and the new absolute_count.
The date format in both elements is in the format "%Y%m%d".
Again the post_id and row_id make up the location of the sensor together.
The response body can be found below.
{
"c": [
{
"counts": [
{
"1": 0,
"2": 0,
"datetime": "20240708_120000"
},
{
"1": 0,
"2": 0,
"datetime": "20240708_130000"
},
],
"post_id": 21,
"row_id": 42,
"spot_id": 123,
"system_id": 456
}
],
"trapeye": [
{
"absolute_count": [
{
"24": 1.0,
"25": 0.0,
"26": 0.0,
"27": 0.0,
"28": 8.0,
"3": 0.0,
"date": "20240709"
},
{
"24": 1.0,
"25": 0.0,
"26": 0.0,
"27": 0.0,
"28": 8.0,
"3": 0.0,
"date": "20240711"
},
],
"new_counts": [
{
"24": NaN,
"25": NaN,
"26": NaN,
"27": NaN,
"28": NaN,
"3": NaN,
"date": "20240709"
},
{
"24": 0.0,
"25": 0.0,
"26": 0.0,
"27": 0.0,
"28": 0.0,
"3": 0.0,
"date": "20240711"
},
],
"post_id": 12,
"row_id": 24
},Download the list of available photos from a certain trapeye in a certain time span. The id's returned can be used in the download trapeye photo endpoint.
The request body can be found below. It contains the following attributes:
section_idthe id of the section this sensor is placed in.row_idandpost_idare the row and post respectively where this sensor is placed.start_dateandend_daterepresent the start and the end of the time frame from which available photos will be shown. The format for these dates should be "%Y%m%d".
{
"section_id": "str",
"row_id": "str",
"post_id": "str",
"start_date": "str",
"end_date": "str",
}The response body contains just one element, photos. This contains a list of id's, each id represents a photo. The id's are in the format "%Y%m%d_%H%M%S".
{
"photos": [
"20240713_140300",
"20240713_120300",
"20240711_140300",
"20240711_120500",
"20240709_140200",
]
}This endpoint is used to download one of the available trapeye photo's returned by the trapeye_photo_list endpoint.
The Request body can be found below.
The first three element: section_id, row_id and post_id are used to identify the sensor that took the photo. The datetime element is used to identify the photo, this corresponds to one of the retrieved id's from the trapeye_photo_list endpoint.
{
"section_id": "str",
"row_id": "str",
"post_id": "str",
"datetime": "str",
}This endpoint does not have a JSON response body. Instead the response body contains the image in byte format.
The download detection features endpoint is used to download information about a specific detection from a pats-c sensor.
To ensure backward compatibility this endpoint accepts two request bodies, both are shown below.
The section_id, detection_class_id, start_datetime and end_datetime are the same in both request bodies. The section_id represents the section the sensor that made the detections is in. The detection_class_id represents an insect id, this specifies from which insect the detections will be that are returned. The start_datetime and end_datetime represent the start and end of the time frame in which the returned detections were made.
row_id and post_id represent the position of the sensor that made the detections.
New request body:
{
"section_id": "str",
"row_id": "str",
"post_id": "str",
"detection_class_id": "str",
"start_datetime": "str",
"end_datetime": "str",
}system_id is a deprecated method to identify sensors.
Legacy request body:
{
"section_id": "str",
"system_id": "str",
"detection_class_id": "str",
"start_datetime": "str",
"end_datetime": "str",
}The response body can be found below. It contains information about specific detections. All units are in SI base units.
datetimethe time on which the detection took place, the format is "%Y%m%d_%H%M%S".dist_trajectdistance as the crow flies between the start and end point of the detection.dist_traveledthe distance flown by the insect during the detection.durationthe duration of the detection.light_levelthe light level during the detection.post_idandrow_idthe post and row the sensor that did the detection is mounted on.sizethe estimated size in meters of the insect.start_datetimethe time on which the detection took place in human readable format, information is the same as indatetimefield.uidthe unique identifier for this detectionvel_max,vel_meanandvel_stdare the max, mean and standard deviation of the velocity of the insect.
{
"data": [
{
"datetime": "str",
"dist_traject": 1.2345678901234567,
"dist_traveled": 9.8765432109876543,
"duration": 1.2345678901234567,
"light_level": 9.8765432109876543,
"post_id": 21,
"row_id": 42,
"size": 0.123456789012345678,
"start_datetime": "Mon, 08 Jul 2024 20:25:45 GMT",
"uid": 012345678,
"vel_max": 9.8765432109876543,
"vel_mean": 0.1234567890123456,
"vel_std": 9.8765432109876543
},
]
}Endpoint to download the flight track of an insect during a specific detection made by a pats-c sensor.
The request body can be found below. The section_id specifies in which section this detection took place, and the detection_uid is the unique identifier for the detection. The detection_uid of a measurement can be obtained using the download_detection_features endpoint.
{
"section_id": "str",
"detection_uid": "str",
}The response body for the c flight track endpoint contains a list of measurement points, all measured in a single detection. The points can be used to reconstruct the flight track during the detection. All units are again in SI base units, except light_level. This is a value between 0 and 1 where 1 is the maximum amount of light the camera can measure.
acc_valid_insectindicator whether moving averaging filter for smoothed accelerations is fulldisparity_insectdifference in image location of insect left and right camera viewelapsedtime since creation of folder containing flightpathfoundL_insectboolean whether an insect is found in the left view of the stereo camerafpfalse positive indicator. Default values is fp_not_a_fp when no abnormalities are detected.hunt_idthe id of the interception with drone, default to -1 if no interception has taken placeimLx_insectandimLy_insectcenter position of the insect in a rendered (non-raw stereo video)imLx_pred_insectandimLy_pred_insectestimated center position (based on previous data points) of the insect in a rendered videolight_levelthe light level during this measurement, this is a value between 0 and 1 where 1 corresponds to the maximum light level the camera can measure.motion_sum_insectsum of all pixel values in blob of motion imagen_frames_lost_insectnumber of frames in a row the camera lost track of the insect. When this reaches 20 frames the detection ends.n_frames_tracking_insectnumber of frames in a row the camera is tracking the insect.posX_insect,posY_insectandposZ_insectthe position of the insect in the viewport of the camera.pos_valid_insectindicator whether moving averaging filter for smoothed positions is fullradius_insectradius of the insect in mrs_idthe id of the measurement.saccX_insect,saccY_insectandsaccZ_insectsmoothed acceleration of the insect in the viewport of the camera.score_insectestimated quality of the blobsize_insectthe estimated size (diameter of bounding box) of the insect in pixel valuessposX_insect,sposY_insectandsposZ_insectsmoothed positions of the insect in the viewport of the camera.svelX_insect,svelY_insectandsvelZ_insectthe velocityvel_valid_insectboolean indicator whether moving averaging filter for smoothed velocities is full.
Response body:
{
"data": [
{
"Unnamed: 32": NaN,
"acc_valid_insect": 0,
"disparity_insect": 21.2121,
"elapsed": 1212.1212,
"foundL_insect": 1,
"fp": "str",
"hunt_id": -1,
"imLx_insect": 21,
"imLx_pred_insect": -1.0,
"imLy_insect": 123,
"imLy_pred_insect": -1.0,
"light_level": 0.123456,
"motion_sum_insect": 21,
"n_frames_lost_insect": 0,
"n_frames_tracking_insect": 1,
"posX_insect": 1.1234,
"posY_insect": -1.234,
"posZ_insect": -1.23456,
"pos_valid_insect": 1,
"radius_insect": 0.1234567,
"rs_id": 123456,
"saccX_insect": 0.0,
"saccY_insect": 0.0,
"saccZ_insect": 0.0,
"score_insect": 0.0,
"size_insect": 4.56789,
"sposX_insect": 1.2345,
"sposY_insect": -1.234,
"sposZ_insect": -1.23456,
"svelX_insect": 0.0,
"svelY_insect": 0.0,
"svelZ_insect": 0.0,
"vel_valid_insect": 0
},
]
}Endpoint used to download the video of a specific detection from a pats-c sensor.
The request body can be found below. The section_id and the detection_uid are used to uniquely identify the detection. The section_id represents the section where the pats-c sensor that made the detection is located, and the detection_uid is the unique id of the detection made. raw_stereo (OPTIONAL, defaults to "0"), is a boolean flag that can be used to request the raw stereo from the detection. Even though it is a boolean flag, it should be a string that is either "0", or "1". Here 1 is True, and 0 corresponds to False.
{
"section_id": "str",
"detection_uid": "str",
"raw_stereo": "str"
}The response body does not contain JSON, as the response body only contains the requested video.