import os,sys
# install required packages
os.system('pip install plotly') # plotly 설치
os.system('pip install matplotlib') # matplotlib 설치
os.system('pip install dgl==1.0.2+cu116 -f https://data.dgl.ai/wheels/cu116/repo.html')
os.environ["DGLBACKEND"] = "pytorch"
print('Modules installed')
import plotly.graph_objects as go
import numpy as np
import gradio as gr
import py3Dmol
from io import StringIO
import json
import secrets
import copy
import matplotlib.pyplot as plt
from utils.sampler import HuggingFace_sampler
from utils.parsers_inference import parse_pdb
from model.util import writepdb
from utils.inpainting_util import *
# install environment goods
#os.system("pip -q install dgl -f https://data.dgl.ai/wheels/cu113/repo.html")
os.system('pip install dgl==1.0.2+cu116 -f https://data.dgl.ai/wheels/cu116/repo.html')
#os.system('pip install gradio')
os.environ["DGLBACKEND"] = "pytorch"
#os.system(f'pip install -r ./PROTEIN_GENERATOR/requirements.txt')
print('Modules installed')
#os.system('pip install --force gradio==3.36.1')
#os.system('pip install gradio_client==0.2.7')
#os.system('pip install \"numpy<2\"')
#os.system('pip install numpy --upgrade')
#os.system('pip install --force numpy==1.24.1')
if not os.path.exists('./SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt'):
print('Downloading model weights 1')
os.system('wget http://files.ipd.uw.edu/pub/sequence_diffusion/checkpoints/SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt')
print('Successfully Downloaded')
if not os.path.exists('./SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt'):
print('Downloading model weights 2')
os.system('wget http://files.ipd.uw.edu/pub/sequence_diffusion/checkpoints/SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt')
print('Successfully Downloaded')
import numpy as np
import gradio as gr
import py3Dmol
from io import StringIO
import json
import secrets
import copy
import matplotlib.pyplot as plt
from utils.sampler import HuggingFace_sampler
from utils.parsers_inference import parse_pdb
from model.util import writepdb
from utils.inpainting_util import *
plt.rcParams.update({'font.size': 13})
with open('./tmp/args.json','r') as f:
args = json.load(f)
# manually set checkpoint to load
args['checkpoint'] = None
args['dump_trb'] = False
args['dump_args'] = True
args['save_best_plddt'] = True
args['T'] = 25
args['strand_bias'] = 0.0
args['loop_bias'] = 0.0
args['helix_bias'] = 0.0
def protein_diffusion_model(sequence, seq_len, helix_bias, strand_bias, loop_bias,
secondary_structure, aa_bias, aa_bias_potential,
num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
contigs, pssm, seq_mask, str_mask, rewrite_pdb):
dssp_checkpoint = './SEQDIFF_230205_dssp_hotspots_25mask_EQtasks_mod30.pt'
og_checkpoint = './SEQDIFF_221219_equalTASKS_nostrSELFCOND_mod30.pt'
model_args = copy.deepcopy(args)
# make sampler
S = HuggingFace_sampler(args=model_args)
# get random prefix
S.out_prefix = './tmp/'+secrets.token_hex(nbytes=10).upper()
# set args
S.args['checkpoint'] = None
S.args['dump_trb'] = False
S.args['dump_args'] = True
S.args['save_best_plddt'] = True
S.args['T'] = 20
S.args['strand_bias'] = 0.0
S.args['loop_bias'] = 0.0
S.args['helix_bias'] = 0.0
S.args['potentials'] = None
S.args['potential_scale'] = None
S.args['aa_composition'] = None
# get sequence if entered and make sure all chars are valid
alt_aa_dict = {'B':['D','N'],'J':['I','L'],'U':['C'],'Z':['E','Q'],'O':['K']}
if sequence not in ['',None]:
L = len(sequence)
aa_seq = []
for aa in sequence.upper():
if aa in alt_aa_dict.keys():
aa_seq.append(np.random.choice(alt_aa_dict[aa]))
else:
aa_seq.append(aa)
S.args['sequence'] = aa_seq
elif contigs not in ['',None]:
S.args['contigs'] = [contigs]
else:
S.args['contigs'] = [f'{seq_len}']
L = int(seq_len)
print('DEBUG: ',rewrite_pdb)
if rewrite_pdb not in ['',None]:
S.args['pdb'] = rewrite_pdb.name
if seq_mask not in ['',None]:
S.args['inpaint_seq'] = [seq_mask]
if str_mask not in ['',None]:
S.args['inpaint_str'] = [str_mask]
if secondary_structure in ['',None]:
secondary_structure = None
else:
secondary_structure = ''.join(['E' if x == 'S' else x for x in secondary_structure])
if L < len(secondary_structure):
secondary_structure = secondary_structure[:len(sequence)]
elif L == len(secondary_structure):
pass
else:
dseq = L - len(secondary_structure)
secondary_structure += secondary_structure[-1]*dseq
# potentials
potential_list = []
potential_bias_list = []
if aa_bias not in ['',None]:
potential_list.append('aa_bias')
S.args['aa_composition'] = aa_bias
if aa_bias_potential in ['',None]:
aa_bias_potential = 3
potential_bias_list.append(str(aa_bias_potential))
'''
if target_charge not in ['',None]:
potential_list.append('charge')
if charge_potential in ['',None]:
charge_potential = 1
potential_bias_list.append(str(charge_potential))
S.args['target_charge'] = float(target_charge)
if target_ph in ['',None]:
target_ph = 7.4
S.args['target_pH'] = float(target_ph)
'''
if hydrophobic_target_score not in ['',None]:
potential_list.append('hydrophobic')
S.args['hydrophobic_score'] = float(hydrophobic_target_score)
if hydrophobic_potential in ['',None]:
hydrophobic_potential = 3
potential_bias_list.append(str(hydrophobic_potential))
if pssm not in ['',None]:
potential_list.append('PSSM')
potential_bias_list.append('5')
S.args['PSSM'] = pssm.name
if len(potential_list) > 0:
S.args['potentials'] = ','.join(potential_list)
S.args['potential_scale'] = ','.join(potential_bias_list)
# normalise secondary_structure bias from range 0-0.3
S.args['secondary_structure'] = secondary_structure
S.args['helix_bias'] = helix_bias
S.args['strand_bias'] = strand_bias
S.args['loop_bias'] = loop_bias
# set T
if num_steps in ['',None]:
S.args['T'] = 20
else:
S.args['T'] = int(num_steps)
# noise
if 'normal' in noise:
S.args['sample_distribution'] = noise
S.args['sample_distribution_gmm_means'] = [0]
S.args['sample_distribution_gmm_variances'] = [1]
elif 'gmm2' in noise:
S.args['sample_distribution'] = noise
S.args['sample_distribution_gmm_means'] = [-1,1]
S.args['sample_distribution_gmm_variances'] = [1,1]
elif 'gmm3' in noise:
S.args['sample_distribution'] = noise
S.args['sample_distribution_gmm_means'] = [-1,0,1]
S.args['sample_distribution_gmm_variances'] = [1,1,1]
if secondary_structure not in ['',None] or helix_bias+strand_bias+loop_bias > 0:
S.args['checkpoint'] = dssp_checkpoint
S.args['d_t1d'] = 29
print('using dssp checkpoint')
else:
S.args['checkpoint'] = og_checkpoint
S.args['d_t1d'] = 24
print('using og checkpoint')
for k,v in S.args.items():
print(f"{k} --> {v}")
# init S
S.model_init()
S.diffuser_init()
S.setup()
# sampling loop
plddt_data = []
for j in range(S.max_t):
print(f'on step {j}')
output_seq, output_pdb, plddt = S.take_step_get_outputs(j)
plddt_data.append(plddt)
yield output_seq, output_pdb, display_pdb(output_pdb), get_plddt_plot(plddt_data, S.max_t)
output_seq, output_pdb, plddt = S.get_outputs()
return output_seq, output_pdb, display_pdb(output_pdb), get_plddt_plot(plddt_data, S.max_t)
def get_plddt_plot(plddt_data, max_t):
x = [i+1 for i in range(len(plddt_data))]
fig, ax = plt.subplots(figsize=(15,6))
ax.plot(x,plddt_data,color='#661dbf', linewidth=3,marker='o')
ax.set_xticks([i+1 for i in range(max_t)])
ax.set_yticks([(i+1)/10 for i in range(10)])
ax.set_ylim([0,1])
ax.set_ylabel('model confidence (plddt)')
ax.set_xlabel('diffusion steps (t)')
return fig
def display_pdb(path_to_pdb):
'''
#function to display pdb in py3dmol
'''
pdb = open(path_to_pdb, "r").read()
view = py3Dmol.view(width=500, height=500)
view.addModel(pdb, "pdb")
view.setStyle({'model': -1}, {"cartoon": {'colorscheme':{'prop':'b','gradient':'roygb','min':0,'max':1}}})#'linear', 'min': 0, 'max': 1, 'colors': ["#ff9ef0","#a903fc",]}}})
view.zoomTo()
output = view._make_html().replace("'", '"')
print(view._make_html())
x = f""" {output} """ # do not use ' in this input
return f""""""
'''
return f""""""
'''
def get_motif_preview(pdb_id, contigs):
try:
input_pdb = fetch_pdb(pdb_id=pdb_id.lower() if pdb_id else None)
if input_pdb is None:
return gr.HTML("PDB ID를 입력해주세요"), None
parse = parse_pdb(input_pdb)
output_name = input_pdb
pdb = open(output_name, "r").read()
view = py3Dmol.view(width=500, height=500)
view.addModel(pdb, "pdb")
if contigs in ['',0]:
contigs = ['0']
else:
contigs = [contigs]
print('DEBUG: ',contigs)
pdb_map = get_mappings(ContigMap(parse,contigs))
print('DEBUG: ',pdb_map)
print('DEBUG: ',pdb_map['con_ref_idx0'])
roi = [x[1]-1 for x in pdb_map['con_ref_pdb_idx']]
colormap = {0:'#D3D3D3', 1:'#F74CFF'}
colors = {i+1: colormap[1] if i in roi else colormap[0] for i in range(parse['xyz'].shape[0])}
view.setStyle({"cartoon": {"colorscheme": {"prop": "resi", "map": colors}}})
view.zoomTo()
output = view._make_html().replace("'", '"')
print(view._make_html())
x = f""" {output} """ # do not use ' in this input
return f"""""", output_name
except Exception as e:
return gr.HTML(f"오류가 발생했습니다: {str(e)}"), None
def fetch_pdb(pdb_id=None):
if pdb_id is None or pdb_id == "":
return None
else:
os.system(f"wget -qnc https://files.rcsb.org/view/{pdb_id}.pdb")
return f"{pdb_id}.pdb"
# MSA AND PSSM GUIDANCE
def save_pssm(file_upload):
filename = file_upload.name
orig_name = file_upload.orig_name
if filename.split('.')[-1] in ['fasta', 'a3m']:
return msa_to_pssm(file_upload)
return filename
def msa_to_pssm(msa_file):
# Define the lookup table for converting amino acids to indices
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,
'K': 11, 'M': 12, 'F': 13, 'P': 14, 'S': 15, 'T': 16, 'W': 17, 'Y': 18, 'V': 19, 'X': 20, '-': 21}
# Open the FASTA file and read the sequences
records = list(SeqIO.parse(msa_file.name, "fasta"))
assert len(records) >= 1, "MSA must contain more than one protein sequecne."
first_seq = str(records[0].seq)
aligned_seqs = [first_seq]
# print(aligned_seqs)
# Perform sequence alignment using the Needleman-Wunsch algorithm
aligner = Align.PairwiseAligner()
aligner.open_gap_score = -0.7
aligner.extend_gap_score = -0.3
for record in records[1:]:
alignment = aligner.align(first_seq, str(record.seq))[0]
alignment = alignment.format().split("\n")
al1 = alignment[0]
al2 = alignment[2]
al1_fin = ""
al2_fin = ""
percent_gap = al2.count('-')/ len(al2)
if percent_gap > 0.4:
continue
for i in range(len(al1)):
if al1[i] != '-':
al1_fin += al1[i]
al2_fin += al2[i]
aligned_seqs.append(str(al2_fin))
# Get the length of the aligned sequences
aligned_seq_length = len(first_seq)
# Initialize the position scoring matrix
matrix = np.zeros((22, aligned_seq_length))
# Iterate through the aligned sequences and count the amino acids at each position
for seq in aligned_seqs:
#print(seq)
for i in range(aligned_seq_length):
if i == len(seq):
break
amino_acid = seq[i]
if amino_acid.upper() not in aa_to_index.keys():
continue
else:
aa_index = aa_to_index[amino_acid.upper()]
matrix[aa_index, i] += 1
# Normalize the counts to get the frequency of each amino acid at each position
matrix /= len(aligned_seqs)
print(len(aligned_seqs))
matrix[20:,]=0
outdir = ".".join(msa_file.name.split('.')[:-1]) + ".csv"
np.savetxt(outdir, matrix[:21,:].T, delimiter=",")
return outdir
def get_pssm(fasta_msa, input_pssm):
try:
if input_pssm is not None:
outdir = input_pssm.name
elif fasta_msa is not None:
outdir = save_pssm(fasta_msa)
else:
return gr.Plot(label="파일을 업로드해주세요"), None
pssm = np.loadtxt(outdir, delimiter=",", dtype=float)
fig, ax = plt.subplots(figsize=(15,6))
plt.imshow(torch.permute(torch.tensor(pssm),(1,0)))
return fig, outdir
except Exception as e:
return gr.Plot(label=f"오류가 발생했습니다: {str(e)}"), None
# 히어로 능력치 계산 함수 추가
def calculate_hero_stats(helix_bias, strand_bias, loop_bias, hydrophobic_score):
stats = {
'strength': strand_bias * 20, # 베타시트 구조 기반
'flexibility': helix_bias * 20, # 알파헬릭스 구조 기반
'speed': loop_bias * 5, # 루프 구조 기반
'defense': abs(hydrophobic_score) if hydrophobic_score else 0
}
return stats
def toggle_seq_input(choice):
if choice == "자동 설계":
return gr.update(visible=True), gr.update(visible=False)
else: # "직접 입력"
return gr.update(visible=False), gr.update(visible=True)
def toggle_secondary_structure(choice):
if choice == "슬라이더로 설정":
return (
gr.update(visible=True), # helix_bias
gr.update(visible=True), # strand_bias
gr.update(visible=True), # loop_bias
gr.update(visible=False) # secondary_structure
)
else: # "직접 입력"
return (
gr.update(visible=False), # helix_bias
gr.update(visible=False), # strand_bias
gr.update(visible=False), # loop_bias
gr.update(visible=True) # secondary_structure
)
def create_radar_chart(stats):
# 레이더 차트 생성 로직
categories = list(stats.keys())
values = list(stats.values())
fig = go.Figure(data=go.Scatterpolar(
r=values,
theta=categories,
fill='toself'
))
fig.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 1]
)),
showlegend=False
)
return fig
def generate_hero_description(name, stats, abilities):
# 히어로 설명 생성 로직
description = f"""
히어로 이름: {name}
주요 능력:
- 근력: {'★' * int(stats['strength'] * 5)}
- 유연성: {'★' * int(stats['flexibility'] * 5)}
- 스피드: {'★' * int(stats['speed'] * 5)}
- 방어력: {'★' * int(stats['defense'] * 5)}
특수 능력: {', '.join(abilities)}
"""
return description
def combined_generation(name, strength, flexibility, speed, defense, size, abilities,
sequence, seq_len, helix_bias, strand_bias, loop_bias,
secondary_structure, aa_bias, aa_bias_potential,
num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
contigs, pssm, seq_mask, str_mask, rewrite_pdb):
try:
# protein_diffusion_model 실행
generator = protein_diffusion_model(
sequence=None,
seq_len=size, # 히어로 크기를 seq_len으로 사용
helix_bias=flexibility, # 히어로 유연성을 helix_bias로 사용
strand_bias=strength, # 히어로 강도를 strand_bias로 사용
loop_bias=speed, # 히어로 스피드를 loop_bias로 사용
secondary_structure=None,
aa_bias=None,
aa_bias_potential=None,
num_steps="25",
noise="normal",
hydrophobic_target_score=str(-defense), # 히어로 방어력을 hydrophobic score로 사용
hydrophobic_potential="2",
contigs=None,
pssm=None,
seq_mask=None,
str_mask=None,
rewrite_pdb=None
)
# 마지막 결과 가져오기
final_result = None
for result in generator:
final_result = result
if final_result is None:
raise Exception("생성 결과가 없습니다")
output_seq, output_pdb, structure_view, plddt_plot = final_result
# 히어로 능력치 계산
stats = calculate_hero_stats(flexibility, strength, speed, defense)
# 모든 결과 반환
return (
create_radar_chart(stats), # 능력치 차트
generate_hero_description(name, stats, abilities), # 히어로 설명
output_seq, # 단백질 서열
output_pdb, # PDB 파일
structure_view, # 3D 구조
plddt_plot # 신뢰도 차트
)
except Exception as e:
print(f"Error in combined_generation: {str(e)}")
return (
None,
f"에러: {str(e)}",
None,
None,
gr.HTML("에러가 발생했습니다"),
None
)
with gr.Blocks(theme='ParityError/Interstellar') as demo:
with gr.Row():
with gr.Column():
gr.Markdown("# 🦸♂️ 슈퍼히어로 단백질 만들기")
with gr.Tabs():
with gr.TabItem("🦸♂️ 히어로 디자인"):
gr.Markdown("""
### ✨ 당신만의 특별한 히어로를 만들어보세요!
각 능력치를 조절하면 히어로의 DNA가 자동으로 설계됩니다.
""")
# 히어로 기본 정보
hero_name = gr.Textbox(
label="히어로 이름",
placeholder="당신의 히어로 이름을 지어주세요!",
info="히어로의 정체성을 나타내는 이름을 입력하세요"
)
# 능력치 설정
gr.Markdown("### 💪 히어로 능력치 설정")
with gr.Row():
strength = gr.Slider(
minimum=0.0, maximum=0.05,
label="💪 초강력(근력)",
value=0.02,
info="단단한 베타시트 구조로 강력한 힘을 생성합니다"
)
flexibility = gr.Slider(
minimum=0.0, maximum=0.05,
label="🤸♂️ 유연성",
value=0.02,
info="나선형 알파헬릭스 구조로 유연한 움직임을 가능하게 합니다"
)
with gr.Row():
speed = gr.Slider(
minimum=0.0, maximum=0.20,
label="⚡ 스피드",
value=0.1,
info="루프 구조로 빠른 움직임을 구현합니다"
)
defense = gr.Slider(
minimum=-10, maximum=10,
label="🛡️ 방어력",
value=0,
info="음수: 수중 활동에 특화, 양수: 지상 활동에 특화"
)
# 히어로 크기 설정
hero_size = gr.Slider(
minimum=50, maximum=200,
label="📏 히어로 크기",
value=100,
info="히어로의 전체적인 크기를 결정합니다"
)
# 특수 능력 설정
with gr.Accordion("🌟 특수 능력", open=False):
gr.Markdown("""
특수 능력을 선택하면 히어로의 DNA에 특별한 구조가 추가됩니다.
- 자가 회복: 단백질 구조 복구 능력 강화
- 원거리 공격: 특수한 구조적 돌출부 형성
- 방어막 생성: 안정적인 보호층 구조 생성
""")
special_ability = gr.CheckboxGroup(
choices=["자가 회복", "원거리 공격", "방어막 생성"],
label="특수 능력 선택"
)
# 생성 버튼
create_btn = gr.Button("🧬 히어로 생성!", variant="primary", scale=2)
with gr.TabItem("🧬 히어로 DNA 설계"):
gr.Markdown("""
### 🧪 히어로 DNA 고급 설정
히어로의 유전자 구조를 더 세밀하게 조정할 수 있습니다.
""")
seq_opt = gr.Radio(
["자동 설계", "직접 입력"],
label="DNA 설계 방식",
value="자동 설계"
)
sequence = gr.Textbox(
label="DNA 시퀀스",
lines=1,
placeholder='사용 가능한 아미노산: A,C,D,E,F,G,H,I,K,L,M,N,P,Q,R,S,T,V,W,Y (X는 무작위)',
visible=False
)
seq_len = gr.Slider(
minimum=5.0, maximum=250.0,
label="DNA 길이",
value=100,
visible=True
)
with gr.Accordion(label='🦴 골격 구조 설정', open=True):
gr.Markdown("""
히어로의 기본 골격 구조를 설정합니다.
- 나선형 구조: 유연하고 탄력있는 움직임
- 병풍형 구조: 단단하고 강력한 힘
- 고리형 구조: 빠르고 민첩한 움직임
""")
sec_str_opt = gr.Radio(
["슬라이더로 설정", "직접 입력"],
label="골격 구조 설정 방식",
value="슬라이더로 설정"
)
secondary_structure = gr.Textbox(
label="골격 구조",
lines=1,
placeholder='H:나선형, S:병풍형, L:고리형, X:자동설정',
visible=False
)
with gr.Column():
helix_bias = gr.Slider(
minimum=0.0, maximum=0.05,
label="나선형 구조 비율",
visible=True
)
strand_bias = gr.Slider(
minimum=0.0, maximum=0.05,
label="병풍형 구조 비율",
visible=True
)
loop_bias = gr.Slider(
minimum=0.0, maximum=0.20,
label="고리형 구조 비율",
visible=True
)
# 아미노산 구성 설정 추가
with gr.Accordion(label='🧬 DNA 구성 설정', open=False):
gr.Markdown("""
특정 아미노산의 비율을 조절하여 히어로의 특성을 강화할 수 있습니다.
예시: W0.2,E0.1 (트립토판 20%, 글루탐산 10%)
""")
with gr.Row():
aa_bias = gr.Textbox(
label="아미노산 비율",
lines=1,
placeholder='예시: W0.2,E0.1'
)
aa_bias_potential = gr.Textbox(
label="강화 정도",
lines=1,
placeholder='1.0-5.0 사이 값 입력'
)
# 환경 적응력 설정 추가
with gr.Accordion(label='🌍 환경 적응력 설정', open=False):
gr.Markdown("""
히어로의 환경 적응력을 조절합니다.
음수: 수중 활동에 특화, 양수: 지상 활동에 특화
""")
with gr.Row():
hydrophobic_target_score = gr.Textbox(
label="환경 적응 점수",
lines=1,
placeholder='예시: -5 (수중 활동에 특화)'
)
hydrophobic_potential = gr.Textbox(
label="적응력 강화 정도",
lines=1,
placeholder='1.0-2.0 사이 값 입력'
)
# 확산 매개변수 설정
with gr.Accordion(label='⚙️ 고급 설정', open=False):
gr.Markdown("""
DNA 생성 과정의 세부 매개변수를 조정합니다.
""")
with gr.Row():
num_steps = gr.Textbox(
label="생성 단계",
lines=1,
placeholder='25 이하 권장'
)
noise = gr.Dropdown(
['normal','gmm2 [-1,1]','gmm3 [-1,0,1]'],
label='노이즈 타입',
value='normal'
)
design_btn = gr.Button("🧬 DNA 설계 생성!", variant="primary", scale=2)
with gr.TabItem("🧪 히어로 유전자 강화"):
gr.Markdown("""
### ⚡ 기존 히어로의 DNA 활용
강력한 히어로의 DNA 일부를 새로운 히어로에게 이식합니다.
""")
gr.Markdown("공개된 히어로 DNA 데이터베이스에서 코드를 찾을 수 있습니다")
pdb_id_code = gr.Textbox(
label="히어로 DNA 코드",
lines=1,
placeholder='기존 히어로의 DNA 코드를 입력하세요 (예: 1DPX)'
)
gr.Markdown("이식하고 싶은 DNA 영역을 선택하고 새로운 DNA를 추가할 수 있습니다")
contigs = gr.Textbox(
label="이식할 DNA 영역",
lines=1,
placeholder='예시: 15,A3-10,20-30'
)
with gr.Row():
seq_mask = gr.Textbox(
label='능력 재설계',
lines=1,
placeholder='선택한 영역의 능력을 새롭게 디자인'
)
str_mask = gr.Textbox(
label='구조 재설계',
lines=1,
placeholder='선택한 영역의 구조를 새롭게 디자인'
)
preview_viewer = gr.HTML()
rewrite_pdb = gr.File(label='히어로 DNA 파일')
preview_btn = gr.Button("🔍 미리보기", variant="secondary")
enhance_btn = gr.Button("⚡ 강화된 히어로 생성!", variant="primary", scale=2)
with gr.TabItem("👑 히어로 가문"):
gr.Markdown("""
### 🏰 위대한 히어로 가문의 유산
강력한 히어로 가문의 특성을 계승하여 새로운 히어로를 만듭니다.
""")
with gr.Row():
with gr.Column():
gr.Markdown("히어로 가문의 DNA 정보가 담긴 파일을 업로드하세요")
fasta_msa = gr.File(label='가문 DNA 데이터')
with gr.Column():
gr.Markdown("이미 분석된 가문 특성 데이터가 있다면 업로드하세요")
input_pssm = gr.File(label='가문 특성 데이터')
pssm = gr.File(label='분석된 가문 특성')
pssm_view = gr.Plot(label='가문 특성 분석 결과')
pssm_gen_btn = gr.Button("✨ 가문 특성 분석", variant="secondary")
inherit_btn = gr.Button("👑 가문의 힘 계승!", variant="primary", scale=2)
with gr.Column():
gr.Markdown("## 🦸♂️ 히어로 프로필")
# 능력치 레이더 차트
hero_stats = gr.Plot(label="능력치 분석")
# 히어로 설명
hero_description = gr.Textbox(label="히어로 특성", lines=3)
gr.Markdown("## 🧬 히어로 DNA 분석 결과")
gr.Markdown("#### ⚡ DNA 안정성 점수")
plddt_plot = gr.Plot(label='안정성 분석')
gr.Markdown("#### 📝 DNA 시퀀스")
output_seq = gr.Textbox(label="DNA 서열")
gr.Markdown("#### 💾 DNA 데이터")
output_pdb = gr.File(label="DNA 파일")
gr.Markdown("#### 🔬 DNA 구조")
output_viewer = gr.HTML()
# 이벤트 연결
seq_opt.change(
fn=toggle_seq_input,
inputs=[seq_opt],
outputs=[seq_len, sequence],
queue=False
)
sec_str_opt.change(
fn=toggle_secondary_structure,
inputs=[sec_str_opt],
outputs=[helix_bias, strand_bias, loop_bias, secondary_structure],
queue=False
)
preview_btn.click(get_motif_preview,[pdb_id_code, contigs],[preview_viewer, rewrite_pdb])
pssm_gen_btn.click(get_pssm,[fasta_msa,input_pssm],[pssm_view, pssm])
# 각 탭의 생성 버튼 연결
create_btn.click(
combined_generation,
inputs=[
hero_name, strength, flexibility, speed, defense, hero_size, special_ability,
sequence, seq_len, helix_bias, strand_bias, loop_bias,
secondary_structure, aa_bias, aa_bias_potential,
num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
contigs, pssm, seq_mask, str_mask, rewrite_pdb
],
outputs=[
hero_stats,
hero_description,
output_seq,
output_pdb,
output_viewer,
plddt_plot
]
)
design_btn.click(
combined_generation,
inputs=[
hero_name, strength, flexibility, speed, defense, hero_size, special_ability,
sequence, seq_len, helix_bias, strand_bias, loop_bias,
secondary_structure, aa_bias, aa_bias_potential,
num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
contigs, pssm, seq_mask, str_mask, rewrite_pdb
],
outputs=[
hero_stats,
hero_description,
output_seq,
output_pdb,
output_viewer,
plddt_plot
]
)
enhance_btn.click(
combined_generation,
inputs=[
hero_name, strength, flexibility, speed, defense, hero_size, special_ability,
sequence, seq_len, helix_bias, strand_bias, loop_bias,
secondary_structure, aa_bias, aa_bias_potential,
num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
contigs, pssm, seq_mask, str_mask, rewrite_pdb
],
outputs=[
hero_stats,
hero_description,
output_seq,
output_pdb,
output_viewer,
plddt_plot
]
)
inherit_btn.click(
combined_generation,
inputs=[
hero_name, strength, flexibility, speed, defense, hero_size, special_ability,
sequence, seq_len, helix_bias, strand_bias, loop_bias,
secondary_structure, aa_bias, aa_bias_potential,
num_steps, noise, hydrophobic_target_score, hydrophobic_potential,
contigs, pssm, seq_mask, str_mask, rewrite_pdb
],
outputs=[
hero_stats,
hero_description,
output_seq,
output_pdb,
output_viewer,
plddt_plot
]
)
demo.queue()
demo.launch(debug=True)