Upload 26 files
Browse files- app_selfies_singlev8.py +2260 -0
- config.json +60 -0
- fpscores.pkl.gz +3 -0
- generation_config.json +9 -0
- lgbm_gas_pipeline.joblib +3 -0
- model.safetensors +3 -0
- polimerx_critic_v2_sanitized.joblib +3 -0
- requirements.txt +0 -0
- rf_eps.joblib +3 -0
- rf_refractive_index.joblib +3 -0
- sascorer.py +192 -0
- special_tokens_map.json +125 -0
- spiece.model +3 -0
- tokenizer.json +0 -0
- tokenizer_config.json +939 -0
- xgb_band gap bulk.joblib +3 -0
- xgb_band gap chain.joblib +3 -0
- xgb_bandgap-crystal.joblib +3 -0
- xgb_cte.joblib +3 -0
- xgb_gaspermability.joblib +3 -0
- xgb_loi.joblib +3 -0
- xgb_solubility.joblib +3 -0
- xgb_td.joblib +3 -0
- xgb_tg.joblib +3 -0
- xgb_thermal_cond.joblib +3 -0
- xgb_tm.joblib +3 -0
app_selfies_singlev8.py
ADDED
|
@@ -0,0 +1,2260 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# =========================================================================
|
| 2 |
+
# I. KURULUM VE KÜTÜPHANELER
|
| 3 |
+
# =========================================================================
|
| 4 |
+
import google.generativeai as genai
|
| 5 |
+
import streamlit as st
|
| 6 |
+
import numpy as np
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import joblib
|
| 9 |
+
import random
|
| 10 |
+
import operator
|
| 11 |
+
import time
|
| 12 |
+
import math
|
| 13 |
+
from stmol import showmol
|
| 14 |
+
import py3Dmol
|
| 15 |
+
import pubchempy as pcp
|
| 16 |
+
# Optimizasyon için DEAP kütüphanesi
|
| 17 |
+
import deap.base as base
|
| 18 |
+
import deap.creator as creator
|
| 19 |
+
import deap.tools as tools
|
| 20 |
+
from deap import algorithms
|
| 21 |
+
import lightgbm as lgbm
|
| 22 |
+
# Kimya kütüphaneleri
|
| 23 |
+
from rdkit import Chem
|
| 24 |
+
from rdkit.Chem import AllChem
|
| 25 |
+
from rdkit import RDLogger
|
| 26 |
+
import selfies as sf
|
| 27 |
+
from datasets import load_dataset
|
| 28 |
+
import rdkit.Chem.rdChemReactions as rdChemReactions
|
| 29 |
+
# import stmol as showmol # 3D görselleştirme kütüphanesi (varsa)
|
| 30 |
+
|
| 31 |
+
RDLogger.DisableLog('rdApp.*')
|
| 32 |
+
from rdkit.Chem import Draw
|
| 33 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
|
| 34 |
+
import matplotlib.pyplot as plt
|
| 35 |
+
# --- YEREL RETROSENTEZ MODELİ ENTEGRASYONU ---
|
| 36 |
+
|
| 37 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
|
| 38 |
+
|
| 39 |
+
# --- MODELİ ÖNBELLEĞE AL (Sadece 1 kere yüklenir) ---
|
| 40 |
+
@st.cache_resource
|
| 41 |
+
def load_my_trained_model():
|
| 42 |
+
model_path = "./PolimerX_Model"
|
| 43 |
+
try:
|
| 44 |
+
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
| 45 |
+
model = AutoModelForSeq2SeqLM.from_pretrained(model_path)
|
| 46 |
+
return tokenizer, model
|
| 47 |
+
except Exception as e:
|
| 48 |
+
st.error(f"Model yüklenemedi: {e}")
|
| 49 |
+
return None, None
|
| 50 |
+
|
| 51 |
+
def predict_monomers_local(polymer_smiles):
|
| 52 |
+
"""
|
| 53 |
+
Önce eğitilmiş T5 modelini kullanır.
|
| 54 |
+
Eğer sonuç başarısızsa kural tabanlı motoru devreye sokar.
|
| 55 |
+
"""
|
| 56 |
+
# 1. MODEL TAHMİNİ
|
| 57 |
+
tokenizer, model = load_my_trained_model()
|
| 58 |
+
ai_prediction = ""
|
| 59 |
+
|
| 60 |
+
if model:
|
| 61 |
+
try:
|
| 62 |
+
# Eğitimde kullandığımız "retrosynthesis: " ön ekini unutmuyoruz!
|
| 63 |
+
input_text = "retrosynthesis: " + polymer_smiles
|
| 64 |
+
inputs = tokenizer(input_text, return_tensors="pt")
|
| 65 |
+
|
| 66 |
+
# Tahmin üret
|
| 67 |
+
outputs = model.generate(
|
| 68 |
+
inputs["input_ids"],
|
| 69 |
+
max_length=128,
|
| 70 |
+
num_beams=5, # En iyi 5 yolu ara
|
| 71 |
+
early_stopping=True
|
| 72 |
+
)
|
| 73 |
+
ai_prediction = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 74 |
+
except:
|
| 75 |
+
ai_prediction = ""
|
| 76 |
+
|
| 77 |
+
# 2. SONUÇ KONTROLÜ VE HİBRİT KARAR
|
| 78 |
+
# Model mantıklı bir şey (örneğin nokta ile ayrılmış iki parça) döndürdü mü?
|
| 79 |
+
if ai_prediction and " . " in ai_prediction:
|
| 80 |
+
return f"{ai_prediction} (Yerel AI Modeli)"
|
| 81 |
+
|
| 82 |
+
# Model başarısızsa veya emin değilse KURAL MOTORUNU çağır
|
| 83 |
+
else:
|
| 84 |
+
rules = decompose_polymer(polymer_smiles) # Mevcut fonksiyonun
|
| 85 |
+
if rules:
|
| 86 |
+
monomers = rules[0]['monomers']
|
| 87 |
+
return f"{' . '.join(monomers)} (Kural Tabanlı - Yedek)"
|
| 88 |
+
else:
|
| 89 |
+
# Model bir şey buldu ama nokta yoksa yine de gösterelim (belki tek monomerdir)
|
| 90 |
+
if ai_prediction:
|
| 91 |
+
return f"{ai_prediction} (AI Modeli - Tek Parça)"
|
| 92 |
+
return "Ayrıştırılamadı"
|
| 93 |
+
# --- YAYGIN ÇÖZÜCÜLER REFERANS LİSTESİ ---
|
| 94 |
+
COMMON_SOLVENTS = {
|
| 95 |
+
"n-Heksan (Apolar)": 7.3,
|
| 96 |
+
"Dietil Eter": 7.4,
|
| 97 |
+
"Toluen (Aromatik)": 8.9,
|
| 98 |
+
"Etil Asetat": 9.1,
|
| 99 |
+
"Kloroform": 9.3,
|
| 100 |
+
"Aseton (Polar Aprotik)": 9.9,
|
| 101 |
+
"Diklorometan (DCM)": 9.7,
|
| 102 |
+
"THF (Tetrahidrofuran)": 9.1,
|
| 103 |
+
"Etanol (Alkol)": 12.7,
|
| 104 |
+
"Metanol": 14.5,
|
| 105 |
+
"Su (Çok Polar)": 23.4
|
| 106 |
+
}
|
| 107 |
+
def get_soluble_solvents(pred_val):
|
| 108 |
+
"""Tahmin edilen Hildebrand değerine göre uygun çözücüleri bulur."""
|
| 109 |
+
soluble_list = []
|
| 110 |
+
swelling_list = [] # Kısmi çözünme / Şişme
|
| 111 |
+
|
| 112 |
+
for solvent, s_val in COMMON_SOLVENTS.items():
|
| 113 |
+
diff = abs(pred_val - s_val)
|
| 114 |
+
|
| 115 |
+
if diff <= 1.8: # İyi çözücü
|
| 116 |
+
soluble_list.append(solvent)
|
| 117 |
+
elif diff <= 2.5: # Sınırda (Isıtarak çözünebilir veya şişer)
|
| 118 |
+
swelling_list.append(solvent)
|
| 119 |
+
|
| 120 |
+
return soluble_list, swelling_list
|
| 121 |
+
def draw_2d_molecule(smiles):
|
| 122 |
+
"""SMILES kodundan yüksek kaliteli 2D resim oluşturur."""
|
| 123 |
+
try:
|
| 124 |
+
mol = Chem.MolFromSmiles(smiles)
|
| 125 |
+
if mol:
|
| 126 |
+
# Görüntü kalitesini artır
|
| 127 |
+
dopts = Draw.MolDrawOptions()
|
| 128 |
+
dopts.addAtomIndices = False
|
| 129 |
+
dopts.bondLineWidth = 2
|
| 130 |
+
return Draw.MolToImage(mol, size=(500, 400), options=dopts)
|
| 131 |
+
except:
|
| 132 |
+
return None
|
| 133 |
+
def inject_custom_css():
|
| 134 |
+
st.markdown("""
|
| 135 |
+
<style>
|
| 136 |
+
/* Ana Başlık Stili */
|
| 137 |
+
.main-title {
|
| 138 |
+
font-size: 3rem;
|
| 139 |
+
color: #4A90E2;
|
| 140 |
+
font-weight: 700;
|
| 141 |
+
text-align: center;
|
| 142 |
+
margin-bottom: 1rem;
|
| 143 |
+
}
|
| 144 |
+
/* Alt Başlık */
|
| 145 |
+
.sub-title {
|
| 146 |
+
font-size: 1.2rem;
|
| 147 |
+
color: #666;
|
| 148 |
+
text-align: center;
|
| 149 |
+
margin-bottom: 2rem;
|
| 150 |
+
}
|
| 151 |
+
/* Kart Tasarımı (Sonuçlar için) */
|
| 152 |
+
.metric-card {
|
| 153 |
+
background-color: #f9f9f9;
|
| 154 |
+
border-left: 5px solid #4A90E2;
|
| 155 |
+
padding: 15px;
|
| 156 |
+
border-radius: 8px;
|
| 157 |
+
box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
|
| 158 |
+
margin-bottom: 10px;
|
| 159 |
+
}
|
| 160 |
+
/* Dark Mode Uyumu için Kart Rengi */
|
| 161 |
+
@media (prefers-color-scheme: dark) {
|
| 162 |
+
.metric-card {
|
| 163 |
+
background-color: #262730;
|
| 164 |
+
border-left: 5px solid #4A90E2;
|
| 165 |
+
color: white;
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
</style>
|
| 169 |
+
""", unsafe_allow_html=True)
|
| 170 |
+
|
| 171 |
+
# Uygulamanın en başında çağırın:
|
| 172 |
+
inject_custom_css()
|
| 173 |
+
# --- SABİTLER ---
|
| 174 |
+
N_BITS = 2048 # Morgan Fingerprint boyutu
|
| 175 |
+
@st.cache_data
|
| 176 |
+
def get_initial_population():
|
| 177 |
+
"""Verisetini sadece bir kez indirir ve önbelleğe alır."""
|
| 178 |
+
repo_id = "OsBaran/Polimer-Ozellik-Tahmini"
|
| 179 |
+
tg_data = load_dataset(repo_id, split="Tg")
|
| 180 |
+
df = tg_data.to_pandas()
|
| 181 |
+
col_name = 'p_smiles' if 'p_smiles' in df.columns else 'smiles'
|
| 182 |
+
# Sadece geçerli SELFIES'leri filtrele ve listeye çevir
|
| 183 |
+
raw_smiles = df[col_name].tolist()
|
| 184 |
+
valid_selfies = []
|
| 185 |
+
for s in raw_smiles:
|
| 186 |
+
sf_str = smiles_to_selfies_safe(s)
|
| 187 |
+
if sf_str:
|
| 188 |
+
valid_selfies.append(sf_str)
|
| 189 |
+
return valid_selfies, raw_smiles # İkisini de döndür
|
| 190 |
+
# --- MODEL YÜKLEME ---
|
| 191 |
+
@st.cache_resource
|
| 192 |
+
def load_critic_models():
|
| 193 |
+
"""Tüm Eleştirmen (Critic) modellerini yükler."""
|
| 194 |
+
models = {}
|
| 195 |
+
try:
|
| 196 |
+
models['Tg'] = joblib.load('xgb_tg.joblib')
|
| 197 |
+
models['Td'] = joblib.load('xgb_td.joblib')
|
| 198 |
+
models['EPS'] = joblib.load('rf_eps.joblib')
|
| 199 |
+
# DİĞER MODELLERİNİZİ BURAYA EKLEYİN
|
| 200 |
+
models['Tm'] = joblib.load('xgb_tm.joblib')
|
| 201 |
+
models['BandgapBulk'] = joblib.load('xgb_band gap bulk.joblib')
|
| 202 |
+
models['BandgapChain'] = joblib.load('xgb_band gap chain.joblib')
|
| 203 |
+
models['BandgapCrystal'] = joblib.load('xgb_bandgap-crystal.joblib')
|
| 204 |
+
models['GasPerma'] = joblib.load('lgbm_gas_pipeline.joblib')
|
| 205 |
+
models['Refractive'] = joblib.load('rf_refractive_index.joblib')
|
| 206 |
+
|
| 207 |
+
models['LOI'] = joblib.load('xgb_loi.joblib') # Yanıcılık
|
| 208 |
+
models['Solubility'] = joblib.load('xgb_solubility.joblib') # Çözünürlük
|
| 209 |
+
models['ThermalCond'] = joblib.load('xgb_thermal_cond.joblib') # Isıl İletkenlik
|
| 210 |
+
models['CTE'] = joblib.load('xgb_cte.joblib')
|
| 211 |
+
|
| 212 |
+
return models
|
| 213 |
+
except Exception as e:
|
| 214 |
+
st.error(f"⚠️ Model Yükleme Hatası! Lütfen 'tg_model.joblib', 'td_model.joblib' ve 'eps_model.joblib' dosyalarının mevcut olduğundan emin olun. Hata: {e}")
|
| 215 |
+
return None
|
| 216 |
+
|
| 217 |
+
def run_ga_silent(models, generations, targets, active_props, initial_pop, ranges_dict):
|
| 218 |
+
"""
|
| 219 |
+
GA'yı grafik çizmeden (sessizce) çalıştırır. Çoklu testler için optimize edilmiştir.
|
| 220 |
+
"""
|
| 221 |
+
# DEAP Kurulumu (Mevcut kodunuzdakiyle aynı)
|
| 222 |
+
toolbox = base.Toolbox()
|
| 223 |
+
toolbox.register("attr_selfies", random.choice, initial_pop)
|
| 224 |
+
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_selfies, n=1)
|
| 225 |
+
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
|
| 226 |
+
toolbox.register("evaluate", evaluate_individual_optimized, models=models, targets=targets, active_props=active_props, ranges=ranges_dict)
|
| 227 |
+
toolbox.register("mate", cxSelfies)
|
| 228 |
+
toolbox.register("select", tools.selTournament, tournsize=7) # Turnuva boyutu 7 (Önerilen)
|
| 229 |
+
|
| 230 |
+
pop_size = 100
|
| 231 |
+
pop = toolbox.population(n=pop_size)
|
| 232 |
+
|
| 233 |
+
# Sadece en iyilerin geçmişini tutacağız
|
| 234 |
+
best_fitness_history = []
|
| 235 |
+
|
| 236 |
+
# Parametreler (Optimize ettiğimiz değerler)
|
| 237 |
+
cxpb, mutpb, extendpb, newpb, chempb = 0.8, 0.05, 0.05, 0.01, 0.05
|
| 238 |
+
|
| 239 |
+
# --- HIZLI DÖNGÜ ---
|
| 240 |
+
for gen in range(generations):
|
| 241 |
+
# Seçilim & Klonlama
|
| 242 |
+
offspring = toolbox.select(pop, pop_size)
|
| 243 |
+
offspring = list(map(toolbox.clone, offspring))
|
| 244 |
+
|
| 245 |
+
# Çaprazlama
|
| 246 |
+
for child1, child2 in zip(offspring[::2], offspring[1::2]):
|
| 247 |
+
if random.random() < cxpb:
|
| 248 |
+
toolbox.mate(child1, child2)
|
| 249 |
+
del child1.fitness.values, child2.fitness.values
|
| 250 |
+
|
| 251 |
+
# Mutasyon
|
| 252 |
+
for i in range(len(offspring)):
|
| 253 |
+
if not offspring[i].fitness.valid: pass
|
| 254 |
+
offspring[i] = generate_offspring(offspring[i], initial_pop, mutpb=mutpb, extendpb=extendpb, newpb=newpb, chempb=chempb)
|
| 255 |
+
del offspring[i].fitness.values
|
| 256 |
+
|
| 257 |
+
# Değerlendirme
|
| 258 |
+
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
|
| 259 |
+
fitnesses = map(toolbox.evaluate, invalid_ind)
|
| 260 |
+
for ind, fit in zip(invalid_ind, fitnesses):
|
| 261 |
+
ind.fitness.values = fit
|
| 262 |
+
|
| 263 |
+
pop = offspring
|
| 264 |
+
|
| 265 |
+
# En iyiyi kaydet
|
| 266 |
+
fits = [ind.fitness.values[0] for ind in pop]
|
| 267 |
+
best_fitness_history.append(min(fits))
|
| 268 |
+
|
| 269 |
+
return best_fitness_history
|
| 270 |
+
# --- YARDIMCI KİMYA FONKSİYONLARI (Değişmedi) --
|
| 271 |
+
def run_mass_random_test(models, generations, initial_pop, ranges_dict, num_trials=100):
|
| 272 |
+
"""
|
| 273 |
+
Rastgele hedeflerle 100 kez stres testi yapar.
|
| 274 |
+
"""
|
| 275 |
+
results = []
|
| 276 |
+
all_props_list = list(ranges_dict.keys())
|
| 277 |
+
|
| 278 |
+
# İlerleme Göstergeleri
|
| 279 |
+
progress_bar = st.progress(0)
|
| 280 |
+
status_text = st.empty()
|
| 281 |
+
|
| 282 |
+
for i in range(num_trials):
|
| 283 |
+
# 1. RASTGELE SENARYO OLUŞTURMA
|
| 284 |
+
# Kaç özellik optimize edilecek? (2 ile 5 arası rastgele)
|
| 285 |
+
n_active = random.randint(2, 5)
|
| 286 |
+
# Hangi özellikler olacak?
|
| 287 |
+
active_props = random.sample(all_props_list, n_active)
|
| 288 |
+
|
| 289 |
+
# Hedefleri belirle (Rastgele)
|
| 290 |
+
current_targets = {}
|
| 291 |
+
target_descriptions = []
|
| 292 |
+
for prop in active_props:
|
| 293 |
+
r = ranges_dict[prop]
|
| 294 |
+
# Min ve Max arasında rastgele bir değer seç
|
| 295 |
+
val = random.uniform(r['min'], r['max'])
|
| 296 |
+
|
| 297 |
+
# Bazı değerleri tam sayıya yuvarla (Sıcaklıklar gibi)
|
| 298 |
+
if r.get('is_int', False) or prop in ['Tg', 'Td', 'Tm', 'LOI']:
|
| 299 |
+
val = round(val, 0)
|
| 300 |
+
else:
|
| 301 |
+
val = round(val, 2)
|
| 302 |
+
|
| 303 |
+
current_targets[prop] = val
|
| 304 |
+
target_descriptions.append(f"{prop}={val}")
|
| 305 |
+
|
| 306 |
+
# 2. GA'YI ÇALIŞTIR (Sessiz Modda)
|
| 307 |
+
# run_ga_silent fonksiyonunu önceki adımdan aldığınızı varsayıyorum
|
| 308 |
+
history = run_ga_silent(models, generations, current_targets, active_props, initial_pop, ranges_dict)
|
| 309 |
+
|
| 310 |
+
# 3. SONUCU KAYDET
|
| 311 |
+
final_score = history[-1] # En son jenerasyonun en iyi skoru
|
| 312 |
+
|
| 313 |
+
results.append({
|
| 314 |
+
"Deneme No": i + 1,
|
| 315 |
+
"Hedef Sayısı": n_active,
|
| 316 |
+
"Hedefler": ", ".join(target_descriptions),
|
| 317 |
+
"Final Hata Skoru": final_score
|
| 318 |
+
})
|
| 319 |
+
|
| 320 |
+
# İlerlemeyi Güncelle
|
| 321 |
+
progress_bar.progress((i + 1) / num_trials)
|
| 322 |
+
status_text.text(f"Test {i+1}/{num_trials} | Son Hata: {final_score:.4f} | Hedefler: {', '.join(target_descriptions)[:50]}...")
|
| 323 |
+
|
| 324 |
+
status_text.success(f"{num_trials} Farklı Senaryo Testi Tamamlandı!")
|
| 325 |
+
return pd.DataFrame(results)
|
| 326 |
+
def smiles_to_selfies_safe(smiles):
|
| 327 |
+
if not smiles: return None
|
| 328 |
+
clean_smi = smiles.replace('*', '[H]').replace('(*)', '[H]').replace('[*]', '[H]')
|
| 329 |
+
try:
|
| 330 |
+
selfies_string = sf.encoder(clean_smi)
|
| 331 |
+
return selfies_string.replace('[H]', '[*]')
|
| 332 |
+
except:
|
| 333 |
+
return None
|
| 334 |
+
|
| 335 |
+
def selfies_to_smiles_safe(selfes_string):
|
| 336 |
+
if not selfes_string: return None
|
| 337 |
+
try:
|
| 338 |
+
temp_selfies = selfes_string.replace('[*]', '[H]')
|
| 339 |
+
smiles = sf.decoder(temp_selfies)
|
| 340 |
+
return smiles.replace('[H]', '*')
|
| 341 |
+
except:
|
| 342 |
+
return None
|
| 343 |
+
|
| 344 |
+
def get_morgan_fp(p_smiles):
|
| 345 |
+
smi_clean = str(p_smiles).replace('*', '[H]').replace('(*)', '[H]').replace('[*]', '[H]')
|
| 346 |
+
mol = Chem.MolFromSmiles(smi_clean)
|
| 347 |
+
if mol is None: return None
|
| 348 |
+
fp = AllChem.GetMorganFingerprintAsBitVect(mol, 3, N_BITS)
|
| 349 |
+
return np.array([fp])
|
| 350 |
+
# --- MEVCUT IMPORTLARIN ALTINA EKLE ---
|
| 351 |
+
from rdkit.Chem import Descriptors
|
| 352 |
+
|
| 353 |
+
# --- YENİ ÖZELLİK FONKSİYONU ---
|
| 354 |
+
def get_gas_features_combined(smiles):
|
| 355 |
+
"""
|
| 356 |
+
Gaz geçirgenliği LGBM modeli için hem Morgan FP hem de
|
| 357 |
+
Fiziksel Deskriptörleri birleştirir.
|
| 358 |
+
"""
|
| 359 |
+
try:
|
| 360 |
+
mol = Chem.MolFromSmiles(smiles.replace('*', '[H]'))
|
| 361 |
+
if mol is None: return None
|
| 362 |
+
|
| 363 |
+
# 1. Morgan Fingerprint (2048 bit)
|
| 364 |
+
fp = np.array(AllChem.GetMorganFingerprintAsBitVect(mol, 3, nBits=2048))
|
| 365 |
+
|
| 366 |
+
# 2. Fiziksel Deskriptörler
|
| 367 |
+
desc = np.array([
|
| 368 |
+
Descriptors.MolWt(mol),
|
| 369 |
+
Descriptors.MolLogP(mol),
|
| 370 |
+
Descriptors.TPSA(mol),
|
| 371 |
+
Descriptors.NumRotatableBonds(mol),
|
| 372 |
+
Descriptors.FractionCSP3(mol),
|
| 373 |
+
Descriptors.HallKierAlpha(mol)
|
| 374 |
+
])
|
| 375 |
+
|
| 376 |
+
# İkisini birleştir
|
| 377 |
+
return np.concatenate((fp, desc)).reshape(1, -1)
|
| 378 |
+
except:
|
| 379 |
+
return None
|
| 380 |
+
def cxSelfies(ind1, ind2):
|
| 381 |
+
t1 = list(sf.split_selfies(ind1[0]))
|
| 382 |
+
t2 = list(sf.split_selfies(ind2[0]))
|
| 383 |
+
min_len = min(len(t1), len(t2))
|
| 384 |
+
if min_len < 2: return ind1, ind2
|
| 385 |
+
|
| 386 |
+
# Segmentleri belirle
|
| 387 |
+
split1 = random.randint(1, min_len-1)
|
| 388 |
+
split2 = random.randint(1, min_len-1)
|
| 389 |
+
|
| 390 |
+
new1 = t1[:split1] + t2[split2:]
|
| 391 |
+
new2 = t2[:split2] + t1[split1:]
|
| 392 |
+
|
| 393 |
+
# Valid bireyleri seç
|
| 394 |
+
new1_str = "".join(new1)
|
| 395 |
+
new2_str = "".join(new2)
|
| 396 |
+
|
| 397 |
+
if is_valid_polymer(new1_str):
|
| 398 |
+
ind1[0] = new1_str
|
| 399 |
+
if is_valid_polymer(new2_str):
|
| 400 |
+
ind2[0] = new2_str
|
| 401 |
+
return ind1, ind2
|
| 402 |
+
|
| 403 |
+
def mutSelfies(individual):
|
| 404 |
+
# Mutasyon fonksiyonu (Değişmedi)
|
| 405 |
+
tokens = list(sf.split_selfies(individual[0]))
|
| 406 |
+
if not tokens: return individual,
|
| 407 |
+
if random.random() < 0.6 and len(tokens) > 1:
|
| 408 |
+
idx = random.randint(0, len(tokens) - 1)
|
| 409 |
+
del tokens[idx]
|
| 410 |
+
if random.random() < 0.4:
|
| 411 |
+
idx = random.randint(0, len(tokens))
|
| 412 |
+
new_token = random.choice(['[C]', '[N]', '[O]', '[F]', '[Cl]', '[S]', '[*]'])
|
| 413 |
+
tokens.insert(idx, new_token)
|
| 414 |
+
individual[0] = "".join(tokens)
|
| 415 |
+
return individual,
|
| 416 |
+
|
| 417 |
+
# =========================================================================
|
| 418 |
+
# II. DİNAMİK DEĞERLENDİRME ÇEKİRDEĞİ (DYNAMIC EVALUATE)
|
| 419 |
+
# =========================================================================
|
| 420 |
+
# II. DİNAMİK DEĞERLENDİRME ÇEKİRDEĞİ kısmına ekleyin
|
| 421 |
+
|
| 422 |
+
# Global önbellek sözlüğü (Uygulama yeniden başlayana kadar tutulur)
|
| 423 |
+
# Key: SELFIES string, Value: (Fitness Score,)
|
| 424 |
+
FITNESS_CACHE = {}
|
| 425 |
+
|
| 426 |
+
def evaluate_individual_optimized(individual, models, targets, active_props, ranges):
|
| 427 |
+
s_selfies = individual[0]
|
| 428 |
+
|
| 429 |
+
# Önbellek Kontrolü
|
| 430 |
+
if s_selfies in FITNESS_CACHE:
|
| 431 |
+
return FITNESS_CACHE[s_selfies]
|
| 432 |
+
|
| 433 |
+
s_smiles = selfies_to_smiles_safe(s_selfies)
|
| 434 |
+
if s_smiles is None: return (1000.0,)
|
| 435 |
+
|
| 436 |
+
# Standart Fingerprint (Diğer modeller için)
|
| 437 |
+
fp = get_morgan_fp(s_smiles)
|
| 438 |
+
|
| 439 |
+
# Gas Model Özellikleri (Sadece GasPerma aktifse hesapla)
|
| 440 |
+
gas_features = None
|
| 441 |
+
if 'GasPerma' in active_props:
|
| 442 |
+
gas_features = get_gas_features_combined(s_smiles)
|
| 443 |
+
|
| 444 |
+
if fp is None: return (1000.0,)
|
| 445 |
+
|
| 446 |
+
preds = {}
|
| 447 |
+
|
| 448 |
+
# --- TAHMİN DÖNGÜSÜ ---
|
| 449 |
+
for prop in active_props:
|
| 450 |
+
if prop in models:
|
| 451 |
+
# ÖZEL DURUM: GasPerma modeli için özel özellikleri kullan
|
| 452 |
+
if prop == 'GasPerma':
|
| 453 |
+
if gas_features is not None:
|
| 454 |
+
# Model log10 tahmini yapıyor, bunu gerçek değere çeviriyoruz (10^x)
|
| 455 |
+
log_pred = models[prop].predict(gas_features)[0]
|
| 456 |
+
preds[prop] = 10 ** log_pred
|
| 457 |
+
else:
|
| 458 |
+
preds[prop] = 0.0 # Hata durumunda
|
| 459 |
+
|
| 460 |
+
# DİĞERLERİ: Standart Fingerprint kullanır
|
| 461 |
+
else:
|
| 462 |
+
preds[prop] = models[prop].predict(fp)[0]
|
| 463 |
+
|
| 464 |
+
# --- HATA HESAPLAMA ---
|
| 465 |
+
total_error = 0.0
|
| 466 |
+
if not active_props: return (1000.0,)
|
| 467 |
+
|
| 468 |
+
for prop in active_props:
|
| 469 |
+
if prop in preds:
|
| 470 |
+
norm_error = abs(preds[prop] - targets[prop]) / (ranges[prop]['max'] - ranges[prop]['min'])
|
| 471 |
+
total_error += np.exp(norm_error * 10) - 1
|
| 472 |
+
|
| 473 |
+
# ... (Geri kalan SA Score ve return kısmı aynı kalacak) ...
|
| 474 |
+
sa_score = get_sa_score_local(s_smiles)
|
| 475 |
+
total_error += sa_score * 2.0
|
| 476 |
+
|
| 477 |
+
result = (total_error,)
|
| 478 |
+
FITNESS_CACHE[s_selfies] = result
|
| 479 |
+
return result
|
| 480 |
+
def run_random_benchmark(models, targets, active_props, initial_pop, ranges_dict, total_budget, batch_size=100):
|
| 481 |
+
"""
|
| 482 |
+
GA ile adil kıyaslama için Rastgele Arama (Random Search) yapar.
|
| 483 |
+
total_budget: Toplam değerlendirme sayısı (GA'daki pop_size * generations)
|
| 484 |
+
batch_size: Grafik çizimi için her kaç adımda bir kayıt alınacağı (GA'daki pop_size kadar olmalı)
|
| 485 |
+
"""
|
| 486 |
+
history_random = []
|
| 487 |
+
best_so_far = float('inf')
|
| 488 |
+
|
| 489 |
+
# İlerleme çubuğu (kullanıcı beklerken sıkılmasın)
|
| 490 |
+
progress_text = st.empty()
|
| 491 |
+
bar = st.progress(0)
|
| 492 |
+
|
| 493 |
+
for i in range(0, total_budget, batch_size):
|
| 494 |
+
# Batch (Grup) halindeki rastgele bireyler
|
| 495 |
+
# initial_pop listesinden rastgele seç
|
| 496 |
+
candidates = random.sample(initial_pop, batch_size)
|
| 497 |
+
|
| 498 |
+
scores = []
|
| 499 |
+
for ind_selfies in candidates:
|
| 500 |
+
# Mevcut evaluate fonksiyonunu kullanıyoruz (Adil olması için)
|
| 501 |
+
# individual formatı liste olduğu için [ind_selfies] şeklinde veriyoruz
|
| 502 |
+
fit = evaluate_individual_optimized([ind_selfies], models, targets, active_props, ranges_dict)
|
| 503 |
+
|
| 504 |
+
# Ceza puanı alanları (1000) filtreleyebiliriz veya olduğu gibi alabiliriz
|
| 505 |
+
# Random search genelde çok hata yapar, olduğu gibi alalım.
|
| 506 |
+
scores.append(fit[0])
|
| 507 |
+
|
| 508 |
+
# Bu batch'teki en iyiyi bul
|
| 509 |
+
current_batch_best = min(scores)
|
| 510 |
+
|
| 511 |
+
# Genel en iyiyi güncelle
|
| 512 |
+
if current_batch_best < best_so_far:
|
| 513 |
+
best_so_far = current_batch_best
|
| 514 |
+
|
| 515 |
+
history_random.append(best_so_far)
|
| 516 |
+
|
| 517 |
+
# İlerlemeyi güncelle
|
| 518 |
+
progress = (i + batch_size) / total_budget
|
| 519 |
+
if progress > 1.0: progress = 1.0
|
| 520 |
+
bar.progress(progress)
|
| 521 |
+
progress_text.text(f"Rastgele Arama: {i}/{total_budget} tamamlandı. En iyi skor: {best_so_far:.4f}")
|
| 522 |
+
|
| 523 |
+
bar.empty()
|
| 524 |
+
progress_text.empty()
|
| 525 |
+
return history_random
|
| 526 |
+
|
| 527 |
+
def evaluate_individual_single_obj(individual, models, targets, active_props):
|
| 528 |
+
|
| 529 |
+
"""
|
| 530 |
+
|
| 531 |
+
Seçilen hedeflere (active_props) olan toplam mesafeye (hata) göre değerlendirir.
|
| 532 |
+
|
| 533 |
+
"""
|
| 534 |
+
|
| 535 |
+
s_selfies = individual[0]
|
| 536 |
+
|
| 537 |
+
s_smiles = selfies_to_smiles_safe(s_selfies)
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
|
| 541 |
+
if s_smiles is None:
|
| 542 |
+
|
| 543 |
+
return (1000.0,)
|
| 544 |
+
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
fp = get_morgan_fp(s_smiles)
|
| 548 |
+
|
| 549 |
+
if fp is None:
|
| 550 |
+
|
| 551 |
+
return (1000.0,)
|
| 552 |
+
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
# 1. Tahminleri Al
|
| 556 |
+
|
| 557 |
+
preds = {}
|
| 558 |
+
|
| 559 |
+
for prop in active_props:
|
| 560 |
+
|
| 561 |
+
if prop in models:
|
| 562 |
+
|
| 563 |
+
preds[prop] = models[prop].predict(fp)[0]
|
| 564 |
+
|
| 565 |
+
|
| 566 |
+
|
| 567 |
+
# 2. Toplam Hatayı Hesapla
|
| 568 |
+
|
| 569 |
+
total_error = 0.0
|
| 570 |
+
|
| 571 |
+
|
| 572 |
+
|
| 573 |
+
if not active_props:
|
| 574 |
+
|
| 575 |
+
# Hiçbir hedef seçilmezse ceza
|
| 576 |
+
|
| 577 |
+
return (1000.0,)
|
| 578 |
+
|
| 579 |
+
|
| 580 |
+
|
| 581 |
+
for prop in active_props:
|
| 582 |
+
|
| 583 |
+
# Hata = |Tahmin - Hedef|
|
| 584 |
+
|
| 585 |
+
if prop in preds:
|
| 586 |
+
|
| 587 |
+
norm_error = abs(preds[prop] - targets[prop]) / (ranges[prop]['max'] - ranges[prop]['min'])
|
| 588 |
+
|
| 589 |
+
total_error += np.exp(norm_error * 10) - 1 # Küçük farklar neredeyse lineer, büyük farklar çok ağır
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
|
| 593 |
+
# Seçilen hiçbir özellik hesaplanamazsa büyük ceza
|
| 594 |
+
|
| 595 |
+
if total_error == 0.0 and len(active_props) > 0:
|
| 596 |
+
|
| 597 |
+
return (1000.0,)
|
| 598 |
+
|
| 599 |
+
total_error += get_sa_score_local(s_smiles) / 10.0 # SA Score ekle
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
return (total_error,)
|
| 603 |
+
|
| 604 |
+
# =========================================================================
|
| 605 |
+
# III. ANA GENETİK ALGORİTMA AKIŞI
|
| 606 |
+
# =========================================================================
|
| 607 |
+
|
| 608 |
+
# DEAP Yapısını Tanımlama (Minimizasyon için)
|
| 609 |
+
if "FitnessMin" not in creator.__dict__:
|
| 610 |
+
creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) # Minimizasyon için
|
| 611 |
+
creator.create("Individual", list, fitness=creator.FitnessMin)
|
| 612 |
+
|
| 613 |
+
# =========================
|
| 614 |
+
# 1. Sentezlenebilirlik Kontrolü
|
| 615 |
+
# =========================
|
| 616 |
+
def is_valid_polymer(selfies_str):
|
| 617 |
+
"""
|
| 618 |
+
Hem kimyasal geçerliliği hem de polimer olma şartını (bağlantı noktaları) kontrol eder.
|
| 619 |
+
"""
|
| 620 |
+
# 1. SELFIES -> SMILES dönüşümü
|
| 621 |
+
smiles = selfies_to_smiles_safe(selfies_str)
|
| 622 |
+
if smiles is None:
|
| 623 |
+
return False
|
| 624 |
+
|
| 625 |
+
# ==========================================================
|
| 626 |
+
# KONTROL 1: Bağlantı Noktası (Star Atom) Kontrolü
|
| 627 |
+
# ==========================================================
|
| 628 |
+
# Bir polimerin tekrar eden birim (monomer) olması için
|
| 629 |
+
# en az 2 ucunun açık olması gerekir (* işareti).
|
| 630 |
+
# Lineer polimerler için genellikle tam 2 adet istenir.
|
| 631 |
+
# Ağ yapılı (cross-linked) polimerler için >2 olabilir.
|
| 632 |
+
|
| 633 |
+
star_count = smiles.count('*')
|
| 634 |
+
if star_count < 2:
|
| 635 |
+
return False # Zincir kopmuş, bu artık bir polimer değil.
|
| 636 |
+
|
| 637 |
+
# ==========================================================
|
| 638 |
+
# KONTROL 2: Çok Küçük Moleküllerin Engellenmesi
|
| 639 |
+
# ==========================================================
|
| 640 |
+
# GA bazen "*C*" gibi çok anlamsız küçük şeyler üretebilir.
|
| 641 |
+
# Yıldızlar hariç atom sayısına bakabiliriz.
|
| 642 |
+
|
| 643 |
+
clean_smi = smiles.replace('*', '[H]')
|
| 644 |
+
mol = Chem.MolFromSmiles(clean_smi)
|
| 645 |
+
|
| 646 |
+
if mol is None:
|
| 647 |
+
return False # Kimyasal olarak bozuk
|
| 648 |
+
|
| 649 |
+
# Yıldızlar (Hidrojen oldu) hariç ağır atom sayısı (C, O, N vs.) en az 4 olsun
|
| 650 |
+
if mol.GetNumHeavyAtoms() < 4:
|
| 651 |
+
return False
|
| 652 |
+
|
| 653 |
+
return True
|
| 654 |
+
|
| 655 |
+
|
| 656 |
+
MUTATION_TOKENS = ['[C]', '[N]', '[O]', '[F]', '[Cl]', '[S]', '[*]', 'c', 'n', 'o']
|
| 657 |
+
|
| 658 |
+
# =========================
|
| 659 |
+
# 2. Mutasyon (küçük token değişiklikleri)
|
| 660 |
+
# =========================
|
| 661 |
+
def mutSelfies(individual, max_attempts=5):
|
| 662 |
+
tokens = list(sf.split_selfies(individual[0]))
|
| 663 |
+
if not tokens:
|
| 664 |
+
return individual
|
| 665 |
+
|
| 666 |
+
for _ in range(max_attempts):
|
| 667 |
+
temp_tokens = tokens.copy()
|
| 668 |
+
# Token silme
|
| 669 |
+
if random.random() < 0.3 and len(temp_tokens) > 1:
|
| 670 |
+
idx = random.randint(0, len(temp_tokens) - 1)
|
| 671 |
+
del temp_tokens[idx]
|
| 672 |
+
# Token ekleme
|
| 673 |
+
if random.random() < 0.3:
|
| 674 |
+
idx = random.randint(0, len(temp_tokens))
|
| 675 |
+
new_token = random.choice(MUTATION_TOKENS)
|
| 676 |
+
temp_tokens.insert(idx, new_token)
|
| 677 |
+
# Token değiştirme
|
| 678 |
+
if random.random() < 0.3:
|
| 679 |
+
idx = random.randint(0, len(temp_tokens) - 1)
|
| 680 |
+
temp_tokens[idx] = random.choice(MUTATION_TOKENS)
|
| 681 |
+
|
| 682 |
+
candidate = "".join(temp_tokens)
|
| 683 |
+
if is_valid_polymer(candidate):
|
| 684 |
+
individual[0] = candidate
|
| 685 |
+
return individual
|
| 686 |
+
|
| 687 |
+
# Max deneme sonrası geçerli değilse rastgele valid birey ata
|
| 688 |
+
individual[0] = random.choice(initial_selfies)
|
| 689 |
+
return individual
|
| 690 |
+
|
| 691 |
+
|
| 692 |
+
# =========================
|
| 693 |
+
# 3. Zincir Uzatma
|
| 694 |
+
# =========================
|
| 695 |
+
def extendPolymer(individual, max_add=3):
|
| 696 |
+
tokens = list(sf.split_selfies(individual[0]))
|
| 697 |
+
for _ in range(random.randint(1, max_add)):
|
| 698 |
+
tokens.append(random.choice(['[C]', '[N]', '[O]', '[F]', '[Cl]', '[S]']))
|
| 699 |
+
candidate = "".join(tokens)
|
| 700 |
+
return candidate if is_valid_polymer(candidate) else individual[0]
|
| 701 |
+
|
| 702 |
+
|
| 703 |
+
# =========================
|
| 704 |
+
# 4. Reaction tabanlı mutasyon
|
| 705 |
+
# =========================
|
| 706 |
+
import rdkit.Chem.rdChemReactions as rdChemReactions
|
| 707 |
+
from rdkit.Chem import rdmolops
|
| 708 |
+
|
| 709 |
+
# Örnek reaction havuzu (kendi ihtiyacına göre genişletilebilir)
|
| 710 |
+
REACTION_SMARTS = [
|
| 711 |
+
"[C:1][H:2]>>[C:1]Cl",
|
| 712 |
+
"[C:1][H:2]>>[C:1]O",
|
| 713 |
+
"[C:1](=O)[O;H1].[O;H1][C:2]>>[C:1](=O)O[C:2]",
|
| 714 |
+
"[C:1](=O)Cl.[N:2]>>[C:1](=O)N",
|
| 715 |
+
"[O:1][H].[C:2]Br>>[O:1][C:2]",
|
| 716 |
+
"c1ccccc1>>c1([N+](=O)[O-])ccccc1",
|
| 717 |
+
"[C:1]=[C:2]>>[C:1]-[C:2]"
|
| 718 |
+
]
|
| 719 |
+
|
| 720 |
+
RDKit_REACTIONS = [rdChemReactions.ReactionFromSmarts(s) for s in REACTION_SMARTS]
|
| 721 |
+
|
| 722 |
+
def chemically_valid_mutate(p_smi: str, reactions=RDKit_REACTIONS, attempts=6):
|
| 723 |
+
"""Reaction tabanlı mutasyon uygular; başarısızsa fallback döner."""
|
| 724 |
+
def sanitize_and_canonicalize(smiles):
|
| 725 |
+
try:
|
| 726 |
+
mol = Chem.MolFromSmiles(smiles)
|
| 727 |
+
if mol is None: return None
|
| 728 |
+
rdmolops.SanitizeMol(mol)
|
| 729 |
+
return Chem.MolToSmiles(mol, canonical=True)
|
| 730 |
+
except:
|
| 731 |
+
return None
|
| 732 |
+
|
| 733 |
+
def replace_star_with_H(smi: str):
|
| 734 |
+
return str(smi).replace('*', '[H]')
|
| 735 |
+
|
| 736 |
+
def restore_H_to_star(smi: str):
|
| 737 |
+
return str(smi).replace('[H]', '*')
|
| 738 |
+
|
| 739 |
+
def is_reasonable_product(prod_smiles, max_atoms=120, min_atoms=4):
|
| 740 |
+
if prod_smiles is None: return False
|
| 741 |
+
try:
|
| 742 |
+
m = Chem.MolFromSmiles(prod_smiles)
|
| 743 |
+
if m is None: return False
|
| 744 |
+
n = m.GetNumAtoms()
|
| 745 |
+
if n > max_atoms or n < min_atoms: return False
|
| 746 |
+
try: rdmolops.SanitizeMol(m)
|
| 747 |
+
except: return False
|
| 748 |
+
return True
|
| 749 |
+
except: return False
|
| 750 |
+
|
| 751 |
+
# 1. Prepare
|
| 752 |
+
base = replace_star_with_H(p_smi)
|
| 753 |
+
base_mol = Chem.MolFromSmiles(base)
|
| 754 |
+
if base_mol is None: return p_smi
|
| 755 |
+
|
| 756 |
+
# 2. Reaction denemeleri
|
| 757 |
+
candidate_products = []
|
| 758 |
+
for _ in range(attempts):
|
| 759 |
+
rxn = random.choice(reactions)
|
| 760 |
+
try:
|
| 761 |
+
ps = rxn.RunReactants((base_mol,))
|
| 762 |
+
except:
|
| 763 |
+
ps = ()
|
| 764 |
+
for prod_tuple in ps:
|
| 765 |
+
for prod_mol in prod_tuple:
|
| 766 |
+
try:
|
| 767 |
+
prod_smiles = Chem.MolToSmiles(prod_mol, canonical=True)
|
| 768 |
+
except: prod_smiles = None
|
| 769 |
+
prod_restored = restore_H_to_star(prod_smiles) if prod_smiles else None
|
| 770 |
+
if is_reasonable_product(prod_restored):
|
| 771 |
+
candidate_products.append(prod_restored)
|
| 772 |
+
|
| 773 |
+
# 3. Sonuç
|
| 774 |
+
if candidate_products:
|
| 775 |
+
out = random.choice(candidate_products)
|
| 776 |
+
if out == p_smi or len(out) < max(4, len(p_smi)//2):
|
| 777 |
+
return p_smi
|
| 778 |
+
return out
|
| 779 |
+
return p_smi
|
| 780 |
+
|
| 781 |
+
# =========================
|
| 782 |
+
# 5. Offspring Üretim Fonksiyonu
|
| 783 |
+
# =========================
|
| 784 |
+
|
| 785 |
+
mutation_stats = {'SELFIES':0, 'REACTION':0, 'EXTEND':0, 'NEW':0}
|
| 786 |
+
|
| 787 |
+
def generate_offspring(individual, initial_selfies, mutpb=0.05, extendpb=0.05, newpb=0.01, chempb=0.05):
|
| 788 |
+
"""Mutasyon, zincir uzatma, yeni birey ve reaction mutasyonunu uygular."""
|
| 789 |
+
# 1. SELFIES mutasyonu
|
| 790 |
+
if random.random() < mutpb:
|
| 791 |
+
individual = mutSelfies(individual)
|
| 792 |
+
mutation_stats['SELFIES'] += 1
|
| 793 |
+
|
| 794 |
+
# 2. Reaction tabanlı mutasyon
|
| 795 |
+
if random.random() < chempb:
|
| 796 |
+
smi = selfies_to_smiles_safe(individual[0])
|
| 797 |
+
if smi:
|
| 798 |
+
mutated = chemically_valid_mutate(smi)
|
| 799 |
+
ind_selfies = smiles_to_selfies_safe(mutated)
|
| 800 |
+
if ind_selfies:
|
| 801 |
+
individual[0] = ind_selfies
|
| 802 |
+
mutation_stats['REACTION'] += 1
|
| 803 |
+
|
| 804 |
+
# 3. Zincir uzatma
|
| 805 |
+
if random.random() < extendpb:
|
| 806 |
+
individual[0] = extendPolymer(individual)
|
| 807 |
+
mutation_stats['EXTEND'] += 1
|
| 808 |
+
|
| 809 |
+
# 4. Rastgele yeni birey
|
| 810 |
+
if random.random() < newpb:
|
| 811 |
+
individual[0] = random.choice(initial_selfies)
|
| 812 |
+
mutation_stats['NEW'] += 1
|
| 813 |
+
|
| 814 |
+
# 5. Geçerlilik kontrolü
|
| 815 |
+
if not is_valid_polymer(individual[0]):
|
| 816 |
+
individual[0] = random.choice(initial_selfies)
|
| 817 |
+
return individual
|
| 818 |
+
|
| 819 |
+
# =========================
|
| 820 |
+
# 6. run_single_objective_flow Güncellemesi
|
| 821 |
+
# =========================
|
| 822 |
+
def run_single_objective_flow(models, generations, targets, active_props, initial_pop, ranges_dict):
|
| 823 |
+
# --- DEAP Kurulumu ---
|
| 824 |
+
toolbox = base.Toolbox()
|
| 825 |
+
toolbox.register("attr_selfies", random.choice, initial_pop)
|
| 826 |
+
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_selfies, n=1)
|
| 827 |
+
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
|
| 828 |
+
|
| 829 |
+
# Optimize edilmiş evaluate fonksiyonu
|
| 830 |
+
toolbox.register("evaluate", evaluate_individual_optimized, models=models, targets=targets, active_props=active_props, ranges=ranges_dict)
|
| 831 |
+
|
| 832 |
+
toolbox.register("mate", cxSelfies)
|
| 833 |
+
toolbox.register("select", tools.selTournament, tournsize=7)
|
| 834 |
+
|
| 835 |
+
pop_size = 100
|
| 836 |
+
pop = toolbox.population(n=pop_size)
|
| 837 |
+
|
| 838 |
+
# --- PERFORMANS TAKİP VERİ YAPISI ---
|
| 839 |
+
history = {
|
| 840 |
+
"gen": [],
|
| 841 |
+
"best_fitness": [],
|
| 842 |
+
"avg_fitness": [],
|
| 843 |
+
"diversity": [] # Standart sapma
|
| 844 |
+
}
|
| 845 |
+
|
| 846 |
+
# İlk değerlendirme
|
| 847 |
+
fitnesses = list(map(toolbox.evaluate, pop))
|
| 848 |
+
for ind, fit in zip(pop, fitnesses):
|
| 849 |
+
ind.fitness.values = fit
|
| 850 |
+
|
| 851 |
+
# --- UI Elementleri (Canlı Dashboard) ---
|
| 852 |
+
st.markdown("### 🧬 Evrimsel Süreç İzleme Paneli")
|
| 853 |
+
progress_bar = st.progress(0)
|
| 854 |
+
status_text = st.empty()
|
| 855 |
+
|
| 856 |
+
# Grafikler için yan yana iki kolon (Canlı güncellenecek)
|
| 857 |
+
col_chart1, col_chart2 = st.columns(2)
|
| 858 |
+
with col_chart1:
|
| 859 |
+
st.caption("📉 Yakınsama (Convergence)")
|
| 860 |
+
chart_fitness_placeholder = st.empty()
|
| 861 |
+
with col_chart2:
|
| 862 |
+
st.caption("🌊 Popülasyon Çeşitliliği (Diversity)")
|
| 863 |
+
chart_diversity_placeholder = st.empty()
|
| 864 |
+
|
| 865 |
+
log_expander = st.expander("📝 GA Logları (Detay)", expanded=False)
|
| 866 |
+
with log_expander:
|
| 867 |
+
log_placeholder = st.empty()
|
| 868 |
+
mutation_placeholder = st.empty()
|
| 869 |
+
|
| 870 |
+
log_data = []
|
| 871 |
+
|
| 872 |
+
# --- ANA DÖNGÜ ---
|
| 873 |
+
for gen in range(generations):
|
| 874 |
+
# Adaptif oranlar
|
| 875 |
+
scale = gen / generations
|
| 876 |
+
cxpb = 0.7 - (0.2 * scale)
|
| 877 |
+
mutpb = 0.05 - (0.2 * scale)
|
| 878 |
+
extendpb = 0.05 - (0.15 * scale)
|
| 879 |
+
newpb = 0.01 - (0.05 * scale)
|
| 880 |
+
chempb = 0.05 - (0.15 * scale)
|
| 881 |
+
|
| 882 |
+
# Seçilim ve Klonlama
|
| 883 |
+
offspring = toolbox.select(pop, pop_size)
|
| 884 |
+
offspring = list(map(toolbox.clone, offspring))
|
| 885 |
+
|
| 886 |
+
# Çaprazlama
|
| 887 |
+
for child1, child2 in zip(offspring[::2], offspring[1::2]):
|
| 888 |
+
if random.random() < cxpb:
|
| 889 |
+
toolbox.mate(child1, child2)
|
| 890 |
+
del child1.fitness.values, child2.fitness.values
|
| 891 |
+
|
| 892 |
+
# Mutasyon
|
| 893 |
+
for i in range(len(offspring)):
|
| 894 |
+
if not offspring[i].fitness.valid:
|
| 895 |
+
pass
|
| 896 |
+
offspring[i] = generate_offspring(offspring[i], initial_pop, mutpb=mutpb, extendpb=extendpb, newpb=newpb, chempb=chempb)
|
| 897 |
+
del offspring[i].fitness.values
|
| 898 |
+
|
| 899 |
+
# Değerlendirme
|
| 900 |
+
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
|
| 901 |
+
fitnesses = map(toolbox.evaluate, invalid_ind)
|
| 902 |
+
for ind, fit in zip(invalid_ind, fitnesses):
|
| 903 |
+
ind.fitness.values = fit
|
| 904 |
+
|
| 905 |
+
pop = offspring
|
| 906 |
+
|
| 907 |
+
# --- İstatistik Toplama (Kritik Bölüm) ---
|
| 908 |
+
# --- ESKİ KOD (SİLİN) ---
|
| 909 |
+
# fits = [ind.fitness.values[0] for ind in pop]
|
| 910 |
+
# best_val = min(fits)
|
| 911 |
+
# mean_val = sum(fits) / len(pop)
|
| 912 |
+
# std_val = np.std(fits)
|
| 913 |
+
|
| 914 |
+
# --- YENİ KOD (BUNU YAPIŞTIRIN) ---
|
| 915 |
+
fits = [ind.fitness.values[0] for ind in pop]
|
| 916 |
+
|
| 917 |
+
# 1. Sadece "Canlı" (Geçerli) bireyleri filtrele (Ceza puanı 999'dan küçük olanlar)
|
| 918 |
+
valid_fits = [f for f in fits if f < 999.0]
|
| 919 |
+
|
| 920 |
+
# 2. İstatistikleri sadece canlılar üzerinden hesapla
|
| 921 |
+
if valid_fits:
|
| 922 |
+
best_val = min(valid_fits) # Zaten min değişmez ama garanti olsun
|
| 923 |
+
mean_val = sum(valid_fits) / len(valid_fits) # GERÇEK ORTALAMA
|
| 924 |
+
std_val = np.std(valid_fits) # GERÇEK ÇEŞİTLİLİK
|
| 925 |
+
else:
|
| 926 |
+
# Herkes öldüyse (Çok nadir olur)
|
| 927 |
+
best_val = 1000.0
|
| 928 |
+
mean_val = 1000.0
|
| 929 |
+
std_val = 0.0
|
| 930 |
+
|
| 931 |
+
# 3. Hayatta Kalma Oranını Hesapla (Survival Rate)
|
| 932 |
+
survival_rate = (len(valid_fits) / len(pop)) * 100
|
| 933 |
+
|
| 934 |
+
# Geçmişe kaydet (survival_rate'i de ekleyebilirsin istersen)
|
| 935 |
+
history["gen"].append(gen)
|
| 936 |
+
history["best_fitness"].append(best_val)
|
| 937 |
+
history["avg_fitness"].append(mean_val)
|
| 938 |
+
history["diversity"].append(std_val)
|
| 939 |
+
|
| 940 |
+
log_data.append({
|
| 941 |
+
"Nesil": gen + 1,
|
| 942 |
+
"En İyi Hata": round(best_val, 4),
|
| 943 |
+
"Ortalama (Valid)": round(mean_val, 4),
|
| 944 |
+
"Canlılık Oranı %": round(survival_rate, 1) # Log tablosunda bunu görmek çok işinize yarar
|
| 945 |
+
})
|
| 946 |
+
|
| 947 |
+
# --- UI Güncelleme (Her adımda veya 2 adımda bir) ---
|
| 948 |
+
if gen % 2 == 0 or gen == generations - 1:
|
| 949 |
+
progress_bar.progress((gen + 1) / generations)
|
| 950 |
+
status_text.markdown(f"**Nesil {gen+1}/{generations}** | En İyi Hata: `{best_val:.4f}` | Çeşitlilik: `{std_val:.4f}`")
|
| 951 |
+
|
| 952 |
+
# 1. Fitness Grafiği Verisi
|
| 953 |
+
df_fit = pd.DataFrame({
|
| 954 |
+
"En İyi (Best)": history["best_fitness"],
|
| 955 |
+
"Ortalama (Avg)": history["avg_fitness"]
|
| 956 |
+
})
|
| 957 |
+
chart_fitness_placeholder.line_chart(df_fit, height=250)
|
| 958 |
+
|
| 959 |
+
# 2. Diversity Grafiği Verisi
|
| 960 |
+
df_div = pd.DataFrame({
|
| 961 |
+
"Çeşitlilik (Std Dev)": history["diversity"]
|
| 962 |
+
})
|
| 963 |
+
# Çeşitlilik grafiğini kırmızı tonla göstermek için (Streamlit varsayılanı kullanır ama veri tek kolon)
|
| 964 |
+
chart_diversity_placeholder.line_chart(df_div, height=250)
|
| 965 |
+
|
| 966 |
+
# Log Tablosu
|
| 967 |
+
df_log = pd.DataFrame(log_data)
|
| 968 |
+
log_placeholder.dataframe(df_log.sort_values(by="Nesil", ascending=False).head(5), use_container_width=True)
|
| 969 |
+
mutation_placeholder.json(mutation_stats)
|
| 970 |
+
|
| 971 |
+
# Sonuç
|
| 972 |
+
best_ind = tools.selBest(pop, 5)[0]
|
| 973 |
+
best_smiles = selfies_to_smiles_safe(best_ind[0])
|
| 974 |
+
|
| 975 |
+
# ... (Yukarıdaki GA döngüsü bittikten sonra) ...
|
| 976 |
+
|
| 977 |
+
# Sonuç - En iyi bireyi seç
|
| 978 |
+
best_ind = tools.selBest(pop, 5)[0]
|
| 979 |
+
best_smiles = selfies_to_smiles_safe(best_ind[0])
|
| 980 |
+
|
| 981 |
+
if best_smiles:
|
| 982 |
+
# 1. Standart Fingerprint (Eski modeller için)
|
| 983 |
+
fp = get_morgan_fp(best_smiles)
|
| 984 |
+
|
| 985 |
+
# 2. Gaz Modeli için Gelişmiş Özellikler (Yeni model için)
|
| 986 |
+
gas_features = get_gas_features_combined(best_smiles)
|
| 987 |
+
|
| 988 |
+
preds = {}
|
| 989 |
+
|
| 990 |
+
# Tüm modeller için tahmin yaparken ayrım yapmalıyız
|
| 991 |
+
for prop in models.keys():
|
| 992 |
+
# ÖZEL DURUM: GasPerma
|
| 993 |
+
if prop == 'GasPerma':
|
| 994 |
+
if gas_features is not None:
|
| 995 |
+
# Model 2054 özellik bekler
|
| 996 |
+
log_pred = models[prop].predict(gas_features)[0]
|
| 997 |
+
# Log10'u geri çevir (10^x)
|
| 998 |
+
preds[prop] = 10 ** log_pred
|
| 999 |
+
else:
|
| 1000 |
+
preds[prop] = 0.0
|
| 1001 |
+
|
| 1002 |
+
# STANDART DURUM: Diğer modeller (Tg, Td, vs.)
|
| 1003 |
+
else:
|
| 1004 |
+
# Modeller sadece 2048 özellik (fp) bekler
|
| 1005 |
+
preds[prop] = models[prop].predict(fp)[0]
|
| 1006 |
+
|
| 1007 |
+
# History sözlüğünü döndürüyoruz
|
| 1008 |
+
return {'smiles': best_smiles, 'preds': preds, 'total_error': best_ind.fitness.values[0]}, history
|
| 1009 |
+
else:
|
| 1010 |
+
return None, history
|
| 1011 |
+
|
| 1012 |
+
import requests
|
| 1013 |
+
|
| 1014 |
+
@st.cache_data
|
| 1015 |
+
def check_pubchem_availability(smiles: str):
|
| 1016 |
+
"""
|
| 1017 |
+
Verilen SMILES için PubChem'de kayıtlı mı kontrol eder.
|
| 1018 |
+
Yıldızları (*) temizleyerek arama yapar.
|
| 1019 |
+
"""
|
| 1020 |
+
# DÜZELTME: Yıldızları temizle veya Hidrojene çevir
|
| 1021 |
+
clean_smi = smiles.replace('*', '')
|
| 1022 |
+
|
| 1023 |
+
# URL encoded hale getirmek gerekebilir ama requests bunu genelde yapar.
|
| 1024 |
+
url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/smiles/{clean_smi}/cids/JSON"
|
| 1025 |
+
|
| 1026 |
+
try:
|
| 1027 |
+
response = requests.get(url, timeout=5)
|
| 1028 |
+
|
| 1029 |
+
# 404 (Bulunamadı) normaldir, hata fırlatmasın
|
| 1030 |
+
if response.status_code == 404:
|
| 1031 |
+
return False, None, None
|
| 1032 |
+
|
| 1033 |
+
response.raise_for_status()
|
| 1034 |
+
data = response.json()
|
| 1035 |
+
|
| 1036 |
+
if "IdentifierList" in data and "CID" in data["IdentifierList"]:
|
| 1037 |
+
cid = data["IdentifierList"]["CID"][0]
|
| 1038 |
+
|
| 1039 |
+
# İsim sorgusu
|
| 1040 |
+
name_url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cid}/property/IUPACName/JSON"
|
| 1041 |
+
name_resp = requests.get(name_url, timeout=5)
|
| 1042 |
+
if name_resp.status_code == 200:
|
| 1043 |
+
name_data = name_resp.json()
|
| 1044 |
+
name = name_data["PropertyTable"]["Properties"][0].get("IUPACName", "Bilinmiyor")
|
| 1045 |
+
else:
|
| 1046 |
+
name = "Bilinmiyor"
|
| 1047 |
+
|
| 1048 |
+
return True, cid, name
|
| 1049 |
+
else:
|
| 1050 |
+
return False, None, None
|
| 1051 |
+
|
| 1052 |
+
except Exception:
|
| 1053 |
+
# Hata olsa bile uygulamayı durdurma, sessizce geç
|
| 1054 |
+
return False, None, None
|
| 1055 |
+
# --- TİCARİ KONTROL FONKSİYONU ---
|
| 1056 |
+
def check_commercial_availability(query):
|
| 1057 |
+
"""
|
| 1058 |
+
Verilen ismi veya SMILES'ı PubChem'de arar.
|
| 1059 |
+
Ticari olarak satılıp satılmadığını (Vendor sayısı) kontrol eder.
|
| 1060 |
+
"""
|
| 1061 |
+
try:
|
| 1062 |
+
# İsim veya SMILES ile arama yap
|
| 1063 |
+
compounds = pcp.get_compounds(query, 'name')
|
| 1064 |
+
if not compounds:
|
| 1065 |
+
compounds = pcp.get_compounds(query, 'smiles')
|
| 1066 |
+
|
| 1067 |
+
if compounds:
|
| 1068 |
+
cid = compounds[0].cid
|
| 1069 |
+
# PubChem'den "Vendor" (Satıcı) bilgisini çekmek biraz daha karmaşıktır,
|
| 1070 |
+
# bu yüzden basitçe "Kayıt var mı?" kontrolü yapıyoruz.
|
| 1071 |
+
# Kayıt varsa %99 ticaridir veya sentezlenebilir.
|
| 1072 |
+
synonyms = compounds[0].synonyms
|
| 1073 |
+
common_name = synonyms[0] if synonyms else query
|
| 1074 |
+
return True, cid, common_name
|
| 1075 |
+
else:
|
| 1076 |
+
return False, None, None
|
| 1077 |
+
except:
|
| 1078 |
+
return False, None, None
|
| 1079 |
+
def make_3d_view_with_reason(smiles):
|
| 1080 |
+
try:
|
| 1081 |
+
clean_smi = str(smiles).replace('*', '[H]')
|
| 1082 |
+
mol = Chem.MolFromSmiles(clean_smi)
|
| 1083 |
+
if mol is None:
|
| 1084 |
+
return None, "SMILES geçersiz veya RDKit ile molekül oluşturulamadı."
|
| 1085 |
+
|
| 1086 |
+
mol = Chem.AddHs(mol)
|
| 1087 |
+
if AllChem.EmbedMolecule(mol) != 0:
|
| 1088 |
+
return None, "3D koordinatlar hesaplanamadı (Embed başarısız)."
|
| 1089 |
+
|
| 1090 |
+
try:
|
| 1091 |
+
AllChem.MMFFOptimizeMolecule(mol)
|
| 1092 |
+
except:
|
| 1093 |
+
return None, "3D yapı enerji optimizasyonunda başarısız."
|
| 1094 |
+
|
| 1095 |
+
mblock = Chem.MolToMolBlock(mol)
|
| 1096 |
+
view = py3Dmol.view(width=400, height=400)
|
| 1097 |
+
view.addModel(mblock, 'mol')
|
| 1098 |
+
view.setStyle({'stick':{'colorscheme':'Jmol'}})
|
| 1099 |
+
view.zoomTo()
|
| 1100 |
+
view.spin(True)
|
| 1101 |
+
return view, None
|
| 1102 |
+
except Exception as e:
|
| 1103 |
+
return None, f"Beklenmeyen bir hata: {e}"
|
| 1104 |
+
|
| 1105 |
+
def get_ai_interpretation(api_key, smiles, preds, targets, active_props):
|
| 1106 |
+
"""Gemini API kullanarak polimer analizi yapar."""
|
| 1107 |
+
if not api_key:
|
| 1108 |
+
return "⚠️ Analiz için lütfen sol menüden geçerli bir Google Gemini API Anahtarı giriniz."
|
| 1109 |
+
|
| 1110 |
+
try:
|
| 1111 |
+
genai.configure(api_key=api_key)
|
| 1112 |
+
model = genai.GenerativeModel('gemini-2.5-flash') # Hızlı ve ekonomik model
|
| 1113 |
+
|
| 1114 |
+
# Dinamik Prompt Hazırlama
|
| 1115 |
+
prompt = f"""
|
| 1116 |
+
Sen uzman bir Polimer Kimyagerisin ve Malzeme Bilimci'sin.
|
| 1117 |
+
Aşağıda genetik algoritma ile üretilmiş yeni bir polimer adayı var.
|
| 1118 |
+
|
| 1119 |
+
Molekül (SMILES): {smiles}
|
| 1120 |
+
|
| 1121 |
+
Tahmin Edilen Özellikler:
|
| 1122 |
+
"""
|
| 1123 |
+
|
| 1124 |
+
for prop in active_props:
|
| 1125 |
+
target_val = targets.get(prop, "Belirtilmedi")
|
| 1126 |
+
pred_val = preds.get(prop, 0.0)
|
| 1127 |
+
prompt += f"- {prop}: Tahmin={pred_val:.2f} (Hedef={target_val})\n"
|
| 1128 |
+
|
| 1129 |
+
prompt += """
|
| 1130 |
+
|
| 1131 |
+
Lütfen bu polimeri şu başlıklar altında Türkçe olarak detaylıca analiz et:
|
| 1132 |
+
1. **Yapı-Özellik İlişkisi:** Bu yapısal özellikler (halkalar, fonksiyonel gruplar, zincir uzunluğu vb.) neden bu tahmin değerlerini (özellikle Tg ve Td) ortaya çıkarmış olabilir? Kimyasal mantığı nedir?
|
| 1133 |
+
2. **Potansiyel Uygulama Alanları:** Bu özelliklere sahip bir polimer endüstride nerede kullanılabilir? (Örn: Havacılık, paketleme, elektronik, membran vb.)
|
| 1134 |
+
3. **Sentezlenebilirlik Yorumu:** Yapıya bakarak sentez zorluğu veya stabilite hakkında kısa bir yorum yap.
|
| 1135 |
+
|
| 1136 |
+
Yanıtın profesyonel, bilimsel ama anlaşılır olsun. Markdown formatı kullan.
|
| 1137 |
+
"""
|
| 1138 |
+
|
| 1139 |
+
with st.spinner('Yapay Zeka polimeri inceliyor...'):
|
| 1140 |
+
response = model.generate_content(prompt)
|
| 1141 |
+
return response.text
|
| 1142 |
+
|
| 1143 |
+
except Exception as e:
|
| 1144 |
+
return f"❌ AI Bağlantı Hatası: {str(e)}"
|
| 1145 |
+
# --- SA Score Fonksiyonu ---
|
| 1146 |
+
|
| 1147 |
+
def get_sa_score_local(p_smiles):
|
| 1148 |
+
"""
|
| 1149 |
+
Yerel SA Score Hesaplayıcı.
|
| 1150 |
+
Eğer klasörde 'sascorer.py' varsa onu kullanır, yoksa basit hesaplama yapar.
|
| 1151 |
+
"""
|
| 1152 |
+
try:
|
| 1153 |
+
import sascorer
|
| 1154 |
+
smi_clean = str(p_smiles).replace('*', '[H]').replace('(*)', '[H]').replace('[*]', '[H]')
|
| 1155 |
+
mol = Chem.MolFromSmiles(smi_clean)
|
| 1156 |
+
if mol is None:
|
| 1157 |
+
raise ValueError("Mol oluşturulamadı")
|
| 1158 |
+
return sascorer.calculateScore(mol)
|
| 1159 |
+
except:
|
| 1160 |
+
# Basit yedek hesaplama: uzunluk ve halka sayısına göre
|
| 1161 |
+
length = len(str(p_smiles))
|
| 1162 |
+
score = 2.0 + (length * 0.05)
|
| 1163 |
+
if "c1" in str(p_smiles):
|
| 1164 |
+
score += 0.5
|
| 1165 |
+
return min(score, 10.0)
|
| 1166 |
+
# =========================================================================
|
| 1167 |
+
# VII. YEŞİL KİMYA / SÜRDÜRÜLEBİLİRLİK MOTORU
|
| 1168 |
+
# =========================================================================
|
| 1169 |
+
|
| 1170 |
+
def calculate_green_score(smiles):
|
| 1171 |
+
"""
|
| 1172 |
+
Polimerin potansiyel biyo-bozunurluğunu ve çevresel etkisini puanlar.
|
| 1173 |
+
Puan: 1 (Çok Kötü/Kalıcı) - 10 (Mükemmel/Bozunabilir)
|
| 1174 |
+
"""
|
| 1175 |
+
mol = Chem.MolFromSmiles(smiles.replace('*', '[H]'))
|
| 1176 |
+
if not mol: return 0, "Hesaplanamadı", "#7f8c8d"
|
| 1177 |
+
|
| 1178 |
+
score = 5.0 # Nötr başlangıç
|
| 1179 |
+
notes = []
|
| 1180 |
+
|
| 1181 |
+
# --- 1. BOZUNABİLİR BAĞLAR (Pozitif) ---
|
| 1182 |
+
# Ester Bağı: Hidroliz olur, doğada parçalanır (Örn: PLA)
|
| 1183 |
+
if mol.HasSubstructMatch(Chem.MolFromSmarts("[C;!R](=[O])[O;!R]")):
|
| 1184 |
+
score += 3.0
|
| 1185 |
+
notes.append("Ester bağı (Hidroliz olabilir)")
|
| 1186 |
+
|
| 1187 |
+
# Amid Bağı: Enzimlerle parçalanabilir (Örn: Proteinler, Naylon)
|
| 1188 |
+
if mol.HasSubstructMatch(Chem.MolFromSmarts("[C;!R](=[O])[N;!R]")):
|
| 1189 |
+
score += 2.0
|
| 1190 |
+
notes.append("Amid bağı (Biyo-bozunurluk potansiyeli)")
|
| 1191 |
+
|
| 1192 |
+
# Eter Bağı (PEG gibi): Suda çözünürlük sağlar, biyolojik atılımı kolaylaştırır
|
| 1193 |
+
if mol.HasSubstructMatch(Chem.MolFromSmarts("[C][O][C]")):
|
| 1194 |
+
score += 1.0
|
| 1195 |
+
notes.append("Eter grubu (Hidrofilik özellik)")
|
| 1196 |
+
|
| 1197 |
+
# --- 2. KALICILIK ve TOKSİSİTE (Negatif) ---
|
| 1198 |
+
# Halojenler (F, Cl, Br): Doğada birikim yapar, toksiktir (Örn: PVC, Teflon)
|
| 1199 |
+
halogens = [atom.GetSymbol() for atom in mol.GetAtoms() if atom.GetSymbol() in ['F', 'Cl', 'Br']]
|
| 1200 |
+
if halogens:
|
| 1201 |
+
count = len(halogens)
|
| 1202 |
+
penalty = min(4.0, count * 1.0) # En fazla 4 puan kır
|
| 1203 |
+
score -= penalty
|
| 1204 |
+
notes.append(f"{count} adet Halojen atomu (Kalıcılık/Toksisite riski)")
|
| 1205 |
+
|
| 1206 |
+
# Aromatik Halkalar: Bakterilerin parçalaması zordur
|
| 1207 |
+
aromatic_atoms = [atom for atom in mol.GetAtoms() if atom.GetIsAromatic()]
|
| 1208 |
+
if len(aromatic_atoms) > 4: # Çok fazla halka varsa
|
| 1209 |
+
score -= 2.0
|
| 1210 |
+
notes.append("Yüksek Aromatiklik (Zor parçalanma)")
|
| 1211 |
+
|
| 1212 |
+
# --- 3. SONUÇ SINIRLANDIRMA ---
|
| 1213 |
+
score = max(1.0, min(10.0, score)) # 1-10 arasına sabitle
|
| 1214 |
+
|
| 1215 |
+
# Renk Kodu Belirle
|
| 1216 |
+
if score >= 7.0: color = "#2ecc71" # Yeşil (İyi)
|
| 1217 |
+
elif score >= 4.0: color = "#f1c40f" # Sarı (Orta)
|
| 1218 |
+
else: color = "#e74c3c" # Kırmızı (Kötü)
|
| 1219 |
+
|
| 1220 |
+
return score, ", ".join(notes), color
|
| 1221 |
+
import plotly.graph_objects as go
|
| 1222 |
+
|
| 1223 |
+
def create_radar_chart(preds, targets, active_props, ranges):
|
| 1224 |
+
"""
|
| 1225 |
+
Hedeflenen özellikler ile tahmin edilen özellikleri karşılaştıran
|
| 1226 |
+
havalı bir Radar (Spider) Grafiği çizer.
|
| 1227 |
+
"""
|
| 1228 |
+
categories = []
|
| 1229 |
+
target_values = []
|
| 1230 |
+
pred_values = []
|
| 1231 |
+
|
| 1232 |
+
for prop in active_props:
|
| 1233 |
+
if prop in preds and prop in targets:
|
| 1234 |
+
# Başlıkları güzelleştir
|
| 1235 |
+
label = prop
|
| 1236 |
+
if prop == 'ThermalCond': label = 'Iletkenlik'
|
| 1237 |
+
if prop == 'Solubility': label = 'Cozunurluk'
|
| 1238 |
+
|
| 1239 |
+
categories.append(label)
|
| 1240 |
+
|
| 1241 |
+
# Değerleri al
|
| 1242 |
+
t_val = targets[prop]
|
| 1243 |
+
p_val = preds[prop]
|
| 1244 |
+
|
| 1245 |
+
# Normalizasyon (Grafikte düzgün durması için 0-1 arasına çekiyoruz)
|
| 1246 |
+
# Min-Max normalizasyonu
|
| 1247 |
+
min_v = ranges[prop]['min']
|
| 1248 |
+
max_v = ranges[prop]['max']
|
| 1249 |
+
|
| 1250 |
+
# Sıfıra bölme hatası önlemi
|
| 1251 |
+
if max_v - min_v == 0: denom = 1
|
| 1252 |
+
else: denom = max_v - min_v
|
| 1253 |
+
|
| 1254 |
+
norm_t = (t_val - min_v) / denom
|
| 1255 |
+
norm_p = (p_val - min_v) / denom
|
| 1256 |
+
|
| 1257 |
+
# Sınırlandırma (Grafik dışına taşmasın)
|
| 1258 |
+
norm_t = max(0.0, min(1.0, norm_t))
|
| 1259 |
+
norm_p = max(0.0, min(1.0, norm_p))
|
| 1260 |
+
|
| 1261 |
+
target_values.append(norm_t)
|
| 1262 |
+
pred_values.append(norm_p)
|
| 1263 |
+
|
| 1264 |
+
# Grafiği kapatmak için ilk değeri sona ekle
|
| 1265 |
+
categories = categories + [categories[0]]
|
| 1266 |
+
target_values = target_values + [target_values[0]]
|
| 1267 |
+
pred_values = pred_values + [pred_values[0]]
|
| 1268 |
+
|
| 1269 |
+
fig = go.Figure()
|
| 1270 |
+
|
| 1271 |
+
# Hedef Alanı (Mavi Çizgi)
|
| 1272 |
+
fig.add_trace(go.Scatterpolar(
|
| 1273 |
+
r=target_values,
|
| 1274 |
+
theta=categories,
|
| 1275 |
+
fill='toself',
|
| 1276 |
+
name='Hedeflenen',
|
| 1277 |
+
line=dict(color='#3498db', dash='dash')
|
| 1278 |
+
))
|
| 1279 |
+
|
| 1280 |
+
# Tahmin Alanı (Kırmızı Dolgu)
|
| 1281 |
+
fig.add_trace(go.Scatterpolar(
|
| 1282 |
+
r=pred_values,
|
| 1283 |
+
theta=categories,
|
| 1284 |
+
fill='toself',
|
| 1285 |
+
name='Uretilen Polimer',
|
| 1286 |
+
line=dict(color='#e74c3c'),
|
| 1287 |
+
opacity=0.7
|
| 1288 |
+
))
|
| 1289 |
+
|
| 1290 |
+
fig.update_layout(
|
| 1291 |
+
polar=dict(
|
| 1292 |
+
radialaxis=dict(
|
| 1293 |
+
visible=True,
|
| 1294 |
+
range=[0, 1] # Normalize ettiğimiz için 0-1 arası
|
| 1295 |
+
)),
|
| 1296 |
+
showlegend=True,
|
| 1297 |
+
margin=dict(l=40, r=40, t=20, b=20),
|
| 1298 |
+
height=300 # Kompakt boyut
|
| 1299 |
+
)
|
| 1300 |
+
|
| 1301 |
+
return fig
|
| 1302 |
+
# =========================================================================
|
| 1303 |
+
# VI. RETROSENTEZ MOTORU (Yeni Eklenen Kısım)
|
| 1304 |
+
# =========================================================================
|
| 1305 |
+
|
| 1306 |
+
# =========================================================================
|
| 1307 |
+
# GÜNCELLENMİŞ RETROSENTEZ MOTORU (Imide Desteği Eklendi)
|
| 1308 |
+
# =========================================================================
|
| 1309 |
+
|
| 1310 |
+
# =========================================================================
|
| 1311 |
+
# GÜNCELLENMİŞ RETROSENTEZ MOTORU v2.0 (Akıllı Varsayılan Eklendi)
|
| 1312 |
+
# =========================================================================
|
| 1313 |
+
|
| 1314 |
+
# =========================================================================
|
| 1315 |
+
# GÜNCELLENMİŞ RETROSENTEZ MOTORU v3.0 (Poliüre & Poliüretan Eklendi)
|
| 1316 |
+
# =========================================================================
|
| 1317 |
+
|
| 1318 |
+
def decompose_polymer(smiles):
|
| 1319 |
+
"""
|
| 1320 |
+
Polimeri parçalar. v3.0: Üre ve Üretan bağlarını da tanır.
|
| 1321 |
+
"""
|
| 1322 |
+
clean_smi = smiles.replace('*', '[H]')
|
| 1323 |
+
mol = Chem.MolFromSmiles(clean_smi)
|
| 1324 |
+
if not mol: return None, "Geçersiz Molekül"
|
| 1325 |
+
|
| 1326 |
+
breakdown_results = []
|
| 1327 |
+
|
| 1328 |
+
# --- KURAL 1: İMİD (Poliimid) ---
|
| 1329 |
+
imide_pattern = Chem.MolFromSmarts("[CX3](=[OX1])[#7][CX3](=[OX1])")
|
| 1330 |
+
if mol.HasSubstructMatch(imide_pattern):
|
| 1331 |
+
return [{
|
| 1332 |
+
"type": "Poliimid Sentezi",
|
| 1333 |
+
"reaction": "Siklo-dehidrasyon",
|
| 1334 |
+
"monomers": ["Dianhidrit", "Diamin"],
|
| 1335 |
+
"mechanism": "Dianhidrit + Diamin -> Poliimid"
|
| 1336 |
+
}]
|
| 1337 |
+
|
| 1338 |
+
# --- KURAL 2: ÜRE (Polyurea) --- [YENİ]
|
| 1339 |
+
# R-NH-C(=O)-NH-R' -> R-N=C=O (İzosiyanat) + H2N-R' (Amin)
|
| 1340 |
+
urea_pattern = Chem.MolFromSmarts("[N;!R][C;!R](=[O])[N;!R]")
|
| 1341 |
+
if mol.HasSubstructMatch(urea_pattern):
|
| 1342 |
+
breakdown_results.append({
|
| 1343 |
+
"type": "Poliüre (Polyurea) Sentezi",
|
| 1344 |
+
"reaction": "Basamaklı Polimerizasyon (Hızlı)",
|
| 1345 |
+
"monomers": ["Diizosiyanat (Diisocyanate)", "Diamin (Diamine)"],
|
| 1346 |
+
"mechanism": "İzosiyanat + Amin -> Üre Bağı (Yan ürün yok)"
|
| 1347 |
+
})
|
| 1348 |
+
|
| 1349 |
+
# --- KURAL 3: ÜRETAN (Polyurethane) --- [YENİ]
|
| 1350 |
+
# R-NH-C(=O)-O-R' -> R-N=C=O (İzosiyanat) + HO-R' (Alkol/Polyol)
|
| 1351 |
+
urethane_pattern = Chem.MolFromSmarts("[N;!R][C;!R](=[O])[O;!R]")
|
| 1352 |
+
if mol.HasSubstructMatch(urethane_pattern):
|
| 1353 |
+
breakdown_results.append({
|
| 1354 |
+
"type": "Poliüretan (PU) Sentezi",
|
| 1355 |
+
"reaction": "Poliladisyon",
|
| 1356 |
+
"monomers": ["Diizosiyanat (Örn: TDI, MDI)", "Diol / Polyol"],
|
| 1357 |
+
"mechanism": "İzosiyanat + Alkol -> Üretan Bağı"
|
| 1358 |
+
})
|
| 1359 |
+
|
| 1360 |
+
# --- KURAL 4: ESTER (Polyester) ---
|
| 1361 |
+
ester_pattern = Chem.MolFromSmarts("[C;!R](=[O])[O;!R]")
|
| 1362 |
+
if mol.HasSubstructMatch(ester_pattern) and not breakdown_results: # Üretan değilse bak
|
| 1363 |
+
breakdown_results.append({
|
| 1364 |
+
"type": "Polyester Sentezi",
|
| 1365 |
+
"reaction": "Kademeli Polimerizasyon",
|
| 1366 |
+
"monomers": ["Dikarboksilik Asit", "Diol"],
|
| 1367 |
+
"mechanism": "Asit + Alkol -> Ester + Su"
|
| 1368 |
+
})
|
| 1369 |
+
|
| 1370 |
+
# --- KURAL 5: AMİD (Nylon) ---
|
| 1371 |
+
amide_pattern = Chem.MolFromSmarts("[C;!R](=[O])[N;!R]")
|
| 1372 |
+
if mol.HasSubstructMatch(amide_pattern) and not breakdown_results: # Üre değilse bak
|
| 1373 |
+
breakdown_results.append({
|
| 1374 |
+
"type": "Poliamid (Nylon) Sentezi",
|
| 1375 |
+
"reaction": "Polikondenzasyon",
|
| 1376 |
+
"monomers": ["Dikarboksilik Asit", "Diamin"],
|
| 1377 |
+
"mechanism": "Asit + Amin -> Amid + Su"
|
| 1378 |
+
})
|
| 1379 |
+
|
| 1380 |
+
# --- VARSAYILAN ---
|
| 1381 |
+
if not breakdown_results:
|
| 1382 |
+
# Akıllı kontrol: Azot/Oksijen var mı?
|
| 1383 |
+
has_hetero = any(atom.GetSymbol() in ['N', 'O', 'S'] for atom in mol.GetAtoms())
|
| 1384 |
+
if has_hetero and "C=C" not in smiles:
|
| 1385 |
+
breakdown_results.append({
|
| 1386 |
+
"type": "Kompleks Kondenzasyon Polimeri",
|
| 1387 |
+
"reaction": "Özel Sentez (AI Analizi Önerilir)",
|
| 1388 |
+
"monomers": ["Fonksiyonel Grup A", "Fonksiyonel Grup B"],
|
| 1389 |
+
"mechanism": "Uç grupların reaksiyonu"
|
| 1390 |
+
})
|
| 1391 |
+
else:
|
| 1392 |
+
breakdown_results.append({
|
| 1393 |
+
"type": "Vinil Polimerizasyonu (Katılma)",
|
| 1394 |
+
"reaction": "Radikalik",
|
| 1395 |
+
"monomers": [smiles.replace('*', '')],
|
| 1396 |
+
"mechanism": "Çift bağ açılması"
|
| 1397 |
+
})
|
| 1398 |
+
|
| 1399 |
+
return breakdown_results
|
| 1400 |
+
def draw_retrosynthesis_grid(monomer_smiles_list):
|
| 1401 |
+
"""Monomerlerin listesini alır ve yan yana çizer."""
|
| 1402 |
+
mols = [Chem.MolFromSmiles(s) for s in monomer_smiles_list]
|
| 1403 |
+
mols = [m for m in mols if m is not None] # Hatalıları temizle
|
| 1404 |
+
if not mols: return None
|
| 1405 |
+
|
| 1406 |
+
img = Draw.MolsToGridImage(
|
| 1407 |
+
mols,
|
| 1408 |
+
molsPerRow=min(len(mols), 3),
|
| 1409 |
+
subImgSize=(200, 200),
|
| 1410 |
+
legends=[f"Monomer {i+1}" for i in range(len(mols))]
|
| 1411 |
+
)
|
| 1412 |
+
return img
|
| 1413 |
+
|
| 1414 |
+
def get_ai_retrosynthesis_guide(api_key, polymer_smiles, monomer_info):
|
| 1415 |
+
"""Gemini'den detaylı sentez rotası ister."""
|
| 1416 |
+
if not api_key: return "⚠️ Detaylı sentez planı için API Key gerekli."
|
| 1417 |
+
|
| 1418 |
+
try:
|
| 1419 |
+
genai.configure(api_key=api_key)
|
| 1420 |
+
model = genai.GenerativeModel('gemini-2.5-flash')
|
| 1421 |
+
|
| 1422 |
+
prompt = f"""
|
| 1423 |
+
Sen uzman bir Sentetik Polimer Kimyagerisin.
|
| 1424 |
+
Aşağıdaki polimer için endüstriyel veya laboratuvar ölçekli bir RETROSENTEZ (geriye dönük sentez) planı hazırla.
|
| 1425 |
+
|
| 1426 |
+
Hedef Polimer (SMILES): {polymer_smiles}
|
| 1427 |
+
Algarlanan Olası Yöntem: {monomer_info}
|
| 1428 |
+
|
| 1429 |
+
Lütfen şu formatta yanıtla:
|
| 1430 |
+
1. **Önerilen Monomerler:** Bu yapıyı oluşturmak için hangi ticari kimyasallar (IUPAC isimleri) gerekir?
|
| 1431 |
+
2. **Sentez Yöntemi:** Hangi reaksiyon türü uygundur? (Örn: Radikalik, Kondenzasyon, ROMP?)
|
| 1432 |
+
3. **Kritik Koşullar:** Sıcaklık, basınç veya spesifik katalizör (AIBN, Ziegler-Natta, H2SO4 vb.) önerisi.
|
| 1433 |
+
4. **Zorluk Analizi:** Bu sentezin pratik zorlukları nelerdir?
|
| 1434 |
+
|
| 1435 |
+
Kısa, net ve bilimsel olsun.
|
| 1436 |
+
"""
|
| 1437 |
+
with st.spinner('AI Sentez Rotasını Hesaplıyor...'):
|
| 1438 |
+
response = model.generate_content(prompt)
|
| 1439 |
+
return response.text
|
| 1440 |
+
except Exception as e:
|
| 1441 |
+
return f"Hata: {str(e)}"
|
| 1442 |
+
from fpdf import FPDF
|
| 1443 |
+
import tempfile
|
| 1444 |
+
|
| 1445 |
+
class PDFReport(FPDF):
|
| 1446 |
+
def header(self):
|
| 1447 |
+
self.set_font('Arial', 'B', 15)
|
| 1448 |
+
self.cell(0, 10, 'PolimerX - Ar-Ge Proje Raporu', 0, 1, 'C')
|
| 1449 |
+
self.ln(5)
|
| 1450 |
+
|
| 1451 |
+
def footer(self):
|
| 1452 |
+
self.set_y(-15)
|
| 1453 |
+
self.set_font('Arial', 'I', 8)
|
| 1454 |
+
self.cell(0, 10, f'Sayfa {self.page_no()}', 0, 0, 'C')
|
| 1455 |
+
|
| 1456 |
+
def clean_text(text):
|
| 1457 |
+
"""FPDF için Türkçe karakterleri ASCII'ye çevirir (Hızlı çözüm)"""
|
| 1458 |
+
replacements = {
|
| 1459 |
+
'ğ': 'g', 'Ğ': 'G', 'ü': 'u', 'Ü': 'U', 'ş': 's', 'Ş': 'S',
|
| 1460 |
+
'ı': 'i', 'İ': 'I', 'ö': 'o', 'Ö': 'O', 'ç': 'c', 'Ç': 'C'
|
| 1461 |
+
}
|
| 1462 |
+
for search, replace in replacements.items():
|
| 1463 |
+
text = text.replace(search, replace)
|
| 1464 |
+
return text.encode('latin-1', 'replace').decode('latin-1')
|
| 1465 |
+
|
| 1466 |
+
def create_pdf_report(poly_data, targets, active_props, ai_analysis_text, retro_info):
|
| 1467 |
+
pdf = PDFReport()
|
| 1468 |
+
pdf.add_page()
|
| 1469 |
+
pdf.set_font("Arial", size=12)
|
| 1470 |
+
|
| 1471 |
+
# 1. Başlık Bilgileri
|
| 1472 |
+
pdf.set_font("Arial", 'B', 14)
|
| 1473 |
+
pdf.cell(0, 10, clean_text("1. Polimer Özellik Tablosu"), 0, 1)
|
| 1474 |
+
pdf.set_font("Arial", size=10)
|
| 1475 |
+
|
| 1476 |
+
# Tablo Başlığı
|
| 1477 |
+
pdf.set_fill_color(200, 220, 255)
|
| 1478 |
+
pdf.cell(60, 8, "Ozellik", 1, 0, 'C', 1)
|
| 1479 |
+
pdf.cell(60, 8, "Hedef", 1, 0, 'C', 1)
|
| 1480 |
+
pdf.cell(60, 8, "Tahmin Degeri", 1, 1, 'C', 1)
|
| 1481 |
+
|
| 1482 |
+
# --- GÜNCELLEME: Tüm tahminleri döngüye al ---
|
| 1483 |
+
all_preds = poly_data['preds']
|
| 1484 |
+
|
| 1485 |
+
for prop, val in all_preds.items():
|
| 1486 |
+
# Hedeflenen değer var mı kontrol et
|
| 1487 |
+
if prop in active_props:
|
| 1488 |
+
target_val = str(targets.get(prop, '-'))
|
| 1489 |
+
# Hedeflenenleri kalın (bold) veya işaretli gösterebiliriz ama
|
| 1490 |
+
# şimdilik standart formatta yazıyoruz.
|
| 1491 |
+
else:
|
| 1492 |
+
target_val = "-" # Hedef belirtilmedi
|
| 1493 |
+
|
| 1494 |
+
pred_val = f"{val:.2f}"
|
| 1495 |
+
|
| 1496 |
+
# Satırı yaz
|
| 1497 |
+
pdf.cell(60, 8, clean_text(prop), 1)
|
| 1498 |
+
pdf.cell(60, 8, target_val, 1)
|
| 1499 |
+
pdf.cell(60, 8, pred_val, 1, 1)
|
| 1500 |
+
|
| 1501 |
+
pdf.ln(10)
|
| 1502 |
+
|
| 1503 |
+
# 2. Molekül Görseli
|
| 1504 |
+
pdf.set_font("Arial", 'B', 14)
|
| 1505 |
+
pdf.cell(0, 10, clean_text("2. Molekuler Yapi"), 0, 1)
|
| 1506 |
+
|
| 1507 |
+
# SMILES
|
| 1508 |
+
pdf.set_font("Courier", size=8)
|
| 1509 |
+
pdf.multi_cell(0, 5, poly_data['smiles'])
|
| 1510 |
+
pdf.ln(5)
|
| 1511 |
+
|
| 1512 |
+
# Görseli ekle
|
| 1513 |
+
mol_img = draw_2d_molecule(poly_data['smiles'])
|
| 1514 |
+
if mol_img:
|
| 1515 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp_file:
|
| 1516 |
+
mol_img.save(tmp_file.name)
|
| 1517 |
+
pdf.image(tmp_file.name, x=60, w=90)
|
| 1518 |
+
|
| 1519 |
+
pdf.ln(10)
|
| 1520 |
+
|
| 1521 |
+
# 3. Retrosentez Bilgisi
|
| 1522 |
+
pdf.set_font("Arial", 'B', 14)
|
| 1523 |
+
pdf.cell(0, 10, clean_text("3. Uretim Plani (Retrosentez)"), 0, 1)
|
| 1524 |
+
pdf.set_font("Arial", size=10)
|
| 1525 |
+
|
| 1526 |
+
if not retro_info or len(retro_info) < 5:
|
| 1527 |
+
pdf.multi_cell(0, 6, clean_text("Retrosentez analizi yapilmadi veya veri yok."))
|
| 1528 |
+
else:
|
| 1529 |
+
clean_retro = clean_text(str(retro_info))
|
| 1530 |
+
pdf.multi_cell(0, 6, clean_retro)
|
| 1531 |
+
|
| 1532 |
+
pdf.ln(10)
|
| 1533 |
+
|
| 1534 |
+
# 4. AI Yorumu
|
| 1535 |
+
pdf.set_font("Arial", 'B', 14)
|
| 1536 |
+
pdf.cell(0, 10, clean_text("4. Yapay Zeka Uzman Görüşü"), 0, 1)
|
| 1537 |
+
pdf.set_font("Arial", size=10)
|
| 1538 |
+
|
| 1539 |
+
if not ai_analysis_text or len(ai_analysis_text) < 5:
|
| 1540 |
+
pdf.multi_cell(0, 6, clean_text("AI analizi talep edilmedi."))
|
| 1541 |
+
else:
|
| 1542 |
+
clean_ai = clean_text(ai_analysis_text).replace('**', '').replace('#', '')
|
| 1543 |
+
pdf.multi_cell(0, 6, clean_ai)
|
| 1544 |
+
|
| 1545 |
+
return pdf.output(dest='S').encode('latin-1')
|
| 1546 |
+
from rdkit import DataStructs
|
| 1547 |
+
|
| 1548 |
+
@st.cache_data
|
| 1549 |
+
def get_reference_fingerprints(smiles_list):
|
| 1550 |
+
"""
|
| 1551 |
+
Referans veri setindeki tüm SMILES'ların parmak izlerini önceden hesaplar ve önbelleğe alır.
|
| 1552 |
+
Bu işlem sadece bir kez yapılır, böylece uygulama hızlanır.
|
| 1553 |
+
"""
|
| 1554 |
+
fps = []
|
| 1555 |
+
names = [] # Varsa isimleri, yoksa SMILES'ın kendisi
|
| 1556 |
+
|
| 1557 |
+
for i, smi in enumerate(smiles_list):
|
| 1558 |
+
try:
|
| 1559 |
+
mol = Chem.MolFromSmiles(str(smi).replace('*', '[H]'))
|
| 1560 |
+
if mol:
|
| 1561 |
+
fp = AllChem.GetMorganFingerprintAsBitVect(mol, 3, 2048)
|
| 1562 |
+
fps.append(fp)
|
| 1563 |
+
names.append(f"Veri Seti Kaydı #{i+1}") # Veya smi
|
| 1564 |
+
except:
|
| 1565 |
+
continue
|
| 1566 |
+
return fps, names
|
| 1567 |
+
|
| 1568 |
+
def calculate_novelty_optimized(generated_smiles, ref_smiles_list):
|
| 1569 |
+
"""
|
| 1570 |
+
Toplu Tanimoto benzerliği hesaplar (Çok hızlıdır).
|
| 1571 |
+
"""
|
| 1572 |
+
# 1. Üretilen molekülün parmak izi
|
| 1573 |
+
gen_mol = Chem.MolFromSmiles(generated_smiles.replace('*', '[H]'))
|
| 1574 |
+
if not gen_mol: return 0.0, "Hesaplanamadı"
|
| 1575 |
+
gen_fp = AllChem.GetMorganFingerprintAsBitVect(gen_mol, 3, 2048)
|
| 1576 |
+
|
| 1577 |
+
# 2. Referans parmak izlerini önbellekten çek
|
| 1578 |
+
ref_fps, ref_names = get_reference_fingerprints(ref_smiles_list)
|
| 1579 |
+
|
| 1580 |
+
if not ref_fps: return 0.0, "Veri Seti Boş"
|
| 1581 |
+
|
| 1582 |
+
# 3. RDKit'in Toplu (Bulk) Karşılaştırma Fonksiyonu
|
| 1583 |
+
# Bu döngüden 100 kat daha hızlıdır.
|
| 1584 |
+
sims = DataStructs.BulkTanimotoSimilarity(gen_fp, ref_fps)
|
| 1585 |
+
|
| 1586 |
+
# 4. En yüksek benzerliği bul
|
| 1587 |
+
max_sim = max(sims)
|
| 1588 |
+
max_idx = sims.index(max_sim)
|
| 1589 |
+
most_similar_name = ref_names[max_idx]
|
| 1590 |
+
|
| 1591 |
+
# Eşleşen SMILES'ı döndürmek daha bilgilendirici olabilir
|
| 1592 |
+
most_similar_smiles = ref_smiles_list[max_idx] if max_idx < len(ref_smiles_list) else "Bilinmiyor"
|
| 1593 |
+
|
| 1594 |
+
return max_sim, most_similar_smiles
|
| 1595 |
+
# =========================================================================
|
| 1596 |
+
# IV. STREAMLIT ANA KISIM
|
| 1597 |
+
# =========================================================================
|
| 1598 |
+
|
| 1599 |
+
# st.title("...") yerine:
|
| 1600 |
+
|
| 1601 |
+
st.markdown('<h1 class="main-title">🧬 PolimerX <br><span style="font-size:1.5rem; color:#666; font-weight:400;">Yapay Zeka Destekli Materyal Keşfi</span></h1>', unsafe_allow_html=True)
|
| 1602 |
+
|
| 1603 |
+
models = load_critic_models()
|
| 1604 |
+
ALL_PROPS = list(models.keys()) # Yüklenen modellerin anahtarları: ['Tg', 'Td', 'EPS']
|
| 1605 |
+
|
| 1606 |
+
# --- Yardımcı: Senkron Slider + Number input ---
|
| 1607 |
+
def add_synced_input(prop_key, label, min_val, max_val, default, step, is_int=False):
|
| 1608 |
+
"""Sidebar üzerinde bir slider ve number_input oluşturur; ikisini session_state üzerinden senkronlar.
|
| 1609 |
+
Döndürülen değer her zaman current value (float/int) olur.
|
| 1610 |
+
"""
|
| 1611 |
+
s_key = f"{prop_key}_val"
|
| 1612 |
+
slider_key = f"{prop_key}_slider"
|
| 1613 |
+
num_key = f"{prop_key}_num"
|
| 1614 |
+
|
| 1615 |
+
# Başlangıç değeri session_state'e konur
|
| 1616 |
+
if s_key not in st.session_state:
|
| 1617 |
+
st.session_state[s_key] = default
|
| 1618 |
+
if slider_key not in st.session_state:
|
| 1619 |
+
st.session_state[slider_key] = st.session_state[s_key]
|
| 1620 |
+
if num_key not in st.session_state:
|
| 1621 |
+
st.session_state[num_key] = st.session_state[s_key]
|
| 1622 |
+
|
| 1623 |
+
def _on_slider_change():
|
| 1624 |
+
# slider değiştiğinde number_input değerini güncelle
|
| 1625 |
+
try:
|
| 1626 |
+
st.session_state[num_key] = st.session_state[slider_key]
|
| 1627 |
+
st.session_state[s_key] = st.session_state[slider_key]
|
| 1628 |
+
except Exception:
|
| 1629 |
+
pass
|
| 1630 |
+
|
| 1631 |
+
def _on_num_change():
|
| 1632 |
+
# number_input değiştiğinde slider'ı güncelle
|
| 1633 |
+
try:
|
| 1634 |
+
st.session_state[slider_key] = st.session_state[num_key]
|
| 1635 |
+
st.session_state[s_key] = st.session_state[num_key]
|
| 1636 |
+
except Exception:
|
| 1637 |
+
pass
|
| 1638 |
+
|
| 1639 |
+
# Slider (min/max tipi int/float ile uyumlu olmalı)
|
| 1640 |
+
if is_int:
|
| 1641 |
+
st.sidebar.slider(label + " (slider)", min_value=int(min_val), max_value=int(max_val), step=int(step), key=slider_key, on_change=_on_slider_change)
|
| 1642 |
+
st.sidebar.number_input(label + " (value)", min_value=int(min_val), max_value=int(max_val), step=int(step), key=num_key, on_change=_on_num_change)
|
| 1643 |
+
else:
|
| 1644 |
+
st.sidebar.slider(label + " (slider)", min_value=float(min_val), max_value=float(max_val), step=float(step), key=slider_key, on_change=_on_slider_change)
|
| 1645 |
+
st.sidebar.number_input(label + " (value)", min_value=float(min_val), max_value=float(max_val), step=float(step), format="%.4f", key=num_key, on_change=_on_num_change)
|
| 1646 |
+
|
| 1647 |
+
return st.session_state[s_key]
|
| 1648 |
+
|
| 1649 |
+
if models:
|
| 1650 |
+
st.sidebar.header("⚙️ Hedef Seçimi")
|
| 1651 |
+
|
| 1652 |
+
# 1. Optimizasyona Dahil Edilecek Özelliklerin Seçimi
|
| 1653 |
+
active_props = []
|
| 1654 |
+
|
| 1655 |
+
st.sidebar.markdown("### Dahil Edilecek Özellikler")
|
| 1656 |
+
# Her özellik için onay kutusu oluştur
|
| 1657 |
+
if st.sidebar.checkbox("Tg (Camsı Geçiş Sıcaklığı)", value=True):
|
| 1658 |
+
active_props.append('Tg')
|
| 1659 |
+
if st.sidebar.checkbox("Td (Bozunma Sıcaklığı)"):
|
| 1660 |
+
active_props.append('Td')
|
| 1661 |
+
if st.sidebar.checkbox("EPS (Dielektrik Sabiti)"):
|
| 1662 |
+
active_props.append('EPS')
|
| 1663 |
+
if st.sidebar.checkbox("Tm (Erime Sıcaklığı)"):
|
| 1664 |
+
active_props.append('Tm')
|
| 1665 |
+
if st.sidebar.checkbox("Bandgap Bulk (Elektriksel Band Aralığı - Bulk)"):
|
| 1666 |
+
active_props.append('BandgapBulk')
|
| 1667 |
+
if st.sidebar.checkbox("Bandgap Chain (Elektriksel Band Aralığı - Zincir)"):
|
| 1668 |
+
active_props.append('BandgapChain')
|
| 1669 |
+
if st.sidebar.checkbox("Bandgap Crystal (Elektriksel Band Aralığı - Kristal)"):
|
| 1670 |
+
active_props.append('BandgapCrystal')
|
| 1671 |
+
if st.sidebar.checkbox("Gas Permeability (Gaz Geçirgenliği)"):
|
| 1672 |
+
active_props.append('GasPerma')
|
| 1673 |
+
if st.sidebar.checkbox("Refractive Index (Kırılma İndeksi)"):
|
| 1674 |
+
active_props.append('Refractive')
|
| 1675 |
+
|
| 1676 |
+
if st.sidebar.checkbox("LOI (Yanıcılık İndeksi)"):
|
| 1677 |
+
active_props.append('LOI')
|
| 1678 |
+
|
| 1679 |
+
if st.sidebar.checkbox("Çözünürlük (Hildebrand)"):
|
| 1680 |
+
active_props.append('Solubility')
|
| 1681 |
+
|
| 1682 |
+
if st.sidebar.checkbox("Isıl İletkenlik (Thermal Cond.)"):
|
| 1683 |
+
active_props.append('ThermalCond')
|
| 1684 |
+
|
| 1685 |
+
if st.sidebar.checkbox("Isıl Genleşme (CTE)"):
|
| 1686 |
+
active_props.append('CTE')
|
| 1687 |
+
# En az bir hedef seçilmemişse uyarı ver
|
| 1688 |
+
|
| 1689 |
+
if not active_props:
|
| 1690 |
+
st.sidebar.warning("Lütfen optimize edilecek en az bir hedef seçin.")
|
| 1691 |
+
st.stop()
|
| 1692 |
+
|
| 1693 |
+
# 2. Hedef Değerler (Sadece seçilenler için giriş alanı göster)
|
| 1694 |
+
st.sidebar.markdown("### Hedef Değerler")
|
| 1695 |
+
targets = {}
|
| 1696 |
+
|
| 1697 |
+
# Önerilen aralıklar (kullanıcının onayladığı değerler)
|
| 1698 |
+
# Sıcaklıklar (°C)
|
| 1699 |
+
ranges = {
|
| 1700 |
+
'Tg': {'min': -150.0, 'max': 300.0, 'default': 200.0, 'step': 1.0, 'is_int': False},
|
| 1701 |
+
'Td': {'min': 150.0, 'max': 600.0, 'default': 350.0, 'step': 1.0, 'is_int': False},
|
| 1702 |
+
'Tm': {'min': 50.0, 'max': 450.0, 'default': 250.0, 'step': 1.0, 'is_int': False},
|
| 1703 |
+
# Diğer özellikler
|
| 1704 |
+
'EPS': {'min': 1.5, 'max': 12.0, 'default': 2.5, 'step': 0.1, 'is_int': False},
|
| 1705 |
+
'BandgapBulk': {'min': 0.5, 'max': 6.0, 'default': 2.5, 'step': 0.01, 'is_int': False},
|
| 1706 |
+
'BandgapChain': {'min': 0.5, 'max': 6.0, 'default': 2.5, 'step': 0.01, 'is_int': False},
|
| 1707 |
+
'BandgapCrystal': {'min': 0.5, 'max': 7.0, 'default': 2.5, 'step': 0.01, 'is_int': False},
|
| 1708 |
+
'GasPerma': {'min': 0.0, 'max': 1000.0, 'default': 2.5, 'step': 0.1, 'is_int': False},
|
| 1709 |
+
'Refractive': {'min': 1.2, 'max': 2.0, 'default': 1.5, 'step': 0.01, 'is_int': False},
|
| 1710 |
+
|
| 1711 |
+
'LOI': {'min': 15.0, 'max': 100.0, 'default': 28.0, 'step': 0.5, 'is_int': False},
|
| 1712 |
+
|
| 1713 |
+
# Çözünürlük (Hildebrand): 7-10 arası apolar çözücüler, 12+ polar
|
| 1714 |
+
'Solubility': {'min': 5.0, 'max': 20.0, 'default': 9.5, 'step': 0.1, 'is_int': False},
|
| 1715 |
+
|
| 1716 |
+
# Isıl İletkenlik: Polimerler genelde 0.1-0.5 arasıdır (yalıtkan)
|
| 1717 |
+
'ThermalCond': {'min': 0.0, 'max': 1.0, 'default': 0.2, 'step': 0.01, 'is_int': False},
|
| 1718 |
+
|
| 1719 |
+
# CTE (Genleşme): Düşük olması (boyutsal kararlılık) istenir.
|
| 1720 |
+
'CTE': {'min': 0.0, 'max': 300.0, 'default': 60.0, 'step': 5.0, 'is_int': False}
|
| 1721 |
+
}
|
| 1722 |
+
|
| 1723 |
+
# Her seçili özellik için senkron slider + number_input ekle
|
| 1724 |
+
for prop in active_props:
|
| 1725 |
+
if prop in ranges:
|
| 1726 |
+
r = ranges[prop]
|
| 1727 |
+
label = prop
|
| 1728 |
+
# Kullanıcıya daha dostça etiket gösterimi
|
| 1729 |
+
if prop == 'Tg': label = 'Hedef Tg (°C)'
|
| 1730 |
+
elif prop == 'Td': label = 'Hedef Td (°C)'
|
| 1731 |
+
elif prop == 'Tm': label = 'Hedef Tm (°C)'
|
| 1732 |
+
elif prop == 'EPS': label = 'Hedef EPS'
|
| 1733 |
+
elif prop == 'BandgapBulk': label = 'Hedef BandgapBulk (eV)'
|
| 1734 |
+
elif prop == 'BandgapChain': label = 'Hedef BandgapChain (eV)'
|
| 1735 |
+
elif prop == 'BandgapCrystal': label = 'Hedef BandgapCrystal (eV)'
|
| 1736 |
+
elif prop == 'GasPerma': label = 'Hedef GasPerma'
|
| 1737 |
+
elif prop == 'Refractive': label = 'Hedef Refractive Index'
|
| 1738 |
+
|
| 1739 |
+
val = add_synced_input(prop, label, r['min'], r['max'], r['default'], r['step'], is_int=r['is_int'])
|
| 1740 |
+
targets[prop] = val
|
| 1741 |
+
else:
|
| 1742 |
+
# Eğer ranges sözlüğünde yoksa varsayılan number_input (güncelleme kolaylığı için)
|
| 1743 |
+
targets[prop] = st.sidebar.number_input(f"Hedef {prop}:", value=0.0)
|
| 1744 |
+
|
| 1745 |
+
# 3. GA Parametreleri
|
| 1746 |
+
generations = st.sidebar.slider("Evrim Nesli Sayısı", 10, 300, 10)
|
| 1747 |
+
|
| 1748 |
+
# Başlangıç popülasyonu (Gerçek verinizi buraya koyun)
|
| 1749 |
+
initial_selfies, reference_smiles = get_initial_population()
|
| 1750 |
+
# Sidebar'ın en altına ekleyebilirsiniz
|
| 1751 |
+
st.sidebar.divider()
|
| 1752 |
+
st.sidebar.markdown("### 🤖 AI Asistan Ayarları")
|
| 1753 |
+
api_key = st.sidebar.text_input("Google Gemini API Key", type="password", help="AI yorumu almak için https://aistudio.google.com/app/apikey adresinden ücretsiz anahtar alabilirsiniz.")
|
| 1754 |
+
# --- BUTON VE HESAPLAMA KISMI ---
|
| 1755 |
+
if st.sidebar.button("🚀 Hedefi Ara", type="primary"):
|
| 1756 |
+
|
| 1757 |
+
if not initial_selfies:
|
| 1758 |
+
st.error("Başlangıç popülasyonu boş veya geçersiz.")
|
| 1759 |
+
st.stop()
|
| 1760 |
+
|
| 1761 |
+
with st.spinner(f'Genetik Algoritma Çalışıyor... Hedefler: {", ".join(active_props)}'):
|
| 1762 |
+
# Hesaplama yapılıyor
|
| 1763 |
+
best_poly_data, history = run_single_objective_flow(models, generations, targets, active_props, initial_selfies, ranges)
|
| 1764 |
+
|
| 1765 |
+
# SONUÇLARI HAFIZAYA (SESSION STATE) KAYDET
|
| 1766 |
+
if best_poly_data:
|
| 1767 |
+
st.session_state['ga_results'] = best_poly_data
|
| 1768 |
+
st.session_state['ga_history'] = history
|
| 1769 |
+
st.session_state['ga_targets'] = targets # O anki hedefleri de sakla
|
| 1770 |
+
st.session_state['ga_active_props'] = active_props # O anki aktif özellikleri de sakla
|
| 1771 |
+
|
| 1772 |
+
# --- SONUÇLARI GÖSTERME KISMI (BUTON BLOĞUNUN DIŞINDA) ---
|
| 1773 |
+
|
| 1774 |
+
# Hafızada sonuç varsa ekrana bas (Sayfa yenilense de burası çalışır)
|
| 1775 |
+
if 'ga_results' in st.session_state:
|
| 1776 |
+
|
| 1777 |
+
# Verileri hafızadan geri çağır
|
| 1778 |
+
best_poly_data = st.session_state['ga_results']
|
| 1779 |
+
history = st.session_state['ga_history']
|
| 1780 |
+
saved_targets = st.session_state['ga_targets']
|
| 1781 |
+
saved_active_props = st.session_state['ga_active_props']
|
| 1782 |
+
|
| 1783 |
+
preds = best_poly_data['preds']
|
| 1784 |
+
|
| 1785 |
+
st.success("✅ Optimizasyon Başarıyla Tamamlandı! (Sonuçlar Hafızada)")
|
| 1786 |
+
|
| 1787 |
+
# 4 SEKME YAPISI
|
| 1788 |
+
tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs(["📊 Genel Bakış", "🧬 Yapısal Analiz", "📈 Evrim Geçmişi", "💾 Raporlama", "🤖 AI Analizi", "🧪 Retrosentez"])
|
| 1789 |
+
# --- TAB 1: ÖZET ---
|
| 1790 |
+
with tab1:
|
| 1791 |
+
col_main, col_score, col_green = st.columns([2, 1, 1])
|
| 1792 |
+
|
| 1793 |
+
with col_main:
|
| 1794 |
+
st.markdown(f"### 🏆 Toplam Hata: **{best_poly_data['total_error']:.4f}**")
|
| 1795 |
+
|
| 1796 |
+
with col_score:
|
| 1797 |
+
sa = get_sa_score_local(best_poly_data['smiles'])
|
| 1798 |
+
st.metric("Sentez Zorluğu (SA)", f"{sa:.2f}", help="1 (Kolay) - 10 (Zor)")
|
| 1799 |
+
|
| 1800 |
+
with col_green:
|
| 1801 |
+
# Yeni Yeşil Kimya Skorunu Hesapla
|
| 1802 |
+
g_score, g_note, g_color = calculate_green_score(best_poly_data['smiles'])
|
| 1803 |
+
|
| 1804 |
+
# Özel renkli metrik gösterimi (HTML ile)
|
| 1805 |
+
st.markdown(f"""
|
| 1806 |
+
<div style="background-color:{g_color}20; border: 1px solid {g_color}; border-radius: 5px; padding: 5px; text-align: center;">
|
| 1807 |
+
<strong style="color:{g_color}; font-size: 0.8rem;">🌱 Yeşil Skor</strong><br>
|
| 1808 |
+
<span style="font-size: 1.5rem; font-weight: bold; color:{g_color};">{g_score:.1f}/10</span>
|
| 1809 |
+
</div>
|
| 1810 |
+
""", unsafe_allow_html=True)
|
| 1811 |
+
|
| 1812 |
+
# Notları altına küçük yazıyla ekle
|
| 1813 |
+
if g_note:
|
| 1814 |
+
st.caption(f"**Çevresel Analiz:** {g_note}")
|
| 1815 |
+
|
| 1816 |
+
st.divider()
|
| 1817 |
+
if 'Solubility' in preds:
|
| 1818 |
+
sol_val = preds['Solubility']
|
| 1819 |
+
solvents, partials = get_soluble_solvents(sol_val)
|
| 1820 |
+
|
| 1821 |
+
st.markdown("### 🧪 Tahmini Çözünürlük Analizi")
|
| 1822 |
+
c1, c2 = st.columns(2)
|
| 1823 |
+
|
| 1824 |
+
with c1:
|
| 1825 |
+
st.info(f"**Çözünmesi Beklenenler:**")
|
| 1826 |
+
if solvents:
|
| 1827 |
+
# Yeşil etiketlerle göster
|
| 1828 |
+
for s in solvents:
|
| 1829 |
+
st.markdown(f"- ✅ {s}")
|
| 1830 |
+
else:
|
| 1831 |
+
st.warning("Bu polimer çok dirençli görünüyor (veya çok özel bir çözücü gerektiriyor).")
|
| 1832 |
+
|
| 1833 |
+
with c2:
|
| 1834 |
+
st.warning(f"**Şişme / Zor Çözünme Beklenenler:**")
|
| 1835 |
+
if partials:
|
| 1836 |
+
for s in partials:
|
| 1837 |
+
st.markdown(f"- ⚠️ {s}")
|
| 1838 |
+
else:
|
| 1839 |
+
st.write("-")
|
| 1840 |
+
|
| 1841 |
+
st.caption(f"*Analiz, 'Benzer Benzeri Çözer' ilkesine göre Polimer (δ={sol_val:.1f}) ve Çözücü arasındaki Hildebrand farkına dayanır.*")
|
| 1842 |
+
cols = st.columns(3)
|
| 1843 |
+
for idx, prop in enumerate(ALL_PROPS):
|
| 1844 |
+
with cols[idx % 3]:
|
| 1845 |
+
is_active = prop in saved_active_props
|
| 1846 |
+
target_val = saved_targets.get(prop, '-')
|
| 1847 |
+
target_text = f"Hedef: {target_val}" if is_active else "Takip Dışı"
|
| 1848 |
+
border_color = "#2ecc71" if is_active else "#95a5a6"
|
| 1849 |
+
pred_value = preds[prop]
|
| 1850 |
+
|
| 1851 |
+
st.markdown(f"""
|
| 1852 |
+
<div class="metric-card" style="border-left: 5px solid {border_color};">
|
| 1853 |
+
<small>{prop}</small><br>
|
| 1854 |
+
<h3 style="margin:0; padding:0;">{pred_value:.2f}</h3>
|
| 1855 |
+
<small style="opacity:0.7">{target_text}</small>
|
| 1856 |
+
</div>
|
| 1857 |
+
""", unsafe_allow_html=True)
|
| 1858 |
+
st.divider()
|
| 1859 |
+
st.subheader("🎯 Hedef Uyumluluk Analizi")
|
| 1860 |
+
if len(saved_active_props) >= 3:
|
| 1861 |
+
fig = create_radar_chart(preds, saved_targets, saved_active_props, ranges)
|
| 1862 |
+
st.plotly_chart(fig, use_container_width=True)
|
| 1863 |
+
else:
|
| 1864 |
+
st.info("Radar grafiği için en az 3 özellik (Örn: Tg, LOI, CTE) seçmelisiniz.")
|
| 1865 |
+
# Az özellik varsa bar chart gösterelim
|
| 1866 |
+
st.progress(100) # Görsel dolgu
|
| 1867 |
+
# --- TAB 2: GÖRSELLİK ---
|
| 1868 |
+
with tab2:
|
| 1869 |
+
col_2d, col_3d = st.columns(2)
|
| 1870 |
+
with col_2d:
|
| 1871 |
+
st.subheader("2D Yapı (Teknik Çizim)")
|
| 1872 |
+
img = draw_2d_molecule(best_poly_data['smiles'])
|
| 1873 |
+
if img:
|
| 1874 |
+
st.image(img, width=400)
|
| 1875 |
+
st.caption("SMILES Kodu:")
|
| 1876 |
+
st.code(best_poly_data['smiles'], language="text")
|
| 1877 |
+
|
| 1878 |
+
with col_3d:
|
| 1879 |
+
st.subheader("3D Konformasyon")
|
| 1880 |
+
view, reason = make_3d_view_with_reason(best_poly_data["smiles"])
|
| 1881 |
+
if view:
|
| 1882 |
+
showmol(view, height=400, width=400)
|
| 1883 |
+
else:
|
| 1884 |
+
st.warning(f"3D Model oluşturulamadı: {reason}")
|
| 1885 |
+
|
| 1886 |
+
is_avail, cid, name = check_pubchem_availability(best_poly_data['smiles'])
|
| 1887 |
+
if is_avail:
|
| 1888 |
+
st.info(f"💡 Bu molekül PubChem'de kayıtlı: **{name}** (CID: {cid})")
|
| 1889 |
+
st.divider()
|
| 1890 |
+
# --- YENİ: ÖZGÜNLÜK / NOVELTY ANALİZİ ---
|
| 1891 |
+
st.subheader("🔍 Özgünlük Analizi (Novelty Search)")
|
| 1892 |
+
|
| 1893 |
+
# reference_smiles değişkenini get_initial_population'dan almıştık
|
| 1894 |
+
similarity_score, similar_smi = calculate_novelty_optimized(best_poly_data['smiles'], reference_smiles)
|
| 1895 |
+
|
| 1896 |
+
c1, c2 = st.columns([1, 3])
|
| 1897 |
+
|
| 1898 |
+
with c1:
|
| 1899 |
+
# Benzerlik Skoru
|
| 1900 |
+
st.metric("Eğitim Setine Benzerlik", f"%{similarity_score*100:.1f}")
|
| 1901 |
+
|
| 1902 |
+
with c2:
|
| 1903 |
+
# Yorum
|
| 1904 |
+
if similarity_score > 0.99:
|
| 1905 |
+
st.error(f"⚠️ **Kopya:** Yapay zeka eğitim setindeki bir veriyi ezberlemiş.")
|
| 1906 |
+
st.code(f"Benzer Kayıt: {similar_smi}")
|
| 1907 |
+
elif similarity_score > 0.85:
|
| 1908 |
+
st.warning(f"ℹ️ **Türev:** Eğitim setindeki bir yapıya çok benziyor.")
|
| 1909 |
+
with st.expander("Benzer Yapıyı Gör"):
|
| 1910 |
+
st.code(similar_smi)
|
| 1911 |
+
else:
|
| 1912 |
+
st.success(f"🌟 **KEŞİF:** Bu yapı eğitim setinde YOK! Tamamen özgün bir tasarım.")
|
| 1913 |
+
st.caption(f"En yakın benzerlik sadece %{similarity_score*100:.1f} oranında.")
|
| 1914 |
+
|
| 1915 |
+
st.progress(similarity_score)
|
| 1916 |
+
st.caption("*Benzerlik, Tanimoto İndeksi (Morgan Fingerprints) kullanılarak hesaplanmıştır.*")
|
| 1917 |
+
|
| 1918 |
+
# --- TAB 3: GRAFİK ---
|
| 1919 |
+
# --- TAB 3: PERFORMANS ANALİZİ ---
|
| 1920 |
+
with tab3:
|
| 1921 |
+
st.subheader("📈 Genetik Algoritma Performans Raporu")
|
| 1922 |
+
|
| 1923 |
+
if 'best_fitness' in history and len(history['best_fitness']) > 0:
|
| 1924 |
+
# Matplotlib ile Profesyonel Çizim
|
| 1925 |
+
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
|
| 1926 |
+
|
| 1927 |
+
# X Ekseni
|
| 1928 |
+
gens = range(len(history['best_fitness']))
|
| 1929 |
+
|
| 1930 |
+
# Grafik 1: Yakınsama (Convergence)
|
| 1931 |
+
ax1.plot(gens, history['best_fitness'], label='En İyi Birey (Best)', color='green', linewidth=2)
|
| 1932 |
+
ax1.plot(gens, history['avg_fitness'], label='Popülasyon Ortalaması (Avg)', color='blue', linestyle='--', alpha=0.7)
|
| 1933 |
+
ax1.set_ylabel('Hata Skoru')
|
| 1934 |
+
ax1.set_title('Yakınsama Analizi (Convergence)', fontweight='bold')
|
| 1935 |
+
ax1.legend()
|
| 1936 |
+
ax1.grid(True, which='both', linestyle='--', alpha=0.5)
|
| 1937 |
+
|
| 1938 |
+
# Grafik 2: Çeşitlilik (Diversity)
|
| 1939 |
+
ax2.plot(gens, history['diversity'], label='Standart Sapma (Diversity)', color='red', linewidth=2)
|
| 1940 |
+
ax2.fill_between(gens, history['diversity'], color='red', alpha=0.1)
|
| 1941 |
+
ax2.set_ylabel('Çeşitlilik (Std Dev)')
|
| 1942 |
+
ax2.set_xlabel('Jenerasyon')
|
| 1943 |
+
ax2.set_title('Popülasyon Çeşitliliği (Diversity)', fontweight='bold')
|
| 1944 |
+
ax2.legend()
|
| 1945 |
+
ax2.grid(True, which='both', linestyle='--', alpha=0.5)
|
| 1946 |
+
|
| 1947 |
+
plt.tight_layout()
|
| 1948 |
+
st.pyplot(fig)
|
| 1949 |
+
|
| 1950 |
+
# Yorumlama Kılavuzu
|
| 1951 |
+
st.info("""
|
| 1952 |
+
**Bu Grafikler Nasıl Okunur?**
|
| 1953 |
+
* **Yakınsama (Üst):** Yeşil çizgi sürekli düşmeli ve bir noktada yataylaşmalıdır (Plateau). Mavi çizgi yeşile çok yaklaşırsa popülasyon "öğrenmiş" demektir.
|
| 1954 |
+
* **Çeşitlilik (Alt):** Kırmızı çizginin sıfıra çok hızlı düşmemesi gerekir. Sıfıra düşerse model "Erken Yakınsama (Premature Convergence)" tuzağına düşmüştür; yani arama uzayını yeterince taramadan bir sonuca saplanmıştır.
|
| 1955 |
+
""")
|
| 1956 |
+
else:
|
| 1957 |
+
st.warning("Henüz grafik çizilecek veri yok.")
|
| 1958 |
+
# --- TAB 3: BENCHMARK VE PERFORMANS ---
|
| 1959 |
+
with tab3:
|
| 1960 |
+
st.header("🏆 Performans Kıyaslama (Benchmark)")
|
| 1961 |
+
st.markdown("Modelin başarısını kanıtlamak için onu 'Rastgele Arama' ile yarıştırın.")
|
| 1962 |
+
|
| 1963 |
+
# Eğer GA sonuçları varsa
|
| 1964 |
+
if 'ga_history' in st.session_state and 'best_fitness' in st.session_state['ga_history']:
|
| 1965 |
+
history = st.session_state['ga_history']
|
| 1966 |
+
ga_best_curve = history['best_fitness']
|
| 1967 |
+
|
| 1968 |
+
# Benchmark Butonu
|
| 1969 |
+
if st.button("🏁 Rastgele Arama ile Kıyasla (Benchmark Başlat)"):
|
| 1970 |
+
with st.spinner("Rastgele Arama yapılıyor... Bu işlem GA kadar sürebilir."):
|
| 1971 |
+
# GA'nın toplam bütçesini hesapla (Jenerasyon x 100 birey)
|
| 1972 |
+
generations_run = len(ga_best_curve)
|
| 1973 |
+
pop_size = 100 # Kodunuzda sabit 100'dü
|
| 1974 |
+
total_evals = generations_run * pop_size
|
| 1975 |
+
|
| 1976 |
+
# Benchmark'ı çalıştır
|
| 1977 |
+
random_curve = run_random_benchmark(
|
| 1978 |
+
models, saved_targets, saved_active_props,
|
| 1979 |
+
initial_selfies, ranges,
|
| 1980 |
+
total_budget=total_evals,
|
| 1981 |
+
batch_size=pop_size
|
| 1982 |
+
)
|
| 1983 |
+
|
| 1984 |
+
# Sonucu Session State'e kaydet (Sayfa yenilenince gitmesin)
|
| 1985 |
+
st.session_state['random_curve'] = random_curve
|
| 1986 |
+
st.success("Benchmark Tamamlandı!")
|
| 1987 |
+
|
| 1988 |
+
# --- GRAFİK ÇİZİMİ ---
|
| 1989 |
+
fig, ax = plt.subplots(figsize=(10, 6))
|
| 1990 |
+
|
| 1991 |
+
# 1. GA Çizgisi (Yeşil)
|
| 1992 |
+
ax.plot(ga_best_curve, label='Genetik Algoritma (Sizin Modeliniz)', color='green', linewidth=2.5)
|
| 1993 |
+
|
| 1994 |
+
# 2. Random Search Çizgisi (Gri/Siyah) - Varsa çiz
|
| 1995 |
+
if 'random_curve' in st.session_state:
|
| 1996 |
+
# Uzunlukları eşitle (Bazen 1 eksik/fazla olabilir)
|
| 1997 |
+
min_len = min(len(ga_best_curve), len(st.session_state['random_curve']))
|
| 1998 |
+
r_curve = st.session_state['random_curve'][:min_len]
|
| 1999 |
+
g_curve = ga_best_curve[:min_len]
|
| 2000 |
+
|
| 2001 |
+
ax.plot(r_curve, label='Rastgele Arama (Random Search)', color='gray', linestyle='--', linewidth=2)
|
| 2002 |
+
|
| 2003 |
+
# Farkı hesapla (Son jenerasyon)
|
| 2004 |
+
diff = r_curve[-1] - g_curve[-1]
|
| 2005 |
+
st.caption(f"**Sonuç:** GA modeliniz, rastgele aramadan **{diff:.2f} puan** daha iyi performans gösterdi.")
|
| 2006 |
+
|
| 2007 |
+
ax.set_title("Zeka Testi: GA vs Şans", fontweight='bold')
|
| 2008 |
+
ax.set_xlabel("Jenerasyon (Her adımda 100 yeni deneme)")
|
| 2009 |
+
ax.set_ylabel("Hata Skoru (Düşük İyidir)")
|
| 2010 |
+
ax.legend()
|
| 2011 |
+
ax.grid(True, linestyle='--', alpha=0.5)
|
| 2012 |
+
|
| 2013 |
+
st.pyplot(fig)
|
| 2014 |
+
|
| 2015 |
+
st.info("""
|
| 2016 |
+
**Grafik Nasıl Yorumlanır?**
|
| 2017 |
+
* **Yeşil Çizgi:** Hızlıca aşağı iniyorsa, modeliniz 'öğreniyor' demektir.
|
| 2018 |
+
* **Gri Çizgi:** Genelde daha yukarıda ve düz kalır.
|
| 2019 |
+
* **Fark:** İki çizgi arasındaki boşluk, Yapay Zekanızın kattığı değerdir.
|
| 2020 |
+
""")
|
| 2021 |
+
|
| 2022 |
+
else:
|
| 2023 |
+
st.warning("Önce 'Hedefi Ara' butonuna basarak GA'yı çalıştırın, sonra kıyaslama yapabilirsiniz.")
|
| 2024 |
+
st.divider()
|
| 2025 |
+
st.header("🎲 Büyük Stres Testi (Mass Random Testing)")
|
| 2026 |
+
st.markdown("""
|
| 2027 |
+
Modelin **genelleştirme yeteneğini** ölçmek için rastgele hedeflerle çoklu deneme yapın.
|
| 2028 |
+
* Her denemede farklı özellikler ve farklı hedef değerler seçilir.
|
| 2029 |
+
* Modelin "kolay" ve "zor" hedeflere tepkisi ölçülür.
|
| 2030 |
+
""")
|
| 2031 |
+
|
| 2032 |
+
col_mass_input, col_mass_btn = st.columns([1, 2])
|
| 2033 |
+
with col_mass_input:
|
| 2034 |
+
mass_trials = st.number_input("Test Sayısı", min_value=10, max_value=500, value=100, step=10)
|
| 2035 |
+
|
| 2036 |
+
if col_mass_btn.button("🔥 100+ Rastgele Testi Başlat"):
|
| 2037 |
+
with st.spinner("Model zorlu bir sınava giriyor... Kahvenizi alın, bu biraz sürebilir."):
|
| 2038 |
+
df_results = run_mass_random_test(models, generations, initial_selfies, ranges, num_trials=mass_trials)
|
| 2039 |
+
|
| 2040 |
+
# --- SONUÇ ANALİZİ ---
|
| 2041 |
+
st.subheader("📊 Test Sonuçları")
|
| 2042 |
+
|
| 2043 |
+
# 1. Özet Metrikler
|
| 2044 |
+
avg_error = df_results["Final Hata Skoru"].mean()
|
| 2045 |
+
success_count = df_results[df_results["Final Hata Skoru"] < 5.0].shape[0]
|
| 2046 |
+
success_rate = (success_count / mass_trials) * 100
|
| 2047 |
+
|
| 2048 |
+
m1, m2, m3 = st.columns(3)
|
| 2049 |
+
m1.metric("Ortalama Hata", f"{avg_error:.2f}")
|
| 2050 |
+
m2.metric("Başarı Oranı (Hata < 5.0)", f"%{success_rate:.1f}")
|
| 2051 |
+
m3.metric("En Zorlu Senaryo Hatası", f"{df_results['Final Hata Skoru'].max():.2f}")
|
| 2052 |
+
|
| 2053 |
+
# 2. Histogram (Hata Dağılımı)
|
| 2054 |
+
fig_hist, ax_hist = plt.subplots(figsize=(10, 5))
|
| 2055 |
+
ax_hist.hist(df_results["Final Hata Skoru"], bins=20, color='#3498db', edgecolor='black', alpha=0.7)
|
| 2056 |
+
ax_hist.set_title("Hata Skorlarının Dağılımı (Histogram)")
|
| 2057 |
+
ax_hist.set_xlabel("Hata Skoru (Sola yığılma iyidir)")
|
| 2058 |
+
ax_hist.set_ylabel("Deneme Sayısı")
|
| 2059 |
+
ax_hist.axvline(avg_error, color='red', linestyle='dashed', linewidth=1, label=f'Ortalama: {avg_error:.2f}')
|
| 2060 |
+
ax_hist.legend()
|
| 2061 |
+
st.pyplot(fig_hist)
|
| 2062 |
+
|
| 2063 |
+
# 3. Scatter Plot (Zorluk vs Hata)
|
| 2064 |
+
# Hedef sayısı arttıkça hata artıyor mu?
|
| 2065 |
+
fig_sc, ax_sc = plt.subplots(figsize=(10, 5))
|
| 2066 |
+
ax_sc.scatter(df_results["Hedef Sayısı"], df_results["Final Hata Skoru"], alpha=0.6, c=df_results["Final Hata Skoru"], cmap='viridis')
|
| 2067 |
+
ax_sc.set_title("Hedef Sayısı vs. Başarı")
|
| 2068 |
+
ax_sc.set_xlabel("Aktif Hedef Sayısı (Zorluk)")
|
| 2069 |
+
ax_sc.set_ylabel("Hata Skoru")
|
| 2070 |
+
ax_sc.grid(True, alpha=0.3)
|
| 2071 |
+
st.pyplot(fig_sc)
|
| 2072 |
+
|
| 2073 |
+
# 4. Detaylı Tablo
|
| 2074 |
+
with st.expander("📄 Tüm Test Verilerini Gör"):
|
| 2075 |
+
st.dataframe(df_results)
|
| 2076 |
+
|
| 2077 |
+
# --- TAB 4: İNDİRME ---
|
| 2078 |
+
# --- TAB 4: RAPORLAMA ve İNDİRME ---
|
| 2079 |
+
with tab4:
|
| 2080 |
+
st.header("💾 Raporlama Merkezi")
|
| 2081 |
+
st.markdown("Proje verilerini CSV veya detaylı PDF raporu olarak dışa aktarabilirsiniz.")
|
| 2082 |
+
|
| 2083 |
+
c1, c2 = st.columns(2)
|
| 2084 |
+
|
| 2085 |
+
# --- CSV İNDİRME KISMI (Mevcut) ---
|
| 2086 |
+
# ... (Buradaki CSV kodlarınız aynen kalabilir) ...
|
| 2087 |
+
export_dict = {
|
| 2088 |
+
"SMILES": best_poly_data['smiles'],
|
| 2089 |
+
"Toplam Hata": best_poly_data['total_error'],
|
| 2090 |
+
"SA Score": get_sa_score_local(best_poly_data['smiles'])
|
| 2091 |
+
}
|
| 2092 |
+
export_dict.update(preds)
|
| 2093 |
+
df_best = pd.DataFrame([export_dict])
|
| 2094 |
+
csv_best = df_best.to_csv(index=False).encode('utf-8')
|
| 2095 |
+
|
| 2096 |
+
with c1:
|
| 2097 |
+
st.download_button(
|
| 2098 |
+
label="📊 Veri Setini İndir (.csv)",
|
| 2099 |
+
data=csv_best,
|
| 2100 |
+
file_name="polimer_data.csv",
|
| 2101 |
+
mime="text/csv"
|
| 2102 |
+
)
|
| 2103 |
+
|
| 2104 |
+
st.divider()
|
| 2105 |
+
|
| 2106 |
+
# --- PDF RAPOR OLUŞTURMA KISMI (Yeni Yeri) ---
|
| 2107 |
+
st.subheader("📄 Kapsamlı PDF Raporu")
|
| 2108 |
+
st.info("Bu rapor; tüm tahminleri, molekül yapısını, AI yorumlarını ve varsa sentez planını içerir.")
|
| 2109 |
+
|
| 2110 |
+
# Verileri Session State'ten Topla
|
| 2111 |
+
|
| 2112 |
+
# 1. AI Yorumu (Tab 5'ten)
|
| 2113 |
+
gen_ai_analysis = st.session_state.get('ai_analysis', "Genel AI analizi yapilmadi.")
|
| 2114 |
+
|
| 2115 |
+
# 2. Retrosentez Bilgisi (Tab 6'dan)
|
| 2116 |
+
# Eğer kullanıcı Tab 6'ya hiç gitmediyse, bu veriler eksik olabilir.
|
| 2117 |
+
manual_retro = st.session_state.get('retro_manual_text', "Otomatik ayristirma verisi yok (Retrosentez sekmesini ziyaret edin).")
|
| 2118 |
+
ai_retro = st.session_state.get('ai_retro_text', "AI sentez recetesi olusturulmadi.")
|
| 2119 |
+
|
| 2120 |
+
full_retro_info = manual_retro + "\n\n--- AI Sentez Notlari ---\n" + ai_retro
|
| 2121 |
+
|
| 2122 |
+
if st.button("🚀 PDF Raporu Oluştur", type="primary", use_container_width=True):
|
| 2123 |
+
with st.spinner("Rapor derleniyor..."):
|
| 2124 |
+
pdf_data = create_pdf_report(
|
| 2125 |
+
best_poly_data,
|
| 2126 |
+
saved_targets,
|
| 2127 |
+
saved_active_props,
|
| 2128 |
+
gen_ai_analysis,
|
| 2129 |
+
full_retro_info
|
| 2130 |
+
)
|
| 2131 |
+
|
| 2132 |
+
st.success("Rapor hazır!")
|
| 2133 |
+
st.download_button(
|
| 2134 |
+
label="📥 PDF Dosyasını İndir",
|
| 2135 |
+
data=pdf_data,
|
| 2136 |
+
file_name="PolimerX_Final_Raporu.pdf",
|
| 2137 |
+
mime="application/pdf",
|
| 2138 |
+
use_container_width=True
|
| 2139 |
+
)
|
| 2140 |
+
with tab5:
|
| 2141 |
+
st.subheader("🧠 Yapay Zeka Uzman Görüşü")
|
| 2142 |
+
|
| 2143 |
+
if not api_key:
|
| 2144 |
+
st.info("💡 Bu polimer hakkında detaylı kimyasal yorum almak için sol menüden **Google Gemini API Key** girmelisiniz.")
|
| 2145 |
+
st.markdown("[👉 Ücretsiz API Key Almak İçin Tıkla](https://aistudio.google.com/app/apikey)")
|
| 2146 |
+
else:
|
| 2147 |
+
# Butonla tetikleyelim ki her sayfa yenilemede kredi harcamasın
|
| 2148 |
+
if st.button("✨ Polimeri Analiz Et", type="primary"):
|
| 2149 |
+
analysis_result = get_ai_interpretation(
|
| 2150 |
+
api_key,
|
| 2151 |
+
best_poly_data['smiles'],
|
| 2152 |
+
best_poly_data['preds'],
|
| 2153 |
+
saved_targets,
|
| 2154 |
+
saved_active_props
|
| 2155 |
+
)
|
| 2156 |
+
st.markdown(analysis_result)
|
| 2157 |
+
|
| 2158 |
+
# Analizi de kaydetmek isterseniz session state'e atabilirsiniz
|
| 2159 |
+
st.session_state['ai_analysis'] = analysis_result
|
| 2160 |
+
|
| 2161 |
+
# Eğer daha önce analiz yapıldıysa hafızadan göster
|
| 2162 |
+
elif 'ai_analysis' in st.session_state:
|
| 2163 |
+
st.markdown(st.session_state['ai_analysis'])
|
| 2164 |
+
# --- TAB 6: RETROSENTEZ ve RAPORLAMA ---
|
| 2165 |
+
# --- TAB 6: RETROSENTEZ (Sadece Analiz) ---
|
| 2166 |
+
with tab6:
|
| 2167 |
+
st.header("🧪 Retrosentez Analizi")
|
| 2168 |
+
|
| 2169 |
+
target_smiles = best_poly_data['smiles']
|
| 2170 |
+
|
| 2171 |
+
# --- 1. OTOMATİK AYRIŞTIRMA ---
|
| 2172 |
+
st.subheader("1. Yapısal Ayrıştırma")
|
| 2173 |
+
retro_results = decompose_polymer(target_smiles)
|
| 2174 |
+
|
| 2175 |
+
monomer_info_text = "Otomatik analiz yapilmadi." # Varsayılan
|
| 2176 |
+
|
| 2177 |
+
if retro_results:
|
| 2178 |
+
best_route = retro_results[0]
|
| 2179 |
+
|
| 2180 |
+
# Metni oluştur
|
| 2181 |
+
monomer_info_text = f"Yontem: {best_route['type']}\nMekanizma: {best_route['mechanism']}\n"
|
| 2182 |
+
|
| 2183 |
+
st.info(f"**Algılanan Sentez Türü:** {best_route['type']}")
|
| 2184 |
+
st.write(f"**Mekanizma:** {best_route['mechanism']}")
|
| 2185 |
+
|
| 2186 |
+
st.markdown("**Olası Başlangıç Monomerleri:**")
|
| 2187 |
+
img_retro = draw_retrosynthesis_grid(best_route['monomers'])
|
| 2188 |
+
if img_retro: st.image(img_retro)
|
| 2189 |
+
|
| 2190 |
+
# Ticari Kontrol
|
| 2191 |
+
st.markdown("#### 🛒 Ticari Bulunabilirlik")
|
| 2192 |
+
found_monomers = []
|
| 2193 |
+
for i, m in enumerate(best_route['monomers']):
|
| 2194 |
+
col_code, col_check = st.columns([3, 1])
|
| 2195 |
+
with col_code:
|
| 2196 |
+
st.code(f"Monomer {i+1}: {m}")
|
| 2197 |
+
with col_check:
|
| 2198 |
+
if st.button(f"🔍 Kontrol #{i+1}", key=f"chk_{i}"):
|
| 2199 |
+
is_avail, cid, name = check_commercial_availability(m)
|
| 2200 |
+
if is_avail:
|
| 2201 |
+
st.success(f"Var: {name}")
|
| 2202 |
+
found_monomers.append(name)
|
| 2203 |
+
else:
|
| 2204 |
+
st.error("Ticari kayit yok")
|
| 2205 |
+
|
| 2206 |
+
if found_monomers:
|
| 2207 |
+
monomer_info_text += f"\nTicari Kaydi Olanlar: {', '.join(found_monomers)}"
|
| 2208 |
+
else:
|
| 2209 |
+
monomer_info_text += "\nTicari kayit kontrolu yapilmadi veya bulunamadi."
|
| 2210 |
+
|
| 2211 |
+
else:
|
| 2212 |
+
st.warning("Yapısal ayrıştırma başarısız.")
|
| 2213 |
+
monomer_info_text = "Yapısal ayrıştırma başarısız."
|
| 2214 |
+
|
| 2215 |
+
# --- VERİYİ KAYDET (Tab 4 için) ---
|
| 2216 |
+
st.session_state['retro_manual_text'] = monomer_info_text
|
| 2217 |
+
|
| 2218 |
+
st.divider()
|
| 2219 |
+
|
| 2220 |
+
# --- 2. AI SENTEZ PLANI ---
|
| 2221 |
+
st.subheader("2. AI Sentez Reçetesi")
|
| 2222 |
+
|
| 2223 |
+
if api_key and st.button("⚗️ Sentez Rotasını Oluştur (AI)", type="primary"):
|
| 2224 |
+
ai_retro_text = get_ai_retrosynthesis_guide(api_key, target_smiles, str(retro_results))
|
| 2225 |
+
st.markdown(ai_retro_text)
|
| 2226 |
+
st.session_state['ai_retro_text'] = ai_retro_text
|
| 2227 |
+
|
| 2228 |
+
elif 'ai_retro_text' in st.session_state:
|
| 2229 |
+
st.markdown(st.session_state['ai_retro_text'])
|
| 2230 |
+
# --- MEVCUT TAB 6 KODUNUN DEVAMI ---
|
| 2231 |
+
|
| 2232 |
+
st.divider()
|
| 2233 |
+
|
| 2234 |
+
# --- 2. YEREL MODEL TAHMİNİ (GEMINI YERİNE) ---
|
| 2235 |
+
st.subheader("2. T5-Model Tahmini (Machine Learning)")
|
| 2236 |
+
st.caption("Eğittiğimiz model, moleküler yapıyı analiz ederek monomerleri tahmin ediyor.")
|
| 2237 |
+
|
| 2238 |
+
if st.button("🧠 Monomerleri Tahmin Et", type="primary"):
|
| 2239 |
+
with st.spinner("Yapay zeka düşünüyor..."):
|
| 2240 |
+
# Tahmin Fonksiyonunu Çağır
|
| 2241 |
+
prediction = predict_monomers_local(best_poly_data['smiles'])
|
| 2242 |
+
|
| 2243 |
+
# Sonucu Göster
|
| 2244 |
+
st.success("Tahmin Başarılı!")
|
| 2245 |
+
|
| 2246 |
+
st.markdown(f"""
|
| 2247 |
+
<div style="background-color:#e8f5e9; padding:15px; border-radius:10px; border:1px solid #4CAF50;">
|
| 2248 |
+
<h4 style="color:#2e7d32; margin:0;">🧪 Önerilen Monomerler:</h4>
|
| 2249 |
+
<code style="font-size:1.1em; color:#1b5e20; background-color:#e8f5e9;">{prediction}</code>
|
| 2250 |
+
</div>
|
| 2251 |
+
""", unsafe_allow_html=True)
|
| 2252 |
+
print("Predicted monomers:", prediction)
|
| 2253 |
+
# Görselleştirme
|
| 2254 |
+
monomers_list = prediction.split(' . ') # Veri setinde " . " ile ayırmıştık
|
| 2255 |
+
img_retro = draw_retrosynthesis_grid(monomers_list)
|
| 2256 |
+
if img_retro:
|
| 2257 |
+
st.image(img_retro, caption="Modelin Önerdiği Yapı Taşları")
|
| 2258 |
+
|
| 2259 |
+
# Session State'e kaydet (PDF raporu için)
|
| 2260 |
+
st.session_state['retro_manual_text'] = f"AI Tahmini: {prediction}"
|
config.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"T5ForConditionalGeneration"
|
| 4 |
+
],
|
| 5 |
+
"classifier_dropout": 0.0,
|
| 6 |
+
"d_ff": 2048,
|
| 7 |
+
"d_kv": 64,
|
| 8 |
+
"d_model": 512,
|
| 9 |
+
"decoder_start_token_id": 0,
|
| 10 |
+
"dense_act_fn": "relu",
|
| 11 |
+
"dropout_rate": 0.1,
|
| 12 |
+
"dtype": "float32",
|
| 13 |
+
"eos_token_id": 1,
|
| 14 |
+
"feed_forward_proj": "relu",
|
| 15 |
+
"initializer_factor": 1.0,
|
| 16 |
+
"is_encoder_decoder": true,
|
| 17 |
+
"is_gated_act": false,
|
| 18 |
+
"layer_norm_epsilon": 1e-06,
|
| 19 |
+
"model_type": "t5",
|
| 20 |
+
"n_positions": 512,
|
| 21 |
+
"num_decoder_layers": 6,
|
| 22 |
+
"num_heads": 8,
|
| 23 |
+
"num_layers": 6,
|
| 24 |
+
"output_past": true,
|
| 25 |
+
"pad_token_id": 0,
|
| 26 |
+
"relative_attention_max_distance": 128,
|
| 27 |
+
"relative_attention_num_buckets": 32,
|
| 28 |
+
"task_specific_params": {
|
| 29 |
+
"summarization": {
|
| 30 |
+
"early_stopping": true,
|
| 31 |
+
"length_penalty": 2.0,
|
| 32 |
+
"max_length": 200,
|
| 33 |
+
"min_length": 30,
|
| 34 |
+
"no_repeat_ngram_size": 3,
|
| 35 |
+
"num_beams": 4,
|
| 36 |
+
"prefix": "summarize: "
|
| 37 |
+
},
|
| 38 |
+
"translation_en_to_de": {
|
| 39 |
+
"early_stopping": true,
|
| 40 |
+
"max_length": 300,
|
| 41 |
+
"num_beams": 4,
|
| 42 |
+
"prefix": "translate English to German: "
|
| 43 |
+
},
|
| 44 |
+
"translation_en_to_fr": {
|
| 45 |
+
"early_stopping": true,
|
| 46 |
+
"max_length": 300,
|
| 47 |
+
"num_beams": 4,
|
| 48 |
+
"prefix": "translate English to French: "
|
| 49 |
+
},
|
| 50 |
+
"translation_en_to_ro": {
|
| 51 |
+
"early_stopping": true,
|
| 52 |
+
"max_length": 300,
|
| 53 |
+
"num_beams": 4,
|
| 54 |
+
"prefix": "translate English to Romanian: "
|
| 55 |
+
}
|
| 56 |
+
},
|
| 57 |
+
"transformers_version": "4.57.3",
|
| 58 |
+
"use_cache": true,
|
| 59 |
+
"vocab_size": 32128
|
| 60 |
+
}
|
fpscores.pkl.gz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:10dcef9340c873e7b987924461b0af5365eb8dd96be607203debe8ddf80c1e73
|
| 3 |
+
size 3848394
|
generation_config.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_from_model_config": true,
|
| 3 |
+
"decoder_start_token_id": 0,
|
| 4 |
+
"eos_token_id": [
|
| 5 |
+
1
|
| 6 |
+
],
|
| 7 |
+
"pad_token_id": 0,
|
| 8 |
+
"transformers_version": "4.57.3"
|
| 9 |
+
}
|
lgbm_gas_pipeline.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:25cbe38babbee4527c033340f324f31ff70363faec07370b83747bc9c63e7350
|
| 3 |
+
size 1932028
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cf17ce234cda524e4b9d0d921ea7693bfcd243d5d6602a7ccad8968b8ae89d23
|
| 3 |
+
size 242041896
|
polimerx_critic_v2_sanitized.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1cbed399cb5dfe36ba48b81637f5ad5c5a6b0c2a25942abcdf232b8d09a7678d
|
| 3 |
+
size 2006300
|
requirements.txt
CHANGED
|
Binary files a/requirements.txt and b/requirements.txt differ
|
|
|
rf_eps.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:37f6d461ac42dd294f84df18bc56fd7314d3abc145d3c05886d7a6ab03c3272c
|
| 3 |
+
size 2735137
|
rf_refractive_index.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a1341740aeab83726a919e4255b5c8221b95d49a845700f6c439974de0a89141
|
| 3 |
+
size 4958065
|
sascorer.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# calculation of synthetic accessibility score as described in:
|
| 3 |
+
#
|
| 4 |
+
# Estimation of Synthetic Accessibility Score of Drug-like Molecules based on Molecular Complexity and Fragment Contributions
|
| 5 |
+
# Peter Ertl and Ansgar Schuffenhauer
|
| 6 |
+
# Journal of Cheminformatics 1:8 (2009)
|
| 7 |
+
# http://www.jcheminf.com/content/1/1/8
|
| 8 |
+
#
|
| 9 |
+
# several small modifications to the original paper are included
|
| 10 |
+
# particularly slightly different formula for marocyclic penalty
|
| 11 |
+
# and taking into account also molecule symmetry (fingerprint density)
|
| 12 |
+
#
|
| 13 |
+
# for a set of 10k diverse molecules the agreement between the original method
|
| 14 |
+
# as implemented in PipelinePilot and this implementation is r2 = 0.97
|
| 15 |
+
#
|
| 16 |
+
# peter ertl & greg landrum, september 2013
|
| 17 |
+
#
|
| 18 |
+
|
| 19 |
+
from rdkit import Chem
|
| 20 |
+
from rdkit.Chem import rdFingerprintGenerator, rdMolDescriptors
|
| 21 |
+
|
| 22 |
+
import math
|
| 23 |
+
import pickle
|
| 24 |
+
|
| 25 |
+
import os.path as op
|
| 26 |
+
|
| 27 |
+
_fscores = None
|
| 28 |
+
mfpgen = rdFingerprintGenerator.GetMorganGenerator(radius=2)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def readFragmentScores(name="fpscores.pkl.gz"):
|
| 32 |
+
import gzip
|
| 33 |
+
global _fscores
|
| 34 |
+
# generate the full path filename:
|
| 35 |
+
if name == "fpscores.pkl.gz":
|
| 36 |
+
name = op.join(op.dirname(__file__), name)
|
| 37 |
+
data = pickle.load(gzip.open(name))
|
| 38 |
+
outDict = {}
|
| 39 |
+
for i in data:
|
| 40 |
+
for j in range(1, len(i)):
|
| 41 |
+
outDict[i[j]] = float(i[0])
|
| 42 |
+
_fscores = outDict
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def numBridgeheadsAndSpiro(mol, ri=None):
|
| 46 |
+
nSpiro = rdMolDescriptors.CalcNumSpiroAtoms(mol)
|
| 47 |
+
nBridgehead = rdMolDescriptors.CalcNumBridgeheadAtoms(mol)
|
| 48 |
+
return nBridgehead, nSpiro
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def calculateScore(m):
|
| 52 |
+
|
| 53 |
+
if not m.GetNumAtoms():
|
| 54 |
+
return None
|
| 55 |
+
|
| 56 |
+
if _fscores is None:
|
| 57 |
+
readFragmentScores()
|
| 58 |
+
|
| 59 |
+
# fragment score
|
| 60 |
+
sfp = mfpgen.GetSparseCountFingerprint(m)
|
| 61 |
+
|
| 62 |
+
score1 = 0.
|
| 63 |
+
nf = 0
|
| 64 |
+
nze = sfp.GetNonzeroElements()
|
| 65 |
+
for id, count in nze.items():
|
| 66 |
+
nf += count
|
| 67 |
+
score1 += _fscores.get(id, -4) * count
|
| 68 |
+
|
| 69 |
+
score1 /= nf
|
| 70 |
+
|
| 71 |
+
# features score
|
| 72 |
+
nAtoms = m.GetNumAtoms()
|
| 73 |
+
nChiralCenters = len(Chem.FindMolChiralCenters(m, includeUnassigned=True))
|
| 74 |
+
ri = m.GetRingInfo()
|
| 75 |
+
nBridgeheads, nSpiro = numBridgeheadsAndSpiro(m, ri)
|
| 76 |
+
nMacrocycles = 0
|
| 77 |
+
for x in ri.AtomRings():
|
| 78 |
+
if len(x) > 8:
|
| 79 |
+
nMacrocycles += 1
|
| 80 |
+
|
| 81 |
+
sizePenalty = nAtoms**1.005 - nAtoms
|
| 82 |
+
stereoPenalty = math.log10(nChiralCenters + 1)
|
| 83 |
+
spiroPenalty = math.log10(nSpiro + 1)
|
| 84 |
+
bridgePenalty = math.log10(nBridgeheads + 1)
|
| 85 |
+
macrocyclePenalty = 0.
|
| 86 |
+
# ---------------------------------------
|
| 87 |
+
# This differs from the paper, which defines:
|
| 88 |
+
# macrocyclePenalty = math.log10(nMacrocycles+1)
|
| 89 |
+
# This form generates better results when 2 or more macrocycles are present
|
| 90 |
+
if nMacrocycles > 0:
|
| 91 |
+
macrocyclePenalty = math.log10(2)
|
| 92 |
+
|
| 93 |
+
score2 = 0. - sizePenalty - stereoPenalty - spiroPenalty - bridgePenalty - macrocyclePenalty
|
| 94 |
+
|
| 95 |
+
# correction for the fingerprint density
|
| 96 |
+
# not in the original publication, added in version 1.1
|
| 97 |
+
# to make highly symmetrical molecules easier to synthetise
|
| 98 |
+
score3 = 0.
|
| 99 |
+
numBits = len(nze)
|
| 100 |
+
if nAtoms > numBits:
|
| 101 |
+
score3 = math.log(float(nAtoms) / numBits) * .5
|
| 102 |
+
|
| 103 |
+
sascore = score1 + score2 + score3
|
| 104 |
+
|
| 105 |
+
# need to transform "raw" value into scale between 1 and 10
|
| 106 |
+
min = -4.0
|
| 107 |
+
max = 2.5
|
| 108 |
+
sascore = 11. - (sascore - min + 1) / (max - min) * 9.
|
| 109 |
+
|
| 110 |
+
# smooth the 10-end
|
| 111 |
+
if sascore > 8.:
|
| 112 |
+
sascore = 8. + math.log(sascore + 1. - 9.)
|
| 113 |
+
if sascore > 10.:
|
| 114 |
+
sascore = 10.0
|
| 115 |
+
elif sascore < 1.:
|
| 116 |
+
sascore = 1.0
|
| 117 |
+
|
| 118 |
+
return sascore
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def processMols(mols):
|
| 122 |
+
print('smiles\tName\tsa_score')
|
| 123 |
+
for i, m in enumerate(mols):
|
| 124 |
+
if m is None:
|
| 125 |
+
continue
|
| 126 |
+
|
| 127 |
+
s = calculateScore(m)
|
| 128 |
+
|
| 129 |
+
smiles = Chem.MolToSmiles(m)
|
| 130 |
+
if s is None:
|
| 131 |
+
print(f"{smiles}\t{m.GetProp('_Name')}\t{s}")
|
| 132 |
+
else:
|
| 133 |
+
print(f"{smiles}\t{m.GetProp('_Name')}\t{s:3f}")
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
if __name__ == '__main__':
|
| 137 |
+
import sys
|
| 138 |
+
import time
|
| 139 |
+
|
| 140 |
+
t1 = time.time()
|
| 141 |
+
if len(sys.argv) == 2:
|
| 142 |
+
readFragmentScores()
|
| 143 |
+
else:
|
| 144 |
+
readFragmentScores(sys.argv[2])
|
| 145 |
+
t2 = time.time()
|
| 146 |
+
|
| 147 |
+
molFile = sys.argv[1]
|
| 148 |
+
if molFile.endswith("smi"):
|
| 149 |
+
suppl = Chem.SmilesMolSupplier(molFile)
|
| 150 |
+
elif molFile.endswith("sdf"):
|
| 151 |
+
suppl = Chem.SDMolSupplier(molFile)
|
| 152 |
+
else:
|
| 153 |
+
print(f"Unrecognized file extension for {molFile}")
|
| 154 |
+
sys.exit()
|
| 155 |
+
|
| 156 |
+
t3 = time.time()
|
| 157 |
+
processMols(suppl)
|
| 158 |
+
t4 = time.time()
|
| 159 |
+
|
| 160 |
+
print('Reading took %.2f seconds. Calculating took %.2f seconds' % ((t2 - t1), (t4 - t3)),
|
| 161 |
+
file=sys.stderr)
|
| 162 |
+
|
| 163 |
+
#
|
| 164 |
+
# Copyright (c) 2013, Novartis Institutes for BioMedical Research Inc.
|
| 165 |
+
# All rights reserved.
|
| 166 |
+
#
|
| 167 |
+
# Redistribution and use in source and binary forms, with or without
|
| 168 |
+
# modification, are permitted provided that the following conditions are
|
| 169 |
+
# met:
|
| 170 |
+
#
|
| 171 |
+
# * Redistributions of source code must retain the above copyright
|
| 172 |
+
# notice, this list of conditions and the following disclaimer.
|
| 173 |
+
# * Redistributions in binary form must reproduce the above
|
| 174 |
+
# copyright notice, this list of conditions and the following
|
| 175 |
+
# disclaimer in the documentation and/or other materials provided
|
| 176 |
+
# with the distribution.
|
| 177 |
+
# * Neither the name of Novartis Institutes for BioMedical Research Inc.
|
| 178 |
+
# nor the names of its contributors may be used to endorse or promote
|
| 179 |
+
# products derived from this software without specific prior written permission.
|
| 180 |
+
#
|
| 181 |
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| 182 |
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| 183 |
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| 184 |
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| 185 |
+
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| 186 |
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| 187 |
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| 188 |
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| 189 |
+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 190 |
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| 191 |
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 192 |
+
#
|
special_tokens_map.json
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"additional_special_tokens": [
|
| 3 |
+
"<extra_id_0>",
|
| 4 |
+
"<extra_id_1>",
|
| 5 |
+
"<extra_id_2>",
|
| 6 |
+
"<extra_id_3>",
|
| 7 |
+
"<extra_id_4>",
|
| 8 |
+
"<extra_id_5>",
|
| 9 |
+
"<extra_id_6>",
|
| 10 |
+
"<extra_id_7>",
|
| 11 |
+
"<extra_id_8>",
|
| 12 |
+
"<extra_id_9>",
|
| 13 |
+
"<extra_id_10>",
|
| 14 |
+
"<extra_id_11>",
|
| 15 |
+
"<extra_id_12>",
|
| 16 |
+
"<extra_id_13>",
|
| 17 |
+
"<extra_id_14>",
|
| 18 |
+
"<extra_id_15>",
|
| 19 |
+
"<extra_id_16>",
|
| 20 |
+
"<extra_id_17>",
|
| 21 |
+
"<extra_id_18>",
|
| 22 |
+
"<extra_id_19>",
|
| 23 |
+
"<extra_id_20>",
|
| 24 |
+
"<extra_id_21>",
|
| 25 |
+
"<extra_id_22>",
|
| 26 |
+
"<extra_id_23>",
|
| 27 |
+
"<extra_id_24>",
|
| 28 |
+
"<extra_id_25>",
|
| 29 |
+
"<extra_id_26>",
|
| 30 |
+
"<extra_id_27>",
|
| 31 |
+
"<extra_id_28>",
|
| 32 |
+
"<extra_id_29>",
|
| 33 |
+
"<extra_id_30>",
|
| 34 |
+
"<extra_id_31>",
|
| 35 |
+
"<extra_id_32>",
|
| 36 |
+
"<extra_id_33>",
|
| 37 |
+
"<extra_id_34>",
|
| 38 |
+
"<extra_id_35>",
|
| 39 |
+
"<extra_id_36>",
|
| 40 |
+
"<extra_id_37>",
|
| 41 |
+
"<extra_id_38>",
|
| 42 |
+
"<extra_id_39>",
|
| 43 |
+
"<extra_id_40>",
|
| 44 |
+
"<extra_id_41>",
|
| 45 |
+
"<extra_id_42>",
|
| 46 |
+
"<extra_id_43>",
|
| 47 |
+
"<extra_id_44>",
|
| 48 |
+
"<extra_id_45>",
|
| 49 |
+
"<extra_id_46>",
|
| 50 |
+
"<extra_id_47>",
|
| 51 |
+
"<extra_id_48>",
|
| 52 |
+
"<extra_id_49>",
|
| 53 |
+
"<extra_id_50>",
|
| 54 |
+
"<extra_id_51>",
|
| 55 |
+
"<extra_id_52>",
|
| 56 |
+
"<extra_id_53>",
|
| 57 |
+
"<extra_id_54>",
|
| 58 |
+
"<extra_id_55>",
|
| 59 |
+
"<extra_id_56>",
|
| 60 |
+
"<extra_id_57>",
|
| 61 |
+
"<extra_id_58>",
|
| 62 |
+
"<extra_id_59>",
|
| 63 |
+
"<extra_id_60>",
|
| 64 |
+
"<extra_id_61>",
|
| 65 |
+
"<extra_id_62>",
|
| 66 |
+
"<extra_id_63>",
|
| 67 |
+
"<extra_id_64>",
|
| 68 |
+
"<extra_id_65>",
|
| 69 |
+
"<extra_id_66>",
|
| 70 |
+
"<extra_id_67>",
|
| 71 |
+
"<extra_id_68>",
|
| 72 |
+
"<extra_id_69>",
|
| 73 |
+
"<extra_id_70>",
|
| 74 |
+
"<extra_id_71>",
|
| 75 |
+
"<extra_id_72>",
|
| 76 |
+
"<extra_id_73>",
|
| 77 |
+
"<extra_id_74>",
|
| 78 |
+
"<extra_id_75>",
|
| 79 |
+
"<extra_id_76>",
|
| 80 |
+
"<extra_id_77>",
|
| 81 |
+
"<extra_id_78>",
|
| 82 |
+
"<extra_id_79>",
|
| 83 |
+
"<extra_id_80>",
|
| 84 |
+
"<extra_id_81>",
|
| 85 |
+
"<extra_id_82>",
|
| 86 |
+
"<extra_id_83>",
|
| 87 |
+
"<extra_id_84>",
|
| 88 |
+
"<extra_id_85>",
|
| 89 |
+
"<extra_id_86>",
|
| 90 |
+
"<extra_id_87>",
|
| 91 |
+
"<extra_id_88>",
|
| 92 |
+
"<extra_id_89>",
|
| 93 |
+
"<extra_id_90>",
|
| 94 |
+
"<extra_id_91>",
|
| 95 |
+
"<extra_id_92>",
|
| 96 |
+
"<extra_id_93>",
|
| 97 |
+
"<extra_id_94>",
|
| 98 |
+
"<extra_id_95>",
|
| 99 |
+
"<extra_id_96>",
|
| 100 |
+
"<extra_id_97>",
|
| 101 |
+
"<extra_id_98>",
|
| 102 |
+
"<extra_id_99>"
|
| 103 |
+
],
|
| 104 |
+
"eos_token": {
|
| 105 |
+
"content": "</s>",
|
| 106 |
+
"lstrip": false,
|
| 107 |
+
"normalized": false,
|
| 108 |
+
"rstrip": false,
|
| 109 |
+
"single_word": false
|
| 110 |
+
},
|
| 111 |
+
"pad_token": {
|
| 112 |
+
"content": "<pad>",
|
| 113 |
+
"lstrip": false,
|
| 114 |
+
"normalized": false,
|
| 115 |
+
"rstrip": false,
|
| 116 |
+
"single_word": false
|
| 117 |
+
},
|
| 118 |
+
"unk_token": {
|
| 119 |
+
"content": "<unk>",
|
| 120 |
+
"lstrip": false,
|
| 121 |
+
"normalized": false,
|
| 122 |
+
"rstrip": false,
|
| 123 |
+
"single_word": false
|
| 124 |
+
}
|
| 125 |
+
}
|
spiece.model
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d60acb128cf7b7f2536e8f38a5b18a05535c9e14c7a355904270e15b0945ea86
|
| 3 |
+
size 791656
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,939 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": null,
|
| 3 |
+
"added_tokens_decoder": {
|
| 4 |
+
"0": {
|
| 5 |
+
"content": "<pad>",
|
| 6 |
+
"lstrip": false,
|
| 7 |
+
"normalized": false,
|
| 8 |
+
"rstrip": false,
|
| 9 |
+
"single_word": false,
|
| 10 |
+
"special": true
|
| 11 |
+
},
|
| 12 |
+
"1": {
|
| 13 |
+
"content": "</s>",
|
| 14 |
+
"lstrip": false,
|
| 15 |
+
"normalized": false,
|
| 16 |
+
"rstrip": false,
|
| 17 |
+
"single_word": false,
|
| 18 |
+
"special": true
|
| 19 |
+
},
|
| 20 |
+
"2": {
|
| 21 |
+
"content": "<unk>",
|
| 22 |
+
"lstrip": false,
|
| 23 |
+
"normalized": false,
|
| 24 |
+
"rstrip": false,
|
| 25 |
+
"single_word": false,
|
| 26 |
+
"special": true
|
| 27 |
+
},
|
| 28 |
+
"32000": {
|
| 29 |
+
"content": "<extra_id_99>",
|
| 30 |
+
"lstrip": false,
|
| 31 |
+
"normalized": false,
|
| 32 |
+
"rstrip": false,
|
| 33 |
+
"single_word": false,
|
| 34 |
+
"special": true
|
| 35 |
+
},
|
| 36 |
+
"32001": {
|
| 37 |
+
"content": "<extra_id_98>",
|
| 38 |
+
"lstrip": false,
|
| 39 |
+
"normalized": false,
|
| 40 |
+
"rstrip": false,
|
| 41 |
+
"single_word": false,
|
| 42 |
+
"special": true
|
| 43 |
+
},
|
| 44 |
+
"32002": {
|
| 45 |
+
"content": "<extra_id_97>",
|
| 46 |
+
"lstrip": false,
|
| 47 |
+
"normalized": false,
|
| 48 |
+
"rstrip": false,
|
| 49 |
+
"single_word": false,
|
| 50 |
+
"special": true
|
| 51 |
+
},
|
| 52 |
+
"32003": {
|
| 53 |
+
"content": "<extra_id_96>",
|
| 54 |
+
"lstrip": false,
|
| 55 |
+
"normalized": false,
|
| 56 |
+
"rstrip": false,
|
| 57 |
+
"single_word": false,
|
| 58 |
+
"special": true
|
| 59 |
+
},
|
| 60 |
+
"32004": {
|
| 61 |
+
"content": "<extra_id_95>",
|
| 62 |
+
"lstrip": false,
|
| 63 |
+
"normalized": false,
|
| 64 |
+
"rstrip": false,
|
| 65 |
+
"single_word": false,
|
| 66 |
+
"special": true
|
| 67 |
+
},
|
| 68 |
+
"32005": {
|
| 69 |
+
"content": "<extra_id_94>",
|
| 70 |
+
"lstrip": false,
|
| 71 |
+
"normalized": false,
|
| 72 |
+
"rstrip": false,
|
| 73 |
+
"single_word": false,
|
| 74 |
+
"special": true
|
| 75 |
+
},
|
| 76 |
+
"32006": {
|
| 77 |
+
"content": "<extra_id_93>",
|
| 78 |
+
"lstrip": false,
|
| 79 |
+
"normalized": false,
|
| 80 |
+
"rstrip": false,
|
| 81 |
+
"single_word": false,
|
| 82 |
+
"special": true
|
| 83 |
+
},
|
| 84 |
+
"32007": {
|
| 85 |
+
"content": "<extra_id_92>",
|
| 86 |
+
"lstrip": false,
|
| 87 |
+
"normalized": false,
|
| 88 |
+
"rstrip": false,
|
| 89 |
+
"single_word": false,
|
| 90 |
+
"special": true
|
| 91 |
+
},
|
| 92 |
+
"32008": {
|
| 93 |
+
"content": "<extra_id_91>",
|
| 94 |
+
"lstrip": false,
|
| 95 |
+
"normalized": false,
|
| 96 |
+
"rstrip": false,
|
| 97 |
+
"single_word": false,
|
| 98 |
+
"special": true
|
| 99 |
+
},
|
| 100 |
+
"32009": {
|
| 101 |
+
"content": "<extra_id_90>",
|
| 102 |
+
"lstrip": false,
|
| 103 |
+
"normalized": false,
|
| 104 |
+
"rstrip": false,
|
| 105 |
+
"single_word": false,
|
| 106 |
+
"special": true
|
| 107 |
+
},
|
| 108 |
+
"32010": {
|
| 109 |
+
"content": "<extra_id_89>",
|
| 110 |
+
"lstrip": false,
|
| 111 |
+
"normalized": false,
|
| 112 |
+
"rstrip": false,
|
| 113 |
+
"single_word": false,
|
| 114 |
+
"special": true
|
| 115 |
+
},
|
| 116 |
+
"32011": {
|
| 117 |
+
"content": "<extra_id_88>",
|
| 118 |
+
"lstrip": false,
|
| 119 |
+
"normalized": false,
|
| 120 |
+
"rstrip": false,
|
| 121 |
+
"single_word": false,
|
| 122 |
+
"special": true
|
| 123 |
+
},
|
| 124 |
+
"32012": {
|
| 125 |
+
"content": "<extra_id_87>",
|
| 126 |
+
"lstrip": false,
|
| 127 |
+
"normalized": false,
|
| 128 |
+
"rstrip": false,
|
| 129 |
+
"single_word": false,
|
| 130 |
+
"special": true
|
| 131 |
+
},
|
| 132 |
+
"32013": {
|
| 133 |
+
"content": "<extra_id_86>",
|
| 134 |
+
"lstrip": false,
|
| 135 |
+
"normalized": false,
|
| 136 |
+
"rstrip": false,
|
| 137 |
+
"single_word": false,
|
| 138 |
+
"special": true
|
| 139 |
+
},
|
| 140 |
+
"32014": {
|
| 141 |
+
"content": "<extra_id_85>",
|
| 142 |
+
"lstrip": false,
|
| 143 |
+
"normalized": false,
|
| 144 |
+
"rstrip": false,
|
| 145 |
+
"single_word": false,
|
| 146 |
+
"special": true
|
| 147 |
+
},
|
| 148 |
+
"32015": {
|
| 149 |
+
"content": "<extra_id_84>",
|
| 150 |
+
"lstrip": false,
|
| 151 |
+
"normalized": false,
|
| 152 |
+
"rstrip": false,
|
| 153 |
+
"single_word": false,
|
| 154 |
+
"special": true
|
| 155 |
+
},
|
| 156 |
+
"32016": {
|
| 157 |
+
"content": "<extra_id_83>",
|
| 158 |
+
"lstrip": false,
|
| 159 |
+
"normalized": false,
|
| 160 |
+
"rstrip": false,
|
| 161 |
+
"single_word": false,
|
| 162 |
+
"special": true
|
| 163 |
+
},
|
| 164 |
+
"32017": {
|
| 165 |
+
"content": "<extra_id_82>",
|
| 166 |
+
"lstrip": false,
|
| 167 |
+
"normalized": false,
|
| 168 |
+
"rstrip": false,
|
| 169 |
+
"single_word": false,
|
| 170 |
+
"special": true
|
| 171 |
+
},
|
| 172 |
+
"32018": {
|
| 173 |
+
"content": "<extra_id_81>",
|
| 174 |
+
"lstrip": false,
|
| 175 |
+
"normalized": false,
|
| 176 |
+
"rstrip": false,
|
| 177 |
+
"single_word": false,
|
| 178 |
+
"special": true
|
| 179 |
+
},
|
| 180 |
+
"32019": {
|
| 181 |
+
"content": "<extra_id_80>",
|
| 182 |
+
"lstrip": false,
|
| 183 |
+
"normalized": false,
|
| 184 |
+
"rstrip": false,
|
| 185 |
+
"single_word": false,
|
| 186 |
+
"special": true
|
| 187 |
+
},
|
| 188 |
+
"32020": {
|
| 189 |
+
"content": "<extra_id_79>",
|
| 190 |
+
"lstrip": false,
|
| 191 |
+
"normalized": false,
|
| 192 |
+
"rstrip": false,
|
| 193 |
+
"single_word": false,
|
| 194 |
+
"special": true
|
| 195 |
+
},
|
| 196 |
+
"32021": {
|
| 197 |
+
"content": "<extra_id_78>",
|
| 198 |
+
"lstrip": false,
|
| 199 |
+
"normalized": false,
|
| 200 |
+
"rstrip": false,
|
| 201 |
+
"single_word": false,
|
| 202 |
+
"special": true
|
| 203 |
+
},
|
| 204 |
+
"32022": {
|
| 205 |
+
"content": "<extra_id_77>",
|
| 206 |
+
"lstrip": false,
|
| 207 |
+
"normalized": false,
|
| 208 |
+
"rstrip": false,
|
| 209 |
+
"single_word": false,
|
| 210 |
+
"special": true
|
| 211 |
+
},
|
| 212 |
+
"32023": {
|
| 213 |
+
"content": "<extra_id_76>",
|
| 214 |
+
"lstrip": false,
|
| 215 |
+
"normalized": false,
|
| 216 |
+
"rstrip": false,
|
| 217 |
+
"single_word": false,
|
| 218 |
+
"special": true
|
| 219 |
+
},
|
| 220 |
+
"32024": {
|
| 221 |
+
"content": "<extra_id_75>",
|
| 222 |
+
"lstrip": false,
|
| 223 |
+
"normalized": false,
|
| 224 |
+
"rstrip": false,
|
| 225 |
+
"single_word": false,
|
| 226 |
+
"special": true
|
| 227 |
+
},
|
| 228 |
+
"32025": {
|
| 229 |
+
"content": "<extra_id_74>",
|
| 230 |
+
"lstrip": false,
|
| 231 |
+
"normalized": false,
|
| 232 |
+
"rstrip": false,
|
| 233 |
+
"single_word": false,
|
| 234 |
+
"special": true
|
| 235 |
+
},
|
| 236 |
+
"32026": {
|
| 237 |
+
"content": "<extra_id_73>",
|
| 238 |
+
"lstrip": false,
|
| 239 |
+
"normalized": false,
|
| 240 |
+
"rstrip": false,
|
| 241 |
+
"single_word": false,
|
| 242 |
+
"special": true
|
| 243 |
+
},
|
| 244 |
+
"32027": {
|
| 245 |
+
"content": "<extra_id_72>",
|
| 246 |
+
"lstrip": false,
|
| 247 |
+
"normalized": false,
|
| 248 |
+
"rstrip": false,
|
| 249 |
+
"single_word": false,
|
| 250 |
+
"special": true
|
| 251 |
+
},
|
| 252 |
+
"32028": {
|
| 253 |
+
"content": "<extra_id_71>",
|
| 254 |
+
"lstrip": false,
|
| 255 |
+
"normalized": false,
|
| 256 |
+
"rstrip": false,
|
| 257 |
+
"single_word": false,
|
| 258 |
+
"special": true
|
| 259 |
+
},
|
| 260 |
+
"32029": {
|
| 261 |
+
"content": "<extra_id_70>",
|
| 262 |
+
"lstrip": false,
|
| 263 |
+
"normalized": false,
|
| 264 |
+
"rstrip": false,
|
| 265 |
+
"single_word": false,
|
| 266 |
+
"special": true
|
| 267 |
+
},
|
| 268 |
+
"32030": {
|
| 269 |
+
"content": "<extra_id_69>",
|
| 270 |
+
"lstrip": false,
|
| 271 |
+
"normalized": false,
|
| 272 |
+
"rstrip": false,
|
| 273 |
+
"single_word": false,
|
| 274 |
+
"special": true
|
| 275 |
+
},
|
| 276 |
+
"32031": {
|
| 277 |
+
"content": "<extra_id_68>",
|
| 278 |
+
"lstrip": false,
|
| 279 |
+
"normalized": false,
|
| 280 |
+
"rstrip": false,
|
| 281 |
+
"single_word": false,
|
| 282 |
+
"special": true
|
| 283 |
+
},
|
| 284 |
+
"32032": {
|
| 285 |
+
"content": "<extra_id_67>",
|
| 286 |
+
"lstrip": false,
|
| 287 |
+
"normalized": false,
|
| 288 |
+
"rstrip": false,
|
| 289 |
+
"single_word": false,
|
| 290 |
+
"special": true
|
| 291 |
+
},
|
| 292 |
+
"32033": {
|
| 293 |
+
"content": "<extra_id_66>",
|
| 294 |
+
"lstrip": false,
|
| 295 |
+
"normalized": false,
|
| 296 |
+
"rstrip": false,
|
| 297 |
+
"single_word": false,
|
| 298 |
+
"special": true
|
| 299 |
+
},
|
| 300 |
+
"32034": {
|
| 301 |
+
"content": "<extra_id_65>",
|
| 302 |
+
"lstrip": false,
|
| 303 |
+
"normalized": false,
|
| 304 |
+
"rstrip": false,
|
| 305 |
+
"single_word": false,
|
| 306 |
+
"special": true
|
| 307 |
+
},
|
| 308 |
+
"32035": {
|
| 309 |
+
"content": "<extra_id_64>",
|
| 310 |
+
"lstrip": false,
|
| 311 |
+
"normalized": false,
|
| 312 |
+
"rstrip": false,
|
| 313 |
+
"single_word": false,
|
| 314 |
+
"special": true
|
| 315 |
+
},
|
| 316 |
+
"32036": {
|
| 317 |
+
"content": "<extra_id_63>",
|
| 318 |
+
"lstrip": false,
|
| 319 |
+
"normalized": false,
|
| 320 |
+
"rstrip": false,
|
| 321 |
+
"single_word": false,
|
| 322 |
+
"special": true
|
| 323 |
+
},
|
| 324 |
+
"32037": {
|
| 325 |
+
"content": "<extra_id_62>",
|
| 326 |
+
"lstrip": false,
|
| 327 |
+
"normalized": false,
|
| 328 |
+
"rstrip": false,
|
| 329 |
+
"single_word": false,
|
| 330 |
+
"special": true
|
| 331 |
+
},
|
| 332 |
+
"32038": {
|
| 333 |
+
"content": "<extra_id_61>",
|
| 334 |
+
"lstrip": false,
|
| 335 |
+
"normalized": false,
|
| 336 |
+
"rstrip": false,
|
| 337 |
+
"single_word": false,
|
| 338 |
+
"special": true
|
| 339 |
+
},
|
| 340 |
+
"32039": {
|
| 341 |
+
"content": "<extra_id_60>",
|
| 342 |
+
"lstrip": false,
|
| 343 |
+
"normalized": false,
|
| 344 |
+
"rstrip": false,
|
| 345 |
+
"single_word": false,
|
| 346 |
+
"special": true
|
| 347 |
+
},
|
| 348 |
+
"32040": {
|
| 349 |
+
"content": "<extra_id_59>",
|
| 350 |
+
"lstrip": false,
|
| 351 |
+
"normalized": false,
|
| 352 |
+
"rstrip": false,
|
| 353 |
+
"single_word": false,
|
| 354 |
+
"special": true
|
| 355 |
+
},
|
| 356 |
+
"32041": {
|
| 357 |
+
"content": "<extra_id_58>",
|
| 358 |
+
"lstrip": false,
|
| 359 |
+
"normalized": false,
|
| 360 |
+
"rstrip": false,
|
| 361 |
+
"single_word": false,
|
| 362 |
+
"special": true
|
| 363 |
+
},
|
| 364 |
+
"32042": {
|
| 365 |
+
"content": "<extra_id_57>",
|
| 366 |
+
"lstrip": false,
|
| 367 |
+
"normalized": false,
|
| 368 |
+
"rstrip": false,
|
| 369 |
+
"single_word": false,
|
| 370 |
+
"special": true
|
| 371 |
+
},
|
| 372 |
+
"32043": {
|
| 373 |
+
"content": "<extra_id_56>",
|
| 374 |
+
"lstrip": false,
|
| 375 |
+
"normalized": false,
|
| 376 |
+
"rstrip": false,
|
| 377 |
+
"single_word": false,
|
| 378 |
+
"special": true
|
| 379 |
+
},
|
| 380 |
+
"32044": {
|
| 381 |
+
"content": "<extra_id_55>",
|
| 382 |
+
"lstrip": false,
|
| 383 |
+
"normalized": false,
|
| 384 |
+
"rstrip": false,
|
| 385 |
+
"single_word": false,
|
| 386 |
+
"special": true
|
| 387 |
+
},
|
| 388 |
+
"32045": {
|
| 389 |
+
"content": "<extra_id_54>",
|
| 390 |
+
"lstrip": false,
|
| 391 |
+
"normalized": false,
|
| 392 |
+
"rstrip": false,
|
| 393 |
+
"single_word": false,
|
| 394 |
+
"special": true
|
| 395 |
+
},
|
| 396 |
+
"32046": {
|
| 397 |
+
"content": "<extra_id_53>",
|
| 398 |
+
"lstrip": false,
|
| 399 |
+
"normalized": false,
|
| 400 |
+
"rstrip": false,
|
| 401 |
+
"single_word": false,
|
| 402 |
+
"special": true
|
| 403 |
+
},
|
| 404 |
+
"32047": {
|
| 405 |
+
"content": "<extra_id_52>",
|
| 406 |
+
"lstrip": false,
|
| 407 |
+
"normalized": false,
|
| 408 |
+
"rstrip": false,
|
| 409 |
+
"single_word": false,
|
| 410 |
+
"special": true
|
| 411 |
+
},
|
| 412 |
+
"32048": {
|
| 413 |
+
"content": "<extra_id_51>",
|
| 414 |
+
"lstrip": false,
|
| 415 |
+
"normalized": false,
|
| 416 |
+
"rstrip": false,
|
| 417 |
+
"single_word": false,
|
| 418 |
+
"special": true
|
| 419 |
+
},
|
| 420 |
+
"32049": {
|
| 421 |
+
"content": "<extra_id_50>",
|
| 422 |
+
"lstrip": false,
|
| 423 |
+
"normalized": false,
|
| 424 |
+
"rstrip": false,
|
| 425 |
+
"single_word": false,
|
| 426 |
+
"special": true
|
| 427 |
+
},
|
| 428 |
+
"32050": {
|
| 429 |
+
"content": "<extra_id_49>",
|
| 430 |
+
"lstrip": false,
|
| 431 |
+
"normalized": false,
|
| 432 |
+
"rstrip": false,
|
| 433 |
+
"single_word": false,
|
| 434 |
+
"special": true
|
| 435 |
+
},
|
| 436 |
+
"32051": {
|
| 437 |
+
"content": "<extra_id_48>",
|
| 438 |
+
"lstrip": false,
|
| 439 |
+
"normalized": false,
|
| 440 |
+
"rstrip": false,
|
| 441 |
+
"single_word": false,
|
| 442 |
+
"special": true
|
| 443 |
+
},
|
| 444 |
+
"32052": {
|
| 445 |
+
"content": "<extra_id_47>",
|
| 446 |
+
"lstrip": false,
|
| 447 |
+
"normalized": false,
|
| 448 |
+
"rstrip": false,
|
| 449 |
+
"single_word": false,
|
| 450 |
+
"special": true
|
| 451 |
+
},
|
| 452 |
+
"32053": {
|
| 453 |
+
"content": "<extra_id_46>",
|
| 454 |
+
"lstrip": false,
|
| 455 |
+
"normalized": false,
|
| 456 |
+
"rstrip": false,
|
| 457 |
+
"single_word": false,
|
| 458 |
+
"special": true
|
| 459 |
+
},
|
| 460 |
+
"32054": {
|
| 461 |
+
"content": "<extra_id_45>",
|
| 462 |
+
"lstrip": false,
|
| 463 |
+
"normalized": false,
|
| 464 |
+
"rstrip": false,
|
| 465 |
+
"single_word": false,
|
| 466 |
+
"special": true
|
| 467 |
+
},
|
| 468 |
+
"32055": {
|
| 469 |
+
"content": "<extra_id_44>",
|
| 470 |
+
"lstrip": false,
|
| 471 |
+
"normalized": false,
|
| 472 |
+
"rstrip": false,
|
| 473 |
+
"single_word": false,
|
| 474 |
+
"special": true
|
| 475 |
+
},
|
| 476 |
+
"32056": {
|
| 477 |
+
"content": "<extra_id_43>",
|
| 478 |
+
"lstrip": false,
|
| 479 |
+
"normalized": false,
|
| 480 |
+
"rstrip": false,
|
| 481 |
+
"single_word": false,
|
| 482 |
+
"special": true
|
| 483 |
+
},
|
| 484 |
+
"32057": {
|
| 485 |
+
"content": "<extra_id_42>",
|
| 486 |
+
"lstrip": false,
|
| 487 |
+
"normalized": false,
|
| 488 |
+
"rstrip": false,
|
| 489 |
+
"single_word": false,
|
| 490 |
+
"special": true
|
| 491 |
+
},
|
| 492 |
+
"32058": {
|
| 493 |
+
"content": "<extra_id_41>",
|
| 494 |
+
"lstrip": false,
|
| 495 |
+
"normalized": false,
|
| 496 |
+
"rstrip": false,
|
| 497 |
+
"single_word": false,
|
| 498 |
+
"special": true
|
| 499 |
+
},
|
| 500 |
+
"32059": {
|
| 501 |
+
"content": "<extra_id_40>",
|
| 502 |
+
"lstrip": false,
|
| 503 |
+
"normalized": false,
|
| 504 |
+
"rstrip": false,
|
| 505 |
+
"single_word": false,
|
| 506 |
+
"special": true
|
| 507 |
+
},
|
| 508 |
+
"32060": {
|
| 509 |
+
"content": "<extra_id_39>",
|
| 510 |
+
"lstrip": false,
|
| 511 |
+
"normalized": false,
|
| 512 |
+
"rstrip": false,
|
| 513 |
+
"single_word": false,
|
| 514 |
+
"special": true
|
| 515 |
+
},
|
| 516 |
+
"32061": {
|
| 517 |
+
"content": "<extra_id_38>",
|
| 518 |
+
"lstrip": false,
|
| 519 |
+
"normalized": false,
|
| 520 |
+
"rstrip": false,
|
| 521 |
+
"single_word": false,
|
| 522 |
+
"special": true
|
| 523 |
+
},
|
| 524 |
+
"32062": {
|
| 525 |
+
"content": "<extra_id_37>",
|
| 526 |
+
"lstrip": false,
|
| 527 |
+
"normalized": false,
|
| 528 |
+
"rstrip": false,
|
| 529 |
+
"single_word": false,
|
| 530 |
+
"special": true
|
| 531 |
+
},
|
| 532 |
+
"32063": {
|
| 533 |
+
"content": "<extra_id_36>",
|
| 534 |
+
"lstrip": false,
|
| 535 |
+
"normalized": false,
|
| 536 |
+
"rstrip": false,
|
| 537 |
+
"single_word": false,
|
| 538 |
+
"special": true
|
| 539 |
+
},
|
| 540 |
+
"32064": {
|
| 541 |
+
"content": "<extra_id_35>",
|
| 542 |
+
"lstrip": false,
|
| 543 |
+
"normalized": false,
|
| 544 |
+
"rstrip": false,
|
| 545 |
+
"single_word": false,
|
| 546 |
+
"special": true
|
| 547 |
+
},
|
| 548 |
+
"32065": {
|
| 549 |
+
"content": "<extra_id_34>",
|
| 550 |
+
"lstrip": false,
|
| 551 |
+
"normalized": false,
|
| 552 |
+
"rstrip": false,
|
| 553 |
+
"single_word": false,
|
| 554 |
+
"special": true
|
| 555 |
+
},
|
| 556 |
+
"32066": {
|
| 557 |
+
"content": "<extra_id_33>",
|
| 558 |
+
"lstrip": false,
|
| 559 |
+
"normalized": false,
|
| 560 |
+
"rstrip": false,
|
| 561 |
+
"single_word": false,
|
| 562 |
+
"special": true
|
| 563 |
+
},
|
| 564 |
+
"32067": {
|
| 565 |
+
"content": "<extra_id_32>",
|
| 566 |
+
"lstrip": false,
|
| 567 |
+
"normalized": false,
|
| 568 |
+
"rstrip": false,
|
| 569 |
+
"single_word": false,
|
| 570 |
+
"special": true
|
| 571 |
+
},
|
| 572 |
+
"32068": {
|
| 573 |
+
"content": "<extra_id_31>",
|
| 574 |
+
"lstrip": false,
|
| 575 |
+
"normalized": false,
|
| 576 |
+
"rstrip": false,
|
| 577 |
+
"single_word": false,
|
| 578 |
+
"special": true
|
| 579 |
+
},
|
| 580 |
+
"32069": {
|
| 581 |
+
"content": "<extra_id_30>",
|
| 582 |
+
"lstrip": false,
|
| 583 |
+
"normalized": false,
|
| 584 |
+
"rstrip": false,
|
| 585 |
+
"single_word": false,
|
| 586 |
+
"special": true
|
| 587 |
+
},
|
| 588 |
+
"32070": {
|
| 589 |
+
"content": "<extra_id_29>",
|
| 590 |
+
"lstrip": false,
|
| 591 |
+
"normalized": false,
|
| 592 |
+
"rstrip": false,
|
| 593 |
+
"single_word": false,
|
| 594 |
+
"special": true
|
| 595 |
+
},
|
| 596 |
+
"32071": {
|
| 597 |
+
"content": "<extra_id_28>",
|
| 598 |
+
"lstrip": false,
|
| 599 |
+
"normalized": false,
|
| 600 |
+
"rstrip": false,
|
| 601 |
+
"single_word": false,
|
| 602 |
+
"special": true
|
| 603 |
+
},
|
| 604 |
+
"32072": {
|
| 605 |
+
"content": "<extra_id_27>",
|
| 606 |
+
"lstrip": false,
|
| 607 |
+
"normalized": false,
|
| 608 |
+
"rstrip": false,
|
| 609 |
+
"single_word": false,
|
| 610 |
+
"special": true
|
| 611 |
+
},
|
| 612 |
+
"32073": {
|
| 613 |
+
"content": "<extra_id_26>",
|
| 614 |
+
"lstrip": false,
|
| 615 |
+
"normalized": false,
|
| 616 |
+
"rstrip": false,
|
| 617 |
+
"single_word": false,
|
| 618 |
+
"special": true
|
| 619 |
+
},
|
| 620 |
+
"32074": {
|
| 621 |
+
"content": "<extra_id_25>",
|
| 622 |
+
"lstrip": false,
|
| 623 |
+
"normalized": false,
|
| 624 |
+
"rstrip": false,
|
| 625 |
+
"single_word": false,
|
| 626 |
+
"special": true
|
| 627 |
+
},
|
| 628 |
+
"32075": {
|
| 629 |
+
"content": "<extra_id_24>",
|
| 630 |
+
"lstrip": false,
|
| 631 |
+
"normalized": false,
|
| 632 |
+
"rstrip": false,
|
| 633 |
+
"single_word": false,
|
| 634 |
+
"special": true
|
| 635 |
+
},
|
| 636 |
+
"32076": {
|
| 637 |
+
"content": "<extra_id_23>",
|
| 638 |
+
"lstrip": false,
|
| 639 |
+
"normalized": false,
|
| 640 |
+
"rstrip": false,
|
| 641 |
+
"single_word": false,
|
| 642 |
+
"special": true
|
| 643 |
+
},
|
| 644 |
+
"32077": {
|
| 645 |
+
"content": "<extra_id_22>",
|
| 646 |
+
"lstrip": false,
|
| 647 |
+
"normalized": false,
|
| 648 |
+
"rstrip": false,
|
| 649 |
+
"single_word": false,
|
| 650 |
+
"special": true
|
| 651 |
+
},
|
| 652 |
+
"32078": {
|
| 653 |
+
"content": "<extra_id_21>",
|
| 654 |
+
"lstrip": false,
|
| 655 |
+
"normalized": false,
|
| 656 |
+
"rstrip": false,
|
| 657 |
+
"single_word": false,
|
| 658 |
+
"special": true
|
| 659 |
+
},
|
| 660 |
+
"32079": {
|
| 661 |
+
"content": "<extra_id_20>",
|
| 662 |
+
"lstrip": false,
|
| 663 |
+
"normalized": false,
|
| 664 |
+
"rstrip": false,
|
| 665 |
+
"single_word": false,
|
| 666 |
+
"special": true
|
| 667 |
+
},
|
| 668 |
+
"32080": {
|
| 669 |
+
"content": "<extra_id_19>",
|
| 670 |
+
"lstrip": false,
|
| 671 |
+
"normalized": false,
|
| 672 |
+
"rstrip": false,
|
| 673 |
+
"single_word": false,
|
| 674 |
+
"special": true
|
| 675 |
+
},
|
| 676 |
+
"32081": {
|
| 677 |
+
"content": "<extra_id_18>",
|
| 678 |
+
"lstrip": false,
|
| 679 |
+
"normalized": false,
|
| 680 |
+
"rstrip": false,
|
| 681 |
+
"single_word": false,
|
| 682 |
+
"special": true
|
| 683 |
+
},
|
| 684 |
+
"32082": {
|
| 685 |
+
"content": "<extra_id_17>",
|
| 686 |
+
"lstrip": false,
|
| 687 |
+
"normalized": false,
|
| 688 |
+
"rstrip": false,
|
| 689 |
+
"single_word": false,
|
| 690 |
+
"special": true
|
| 691 |
+
},
|
| 692 |
+
"32083": {
|
| 693 |
+
"content": "<extra_id_16>",
|
| 694 |
+
"lstrip": false,
|
| 695 |
+
"normalized": false,
|
| 696 |
+
"rstrip": false,
|
| 697 |
+
"single_word": false,
|
| 698 |
+
"special": true
|
| 699 |
+
},
|
| 700 |
+
"32084": {
|
| 701 |
+
"content": "<extra_id_15>",
|
| 702 |
+
"lstrip": false,
|
| 703 |
+
"normalized": false,
|
| 704 |
+
"rstrip": false,
|
| 705 |
+
"single_word": false,
|
| 706 |
+
"special": true
|
| 707 |
+
},
|
| 708 |
+
"32085": {
|
| 709 |
+
"content": "<extra_id_14>",
|
| 710 |
+
"lstrip": false,
|
| 711 |
+
"normalized": false,
|
| 712 |
+
"rstrip": false,
|
| 713 |
+
"single_word": false,
|
| 714 |
+
"special": true
|
| 715 |
+
},
|
| 716 |
+
"32086": {
|
| 717 |
+
"content": "<extra_id_13>",
|
| 718 |
+
"lstrip": false,
|
| 719 |
+
"normalized": false,
|
| 720 |
+
"rstrip": false,
|
| 721 |
+
"single_word": false,
|
| 722 |
+
"special": true
|
| 723 |
+
},
|
| 724 |
+
"32087": {
|
| 725 |
+
"content": "<extra_id_12>",
|
| 726 |
+
"lstrip": false,
|
| 727 |
+
"normalized": false,
|
| 728 |
+
"rstrip": false,
|
| 729 |
+
"single_word": false,
|
| 730 |
+
"special": true
|
| 731 |
+
},
|
| 732 |
+
"32088": {
|
| 733 |
+
"content": "<extra_id_11>",
|
| 734 |
+
"lstrip": false,
|
| 735 |
+
"normalized": false,
|
| 736 |
+
"rstrip": false,
|
| 737 |
+
"single_word": false,
|
| 738 |
+
"special": true
|
| 739 |
+
},
|
| 740 |
+
"32089": {
|
| 741 |
+
"content": "<extra_id_10>",
|
| 742 |
+
"lstrip": false,
|
| 743 |
+
"normalized": false,
|
| 744 |
+
"rstrip": false,
|
| 745 |
+
"single_word": false,
|
| 746 |
+
"special": true
|
| 747 |
+
},
|
| 748 |
+
"32090": {
|
| 749 |
+
"content": "<extra_id_9>",
|
| 750 |
+
"lstrip": false,
|
| 751 |
+
"normalized": false,
|
| 752 |
+
"rstrip": false,
|
| 753 |
+
"single_word": false,
|
| 754 |
+
"special": true
|
| 755 |
+
},
|
| 756 |
+
"32091": {
|
| 757 |
+
"content": "<extra_id_8>",
|
| 758 |
+
"lstrip": false,
|
| 759 |
+
"normalized": false,
|
| 760 |
+
"rstrip": false,
|
| 761 |
+
"single_word": false,
|
| 762 |
+
"special": true
|
| 763 |
+
},
|
| 764 |
+
"32092": {
|
| 765 |
+
"content": "<extra_id_7>",
|
| 766 |
+
"lstrip": false,
|
| 767 |
+
"normalized": false,
|
| 768 |
+
"rstrip": false,
|
| 769 |
+
"single_word": false,
|
| 770 |
+
"special": true
|
| 771 |
+
},
|
| 772 |
+
"32093": {
|
| 773 |
+
"content": "<extra_id_6>",
|
| 774 |
+
"lstrip": false,
|
| 775 |
+
"normalized": false,
|
| 776 |
+
"rstrip": false,
|
| 777 |
+
"single_word": false,
|
| 778 |
+
"special": true
|
| 779 |
+
},
|
| 780 |
+
"32094": {
|
| 781 |
+
"content": "<extra_id_5>",
|
| 782 |
+
"lstrip": false,
|
| 783 |
+
"normalized": false,
|
| 784 |
+
"rstrip": false,
|
| 785 |
+
"single_word": false,
|
| 786 |
+
"special": true
|
| 787 |
+
},
|
| 788 |
+
"32095": {
|
| 789 |
+
"content": "<extra_id_4>",
|
| 790 |
+
"lstrip": false,
|
| 791 |
+
"normalized": false,
|
| 792 |
+
"rstrip": false,
|
| 793 |
+
"single_word": false,
|
| 794 |
+
"special": true
|
| 795 |
+
},
|
| 796 |
+
"32096": {
|
| 797 |
+
"content": "<extra_id_3>",
|
| 798 |
+
"lstrip": false,
|
| 799 |
+
"normalized": false,
|
| 800 |
+
"rstrip": false,
|
| 801 |
+
"single_word": false,
|
| 802 |
+
"special": true
|
| 803 |
+
},
|
| 804 |
+
"32097": {
|
| 805 |
+
"content": "<extra_id_2>",
|
| 806 |
+
"lstrip": false,
|
| 807 |
+
"normalized": false,
|
| 808 |
+
"rstrip": false,
|
| 809 |
+
"single_word": false,
|
| 810 |
+
"special": true
|
| 811 |
+
},
|
| 812 |
+
"32098": {
|
| 813 |
+
"content": "<extra_id_1>",
|
| 814 |
+
"lstrip": false,
|
| 815 |
+
"normalized": false,
|
| 816 |
+
"rstrip": false,
|
| 817 |
+
"single_word": false,
|
| 818 |
+
"special": true
|
| 819 |
+
},
|
| 820 |
+
"32099": {
|
| 821 |
+
"content": "<extra_id_0>",
|
| 822 |
+
"lstrip": false,
|
| 823 |
+
"normalized": false,
|
| 824 |
+
"rstrip": false,
|
| 825 |
+
"single_word": false,
|
| 826 |
+
"special": true
|
| 827 |
+
}
|
| 828 |
+
},
|
| 829 |
+
"additional_special_tokens": [
|
| 830 |
+
"<extra_id_0>",
|
| 831 |
+
"<extra_id_1>",
|
| 832 |
+
"<extra_id_2>",
|
| 833 |
+
"<extra_id_3>",
|
| 834 |
+
"<extra_id_4>",
|
| 835 |
+
"<extra_id_5>",
|
| 836 |
+
"<extra_id_6>",
|
| 837 |
+
"<extra_id_7>",
|
| 838 |
+
"<extra_id_8>",
|
| 839 |
+
"<extra_id_9>",
|
| 840 |
+
"<extra_id_10>",
|
| 841 |
+
"<extra_id_11>",
|
| 842 |
+
"<extra_id_12>",
|
| 843 |
+
"<extra_id_13>",
|
| 844 |
+
"<extra_id_14>",
|
| 845 |
+
"<extra_id_15>",
|
| 846 |
+
"<extra_id_16>",
|
| 847 |
+
"<extra_id_17>",
|
| 848 |
+
"<extra_id_18>",
|
| 849 |
+
"<extra_id_19>",
|
| 850 |
+
"<extra_id_20>",
|
| 851 |
+
"<extra_id_21>",
|
| 852 |
+
"<extra_id_22>",
|
| 853 |
+
"<extra_id_23>",
|
| 854 |
+
"<extra_id_24>",
|
| 855 |
+
"<extra_id_25>",
|
| 856 |
+
"<extra_id_26>",
|
| 857 |
+
"<extra_id_27>",
|
| 858 |
+
"<extra_id_28>",
|
| 859 |
+
"<extra_id_29>",
|
| 860 |
+
"<extra_id_30>",
|
| 861 |
+
"<extra_id_31>",
|
| 862 |
+
"<extra_id_32>",
|
| 863 |
+
"<extra_id_33>",
|
| 864 |
+
"<extra_id_34>",
|
| 865 |
+
"<extra_id_35>",
|
| 866 |
+
"<extra_id_36>",
|
| 867 |
+
"<extra_id_37>",
|
| 868 |
+
"<extra_id_38>",
|
| 869 |
+
"<extra_id_39>",
|
| 870 |
+
"<extra_id_40>",
|
| 871 |
+
"<extra_id_41>",
|
| 872 |
+
"<extra_id_42>",
|
| 873 |
+
"<extra_id_43>",
|
| 874 |
+
"<extra_id_44>",
|
| 875 |
+
"<extra_id_45>",
|
| 876 |
+
"<extra_id_46>",
|
| 877 |
+
"<extra_id_47>",
|
| 878 |
+
"<extra_id_48>",
|
| 879 |
+
"<extra_id_49>",
|
| 880 |
+
"<extra_id_50>",
|
| 881 |
+
"<extra_id_51>",
|
| 882 |
+
"<extra_id_52>",
|
| 883 |
+
"<extra_id_53>",
|
| 884 |
+
"<extra_id_54>",
|
| 885 |
+
"<extra_id_55>",
|
| 886 |
+
"<extra_id_56>",
|
| 887 |
+
"<extra_id_57>",
|
| 888 |
+
"<extra_id_58>",
|
| 889 |
+
"<extra_id_59>",
|
| 890 |
+
"<extra_id_60>",
|
| 891 |
+
"<extra_id_61>",
|
| 892 |
+
"<extra_id_62>",
|
| 893 |
+
"<extra_id_63>",
|
| 894 |
+
"<extra_id_64>",
|
| 895 |
+
"<extra_id_65>",
|
| 896 |
+
"<extra_id_66>",
|
| 897 |
+
"<extra_id_67>",
|
| 898 |
+
"<extra_id_68>",
|
| 899 |
+
"<extra_id_69>",
|
| 900 |
+
"<extra_id_70>",
|
| 901 |
+
"<extra_id_71>",
|
| 902 |
+
"<extra_id_72>",
|
| 903 |
+
"<extra_id_73>",
|
| 904 |
+
"<extra_id_74>",
|
| 905 |
+
"<extra_id_75>",
|
| 906 |
+
"<extra_id_76>",
|
| 907 |
+
"<extra_id_77>",
|
| 908 |
+
"<extra_id_78>",
|
| 909 |
+
"<extra_id_79>",
|
| 910 |
+
"<extra_id_80>",
|
| 911 |
+
"<extra_id_81>",
|
| 912 |
+
"<extra_id_82>",
|
| 913 |
+
"<extra_id_83>",
|
| 914 |
+
"<extra_id_84>",
|
| 915 |
+
"<extra_id_85>",
|
| 916 |
+
"<extra_id_86>",
|
| 917 |
+
"<extra_id_87>",
|
| 918 |
+
"<extra_id_88>",
|
| 919 |
+
"<extra_id_89>",
|
| 920 |
+
"<extra_id_90>",
|
| 921 |
+
"<extra_id_91>",
|
| 922 |
+
"<extra_id_92>",
|
| 923 |
+
"<extra_id_93>",
|
| 924 |
+
"<extra_id_94>",
|
| 925 |
+
"<extra_id_95>",
|
| 926 |
+
"<extra_id_96>",
|
| 927 |
+
"<extra_id_97>",
|
| 928 |
+
"<extra_id_98>",
|
| 929 |
+
"<extra_id_99>"
|
| 930 |
+
],
|
| 931 |
+
"clean_up_tokenization_spaces": true,
|
| 932 |
+
"eos_token": "</s>",
|
| 933 |
+
"extra_ids": 100,
|
| 934 |
+
"extra_special_tokens": {},
|
| 935 |
+
"model_max_length": 512,
|
| 936 |
+
"pad_token": "<pad>",
|
| 937 |
+
"tokenizer_class": "T5Tokenizer",
|
| 938 |
+
"unk_token": "<unk>"
|
| 939 |
+
}
|
xgb_band gap bulk.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2dce1313ec3ce92b6019b8b9071f7bec96deb27eb15177c43267baac4a2a87e0
|
| 3 |
+
size 179430
|
xgb_band gap chain.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:791b1c9d7de1564baf5f04b397a4c487a334d19ca5e7828463b6b7e6facff5e5
|
| 3 |
+
size 269055
|
xgb_bandgap-crystal.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:24b0cc7edda31ac607ff8e13f259bbbaf62e995977b9c7655835806be3027f7e
|
| 3 |
+
size 150871
|
xgb_cte.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3fbb04ce5771d9dad717d7f4d7fe7234f66d8d973da74b3261805f5f2ee1a191
|
| 3 |
+
size 520320
|
xgb_gaspermability.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cc20231f90a77da7fb9f7fac05dd0aabcbfdc8b70ddc440697419fc6cd3b2a0f
|
| 3 |
+
size 443720
|
xgb_loi.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1c972fcea91d3066659327a8b3bbcab3cfe5c2aebddbf476cae71885ee71a8dd
|
| 3 |
+
size 544399
|
xgb_solubility.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5cee16a2a1010d7754801452a816c0187a4b70ade97defa1d03a7b3277d590cd
|
| 3 |
+
size 516200
|
xgb_td.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c29ca68268e50b016f0b9acab03fd47bee3deee1f690816aca805704e99fd499
|
| 3 |
+
size 7218153
|
xgb_tg.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1cbed399cb5dfe36ba48b81637f5ad5c5a6b0c2a25942abcdf232b8d09a7678d
|
| 3 |
+
size 2006300
|
xgb_thermal_cond.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:38bdd642b03d04e95ec3411eb6145e863b9e8101d79c87d0ae45ea0863b81f6a
|
| 3 |
+
size 502815
|
xgb_tm.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:54e183e50d94c6673c6ccdbb2f2bd73cc0ea7752427822b099980b81ed3eb62a
|
| 3 |
+
size 253017
|