<jupyter_start><jupyter_text>Narzędzia odtwarzalnej analizy danych    (a.k.a. Reproducible Research)            <NAME> Agenda========================================================- **Definicje**    - Repeatable vs Reproducible research     - Literate (Statistical) Programming- **Narzędzia**    - Git i Github    - Jupyter (i knitr)    - Zenodo- **Praktyczne przykłady**    - Uruchamianie skryptu    - Rysunki i wizualizacje    - Odpytywanie bazy CSD    - Analiza danych  Definicje Powtarzalność (Repeatability)Eksperyment jest powtarzalny, jeżeli inny zespół jest w stanie powtórzyć ten sam eksperyment (w możliwie tych samych warunkach) i otrzymać te same wyniki. ------------------------------------------- Odtwarzalność (Reproduciblity)Wyniki eksperymentu są odtwarzalne, jeżeli autorzy eksperymentu dzielą się danymi i pozwalają odtworzyć wszystkie opublikowane wyniki.-------------------------------------------  Spostrzeżenia**Eksperyment może być powtarzalny, ale jego wyniki nie muszą być odtwarzalne.**Przykład: Autorzy nie podzielili się zebranymi danymi na temat członków plemienia Yanomami i zaprezentowali tylko wyniki swojej analizy. Eksperyment można powtórzyć (pojechać nad Amazonkę i zebrać nowe dane), ale analizy nie można odtworzyć na tych samych danych. **Eksperyment może być niepowtarzalny, ale jego wyniki mogą być odtwarzalne.** Przykład: Autorzy zbadali zwyczaje plemienia Atakapa. Eksperymentu nie można powtórzyć, bo plemię wymarło, ale ponieważ autorzy podzielili się zebranymi danymi i spisali wszystkie kroki obliczeń, analizę można w pełni odtworzyć.  ![images/reproducibility-spectrum.png](images/reproducibility-spectrum.png) Dlaczego warto robić odtwarzalne analizy danych========================================- Niczego nie ukrywamy przed resztą świata naukowego (**transparentność**) - Inni naukowcy chętniej będą korzystali z naszych wyników (**cytowania**)- Inne osoby łatwiej znajdą błędy w naszych badaniach (**dokładność**)- Osoby z zespołu nie będą musiały nas pytać jak coś zrobiliśmy (**czas**)- Wykonanie analizy na nowych danych będzie dużo prostsze (**produktywność**)- Nie boimy się powtórzyć własnej analizy (**pewność**)*Podobne zyski dotyczą również [analiz wykonywanych w firmach](https://medium.com/airbnb-engineering/scaling-knowledge-at-airbnb-875d73eff091.rf1fniree)* Podstawy odtwarzalnej analizy danych====================================- **Zdecydować, że analiza będzie odtwarzalna**- Korzystać z repozytorium- Wykorzystać oprogramowanie, w którym można zaprogramować kolejne kroki- Pracować na surowych danych (**nie edytować niczego ręcznie**)- Nie zapisywać wyników końcowych- Korzystać z otwartych formatów danych Literate Programming==================- Pomysł autorstwa [<NAME>](https://pl.wikipedia.org/wiki/Donald_Knuth)- Artykuł jako strumień tekstu i kodu- Potrzebny język programowania i język do dokumentacji - Kod podzielony na fragmenty- Opis tłumaczący co się po kolei dzieje- Z artykułu można wyciągnąć tylko kod albo zostawić tylko opis- Przykłady: [LaTeX](https://en.wikipedia.org/wiki/LaTeX), [Sweave](https://en.wikipedia.org/wiki/Sweave), [knitr](http://yihui.name/knitr/), [Jupyter](https://jupyter.org/) Git====- Git to **system kontroli wersji**- Pomaga śledzić hietorię zmian w plikach- Po edycji pliku potrafi pokazać **kto** zmienił **co** i **dlaczego**- Ułatwia współpracę wielu osób nad jednym projektem - Typowo używany do pracy nad kodem, ale można go też wykorzystywać do prac nad:    - projektem graficznym,    - projektem architektonicznym,    - analizą danych,    - dokumentami,    - materiałami dydaktycznymi... Git====- Tradycyjnie obsługiwany z linii poleceń - Istnieją też narzędzia graficzne (np. [TortoiseGit](https://tortoisegit.org/) albo [GitHub Desktop](https://desktop.github.com/))- Podstawowe operacje:    - **commit** zrób checkpoint lokalnie na dysku     - **push** zapisz zmiany na serwerze zewnętrznym    - **pull** wczytanie zmian z serwera zewnętrznego    - **revert** cofnięcie zmian do wybranego checkpointa    - **diff** porównaj zmiany Demo===== ![demo](images/examples.png) GitHub======- Najpopularniejsze otwarte repozytorium kodu  - Serwer zewnętrzny dla repozytoriów Git- Darmowe dla publicznych projektów- Standard współpracy nad otwartymi projektami informatycznymi    - Możliwość zgłaszania błędów    - Możliwość zgłaszania poprawek    - Wersjonowanie Github======[![github-example.png](images/github-example.png)](https://github.com/dabrze/CheckMyBlob) Jupyter======= - Jedna z implementacji idei Literate Programming- Najpopularniejsze narzędzie dla powtarzalnych analiz w języku Python- Obsługuje tez inne języki (**Ju**=Julia, **pyt**=Python, **er**=R)- Tekst i kod powiązane w **notatnikach** (ang. notebook)- Do pisania tekstu wykorzystywany jest język **Markdown**- Działa w przeglądarce (**możliwość pracy zdalnej**) Jupyter (dashboard)=================![demo](images/jupyter-dashboard.png) Jupyter (notebook)================![demo](images/jupyter-notebook.png) Demo=====![demo](images/examples.png) Zenodo======- Darmowe repozytorium danych naukowych - Serwery hostowane przez CERN- Każdy wgrany element otrzymuje własne DOI- Pliki wgrane na Zenodo będą dostępne i łatwo wyszukiwalne przez lata- Integracja z GitHub Przykłady========- Na kolejnych slajdach przedstawione zostaną przykłady wykorzystania notatników Jupyter- Przykłady zostały dobrane tak, aby miały związek z krystalografią- Można oczywiście wykorzystać notatniki do wielu innych zadań! Uruchamianie skryptu==================Za pomocą jupyter notebooka można pokazać innym autorom kolejne kroki, które wykonano w trakcie analizy. Ponieważ notatniki można uruchamiać, inni naukowcy mogą łatwo powtórzyć te kroki samemu. Pomysły na wykorzystanie: refmac, phenix, XDS, pymol, ...<jupyter_code># cat ./Reproducible research.ipynb | wc -l
!findstr /R /N "^" "Reproducible research.ipynb"  | find /c /v ""<jupyter_output>2532<jupyter_text>Uruchamianie skryptu==================<jupyter_code>PHENIX_BIN = "C:/Tools/Crystallography/Phenix/phenix-installer-1.14-3260-intel-windows-x86_64/build/bin/"
PDB = "data/ISO2-1_6A_refine_96.pdb"
MTZ = "data/ISO2-1_6A_refine_96.mtz"
CIF = "data/IC-IG-QM-paired-lib.cif"
OPTIONS = "main.random_seed=7 main.number_of_macro_cycles=0"

cmd = "{0}phenix.refine {1} {2} {3} {4}".format(PHENIX_BIN, MTZ, PDB, CIF, OPTIONS)
!{cmd}<jupyter_output># Date 2019-06-07 Time 09:48:01 Środkowoeuropejski czas letni +0200 (1559893681.56 s)
#phil __OFF__

Command line arguments: "data/ISO2-1_6A_refine_96.mtz" "data/ISO2-1_6A_refine_96.pdb" "data/IC-IG-QM-paired-lib.cif" "main.random_seed=7" "main.number_of_macro_cycles=0"

COMPUTERNAME = KERMIT
PROCESSOR_ARCHITECTURE = AMD64
USERNAME = Lenovo
PID = 14512

-------------------------------------------------------------------------------
  PHENIX: Python-based Hierarchical ENvironment for Integrated Xtallography
  Version: 1.14
  Release tag: 3260
  Platform: intel-windows-x86_64
  User: Lenovo
-------------------------------------------------------------------------------

              phenix.refine: Macromolecular Structure Refinement

-------------------------------------------------------------------------------

Phenix developers include:
  <NAME>, <NAME>, <NAME>, <NAME>, <NAME>, 
  <NAME>, <NAME>, <NAME>, <NAME>, <NAME>, 
  P[...]<jupyter_text>Rysunki i wizualizacje==================Notatniki pozwalają w łatwy sposób pokazać jak uzyskano daną wizualizację. Jest to sposób na udowodnienie, że wykresy są oparte na danych eksperymentalnych i nie były w żaden sposób ręcznie modyfikowane.<jupyter_code>import nglview as nv
w = nv.show_pdbid("3pqr")
w<jupyter_output><empty_output><jupyter_text>Odpytywanie baz danych======================W notatniku można pokazać jak działając na danych bezpośrednio z bazy (np. CSD albo PDB) uzyskano wyniki przedstawiane w pracy naukowej.<jupyter_code>%matplotlib inline 
from ccdc import io
from ccdc.diagram import DiagramGenerator
from ccdc.search import TextNumericSearch, SubstructureSearch, ConnserSubstructure

csd_reader = io.EntryReader('CSD') # można podać własną (pod)bazę CSD
first_entry = csd_reader[0]

# pierwszy wpis w bazie CSD
print(first_entry.identifier)<jupyter_output>AABHTZ<jupyter_text>Odpytywanie baz danych (diagramy)==============================Znalezioną strukturę można zwizualizować...<jupyter_code>diagram_generator = DiagramGenerator()
img = diagram_generator.image(first_entry)
img<jupyter_output><empty_output><jupyter_text>Odpytywanie baz danych (przeszukiwanie tekstowe)===========================================CSD można oczywiście przeszukiwać tekstowo (również po synonimach)...<jupyter_code>text_numeric_search = TextNumericSearch()

text_numeric_search.add_compound_name('aspirin')
identifiers = [h.identifier for h in text_numeric_search.search()]

text_numeric_search.clear()
text_numeric_search.add_synonym('aspirin')
identifiers.extend([h.identifier for h in text_numeric_search.search()])

print(identifiers)<jupyter_output>['ACMEBZ', 'ACSALA', 'ACSALA01', 'ACSALA02', 'ACSALA03', 'ACSALA04', 'ACSALA05', 'ACSALA06', 'ACSALA07', 'ACSALA08', 'ACSALA09', 'ACSALA10', 'ACSALA11', 'ACSALA12', 'ACSALA13', 'ACSALA14', 'ACSALA15', 'ACSALA16', 'ACSALA17', 'ACSALA18', 'ACSALA19', 'ACSALA20', 'ACSALA21', 'ACSALA22', 'ACSALA23', 'ACSALA24', 'ACSALA25', 'ARIFOX', 'ASPRIN', 'BEHWOA', 'CUASPR', 'CUASPR01', 'CUASPR02', 'DIFHOP', 'DIFQAK', 'DISXOU', 'ECONOA', 'EYOMEL', 'EYOMIP', 'EYOMOV', 'EYOMUB', 'EYONAI', 'HUNJEH', 'HUPPOX', 'HUPPOX01', 'IBOBUY', 'IBOBUY01', 'IBOCEJ', 'IBOCEJ01', 'IBOCOT', 'IBOCOT01', 'JIRNEE', 'KEWNOQ', 'KEWNOQ01', 'KICVUP', 'LAJVUO01', 'NINFUN', 'NUKXOH', 'NUWTIJ01', 'NUWTOP01', 'NUWTOP02', 'OKEZUZ', 'PETZAQ', 'PETZIY', 'PETZOE', 'PETZUK', 'PIKYOA', 'PIKYUG', 'PIKZAN', 'SIBYUA', 'SIBYUA01', 'TAZRAO', 'TORQUM02', 'UTUCIW', 'VUGMIT', 'XOJMOZ', 'YIRPEW', 'YOSMOI', 'DIPJAQ', 'TAZRAO01', 'TAZRAO02', 'ACMEBZ', 'ACSALA', 'ACSALA01', 'ACSALA02', 'ACSALA03', 'ACSALA04', 'ACSALA05', 'ACSALA06', 'ACSALA07', 'ACSA[...]<jupyter_text>Odpytywanie baz danych (przeszukiwanie tekstowe)================================================<jupyter_code>aspiryna = csd_reader.entry('ACMEBZ')
img = diagram_generator.image(aspiryna)
img<jupyter_output><empty_output><jupyter_text>Odpytywanie baz danych (zapytania graficzne)======================================Można również zadawać zapytania dotyczące geometrii cząsteczek. W tym celu najłatwiej "wyklikać" zapytanie w programie CONQUEST. Przykład zapytania poniżej: Odpytywanie baz danych (zapytania graficzne)======================================<jupyter_code>con_substructure = ConnserSubstructure("data/adenine.con")
substructure_search = SubstructureSearch()
substructure_search.add_substructure(con_substructure)
hits = substructure_search.search()

print("Znaleziono {0} struktur pasujących do zapytania".format(hits.__len__()))<jupyter_output>Znaleziono 437 struktur pasujących do zapytania<jupyter_text>Odpytywanie baz danych (analiza wyników)======================================<jupyter_code>import pandas as pd
import numpy as np

df = pd.DataFrame([h.measurements for h in hits], index=list([h.identifier + "_" + str(idx) for idx, h in enumerate(hits)]))
df.head()<jupyter_output><empty_output><jupyter_text>Odpytywanie baz danych (analiza wyników)======================================<jupyter_code>bonds = ['N1_C2', 'C2_N3', 'N3_C4', 'C4_C5', 'C5_C6', 'N1_C6', 'C5_N7', 'N7_C8', 'C8_N9', 'N9_C', 'C6_NH']
df.loc[:, bonds].hist(bins=20, figsize=(16, 8), grid=False, layout=(3,4));<jupyter_output><empty_output><jupyter_text>Analiza danych=============Jako przykład spróbujemy przeanalizować jakość struktur w PDB z podziałem na rozdzielczość, lata i czasopisma. *Dane dzięki uprzejmości Zbyszka Dautera*<jupyter_code># wczytujemy dane z plików
pdb_df = pd.read_fwf("data/percentiles_all.diffr", names=["PDB code", "Resolution", "Date", "Rfree_percentile_abs", "Clash_percentile_abs", "Ramachandran_percentile_abs", "Rota_percentile_abs", "RSRZ_percentile_abs", "Rfree_percentile_rel", "Clash_percentile_rel", "Ramachandran_percentile_rel", "Rota_percentile_rel", "RSRZ_percentile_rel", "Rfree_raw", "Clash_raw", "Ramachandran_raw", "Rota_raw", "RSRZ_raw"], na_values="NotAv", infer_nrows=10000)
journal_df = pd.read_fwf("data/journ.all_xray", names=["PDB code", "Journal", "Volume", "Page", "Publication year"], infer_nrows=10000)

pdb_df.head()<jupyter_output><empty_output><jupyter_text>Analiza danych=============<jupyter_code># łączymy zbiory danych
merged_df = pd.merge(pdb_df, journal_df, on="PDB code")

# zostawiamy tylko wybrane kolumny i wiersze bez wartości pustych
merged_df = merged_df.loc[:, ["PDB code", "Resolution", "Date", "RSRZ_raw", "Journal", "Publication year"]]
merged_df = merged_df.dropna()

# czyścimy dane i nazwy kolumn
merged_df.loc[:, "Date"]  = merged_df.loc[:, "Date"].apply(str).str.slice(stop=4).apply(int)
merged_df.loc[:, "Publication year"] = merged_df.loc[:, "Publication year"].astype(int)
merged_df.loc[:, "Resolution"] = merged_df.loc[:, "Resolution"].round(decimals=1)
merged_df = merged_df.rename(index=str, columns={"RSRZ_raw": "RSR Z-score", "Date": "Year"})

merged_df.head()<jupyter_output><empty_output><jupyter_text>Analiza danych=============<jupyter_code>from plotnine import *
import plotnine.options
plotnine.options.figure_size = (10, 5)

resolution_df = merged_df.groupby(['Resolution'], as_index=False).mean()
(ggplot(resolution_df, aes(x="Resolution", y="RSR Z-score")) + geom_point() + theme_bw()).draw();<jupyter_output><empty_output><jupyter_text>Analiza danych=============<jupyter_code>year_df = merged_df.groupby(['Year'], as_index=False).mean()
(ggplot(year_df, aes(x="Year", y="RSR Z-score")) + geom_point() + theme_bw()).draw();<jupyter_output><empty_output><jupyter_text>Analiza danych=============<jupyter_code>venue_count_df = merged_df.groupby(['Journal'], as_index=False).size()
popular_venues = venue_count_df[venue_count_df >= 20].index
venue_df = merged_df.loc[merged_df.Journal.isin(popular_venues), :].groupby(['Journal'], as_index=False).mean()

top_ten = venue_df.sort_values(by="RSR Z-score", ascending=True).head(20)
top_ten['Journal'] = pd.Categorical(top_ten['Journal'], categories=top_ten.Journal)

(ggplot(top_ten, aes(x="Journal", y="RSR Z-score")) + geom_bar(stat="identity") 
    + theme_bw() + theme(axis_text_x = element_text(angle = 90))).draw();<jupyter_output><empty_output><jupyter_text>Analiza danych=============<jupyter_code>bottom_ten = venue_df.sort_values(by="RSR Z-score", ascending=False).head(20)
bottom_ten['Journal'] = pd.Categorical(bottom_ten['Journal'], categories=bottom_ten.Journal)

(ggplot(bottom_ten, aes(x="Journal", y="RSR Z-score")) + geom_bar(stat="identity") + theme_bw() 
    + theme(axis_text_x = element_text(angle = 90))).draw();<jupyter_output><empty_output><jupyter_text>Analiza danych=============<jupyter_code>year_venue_df = merged_df.loc[merged_df.Journal.isin(['FEBS J.', 'SCIENCE', 'NATURE', 'ACTA CRYSTALLOGR.,SECT.D']), :]\
    .groupby(['Year', 'Journal'], as_index=False).median()

(ggplot(year_venue_df, aes(x="Year", y="RSR Z-score", color="Journal")) + geom_point() +
    facet_grid('.~Journal') + geom_smooth(method="glm") + theme_bw()).draw();<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.18420880057708702, 'fraction_numerical': 0.016591251885369532, 'mean_word_length': 6.15962441314554, 'pattern_counts': {'":': 2, '<': 76, '<?xml version=': 0, '>': 77, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '17', 'dir': 'jupyter-structured-clean-dedup', 'id': '136516', 'license': 'MIT', 'n_tokens_mistral': 6176, 'n_tokens_neox': 5997, 'n_words': 1195, 'path': 'Reproducible research.ipynb', 'repo_name': 'dabrze/cbb_reproducibility', 'size': '15329'}