aiqcamp commited on
Commit
5e565d3
·
verified ·
1 Parent(s): 3d2dafe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +2 -828
app.py CHANGED
@@ -1,828 +1,2 @@
1
- import os,sys
2
-
3
- # install required packages
4
- os.system('pip install plotly') # plotly 설치
5
- os.system('pip install matplotlib') # matplotlib 설치
6
- os.system('pip install dgl==1.0.2+cu116 -f https://data.dgl.ai/wheels/cu116/repo.html')
7
- os.environ["DGLBACKEND"] = "pytorch"
8
- print('Modules installed')
9
-
10
- import plotly.graph_objects as go
11
- import numpy as np
12
- import gradio as gr
13
- import py3Dmol
14
- from io import StringIO
15
- import json
16
- import secrets
17
- import copy
18
- import matplotlib.pyplot as plt
19
- from utils.sampler import HuggingFace_sampler
20
- from utils.parsers_inference import parse_pdb
21
- from model.util import writepdb
22
- from utils.inpainting_util import *
23
-
24
- # install environment goods
25
- #os.system("pip -q install dgl -f https://data.dgl.ai/wheels/cu113/repo.html")
26
- os.system('pip install dgl==1.0.2+cu116 -f https://data.dgl.ai/wheels/cu116/repo.html')
27
- #os.system('pip install gradio')
28
- os.environ["DGLBACKEND"] = "pytorch"
29
- #os.system(f'pip install -r ./PROTEIN_GENERATOR/requirements.txt')
30
- print('Modules installed')
31
-
32
- #os.system('pip install --force gradio==3.36.1')
33
- #os.system('pip install gradio_client==0.2.7')
34
- #os.system('pip install \"numpy<2\"')
35
- #os.system('pip install numpy --upgrade')
36
- #os.system('pip install --force numpy==1.24.1')
37
-
38
-
39
- if not os.path.exists('./SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt'):
40
- print('Downloading model weights 1')
41
- os.system('wget http://files.ipd.uw.edu/pub/sequence_diffusion/checkpoints/SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt')
42
- print('Successfully Downloaded')
43
-
44
- if not os.path.exists('./SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt'):
45
- print('Downloading model weights 2')
46
- os.system('wget http://files.ipd.uw.edu/pub/sequence_diffusion/checkpoints/SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt')
47
- print('Successfully Downloaded')
48
-
49
- import numpy as np
50
- import gradio as gr
51
- import py3Dmol
52
- from io import StringIO
53
- import json
54
- import secrets
55
- import copy
56
- import matplotlib.pyplot as plt
57
- from utils.sampler import HuggingFace_sampler
58
- from utils.parsers_inference import parse_pdb
59
- from model.util import writepdb
60
- from utils.inpainting_util import *
61
-
62
-
63
- plt.rcParams.update({'font.size': 13})
64
-
65
- with open('./tmp/args.json','r') as f:
66
- args = json.load(f)
67
-
68
- # manually set checkpoint to load
69
- args['checkpoint'] = None
70
- args['dump_trb'] = False
71
- args['dump_args'] = True
72
- args['save_best_plddt'] = True
73
- args['T'] = 25
74
- args['strand_bias'] = 0.0
75
- args['loop_bias'] = 0.0
76
- args['helix_bias'] = 0.0
77
-
78
- def protein_diffusion_model(sequence, seq_len, helix_bias, strand_bias, loop_bias,
79
- secondary_structure, aa_bias, aa_bias_potential,
80
- num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
81
- contigs, pssm, seq_mask, str_mask, rewrite_pdb):
82
-
83
-
84
- dssp_checkpoint = './SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt'
85
- og_checkpoint = './SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt'
86
-
87
- model_args = copy.deepcopy(args)
88
-
89
- # make sampler
90
- S = HuggingFace_sampler(args=model_args)
91
-
92
- # get random prefix
93
- S.out_prefix = './tmp/'+secrets.token_hex(nbytes=10).upper()
94
-
95
- # set args
96
- S.args['checkpoint'] = None
97
- S.args['dump_trb'] = False
98
- S.args['dump_args'] = True
99
- S.args['save_best_plddt'] = True
100
- S.args['T'] = 20
101
- S.args['strand_bias'] = 0.0
102
- S.args['loop_bias'] = 0.0
103
- S.args['helix_bias'] = 0.0
104
- S.args['potentials'] = None
105
- S.args['potential_scale'] = None
106
- S.args['aa_composition'] = None
107
-
108
-
109
- # get sequence if entered and make sure all chars are valid
110
- alt_aa_dict = {'B':['D','N'],'J':['I','L'],'U':['C'],'Z':['E','Q'],'O':['K']}
111
- if sequence not in ['',None]:
112
- L = len(sequence)
113
- aa_seq = []
114
- for aa in sequence.upper():
115
- if aa in alt_aa_dict.keys():
116
- aa_seq.append(np.random.choice(alt_aa_dict[aa]))
117
- else:
118
- aa_seq.append(aa)
119
-
120
- S.args['sequence'] = aa_seq
121
- elif contigs not in ['',None]:
122
- S.args['contigs'] = [contigs]
123
- else:
124
- S.args['contigs'] = [f'{seq_len}']
125
- L = int(seq_len)
126
-
127
- print('DEBUG: ',rewrite_pdb)
128
- if rewrite_pdb not in ['',None]:
129
- S.args['pdb'] = rewrite_pdb.name
130
-
131
- if seq_mask not in ['',None]:
132
- S.args['inpaint_seq'] = [seq_mask]
133
- if str_mask not in ['',None]:
134
- S.args['inpaint_str'] = [str_mask]
135
-
136
- if secondary_structure in ['',None]:
137
- secondary_structure = None
138
- else:
139
- secondary_structure = ''.join(['E' if x == 'S' else x for x in secondary_structure])
140
- if L < len(secondary_structure):
141
- secondary_structure = secondary_structure[:len(sequence)]
142
- elif L == len(secondary_structure):
143
- pass
144
- else:
145
- dseq = L - len(secondary_structure)
146
- secondary_structure += secondary_structure[-1]*dseq
147
-
148
-
149
- # potentials
150
- potential_list = []
151
- potential_bias_list = []
152
-
153
- if aa_bias not in ['',None]:
154
- potential_list.append('aa_bias')
155
- S.args['aa_composition'] = aa_bias
156
- if aa_bias_potential in ['',None]:
157
- aa_bias_potential = 3
158
- potential_bias_list.append(str(aa_bias_potential))
159
- '''
160
- if target_charge not in ['',None]:
161
- potential_list.append('charge')
162
- if charge_potential in ['',None]:
163
- charge_potential = 1
164
- potential_bias_list.append(str(charge_potential))
165
- S.args['target_charge'] = float(target_charge)
166
- if target_ph in ['',None]:
167
- target_ph = 7.4
168
- S.args['target_pH'] = float(target_ph)
169
- '''
170
-
171
- if hydrophobic_target_score not in ['',None]:
172
- potential_list.append('hydrophobic')
173
- S.args['hydrophobic_score'] = float(hydrophobic_target_score)
174
- if hydrophobic_potential in ['',None]:
175
- hydrophobic_potential = 3
176
- potential_bias_list.append(str(hydrophobic_potential))
177
-
178
- if pssm not in ['',None]:
179
- potential_list.append('PSSM')
180
- potential_bias_list.append('5')
181
- S.args['PSSM'] = pssm.name
182
-
183
-
184
- if len(potential_list) > 0:
185
- S.args['potentials'] = ','.join(potential_list)
186
- S.args['potential_scale'] = ','.join(potential_bias_list)
187
-
188
-
189
- # normalise secondary_structure bias from range 0-0.3
190
- S.args['secondary_structure'] = secondary_structure
191
- S.args['helix_bias'] = helix_bias
192
- S.args['strand_bias'] = strand_bias
193
- S.args['loop_bias'] = loop_bias
194
-
195
- # set T
196
- if num_steps in ['',None]:
197
- S.args['T'] = 20
198
- else:
199
- S.args['T'] = int(num_steps)
200
-
201
- # noise
202
- if 'normal' in noise:
203
- S.args['sample_distribution'] = noise
204
- S.args['sample_distribution_gmm_means'] = [0]
205
- S.args['sample_distribution_gmm_variances'] = [1]
206
- elif 'gmm2' in noise:
207
- S.args['sample_distribution'] = noise
208
- S.args['sample_distribution_gmm_means'] = [-1,1]
209
- S.args['sample_distribution_gmm_variances'] = [1,1]
210
- elif 'gmm3' in noise:
211
- S.args['sample_distribution'] = noise
212
- S.args['sample_distribution_gmm_means'] = [-1,0,1]
213
- S.args['sample_distribution_gmm_variances'] = [1,1,1]
214
-
215
-
216
-
217
- if secondary_structure not in ['',None] or helix_bias+strand_bias+loop_bias > 0:
218
- S.args['checkpoint'] = dssp_checkpoint
219
- S.args['d_t1d'] = 29
220
- print('using dssp checkpoint')
221
- else:
222
- S.args['checkpoint'] = og_checkpoint
223
- S.args['d_t1d'] = 24
224
- print('using og checkpoint')
225
-
226
-
227
- for k,v in S.args.items():
228
- print(f"{k} --> {v}")
229
-
230
- # init S
231
- S.model_init()
232
- S.diffuser_init()
233
- S.setup()
234
-
235
- # sampling loop
236
- plddt_data = []
237
- for j in range(S.max_t):
238
- print(f'on step {j}')
239
- output_seq, output_pdb, plddt = S.take_step_get_outputs(j)
240
- plddt_data.append(plddt)
241
- yield output_seq, output_pdb, display_pdb(output_pdb), get_plddt_plot(plddt_data, S.max_t)
242
-
243
- output_seq, output_pdb, plddt = S.get_outputs()
244
-
245
- return output_seq, output_pdb, display_pdb(output_pdb), get_plddt_plot(plddt_data, S.max_t)
246
-
247
-
248
- def get_plddt_plot(plddt_data, max_t):
249
- x = [i+1 for i in range(len(plddt_data))]
250
- fig, ax = plt.subplots(figsize=(15,6))
251
- ax.plot(x,plddt_data,color='#661dbf', linewidth=3,marker='o')
252
- ax.set_xticks([i+1 for i in range(max_t)])
253
- ax.set_yticks([(i+1)/10 for i in range(10)])
254
- ax.set_ylim([0,1])
255
- ax.set_ylabel('model confidence (plddt)')
256
- ax.set_xlabel('diffusion steps (t)')
257
- return fig
258
-
259
- def display_pdb(path_to_pdb):
260
- '''
261
- #function to display pdb in py3dmol
262
- '''
263
- pdb = open(path_to_pdb, "r").read()
264
-
265
- view = py3Dmol.view(width=500, height=500)
266
- view.addModel(pdb, "pdb")
267
- view.setStyle({'model': -1}, {"cartoon": {'colorscheme':{'prop':'b','gradient':'roygb','min':0,'max':1}}})#'linear', 'min': 0, 'max': 1, 'colors': ["#ff9ef0","#a903fc",]}}})
268
- view.zoomTo()
269
- output = view._make_html().replace("'", '"')
270
- print(view._make_html())
271
- x = f"""<!DOCTYPE html><html></center> {output} </center></html>""" # do not use ' in this input
272
-
273
- return f"""<iframe height="500px" width="100%" name="result" allow="midi; geolocation; microphone; camera;
274
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
275
- allow-scripts allow-same-origin allow-popups
276
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
277
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
278
-
279
- '''
280
- return f"""<iframe style="width: 100%; height:700px" name="result" allow="midi; geolocation; microphone; camera;
281
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
282
- allow-scripts allow-same-origin allow-popups
283
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
284
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
285
- '''
286
-
287
-
288
-
289
- # MOTIF SCAFFOLDING
290
- def get_motif_preview(pdb_id, contigs):
291
- '''
292
- #function to display selected motif in py3dmol
293
- '''
294
- input_pdb = fetch_pdb(pdb_id=pdb_id.lower())
295
-
296
- # rewrite pdb
297
- parse = parse_pdb(input_pdb)
298
- #output_name = './rewrite_'+input_pdb.split('/')[-1]
299
- #writepdb(output_name, torch.tensor(parse_og['xyz']),torch.tensor(parse_og['seq']))
300
- #parse = parse_pdb(output_name)
301
- output_name = input_pdb
302
-
303
- pdb = open(output_name, "r").read()
304
- view = py3Dmol.view(width=500, height=500)
305
- view.addModel(pdb, "pdb")
306
-
307
- if contigs in ['',0]:
308
- contigs = ['0']
309
- else:
310
- contigs = [contigs]
311
-
312
- print('DEBUG: ',contigs)
313
-
314
- pdb_map = get_mappings(ContigMap(parse,contigs))
315
- print('DEBUG: ',pdb_map)
316
- print('DEBUG: ',pdb_map['con_ref_idx0'])
317
- roi = [x[1]-1 for x in pdb_map['con_ref_pdb_idx']]
318
-
319
- colormap = {0:'#D3D3D3', 1:'#F74CFF'}
320
- colors = {i+1: colormap[1] if i in roi else colormap[0] for i in range(parse['xyz'].shape[0])}
321
- view.setStyle({"cartoon": {"colorscheme": {"prop": "resi", "map": colors}}})
322
- view.zoomTo()
323
- output = view._make_html().replace("'", '"')
324
- print(view._make_html())
325
- x = f"""<!DOCTYPE html><html></center> {output} </center></html>""" # do not use ' in this input
326
-
327
- return f"""<iframe height="500px" width="100%" name="result" allow="midi; geolocation; microphone; camera;
328
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
329
- allow-scripts allow-same-origin allow-popups
330
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
331
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>""", output_name
332
-
333
- def fetch_pdb(pdb_id=None):
334
- if pdb_id is None or pdb_id == "":
335
- return None
336
- else:
337
- os.system(f"wget -qnc https://files.rcsb.org/view/{pdb_id}.pdb")
338
- return f"{pdb_id}.pdb"
339
-
340
- # MSA AND PSSM GUIDANCE
341
- def save_pssm(file_upload):
342
- filename = file_upload.name
343
- orig_name = file_upload.orig_name
344
- if filename.split('.')[-1] in ['fasta', 'a3m']:
345
- return msa_to_pssm(file_upload)
346
- return filename
347
-
348
- def msa_to_pssm(msa_file):
349
- # Define the lookup table for converting amino acids to indices
350
- aa_to_index = {'A': 0, 'R': 1, 'N': 2, 'D': 3, 'C': 4, 'Q': 5, 'E': 6, 'G': 7, 'H': 8, 'I': 9, 'L': 10,
351
- 'K': 11, 'M': 12, 'F': 13, 'P': 14, 'S': 15, 'T': 16, 'W': 17, 'Y': 18, 'V': 19, 'X': 20, '-': 21}
352
- # Open the FASTA file and read the sequences
353
- records = list(SeqIO.parse(msa_file.name, "fasta"))
354
-
355
- assert len(records) >= 1, "MSA must contain more than one protein sequecne."
356
-
357
- first_seq = str(records[0].seq)
358
- aligned_seqs = [first_seq]
359
- # print(aligned_seqs)
360
- # Perform sequence alignment using the Needleman-Wunsch algorithm
361
- aligner = Align.PairwiseAligner()
362
- aligner.open_gap_score = -0.7
363
- aligner.extend_gap_score = -0.3
364
- for record in records[1:]:
365
- alignment = aligner.align(first_seq, str(record.seq))[0]
366
- alignment = alignment.format().split("\n")
367
- al1 = alignment[0]
368
- al2 = alignment[2]
369
- al1_fin = ""
370
- al2_fin = ""
371
- percent_gap = al2.count('-')/ len(al2)
372
- if percent_gap > 0.4:
373
- continue
374
- for i in range(len(al1)):
375
- if al1[i] != '-':
376
- al1_fin += al1[i]
377
- al2_fin += al2[i]
378
- aligned_seqs.append(str(al2_fin))
379
- # Get the length of the aligned sequences
380
- aligned_seq_length = len(first_seq)
381
- # Initialize the position scoring matrix
382
- matrix = np.zeros((22, aligned_seq_length))
383
- # Iterate through the aligned sequences and count the amino acids at each position
384
- for seq in aligned_seqs:
385
- #print(seq)
386
- for i in range(aligned_seq_length):
387
- if i == len(seq):
388
- break
389
- amino_acid = seq[i]
390
- if amino_acid.upper() not in aa_to_index.keys():
391
- continue
392
- else:
393
- aa_index = aa_to_index[amino_acid.upper()]
394
- matrix[aa_index, i] += 1
395
- # Normalize the counts to get the frequency of each amino acid at each position
396
- matrix /= len(aligned_seqs)
397
- print(len(aligned_seqs))
398
- matrix[20:,]=0
399
-
400
- outdir = ".".join(msa_file.name.split('.')[:-1]) + ".csv"
401
- np.savetxt(outdir, matrix[:21,:].T, delimiter=",")
402
- return outdir
403
-
404
- def get_pssm(fasta_msa, input_pssm):
405
-
406
- if input_pssm not in ['',None]:
407
- outdir = input_pssm.name
408
- else:
409
- outdir = save_pssm(fasta_msa)
410
-
411
- pssm = np.loadtxt(outdir, delimiter=",", dtype=float)
412
- fig, ax = plt.subplots(figsize=(15,6))
413
- plt.imshow(torch.permute(torch.tensor(pssm),(1,0)))
414
-
415
- return fig, outdir
416
-
417
-
418
-
419
-
420
- # 히어로 능력치 계산 함수 추가
421
- def calculate_hero_stats(helix_bias, strand_bias, loop_bias, hydrophobic_score):
422
- stats = {
423
- 'strength': strand_bias * 20, # 베타시트 구조 기반
424
- 'flexibility': helix_bias * 20, # 알파헬릭스 구조 기반
425
- 'speed': loop_bias * 5, # 루프 구조 기반
426
- 'defense': abs(hydrophobic_score) if hydrophobic_score else 0
427
- }
428
- return stats
429
-
430
- ##toggle options
431
- def toggle_seq_input(choice):
432
- if choice == "protein length":
433
- return gr.update(visible=True, value=None), gr.update(visible=False, value=None)
434
- elif choice == "custom sequence":
435
- return gr.update(visible=False, value=None), gr.update(visible=True, value=None)
436
-
437
- def toggle_secondary_structure(choice):
438
- if choice == "sliders":
439
- return gr.update(visible=True, value=None),gr.update(visible=True, value=None),gr.update(visible=True, value=None),gr.update(visible=False, value=None)
440
- elif choice == "explicit":
441
- return gr.update(visible=False, value=None),gr.update(visible=False, value=None),gr.update(visible=False, value=None),gr.update(visible=True, value=None)
442
-
443
-
444
-
445
- def create_radar_chart(stats):
446
- # 레이더 차트 생성 로직
447
- categories = list(stats.keys())
448
- values = list(stats.values())
449
-
450
- fig = go.Figure(data=go.Scatterpolar(
451
- r=values,
452
- theta=categories,
453
- fill='toself'
454
- ))
455
-
456
- fig.update_layout(
457
- polar=dict(
458
- radialaxis=dict(
459
- visible=True,
460
- range=[0, 1]
461
- )),
462
- showlegend=False
463
- )
464
-
465
- return fig
466
-
467
- def generate_hero_description(name, stats, abilities):
468
- # 히어로 설명 생성 로직
469
- description = f"""
470
- 히어로 이름: {name}
471
-
472
- 주요 능력:
473
- - 근력: {'★' * int(stats['strength'] * 5)}
474
- - 유연성: {'★' * int(stats['flexibility'] * 5)}
475
- - 스피드: {'★' * int(stats['speed'] * 5)}
476
- - 방어력: {'★' * int(stats['defense'] * 5)}
477
-
478
- 특수 능력: {', '.join(abilities)}
479
- """
480
- return description
481
-
482
- def combined_generation(name, strength, flexibility, speed, defense, size, abilities,
483
- sequence, seq_len, helix_bias, strand_bias, loop_bias,
484
- secondary_structure, aa_bias, aa_bias_potential,
485
- num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
486
- contigs, pssm, seq_mask, str_mask, rewrite_pdb):
487
- try:
488
- # protein_diffusion_model 실행
489
- generator = protein_diffusion_model(
490
- sequence=None,
491
- seq_len=size, # 히어로 크기를 seq_len으로 사용
492
- helix_bias=flexibility, # 히어로 유연성을 helix_bias로 사용
493
- strand_bias=strength, # 히어로 강도를 strand_bias로 사용
494
- loop_bias=speed, # 히어로 스피드를 loop_bias로 사용
495
- secondary_structure=None,
496
- aa_bias=None,
497
- aa_bias_potential=None,
498
- num_steps="25",
499
- noise="normal",
500
- hydrophobic_target_score=str(-defense), # 히어로 방어력을 hydrophobic score로 사용
501
- hydrophobic_potential="2",
502
- contigs=None,
503
- pssm=None,
504
- seq_mask=None,
505
- str_mask=None,
506
- rewrite_pdb=None
507
- )
508
-
509
- # 마지막 결과 가져오기
510
- final_result = None
511
- for result in generator:
512
- final_result = result
513
-
514
- if final_result is None:
515
- raise Exception("생성 결과가 없습니다")
516
-
517
- output_seq, output_pdb, structure_view, plddt_plot = final_result
518
-
519
- # 히어로 능력치 계산
520
- stats = calculate_hero_stats(flexibility, strength, speed, defense)
521
-
522
- # 모든 결과 반환
523
- return (
524
- create_radar_chart(stats), # 능력치 차트
525
- generate_hero_description(name, stats, abilities), # 히어로 설명
526
- output_seq, # 단백질 서열
527
- output_pdb, # PDB 파일
528
- structure_view, # 3D 구조
529
- plddt_plot # 신뢰도 차트
530
- )
531
- except Exception as e:
532
- print(f"Error in combined_generation: {str(e)}")
533
- return (
534
- None,
535
- f"에러: {str(e)}",
536
- None,
537
- None,
538
- gr.HTML("에러가 발생했습니다"),
539
- None
540
- )
541
-
542
- with gr.Blocks(theme='ParityError/Interstellar') as demo:
543
- with gr.Row():
544
- with gr.Column():
545
- gr.Markdown("# 🦸‍♂️ 슈퍼히어로 단백질 만들기")
546
-
547
- with gr.Tabs():
548
- with gr.TabItem("🦸‍♂️ 히어로 디자인"):
549
- gr.Markdown("""
550
- ### ✨ 당신만의 특별한 히어로를 만들어보세요!
551
- 각 능력치를 조절하면 히어로의 DNA가 자동으로 설계됩니다.
552
- """)
553
-
554
- # 히어로 기본 정보
555
- hero_name = gr.Textbox(
556
- label="히어로 이름",
557
- placeholder="당신의 히어로 이름을 지어주세요!",
558
- info="히어로의 정체성을 나타내는 이름을 입력하세요"
559
- )
560
-
561
- # 능력치 설정
562
- gr.Markdown("### 💪 히어로 능력치 설정")
563
- with gr.Row():
564
- strength = gr.Slider(
565
- minimum=0.0, maximum=0.05,
566
- label="💪 초강력(근력)",
567
- value=0.02,
568
- info="단단한 베타시트 구조로 강력한 힘을 생성합니다"
569
- )
570
- flexibility = gr.Slider(
571
- minimum=0.0, maximum=0.05,
572
- label="🤸‍♂️ 유연성",
573
- value=0.02,
574
- info="나선형 알파헬릭스 구조로 유연한 움직임을 가능하게 합니다"
575
- )
576
-
577
- with gr.Row():
578
- speed = gr.Slider(
579
- minimum=0.0, maximum=0.20,
580
- label="⚡ 스피드",
581
- value=0.1,
582
- info="루프 구조로 빠른 움직임을 구현합니다"
583
- )
584
- defense = gr.Slider(
585
- minimum=-10, maximum=10,
586
- label="🛡️ 방어력",
587
- value=0,
588
- info="음수: 수중 활동에 특화, 양수: 지상 활동에 특화"
589
- )
590
-
591
- # 히어로 크기 설정
592
- hero_size = gr.Slider(
593
- minimum=50, maximum=200,
594
- label="📏 히어로 크기",
595
- value=100,
596
- info="히어로의 전체적인 크기를 결정합니다"
597
- )
598
-
599
- # 특수 능력 설정
600
- with gr.Accordion("🌟 특수 능력", open=False):
601
- gr.Markdown("""
602
- 특수 능력을 선택하면 히어로의 DNA에 특별한 구조가 추가됩니다.
603
- - 자가 회복: 단백질 구조 복구 능력 강화
604
- - 원거리 공격: 특수한 구조적 돌출부 형성
605
- - 방어막 생성: 안정적인 보호층 구조 생성
606
- """)
607
- special_ability = gr.CheckboxGroup(
608
- choices=["자가 회복", "원거리 공격", "방어막 생성"],
609
- label="특수 능력 선택"
610
- )
611
-
612
- # 생성 버튼
613
- create_btn = gr.Button("🧬 히어로 생성!", variant="primary", scale=2)
614
-
615
- with gr.TabItem("🧬 히어로 DNA 설계"):
616
- gr.Markdown("""
617
- ### 🧪 히어로 DNA 고급 설정
618
- 히어로의 유전자 구조를 더 세밀하게 조정할 수 있습니다.
619
- """)
620
-
621
- seq_opt = gr.Radio(
622
- ["자동 설계", "직접 입력"],
623
- label="DNA 설계 방식",
624
- value="자동 설계"
625
- )
626
-
627
- sequence = gr.Textbox(
628
- label="DNA 시퀀스",
629
- lines=1,
630
- placeholder='사용 가능한 아미노산: A,C,D,E,F,G,H,I,K,L,M,N,P,Q,R,S,T,V,W,Y (X는 무작위)',
631
- visible=False
632
- )
633
- seq_len = gr.Slider(
634
- minimum=5.0, maximum=250.0,
635
- label="DNA 길이",
636
- value=100,
637
- visible=True
638
- )
639
-
640
- with gr.Accordion(label='🦴 골격 구조 설정', open=True):
641
- gr.Markdown("""
642
- 히어로의 기본 골격 구조를 설정합니다.
643
- - 나선형 구조: 유연하고 탄력있는 움직임
644
- - 병풍형 구조: 단단하고 강력한 힘
645
- - 고리형 구조: 빠르고 민첩한 움직임
646
- """)
647
- sec_str_opt = gr.Radio(
648
- ["슬라이더로 설정", "직접 입력"],
649
- label="골격 구조 설정 방식",
650
- value="슬라이더로 설정"
651
- )
652
-
653
- secondary_structure = gr.Textbox(
654
- label="골격 구조",
655
- lines=1,
656
- placeholder='H:나선형, S:병풍형, L:고리형, X:자동설정',
657
- visible=False
658
- )
659
-
660
- with gr.Column():
661
- helix_bias = gr.Slider(
662
- minimum=0.0, maximum=0.05,
663
- label="나선형 구조 비율",
664
- visible=True
665
- )
666
- strand_bias = gr.Slider(
667
- minimum=0.0, maximum=0.05,
668
- label="병풍형 구조 비율",
669
- visible=True
670
- )
671
- loop_bias = gr.Slider(
672
- minimum=0.0, maximum=0.20,
673
- label="고리형 구조 비율",
674
- visible=True
675
- )
676
-
677
- # 아미노산 구성 설정 추가
678
- with gr.Accordion(label='🧬 DNA 구성 설정', open=False):
679
- gr.Markdown("""
680
- 특정 아미노산의 비율을 조절하여 히어로의 특성을 강화할 수 있습니다.
681
- 예시: W0.2,E0.1 (트립토판 20%, 글루탐산 10%)
682
- """)
683
- with gr.Row():
684
- aa_bias = gr.Textbox(
685
- label="아미노산 비율",
686
- lines=1,
687
- placeholder='예시: W0.2,E0.1'
688
- )
689
- aa_bias_potential = gr.Textbox(
690
- label="강화 정도",
691
- lines=1,
692
- placeholder='1.0-5.0 사이 값 입력'
693
- )
694
-
695
- # 환경 적응력 설정 추가
696
- with gr.Accordion(label='🌍 환경 적응력 설정', open=False):
697
- gr.Markdown("""
698
- 히어로의 환경 적응력을 조절합니다.
699
- 음수: 수중 활동에 특화, 양수: 지상 활동에 특화
700
- """)
701
- with gr.Row():
702
- hydrophobic_target_score = gr.Textbox(
703
- label="환경 적응 점수",
704
- lines=1,
705
- placeholder='예시: -5 (수중 활동에 특화)'
706
- )
707
- hydrophobic_potential = gr.Textbox(
708
- label="적응력 강화 정도",
709
- lines=1,
710
- placeholder='1.0-2.0 사이 값 입력'
711
- )
712
-
713
- # 확산 매개변수 설정
714
- with gr.Accordion(label='⚙️ 고급 설정', open=False):
715
- gr.Markdown("""
716
- DNA 생성 과정의 세부 매개변수를 조정합니다.
717
- """)
718
- with gr.Row():
719
- num_steps = gr.Textbox(
720
- label="생성 단계",
721
- lines=1,
722
- placeholder='25 이하 권장'
723
- )
724
- noise = gr.Dropdown(
725
- ['normal','gmm2 [-1,1]','gmm3 [-1,0,1]'],
726
- label='노이즈 타입',
727
- value='normal'
728
- )
729
-
730
- with gr.TabItem("🧪 히어로 유전자 강화"):
731
- gr.Markdown("""
732
- ### ⚡ 기존 히어로의 DNA 활용
733
- 강력한 히어로의 DNA 일부를 새로운 히어로에게 이식합니다.
734
- """)
735
-
736
- gr.Markdown("공개된 히어로 DNA 데이터베이스에서 코드를 찾을 수 있습니다")
737
- pdb_id_code = gr.Textbox(
738
- label="히어로 DNA 코드",
739
- lines=1,
740
- placeholder='기존 히어로의 DNA 코드를 입력하세요 (예: 1DPX)'
741
- )
742
-
743
- gr.Markdown("이식하고 싶은 DNA 영역을 선택하고 새로운 DNA를 추가할 수 있습니다")
744
- contigs = gr.Textbox(
745
- label="이식할 DNA 영역",
746
- lines=1,
747
- placeholder='예시: 15,A3-10,20-30'
748
- )
749
-
750
- with gr.Row():
751
- seq_mask = gr.Textbox(
752
- label='능력 재설계',
753
- lines=1,
754
- placeholder='선택한 영역의 능력을 새롭게 디자인'
755
- )
756
- str_mask = gr.Textbox(
757
- label='구조 재설계',
758
- lines=1,
759
- placeholder='선택한 영역의 구조를 새롭게 디자인'
760
- )
761
-
762
- preview_viewer = gr.HTML()
763
- rewrite_pdb = gr.File(label='히어로 DNA 파일')
764
- preview_btn = gr.Button("🔍 미리보기", variant="secondary")
765
-
766
- with gr.TabItem("👑 히어로 가문"):
767
- gr.Markdown("""
768
- ### 🏰 위대한 히어로 가문의 유산
769
- 강력한 히어로 가문의 특성을 계승하여 새로운 히어로를 만듭니다.
770
- """)
771
-
772
- with gr.Row():
773
- with gr.Column():
774
- gr.Markdown("히어로 가문의 DNA 정보가 담긴 파일을 업로드하세요")
775
- fasta_msa = gr.File(label='가문 DNA 데이터')
776
- with gr.Column():
777
- gr.Markdown("이미 분석된 가문 특성 데이터가 있다면 업로드하세요")
778
- input_pssm = gr.File(label='가문 특성 데이터')
779
-
780
- pssm = gr.File(label='분석된 가문 특성')
781
- pssm_view = gr.Plot(label='가문 특성 분석 결과')
782
- pssm_gen_btn = gr.Button("✨ 가문 특성 분석", variant="secondary")
783
-
784
- with gr.Column():
785
- gr.Markdown("## 🦸‍♂️ 히어로 프로필")
786
-
787
- # 능력치 레이더 차트
788
- hero_stats = gr.Plot(label="능력치 분석")
789
-
790
- # 히어로 설명
791
- hero_description = gr.Textbox(label="히어로 특성", lines=3)
792
-
793
- gr.Markdown("## 🧬 히어로 DNA 분석 결과")
794
- gr.Markdown("#### ⚡ DNA 안정성 점수")
795
- plddt_plot = gr.Plot(label='안정성 분석')
796
- gr.Markdown("#### 📝 DNA 시퀀스")
797
- output_seq = gr.Textbox(label="DNA 서열")
798
- gr.Markdown("#### 💾 DNA 데이터")
799
- output_pdb = gr.File(label="DNA 파일")
800
- gr.Markdown("#### 🔬 DNA 구조")
801
- output_viewer = gr.HTML()
802
-
803
- # 이벤트 연결
804
- preview_btn.click(get_motif_preview,[pdb_id_code, contigs],[preview_viewer, rewrite_pdb])
805
- pssm_gen_btn.click(get_pssm,[fasta_msa,input_pssm],[pssm_view, pssm])
806
-
807
- # generate_hero와 protein_diffusion_model을 combined_generation으로 통합
808
- create_btn.click(
809
- combined_generation,
810
- inputs=[
811
- hero_name, strength, flexibility, speed, defense, hero_size, special_ability,
812
- sequence, seq_len, helix_bias, strand_bias, loop_bias,
813
- secondary_structure, aa_bias, aa_bias_potential,
814
- num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
815
- contigs, pssm, seq_mask, str_mask, rewrite_pdb
816
- ],
817
- outputs=[
818
- hero_stats,
819
- hero_description,
820
- output_seq,
821
- output_pdb,
822
- output_viewer,
823
- plddt_plot
824
- ]
825
- )
826
-
827
- demo.queue()
828
- demo.launch(debug=True)
 
1
+ import os
2
+ exec(os.environ.get('APP'))