Sharfy commited on
Commit
0424b36
Β·
1 Parent(s): 2f17f02

Fix merge conflict

Browse files
Files changed (5) hide show
  1. .gitignore +212 -0
  2. app.py +269 -0
  3. requirements.txt +3 -0
  4. scripts.py +18 -0
  5. sql2redis.py +125 -0
.gitignore ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .idea/
2
+
3
+ # Created by https://www.gitignore.io/api/macos,linux,django,python,pycharm
4
+
5
+ ### Django ###
6
+ *.log
7
+ *.pot
8
+ *.pyc
9
+ __pycache__/
10
+ local_settings.py
11
+ db.sqlite3
12
+ media
13
+
14
+ ### Linux ###
15
+ *~
16
+
17
+ # temporary files which can be created if a process still has a handle open of a deleted file
18
+ .fuse_hidden*
19
+
20
+ # KDE directory preferences
21
+ .directory
22
+
23
+ # Linux trash folder which might appear on any partition or disk
24
+ .Trash-*
25
+
26
+ # .nfs files are created when an open file is removed but is still being accessed
27
+ .nfs*
28
+
29
+ ### macOS ###
30
+ *.DS_Store
31
+ .AppleDouble
32
+ .LSOverride
33
+
34
+ # Icon must end with two \r
35
+ Icon
36
+
37
+ # Thumbnails
38
+ ._*
39
+
40
+ # Files that might appear in the root of a volume
41
+ .DocumentRevisions-V100
42
+ .fseventsd
43
+ .Spotlight-V100
44
+ .TemporaryItems
45
+ .Trashes
46
+ .VolumeIcon.icns
47
+ .com.apple.timemachine.donotpresent
48
+
49
+ # Directories potentially created on remote AFP share
50
+ .AppleDB
51
+ .AppleDesktop
52
+ Network Trash Folder
53
+ Temporary Items
54
+ .apdisk
55
+
56
+ ### PyCharm ###
57
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
58
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
59
+
60
+ # User-specific stuff:
61
+ .idea/**/workspace.xml
62
+ .idea/**/tasks.xml
63
+ .idea/dictionaries
64
+
65
+ # Sensitive or high-churn files:
66
+ .idea/**/dataSources/
67
+ .idea/**/dataSources.ids
68
+ .idea/**/dataSources.xml
69
+ .idea/**/dataSources.local.xml
70
+ .idea/**/sqlDataSources.xml
71
+ .idea/**/dynamic.xml
72
+ .idea/**/uiDesigner.xml
73
+
74
+ # Gradle:
75
+ .idea/**/gradle.xml
76
+ .idea/**/libraries
77
+
78
+ # CMake
79
+ cmake-build-debug/
80
+
81
+ # Mongo Explorer plugin:
82
+ .idea/**/mongoSettings.xml
83
+
84
+ ## File-based project format:
85
+ *.iws
86
+
87
+ ## Plugin-specific files:
88
+
89
+ # IntelliJ
90
+ /out/
91
+
92
+ # mpeltonen/sbt-idea plugin
93
+ .idea_modules/
94
+
95
+ # JIRA plugin
96
+ atlassian-ide-plugin.xml
97
+
98
+ # Cursive Clojure plugin
99
+ .idea/replstate.xml
100
+
101
+ # Crashlytics plugin (for Android Studio and IntelliJ)
102
+ com_crashlytics_export_strings.xml
103
+ crashlytics.properties
104
+ crashlytics-build.properties
105
+ fabric.properties
106
+
107
+ ### PyCharm Patch ###
108
+ # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
109
+
110
+ # *.iml
111
+ # modules.xml
112
+ # .idea/misc.xml
113
+ # *.ipr
114
+
115
+ # Sonarlint plugin
116
+ .idea/sonarlint
117
+
118
+ ### Python ###
119
+ # Byte-compiled / optimized / DLL files
120
+ *.py[cod]
121
+ *$py.class
122
+
123
+ # C extensions
124
+ *.so
125
+
126
+ # Distribution / packaging
127
+ .Python
128
+ env/
129
+ build/
130
+ develop-eggs/
131
+ dist/
132
+ downloads/
133
+ eggs/
134
+ .eggs/
135
+ lib/
136
+ lib64/
137
+ parts/
138
+ sdist/
139
+ var/
140
+ wheels/
141
+ *.egg-info/
142
+ .installed.cfg
143
+ *.egg
144
+
145
+ # PyInstaller
146
+ # Usually these files are written by a python script from a template
147
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
148
+ *.manifest
149
+ *.spec
150
+
151
+ # Installer logs
152
+ pip-log.txt
153
+ pip-delete-this-directory.txt
154
+
155
+ # Unit test / coverage reports
156
+ htmlcov/
157
+ .tox/
158
+ .coverage
159
+ .coverage.*
160
+ .cache
161
+ nosetests.xml
162
+ coverage.xml
163
+ *,cover
164
+ .hypothesis/
165
+
166
+ # Translations
167
+ *.mo
168
+
169
+ # Django stuff:
170
+
171
+ # Flask stuff:
172
+ instance/
173
+ .webassets-cache
174
+
175
+ # Scrapy stuff:
176
+ .scrapy
177
+
178
+ # Sphinx documentation
179
+ docs/_build/
180
+
181
+ # PyBuilder
182
+ target/
183
+
184
+ # Jupyter Notebook
185
+ .ipynb_checkpoints
186
+
187
+ # pyenv
188
+ .python-version
189
+
190
+ # celery beat schedule file
191
+ celerybeat-schedule
192
+
193
+ # SageMath parsed files
194
+ *.sage.py
195
+
196
+ # dotenv
197
+ .env
198
+
199
+ # virtualenv
200
+ .venv
201
+ venv/
202
+ ENV/
203
+
204
+ # Spyder project settings
205
+ .spyderproject
206
+ .spyproject
207
+
208
+ # Rope project settings
209
+ .ropeproject
210
+
211
+ # mkdocs documentation
212
+ /site
app.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import discord
2
+ from discord import Option
3
+ import redis
4
+ import os
5
+
6
+ # Function to generate auto-incremented IDs
7
+ def generate_id(key):
8
+ return r.incr(key)
9
+
10
+ def generate_progress_bar(num_labels, width=20):
11
+ print(num_labels)
12
+ percentage = int(int(num_labels) / 300 * 100)
13
+ completed_blocks = int(percentage * width / 100)
14
+ remaining_blocks = width - completed_blocks
15
+
16
+ progress_bar = 'β–“' * completed_blocks + 'β–‘' * remaining_blocks
17
+ percentage_text = f' {num_labels}/50 identified 🦜🌱 '
18
+
19
+ return f'πŸ† {progress_bar} {percentage_text}'
20
+
21
+ # Redis client setup
22
+
23
+ redis_url = 'redis://default:[email protected]:7369'
24
+ r = redis.from_url(redis_url)
25
+
26
+ r.set('species_identified', 0)
27
+
28
+ def improve_player_stats(ctx):
29
+ # add 1 to the number of species identified
30
+ value = r.get(b'species_identified').decode('utf-8')
31
+ r.set(b'species_identified', int(value) + 1)
32
+
33
+ xp_key = f'{ctx.author.name}:XP'.encode('utf-8')
34
+ if not r.exists(xp_key):
35
+ r.set(xp_key, 0)
36
+
37
+ role_key = f'{ctx.author.name}:role'.encode('utf-8')
38
+ if not r.exists(role_key):
39
+ r.set(role_key, 'Naturalist')
40
+
41
+ oc_key = f'{ctx.author.name}:occurances'.encode('utf-8')
42
+ if not r.exists(oc_key):
43
+ r.set(oc_key, 0)
44
+ r.set(xp_key, int(r.get(xp_key)) + 10)
45
+ r.set(oc_key, int(r.get(oc_key)) + 1)
46
+
47
+ bot = discord.Bot()
48
+
49
+ @bot.event
50
+ async def on_ready():
51
+ print(f"{bot.user} is ready and online!")
52
+
53
+ @bot.command(
54
+ description="Get image predictions",
55
+ options=[
56
+ Option(name="id", description="The ID of the image")
57
+ ])
58
+ async def predict_image(ctx, id):
59
+ # Fetch the image data from Redis
60
+ image_data_bytes = r.hgetall(f'image:{id}'.encode('utf-8'))
61
+ image_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in image_data_bytes.items()}
62
+ path = f'https://gainforest-transparency-dashboard.s3.amazonaws.com/{image_data["awsCID"]}'
63
+ print(image_data)
64
+ message = f"**Image Observation: {id} by _{image_data['sensor']}_**"
65
+
66
+ message += "\n_Below are Top 10 predictions of AI_"
67
+ emoji_unicode_list = [chr(0x30 + i) + '\uFE0F\u20E3' for i in range(11)]
68
+
69
+ prediction_data_bytes = r.hgetall(f'prediction:{id}:1'.encode('utf-8'))
70
+ prediction_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in prediction_data_bytes.items()}
71
+
72
+ embed = discord.Embed(
73
+ title="",
74
+ description=f"Label: {prediction_data['label']}\nPredictions of our AI algorithms",
75
+ color=discord.Colour.blurple(), # Pycord provides a class with default colors you can choose from
76
+ )
77
+ embed.set_author(name=f"Image Observation {id} - AI Predictions", icon_url=ctx.author.display_avatar.url)
78
+
79
+ for i in range(1, 10):
80
+ prediction_data_bytes = r.hgetall(f'prediction:{id}:{i}'.encode('utf-8'))
81
+ prediction_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in prediction_data_bytes.items()}
82
+ species = prediction_data['label']
83
+ score = prediction_data['confidence']
84
+ # message = message + f'\n> {emoji_unicode_list[i-1]} {species} with confidence {score}'
85
+ embed.add_field(name=f'{species}', value=f'Confidence: {float(score):.4f}', inline=True)
86
+ embed.set_thumbnail(url=path)
87
+
88
+ # Send the image
89
+ await ctx.respond("Hint: You can use [NParks Flora & Fauna Database](https://www.nparks.gov.sg/florafaunaweb) to verify", embed=embed)
90
+
91
+ @bot.command(
92
+ description="Get image observation",
93
+ options=[
94
+ Option(name="id", description="The ID of the image")
95
+ ])
96
+ async def image(ctx, id):
97
+ # Fetch the image data from Redis
98
+ image_data_bytes = r.hgetall(f'image:{id}'.encode('utf-8'))
99
+ image_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in image_data_bytes.items()}
100
+ print(image_data)
101
+
102
+ # Create an embed
103
+ embed = discord.Embed(color=discord.Colour.blurple())
104
+ embed.set_author(name=f"Image Observation {id} - Task", icon_url=ctx.author.display_avatar.url)
105
+ embed.add_field(name="Sensor", value=image_data['sensor'], inline=True)
106
+ # embed.add_field(name="Latest Label by", value=image_data['author'], inline=True)
107
+ path = f'https://gainforest-transparency-dashboard.s3.amazonaws.com/{image_data["awsCID"]}'
108
+ embed.set_image(url=path)
109
+ await ctx.respond(embed=embed)
110
+
111
+ @bot.command(
112
+ description="Label image observation",
113
+ options=[
114
+ Option(name="id", description="The ID of the image"),
115
+ Option(name="label", description="The label for the image"),
116
+ Option(name="confidence", description="The confidence for the label"),
117
+ ])
118
+ async def label_image(ctx, id:int, label:str, confidence:int):
119
+ label_cnt = generate_id(f'label:{id}')
120
+ r.hset(f'label:{id}:{label_cnt}'.encode('utf-8'), b'label', label.encode('utf-8'))
121
+ r.hset(f'label:{id}:{label_cnt}'.encode('utf-8'), b'author', ctx.author.mention.encode('utf-8'))
122
+ r.hset(f'label:{id}:{label_cnt}'.encode('utf-8'), b'confidence', ctx.author.mention.encode('utf-8'))
123
+
124
+ # Fetch the image data from Redis
125
+ image_data_bytes = r.hgetall(f'image:{id}'.encode('utf-8'))
126
+ image_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in image_data_bytes.items()}
127
+ print(image_data)
128
+
129
+ # Create an embed
130
+ embed = discord.Embed(color=discord.Colour.blurple())
131
+ embed.set_author(name=f"Image Observation {id} - New Label πŸŽ‰", icon_url=ctx.author.display_avatar.url)
132
+ embed.add_field(name="Sensor", value=image_data['sensor'], inline=True)
133
+ embed.add_field(name="Label", value=image_data['label'], inline=True)
134
+ embed.add_field(name="Proposed by", value=image_data['author'], inline=True)
135
+ embed.set_image(url=image_data['path'])
136
+
137
+ improve_player_stats(ctx)
138
+
139
+ await ctx.respond(f"{ctx.author.mention} labeled observation **{id}** as **{label}** πŸŽ‰ (Earned 10 XP)", embed=embed)
140
+
141
+ @bot.command(description="Get progress bar.")
142
+ async def progress(ctx):
143
+ value = r.get(b'species_identified').decode('utf-8')
144
+ progress_bar = generate_progress_bar(value)
145
+ await ctx.respond(progress_bar) # this decorator makes a slash command
146
+
147
+ @bot.command(description="Get sound data.") # this decorator makes a slash command
148
+ async def sound(ctx, id): # a slash command will be created with the name "ping"
149
+ # Fetch the sound data from Redis
150
+ sound_data_bytes = r.hgetall(f'sound:{id}'.encode('utf-8'))
151
+ sound_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in sound_data_bytes.items()}
152
+
153
+ # Create an embed
154
+ embed = discord.Embed(color=discord.Colour.blurple())
155
+ embed.set_author(name=f"Sound Observation {id} - Task", icon_url=ctx.author.display_avatar.url)
156
+ embed.add_field(name="Sensor", value=sound_data['sensor'], inline=True)
157
+ embed.add_field(name="Label", value=sound_data['label'], inline=True)
158
+ embed.add_field(name="Proposed by", value=sound_data['author'], inline=True)
159
+ embed.add_field(name="Timestamp", value=sound_data['time'], inline=True)
160
+
161
+ with open(sound_data['path'], 'rb') as f:
162
+ sound = discord.File(f)
163
+ message = await ctx.respond(file=sound, embed=embed)
164
+ print('The ID of the message is:', message.id)
165
+
166
+ @bot.command(
167
+ description="Label sound observation",
168
+ options=[
169
+ Option(name="id", description="The ID of the sound"),
170
+ Option(name="label", description="The label for the sound"),
171
+ Option(name="timestamp", description="The timestamp of the observation"),
172
+ ])
173
+ async def label_sound(ctx, id:int, label:str, timestamp:str):
174
+ r.hset(f'sound:{id}'.encode('utf-8'), b'label', label.encode('utf-8'))
175
+ r.hset(f'sound:{id}'.encode('utf-8'), b'time', timestamp.encode('utf-8'))
176
+ r.hset(f'sound:{id}'.encode('utf-8'), b'author', ctx.author.mention.encode('utf-8'))
177
+
178
+ # Fetch the sound data from Redis
179
+ sound_data_bytes = r.hgetall(f'sound:{id}'.encode('utf-8'))
180
+ sound_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in sound_data_bytes.items()}
181
+
182
+ # Create an embed
183
+ embed = discord.Embed(color=discord.Colour.blurple())
184
+ embed.set_author(name=f"Sound Observation {id} - New Label πŸŽ‰", icon_url=ctx.author.display_avatar.url)
185
+ embed.add_field(name="Sensor", value=sound_data['sensor'], inline=True)
186
+ embed.add_field(name="Label", value=sound_data['label'], inline=True)
187
+ embed.add_field(name="Proposed by", value=sound_data['author'], inline=True)
188
+ embed.add_field(name="Time", value=sound_data['time'], inline=True)
189
+
190
+ improve_player_stats(ctx)
191
+
192
+ with open(sound_data['path'], 'rb') as f:
193
+ sound = discord.File(f)
194
+ await ctx.respond(f"{ctx.author.mention} labeled sound observation **{id}** as **{label}** at **{timestamp}** πŸŽ‰ (Earned 10 XP)", file=sound, embed=embed)
195
+
196
+ @bot.command(
197
+ description="List all unlabeled sound observations"
198
+ )
199
+ async def list_unlabeled_sound(ctx):
200
+
201
+ unlabeled_ids = []
202
+
203
+ # Fetch all the sound data from Redis
204
+ keys = r.keys('sound:*'.encode('utf-8'))
205
+ for key in keys:
206
+ sound_data_bytes = r.hgetall(key)
207
+ sound_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in sound_data_bytes.items()}
208
+ if '❓' == sound_data['label']:
209
+ unlabeled_ids = unlabeled_ids + [key.decode('utf-8')]
210
+
211
+ # Create an embed
212
+ embed = discord.Embed(color=discord.Colour.blurple())
213
+ embed.set_author(name=f"Unlabeled Sound Observations", icon_url=ctx.author.display_avatar.url)
214
+
215
+ for id in unlabeled_ids:
216
+ embed.add_field(name=f"{id}", value="❓", inline=True)
217
+
218
+ await ctx.respond(embed=embed)
219
+
220
+ @bot.command(
221
+ description="List all unlabeled image observations"
222
+ )
223
+ async def list_unlabeled_image(ctx):
224
+
225
+ unlabeled_ids = []
226
+
227
+ # Fetch all the image data from Redis
228
+ keys = r.keys('image:*'.encode('utf-8'))
229
+ for key in keys:
230
+ image_data_bytes = r.hgetall(key)
231
+ image_data = {k.decode('utf-8'): v.decode('utf-8') for k, v in image_data_bytes.items()}
232
+ if '❓' == image_data['label']:
233
+ unlabeled_ids = unlabeled_ids + [key.decode('utf-8')]
234
+
235
+ # Create an embed
236
+ embed = discord.Embed(color=discord.Colour.blurple())
237
+ embed.set_author(name=f"Unlabeled Image Observations", icon_url=ctx.author.display_avatar.url)
238
+
239
+ for id in unlabeled_ids:
240
+ embed.add_field(name=f"{id}", value="❓", inline=True)
241
+
242
+ await ctx.respond(embed=embed)
243
+
244
+ @bot.command(
245
+ description="Check your profile"
246
+ )
247
+ async def profile(ctx):
248
+ xp_key = f'{ctx.author.name}:XP'.encode('utf-8')
249
+ if not r.exists(xp_key):
250
+ r.set(xp_key, 0)
251
+
252
+ role_key = f'{ctx.author.name}:role'.encode('utf-8')
253
+ if not r.exists(role_key):
254
+ r.set(role_key, 'NATURALIST')
255
+
256
+ oc_key = f'{ctx.author.name}:occurances'.encode('utf-8')
257
+ if not r.exists(oc_key):
258
+ r.set(oc_key, 0)
259
+
260
+ # Create an embed
261
+ embed = discord.Embed(color=discord.Colour.blurple())
262
+ embed.set_author(name=f"{ctx.author.name} - Profile", icon_url=ctx.author.display_avatar.url)
263
+ embed.add_field(name="**PROGRESS**", value=f"**Level**: 1\n**XP**: {r.get(xp_key).decode()}/1000\n", inline=False)
264
+ embed.add_field(name="**STATS**", value=f"**🦜 Labels**: {r.get(oc_key).decode()}", inline=False)
265
+ embed.set_thumbnail(url=ctx.author.display_avatar.url)
266
+ embed.set_footer(text=f"πŸ† RANK: {r.get(role_key).decode()}")
267
+ await ctx.respond(embed=embed)
268
+
269
+ bot.run('MTA5NzMzMDI2MDI4NDAzNTEyMg.GNFiQP.hZC_2HLTvVAROlKKUmnVQjviT0G4wHeQq23-rs')
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ py-cord
2
+ redis
3
+ os
scripts.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+
4
+ def run_ffmpeg(input_variable, output_variable):
5
+ # Construct the FFmpeg command using the input and output variables
6
+ command = f'ffmpeg -i {input_variable} -vf "scale=640:480" -b:v 1000k -vcodec libx264 -acodec aac {output_variable}'
7
+
8
+ # Execute the FFmpeg command using os.system()
9
+ os.system(command)
10
+
11
+ if __name__ == '__main__':
12
+ # Check if the script is being executed directly
13
+ if len(sys.argv) != 3:
14
+ print('Usage: python script.py input_file output_file')
15
+ else:
16
+ input_file = sys.argv[1]
17
+ output_file = sys.argv[2]
18
+ run_ffmpeg(input_file, output_file)
sql2redis.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import redis
2
+ import psycopg2
3
+ from gradio_client import Client
4
+ import json
5
+
6
+ redis_url = 'redis://default:[email protected]:7369'
7
+ r = redis.from_url(redis_url)
8
+ # run josh's algorithm
9
+ client = Client("https://diverseco-metaformer.hf.space/")
10
+
11
+ # Postgres database get the observations
12
+ def connect():
13
+ conn = None
14
+ try:
15
+ # Connecting to your PostgreSQL server
16
+ print('Connecting to the PostgreSQL database...')
17
+ conn = psycopg2.connect('postgresql://postgres:[email protected]:7297/railway')
18
+ # conn = psycopg2.connect('postgresql://postgres:[email protected]:6771/railway') #staging
19
+ # conn = psycopg2.connect('postgresql://postgres:[email protected]:5772/railway') #development
20
+
21
+ except (Exception, psycopg2.DatabaseError) as error:
22
+ print(error)
23
+
24
+ print("Connection successful")
25
+ return conn
26
+
27
+ def get_all_images():
28
+ query = """SELECT "id", "awsCID" FROM "Asset" WHERE "projectId" = 37 AND "classification" = 'Camera Traps'"""
29
+ conn = connect()
30
+ cur = conn.cursor()
31
+
32
+ try:
33
+ # Execute a simple SQL command
34
+ cur.execute(query)
35
+
36
+ # Fetch all the data returned by the database
37
+ rows = cur.fetchall()
38
+ for row in rows:
39
+ image_cnt = generate_id('image_cnt')
40
+ # Set multiple field-value pairs using HMSET
41
+ fields_values = {
42
+ 'uuid': row[0],
43
+ 'awsCID': row[1],
44
+ 'sensor': 'Rover/RGB',
45
+ 'label': '❓',
46
+ 'author': '❓',
47
+ 'timestamp': '❓'
48
+ }
49
+ r.hmset(f'image:{image_cnt}', fields_values)
50
+
51
+ image_url = f'https://gainforest-transparency-dashboard.s3.amazonaws.com/{row[1]}'
52
+ print(f'predicting {image_url}')
53
+
54
+ result = client.predict(
55
+ image_url,
56
+ api_name="/predict"
57
+ )
58
+
59
+ with open(result, 'r') as file:
60
+ json_data = json.load(file)
61
+
62
+ # Extract labels and confidences from JSON data
63
+ labels = [data['label'] for data in json_data['confidences']]
64
+ confidences = [data['confidence'] for data in json_data['confidences']]
65
+
66
+ # Store labels and confidences in Redis using HMSET
67
+ for label, confidence in zip(labels, confidences):
68
+ pred_cnt = generate_id(f'prediction:{image_cnt}')
69
+ fields_values = {
70
+ 'label': label,
71
+ 'confidence': confidence,
72
+ }
73
+ r.hmset(f'prediction:{image_cnt}:{pred_cnt}', fields_values)
74
+
75
+
76
+ except (Exception, psycopg2.DatabaseError) as error:
77
+ print(error)
78
+
79
+ finally:
80
+ # Close the cursor and connection
81
+ cur.close()
82
+ conn.close()
83
+ r.close()
84
+
85
+ def get_all_sounds():
86
+ query = """SELECT "id", "awsCID" FROM "Asset" WHERE "projectId" = 37 AND "classification" = 'Bioacoustics'"""
87
+ conn = connect()
88
+ cur = conn.cursor()
89
+
90
+ try:
91
+ # Execute a simple SQL command
92
+ cur.execute(query)
93
+
94
+ # Fetch all the data returned by the database
95
+ rows = cur.fetchall()
96
+ for row in rows:
97
+ sound_cnt = generate_id('sound_cnt')
98
+ # Set multiple field-value pairs using HMSET
99
+ fields_values = {
100
+ 'uuid': row[0],
101
+ 'awsCID': row[1],
102
+ 'sensor': 'Speedybee/Acoustic',
103
+ 'label': '❓',
104
+ 'author': '❓',
105
+ 'label_at': '❓',
106
+ 'timestamp': '❓'
107
+ }
108
+ r.hmset(f'sound:{sound_cnt}', fields_values)
109
+
110
+ except (Exception, psycopg2.DatabaseError) as error:
111
+ print(error)
112
+
113
+ finally:
114
+ # Close the cursor and connection
115
+ cur.close()
116
+ conn.close()
117
+ r.close()
118
+
119
+ # Function to generate auto-incremented IDs
120
+ def generate_id(key):
121
+ return r.incr(key)
122
+
123
+ r.flushdb()
124
+ get_all_images()
125
+ get_all_sounds()