Skip to content

Commit cf27b78

Browse files
Shaokai/0.1.3 (#55)
* corrected broken links and broken references * Update setup.cfg - bump to stable v1 and v0.1.1 * Update pyproject.toml * Update version.py * Corrected typo. Added config yamls in setup * Removed config files that are no longer needed * changed work from to pull the repo from git * Added comments to remind people to pay attentino to data folder in the demo notebooks * fixed pypi typo * Fixed a bug in create_project. Changed default use_vlm to False. Updated demo notebooks * removed WIP 3d keypoints * Fixed one more * WIP * enforcing the use of create_project in demo notebooks and modified the test * 3D supported. Better tests. More flexible identifier * black and isort * added dlc to test requirement * Made test use stronger gpt. Added dummy video * easier superanimal test * Better 3D prompt and fixed self-debug * preventing infinite loop * better prompt for 3D * better prompt for 3D * better prompt * updates * fixed serialization * extension to support animation. Made self-debugging work with bigger output. Allowing to skip code execution in parse result * better interpolation and corrected x,y,z convention * incorporated suggestions * add a test plot keypoint label * Fixed a bug. Changed hardcoded path to relative path in notebooks * updated vlm prompt to be more robust * deleted y axis inversion prompt * Added animation support and added animation in horse demo * edited readme --------- Co-authored-by: Mackenzie Mathis <[email protected]>
1 parent d550ef0 commit cf27b78

File tree

14 files changed

+105
-37
lines changed

14 files changed

+105
-37
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ You can git clone (or download) this repo to grab a copy and go. We provide exam
7373
### Here are a few demos that could fuel your own work, so please check them out!
7474

7575
1) [Draw a region of interest (ROI) and ask, "when is the animal in the ROI?"](https://github.com/AdaptiveMotorControlLab/AmadeusGPT/tree/main/notebooks/EPM_demo.ipynb)
76-
2) [Use a DeepLabCut SuperAnimal pose model to do video inference](https://github.com/AdaptiveMotorControlLab/AmadeusGPT/tree/main/notebooks/custom_mouse_demo.ipynb) - (make sure you use a GPU if you don't have corresponding DeepLabCut keypoint files already!
76+
2) [Use your own data](https://github.com/AdaptiveMotorControlLab/AmadeusGPT/tree/main/notebooks/YourData.ipynb) - (make sure you use a GPU to run SuperAnimal if you don't have corresponding DeepLabCut keypoint files already!
7777
3) [Write you own integration modules and use them](https://github.com/AdaptiveMotorControlLab/AmadeusGPT/tree/main/notebooks/Horse_demo.ipynb). Bonus: [source code](amadeusgpt/integration_modules). Make sure you delete the cached modules_embedding.pickle if you add new modules!
7878
4) [Multi-Animal social interactions](https://github.com/AdaptiveMotorControlLab/AmadeusGPT/tree/main/notebooks/MABe_demo.ipynb)
7979
5) [Reuse the task program generated by LLM and run it on different videos](https://github.com/AdaptiveMotorControlLab/AmadeusGPT/tree/main/notebooks/MABe_demo.ipynb)
@@ -126,6 +126,8 @@ the key dependencies that need installed are:
126126
pip install notebook
127127
conda install hdf5
128128
conda install pytables==3.8
129+
# pip install deeplabcut==3.0.0rc4 if you want to use SuperAnimal on your own videos
130+
129131
pip install amadeusgpt
130132
```
131133
## Citation

amadeusgpt/analysis_objects/visualization.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def __init__(
143143
n_individuals: int,
144144
average_keypoints: Optional[bool] = True,
145145
events: Optional[List[BaseEvent]] = None,
146+
use_3d: Optional[bool] = False,
146147
):
147148
assert len(keypoints.shape) == 3
148149
super().__init__(axs)
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
1-
from .cebra import *
1+
try:
2+
import cebra
3+
from .cebra import *
4+
except:
5+
print ('not able to import cebra')
6+
27
from .umap import *

amadeusgpt/managers/visual_manager.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,21 @@ def __init__(
4747
self.animal_manager = animal_manager
4848
self.object_manager = object_manager
4949

50-
def get_scene_image(self):
51-
scene_frame_index = self.config["video_info"].get("scene_frame_number", 1)
50+
@register_core_api
51+
def get_scene_image(self, scene_frame_index: int |None = None)-> np.ndarray:
52+
"""
53+
Returns the frame given the index in the video.
54+
Parameter
55+
---------
56+
scene_frame_index: int (optional) that specifies the index of the video frame.
57+
Returns
58+
-------
59+
An ndarray image
60+
61+
For visualizing keypoints or keypoint labels, it's nice to overlay the keypoints on the scene image.
62+
"""
63+
if scene_frame_index is None:
64+
scene_frame_index = self.config["video_info"].get("scene_frame_number", 1)
5265
if os.path.exists(self.video_file_path):
5366
cap = cv2.VideoCapture(self.video_file_path)
5467
cap.set(cv2.CAP_PROP_POS_FRAMES, scene_frame_index)

amadeusgpt/project.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ def create_project(data_folder, result_folder, **kwargs):
1414
"result_folder": result_folder,
1515
"video_suffix": ".mp4",
1616
},
17-
"llm_info": {"max_tokens": 4096, "temperature": 0.0, "keep_last_n_messages": 2},
17+
"llm_info": {"max_tokens": 4096,
18+
"temperature": 0.0,
19+
# let's use the best model by default
20+
"gpt_model": "gpt-4o",
21+
"keep_last_n_messages": 2},
1822
"object_info": {"load_objects_from_disk": False, "use_grid_objects": False},
1923
"keypoint_info": {
2024
"use_3d": False,

amadeusgpt/system_prompts/code_generator.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ def get_watching_events(identifier):
8585
4) Make sure you do not import any libraries in your code. All needed libraries are imported already.
8686
5) Make sure you disintuigh positional and keyword arguments when you call functions in api docs
8787
6) If you are writing code that uses matplotlib to plot, make sure you comment shape of the data to be plotted to double-check
88-
7) if your plotting code plots coordinates of keypoints, make sure you invert y axis (only during plotting) so that the plot is consistent with the image
89-
8) make sure the xlim and ylim covers the whole image. The image (h,w) is ({image_h},{image_w})
90-
9) Do not define your own objects (including grid objects). Only use objects that are given to you.
91-
10) You MUST use the index from get_keypoint_names to access the keypoint data of specific keyponit names. Do not assume the order of the bodypart.
92-
11) You MUST call functions in api docs on the analysis object.
93-
12) For api functions that require min_window and max_window, make sure you leave them as default values unless you are asked to change them.
88+
7) make sure the xlim and ylim covers the whole image. The image (h,w) is ({image_h},{image_w})
89+
8) Do not define your own objects (including grid objects). Only use objects that are given to you.
90+
9) You MUST use the index from get_keypoint_names to access the keypoint data of specific keyponit names. Do not assume the order of the bodypart.
91+
10) You MUST call functions in api docs on the analysis object.
92+
11) For api functions that require min_window and max_window, make sure you leave them as default values unless you are asked to change them.
93+
12) When making plots of keypoints of making animation about keypoints, try to overlap the plots with the scene frame if feasible.
94+
9495
9596
HOW TO AVOID BUGS:
9697
You should always comment the shape of the any numpy array you are working with to avoid bugs. YOU MUST DO IT.

amadeusgpt/system_prompts/visual_llm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def _get_system_prompt():
1111
```
1212
The "description" has high level description of the image.
1313
The "individuals" indicates the number of animals in the image
14-
The "species" indicates the species of the animals in the image. You can only choose from one of "topview_mouse", "sideview_quadruped" or "others".
14+
The "species" indicates the species of the animals in the image. You can only choose from one of "topview_mouse", "sideview_quadruped" or "others". Note all quadruped animals should be considered as sideview_quadruped.
1515
The "background_objects" is a list of background objects in the image.
1616
Explain your answers before you fill the answers. Make sure you only return one json string.
1717
"""

amadeusgpt/utils.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def create_qa_message(query: str, video_file_paths: list[str]) -> QA_Message:
212212
return QA_Message(query, video_file_paths)
213213

214214

215-
from IPython.display import Markdown, Video, display
215+
from IPython.display import Markdown, Video, display, HTML
216216

217217

218218
def parse_result(amadeus, qa_message, use_ipython=True, skip_code_execution=False):
@@ -231,13 +231,20 @@ def parse_result(amadeus, qa_message, use_ipython=True, skip_code_execution=Fals
231231
)
232232
if use_ipython:
233233
if len(qa_message.out_videos) > 0:
234-
for video_path, event_videos in qa_message.out_videos.items():
234+
for identifier, event_videos in qa_message.out_videos.items():
235235
for event_video in event_videos:
236236
display(Video(event_video, embed=True))
237237

238238
if use_ipython:
239+
from matplotlib.animation import FuncAnimation
239240
if len(qa_message.function_rets) > 0:
240-
for video_file_path in qa_message.function_rets:
241-
display(Markdown(str(qa_message.function_rets[video_file_path])))
241+
for identifier, rets in qa_message.function_rets.items():
242+
if not isinstance(rets, (tuple, list)):
243+
rets = [rets]
244+
for ret in rets:
245+
if isinstance(ret, FuncAnimation):
246+
display(HTML(ret.to_jshtml()))
247+
else:
248+
display(Markdown(str(qa_message.function_rets[identifier])))
242249

243250
return qa_message

notebooks/EPM_demo.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
"metadata": {},
8585
"outputs": [],
8686
"source": [
87-
"behavior_analysis = amadeus.get_behavior_analysis('/Users/shaokaiye/AmadeusGPT-dev/examples/EPM/EPM_11.mp4')\n",
87+
"behavior_analysis = amadeus.get_behavior_analysis('../examples/EPM/EPM_11.mp4')\n",
8888
"behavior_analysis.gui_manager.add_roi_from_video_selection()"
8989
]
9090
},
@@ -174,9 +174,9 @@
174174
],
175175
"metadata": {
176176
"kernelspec": {
177-
"display_name": "amadeusgpt-minimal",
177+
"display_name": "amadeusgpt-cpu",
178178
"language": "python",
179-
"name": "python3"
179+
"name": "amadeusgpt-cpu"
180180
},
181181
"language_info": {
182182
"codemirror_mode": {

notebooks/Horse_demo.ipynb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
"\n",
4343
"kwargs = { \n",
4444
" \"video_info.scene_frame_number\" : scene_frame_number,\n",
45+
" \"llm_info\": {\n",
46+
" \"gpt_model\": \"gpt-4o\",\n",
47+
" }\n",
48+
"\n",
4549
"}\n",
4650
"\n",
4751
"config = create_project(data_folder = \"../examples/Horse\",\n",
@@ -61,7 +65,7 @@
6165
"metadata": {},
6266
"outputs": [],
6367
"source": [
64-
"behavior_analysis = amadeus.get_behavior_analysis('/Users/shaokaiye/AmadeusGPT-dev/examples/Horse/BrownHorseinShadow.mp4')\n",
68+
"behavior_analysis = amadeus.get_behavior_analysis(video_file_path = '../examples/Horse/BrownHorseinShadow.mp4')\n",
6569
"scene_image = behavior_analysis.visual_manager.get_scene_image()\n",
6670
"plt.imshow(scene_image)"
6771
]
@@ -84,7 +88,11 @@
8488
"id": "e394c4e0",
8589
"metadata": {},
8690
"outputs": [],
87-
"source": []
91+
"source": [
92+
"query = \"\"\" make an animation of the horse keypoints over time. Overlap the image frame on it. Save the animation on the disk. \"\"\"\n",
93+
"qa_message = amadeus.step(query)\n",
94+
"qa_message = parse_result(amadeus, qa_message)"
95+
]
8896
}
8997
],
9098
"metadata": {

notebooks/MABe_demo.ipynb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
"metadata": {},
6565
"outputs": [],
6666
"source": [
67-
"behavior_analysis = amadeus.get_behavior_analysis('/Users/shaokaiye/AmadeusGPT-dev/examples/MABe/EGS8X2MN4SSUGFWAV976.mp4')\n",
67+
"behavior_analysis = amadeus.get_behavior_analysis(video_file_path='../examples/MABe/EGS8X2MN4SSUGFWAV976.mp4',\n",
68+
" keypoint_file_path='../examples/MABe/EGS8X2MN4SSUGFWAV976.h5')\n",
6869
"scene_image = behavior_analysis.visual_manager.get_scene_image()\n",
6970
"plt.imshow(scene_image)"
7071
]

notebooks/MausHaus_demo.ipynb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
"metadata": {},
6666
"outputs": [],
6767
"source": [
68-
"behavior_analysis = amadeus.get_behavior_analysis('/Users/shaokaiye/AmadeusGPT-dev/examples/MausHaus/maushaus_trimmed.mp4')\n",
68+
"behavior_analysis = amadeus.get_behavior_analysis(video_file_path='../examples/MausHaus/maushaus_trimmed.mp4',\n",
69+
" keypoint_file_path='../examples/MausHaus/maushaus_trimmed.h5')\n",
70+
"\n",
6971
"behavior_analysis.gui_manager.add_roi_from_video_selection()"
7072
]
7173
},

notebooks/custom_mouse_video.ipynb renamed to notebooks/YourData.ipynb

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,8 @@
2121
"outputs": [],
2222
"source": [
2323
"from amadeusgpt import AMADEUS\n",
24-
"from amadeusgpt.config import Config\n",
2524
"from amadeusgpt.utils import parse_result\n",
26-
"import amadeusgpt\n",
27-
"from amadeusgpt import create_project\n",
28-
"import matplotlib.pyplot as plt\n",
29-
"import cv2"
25+
"from amadeusgpt import create_project"
3026
]
3127
},
3228
{
@@ -35,7 +31,7 @@
3531
"metadata": {},
3632
"source": [
3733
"### Note that unlike other notebooks, we don't have keypoint_file_path here (as it's not provided)\n",
38-
"### By default, we use gpt-4o to determine which SuperAnimal models to run and it will run SuperAnimal in the first time the keypoints related queries are asked\n",
34+
"### By default, we use gpt-4o to determine which SuperAnimal models to run and it will run SuperAnimal in the first time the keypoints related queries are asked. Note to use superanimal, you will need to install the newest DeepLabCut.\n",
3935
"### Make sure you use a short video clips if you are not using GPUs in Linux (Mac silicon support to be added)"
4036
]
4137
},
@@ -46,16 +42,44 @@
4642
"metadata": {},
4743
"outputs": [],
4844
"source": [
49-
"scene_frame_number = 400\n",
50-
"\n",
5145
"# where you store you video and (optionally) keypoint files\n",
52-
"data_folder = \"temp_data_folder\"\n",
46+
"# If you don't have keypoint files, we would try to run SuperAnimal on your video\n",
47+
"# If you have pair of video and keypoint files, make sure they follow the naming convention as following:\n",
48+
"\n",
49+
"# your_folder\n",
50+
"# - cat.mp4\n",
51+
"# - cat.h5 (DLC output)\n",
52+
"# - dog.mp4\n",
53+
"# - dog.h5 (DLC output)\n",
54+
"\n",
55+
"data_folder = \"../examples/Horse\"\n",
5356
"result_folder = \"temp_result_folder\"\n",
5457
"video_suffix = \".mp4\"\n",
5558
"\n",
56-
"config = create_project(data_folder, result_folder, video_suffix = video_suffix)\n",
59+
"# if you want to overwrite the default config, you can do it here\n",
60+
"kwargs = {\n",
61+
" \"data_info\": {\n",
62+
" \"data_folder\": data_folder,\n",
63+
" \"result_folder\": result_folder,\n",
64+
" # can only locate videos specified in video_suffix\n",
65+
" \"video_suffix\": \".mp4\",\n",
66+
" },\n",
67+
" \n",
68+
" \"llm_info\": {\"max_tokens\": 4096, \n",
69+
" \"temperature\": 0.0, \n",
70+
" # one can swtich this to gpt-4o-mini for cheaper inference with the cost of worse performance.\n",
71+
" \"gpt_model\": \"gpt-4o\",\n",
72+
" # We only keep conversation history of 2. You can make it longer with more cost. We are switching to a different form of long-term memory.\n",
73+
" \"keep_last_n_messages\": 2},\n",
74+
" \"keypoint_info\": {\n",
75+
" # only set True if you work with 3D keypoint \n",
76+
" \"use_3d\": False,\n",
77+
" },\n",
78+
" # this is the frame index for gpt-4o to match the right superanimal model.\n",
79+
" \"video_info\": {\"scene_frame_number\": 1},\n",
80+
" }\n",
5781
"\n",
58-
"config[\"scene_frame_number\"] = scene_frame_number\n",
82+
"config = create_project(data_folder, result_folder, video_suffix = video_suffix, **kwargs)\n",
5983
"\n",
6084
"amadeus = AMADEUS(config, use_vlm = True)\n",
6185
"video_file_paths = amadeus.get_video_file_paths()\n",
@@ -89,9 +113,9 @@
89113
],
90114
"metadata": {
91115
"kernelspec": {
92-
"display_name": "amadeusgpt-cpu",
116+
"display_name": "amadeusgpt-minimal",
93117
"language": "python",
94-
"name": "amadeusgpt-cpu"
118+
"name": "python3"
95119
},
96120
"language_info": {
97121
"codemirror_mode": {

tests/test_3d.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ def test_3d_maushaus():
3030

3131
qa_message = amadeus.step(query)
3232

33-
parse_result(amadeus, qa_message, use_ipython=False)
33+
parse_result(amadeus, qa_message, use_ipython=False)

0 commit comments

Comments
 (0)