toilaluan commited on
Commit
22df377
β€’
1 Parent(s): b7ea0ca
common.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ BACKGROUND_COLOR = "white"
2
+ COLOR = "black"
3
+
4
+ import streamlit as st
5
+
6
+ def set_page_container_style(
7
+ max_width: int = 1100,
8
+ max_width_100_percent: bool = False,
9
+ padding_top: int = 1,
10
+ padding_right: int = 10,
11
+ padding_left: int = 1,
12
+ padding_bottom: int = 10,
13
+ color: str = COLOR,
14
+ background_color: str = BACKGROUND_COLOR,
15
+ ):
16
+ if max_width_100_percent:
17
+ max_width_str = f"max-width: 100%;"
18
+ else:
19
+ max_width_str = f"max-width: {max_width}px;"
20
+ st.markdown(
21
+ f"""
22
+ <style>
23
+ .reportview-container .css-1lcbmhc .css-1outpf7 {{
24
+ padding-top: 35px;
25
+ }}
26
+ .reportview-container .main .block-container {{
27
+ {max_width_str}
28
+ padding-top: {padding_top}rem;
29
+ padding-right: {padding_right}rem;
30
+ padding-left: {padding_left}rem;
31
+ padding-bottom: {padding_bottom}rem;
32
+ }}
33
+ .reportview-container .main {{
34
+ color: {color};
35
+ background-color: {background_color};
36
+ }}
37
+ </style>
38
+ """,
39
+ unsafe_allow_html=True,
40
+ )
core.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import io
3
+ import random
4
+ import time
5
+ from typing import List
6
+ from PIL import Image
7
+ import aiohttp
8
+ import asyncio
9
+ import requests
10
+ import streamlit as st
11
+ import requests
12
+ import zipfile
13
+ import io
14
+ import pandas as pd
15
+ from utils import icon
16
+ from streamlit_image_select import image_select
17
+ from PIL import Image
18
+ import random
19
+ import time
20
+ import base64
21
+ from typing import List
22
+ import aiohttp
23
+ import asyncio
24
+ import plotly.express as px
25
+ from common import set_page_container_style
26
+
27
+
28
+ def pil_image_to_base64(image: Image.Image) -> str:
29
+ image_stream = io.BytesIO()
30
+ image.save(image_stream, format="PNG")
31
+ base64_image = base64.b64encode(image_stream.getvalue()).decode("utf-8")
32
+
33
+ return base64_image
34
+
35
+
36
+ def get_or_create_eventloop():
37
+ try:
38
+ return asyncio.get_event_loop()
39
+ except RuntimeError as ex:
40
+ if "There is no current event loop in thread" in str(ex):
41
+ loop = asyncio.new_event_loop()
42
+ asyncio.set_event_loop(loop)
43
+ return asyncio.get_event_loop()
44
+
45
+
46
+ model_config = {
47
+ "RealisticVision": {
48
+ "ratio": {
49
+ "square": (512, 512),
50
+ "tall": (512, 768),
51
+ "wide": (768, 512),
52
+ },
53
+ "num_inference_steps": 30,
54
+ "guidance_scale": 7.0,
55
+ "clip_skip": 2,
56
+ },
57
+ "AnimeV3": {
58
+ "num_inference_steps": 25,
59
+ "guidance_scale": 7,
60
+ "clip_skip": 2,
61
+ "ratio": {
62
+ "square": (1024, 1024),
63
+ "tall": (672, 1024),
64
+ "wide": (1024, 672),
65
+ },
66
+ },
67
+ "DreamShaper": {
68
+ "num_inference_steps": 35,
69
+ "guidance_scale": 7,
70
+ "clip_skip": 2,
71
+ "ratio": {
72
+ "square": (512, 512),
73
+ "tall": (512, 768),
74
+ "wide": (768, 512),
75
+ },
76
+ },
77
+ "RealitiesEdgeXL": {
78
+ "num_inference_steps": 7,
79
+ "guidance_scale": 2.5,
80
+ "clip_skip": 2,
81
+ "ratio": {
82
+ "square": (1024, 1024),
83
+ "tall": (672, 1024),
84
+ "wide": (1024, 672),
85
+ },
86
+ },
87
+ }
88
+
89
+
90
+ def base64_to_image(base64_string):
91
+ return Image.open(io.BytesIO(base64.b64decode(base64_string)))
92
+
93
+
94
+ async def call_niche_api(url, data) -> List[Image.Image]:
95
+ try:
96
+ async with aiohttp.ClientSession() as session:
97
+ async with session.post(url, json=data) as response:
98
+ response = await response.json()
99
+ return base64_to_image(response)
100
+ except Exception as e:
101
+ print(e)
102
+ return None
103
+
104
+
105
+ async def get_output(url, datas):
106
+ tasks = [asyncio.create_task(call_niche_api(url, data)) for data in datas]
107
+ return await asyncio.gather(*tasks)
108
+
109
+
110
+ def main_page(
111
+ submitted: bool,
112
+ model_name: str,
113
+ prompt: str,
114
+ negative_prompt: str,
115
+ aspect_ratio: str,
116
+ num_images: int,
117
+ uid: str,
118
+ secret_key: str,
119
+ seed: str,
120
+ conditional_image: str,
121
+ controlnet_conditioning_scale: list,
122
+ pipeline_type: str,
123
+ api_token: str,
124
+ generated_images_placeholder,
125
+ ) -> None:
126
+ """Main page layout and logic for generating images.
127
+
128
+ Args:
129
+ submitted (bool): Flag indicating whether the form has been submitted.
130
+ width (int): Width of the output image.
131
+ height (int): Height of the output image.
132
+ num_inference_steps (int): Number of denoising steps.
133
+ guidance_scale (float): Scale for classifier-free guidance.
134
+ prompt_strength (float): Prompt strength when using img2img/inpaint.
135
+ prompt (str): Text prompt for the image generation.
136
+ negative_prompt (str): Text prompt for elements to avoid in the image.
137
+ """
138
+ if submitted:
139
+ if secret_key != api_token and uid != "-1":
140
+ st.error("Invalid secret key")
141
+ return
142
+ try:
143
+ uid = int(uid)
144
+ except ValueError:
145
+ uid = -1
146
+ width, height = model_config[model_name]["ratio"][aspect_ratio.lower()]
147
+ width = int(width)
148
+ height = int(height)
149
+ num_inference_steps = model_config[model_name]["num_inference_steps"]
150
+ guidance_scale = model_config[model_name]["guidance_scale"]
151
+
152
+ with st.status(
153
+ "πŸ‘©πŸΎβ€πŸ³ Whipping up your words into art...", expanded=True
154
+ ) as status:
155
+ try:
156
+ # Only call the API if the "Submit" button was pressed
157
+ if submitted:
158
+ start_time = time.time()
159
+ # Calling the replicate API to get the image
160
+ with generated_images_placeholder.container():
161
+ try:
162
+ seed = int(seed)
163
+ except ValueError:
164
+ seed = -1
165
+ if seed >= 0:
166
+ seeds = [int(seed) + i for i in range(num_images)]
167
+ else:
168
+ seeds = [random.randint(0, 1e9) for _ in range(num_images)]
169
+ all_images = [] # List to store all generated images
170
+ data = {
171
+ "key": api_token,
172
+ "prompt": prompt, # prompt
173
+ "model_name": model_name, # See avaialble models in https://github.com/NicheTensor/NicheImage/blob/main/configs/model_config.yaml
174
+ "seed": seed, # -1 means random seed
175
+ "miner_uid": int(
176
+ uid
177
+ ), # specify miner uid, -1 means random miner selected by validator
178
+ "pipeline_type": pipeline_type,
179
+ "conditional_image": conditional_image,
180
+ "pipeline_params": { # params feed to diffusers pipeline, see all params here https://huggingface.co/docs/diffusers/api/pipelines/stable_diffusion/text2img#diffusers.StableDiffusionPipeline.__call__
181
+ "width": width,
182
+ "height": height,
183
+ "num_inference_steps": num_inference_steps,
184
+ "guidance_scale": guidance_scale,
185
+ "negative_prompt": negative_prompt,
186
+ "controlnet_conditioning_scale": controlnet_conditioning_scale,
187
+ "clip_skip": model_config[model_name]["clip_skip"],
188
+ },
189
+ }
190
+ duplicate_data = [data.copy() for _ in range(num_images)]
191
+ for i, d in enumerate(duplicate_data):
192
+ d["seed"] = seeds[i]
193
+ # Call the NicheImage API
194
+ loop = get_or_create_eventloop()
195
+ asyncio.set_event_loop(loop)
196
+ output = loop.run_until_complete(
197
+ get_output(
198
+ "http://proxy_client_nicheimage.nichetensor.com:10003/generate",
199
+ duplicate_data,
200
+ )
201
+ )
202
+ while len(output) < 4:
203
+ output.append(None)
204
+ for i, image in enumerate(output):
205
+ if not image:
206
+ output[i] = Image.new("RGB", (width, height), (0, 0, 0))
207
+ print(output)
208
+ if output:
209
+ st.toast("Your image has been generated!", icon="😍")
210
+ end_time = time.time()
211
+ status.update(
212
+ label=f"βœ… Images generated in {round(end_time-start_time, 3)} seconds",
213
+ state="complete",
214
+ expanded=False,
215
+ )
216
+
217
+ # Save generated image to session state
218
+ st.session_state.generated_image = output
219
+ captions = [f"Image {i+1} 🎈" for i in range(4)]
220
+ all_images = []
221
+ # Displaying the image
222
+ _, main_col, _ = st.columns([0.15, 0.7, 0.15])
223
+ with main_col:
224
+ cols_1 = st.columns(2)
225
+ cols_2 = st.columns(2)
226
+ with st.container(border=True):
227
+ for i, image in enumerate(
228
+ st.session_state.generated_image[:2]
229
+ ):
230
+ cols_1[i].image(
231
+ image,
232
+ caption=captions[i],
233
+ use_column_width=True,
234
+ output_format="PNG",
235
+ )
236
+ # Add image to the list
237
+ all_images.append(image)
238
+ for i, image in enumerate(
239
+ st.session_state.generated_image[2:]
240
+ ):
241
+ cols_2[i].image(
242
+ image,
243
+ caption=captions[i + 2],
244
+ use_column_width=True,
245
+ output_format="PNG",
246
+ )
247
+
248
+ # Save all generated images to session state
249
+ st.session_state.all_images = all_images
250
+ zip_io = io.BytesIO()
251
+ # Download option for each image
252
+ with zipfile.ZipFile(zip_io, "w") as zipf:
253
+ for i, image in enumerate(st.session_state.all_images):
254
+ image_data = io.BytesIO()
255
+ image.save(image_data, format="PNG")
256
+ image_data.seek(0)
257
+ # Write each image to the zip file with a name
258
+ zipf.writestr(
259
+ f"output_file_{i+1}.png", image_data.read()
260
+ )
261
+ # Create a download button for the zip file
262
+ st.download_button(
263
+ ":red[**Download All Images**]",
264
+ data=zip_io.getvalue(),
265
+ file_name="output_files.zip",
266
+ mime="application/zip",
267
+ use_container_width=True,
268
+ )
269
+ status.update(
270
+ label="βœ… Images generated!", state="complete", expanded=False
271
+ )
272
+ except Exception as e:
273
+ print(e)
274
+ st.error(f"Encountered an error: {e}", icon="🚨")
275
+
276
+ # If not submitted, chill here 🍹
277
+ else:
278
+ pass
pages/1_🎨_Text_To_Image.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import base64
3
+ import io
4
+ import random
5
+ import time
6
+ from typing import List
7
+ from PIL import Image
8
+ import aiohttp
9
+ import asyncio
10
+ from streamlit_image_select import image_select
11
+ import requests
12
+ import streamlit as st
13
+ import requests
14
+ import zipfile
15
+ import io
16
+ import pandas as pd
17
+ from core import *
18
+ from utils import icon
19
+ from streamlit_image_select import image_select
20
+ from PIL import Image
21
+ import random
22
+ import time
23
+ import base64
24
+ from typing import List
25
+ import aiohttp
26
+ import asyncio
27
+ import plotly.express as px
28
+ from common import set_page_container_style
29
+
30
+ replicate_text = "NicheImage - Subnet 23 - Bittensor"
31
+ replicate_logo = "assets/NicheTensorTransparent.png"
32
+ replicate_link = "https://github.com/NicheTensor/NicheImage"
33
+
34
+ st.set_page_config(
35
+ page_title="NicheImage Generator", page_icon=replicate_logo, layout="wide"
36
+ )
37
+ set_page_container_style(
38
+ max_width=1100,
39
+ max_width_100_percent=True,
40
+ padding_top=0,
41
+ padding_right=10,
42
+ padding_left=5,
43
+ padding_bottom=10,
44
+ )
45
+
46
+
47
+ def get_or_create_eventloop():
48
+ try:
49
+ return asyncio.get_event_loop()
50
+ except RuntimeError as ex:
51
+ if "There is no current event loop in thread" in str(ex):
52
+ loop = asyncio.new_event_loop()
53
+ asyncio.set_event_loop(loop)
54
+ return asyncio.get_event_loop()
55
+
56
+
57
+ # UI configurations
58
+ st.markdown(
59
+ """<style>
60
+ #root > div:nth-child(1) > div > div > div > div > section > div {padding-top: 2rem;}
61
+ </style>
62
+
63
+ """,
64
+ unsafe_allow_html=True,
65
+ )
66
+ css = """
67
+ <style>
68
+ section.main > div:has(~ footer ) {
69
+ padding-bottom: 5px;
70
+ }
71
+ </style>
72
+ """
73
+ st.markdown(css, unsafe_allow_html=True)
74
+
75
+ # API Tokens and endpoints from `.streamlit/secrets.toml` file
76
+ API_TOKEN = st.secrets["API_TOKEN"]
77
+ # Placeholders for images and gallery
78
+ generated_images_placeholder = st.empty()
79
+ gallery_placeholder = st.empty()
80
+
81
+
82
+ def configure_sidebar() -> None:
83
+ """
84
+ Setup and display the sidebar elements.
85
+
86
+ This function configures the sidebar of the Streamlit application,
87
+ including the form for user inputs and the resources section.
88
+ """
89
+ with st.sidebar:
90
+ st.image(replicate_logo, use_column_width=True)
91
+ with st.form("my_form"):
92
+ model_name = st.selectbox(
93
+ ":blue[**Select Model**]",
94
+ options=[
95
+ "RealisticVision",
96
+ "AnimeV3",
97
+ "DreamShaper",
98
+ "RealitiesEdgeXL",
99
+ ],
100
+ )
101
+ prompt = st.text_area(
102
+ ":blue[**Enter prompt ✍🏾**]",
103
+ value="cinematic still of a shiba inu, fluffy neck, wearing a suit of ornate metal armor",
104
+ )
105
+ aspect_ratio = st.selectbox(
106
+ ":blue[**Aspect Ratio**]", options=["Tall", "Wide", "Square"]
107
+ )
108
+ num_images = 4
109
+ negative_prompt = st.text_area(
110
+ ":blue[**Negative Prompt πŸ™…πŸ½β€β™‚οΈ**]",
111
+ value="low quality, blurry, pixelated, noisy, low resolution, defocused, out of focus, overexposed, bad image, nsfw",
112
+ help="This is a negative prompt, basically type what you don't want to see in the generated image",
113
+ )
114
+ with st.expander(
115
+ "πŸ“š Advanced",
116
+ expanded=False,
117
+ ):
118
+ uid = st.text_input("Specify an UID", value="-1")
119
+ secret_key = st.text_input("Enter secret key", value="")
120
+ seed = st.text_input("Seed", value="-1")
121
+ # The Big Red "Submit" Button!
122
+ submitted = st.form_submit_button(
123
+ "Submit", type="primary", use_container_width=True
124
+ )
125
+
126
+ return (
127
+ submitted,
128
+ model_name,
129
+ prompt,
130
+ negative_prompt,
131
+ aspect_ratio,
132
+ num_images,
133
+ uid,
134
+ secret_key,
135
+ seed,
136
+ "",
137
+ )
138
+
139
+
140
+ def main():
141
+ """
142
+ Main function to run the Streamlit application.
143
+
144
+ This function initializes the sidebar configuration and the main page layout.
145
+ It retrieves the user inputs from the sidebar, and passes them to the main page function.
146
+ The main page function then generates images based on these inputs.
147
+ """
148
+ (
149
+ submitted,
150
+ model_name,
151
+ prompt,
152
+ negative_prompt,
153
+ aspect_ratio,
154
+ num_images,
155
+ uid,
156
+ secret_key,
157
+ seed,
158
+ conditional_image,
159
+ ) = configure_sidebar()
160
+ main_page(
161
+ submitted,
162
+ model_name,
163
+ prompt,
164
+ negative_prompt,
165
+ aspect_ratio,
166
+ num_images,
167
+ uid,
168
+ secret_key,
169
+ seed,
170
+ conditional_image,
171
+ [],
172
+ "txt2img",
173
+ API_TOKEN,
174
+ generated_images_placeholder,
175
+ )
176
+ if not submitted:
177
+ with gallery_placeholder.container():
178
+ with st.container():
179
+ st.info(
180
+ "πŸ‘©πŸΎβ€πŸ³ :blue[**Realistic Vision Style - [CivitAI](https://civitai.com/models/4201/realistic-vision-v60-b1)**]"
181
+ )
182
+ st.balloons()
183
+ with st.container(border=True):
184
+ _ = image_select(
185
+ label="",
186
+ images=[
187
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/401d2674-e1f8-4976-a615-36110d0b76b3/original=true/ref-res-1.jpeg",
188
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/d2050c06-e916-4091-857a-66bdafcaf6d9/original=true/00029-913302605.jpeg",
189
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/0012d0e9-6d77-4981-b16e-13ac9f3eeb53/original=true/00011-836818560.jpeg",
190
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/088542b8-00dc-4135-8115-f2086ebb4ffb/original=true/06772-2405195618-HDR,UHD,8K,Highly%20detailed,best%20quality,masterpiece,_lora_catman_0.8_,maomi,blurry%20background,blurry,sunglasses,hat,hands%20in%20poc.jpeg",
191
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/3b23b565-9b7b-4e5b-9a40-ff9b5e80565d/original=true/00076-329187343.jpeg",
192
+ ],
193
+ use_container_width=False,
194
+ )
195
+ with st.container():
196
+ st.info(
197
+ "πŸ‘©πŸΎβ€πŸ³ :blue[**DreamShaper Style - [CivitAI](https://civitai.com/models/4384/dreamshaper)**]"
198
+ )
199
+ with st.container(border=True):
200
+ _ = image_select(
201
+ label="",
202
+ images=[
203
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/af837eea-2ccc-4801-b916-75ecb270c382/original=true/71584-4007479174-masterpiece,%20a%20dinosaur%20(in%20the%20museum_1.2),%20background%20is%20museum%20exhibition,%20(art%20by%20YRAX_1.1),%20saturated%20colors,%20concept%20art,.jpeg",
204
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/77940ee3-062a-4d2b-95c4-52c69b79fffd/original=true/00524-2430470379.jpeg",
205
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/1649bcd9-4417-4c83-97f8-674373b67d61/original=true/42445-1548916933-wabstyle,%20monochrome,%20_lora_wabstyle_1_%20a%20dog.jpeg",
206
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/09264ecb-38c6-42ed-a2f7-a7ab5ab662fb/original=true/00262-5775713%20-%20Kopie.jpeg",
207
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/a25faadc-7370-426d-9e95-1e102a10e508/original=true/00613-787076454-(a%20Glass%20ring_1.3),%20masterpiece,%20best%20quality,%20_lora_RingArt_Sora_0.8_,%20(style%20of%20Ellen%20Gallagher_1.3)__(masterpiece,%20best%20quali%20(1).jpeg",
208
+ ],
209
+ use_container_width=False,
210
+ )
211
+ with st.container():
212
+ st.info(
213
+ "πŸ‘©πŸΎβ€πŸ³ :blue[**AnimeV3 Style - [CivitAI](https://civitai.com/models/146113/newdream-sdxl)**]"
214
+ )
215
+ with st.container(border=True):
216
+ _ = image_select(
217
+ label="",
218
+ images=[
219
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/c788e346-7af1-4135-928a-c944634a4a51/original=true/Soldier.jpeg",
220
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/dc86e78e-7587-45b8-b709-b6f611af68fa/original=true/pirate%20(3).jpeg",
221
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/cb6aa6c4-6cd6-4efd-84a8-4b3917ca4d24/original=true/00000-1761366536.jpeg",
222
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/61cad059-f9d8-446f-b33d-b22e078ac5fb/original=true/Scream.jpeg",
223
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/58d55973-12c9-4854-afbc-4fbd8f5434ef/original=true/CarSakura.jpeg",
224
+ ],
225
+ use_container_width=False,
226
+ )
227
+ with st.container():
228
+ st.info(
229
+ "πŸ‘©πŸΎβ€πŸ³ :blue[**RealitiesEdgeXL Style - [CivitAI](https://civitai.com/models/129666?modelVersionId=356472)**]"
230
+ )
231
+ with st.container(border=True):
232
+ _ = image_select(
233
+ label="",
234
+ images=[
235
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/7ae8de93-3634-4fb2-acb6-7ba66a630670/original=true/00044-3526680654.jpeg",
236
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/d7a3e977-5433-46d0-82ba-4946386bd28e/original=true/00135-1518921975.jpeg",
237
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/c3852385-4c73-4821-ac6f-b9f0323c7d6f/original=true/08323--3358745561.jpeg",
238
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/7f6be0cf-4b58-4c16-aa8f-4c396fb135b2/original=true/ComfyUI-1-_01583_.jpeg",
239
+ "https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/e9ecf8ad-8f3b-4fc3-9eca-c59389e84a3f/original=true/08314--1054985950.jpeg",
240
+ ],
241
+ use_container_width=False,
242
+ )
243
+
244
+
245
+ if __name__ == "__main__":
246
+ main()
pages/2_🎨_Image_To_Image.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import base64
3
+ import io
4
+ import random
5
+ import time
6
+ from typing import List
7
+ from PIL import Image
8
+ import aiohttp
9
+ import asyncio
10
+ import requests
11
+ import streamlit as st
12
+ import requests
13
+ import zipfile
14
+ import io
15
+ import pandas as pd
16
+ from core import *
17
+ from utils import icon
18
+ from streamlit_image_select import image_select
19
+ from PIL import Image
20
+ import random
21
+ import time
22
+ import base64
23
+ from typing import List
24
+ import aiohttp
25
+ import asyncio
26
+ import plotly.express as px
27
+ from common import set_page_container_style
28
+
29
+ replicate_text = "NicheImage - Subnet 23 - Bittensor"
30
+ replicate_logo = "assets/NicheTensorTransparent.png"
31
+ replicate_link = "https://github.com/NicheTensor/NicheImage"
32
+
33
+ st.set_page_config(
34
+ page_title="NicheImage Generator", page_icon=replicate_logo, layout="wide"
35
+ )
36
+ set_page_container_style(
37
+ max_width=1100,
38
+ max_width_100_percent=True,
39
+ padding_top=0,
40
+ padding_right=10,
41
+ padding_left=5,
42
+ padding_bottom=10,
43
+ )
44
+
45
+
46
+ def get_or_create_eventloop():
47
+ try:
48
+ return asyncio.get_event_loop()
49
+ except RuntimeError as ex:
50
+ if "There is no current event loop in thread" in str(ex):
51
+ loop = asyncio.new_event_loop()
52
+ asyncio.set_event_loop(loop)
53
+ return asyncio.get_event_loop()
54
+
55
+
56
+ # UI configurations
57
+ st.markdown(
58
+ """<style>
59
+ #root > div:nth-child(1) > div > div > div > div > section > div {padding-top: 2rem;}
60
+ </style>
61
+
62
+ """,
63
+ unsafe_allow_html=True,
64
+ )
65
+ css = """
66
+ <style>
67
+ section.main > div:has(~ footer ) {
68
+ padding-bottom: 5px;
69
+ }
70
+ </style>
71
+ """
72
+ st.markdown(css, unsafe_allow_html=True)
73
+
74
+ # API Tokens and endpoints from `.streamlit/secrets.toml` file
75
+ API_TOKEN = st.secrets["API_TOKEN"]
76
+ # Placeholders for images and gallery
77
+ generated_images_placeholder = st.empty()
78
+ gallery_placeholder = st.empty()
79
+
80
+
81
+ def configure_sidebar() -> None:
82
+ """
83
+ Setup and display the sidebar elements.
84
+
85
+ This function configures the sidebar of the Streamlit application,
86
+ including the form for user inputs and the resources section.
87
+ """
88
+ with st.sidebar:
89
+ st.image(replicate_logo, use_column_width=True)
90
+ with st.form("my_form"):
91
+ model_name = st.selectbox(
92
+ ":blue[**Select Model**]",
93
+ options=["DreamShaper"],
94
+ )
95
+ prompt = st.text_area(
96
+ ":blue[**Enter prompt ✍🏾**]",
97
+ value="cinematic still of a shiba inu, fluffy neck, wearing a suit of ornate metal armor",
98
+ )
99
+ # aspect_ratio = st.selectbox(
100
+ # ":blue[**Aspect Ratio**]", options=["Tall", "Wide", "Square"]
101
+ # )
102
+ aspect_ratio = "Square"
103
+ conditional_image = st.file_uploader(
104
+ ":blue[**Upload your image**]",
105
+ type=["png", "jpg", "jpeg"],
106
+ help="Upload an image to condition the generation",
107
+ )
108
+ if conditional_image:
109
+ st.image(conditional_image)
110
+ # num_images = st.slider(":blue[**Number of images to generate**]", 1, 4, 1)
111
+ num_images = 4
112
+ negative_prompt = st.text_area(
113
+ ":blue[**Negative Prompt πŸ™…πŸ½β€β™‚οΈ**]",
114
+ value="low quality, blurry, pixelated, noisy, low resolution, defocused, out of focus, overexposed, bad image, nsfw",
115
+ help="This is a negative prompt, basically type what you don't want to see in the generated image",
116
+ )
117
+ with st.expander(
118
+ "πŸ“š Advanced",
119
+ expanded=False,
120
+ ):
121
+ uid = st.text_input("Specify an UID", value="-1")
122
+ secret_key = st.text_input("Enter secret key", value="")
123
+ seed = st.text_input("Seed", value="-1")
124
+ # The Big Red "Submit" Button!
125
+ submitted = st.form_submit_button(
126
+ "Submit", type="primary", use_container_width=True
127
+ )
128
+
129
+ return (
130
+ submitted,
131
+ model_name,
132
+ prompt,
133
+ negative_prompt,
134
+ aspect_ratio,
135
+ num_images,
136
+ uid,
137
+ secret_key,
138
+ seed,
139
+ conditional_image,
140
+ )
141
+
142
+
143
+ def main():
144
+ """
145
+ Main function to run the Streamlit application.
146
+
147
+ This function initializes the sidebar configuration and the main page layout.
148
+ It retrieves the user inputs from the sidebar, and passes them to the main page function.
149
+ The main page function then generates images based on these inputs.
150
+ """
151
+ (
152
+ submitted,
153
+ model_name,
154
+ prompt,
155
+ negative_prompt,
156
+ aspect_ratio,
157
+ num_images,
158
+ uid,
159
+ secret_key,
160
+ seed,
161
+ conditional_image,
162
+ ) = configure_sidebar()
163
+ if conditional_image:
164
+ conditional_image = Image.open(conditional_image)
165
+ conditional_image = pil_image_to_base64(conditional_image)
166
+ main_page(
167
+ submitted,
168
+ model_name,
169
+ prompt,
170
+ negative_prompt,
171
+ aspect_ratio,
172
+ num_images,
173
+ uid,
174
+ secret_key,
175
+ seed,
176
+ conditional_image,
177
+ [],
178
+ "img2img",
179
+ API_TOKEN,
180
+ generated_images_placeholder,
181
+ )
182
+ if not submitted:
183
+ st.info("🎨 Upload your image and imagine the possibilities!")
184
+ st.image(
185
+ "https://preview.redd.it/using-crude-drawings-for-composition-img2img-v0-v7adchf52oha1.jpg?auto=webp&s=1251ed1c567a04ec0cf17fe257fbac01b2d903bd"
186
+ )
187
+
188
+
189
+ if __name__ == "__main__":
190
+ main()
pages/3_🎨_Control_To_Image.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import base64
3
+ import io
4
+ import random
5
+ import time
6
+ from typing import List
7
+ from PIL import Image
8
+ import aiohttp
9
+ import asyncio
10
+ import requests
11
+ import streamlit as st
12
+ import requests
13
+ import zipfile
14
+ import io
15
+ import pandas as pd
16
+ from core import *
17
+ from utils import icon
18
+ from streamlit_image_select import image_select
19
+ from PIL import Image
20
+ import random
21
+ import time
22
+ import base64
23
+ from typing import List
24
+ import aiohttp
25
+ import asyncio
26
+ import plotly.express as px
27
+ from common import set_page_container_style
28
+
29
+ replicate_text = "NicheImage - Subnet 23 - Bittensor"
30
+ replicate_logo = "assets/NicheTensorTransparent.png"
31
+ replicate_link = "https://github.com/NicheTensor/NicheImage"
32
+
33
+ st.set_page_config(
34
+ page_title="NicheImage Generator", page_icon=replicate_logo, layout="wide"
35
+ )
36
+ set_page_container_style(
37
+ max_width=1100,
38
+ max_width_100_percent=True,
39
+ padding_top=0,
40
+ padding_right=10,
41
+ padding_left=5,
42
+ padding_bottom=10,
43
+ )
44
+
45
+
46
+ def get_or_create_eventloop():
47
+ try:
48
+ return asyncio.get_event_loop()
49
+ except RuntimeError as ex:
50
+ if "There is no current event loop in thread" in str(ex):
51
+ loop = asyncio.new_event_loop()
52
+ asyncio.set_event_loop(loop)
53
+ return asyncio.get_event_loop()
54
+
55
+
56
+ # UI configurations
57
+ st.markdown(
58
+ """<style>
59
+ #root > div:nth-child(1) > div > div > div > div > section > div {padding-top: 2rem;}
60
+ </style>
61
+
62
+ """,
63
+ unsafe_allow_html=True,
64
+ )
65
+ css = """
66
+ <style>
67
+ section.main > div:has(~ footer ) {
68
+ padding-bottom: 5px;
69
+ }
70
+ </style>
71
+ """
72
+ st.markdown(css, unsafe_allow_html=True)
73
+
74
+ # API Tokens and endpoints from `.streamlit/secrets.toml` file
75
+ API_TOKEN = st.secrets["API_TOKEN"]
76
+ # Placeholders for images and gallery
77
+ generated_images_placeholder = st.empty()
78
+ gallery_placeholder = st.empty()
79
+
80
+
81
+ def configure_sidebar() -> None:
82
+ """
83
+ Setup and display the sidebar elements.
84
+
85
+ This function configures the sidebar of the Streamlit application,
86
+ including the form for user inputs and the resources section.
87
+ """
88
+ with st.sidebar:
89
+ st.image(replicate_logo, use_column_width=True)
90
+ with st.form("my_form"):
91
+ model_name = st.selectbox(
92
+ ":blue[**Select Model**]",
93
+ options=["DreamShaper"],
94
+ )
95
+ prompt = st.text_area(
96
+ ":blue[**Enter prompt ✍🏾**]",
97
+ value="cinematic still of a shiba inu, fluffy neck, wearing a suit of ornate metal armor",
98
+ )
99
+ aspect_ratio = "Square"
100
+ conditional_image = st.file_uploader(
101
+ ":blue[**Upload your image**]",
102
+ type=["png", "jpg", "jpeg"],
103
+ help="Upload an image to condition the generation",
104
+ )
105
+ if conditional_image:
106
+ st.image(conditional_image)
107
+ with st.container(border=True):
108
+ canny_strength = st.slider(
109
+ ":blue[**Canny Strength**]",
110
+ min_value=0.0,
111
+ max_value=1.0,
112
+ value=0.5,
113
+ step=0.01,
114
+ help="Strength of the Canny ControlNet",
115
+ )
116
+ depth_strength = st.slider(
117
+ ":blue[**Depth Strength**]",
118
+ min_value=0.0,
119
+ max_value=1.0,
120
+ value=0.5,
121
+ step=0.01,
122
+ help="Strength of the Depth ControlNet",
123
+ )
124
+ mlsd_strength = st.slider(
125
+ ":blue[**MLSD Strength**]",
126
+ min_value=0.0,
127
+ max_value=1.0,
128
+ value=0.5,
129
+ step=0.01,
130
+ help="Strength of the MLSD ControlNet",
131
+ )
132
+ controlnet_conditioning_scale = [
133
+ canny_strength,
134
+ depth_strength,
135
+ mlsd_strength,
136
+ ]
137
+
138
+ num_images = 4
139
+ negative_prompt = st.text_area(
140
+ ":blue[**Negative Prompt πŸ™…πŸ½β€β™‚οΈ**]",
141
+ value="low quality, blurry, pixelated, noisy, low resolution, defocused, out of focus, overexposed, bad image, nsfw",
142
+ help="This is a negative prompt, basically type what you don't want to see in the generated image",
143
+ )
144
+ with st.expander(
145
+ "πŸ“š Advanced",
146
+ expanded=False,
147
+ ):
148
+ uid = st.text_input("Specify an UID", value="-1")
149
+ secret_key = st.text_input("Enter secret key", value="")
150
+ seed = st.text_input("Seed", value="-1")
151
+ # The Big Red "Submit" Button!
152
+ submitted = st.form_submit_button(
153
+ "Submit", type="primary", use_container_width=True
154
+ )
155
+
156
+ return (
157
+ submitted,
158
+ model_name,
159
+ prompt,
160
+ negative_prompt,
161
+ aspect_ratio,
162
+ num_images,
163
+ uid,
164
+ secret_key,
165
+ seed,
166
+ conditional_image,
167
+ controlnet_conditioning_scale,
168
+ )
169
+
170
+
171
+ def main():
172
+ """
173
+ Main function to run the Streamlit application.
174
+
175
+ This function initializes the sidebar configuration and the main page layout.
176
+ It retrieves the user inputs from the sidebar, and passes them to the main page function.
177
+ The main page function then generates images based on these inputs.
178
+ """
179
+ (
180
+ submitted,
181
+ model_name,
182
+ prompt,
183
+ negative_prompt,
184
+ aspect_ratio,
185
+ num_images,
186
+ uid,
187
+ secret_key,
188
+ seed,
189
+ conditional_image,
190
+ controlnet_conditioning_scale,
191
+ ) = configure_sidebar()
192
+ if conditional_image:
193
+ conditional_image = Image.open(conditional_image)
194
+ conditional_image = pil_image_to_base64(conditional_image)
195
+ main_page(
196
+ submitted,
197
+ model_name,
198
+ prompt,
199
+ negative_prompt,
200
+ aspect_ratio,
201
+ num_images,
202
+ uid,
203
+ secret_key,
204
+ seed,
205
+ conditional_image,
206
+ controlnet_conditioning_scale,
207
+ "controlnet_txt2img",
208
+ API_TOKEN,
209
+ generated_images_placeholder,
210
+ )
211
+ if not submitted:
212
+ with generated_images_placeholder.container():
213
+ st.info("🎨 :blue[**Canny Edge**]")
214
+ cols = st.columns(2)
215
+ with cols[0]:
216
+ st.image(
217
+ "https://huggingface.co/takuma104/controlnet_dev/resolve/main/gen_compare/control_images/converted/control_bird_canny.png",
218
+ use_column_width=True,
219
+ )
220
+ with cols[1]:
221
+ st.image(
222
+ "https://cdn-lfs.huggingface.co/repos/f4/f7/f4f7a7f70b5d098c5f2b46c19c2063eea26d6eba1488e9141804f6402b509cbb/3907d804ef04bcc1dd998ddb8dbd01ad6ffd071d6f13bd2e8a03936f7fe35f13?response-content-disposition=inline%3B+filename*%3DUTF-8%27%27output_bird_canny_1.png%3B+filename%3D%22output_bird_canny_1.png%22%3B&response-content-type=image%2Fpng&Expires=1709913845&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcwOTkxMzg0NX19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLWxmcy5odWdnaW5nZmFjZS5jby9yZXBvcy9mNC9mNy9mNGY3YTdmNzBiNWQwOThjNWYyYjQ2YzE5YzIwNjNlZWEyNmQ2ZWJhMTQ4OGU5MTQxODA0ZjY0MDJiNTA5Y2JiLzM5MDdkODA0ZWYwNGJjYzFkZDk5OGRkYjhkYmQwMWFkNmZmZDA3MWQ2ZjEzYmQyZThhMDM5MzZmN2ZlMzVmMTM%7EcmVzcG9uc2UtY29udGVudC1kaXNwb3NpdGlvbj0qJnJlc3BvbnNlLWNvbnRlbnQtdHlwZT0qIn1dfQ__&Signature=JplN20XzO7Y34tz-FkA3-cv4VRfIkzz9Tf8-Re7EdW-7%7EaBEItVnl5SDX44oSk-WeNFPfhcHg-b7RK1zlD6H1n3Zo7Y8JtMR1Z07%7ElZ6S6s80j1vpOrMmnkyB-7DcM9Mvi2ITDPXhOdYGnAK1GER1Zdg-ctVEkf7frNEj%7E5zcqJ1kFyRCJcjPHtgAtIAySOANk6BIZEWLEbZGM3b4swTMnNPUZZw5CYRp2dgGgVEo8i6xalR1l8rqvAxQ3yB4C5nfJURcqQLY1lkk9B58dhR6Afy5ZG-krqilv07R7HqbsS7GWq6w8BCEXA0E9cjQTqzqlpCZG0wH78vNE8GDdF6kQ__&Key-Pair-Id=KVTP0A1DKRTAX",
223
+ use_column_width=True,
224
+ )
225
+ st.info("🎨 :blue[**Depth Map**]")
226
+ cols2 = st.columns(2)
227
+ with st.container():
228
+ with cols2[0]:
229
+ st.image(
230
+ "https://huggingface.co/takuma104/controlnet_dev/resolve/main/gen_compare/control_images/converted/control_vermeer_depth.png",
231
+ use_column_width=True,
232
+ )
233
+ with cols2[1]:
234
+ st.image(
235
+ "https://cdn-lfs.huggingface.co/repos/f4/f7/f4f7a7f70b5d098c5f2b46c19c2063eea26d6eba1488e9141804f6402b509cbb/25c89f31165aa3c435b28deeb1e542c68b0dab496727403c1f3c7ded3b78fdd1?response-content-disposition=inline%3B+filename*%3DUTF-8%27%27output_vermeer_depth_2.png%3B+filename%3D%22output_vermeer_depth_2.png%22%3B&response-content-type=image%2Fpng&Expires=1709913950&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcwOTkxMzk1MH19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLWxmcy5odWdnaW5nZmFjZS5jby9yZXBvcy9mNC9mNy9mNGY3YTdmNzBiNWQwOThjNWYyYjQ2YzE5YzIwNjNlZWEyNmQ2ZWJhMTQ4OGU5MTQxODA0ZjY0MDJiNTA5Y2JiLzI1Yzg5ZjMxMTY1YWEzYzQzNWIyOGRlZWIxZTU0MmM2OGIwZGFiNDk2NzI3NDAzYzFmM2M3ZGVkM2I3OGZkZDE%7EcmVzcG9uc2UtY29udGVudC1kaXNwb3NpdGlvbj0qJnJlc3BvbnNlLWNvbnRlbnQtdHlwZT0qIn1dfQ__&Signature=b%7EhyTb-HRh2shXtGNEfhNrXU%7EsuQdyE0iTXVKpR76CDxlS147%7EYxiU%7E9JJAL1asz-vfUS5u%7ErtqIRfGkKAcU1DP8lqtGhIfDBi6iPNEyWoAWAGj7mF6y50qj7xeq2Iz4yWeHoiZpzotiWbMqCE6V6QKrHsaU2btHlHjlLsw4owh3ELXjHB6%7ENCKwH0uKLfABOBZzrOJOCilJU8VwiCRsk3QryLD3uywZMGDxyzd1vxnaBR4PTIrZ46FEatcXCpGdZ1ZJngtdiepdLRX4tI41gVk0fWYrQ5wOnMSudCQuCfVXvHRnoPwKUVcmF5mCa7smZykizITEmwg3ctW4W80pBA__&Key-Pair-Id=KVTP0A1DKRTAX",
236
+ use_column_width=True,
237
+ )
238
+ st.info("🎨 :blue[**MLSD**]")
239
+ cols3 = st.columns(2)
240
+ with st.container():
241
+ with cols3[0]:
242
+ st.image(
243
+ "https://huggingface.co/takuma104/controlnet_dev/resolve/main/gen_compare/control_images/converted/control_room_mlsd.png",
244
+ use_column_width=True,
245
+ )
246
+ with cols3[1]:
247
+ st.image(
248
+ "https://cdn-lfs.huggingface.co/repos/f4/f7/f4f7a7f70b5d098c5f2b46c19c2063eea26d6eba1488e9141804f6402b509cbb/92c95cf788f547ef7ea2da0fb45a0232864899ddd93c8f04d88b04f681216ad3?response-content-disposition=inline%3B+filename*%3DUTF-8%27%27output_room_mlsd_0.png%3B+filename%3D%22output_room_mlsd_0.png%22%3B&response-content-type=image%2Fpng&Expires=1709912870&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcwOTkxMjg3MH19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLWxmcy5odWdnaW5nZmFjZS5jby9yZXBvcy9mNC9mNy9mNGY3YTdmNzBiNWQwOThjNWYyYjQ2YzE5YzIwNjNlZWEyNmQ2ZWJhMTQ4OGU5MTQxODA0ZjY0MDJiNTA5Y2JiLzkyYzk1Y2Y3ODhmNTQ3ZWY3ZWEyZGEwZmI0NWEwMjMyODY0ODk5ZGRkOTNjOGYwNGQ4OGIwNGY2ODEyMTZhZDM%7EcmVzcG9uc2UtY29udGVudC1kaXNwb3NpdGlvbj0qJnJlc3BvbnNlLWNvbnRlbnQtdHlwZT0qIn1dfQ__&Signature=A9jKF1jw8YO8OFuB7CzbaeQrEdT8wuPZJnT%7E1gZTxBAot9-HBQypW4IMsP7XPCeWnfdJBH4EKcsfzP2RU2-y2%7ENHrJl6wd9n-Wyi5traDPUgoHlSGIe6BvEKJlkzUI7gf87ThVWNc6wI3kHZM0l3dESE0ID2e2aCKGNxUCfaV%7EBdyt-Myr0HbVQtfYR8SjW7Rdj5WCJy9vOZKS3y2nzfPsUZRNtup4Xw3EW%7Ei0BGomdrB%7EfoOj4A0CvuL-La8SxPz1a3AcakD0ti8P0TPIJ9FrjmWLr49t9gJvn2XMYD3mH8VVsSBsGDn6pjgTLS4FK0KvCu-lIqt14v1bF10wCzBA__&Key-Pair-Id=KVTP0A1DKRTAX",
249
+ use_column_width=True,
250
+ )
251
+
252
+
253
+ if __name__ == "__main__":
254
+ main()