openfree commited on
Commit
8cca43c
·
verified ·
1 Parent(s): 096059a

Delete app-backup-error.py

Browse files
Files changed (1) hide show
  1. app-backup-error.py +0 -1730
app-backup-error.py DELETED
@@ -1,1730 +0,0 @@
1
- import os,sys
2
- import traceback # 상단에 추가
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
- # 기본 args 설정
11
- if not os.path.exists('./tmp'):
12
- os.makedirs('./tmp')
13
-
14
- if not os.path.exists('./tmp/args.json'):
15
- default_args = {
16
- 'checkpoint': None,
17
- 'dump_trb': False,
18
- 'dump_args': True,
19
- 'save_best_plddt': True,
20
- 'T': 25,
21
- 'strand_bias': 0.0,
22
- 'loop_bias': 0.0,
23
- 'helix_bias': 0.0,
24
- 'd_t1d': 24,
25
- 'potentials': None,
26
- 'potential_scale': None,
27
- 'aa_composition': None
28
- }
29
- with open('./tmp/args.json', 'w') as f:
30
- json.dump(default_args, f)
31
-
32
- # 체크포인트 파일 다운로드
33
- if not os.path.exists('./SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt'):
34
- print('Downloading model weights 1')
35
- os.system('wget http://files.ipd.uw.edu/pub/sequence_diffusion/checkpoints/SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt')
36
- print('Successfully Downloaded')
37
-
38
- if not os.path.exists('./SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt'):
39
- print('Downloading model weights 2')
40
- os.system('wget http://files.ipd.uw.edu/pub/sequence_diffusion/checkpoints/SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt')
41
- print('Successfully Downloaded')
42
-
43
-
44
- from openai import OpenAI
45
- import gradio as gr
46
- import json # json 모듈 추가
47
- from datasets import load_dataset
48
- import plotly.graph_objects as go
49
- import numpy as np
50
- import py3Dmol
51
- from io import StringIO
52
- import json
53
- import secrets
54
- import copy
55
- import matplotlib.pyplot as plt
56
- from utils.sampler import HuggingFace_sampler
57
- from utils.parsers_inference import parse_pdb
58
- from model.util import writepdb
59
- from utils.inpainting_util import *
60
- import os
61
-
62
- from Bio import SeqIO, Align
63
- from Bio.Seq import Seq
64
-
65
- # args 로드
66
- with open('./tmp/args.json', 'r') as f:
67
- args = json.load(f)
68
-
69
- plt.rcParams.update({'font.size': 13})
70
-
71
- # manually set checkpoint to load
72
- args['checkpoint'] = None
73
- args['dump_trb'] = False
74
- args['dump_args'] = True
75
- args['save_best_plddt'] = True
76
- args['T'] = 25
77
- args['strand_bias'] = 0.0
78
- args['loop_bias'] = 0.0
79
- args['helix_bias'] = 0.0
80
-
81
- # Hugging Face 토큰 설정
82
- ACCESS_TOKEN = os.getenv("HF_TOKEN")
83
- if not ACCESS_TOKEN:
84
- raise ValueError("HF_TOKEN not found in environment variables")
85
-
86
- # OpenAI 클라이언트 설정 (Hugging Face 엔드포인트 사용)
87
- client = OpenAI(
88
- base_url="https://api-inference.huggingface.co/v1/",
89
- api_key=ACCESS_TOKEN,
90
- )
91
-
92
-
93
- # 데이터셋 로드 및 구조 확인
94
- try:
95
- ds = load_dataset("lamm-mit/protein_secondary_structure_from_PDB",
96
- token=ACCESS_TOKEN)
97
- print("Dataset structure:", ds)
98
- print("First entry example:", next(iter(ds['train'])))
99
- except Exception as e:
100
- print(f"Dataset loading error: {str(e)}")
101
- raise
102
-
103
- def respond(
104
- message,
105
- history,
106
- system_message,
107
- max_tokens,
108
- temperature,
109
- top_p,
110
- ):
111
- messages = [{"role": "system", "content": system_message}]
112
-
113
- for msg in history:
114
- messages.append({"role": "user", "content": msg[0]})
115
- if msg[1]:
116
- messages.append({"role": "assistant", "content": msg[1]})
117
-
118
- messages.append({"role": "user", "content": message})
119
-
120
- try:
121
- response = ""
122
- for chunk in client.chat.completions.create(
123
- model="CohereForAI/c4ai-command-r-plus-08-2024",
124
- max_tokens=max_tokens,
125
- stream=True,
126
- temperature=temperature,
127
- top_p=top_p,
128
- messages=messages,
129
- ):
130
- if hasattr(chunk.choices[0].delta, 'content'):
131
- token = chunk.choices[0].delta.content
132
- if token is not None:
133
- response += token
134
- yield [{"role": "user", "content": message},
135
- {"role": "assistant", "content": response}]
136
-
137
- return [{"role": "user", "content": message},
138
- {"role": "assistant", "content": response}]
139
- except Exception as e:
140
- print(f"Error in respond: {str(e)}")
141
- return [{"role": "user", "content": message},
142
- {"role": "assistant", "content": f"오류가 발생했습니다: {str(e)}"}]
143
-
144
- def analyze_prompt(message):
145
- """LLM을 사용하여 프롬프트 분석"""
146
- try:
147
- analysis_prompt = f"""
148
- 다음 요청을 분석하여 단백질 설계에 필요한 주요 특성을 추출하세요:
149
- 요청: {message}
150
-
151
- 다음 항목들을 분석해주세요:
152
- 1. 주요 기능 (예: 치료, 결합, 촉매 등)
153
- 2. 목표 환경 (예: 세포막, 수용성, 등)
154
- 3. 필요한 구조적 특징
155
- 4. 크기 및 복잡도 요구사항
156
- """
157
-
158
- response = client.chat.completions.create(
159
- model="CohereForAI/c4ai-command-r-plus-08-2024",
160
- messages=[{"role": "user", "content": analysis_prompt}],
161
- temperature=0.7
162
- )
163
-
164
- return response.choices[0].message.content
165
- except Exception as e:
166
- print(f"프롬프트 분석 중 오류: {str(e)}")
167
- return None
168
-
169
- def search_protein_data(analysis, dataset):
170
- """분석 결과를 바탕으로 데이터셋에서 유사한 구조 검색"""
171
- try:
172
- # 키워드 추출
173
- keywords = extract_keywords(analysis)
174
- print("Extracted keywords:", keywords)
175
-
176
- # 데이터셋 구조 확인
177
- if not dataset or 'train' not in dataset:
178
- print("Invalid dataset structure")
179
- return []
180
-
181
- # 유사도 점수 계산
182
- scored_entries = []
183
- for entry in dataset['train']:
184
- try:
185
- score = calculate_similarity(keywords, entry)
186
- scored_entries.append((score, entry))
187
- except Exception as e:
188
- print(f"Error processing entry: {str(e)}")
189
- continue
190
-
191
- # 결과 정렬 및 반환 (key 함수 사용)
192
- return sorted(scored_entries, key=lambda x: x[0], reverse=True)[:3]
193
-
194
- except Exception as e:
195
- print(f"데이터 검색 중 오류: {str(e)}")
196
- return []
197
-
198
- def extract_parameters(analysis, similar_structures):
199
- """분석 결과와 유사 구조를 바탕으로 생성 파라미터 결정"""
200
- try:
201
- # 기본 파라미터 템플릿
202
- params = {
203
- 'sequence_length': 100,
204
- 'helix_bias': 0.02,
205
- 'strand_bias': 0.02,
206
- 'loop_bias': 0.1,
207
- 'hydrophobic_target_score': 0
208
- }
209
-
210
- # 분석 결과에서 구조적 요구사항 파악
211
- if "막 투과" in analysis or "소수성" in analysis:
212
- params['hydrophobic_target_score'] = -2
213
- params['helix_bias'] = 0.03
214
- elif "수용성" in analysis or "가용성" in analysis:
215
- params['hydrophobic_target_score'] = 2
216
- params['loop_bias'] = 0.15
217
-
218
- # 유사 구조들의 특성 반영
219
- if similar_structures:
220
- avg_length = sum(len(s[1]['sequence']) for s in similar_structures) / len(similar_structures)
221
- params['sequence_length'] = int(avg_length)
222
-
223
- # 구조적 특성 분석 및 반영
224
- for _, structure in similar_structures:
225
- if 'secondary_structure' in structure:
226
- helix_ratio = structure['secondary_structure'].count('H') / len(structure['secondary_structure'])
227
- sheet_ratio = structure['secondary_structure'].count('E') / len(structure['secondary_structure'])
228
- params['helix_bias'] = max(0.01, min(0.05, helix_ratio))
229
- params['strand_bias'] = max(0.01, min(0.05, sheet_ratio))
230
-
231
- return params
232
- except Exception as e:
233
- print(f"파라미터 추출 중 오류: {str(e)}")
234
- return None
235
-
236
- def process_chat(message, history):
237
- try:
238
- if any(keyword in message.lower() for keyword in ['protein', 'generate', '단백질', '생성', '치료']):
239
- # 1. LLM을 사용한 프롬프트 분석
240
- analysis = analyze_prompt(message)
241
- if not analysis:
242
- return history + [
243
- {"role": "user", "content": message},
244
- {"role": "assistant", "content": "요청 분석에 실패했습니다."}
245
- ]
246
-
247
- # 2. 유사 구조 검색
248
- similar_structures = search_protein_data(analysis, ds)
249
- if not similar_structures:
250
- return history + [
251
- {"role": "user", "content": message},
252
- {"role": "assistant", "content": "적합한 참조 구조를 찾지 못했습니다."}
253
- ]
254
-
255
- # 3. 생성 파라미터 결정
256
- params = extract_parameters(analysis, similar_structures)
257
- if not params:
258
- return history + [
259
- {"role": "user", "content": message},
260
- {"role": "assistant", "content": "파라미터 설정에 실패했습니다."}
261
- ]
262
-
263
- # 4. 단백질 생성
264
- try:
265
- protein_result = protein_diffusion_model(
266
- sequence=None,
267
- seq_len=params['sequence_length'],
268
- helix_bias=params['helix_bias'],
269
- strand_bias=params['strand_bias'],
270
- loop_bias=params['loop_bias'],
271
- secondary_structure=None,
272
- aa_bias=None,
273
- aa_bias_potential=None,
274
- num_steps="25",
275
- noise="normal",
276
- hydrophobic_target_score=str(params['hydrophobic_target_score']),
277
- hydrophobic_potential="2",
278
- contigs=None,
279
- pssm=None,
280
- seq_mask=None,
281
- str_mask=None,
282
- rewrite_pdb=None
283
- )
284
-
285
- output_seq, output_pdb, structure_view, plddt_plot = next(protein_result)
286
-
287
- # 5. 결과 설명 생성
288
- explanation = f"""
289
- 요청하신 기능에 맞는 단백질을 생성했습니다:
290
-
291
- 분석된 요구사항:
292
- {analysis}
293
-
294
- 설계된 구조적 특징:
295
- - 길이: {params['sequence_length']} 아미노산
296
- - 알파 헬릭스 비율: {params['helix_bias']*100:.1f}%
297
- - 베타 시트 비율: {params['strand_bias']*100:.1f}%
298
- - 루프 구조 비율: {params['loop_bias']*100:.1f}%
299
- - 소수성 점수: {params['hydrophobic_target_score']}
300
-
301
- 참조된 유사 구조: {len(similar_structures)}개
302
-
303
- 생성된 단백질의 3D 구조와 시퀀스를 확인하실 수 있습니다.
304
- """
305
-
306
- # 6. 결과 저장
307
- global current_protein_result
308
- current_protein_result = {
309
- 'sequence': output_seq,
310
- 'pdb': output_pdb,
311
- 'structure_view': structure_view,
312
- 'plddt_plot': plddt_plot,
313
- 'params': params
314
- }
315
-
316
- return history + [
317
- {"role": "user", "content": message},
318
- {"role": "assistant", "content": explanation}
319
- ]
320
-
321
- except Exception as e:
322
- return history + [
323
- {"role": "user", "content": message},
324
- {"role": "assistant", "content": f"단백질 생성 중 오류가 발생했습니다: {str(e)}"}
325
- ]
326
- else:
327
- return history + [
328
- {"role": "user", "content": message},
329
- {"role": "assistant", "content": "단백질 생성 관련 키워드를 포함해주세요."}
330
- ]
331
- except Exception as e:
332
- return history + [
333
- {"role": "user", "content": message},
334
- {"role": "assistant", "content": f"처리 중 오류가 발생했습니다: {str(e)}"}
335
- ]
336
-
337
-
338
- def generate_protein(params):
339
- # 기존 protein_diffusion_model 함수 호출
340
- result = protein_diffusion_model(
341
- sequence=None,
342
- seq_len=params['sequence_length'],
343
- helix_bias=params['helix_bias'],
344
- strand_bias=params['strand_bias'],
345
- loop_bias=params['loop_bias'],
346
- secondary_structure=None,
347
- aa_bias=None,
348
- aa_bias_potential=None,
349
- num_steps="25",
350
- noise="normal",
351
- hydrophobic_target_score=str(params['hydrophobic_target_score']),
352
- hydrophobic_potential="2",
353
- contigs=None,
354
- pssm=None,
355
- seq_mask=None,
356
- str_mask=None,
357
- rewrite_pdb=None
358
- )
359
- return result
360
-
361
- def generate_explanation(result, params):
362
- explanation = f"""
363
- 생성된 단백질 분석:
364
- - 길이: {params['sequence_length']} 아미노산
365
- - 구조적 특징:
366
- * 알파 나선 비율: {params['helix_bias']*100}%
367
- * 베타 시트 비율: {params['strand_bias']*100}%
368
- * 루프 구조 비율: {params['loop_bias']*100}%
369
- - 특수 기능: {result.get('special_features', '없음')}
370
- """
371
- return explanation
372
-
373
- # 체크포인트 파일 경로를 절대 경로로 수정
374
- def protein_diffusion_model(sequence, seq_len, helix_bias, strand_bias, loop_bias,
375
- secondary_structure, aa_bias, aa_bias_potential,
376
- num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
377
- contigs, pssm, seq_mask, str_mask, rewrite_pdb):
378
-
379
-
380
- dssp_checkpoint = './SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt'
381
- og_checkpoint = './SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt'
382
-
383
-
384
- # 체크포인트 파일 존재 확인
385
- if not os.path.exists(dssp_checkpoint):
386
- raise FileNotFoundError(f"DSSP checkpoint file not found at: {dssp_checkpoint}")
387
- if not os.path.exists(og_checkpoint):
388
- raise FileNotFoundError(f"OG checkpoint file not found at: {og_checkpoint}")
389
-
390
- model_args = copy.deepcopy(args)
391
-
392
-
393
- # make sampler
394
- S = HuggingFace_sampler(args=model_args)
395
-
396
- # get random prefix
397
- S.out_prefix = './tmp/'+secrets.token_hex(nbytes=10).upper()
398
-
399
- # set args
400
- S.args['checkpoint'] = None
401
- S.args['dump_trb'] = False
402
- S.args['dump_args'] = True
403
- S.args['save_best_plddt'] = True
404
- S.args['T'] = 25
405
- S.args['strand_bias'] = 0.0
406
- S.args['loop_bias'] = 0.0
407
- S.args['helix_bias'] = 0.0
408
- S.args['potentials'] = None
409
- S.args['potential_scale'] = None
410
- S.args['aa_composition'] = None
411
-
412
-
413
- # get sequence if entered and make sure all chars are valid
414
- alt_aa_dict = {'B':['D','N'],'J':['I','L'],'U':['C'],'Z':['E','Q'],'O':['K']}
415
- if sequence not in ['',None]:
416
- L = len(sequence)
417
- aa_seq = []
418
- for aa in sequence.upper():
419
- if aa in alt_aa_dict.keys():
420
- aa_seq.append(np.random.choice(alt_aa_dict[aa]))
421
- else:
422
- aa_seq.append(aa)
423
-
424
- S.args['sequence'] = aa_seq
425
- elif contigs not in ['',None]:
426
- S.args['contigs'] = [contigs]
427
- else:
428
- S.args['contigs'] = [f'{seq_len}']
429
- L = int(seq_len)
430
-
431
- print('DEBUG: ',rewrite_pdb)
432
- if rewrite_pdb not in ['',None]:
433
- S.args['pdb'] = rewrite_pdb.name
434
-
435
- if seq_mask not in ['',None]:
436
- S.args['inpaint_seq'] = [seq_mask]
437
- if str_mask not in ['',None]:
438
- S.args['inpaint_str'] = [str_mask]
439
-
440
- if secondary_structure in ['',None]:
441
- secondary_structure = None
442
- else:
443
- secondary_structure = ''.join(['E' if x == 'S' else x for x in secondary_structure])
444
- if L < len(secondary_structure):
445
- secondary_structure = secondary_structure[:len(sequence)]
446
- elif L == len(secondary_structure):
447
- pass
448
- else:
449
- dseq = L - len(secondary_structure)
450
- secondary_structure += secondary_structure[-1]*dseq
451
-
452
-
453
- # potentials
454
- potential_list = []
455
- potential_bias_list = []
456
-
457
- if aa_bias not in ['',None]:
458
- potential_list.append('aa_bias')
459
- S.args['aa_composition'] = aa_bias
460
- if aa_bias_potential in ['',None]:
461
- aa_bias_potential = 3
462
- potential_bias_list.append(str(aa_bias_potential))
463
- '''
464
- if target_charge not in ['',None]:
465
- potential_list.append('charge')
466
- if charge_potential in ['',None]:
467
- charge_potential = 1
468
- potential_bias_list.append(str(charge_potential))
469
- S.args['target_charge'] = float(target_charge)
470
- if target_ph in ['',None]:
471
- target_ph = 7.4
472
- S.args['target_pH'] = float(target_ph)
473
- '''
474
-
475
- if hydrophobic_target_score not in ['',None]:
476
- potential_list.append('hydrophobic')
477
- S.args['hydrophobic_score'] = float(hydrophobic_target_score)
478
- if hydrophobic_potential in ['',None]:
479
- hydrophobic_potential = 3
480
- potential_bias_list.append(str(hydrophobic_potential))
481
-
482
- if pssm not in ['',None]:
483
- potential_list.append('PSSM')
484
- potential_bias_list.append('5')
485
- S.args['PSSM'] = pssm.name
486
-
487
-
488
- if len(potential_list) > 0:
489
- S.args['potentials'] = ','.join(potential_list)
490
- S.args['potential_scale'] = ','.join(potential_bias_list)
491
-
492
-
493
- # normalise secondary_structure bias from range 0-0.3
494
- S.args['secondary_structure'] = secondary_structure
495
- S.args['helix_bias'] = helix_bias
496
- S.args['strand_bias'] = strand_bias
497
- S.args['loop_bias'] = loop_bias
498
-
499
- # set T
500
- if num_steps in ['',None]:
501
- S.args['T'] = 20
502
- else:
503
- S.args['T'] = int(num_steps)
504
-
505
- # noise
506
- if 'normal' in noise:
507
- S.args['sample_distribution'] = noise
508
- S.args['sample_distribution_gmm_means'] = [0]
509
- S.args['sample_distribution_gmm_variances'] = [1]
510
- elif 'gmm2' in noise:
511
- S.args['sample_distribution'] = noise
512
- S.args['sample_distribution_gmm_means'] = [-1,1]
513
- S.args['sample_distribution_gmm_variances'] = [1,1]
514
- elif 'gmm3' in noise:
515
- S.args['sample_distribution'] = noise
516
- S.args['sample_distribution_gmm_means'] = [-1,0,1]
517
- S.args['sample_distribution_gmm_variances'] = [1,1,1]
518
-
519
-
520
-
521
- if secondary_structure not in ['',None] or helix_bias+strand_bias+loop_bias > 0:
522
- S.args['checkpoint'] = dssp_checkpoint
523
- S.args['d_t1d'] = 29
524
- print('using dssp checkpoint')
525
- else:
526
- S.args['checkpoint'] = og_checkpoint
527
- S.args['d_t1d'] = 24
528
- print('using og checkpoint')
529
-
530
-
531
- for k,v in S.args.items():
532
- print(f"{k} --> {v}")
533
-
534
- # init S
535
- S.model_init()
536
- S.diffuser_init()
537
- S.setup()
538
-
539
- # sampling loop
540
- plddt_data = []
541
- for j in range(S.max_t):
542
- print(f'on step {j}')
543
- output_seq, output_pdb, plddt = S.take_step_get_outputs(j)
544
- plddt_data.append(plddt)
545
- yield output_seq, output_pdb, display_pdb(output_pdb), get_plddt_plot(plddt_data, S.max_t)
546
-
547
- output_seq, output_pdb, plddt = S.get_outputs()
548
-
549
- return output_seq, output_pdb, display_pdb(output_pdb), get_plddt_plot(plddt_data, S.max_t)
550
-
551
- def get_plddt_plot(plddt_data, max_t):
552
- fig, ax = plt.subplots(figsize=(15,6))
553
- x = list(range(1, len(plddt_data) + 1))
554
- ax.plot(x, plddt_data, color='#661dbf', linewidth=3, marker='o')
555
- ax.set_xticks(range(1, max_t + 1))
556
- ax.set_yticks([i/10 for i in range(11)]) # 0부터 1까지
557
- ax.set_ylim([0, 1])
558
- ax.set_ylabel('model confidence (plddt)')
559
- ax.set_xlabel('diffusion steps (t)')
560
- plt.close() # 메모리 관리를 위해 닫기
561
- return fig
562
-
563
-
564
- def display_pdb(path_to_pdb):
565
- '''
566
- #function to display pdb in py3dmol
567
- '''
568
- pdb = open(path_to_pdb, "r").read()
569
-
570
- view = py3Dmol.view(width=500, height=500)
571
- view.addModel(pdb, "pdb")
572
- view.setStyle({'model': -1}, {"cartoon": {'colorscheme':{'prop':'b','gradient':'roygb','min':0,'max':1}}})#'linear', 'min': 0, 'max': 1, 'colors': ["#ff9ef0","#a903fc",]}}})
573
- view.zoomTo()
574
- output = view._make_html().replace("'", '"')
575
- print(view._make_html())
576
- x = f"""<!DOCTYPE html><html></center> {output} </center></html>""" # do not use ' in this input
577
-
578
- return f"""<iframe height="500px" width="100%" name="result" allow="midi; geolocation; microphone; camera;
579
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
580
- allow-scripts allow-same-origin allow-popups
581
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
582
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
583
-
584
- '''
585
- return f"""<iframe style="width: 100%; height:700px" name="result" allow="midi; geolocation; microphone; camera;
586
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
587
- allow-scripts allow-same-origin allow-popups
588
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
589
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
590
- '''
591
-
592
- def get_motif_preview(pdb_id, contigs):
593
- try:
594
- input_pdb = fetch_pdb(pdb_id=pdb_id.lower() if pdb_id else None)
595
- if input_pdb is None:
596
- return gr.HTML("PDB ID를 입력해주세요"), None
597
-
598
- parse = parse_pdb(input_pdb)
599
- output_name = input_pdb
600
-
601
- pdb = open(output_name, "r").read()
602
- view = py3Dmol.view(width=500, height=500)
603
- view.addModel(pdb, "pdb")
604
-
605
- if contigs in ['',0]:
606
- contigs = ['0']
607
- else:
608
- contigs = [contigs]
609
-
610
- print('DEBUG: ',contigs)
611
-
612
- pdb_map = get_mappings(ContigMap(parse,contigs))
613
- print('DEBUG: ',pdb_map)
614
- print('DEBUG: ',pdb_map['con_ref_idx0'])
615
- roi = [x[1]-1 for x in pdb_map['con_ref_pdb_idx']]
616
-
617
- colormap = {0:'#D3D3D3', 1:'#F74CFF'}
618
- colors = {i+1: colormap[1] if i in roi else colormap[0] for i in range(parse['xyz'].shape[0])}
619
- view.setStyle({"cartoon": {"colorscheme": {"prop": "resi", "map": colors}}})
620
- view.zoomTo()
621
- output = view._make_html().replace("'", '"')
622
- print(view._make_html())
623
- x = f"""<!DOCTYPE html><html></center> {output} </center></html>""" # do not use ' in this input
624
-
625
- return f"""<iframe height="500px" width="100%" name="result" allow="midi; geolocation; microphone; camera;
626
- display-capture; encrypted-media;" sandbox="allow-modals allow-forms
627
- allow-scripts allow-same-origin allow-popups
628
- allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
629
- allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>""", output_name
630
-
631
- except Exception as e:
632
- return gr.HTML(f"오류가 발생했습니다: {str(e)}"), None
633
-
634
- def fetch_pdb(pdb_id=None):
635
- if pdb_id is None or pdb_id == "":
636
- return None
637
- else:
638
- os.system(f"wget -qnc https://files.rcsb.org/view/{pdb_id}.pdb")
639
- return f"{pdb_id}.pdb"
640
-
641
- # MSA AND PSSM GUIDANCE
642
- def save_pssm(file_upload):
643
- filename = file_upload.name
644
- orig_name = file_upload.orig_name
645
- if filename.split('.')[-1] in ['fasta', 'a3m']:
646
- return msa_to_pssm(file_upload)
647
- return filename
648
-
649
- def msa_to_pssm(msa_file):
650
- # Define the lookup table for converting amino acids to indices
651
- 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,
652
- 'K': 11, 'M': 12, 'F': 13, 'P': 14, 'S': 15, 'T': 16, 'W': 17, 'Y': 18, 'V': 19, 'X': 20, '-': 21}
653
- # Open the FASTA file and read the sequences
654
- records = list(SeqIO.parse(msa_file.name, "fasta"))
655
-
656
- assert len(records) >= 1, "MSA must contain more than one protein sequecne."
657
-
658
- first_seq = str(records[0].seq)
659
- aligned_seqs = [first_seq]
660
- # print(aligned_seqs)
661
- # Perform sequence alignment using the Needleman-Wunsch algorithm
662
- aligner = Align.PairwiseAligner()
663
- aligner.open_gap_score = -0.7
664
- aligner.extend_gap_score = -0.3
665
- for record in records[1:]:
666
- alignment = aligner.align(first_seq, str(record.seq))[0]
667
- alignment = alignment.format().split("\n")
668
- al1 = alignment[0]
669
- al2 = alignment[2]
670
- al1_fin = ""
671
- al2_fin = ""
672
- percent_gap = al2.count('-')/ len(al2)
673
- if percent_gap > 0.4:
674
- continue
675
- for i in range(len(al1)):
676
- if al1[i] != '-':
677
- al1_fin += al1[i]
678
- al2_fin += al2[i]
679
- aligned_seqs.append(str(al2_fin))
680
- # Get the length of the aligned sequences
681
- aligned_seq_length = len(first_seq)
682
- # Initialize the position scoring matrix
683
- matrix = np.zeros((22, aligned_seq_length))
684
- # Iterate through the aligned sequences and count the amino acids at each position
685
- for seq in aligned_seqs:
686
- #print(seq)
687
- for i in range(aligned_seq_length):
688
- if i == len(seq):
689
- break
690
- amino_acid = seq[i]
691
- if amino_acid.upper() not in aa_to_index.keys():
692
- continue
693
- else:
694
- aa_index = aa_to_index[amino_acid.upper()]
695
- matrix[aa_index, i] += 1
696
- # Normalize the counts to get the frequency of each amino acid at each position
697
- matrix /= len(aligned_seqs)
698
- print(len(aligned_seqs))
699
- matrix[20:,]=0
700
-
701
- outdir = ".".join(msa_file.name.split('.')[:-1]) + ".csv"
702
- np.savetxt(outdir, matrix[:21,:].T, delimiter=",")
703
- return outdir
704
-
705
- def get_pssm(fasta_msa, input_pssm):
706
- try:
707
- if input_pssm is not None:
708
- outdir = input_pssm.name
709
- elif fasta_msa is not None:
710
- outdir = save_pssm(fasta_msa)
711
- else:
712
- return gr.Plot(label="파일을 업로드해주세요"), None
713
-
714
- pssm = np.loadtxt(outdir, delimiter=",", dtype=float)
715
- fig, ax = plt.subplots(figsize=(15,6))
716
- plt.imshow(torch.permute(torch.tensor(pssm),(1,0)))
717
- return fig, outdir
718
- except Exception as e:
719
- return gr.Plot(label=f"오류가 발생했습니다: {str(e)}"), None
720
-
721
- # 히어로 능력치 계산 함수 추가
722
- def calculate_hero_stats(helix_bias, strand_bias, loop_bias, hydrophobic_score):
723
- stats = {
724
- 'strength': strand_bias * 20, # 베타시트 구조 기반
725
- 'flexibility': helix_bias * 20, # 알파헬릭스 구조 기반
726
- 'speed': loop_bias * 5, # 루프 구조 기반
727
- 'defense': abs(hydrophobic_score) if hydrophobic_score else 0
728
- }
729
- return stats
730
-
731
- def toggle_seq_input(choice):
732
- if choice == "자동 설계":
733
- return gr.update(visible=True), gr.update(visible=False)
734
- else: # "직접 입력"
735
- return gr.update(visible=False), gr.update(visible=True)
736
-
737
- def toggle_secondary_structure(choice):
738
- if choice == "슬라이더로 설정":
739
- return (
740
- gr.update(visible=True), # helix_bias
741
- gr.update(visible=True), # strand_bias
742
- gr.update(visible=True), # loop_bias
743
- gr.update(visible=False) # secondary_structure
744
- )
745
- else: # "직접 입력"
746
- return (
747
- gr.update(visible=False), # helix_bias
748
- gr.update(visible=False), # strand_bias
749
- gr.update(visible=False), # loop_bias
750
- gr.update(visible=True) # secondary_structure
751
- )
752
-
753
-
754
- def create_radar_chart(stats):
755
- # 레이더 차트 생성 로직
756
- categories = list(stats.keys())
757
- values = list(stats.values())
758
-
759
- fig = go.Figure(data=go.Scatterpolar(
760
- r=values,
761
- theta=categories,
762
- fill='toself'
763
- ))
764
-
765
- fig.update_layout(
766
- polar=dict(
767
- radialaxis=dict(
768
- visible=True,
769
- range=[0, 1]
770
- )),
771
- showlegend=False
772
- )
773
-
774
- return fig
775
-
776
- def generate_hero_description(name, stats, abilities):
777
- # 히어로 설명 생성 로직
778
- description = f"""
779
- 히어로 이름: {name}
780
-
781
- 주요 능력:
782
- - 근력: {'★' * int(stats['strength'] * 5)}
783
- - 유연성: {'★' * int(stats['flexibility'] * 5)}
784
- - 스피드: {'★' * int(stats['speed'] * 5)}
785
- - 방어력: {'★' * int(stats['defense'] * 5)}
786
-
787
- 특수 능력: {', '.join(abilities)}
788
- """
789
- return description
790
-
791
- def combined_generation(name, strength, flexibility, speed, defense, size, abilities,
792
- sequence, seq_len, helix_bias, strand_bias, loop_bias,
793
- secondary_structure, aa_bias, aa_bias_potential,
794
- num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
795
- contigs, pssm, seq_mask, str_mask, rewrite_pdb):
796
- try:
797
- # protein_diffusion_model 실행
798
- generator = protein_diffusion_model(
799
- sequence=None,
800
- seq_len=size, # 히어로 크기를 seq_len으로 사용
801
- helix_bias=flexibility, # 히어로 유연성을 helix_bias로 사용
802
- strand_bias=strength, # 히어로 강도를 strand_bias로 사용
803
- loop_bias=speed, # 히어로 스피드를 loop_bias로 사용
804
- secondary_structure=None,
805
- aa_bias=None,
806
- aa_bias_potential=None,
807
- num_steps="25",
808
- noise="normal",
809
- hydrophobic_target_score=str(-defense), # 히어로 방어력을 hydrophobic score로 사용
810
- hydrophobic_potential="2",
811
- contigs=None,
812
- pssm=None,
813
- seq_mask=None,
814
- str_mask=None,
815
- rewrite_pdb=None
816
- )
817
-
818
- # 마지막 결과 가져오기
819
- final_result = None
820
- for result in generator:
821
- final_result = result
822
-
823
- if final_result is None:
824
- raise Exception("생성 결과가 없습니다")
825
-
826
- output_seq, output_pdb, structure_view, plddt_plot = final_result
827
-
828
- # 히어로 능력치 계산
829
- stats = calculate_hero_stats(flexibility, strength, speed, defense)
830
-
831
- # 모든 결과 반환
832
- return (
833
- create_radar_chart(stats), # 능력치 차트
834
- generate_hero_description(name, stats, abilities), # 히어로 설명
835
- output_seq, # 단백질 서열
836
- output_pdb, # PDB 파일
837
- structure_view, # 3D 구조
838
- plddt_plot # 신뢰도 차트
839
- )
840
- except Exception as e:
841
- print(f"Error in combined_generation: {str(e)}")
842
- return (
843
- None,
844
- f"에러: {str(e)}",
845
- None,
846
- None,
847
- gr.HTML("에러가 발생했습니다"),
848
- None
849
- )
850
-
851
-
852
- def extract_parameters_from_chat(chat_response):
853
- """챗봇 응답에서 파라미터 추출"""
854
- try:
855
- params = {
856
- 'sequence_length': 100,
857
- 'helix_bias': 0.02,
858
- 'strand_bias': 0.02,
859
- 'loop_bias': 0.1,
860
- 'hydrophobic_target_score': 0
861
- }
862
-
863
- # 응답 텍스트에서 값 추출
864
- if "길이:" in chat_response:
865
- length_match = re.search(r'길이: (\d+)', chat_response)
866
- if length_match:
867
- params['sequence_length'] = int(length_match.group(1))
868
-
869
- if "알파 헬릭스 비율:" in chat_response:
870
- helix_match = re.search(r'알파 헬릭스 비율: ([\d.]+)', chat_response)
871
- if helix_match:
872
- params['helix_bias'] = float(helix_match.group(1)) / 100
873
-
874
- if "베타 시트 비율:" in chat_response:
875
- strand_match = re.search(r'베타 시트 비율: ([\d.]+)', chat_response)
876
- if strand_match:
877
- params['strand_bias'] = float(strand_match.group(1)) / 100
878
-
879
- if "루프 구조 비율:" in chat_response:
880
- loop_match = re.search(r'루프 구조 비율: ([\d.]+)', chat_response)
881
- if loop_match:
882
- params['loop_bias'] = float(loop_match.group(1)) / 100
883
-
884
- if "소수성 점수:" in chat_response:
885
- hydro_match = re.search(r'소수성 점수: ([-\d.]+)', chat_response)
886
- if hydro_match:
887
- params['hydrophobic_target_score'] = float(hydro_match.group(1))
888
-
889
- return params
890
- except Exception as e:
891
- print(f"파라미터 추출 중 오류: {str(e)}")
892
- return None
893
-
894
- def update_protein_display(chat_response):
895
- if "생성된 단백질 분석" in chat_response:
896
- params = extract_parameters_from_chat(chat_response)
897
- if params:
898
- result = generate_protein(params)
899
- stats = calculate_hero_stats(
900
- helix_bias=params['helix_bias'],
901
- strand_bias=params['strand_bias'],
902
- loop_bias=params['loop_bias'],
903
- hydrophobic_score=params['hydrophobic_target_score']
904
- )
905
- return {
906
- hero_stats: create_radar_chart(stats),
907
- hero_description: chat_response,
908
- output_seq: result[0],
909
- output_pdb: result[1],
910
- output_viewer: display_pdb(result[1]),
911
- plddt_plot: result[3]
912
- }
913
- return None
914
-
915
- def analyze_active_sites(sequence):
916
- """활성 부위 분석"""
917
- return "분석 중..." # 임시 구현
918
-
919
- def predict_interactions(params):
920
- """상호작용 예측"""
921
- return "예측 중..." # 임시 구현
922
-
923
- def evaluate_stability(plddt_data):
924
- """안정성 평가"""
925
- if not plddt_data:
926
- return "평가 불가"
927
- avg_score = np.mean(plddt_data)
928
- if avg_score > 0.8:
929
- return "매우 안정적"
930
- elif avg_score > 0.6:
931
- return "안정적"
932
- else:
933
- return "보통"
934
-
935
- def process_chat_and_generate(message, history):
936
- try:
937
- # 1. 초기 응답 생성 (이전 대화 기록 유지)
938
- current_history = history + [
939
- {"role": "user", "content": message},
940
- {"role": "assistant", "content": "단백질 설계를 시작합니다. 잠시만 기다려주세요..."}
941
- ]
942
- yield (current_history, None, None, None, None, None, None)
943
-
944
- # 2. 프롬프트 분석
945
- analysis = analyze_prompt(message)
946
- if not analysis:
947
- return history + [
948
- {"role": "user", "content": message},
949
- {"role": "assistant", "content": "요청 분석에 실패했습니다."}
950
- ], None, None, None, None, None, None
951
-
952
- similar_structures = search_protein_data(analysis, ds)
953
- if not similar_structures:
954
- return history + [
955
- {"role": "user", "content": message},
956
- {"role": "assistant", "content": "적합한 참조 구조를 찾지 못했습니다."}
957
- ], None, None, None, None, None, None
958
-
959
- params = extract_parameters(analysis, similar_structures)
960
- if not params:
961
- return history + [
962
- {"role": "user", "content": message},
963
- {"role": "assistant", "content": "파라미터 설정에 실패했습니다."}
964
- ], None, None, None, None, None, None
965
-
966
- # 3. 분석 결과 추가 (이전 메시지 유지)
967
- current_history = current_history[:-1] + [
968
- {"role": "assistant", "content": f"""
969
- 분석 결과:
970
- {analysis}
971
-
972
- 단백질 구조 생성을 시작합니다...
973
- """}
974
- ]
975
- yield (current_history, None, None, None, None, None, None)
976
-
977
- # 4. 단백질 생성
978
- try:
979
- generator = protein_diffusion_model(
980
- sequence=None,
981
- seq_len=params['sequence_length'],
982
- helix_bias=params['helix_bias'],
983
- strand_bias=params['strand_bias'],
984
- loop_bias=params['loop_bias'],
985
- secondary_structure=None,
986
- aa_bias=None,
987
- aa_bias_potential=None,
988
- num_steps="25",
989
- noise="normal",
990
- hydrophobic_target_score=str(params['hydrophobic_target_score']),
991
- hydrophobic_potential="2",
992
- contigs=None,
993
- pssm=None,
994
- seq_mask=None,
995
- str_mask=None,
996
- rewrite_pdb=None
997
- )
998
-
999
- # 5. 생성 과정 추적 (이전 메시지들 유지)
1000
- step = 0
1001
- final_result = None
1002
- for result in generator:
1003
- step += 1
1004
- final_result = result
1005
- progress_msg = f"단백질 생성 중... {step}/25 단계 완료"
1006
- current_history = current_history[:-1] + [
1007
- {"role": "assistant", "content": progress_msg}
1008
- ]
1009
- yield (
1010
- current_history,
1011
- create_radar_chart(calculate_hero_stats(
1012
- params['helix_bias'],
1013
- params['strand_bias'],
1014
- params['loop_bias'],
1015
- float(params['hydrophobic_target_score'])
1016
- )),
1017
- progress_msg,
1018
- result[0], # output_seq
1019
- result[1], # output_pdb
1020
- result[2], # structure_view
1021
- result[3] # plddt_plot
1022
- )
1023
-
1024
- if final_result is None:
1025
- raise Exception("생성 결과가 없습니다")
1026
-
1027
- # 6. 최종 결과 및 설명 추가
1028
- output_seq, output_pdb, structure_view, plddt_plot = final_result
1029
-
1030
- final_explanation = f"""
1031
- 단백질 설계가 완료되었습니다.
1032
-
1033
- [분석 결과]
1034
- {analysis}
1035
-
1036
- [구조적 특징]
1037
- - 길이: {params['sequence_length']} 아미노산
1038
- - 알파 헬릭스 비율: {params['helix_bias']*100:.1f}%
1039
- - 베타 시트 비율: {params['strand_bias']*100:.1f}%
1040
- - 루프 구조 비율: {params['loop_bias']*100:.1f}%
1041
- - 소수성 점수: {params['hydrophobic_target_score']}
1042
-
1043
- [생성 과정]
1044
- - 총 {step}단계의 최적화 완료
1045
- - 최종 안정성 점수: {np.mean(plddt_data) if plddt_data else 0:.2f}
1046
- - 참조된 유사 구조: {len(similar_structures)}개
1047
-
1048
- 3D 구조와 상세 분석 결과를 확인하실 수 있습니다.
1049
- """
1050
-
1051
- final_history = current_history + [
1052
- {"role": "assistant", "content": final_explanation}
1053
- ]
1054
-
1055
- stats = calculate_hero_stats(
1056
- params['helix_bias'],
1057
- params['strand_bias'],
1058
- params['loop_bias'],
1059
- float(params['hydrophobic_target_score'])
1060
- )
1061
-
1062
- return (
1063
- final_history,
1064
- create_radar_chart(stats),
1065
- final_explanation,
1066
- output_seq,
1067
- output_pdb,
1068
- structure_view,
1069
- plddt_plot
1070
- )
1071
-
1072
- except Exception as e:
1073
- error_msg = f"단백질 생성 중 오류가 발생했습니다: {str(e)}"
1074
- print(error_msg)
1075
- traceback.print_exc()
1076
- return (
1077
- current_history + [
1078
- {"role": "assistant", "content": error_msg}
1079
- ],
1080
- None, None, None, None, None, None
1081
- )
1082
-
1083
- except Exception as e:
1084
- error_msg = f"처리 중 오류가 발생했습니다: {str(e)}"
1085
- print(f"Error in process_chat_and_generate: {str(e)}")
1086
- traceback.print_exc()
1087
- return (
1088
- history + [
1089
- {"role": "user", "content": message},
1090
- {"role": "assistant", "content": error_msg}
1091
- ],
1092
- None, None, None, None, None, None
1093
- )
1094
-
1095
-
1096
- # 시작 부분에 추가
1097
- def extract_keywords(analysis):
1098
- """분석 텍스트에서 키워드 추출"""
1099
- try:
1100
- keywords = []
1101
- # 주요 기능 키워드
1102
- if "치료" in analysis: keywords.extend(["therapeutic", "binding"])
1103
- if "결합" in analysis: keywords.extend(["binding", "interaction"])
1104
- if "촉매" in analysis: keywords.extend(["enzyme", "catalytic"])
1105
-
1106
- # 환경 키워드
1107
- if "막" in analysis: keywords.extend(["membrane", "transmembrane"])
1108
- if "수용성" in analysis: keywords.extend(["soluble", "hydrophilic"])
1109
- if "소수성" in analysis: keywords.extend(["hydrophobic"])
1110
-
1111
- # 구조 키워드
1112
- if "알파" in analysis or "나선" in analysis: keywords.append("helix")
1113
- if "베타" in analysis or "시트" in analysis: keywords.append("sheet")
1114
- if "루프" in analysis: keywords.append("loop")
1115
-
1116
- return list(set(keywords))
1117
- except Exception as e:
1118
- print(f"키워드 추출 중 오류: {str(e)}")
1119
- return []
1120
-
1121
- def calculate_similarity(keywords, entry):
1122
- """키워드와 데이터셋 항목 간의 유사도 계산"""
1123
- try:
1124
- score = 0
1125
- if not isinstance(entry, dict):
1126
- return 0
1127
-
1128
- # 안전한 접근을 위한 get 메서드 사용
1129
- sequence = entry.get('sequence', '').lower()
1130
- description = entry.get('description', '')
1131
-
1132
- for keyword in keywords:
1133
- if keyword in description.lower():
1134
- score += 2
1135
- if keyword in sequence:
1136
- score += 1
1137
- if 'secondary_structure' in entry:
1138
- sec_structure = entry['secondary_structure']
1139
- if keyword in ['helix'] and 'H' in sec_structure:
1140
- score += 1
1141
- if keyword in ['sheet'] and 'E' in sec_structure:
1142
- score += 1
1143
- if keyword in ['loop'] and 'L' in sec_structure:
1144
- score += 1
1145
- return score
1146
- except Exception as e:
1147
- print(f"유사도 계산 중 오류: {str(e)}")
1148
- return 0
1149
-
1150
- # 전역 변수 정의
1151
- plddt_data = []
1152
- stats = {} # 능력치 저장용
1153
- output_seq = None
1154
- output_pdb = None
1155
- structure_view = None
1156
- plddt_plot = None
1157
-
1158
- # 예제 프롬프트 처리 함수 수정
1159
- def use_example(example):
1160
- try:
1161
- if example:
1162
- return example
1163
- return ""
1164
- except Exception as e:
1165
- print(f"예제 처리 중 오류: {str(e)}")
1166
- return ""
1167
-
1168
- # 이벤트 핸들러에서 필요한 변수들 정의
1169
- current_protein_result = None
1170
-
1171
-
1172
- def download_checkpoint_files():
1173
- """필요한 체크포인트 파일 다운로드"""
1174
- try:
1175
- import requests
1176
-
1177
- # 체크포인트 파일 URL (실제 URL로 교체 필요)
1178
- dssp_url = "YOUR_DSSP_CHECKPOINT_URL"
1179
- og_url = "YOUR_OG_CHECKPOINT_URL"
1180
-
1181
- # DSSP 체크포인트 다운로드
1182
- if not os.path.exists(dssp_checkpoint):
1183
- print("Downloading DSSP checkpoint...")
1184
- response = requests.get(dssp_url)
1185
- with open(dssp_checkpoint, 'wb') as f:
1186
- f.write(response.content)
1187
-
1188
- # OG 체크포인트 다운로드
1189
- if not os.path.exists(og_checkpoint):
1190
- print("Downloading OG checkpoint...")
1191
- response = requests.get(og_url)
1192
- with open(og_checkpoint, 'wb') as f:
1193
- f.write(response.content)
1194
-
1195
- print("Checkpoint files downloaded successfully")
1196
- except Exception as e:
1197
- print(f"Error downloading checkpoint files: {str(e)}")
1198
- raise
1199
-
1200
- # 시작 시 체크포인트 파일 확인 및 다운로드
1201
- try:
1202
- download_checkpoint_files()
1203
- except Exception as e:
1204
- print(f"Warning: Could not download checkpoint files: {str(e)}")
1205
-
1206
-
1207
-
1208
- with gr.Blocks(theme='ParityError/Interstellar') as demo:
1209
- # 예제 프롬프트 리스트 정의
1210
- example_prompts = [
1211
- "암세포만 선택적으로 공격하는 면역 단백질을 설계해주세요",
1212
- "COVID-19 스파이크 단백질에 강하게 결합하는 항체 단백질을 생성해주세요",
1213
- "혈당 수준을 실시간으로 모니터링하는 단백질을 만들어주세요",
1214
- "알츠하이머 베타 아밀로이드를 분해할 수 있는 효소 단백질을 설계해주세요",
1215
- "암 마커를 초고감도로 검출하는 단백질을 생성해주세요",
1216
- "플라스틱을 분해할 수 있는 효소 단백질을 설계해주세요",
1217
- "이산화탄소를 효율적으로 포집하는 단백질을 만들어주세요",
1218
- "식품의 보존기간을 연장하는 항균 단백질을 설계해주세요",
1219
- "수소 생산을 촉진하는 효소 단백질을 생성해주세요",
1220
- "혈전을 효과적으로 분해하는 단백질을 설계해주세요",
1221
- "인슐린 저항성을 개선하는 새로운 호르몬 단백질을 만들어주세요",
1222
- "식물의 가뭄 저항성을 높이는 단백질을 설계해주세요",
1223
- "태양광 에너지를 효율적으로 포집하는 단백질을 생성해주세요",
1224
- "해수에서 중금속을 제거하는 단백질을 설계해주세요",
1225
- "질소 고정 효율을 높이는 효소 단백질을 만들어주세요",
1226
- "신경전달물질을 감지하는 나노바이오센서를 설계해주세요",
1227
- "특정 독성 물질을 감지하는 바이오센서 단백질을 생성해주세요",
1228
- "배터리 성능을 향상시키는 전도성 단백질을 설계해주세요",
1229
- "극한의 고온에서도 안정한 초내열성 단백질을 만들어주세요",
1230
- "생분해성 플라스틱 생산을 위한 중합효소를 설계해주세요",
1231
- "식물의 병해충 저항성을 강화하는 단백질을 생성해주세요",
1232
- "과일의 숙성을 조절하는 단백질을 설계해주세요",
1233
- "대기 오염물질을 실시간 감지하는 단백질을 만들어주세요",
1234
- "석유 오염을 분해하는 해양 단백질을 설계해주세요",
1235
- "극저온에서 활성을 유지하는 저온 적응 단백질을 생성해주세요",
1236
- "고압 환경에서 안정한 심해 적응 단백질을 설계해주세요",
1237
- "강한 산성 환경에서 작동하는 단백질을 만들어주세요",
1238
- "나노 구조체를 자가 조립하는 단백질을 설계해주세요",
1239
- "방사능 물질을 안전하게 분해하는 단백질을 생성해주세요",
1240
- "방사선에 저항성이 있는 우주 환경용 단백질을 설계해주세요"
1241
- ]
1242
-
1243
- with gr.Row():
1244
- with gr.Column(scale=1):
1245
- # 챗봇 인터페이스
1246
- gr.Markdown("# 🤖 ProteinGPT: AI 단백질 생성기기")
1247
-
1248
- # 예제 프롬프트 드롭다운과 버튼을 Row로 배치
1249
- with gr.Row():
1250
- example_dropdown = gr.Dropdown(
1251
- choices=example_prompts,
1252
- label="예제 프롬프트 선택",
1253
- info="원하는 예제를 선택하세요",
1254
- scale=4
1255
- )
1256
- example_btn = gr.Button("👉 예제 사용", scale=1)
1257
-
1258
- # 챗봇
1259
- chatbot = gr.Chatbot(
1260
- height=600,
1261
- type='messages'
1262
- )
1263
-
1264
- # 메시지 입력
1265
- with gr.Row():
1266
- msg = gr.Textbox(
1267
- label="메시지를 입력하세요",
1268
- placeholder="예: COVID-19를 치료할 수 있는 단백질을 생성해주세요",
1269
- lines=2,
1270
- scale=4
1271
- )
1272
- submit_btn = gr.Button("전송", variant="primary", scale=1)
1273
-
1274
- clear = gr.Button("대화 내용 지우기")
1275
-
1276
-
1277
- with gr.Accordion("채팅 설정", open=False):
1278
- system_message = gr.Textbox(
1279
- value="당신은 단백질 설계를 도와주는 전문가입니다.",
1280
- label="시스템 메시지"
1281
- )
1282
- max_tokens = gr.Slider(
1283
- minimum=1,
1284
- maximum=3800,
1285
- value=3800,
1286
- step=1,
1287
- label="최대 토큰 수"
1288
- )
1289
- temperature = gr.Slider(
1290
- minimum=0.1,
1291
- maximum=4.0,
1292
- value=0.7,
1293
- step=0.1,
1294
- label="Temperature"
1295
- )
1296
- top_p = gr.Slider(
1297
- minimum=0.1,
1298
- maximum=1.0,
1299
- value=0.95,
1300
- step=0.05,
1301
- label="Top-P"
1302
- )
1303
-
1304
- # 탭 인터페이스
1305
- with gr.Tabs():
1306
- with gr.TabItem("🧬 커스텀 디자인"):
1307
- gr.Markdown("""
1308
- ### ✨ 당신만의 특별한 커스텀을 만들어보세요!
1309
- 각 능력치를 조절하면 커스텀된 단백질이 자동으로 설계됩니다.
1310
- """)
1311
-
1312
- # 기본 정보
1313
- hero_name = gr.Textbox(
1314
- label="커스��� 이름",
1315
- placeholder="당신의 커스텀 단백질 이름을 지어주세요!",
1316
- info="당신만의 정체성을 나타내는 이름을 입력하세요"
1317
- )
1318
-
1319
- # 능력치 설정
1320
- gr.Markdown("### 💪 커스텀 능력치 설정")
1321
- with gr.Row():
1322
- strength = gr.Slider(
1323
- minimum=0.0, maximum=0.05,
1324
- label="💪 초강력(근력)",
1325
- value=0.02,
1326
- info="단단한 베타시트 구조로 강력한 힘을 생성합니다"
1327
- )
1328
- flexibility = gr.Slider(
1329
- minimum=0.0, maximum=0.05,
1330
- label="🤸‍♂️ 유연성",
1331
- value=0.02,
1332
- info="나선형 알파헬릭스 구조로 유연한 움직임을 가능하게 합니다"
1333
- )
1334
-
1335
- with gr.Row():
1336
- speed = gr.Slider(
1337
- minimum=0.0, maximum=0.20,
1338
- label="⚡ 스피드",
1339
- value=0.1,
1340
- info="루프 구조로 빠른 움직임을 구현합니다"
1341
- )
1342
- defense = gr.Slider(
1343
- minimum=-10, maximum=10,
1344
- label="🛡️ 방어력",
1345
- value=0,
1346
- info="음수: 수중 활동에 특화, 양수: 지상 활동에 특화"
1347
- )
1348
-
1349
- # 크기 설정
1350
- hero_size = gr.Slider(
1351
- minimum=50, maximum=200,
1352
- label="📏 커스텀 단백질 크기",
1353
- value=100,
1354
- info="전체적인 크기를 결정합니다"
1355
- )
1356
-
1357
- # 특수 능력 설정
1358
- with gr.Accordion("🌟 특수 능력", open=False):
1359
- gr.Markdown("""
1360
- 특수 능력을 선택하면 커스텀 단백질에 특별한 구조가 추가됩니다.
1361
- - 자가 회복: 단백질 구조 복구 능력 강화
1362
- - 원거리 공격: 특수한 구조적 돌출부 형성
1363
- - 방어막 생성: 안정적인 보호층 구조 생성
1364
- """)
1365
- special_ability = gr.CheckboxGroup(
1366
- choices=["자가 회복", "원거리 공격", "방어막 생성"],
1367
- label="특수 능력 선택"
1368
- )
1369
-
1370
- # 생성 버튼
1371
- create_btn = gr.Button("🧬 커스텀 단백질 생성!", variant="primary", scale=2)
1372
-
1373
- with gr.TabItem("🧬 커스텀 단백질 설계"):
1374
- gr.Markdown("""
1375
- ### 🧪 커스텀 단백질 고급 설정
1376
- 유전자 구조를 더 세밀하게 조정할 수 있습니다.
1377
- """)
1378
-
1379
- seq_opt = gr.Radio(
1380
- ["자동 설계", "직접 입력"],
1381
- label="DNA 설계 방식",
1382
- value="자동 설계"
1383
- )
1384
-
1385
- sequence = gr.Textbox(
1386
- label="단백질 시퀀스",
1387
- lines=1,
1388
- placeholder='사용 가능한 아미노산: A,C,D,E,F,G,H,I,K,L,M,N,P,Q,R,S,T,V,W,Y (X는 무작위)',
1389
- visible=False
1390
- )
1391
- seq_len = gr.Slider(
1392
- minimum=5.0, maximum=250.0,
1393
- label="DNA 길이",
1394
- value=100,
1395
- visible=True
1396
- )
1397
-
1398
- with gr.Accordion(label='🦴 골격 구조 설정', open=True):
1399
- gr.Markdown("""
1400
- 커스텀 단백질 기본 골격 구조를 설정합니다.
1401
- - 나선형 구조: 유연하고 탄력있는 움직임
1402
- - 병풍형 구조: 단단하고 강력한 힘
1403
- - 고리형 구조: 빠르고 민첩한 움직임
1404
- """)
1405
- sec_str_opt = gr.Radio(
1406
- ["슬라이더로 설정", "직접 입력"],
1407
- label="골격 구조 설정 방식",
1408
- value="슬라이더로 설정"
1409
- )
1410
-
1411
- secondary_structure = gr.Textbox(
1412
- label="골격 구조",
1413
- lines=1,
1414
- placeholder='H:나선형, S:병풍형, L:고리형, X:자동설정',
1415
- visible=False
1416
- )
1417
-
1418
- with gr.Column():
1419
- helix_bias = gr.Slider(
1420
- minimum=0.0, maximum=0.05,
1421
- label="나선형 구조 비율",
1422
- visible=True
1423
- )
1424
- strand_bias = gr.Slider(
1425
- minimum=0.0, maximum=0.05,
1426
- label="병풍형 구조 비율",
1427
- visible=True
1428
- )
1429
- loop_bias = gr.Slider(
1430
- minimum=0.0, maximum=0.20,
1431
- label="고리형 구조 비율",
1432
- visible=True
1433
- )
1434
-
1435
- with gr.Accordion(label='🧬 단백질 구성 설정', open=False):
1436
- gr.Markdown("""
1437
- 특정 아미노산의 비율을 조절하여 특성을 강화할 수 있습니다.
1438
- 예시: W0.2,E0.1 (트립토판 20%, 글루탐산 10%)
1439
- """)
1440
- with gr.Row():
1441
- aa_bias = gr.Textbox(
1442
- label="아미노산 비율",
1443
- lines=1,
1444
- placeholder='예시: W0.2,E0.1'
1445
- )
1446
- aa_bias_potential = gr.Textbox(
1447
- label="강화 정도",
1448
- lines=1,
1449
- placeholder='1.0-5.0 사이 값 입력'
1450
- )
1451
-
1452
- with gr.Accordion(label='🌍 환경 적응력 설정', open=False):
1453
- gr.Markdown("""
1454
- 환경 적응력을 조절합니다.
1455
- 음수: 수중 활동에 특화, 양수: 지상 활동에 특화
1456
- """)
1457
- with gr.Row():
1458
- hydrophobic_target_score = gr.Textbox(
1459
- label="환경 적응 점수",
1460
- lines=1,
1461
- placeholder='예시: -5 (수중 활동에 특화)'
1462
- )
1463
- hydrophobic_potential = gr.Textbox(
1464
- label="적응력 강화 정도",
1465
- lines=1,
1466
- placeholder='1.0-2.0 사이 값 입력'
1467
- )
1468
-
1469
- with gr.Accordion(label='⚙️ 고급 설정', open=False):
1470
- gr.Markdown("""
1471
- DNA 생성 과정의 세부 매개변수를 조정합니다.
1472
- """)
1473
- with gr.Row():
1474
- num_steps = gr.Textbox(
1475
- label="생성 단계",
1476
- lines=1,
1477
- placeholder='25 이하 권장'
1478
- )
1479
- noise = gr.Dropdown(
1480
- ['normal','gmm2 [-1,1]','gmm3 [-1,0,1]'],
1481
- label='노이즈 타입',
1482
- value='normal'
1483
- )
1484
-
1485
- design_btn = gr.Button("🧬 단백질 설계 생성!", variant="primary", scale=2)
1486
-
1487
- with gr.TabItem("🧪 커스텀 단백질 강화"):
1488
- gr.Markdown("""
1489
- ### ⚡ 기존 커스텀 단백질 활용
1490
- 기존 단백질 일부를 새로운 커스텀에게 이식합니다.
1491
- """)
1492
-
1493
- gr.Markdown("공개된 커스텀 단백질 데이터베이스에서 코드를 찾을 수 있습니다")
1494
- pdb_id_code = gr.Textbox(
1495
- label="커스텀 단백질 코드",
1496
- lines=1,
1497
- placeholder='기존 커스텀 단백질 코드를 입력하세요 (예: 1DPX)'
1498
- )
1499
-
1500
- gr.Markdown("이식하고 싶은 단백질 영역을 선택하고 새로운 단백질을 추가할 수 있습니다")
1501
- contigs = gr.Textbox(
1502
- label="이식할 단백질 영역",
1503
- lines=1,
1504
- placeholder='예시: 15,A3-10,20-30'
1505
- )
1506
-
1507
- with gr.Row():
1508
- seq_mask = gr.Textbox(
1509
- label='능력 재설계',
1510
- lines=1,
1511
- placeholder='선택한 영역의 능력을 새롭게 디자인'
1512
- )
1513
- str_mask = gr.Textbox(
1514
- label='구조 재설계',
1515
- lines=1,
1516
- placeholder='선택한 영역의 구조를 새롭게 디자인'
1517
- )
1518
-
1519
- preview_viewer = gr.HTML()
1520
- rewrite_pdb = gr.File(label='커스텀 단백질 파일')
1521
- preview_btn = gr.Button("🔍 미리보기", variant="secondary")
1522
- enhance_btn = gr.Button("⚡ 강화된 커스텀 단백질 생성!", variant="primary", scale=2)
1523
-
1524
- with gr.TabItem("👑 커스텀 단백질 족보"):
1525
- gr.Markdown("""
1526
- ### 🏰 위대한 커스텀 단백질 가문의 유산
1527
- 강력한 특성을 계승하여 새로운 커스텀 단백질을 만듭니다.
1528
- """)
1529
-
1530
- with gr.Row():
1531
- with gr.Column():
1532
- gr.Markdown("커스텀 단백질 정보가 담긴 파일을 업로드하세요")
1533
- fasta_msa = gr.File(label='가문 DNA 데이터')
1534
- with gr.Column():
1535
- gr.Markdown("이미 분석된 가문 특성 데이터가 있다면 업로드하세요")
1536
- input_pssm = gr.File(label='가문 특성 데이터')
1537
-
1538
- pssm = gr.File(label='분석된 가문 특성')
1539
- pssm_view = gr.Plot(label='가문 특성 분석 결과')
1540
- pssm_gen_btn = gr.Button("✨ 가문 특성 분석", variant="secondary")
1541
- inherit_btn = gr.Button("👑 가문의 힘 계승!", variant="primary", scale=2)
1542
-
1543
- # 오른쪽 열: 결과 표시
1544
- with gr.Column(scale=1):
1545
- gr.Markdown("## 🧬 커스텀 단백질 프로필")
1546
- hero_stats = gr.Plot(label="능력치 분석")
1547
- hero_description = gr.Textbox(label="커스텀 단백질 특성", lines=3)
1548
-
1549
- gr.Markdown("## 🧬 커스텀 단백질 분석 결과")
1550
- gr.Markdown("#### ⚡ 커스텀 단백질 안정성 점수")
1551
- plddt_plot = gr.Plot(label='안정성 분석')
1552
- gr.Markdown("#### 📝 커스텀 단백질 시퀀스")
1553
- output_seq = gr.Textbox(label="커스텀 단백질 서열")
1554
- gr.Markdown("#### 💾 커스텀 단백질 데이터")
1555
- output_pdb = gr.File(label="커스텀 단백질 파일")
1556
- gr.Markdown("#### 🔬 커스텀 단백질 구조")
1557
- output_viewer = gr.HTML()
1558
-
1559
- # 예제 선택 이벤트 연결
1560
- def use_example(example):
1561
- if example:
1562
- return example
1563
- return ""
1564
-
1565
- example_btn.click(
1566
- fn=use_example,
1567
- inputs=[example_dropdown],
1568
- outputs=[msg]
1569
- )
1570
-
1571
-
1572
-
1573
- # 이벤트 연결
1574
- # 챗봇 이벤트
1575
- msg.submit(process_chat, [msg, chatbot], [chatbot])
1576
- clear.click(lambda: None, None, chatbot, queue=False)
1577
-
1578
- # 입력 방식 변경 이벤트
1579
- seq_opt.change(
1580
- fn=toggle_seq_input,
1581
- inputs=[seq_opt],
1582
- outputs=[seq_len, sequence],
1583
- queue=False
1584
- )
1585
-
1586
- # 구조 설정 방식 변경 이벤트
1587
- sec_str_opt.change(
1588
- fn=toggle_secondary_structure,
1589
- inputs=[sec_str_opt],
1590
- outputs=[helix_bias, strand_bias, loop_bias, secondary_structure],
1591
- queue=False
1592
- )
1593
-
1594
- # 미리보기 이벤트
1595
- preview_btn.click(
1596
- get_motif_preview,
1597
- inputs=[pdb_id_code, contigs],
1598
- outputs=[preview_viewer, rewrite_pdb]
1599
- )
1600
-
1601
- # PSSM 분석 이벤트
1602
- pssm_gen_btn.click(
1603
- get_pssm,
1604
- inputs=[fasta_msa, input_pssm],
1605
- outputs=[pssm_view, pssm]
1606
- )
1607
-
1608
- # 챗봇 기반 단백질 생성 결과 업데이트
1609
- def update_protein_display(chat_response):
1610
- if "생성된 단백질 분석" in chat_response:
1611
- params = extract_parameters_from_chat(chat_response)
1612
- result = generate_protein(params)
1613
- return {
1614
- hero_stats: create_radar_chart(calculate_hero_stats(params)),
1615
- hero_description: chat_response,
1616
- output_seq: result[0],
1617
- output_pdb: result[1],
1618
- output_viewer: display_pdb(result[1]),
1619
- plddt_plot: result[3]
1620
- }
1621
- return None
1622
-
1623
- # 각 생성 버튼 이벤트 연결
1624
- for btn in [create_btn, design_btn, enhance_btn, inherit_btn]:
1625
- btn.click(
1626
- combined_generation,
1627
- inputs=[
1628
- hero_name, strength, flexibility, speed, defense, hero_size, special_ability,
1629
- sequence, seq_len, helix_bias, strand_bias, loop_bias,
1630
- secondary_structure, aa_bias, aa_bias_potential,
1631
- num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
1632
- contigs, pssm, seq_mask, str_mask, rewrite_pdb
1633
- ],
1634
- outputs=[
1635
- hero_stats,
1636
- hero_description,
1637
- output_seq,
1638
- output_pdb,
1639
- output_viewer,
1640
- plddt_plot
1641
- ]
1642
- )
1643
-
1644
- # 이벤트 핸들러 연결
1645
- msg.submit(
1646
- fn=process_chat_and_generate,
1647
- inputs=[msg, chatbot],
1648
- outputs=[
1649
- chatbot,
1650
- hero_stats,
1651
- hero_description,
1652
- output_seq,
1653
- output_pdb,
1654
- output_viewer,
1655
- plddt_plot
1656
- ]
1657
- )
1658
-
1659
- submit_btn.click(
1660
- fn=process_chat_and_generate,
1661
- inputs=[msg, chatbot],
1662
- outputs=[
1663
- chatbot,
1664
- hero_stats,
1665
- hero_description,
1666
- output_seq,
1667
- output_pdb,
1668
- output_viewer,
1669
- plddt_plot
1670
- ]
1671
- )
1672
-
1673
- # 채팅 내용 지우기
1674
- clear.click(
1675
- lambda: (None, None, None, None, None, None, None),
1676
- None,
1677
- [chatbot, hero_stats, hero_description, output_seq, output_pdb, output_viewer, plddt_plot],
1678
- queue=False
1679
- )
1680
-
1681
- # 챗봇 응답에 따른 결과 업데이트
1682
- msg.submit(
1683
- update_protein_display,
1684
- inputs=[chatbot],
1685
- outputs=[hero_stats, hero_description, output_seq, output_pdb, output_viewer, plddt_plot]
1686
- )
1687
-
1688
- # 기본 챗봇 응답 처리
1689
- submit_btn.click(respond,
1690
- [msg, chatbot, system_message, max_tokens, temperature, top_p],
1691
- [chatbot])
1692
- msg.submit(respond,
1693
- [msg, chatbot, system_message, max_tokens, temperature, top_p],
1694
- [chatbot])
1695
- clear.click(lambda: None, None, chatbot, queue=False)
1696
-
1697
- # 진행 상태 표시 이벤트
1698
- msg.submit(
1699
- fn=process_chat_and_generate,
1700
- inputs=[msg, chatbot],
1701
- outputs=[
1702
- chatbot,
1703
- hero_stats,
1704
- hero_description,
1705
- output_seq,
1706
- output_pdb,
1707
- output_viewer,
1708
- plddt_plot
1709
- ],
1710
- show_progress=True
1711
- )
1712
-
1713
- submit_btn.click(
1714
- fn=process_chat_and_generate,
1715
- inputs=[msg, chatbot],
1716
- outputs=[
1717
- chatbot,
1718
- hero_stats,
1719
- hero_description,
1720
- output_seq,
1721
- output_pdb,
1722
- output_viewer,
1723
- plddt_plot
1724
- ],
1725
- show_progress=True
1726
- )
1727
-
1728
- # 실행
1729
- demo.queue()
1730
- demo.launch(debug=True, share=True)