Data Programming Course  Check-in [b00e2b9dd2]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:correzioni delle slide della lezione 7
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:b00e2b9dd29b26e2486f57a60b82321848987d13
User & Date: EnricoGiampieri 2017-03-14 08:04:18
Context
2017-03-16
15:17
spostata la lezione sul profiling come lezione extra check-in: 1a5d1a0f98 user: EnricoGiampieri tags: trunk
2017-03-14
08:04
correzioni delle slide della lezione 7 check-in: b00e2b9dd2 user: EnricoGiampieri tags: trunk
2017-03-13
23:30
aggiunta l'immagine svg necessaria per la lezione 7 check-in: 08339bafe1 user: EnricoGiampieri tags: trunk
Changes

Changes to Lezione 7 - Data pipeline e Snakemake.html.

11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
.....
11984
11985
11986
11987
11988
11989
11990
11991

11992
11993
11994
11995
11996
11997
11998
.....
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
.....
12130
12131
12132
12133
12134
12135
12136



































































12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147

12148
12149
12150
12151
12152
12153
12154
.....
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181

12182
12183
12184
12185
12186
12187
12188
12189
12190


















12191
12192
12193
12194
12195
12196
12197
12198
.....
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
.....
12247
12248
12249
12250
12251
12252
12253
12254
12255




















12256

















12257
12258
12259
12260
12261
12262
12263
.....
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332

<pre><code>nome;età;abitazione
Antonio;32;Bologna
Maria;25;Torino
Francesco;47;Napoli

</code></pre>
<p>Permettono di inserire commenti (tipicamente con #) e possono essere aperti ed editati facilmente con programmi con Excel, ma possono contenere solo dati in formato tabella</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="JSON">JSON<a class="anchor-link" href="#JSON">&#182;</a></h4><p>formato standard di condivisione dati su internet, è molto utile per rappresentare dati gerarchici. Corrisponde sostanzialmente ad una dizionario di dizionari in termini di python, ed ha praticamente la stessa sintassi.</p>

<pre><code>{"persone":
    {"antonio": {"età": "32", "abitazione": "Bologna"},
     "maria": {"età": "20", "abitazione": "Cesena"},
     }
}</code></pre>

................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="immagini-lossless:-bmp,-png,-gif,-tiff">immagini lossless: bmp, png, gif, tiff<a class="anchor-link" href="#immagini-lossless:-bmp,-png,-gif,-tiff">&#182;</a></h4><p>Questi formati contengono i valori di colore contenuti in un'immagine con diversi tipi di compressione, senza però perdere alcuna informazione, al contrario di formati come il jpeg, che andrebbe quindi evitato per lo storage di immagini</p>


</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="hashing-dei-file">hashing dei file<a class="anchor-link" href="#hashing-dei-file">&#182;</a></h4><p>Una operazione molto comune nella data analisi è il cosiddetto hasing.</p>
<p>Questo consiste nella generazione di una stringa alfanumerica (tipicamente di qualche centinaio di caratteri) a partire dal contenuto del file.</p>
<p>Gli algoritmi di hash garantiscono che piccole modifiche del contenuto del file comporti grandi variazioni dell'hash, permettendo di usare queste stringhe per garantire l'integrità dei dati.</p>
<p>Esistono diversi algoritmi per la generazione dell'hash (SHA1, md5, sha512, etc...) per cui l'algoritmo di calcolo dovrebbe essere riportato insieme all'hash</p>
<p>I sistemi di controllo di versione usano internamente gli hash dei file per verificare se questi sono cambiati o meno.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[23]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">hashlib</span>

<span class="n">stringa1</span> <span class="o">=</span> <span class="s2">&quot;sono una stringa di testo completamente 1nnocente&quot;</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf8&#39;</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">stringa1</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;md5: </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
................................................................................
</pre>
</div>
</div>

</div>
</div>




































































</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Data-Pipeline">Data Pipeline<a class="anchor-link" href="#Data-Pipeline">&#182;</a></h2><p>Ora che abbiamo un'idea di come siano fatti i dati, possiamo discutere di come questi dati possano venir messi insieme in una pipeline.</p>
<p>Per semplicità, li possiamo inserire in una gerarchia di rilevanza:</p>
<ol>
<li>Metadati</li>
<li>raw data</li>

<li>source data</li>
<li>usage data</li>
<li>intermediate data</li>
<li>temporary data</li>
</ol>
<p>Questi nomi non sono formali, solo un modo per discuterne fra di noi, ma rispecchiano molto bene la tipica procedura di analisi.</p>

................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="0---Metadati">0 - Metadati<a class="anchor-link" href="#0---Metadati">&#182;</a></h3><p>Dati a proposito dei dati.</p>
<p>Tipicamente un file di testo semplice, che descrive il motivo per cui i dati sono stati presi, chi li ha raccolti, quando e con che metodi.</p>
<p>Può sembrare banale, ma a distanza di qualche anno potreste trovarvi un disco pieno di dati di cui non capite la ragione d'essere.</p>
<p>Un dato di cui non si conosce il motivo di esistere ha lo stesso valore di un dato cancellato.</p>
<p>Spesso riporta anche l'hashing dei dati RAW per garantire di poterne verificare l'integrità.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="1---Raw-data">1 - Raw data<a class="anchor-link" href="#1---Raw-data">&#182;</a></h3><p>Questi sono i dati originari dei vostri esperimenti. Non li userete direttamente nelle vostre analisi.
Potrebbero essere nei formati più strampalati, a seconda dell'output dello strumento di misura.</p>
<p>Questi dati sono <strong>SACRI</strong>.</p>
<p>Vanno conservati scrupolosamente e non modificati.</p>
<p>Se si dovessero avere nuove versioni (ad esempio una misura è stata ripetuta ed aggiornata) non sovrascriveteli, ma tenete le varie versioni.</p>


</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">


















<h3 id="2---Source-data">2 - Source data<a class="anchor-link" href="#2---Source-data">&#182;</a></h3><p>Una volta ottenuti i raw data, processateli tramite uno script in un formato decente.
Tramite questo script potrete unire eventuali file frammentati (ad esempio da un file per persona ad un dataset unico), correggere errori nei raw data (non dovete andare a modificarli alla fonte!) e mettere il tutto in una struttura che possa essere mantenuta a lungo. La mia preferenza è per formati di testo come il csv.</p>
<p>Lo script di generazione è più importante dei dati risultanti!</p>
<p>In questa fase dovete mantenere i dati il più possibile aderenti alle informazioni dei file RAW.
Non fate detrending, normalizzazioni o altre modifiche, solo trasportarli in un formato ragionevole.</p>
<p>Se i RAW fossero già ben formattati e strutturati e corretti, potete considerarli direttamente dei source.
Non capita mai, non sperateci.
Quando capita di solito vi stanno mentendo e non sono davvero i RAW ma dei dati già processati.</p>
................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="3---Usage-data">3 - Usage data<a class="anchor-link" href="#3---Usage-data">&#182;</a></h3><p>Qui iniziamo effettivamente la nostra analisi.</p>
<p>A partire dai dati source, possiamo comporre i dati nel formato più comodo per le analisi che abbiamo in mente, senza doverci preoccupare di cose come la normalizzazione delle tabelle del database e simili.</p>
<p>Tipicamente questi dati saranno generati solo una volta, a meno che non si riscontrino dei problemi nell'analisi (nel qual caso sarà necessario tornare indietro ai source data e capire cosa sia andato storto).</p>
<p>Diverse analisi potrebbero aver bisogno di diversi usage data.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="4---Intermediate-Data">4 - Intermediate Data<a class="anchor-link" href="#4---Intermediate-Data">&#182;</a></h3><p>La vostra analisi sarà tipicamente composta da diverse fasi, quali la normalizzazione dei dati, il detrending, e così via.</p>
<p>Dopo ciascuno di questi step è solitamente buona pratica tener traccia dei risultati in dei file intermedi, in modo da poter riprendere l'analisi da qualsiasi step intermedio senza dover ripartire da capo.</p>
<p>Di solito l'unico inconveniente della perdita di questi dati è il tempo necessario per ripetere l'analisi.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="5---Temporary-data">5 - Temporary data<a class="anchor-link" href="#5---Temporary-data">&#182;</a></h3><p>Questi dati sono il risultato intermedio delle analisi, ma con il preciso obiettivo di essere rimossi alla fine di ogni step.</p>
<p>Ad esempio potrebbero essere generati da un algoritmo parallelo distribuito che analizza un paziente alla volta, per poi ricomporre i risultati in un'unica tabella che li contiene tutti. Una volta generata la tabella complessiva, non c'è ragione di tenere le tabelle dei singoli pazienti in giro a consumare spazio, e vanno quindi eliminate.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
................................................................................

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">




















<p>La struttura fondamentale di Snakemake è una <strong>regola</strong>, che rappresenta un programma (tipicamente uno script), i file che ha bisogno di avere in input e quelli che restituirà in output.</p>

















<p>Se il file di output della regola esiste già, la regola non viene eseguita (a meno di non constringerlo).</p>
<p>Se il file di input della regola non esiste, snakemake cerca un'altra regola che abbia quel file come output e la esegue prima.</p>
<p>Questa è una struttura chiamata <strong>pull</strong> (in cui specifico il punto di arrivo), e richiede un po' di tempo per prenderci confidenza (lo standard della programmazione è di tipo <strong>push</strong>, in cui specifico il punto di partenza).</p>

</div>
</div>
</div>
................................................................................
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Uno snakefile è diviso in regole.</p>
<p>Ciascuna regola viene eseguita come un nuovo processo python a se stante.</p>
<p>Una regola ha delle sotto sezioni, di cui le più importanti sono:</p>
<ul>
<li>output: la lista dei file che la regola genererà in output (è una promessa, vanno poi effettivamente creati)</li>
<li>input: la lista dei file che la regola richiede</li>
<li>shell/run: esegue uno o più comandi di shell oppure esegue del codice python arbitrario</li>
</ul>
<p>Di default, se non si specifica altro, snakemake cerca di eseguire la regola <strong>all</strong></p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[41]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="o">%%</span><span class="k">file</span> Snakefile







|









|







 







|
>







 







|










|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|

>







 







|













|




>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







 







|












|











|







 









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
.....
11984
11985
11986
11987
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
.....
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
.....
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
.....
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
.....
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
.....
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
.....
12426
12427
12428
12429
12430
12431
12432


















12433
12434
12435
12436
12437
12438
12439

<pre><code>nome;età;abitazione
Antonio;32;Bologna
Maria;25;Torino
Francesco;47;Napoli

</code></pre>
<p>Permettono di inserire commenti (tipicamente con #) e possono essere aperti ed editati facilmente con programmi come Excel, ma possono contenere solo dati in formato tabella</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="JSON">JSON<a class="anchor-link" href="#JSON">&#182;</a></h4><p>formato standard di condivisione dati su internet, è molto utile per rappresentare dati gerarchici. Corrisponde sostanzialmente ad una dizionario di dizionari (in termini di python), ed ha praticamente la stessa sintassi.</p>

<pre><code>{"persone":
    {"antonio": {"età": "32", "abitazione": "Bologna"},
     "maria": {"età": "20", "abitazione": "Cesena"},
     }
}</code></pre>

................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="immagini-lossless:-bmp,-png,-gif,-tiff">immagini lossless: bmp, png, gif, tiff<a class="anchor-link" href="#immagini-lossless:-bmp,-png,-gif,-tiff">&#182;</a></h4><p>Questi formati contengono i valori di colore contenuti in un'immagine con diversi tipi di compressione, senza però perdere alcuna informazione, al contrario di formati come il jpeg, che andrebbe quindi evitato per lo storage di immagini.</p>
<p>Se il vostro dato è un plot e non un'immagine generica, considerate l'uso del formato SVG, che permette modificazioni successive con più facilità.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="hashing-dei-file">hashing dei file<a class="anchor-link" href="#hashing-dei-file">&#182;</a></h4><p>Una operazione molto comune nella data analisi è il cosiddetto hashing.</p>
<p>Questo consiste nella generazione di una stringa alfanumerica (tipicamente di qualche centinaio di caratteri) a partire dal contenuto del file.</p>
<p>Gli algoritmi di hash garantiscono che piccole modifiche del contenuto del file comporti grandi variazioni dell'hash, permettendo di usare queste stringhe per garantire l'integrità dei dati.</p>
<p>Esistono diversi algoritmi per la generazione dell'hash (SHA1, md5, sha512, etc...) per cui l'algoritmo di calcolo dovrebbe essere riportato insieme all'hash</p>
<p>I sistemi di controllo di versione usano internamente gli hash dei file per verificare se questi sono cambiati o meno.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[2]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">hashlib</span>

<span class="n">stringa1</span> <span class="o">=</span> <span class="s2">&quot;sono una stringa di testo completamente 1nnocente&quot;</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf8&#39;</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">stringa1</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;md5: </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
................................................................................
</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[4]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="o">!</span>md5sum ./Snakefile
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>

<div class="output_subarea output_stream output_stdout output_text">
<pre>fcdcdbda6cc42ee8fac608ed9e2d4391  ./Snakefile
</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[6]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">md5</span><span class="p">(</span><span class="n">fname</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;funzione di hash dei file appropriata anche per i big data&quot;&quot;&quot;</span>
    <span class="n">hash_md5</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">()</span>
    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">chunk</span> <span class="ow">in</span> <span class="nb">iter</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">4096</span><span class="p">),</span> <span class="sa">b</span><span class="s2">&quot;&quot;</span><span class="p">):</span>
            <span class="n">hash_md5</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">hash_md5</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>

<span class="n">hash_result</span> <span class="o">=</span> <span class="n">md5</span><span class="p">(</span><span class="s2">&quot;Snakefile&quot;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">hash_result</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>

<div class="output_subarea output_stream output_stdout output_text">
<pre>fcdcdbda6cc42ee8fac608ed9e2d4391
</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Data-Pipeline">Data Pipeline<a class="anchor-link" href="#Data-Pipeline">&#182;</a></h2><p>Ora che abbiamo un'idea di come siano fatti i dati, possiamo discutere di come questi dati possano venir messi insieme in una pipeline.</p>
<p>Per semplicità, li possiamo inserire in una gerarchia di rilevanza:</p>
<ol>
<li>metadati</li>
<li>raw data</li>
<li>codice sorgente</li>
<li>source data</li>
<li>usage data</li>
<li>intermediate data</li>
<li>temporary data</li>
</ol>
<p>Questi nomi non sono formali, solo un modo per discuterne fra di noi, ma rispecchiano molto bene la tipica procedura di analisi.</p>

................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="1---metadati">1 - metadati<a class="anchor-link" href="#1---metadati">&#182;</a></h3><p>Dati a proposito dei dati.</p>
<p>Tipicamente un file di testo semplice, che descrive il motivo per cui i dati sono stati presi, chi li ha raccolti, quando e con che metodi.</p>
<p>Può sembrare banale, ma a distanza di qualche anno potreste trovarvi un disco pieno di dati di cui non capite la ragione d'essere.</p>
<p>Un dato di cui non si conosce il motivo di esistere ha lo stesso valore di un dato cancellato.</p>
<p>Spesso riporta anche l'hashing dei dati RAW per garantire di poterne verificare l'integrità.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="2---Raw-data">2 - Raw data<a class="anchor-link" href="#2---Raw-data">&#182;</a></h3><p>Questi sono i dati originari dei vostri esperimenti. Non li userete direttamente nelle vostre analisi.
Potrebbero essere nei formati più strampalati, a seconda dell'output dello strumento di misura.</p>
<p>Questi dati sono <strong>SACRI</strong>.</p>
<p>Vanno conservati scrupolosamente e non modificati.</p>
<p>Se si dovessero avere nuove versioni (ad esempio una misura è stata ripetuta ed aggiornata) non sovrascriveteli, ma tenete le varie versioni.</p>
<p>Dal punto di vista di FOSSIL per il controllo di versione, questo tipo di dati può essere tenuto nel repository come <strong>unversioned</strong>, visto che non dovrebbe essere modificato.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="3---Codice-sorgente">3 - Codice sorgente<a class="anchor-link" href="#3---Codice-sorgente">&#182;</a></h3><p>Può sembrare banale, ma il vostro codice rappresenta comunque informazione a proposito del problema:</p>
<ul>
<li>come vanno letti e manipolati i dati?</li>
<li>come correggere gli errori? </li>
<li>a cosa bisogna stare attenti?</li>
<li>quali sono le analisi già fatte?</li>
</ul>
<p>Queste informazioni meritano di essere trattate come dati a tutti gli effetti, e sono quasi altrettanto importanti dei raw data.</p>
<p>È per questo che esiste il controllo di versione, usatelo!</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="4---Source-data">4 - Source data<a class="anchor-link" href="#4---Source-data">&#182;</a></h3><p>Una volta ottenuti i raw data, processateli tramite uno script in un formato decente.
Tramite questo script potrete unire eventuali file frammentati (ad esempio da un file per persona ad un dataset unico), correggere errori nei raw data (non dovete andare a modificarli alla fonte!) e mettere il tutto in una struttura che possa essere mantenuta a lungo. La mia preferenza è per formati di testo come il csv.</p>
<p>Lo script di generazione è più importante dei dati risultanti!</p>
<p>In questa fase dovete mantenere i dati il più possibile aderenti alle informazioni dei file RAW.
Non fate detrending, normalizzazioni o altre modifiche, solo trasportarli in un formato ragionevole.</p>
<p>Se i RAW fossero già ben formattati e strutturati e corretti, potete considerarli direttamente dei source.
Non capita mai, non sperateci.
Quando capita di solito vi stanno mentendo e non sono davvero i RAW ma dei dati già processati.</p>
................................................................................
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="5---Usage-data">5 - Usage data<a class="anchor-link" href="#5---Usage-data">&#182;</a></h3><p>Qui iniziamo effettivamente la nostra analisi.</p>
<p>A partire dai dati source, possiamo comporre i dati nel formato più comodo per le analisi che abbiamo in mente, senza doverci preoccupare di cose come la normalizzazione delle tabelle del database e simili.</p>
<p>Tipicamente questi dati saranno generati solo una volta, a meno che non si riscontrino dei problemi nell'analisi (nel qual caso sarà necessario tornare indietro ai source data e capire cosa sia andato storto).</p>
<p>Diverse analisi potrebbero aver bisogno di diversi usage data.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="6---Intermediate-Data">6 - Intermediate Data<a class="anchor-link" href="#6---Intermediate-Data">&#182;</a></h3><p>La vostra analisi sarà tipicamente composta da diverse fasi, quali la normalizzazione dei dati, il detrending, e così via.</p>
<p>Dopo ciascuno di questi step è solitamente buona pratica tener traccia dei risultati in dei file intermedi, in modo da poter riprendere l'analisi da qualsiasi step intermedio senza dover ripartire da capo.</p>
<p>Di solito l'unico inconveniente della perdita di questi dati è il tempo necessario per ripetere l'analisi.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="7---Temporary-data">7 - Temporary data<a class="anchor-link" href="#7---Temporary-data">&#182;</a></h3><p>Questi dati sono il risultato intermedio delle analisi, ma con il preciso obiettivo di essere rimossi alla fine di ogni step.</p>
<p>Ad esempio potrebbero essere generati da un algoritmo parallelo distribuito che analizza un paziente alla volta, per poi ricomporre i risultati in un'unica tabella che li contiene tutti. Una volta generata la tabella complessiva, non c'è ragione di tenere le tabelle dei singoli pazienti in giro a consumare spazio, e vanno quindi eliminate.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
................................................................................

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Snakamake è solo uno dei tanti sistemi di gestione delle pipeline di dati.</p>
<p>È quello che reputo più vicino ai nostri bisogni, ma vi invito a guardare anche gli altri.</p>
<p>Alcuni esempi famosi sono:</p>
<ul>
<li>Luigi</li>
<li>Apache Airflow</li>
<li>BigDataScript</li>
<li>Dask</li>
<li>Nextflow</li>
</ul>
<p>una lista molto comprensiva la trovate alla pagina <a href="https://github.com/pditommaso/awesome-pipeline">awesome-pipeline</a></p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>La struttura fondamentale di Snakemake è una <strong>regola</strong>, che rappresenta un programma (tipicamente uno script), i file che ha bisogno di avere in input e quelli che restituirà in output.</p>
<p>Ciascuna regola viene eseguita come un nuovo processo python a se stante.</p>
<p>Una regola ha delle sotto sezioni, di cui le più importanti sono:</p>
<ul>
<li>output: la lista dei file che la regola genererà in output (è una promessa, vanno poi effettivamente creati)</li>
<li>input: la lista dei file che la regola richiede</li>
<li>shell/run: esegue uno o più comandi di shell oppure esegue del codice python arbitrario</li>
</ul>
<p>Di default, se non si specifica altro, snakemake cerca di eseguire la regola <strong>all</strong></p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Se il file di output della regola esiste già, la regola non viene eseguita (a meno di non constringerlo).</p>
<p>Se il file di input della regola non esiste, snakemake cerca un'altra regola che abbia quel file come output e la esegue prima.</p>
<p>Questa è una struttura chiamata <strong>pull</strong> (in cui specifico il punto di arrivo), e richiede un po' di tempo per prenderci confidenza (lo standard della programmazione è di tipo <strong>push</strong>, in cui specifico il punto di partenza).</p>

</div>
</div>
</div>
................................................................................
</div>

</div>

</div>
</div>



















</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[41]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="o">%%</span><span class="k">file</span> Snakefile

Changes to Lezione 7 - Data pipeline e Snakemake.ipynb.

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
285
286
287
288
289
290
291
292


293
294
295
296
297
298
299
...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
426
427
428
429
430
431
432





















































433
434
435
436
437
438
439
...
442
443
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458
459
460
461
...
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501


502
503
504
505
506






















507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
...
601
602
603
604
605
606
607























608
609
610
611
612
613
614
615
616





















617
618
619
620
621
622
623
...
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
767
768
769
770
771
772
773


774
775
776
777
778
779
780
...
887
888
889
890
891
892
893
894



895
896
897
898
899
900
901
...
960
961
962
963
964
965
966


967
968
969
970
971
972
973
....
1303
1304
1305
1306
1307
1308
1309


1310
1311
1312
1313
1314
1315
1316
....
1498
1499
1500
1501
1502
1503
1504


1505
1506
1507
1508
1509
1510
1511
....
1554
1555
1556
1557
1558
1559
1560


1561
1562
1563
1564
1565
1566
1567
....
1755
1756
1757
1758
1759
1760
1761


1762
1763
1764
1765
1766
1767
1768
....
1851
1852
1853
1854
1855
1856
1857


1858
1859
1860
1861
1862
1863
1864
....
1999
2000
2001
2002
2003
2004
2005


2006
2007
2008
2009
2010
2011
2012
....
2041
2042
2043
2044
2045
2046
2047


2048
2049
2050
2051
2052
2053
2054
....
2055
2056
2057
2058
2059
2060
2061


2062
2063
2064
2065
2066
2067
2068
....
2127
2128
2129
2130
2131
2132
2133


2134
2135
2136
2137
2138
2139
2140
....
2150
2151
2152
2153
2154
2155
2156


2157
2158
2159
2160
2161
2162
2163
....
2194
2195
2196
2197
2198
2199
2200


2201
2202
2203
2204
2205
2206
2207
....
2208
2209
2210
2211
2212
2213
2214


2215
2216
2217
2218
2219
2220
2221
....
2302
2303
2304
2305
2306
2307
2308


2309
2310
2311
2312
2313
2314
2315
....
2318
2319
2320
2321
2322
2323
2324
2325


2326
2327
2328
2329
2330
2331
2332
    "Formati tabulari, separati da virgole o tabulazioni (o punti e virgola), uno dei formati più comuni per rappresentare le tabelle.\n",
    "\n",
    "    nome;età;abitazione\n",
    "    Antonio;32;Bologna\n",
    "    Maria;25;Torino\n",
    "    Francesco;47;Napoli\n",
    "    \n",
    "Permettono di inserire commenti (tipicamente con #) e possono essere aperti ed editati facilmente con programmi con Excel, ma possono contenere solo dati in formato tabella"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
................................................................................
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### JSON\n",
    "\n",
    "formato standard di condivisione dati su internet, è molto utile per rappresentare dati gerarchici. Corrisponde sostanzialmente ad una dizionario di dizionari in termini di python, ed ha praticamente la stessa sintassi.\n",
    "\n",
    "    {\"persone\":\n",
    "        {\"antonio\": {\"età\": \"32\", \"abitazione\": \"Bologna\"},\n",
    "         \"maria\": {\"età\": \"20\", \"abitazione\": \"Cesena\"},\n",
    "         }\n",
    "    }\n",
    "    \n"
................................................................................
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### immagini lossless: bmp, png, gif, tiff\n",
    "\n",
    "Questi formati contengono i valori di colore contenuti in un'immagine con diversi tipi di compressione, senza però perdere alcuna informazione, al contrario di formati come il jpeg, che andrebbe quindi evitato per lo storage di immagini"


   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
................................................................................
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### hashing dei file\n",
    "\n",
    "Una operazione molto comune nella data analisi è il cosiddetto hasing.\n",
    "\n",
    "Questo consiste nella generazione di una stringa alfanumerica (tipicamente di qualche centinaio di caratteri) a partire dal contenuto del file.\n",
    "\n",
    "Gli algoritmi di hash garantiscono che piccole modifiche del contenuto del file comporti grandi variazioni dell'hash, permettendo di usare queste stringhe per garantire l'integrità dei dati.\n",
    "\n",
    "Esistono diversi algoritmi per la generazione dell'hash (SHA1, md5, sha512, etc...) per cui l'algoritmo di calcolo dovrebbe essere riportato insieme all'hash\n",
    "\n",
    "I sistemi di controllo di versione usano internamente gli hash dei file per verificare se questi sono cambiati o meno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
................................................................................
    "print('md5: {}'.format(r))\n",
    "\n",
    "stringa1 = \"sono una stringa di testo completamente innocente\".encode('utf8')\n",
    "r = hashlib.md5(stringa1).hexdigest()\n",
    "print('md5: {}'.format(r))"
   ]
  },





















































  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
................................................................................
   "source": [
    "## Data Pipeline\n",
    "\n",
    "Ora che abbiamo un'idea di come siano fatti i dati, possiamo discutere di come questi dati possano venir messi insieme in una pipeline.\n",
    "\n",
    "Per semplicità, li possiamo inserire in una gerarchia di rilevanza:\n",
    "\n",
    "0. Metadati\n",
    "1. raw data\n",

    "2. source data\n",
    "3. usage data\n",
    "4. intermediate data\n",
    "5. temporary data\n",
    "\n",
    "Questi nomi non sono formali, solo un modo per discuterne fra di noi, ma rispecchiano molto bene la tipica procedura di analisi."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 0 - Metadati\n",
    "\n",
    "Dati a proposito dei dati.\n",
    "\n",
    "Tipicamente un file di testo semplice, che descrive il motivo per cui i dati sono stati presi, chi li ha raccolti, quando e con che metodi.\n",
    "\n",
    "Può sembrare banale, ma a distanza di qualche anno potreste trovarvi un disco pieno di dati di cui non capite la ragione d'essere.\n",
    "\n",
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 1 - Raw data\n",
    "\n",
    "Questi sono i dati originari dei vostri esperimenti. Non li userete direttamente nelle vostre analisi.\n",
    "Potrebbero essere nei formati più strampalati, a seconda dell'output dello strumento di misura.\n",
    "\n",
    "Questi dati sono **SACRI**.\n",
    "\n",
    "Vanno conservati scrupolosamente e non modificati.\n",
    "\n",
    "Se si dovessero avere nuove versioni (ad esempio una misura è stata ripetuta ed aggiornata) non sovrascriveteli, ma tenete le varie versioni."


   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {






















    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 2 - Source data\n",
    "\n",
    "Una volta ottenuti i raw data, processateli tramite uno script in un formato decente.\n",
    "Tramite questo script potrete unire eventuali file frammentati (ad esempio da un file per persona ad un dataset unico), correggere errori nei raw data (non dovete andare a modificarli alla fonte!) e mettere il tutto in una struttura che possa essere mantenuta a lungo. La mia preferenza è per formati di testo come il csv.\n",
    "\n",
    "Lo script di generazione è più importante dei dati risultanti!\n",
    "\n",
    "In questa fase dovete mantenere i dati il più possibile aderenti alle informazioni dei file RAW.\n",
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 3 - Usage data\n",
    "\n",
    "Qui iniziamo effettivamente la nostra analisi.\n",
    "\n",
    "A partire dai dati source, possiamo comporre i dati nel formato più comodo per le analisi che abbiamo in mente, senza doverci preoccupare di cose come la normalizzazione delle tabelle del database e simili.\n",
    "\n",
    "Tipicamente questi dati saranno generati solo una volta, a meno che non si riscontrino dei problemi nell'analisi (nel qual caso sarà necessario tornare indietro ai source data e capire cosa sia andato storto).\n",
    "\n",
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 4 - Intermediate Data\n",
    "\n",
    "La vostra analisi sarà tipicamente composta da diverse fasi, quali la normalizzazione dei dati, il detrending, e così via.\n",
    "\n",
    "Dopo ciascuno di questi step è solitamente buona pratica tener traccia dei risultati in dei file intermedi, in modo da poter riprendere l'analisi da qualsiasi step intermedio senza dover ripartire da capo.\n",
    "\n",
    "Di solito l'unico inconveniente della perdita di questi dati è il tempo necessario per ripetere l'analisi."
   ]
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 5 - Temporary data\n",
    "\n",
    "Questi dati sono il risultato intermedio delle analisi, ma con il preciso obiettivo di essere rimossi alla fine di ogni step.\n",
    "\n",
    "Ad esempio potrebbero essere generati da un algoritmo parallelo distribuito che analizza un paziente alla volta, per poi ricomporre i risultati in un'unica tabella che li contiene tutti. Una volta generata la tabella complessiva, non c'è ragione di tenere le tabelle dei singoli pazienti in giro a consumare spazio, e vanno quindi eliminate."
   ]
  },
  {
................................................................................
    "\n",
    "Vi permette di collegare in modo molto semplice comandi di bash (e quindi programmi generici), script in python ed R (a cui può passare variabili direttamente in memoria) o di mescolare del codice python direttamente nello script."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {























    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "La struttura fondamentale di Snakemake è una **regola**, che rappresenta un programma (tipicamente uno script), i file che ha bisogno di avere in input e quelli che restituirà in output.\n",
    "\n",





















    "Se il file di output della regola esiste già, la regola non viene eseguita (a meno di non constringerlo).\n",
    "\n",
    "Se il file di input della regola non esiste, snakemake cerca un'altra regola che abbia quel file come output e la esegue prima.\n",
    "\n",
    "Questa è una struttura chiamata **pull** (in cui specifico il punto di arrivo), e richiede un po' di tempo per prenderci confidenza (lo standard della programmazione è di tipo **push**, in cui specifico il punto di partenza)."
   ]
  },
................................................................................
   ],
   "source": [
    "%cd /home/enrico/lavoro/DataProgrammingCourse/\n",
    "%mkdir ../snakemake_lesson/\n",
    "%cd ../snakemake_lesson/\n",
    "%pwd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Uno snakefile è diviso in regole.\n",
    "\n",
    "Ciascuna regola viene eseguita come un nuovo processo python a se stante.\n",
    "\n",
    "Una regola ha delle sotto sezioni, di cui le più importanti sono:\n",
    "\n",
    "* output: la lista dei file che la regola genererà in output (è una promessa, vanno poi effettivamente creati)\n",
    "* input: la lista dei file che la regola richiede\n",
    "* shell/run: esegue uno o più comandi di shell oppure esegue del codice python arbitrario\n",
    "\n",
    "Di default, se non si specifica altro, snakemake cerca di eseguire la regola **all**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false,
    "deletable": true,
................................................................................
   "source": [
    "%ls"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Se il file di output di una regola esiste già, ed è più recente dei file di input, la regola non viene eseguita.\n",
    "\n",
................................................................................
   ],
   "source": [
    "!snakemake"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},



   "source": [
    "Se i fil di input sono specificati e:\n",
    "\n",
    "1. non esistono\n",
    "2. non esiste una regola che li produca in output\n",
    "\n",
    "Allora snakemake ritornerà un errore"
................................................................................
   "source": [
    "!snakemake"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Vediamo come appare uno script con due regole distinte, una per creare i due parziali ed una per processarli."
   ]
................................................................................
   "source": [
    "!snakemake"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Per usare le wildcard devo dare da qualche parte il comando expand, che assegna di vari possibili valori alle wildcards.\n",
    "\n",
................................................................................
    "%rm parziali1.txt\n",
    "%rm result.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Snakamake mi permette anche di creare un grafico di flusso che visualizza tutto ciò che deve essere fatto, e ciò che invece è stato già fatto e non ha bisogno di una nuova esecuzione."
   ]
................................................................................
   "source": [
    "![visualizzazione pipeline](./immagini/snakemake_dag.svg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Un'altra funzione estramamente utile è la creazione di un registro di provenance, che mi indica quali file sono stati creati da quale regola e con che parametri.\n",
    "\n",
................................................................................
   "source": [
    "%rm *.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Se voglio eseguire più regole in parallelo (ovviamente rispettando l'ordine necessario di esecuzione di ciascun ramo), mi basta dare il comando `--cores <N>` e snakemake eseguirà in automatico tutto quello che riesce in parallelo.\n",
    "\n",
................................................................................
   "source": [
    "%rm *.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Posso anche specificare delle risorse limitate (oltre i processori) in modo che la pipeline non ecceda nell'uso.\n",
    "\n",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "%rm *.txt"
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "%rm *.txt"
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false,


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
    "* ci sono 50 file chiamati transazioni_{}.tsv con l'indice da 00 a 49\n",
    "* il file di controllo degli hash è `md5sums.tsv`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {


    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### suggerimenti\n",
    "\n",
................................................................................
    "* usate le wildcard per ottenere i file, o non finite più!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true


   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",







|







 







|







 







|
>
>







 







|












|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
>
|
|
|
|







 







|







 







|








|
>
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|







 







|







 







|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>







 







|
>
>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







>
>







 







|
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
...
779
780
781
782
783
784
785





















786
787
788
789
790
791
792
...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
...
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
....
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
....
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
....
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
....
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
....
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
....
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
....
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
....
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
....
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
....
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
....
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
....
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
....
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
....
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
....
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
    "Formati tabulari, separati da virgole o tabulazioni (o punti e virgola), uno dei formati più comuni per rappresentare le tabelle.\n",
    "\n",
    "    nome;età;abitazione\n",
    "    Antonio;32;Bologna\n",
    "    Maria;25;Torino\n",
    "    Francesco;47;Napoli\n",
    "    \n",
    "Permettono di inserire commenti (tipicamente con #) e possono essere aperti ed editati facilmente con programmi come Excel, ma possono contenere solo dati in formato tabella"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
................................................................................
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### JSON\n",
    "\n",
    "formato standard di condivisione dati su internet, è molto utile per rappresentare dati gerarchici. Corrisponde sostanzialmente ad una dizionario di dizionari (in termini di python), ed ha praticamente la stessa sintassi.\n",
    "\n",
    "    {\"persone\":\n",
    "        {\"antonio\": {\"età\": \"32\", \"abitazione\": \"Bologna\"},\n",
    "         \"maria\": {\"età\": \"20\", \"abitazione\": \"Cesena\"},\n",
    "         }\n",
    "    }\n",
    "    \n"
................................................................................
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### immagini lossless: bmp, png, gif, tiff\n",
    "\n",
    "Questi formati contengono i valori di colore contenuti in un'immagine con diversi tipi di compressione, senza però perdere alcuna informazione, al contrario di formati come il jpeg, che andrebbe quindi evitato per lo storage di immagini.\n",
    "\n",
    "Se il vostro dato è un plot e non un'immagine generica, considerate l'uso del formato SVG, che permette modificazioni successive con più facilità."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
................................................................................
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "#### hashing dei file\n",
    "\n",
    "Una operazione molto comune nella data analisi è il cosiddetto hashing.\n",
    "\n",
    "Questo consiste nella generazione di una stringa alfanumerica (tipicamente di qualche centinaio di caratteri) a partire dal contenuto del file.\n",
    "\n",
    "Gli algoritmi di hash garantiscono che piccole modifiche del contenuto del file comporti grandi variazioni dell'hash, permettendo di usare queste stringhe per garantire l'integrità dei dati.\n",
    "\n",
    "Esistono diversi algoritmi per la generazione dell'hash (SHA1, md5, sha512, etc...) per cui l'algoritmo di calcolo dovrebbe essere riportato insieme all'hash\n",
    "\n",
    "I sistemi di controllo di versione usano internamente gli hash dei file per verificare se questi sono cambiati o meno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
................................................................................
    "print('md5: {}'.format(r))\n",
    "\n",
    "stringa1 = \"sono una stringa di testo completamente innocente\".encode('utf8')\n",
    "r = hashlib.md5(stringa1).hexdigest()\n",
    "print('md5: {}'.format(r))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fcdcdbda6cc42ee8fac608ed9e2d4391  ./Snakefile\r\n"
     ]
    }
   ],
   "source": [
    "!md5sum ./Snakefile"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fcdcdbda6cc42ee8fac608ed9e2d4391\n"
     ]
    }
   ],
   "source": [
    "def md5(fname):\n",
    "    \"\"\"funzione di hash dei file appropriata anche per i big data\"\"\"\n",
    "    hash_md5 = hashlib.md5()\n",
    "    with open(fname, \"rb\") as f:\n",
    "        for chunk in iter(lambda: f.read(4096), b\"\"):\n",
    "            hash_md5.update(chunk)\n",
    "    return hash_md5.hexdigest()\n",
    "\n",
    "hash_result = md5(\"Snakefile\")\n",
    "print(hash_result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
................................................................................
   "source": [
    "## Data Pipeline\n",
    "\n",
    "Ora che abbiamo un'idea di come siano fatti i dati, possiamo discutere di come questi dati possano venir messi insieme in una pipeline.\n",
    "\n",
    "Per semplicità, li possiamo inserire in una gerarchia di rilevanza:\n",
    "\n",
    "1. metadati\n",
    "2. raw data\n",
    "3. codice sorgente\n",
    "4. source data\n",
    "5. usage data\n",
    "6. intermediate data\n",
    "7. temporary data\n",
    "\n",
    "Questi nomi non sono formali, solo un modo per discuterne fra di noi, ma rispecchiano molto bene la tipica procedura di analisi."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 1 - metadati\n",
    "\n",
    "Dati a proposito dei dati.\n",
    "\n",
    "Tipicamente un file di testo semplice, che descrive il motivo per cui i dati sono stati presi, chi li ha raccolti, quando e con che metodi.\n",
    "\n",
    "Può sembrare banale, ma a distanza di qualche anno potreste trovarvi un disco pieno di dati di cui non capite la ragione d'essere.\n",
    "\n",
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 2 - Raw data\n",
    "\n",
    "Questi sono i dati originari dei vostri esperimenti. Non li userete direttamente nelle vostre analisi.\n",
    "Potrebbero essere nei formati più strampalati, a seconda dell'output dello strumento di misura.\n",
    "\n",
    "Questi dati sono **SACRI**.\n",
    "\n",
    "Vanno conservati scrupolosamente e non modificati.\n",
    "\n",
    "Se si dovessero avere nuove versioni (ad esempio una misura è stata ripetuta ed aggiornata) non sovrascriveteli, ma tenete le varie versioni.\n",
    "\n",
    "Dal punto di vista di FOSSIL per il controllo di versione, questo tipo di dati può essere tenuto nel repository come **unversioned**, visto che non dovrebbe essere modificato."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 3 - Codice sorgente\n",
    "\n",
    "Può sembrare banale, ma il vostro codice rappresenta comunque informazione a proposito del problema: \n",
    "\n",
    "* come vanno letti e manipolati i dati?\n",
    "* come correggere gli errori? \n",
    "* a cosa bisogna stare attenti?\n",
    "* quali sono le analisi già fatte?\n",
    "\n",
    "Queste informazioni meritano di essere trattate come dati a tutti gli effetti, e sono quasi altrettanto importanti dei raw data.\n",
    "\n",
    "È per questo che esiste il controllo di versione, usatelo!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 4 - Source data\n",
    "\n",
    "Una volta ottenuti i raw data, processateli tramite uno script in un formato decente.\n",
    "Tramite questo script potrete unire eventuali file frammentati (ad esempio da un file per persona ad un dataset unico), correggere errori nei raw data (non dovete andare a modificarli alla fonte!) e mettere il tutto in una struttura che possa essere mantenuta a lungo. La mia preferenza è per formati di testo come il csv.\n",
    "\n",
    "Lo script di generazione è più importante dei dati risultanti!\n",
    "\n",
    "In questa fase dovete mantenere i dati il più possibile aderenti alle informazioni dei file RAW.\n",
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 5 - Usage data\n",
    "\n",
    "Qui iniziamo effettivamente la nostra analisi.\n",
    "\n",
    "A partire dai dati source, possiamo comporre i dati nel formato più comodo per le analisi che abbiamo in mente, senza doverci preoccupare di cose come la normalizzazione delle tabelle del database e simili.\n",
    "\n",
    "Tipicamente questi dati saranno generati solo una volta, a meno che non si riscontrino dei problemi nell'analisi (nel qual caso sarà necessario tornare indietro ai source data e capire cosa sia andato storto).\n",
    "\n",
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 6 - Intermediate Data\n",
    "\n",
    "La vostra analisi sarà tipicamente composta da diverse fasi, quali la normalizzazione dei dati, il detrending, e così via.\n",
    "\n",
    "Dopo ciascuno di questi step è solitamente buona pratica tener traccia dei risultati in dei file intermedi, in modo da poter riprendere l'analisi da qualsiasi step intermedio senza dover ripartire da capo.\n",
    "\n",
    "Di solito l'unico inconveniente della perdita di questi dati è il tempo necessario per ripetere l'analisi."
   ]
................................................................................
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### 7 - Temporary data\n",
    "\n",
    "Questi dati sono il risultato intermedio delle analisi, ma con il preciso obiettivo di essere rimossi alla fine di ogni step.\n",
    "\n",
    "Ad esempio potrebbero essere generati da un algoritmo parallelo distribuito che analizza un paziente alla volta, per poi ricomporre i risultati in un'unica tabella che li contiene tutti. Una volta generata la tabella complessiva, non c'è ragione di tenere le tabelle dei singoli pazienti in giro a consumare spazio, e vanno quindi eliminate."
   ]
  },
  {
................................................................................
    "\n",
    "Vi permette di collegare in modo molto semplice comandi di bash (e quindi programmi generici), script in python ed R (a cui può passare variabili direttamente in memoria) o di mescolare del codice python direttamente nello script."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Snakamake è solo uno dei tanti sistemi di gestione delle pipeline di dati.\n",
    "\n",
    "È quello che reputo più vicino ai nostri bisogni, ma vi invito a guardare anche gli altri.\n",
    "\n",
    "Alcuni esempi famosi sono:\n",
    "\n",
    "* Luigi\n",
    "* Apache Airflow\n",
    "* BigDataScript\n",
    "* Dask\n",
    "* Nextflow\n",
    "\n",
    "una lista molto comprensiva la trovate alla pagina [awesome-pipeline](https://github.com/pditommaso/awesome-pipeline)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "La struttura fondamentale di Snakemake è una **regola**, che rappresenta un programma (tipicamente uno script), i file che ha bisogno di avere in input e quelli che restituirà in output.\n",
    "\n",
    "Ciascuna regola viene eseguita come un nuovo processo python a se stante.\n",
    "\n",
    "Una regola ha delle sotto sezioni, di cui le più importanti sono:\n",
    "\n",
    "* output: la lista dei file che la regola genererà in output (è una promessa, vanno poi effettivamente creati)\n",
    "* input: la lista dei file che la regola richiede\n",
    "* shell/run: esegue uno o più comandi di shell oppure esegue del codice python arbitrario\n",
    "\n",
    "Di default, se non si specifica altro, snakemake cerca di eseguire la regola **all**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Se il file di output della regola esiste già, la regola non viene eseguita (a meno di non constringerlo).\n",
    "\n",
    "Se il file di input della regola non esiste, snakemake cerca un'altra regola che abbia quel file come output e la esegue prima.\n",
    "\n",
    "Questa è una struttura chiamata **pull** (in cui specifico il punto di arrivo), e richiede un po' di tempo per prenderci confidenza (lo standard della programmazione è di tipo **push**, in cui specifico il punto di partenza)."
   ]
  },
................................................................................
   ],
   "source": [
    "%cd /home/enrico/lavoro/DataProgrammingCourse/\n",
    "%mkdir ../snakemake_lesson/\n",
    "%cd ../snakemake_lesson/\n",
    "%pwd"
   ]





















  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false,
    "deletable": true,
................................................................................
   "source": [
    "%ls"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Se il file di output di una regola esiste già, ed è più recente dei file di input, la regola non viene eseguita.\n",
    "\n",
................................................................................
   ],
   "source": [
    "!snakemake"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Se i fil di input sono specificati e:\n",
    "\n",
    "1. non esistono\n",
    "2. non esiste una regola che li produca in output\n",
    "\n",
    "Allora snakemake ritornerà un errore"
................................................................................
   "source": [
    "!snakemake"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Vediamo come appare uno script con due regole distinte, una per creare i due parziali ed una per processarli."
   ]
................................................................................
   "source": [
    "!snakemake"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Per usare le wildcard devo dare da qualche parte il comando expand, che assegna di vari possibili valori alle wildcards.\n",
    "\n",
................................................................................
    "%rm parziali1.txt\n",
    "%rm result.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Snakamake mi permette anche di creare un grafico di flusso che visualizza tutto ciò che deve essere fatto, e ciò che invece è stato già fatto e non ha bisogno di una nuova esecuzione."
   ]
................................................................................
   "source": [
    "![visualizzazione pipeline](./immagini/snakemake_dag.svg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Un'altra funzione estramamente utile è la creazione di un registro di provenance, che mi indica quali file sono stati creati da quale regola e con che parametri.\n",
    "\n",
................................................................................
   "source": [
    "%rm *.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Se voglio eseguire più regole in parallelo (ovviamente rispettando l'ordine necessario di esecuzione di ciascun ramo), mi basta dare il comando `--cores <N>` e snakemake eseguirà in automatico tutto quello che riesce in parallelo.\n",
    "\n",
................................................................................
   "source": [
    "%rm *.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Posso anche specificare delle risorse limitate (oltre i processori) in modo che la pipeline non ecceda nell'uso.\n",
    "\n",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "%rm *.txt"
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "%rm *.txt"
................................................................................
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
................................................................................
    "* ci sono 50 file chiamati transazioni_{}.tsv con l'indice da 00 a 49\n",
    "* il file di controllo degli hash è `md5sums.tsv`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### suggerimenti\n",
    "\n",
................................................................................
    "* usate le wildcard per ottenere i file, o non finite più!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",

Changes to Lezione 7 - Data pipeline e Snakemake.slides.html.

11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
.....
12065
12066
12067
12068
12069
12070
12071
12072

12073
12074
12075
12076
12077
12078
12079
.....
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
.....
12212
12213
12214
12215
12216
12217
12218



































































12219
12220
12221
12222
12223
12224
12225
12226
12227
12228

12229
12230
12231
12232
12233
12234
12235
.....
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262

12263
12264
12265
12266
12267
12268
12269
12270
12271


















12272
12273
12274
12275
12276
12277
12278
12279
.....
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
.....
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340







12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359












12360
12361
12362
12363
12364
12365
12366

<pre><code>nome;età;abitazione
Antonio;32;Bologna
Maria;25;Torino
Francesco;47;Napoli

</code></pre>
<p>Permettono di inserire commenti (tipicamente con #) e possono essere aperti ed editati facilmente con programmi con Excel, ma possono contenere solo dati in formato tabella</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="JSON">JSON<a class="anchor-link" href="#JSON">&#182;</a></h4><p>formato standard di condivisione dati su internet, è molto utile per rappresentare dati gerarchici. Corrisponde sostanzialmente ad una dizionario di dizionari in termini di python, ed ha praticamente la stessa sintassi.</p>

<pre><code>{"persone":
    {"antonio": {"età": "32", "abitazione": "Bologna"},
     "maria": {"età": "20", "abitazione": "Cesena"},
     }
}</code></pre>

................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="immagini-lossless:-bmp,-png,-gif,-tiff">immagini lossless: bmp, png, gif, tiff<a class="anchor-link" href="#immagini-lossless:-bmp,-png,-gif,-tiff">&#182;</a></h4><p>Questi formati contengono i valori di colore contenuti in un'immagine con diversi tipi di compressione, senza però perdere alcuna informazione, al contrario di formati come il jpeg, che andrebbe quindi evitato per lo storage di immagini</p>


</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="hashing-dei-file">hashing dei file<a class="anchor-link" href="#hashing-dei-file">&#182;</a></h4><p>Una operazione molto comune nella data analisi è il cosiddetto hasing.</p>
<p>Questo consiste nella generazione di una stringa alfanumerica (tipicamente di qualche centinaio di caratteri) a partire dal contenuto del file.</p>
<p>Gli algoritmi di hash garantiscono che piccole modifiche del contenuto del file comporti grandi variazioni dell'hash, permettendo di usare queste stringhe per garantire l'integrità dei dati.</p>
<p>Esistono diversi algoritmi per la generazione dell'hash (SHA1, md5, sha512, etc...) per cui l'algoritmo di calcolo dovrebbe essere riportato insieme all'hash</p>
<p>I sistemi di controllo di versione usano internamente gli hash dei file per verificare se questi sono cambiati o meno.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[23]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">hashlib</span>

<span class="n">stringa1</span> <span class="o">=</span> <span class="s2">&quot;sono una stringa di testo completamente 1nnocente&quot;</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf8&#39;</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">stringa1</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;md5: </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
................................................................................
</div>
</div>

</div>
</div>

</div></section></section><section><section>



































































<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Data-Pipeline">Data Pipeline<a class="anchor-link" href="#Data-Pipeline">&#182;</a></h2><p>Ora che abbiamo un'idea di come siano fatti i dati, possiamo discutere di come questi dati possano venir messi insieme in una pipeline.</p>
<p>Per semplicità, li possiamo inserire in una gerarchia di rilevanza:</p>
<ol>
<li>Metadati</li>
<li>raw data</li>

<li>source data</li>
<li>usage data</li>
<li>intermediate data</li>
<li>temporary data</li>
</ol>
<p>Questi nomi non sono formali, solo un modo per discuterne fra di noi, ma rispecchiano molto bene la tipica procedura di analisi.</p>

................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="0---Metadati">0 - Metadati<a class="anchor-link" href="#0---Metadati">&#182;</a></h3><p>Dati a proposito dei dati.</p>
<p>Tipicamente un file di testo semplice, che descrive il motivo per cui i dati sono stati presi, chi li ha raccolti, quando e con che metodi.</p>
<p>Può sembrare banale, ma a distanza di qualche anno potreste trovarvi un disco pieno di dati di cui non capite la ragione d'essere.</p>
<p>Un dato di cui non si conosce il motivo di esistere ha lo stesso valore di un dato cancellato.</p>
<p>Spesso riporta anche l'hashing dei dati RAW per garantire di poterne verificare l'integrità.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="1---Raw-data">1 - Raw data<a class="anchor-link" href="#1---Raw-data">&#182;</a></h3><p>Questi sono i dati originari dei vostri esperimenti. Non li userete direttamente nelle vostre analisi.
Potrebbero essere nei formati più strampalati, a seconda dell'output dello strumento di misura.</p>
<p>Questi dati sono <strong>SACRI</strong>.</p>
<p>Vanno conservati scrupolosamente e non modificati.</p>
<p>Se si dovessero avere nuove versioni (ad esempio una misura è stata ripetuta ed aggiornata) non sovrascriveteli, ma tenete le varie versioni.</p>


</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">


















<h3 id="2---Source-data">2 - Source data<a class="anchor-link" href="#2---Source-data">&#182;</a></h3><p>Una volta ottenuti i raw data, processateli tramite uno script in un formato decente.
Tramite questo script potrete unire eventuali file frammentati (ad esempio da un file per persona ad un dataset unico), correggere errori nei raw data (non dovete andare a modificarli alla fonte!) e mettere il tutto in una struttura che possa essere mantenuta a lungo. La mia preferenza è per formati di testo come il csv.</p>
<p>Lo script di generazione è più importante dei dati risultanti!</p>
<p>In questa fase dovete mantenere i dati il più possibile aderenti alle informazioni dei file RAW.
Non fate detrending, normalizzazioni o altre modifiche, solo trasportarli in un formato ragionevole.</p>
<p>Se i RAW fossero già ben formattati e strutturati e corretti, potete considerarli direttamente dei source.
Non capita mai, non sperateci.
Quando capita di solito vi stanno mentendo e non sono davvero i RAW ma dei dati già processati.</p>
................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="3---Usage-data">3 - Usage data<a class="anchor-link" href="#3---Usage-data">&#182;</a></h3><p>Qui iniziamo effettivamente la nostra analisi.</p>
<p>A partire dai dati source, possiamo comporre i dati nel formato più comodo per le analisi che abbiamo in mente, senza doverci preoccupare di cose come la normalizzazione delle tabelle del database e simili.</p>
<p>Tipicamente questi dati saranno generati solo una volta, a meno che non si riscontrino dei problemi nell'analisi (nel qual caso sarà necessario tornare indietro ai source data e capire cosa sia andato storto).</p>
<p>Diverse analisi potrebbero aver bisogno di diversi usage data.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="4---Intermediate-Data">4 - Intermediate Data<a class="anchor-link" href="#4---Intermediate-Data">&#182;</a></h3><p>La vostra analisi sarà tipicamente composta da diverse fasi, quali la normalizzazione dei dati, il detrending, e così via.</p>
<p>Dopo ciascuno di questi step è solitamente buona pratica tener traccia dei risultati in dei file intermedi, in modo da poter riprendere l'analisi da qualsiasi step intermedio senza dover ripartire da capo.</p>
<p>Di solito l'unico inconveniente della perdita di questi dati è il tempo necessario per ripetere l'analisi.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="5---Temporary-data">5 - Temporary data<a class="anchor-link" href="#5---Temporary-data">&#182;</a></h3><p>Questi dati sono il risultato intermedio delle analisi, ma con il preciso obiettivo di essere rimossi alla fine di ogni step.</p>
<p>Ad esempio potrebbero essere generati da un algoritmo parallelo distribuito che analizza un paziente alla volta, per poi ricomporre i risultati in un'unica tabella che li contiene tutti. Una volta generata la tabella complessiva, non c'è ragione di tenere le tabelle dei singoli pazienti in giro a consumare spazio, e vanno quindi eliminate.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>La struttura fondamentale di Snakemake è una <strong>regola</strong>, che rappresenta un programma (tipicamente uno script), i file che ha bisogno di avere in input e quelli che restituirà in output.</p>
<p>Se il file di output della regola esiste già, la regola non viene eseguita (a meno di non constringerlo).</p>
<p>Se il file di input della regola non esiste, snakemake cerca un'altra regola che abbia quel file come output e la esegue prima.</p>
<p>Questa è una struttura chiamata <strong>pull</strong> (in cui specifico il punto di arrivo), e richiede un po' di tempo per prenderci confidenza (lo standard della programmazione è di tipo <strong>push</strong>, in cui specifico il punto di partenza).</p>








</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Uno snakefile è diviso in regole.</p>
<p>Ciascuna regola viene eseguita come un nuovo processo python a se stante.</p>
<p>Una regola ha delle sotto sezioni, di cui le più importanti sono:</p>
<ul>
<li>output: la lista dei file che la regola genererà in output (è una promessa, vanno poi effettivamente creati)</li>
<li>input: la lista dei file che la regola richiede</li>
<li>shell/run: esegue uno o più comandi di shell oppure esegue del codice python arbitrario</li>
</ul>
<p>Di default, se non si specifica altro, snakemake cerca di eseguire la regola <strong>all</strong></p>













</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[41]:</div>
<div class="inner_cell">







|









|







 







|
>







 







|










|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|

>







 







|













|




>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







 







|












|











|







 







|
|
|
|
>
>
>
>
>
>
>









|









>
>
>
>
>
>
>
>
>
>
>
>







11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
.....
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
.....
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
.....
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
.....
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
.....
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409
.....
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473

<pre><code>nome;età;abitazione
Antonio;32;Bologna
Maria;25;Torino
Francesco;47;Napoli

</code></pre>
<p>Permettono di inserire commenti (tipicamente con #) e possono essere aperti ed editati facilmente con programmi come Excel, ma possono contenere solo dati in formato tabella</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="JSON">JSON<a class="anchor-link" href="#JSON">&#182;</a></h4><p>formato standard di condivisione dati su internet, è molto utile per rappresentare dati gerarchici. Corrisponde sostanzialmente ad una dizionario di dizionari (in termini di python), ed ha praticamente la stessa sintassi.</p>

<pre><code>{"persone":
    {"antonio": {"età": "32", "abitazione": "Bologna"},
     "maria": {"età": "20", "abitazione": "Cesena"},
     }
}</code></pre>

................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="immagini-lossless:-bmp,-png,-gif,-tiff">immagini lossless: bmp, png, gif, tiff<a class="anchor-link" href="#immagini-lossless:-bmp,-png,-gif,-tiff">&#182;</a></h4><p>Questi formati contengono i valori di colore contenuti in un'immagine con diversi tipi di compressione, senza però perdere alcuna informazione, al contrario di formati come il jpeg, che andrebbe quindi evitato per lo storage di immagini.</p>
<p>Se il vostro dato è un plot e non un'immagine generica, considerate l'uso del formato SVG, che permette modificazioni successive con più facilità.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="hashing-dei-file">hashing dei file<a class="anchor-link" href="#hashing-dei-file">&#182;</a></h4><p>Una operazione molto comune nella data analisi è il cosiddetto hashing.</p>
<p>Questo consiste nella generazione di una stringa alfanumerica (tipicamente di qualche centinaio di caratteri) a partire dal contenuto del file.</p>
<p>Gli algoritmi di hash garantiscono che piccole modifiche del contenuto del file comporti grandi variazioni dell'hash, permettendo di usare queste stringhe per garantire l'integrità dei dati.</p>
<p>Esistono diversi algoritmi per la generazione dell'hash (SHA1, md5, sha512, etc...) per cui l'algoritmo di calcolo dovrebbe essere riportato insieme all'hash</p>
<p>I sistemi di controllo di versione usano internamente gli hash dei file per verificare se questi sono cambiati o meno.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[2]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">hashlib</span>

<span class="n">stringa1</span> <span class="o">=</span> <span class="s2">&quot;sono una stringa di testo completamente 1nnocente&quot;</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf8&#39;</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">(</span><span class="n">stringa1</span><span class="p">)</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;md5: </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
................................................................................
</div>
</div>

</div>
</div>

</div></section></section><section><section>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[4]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="o">!</span>md5sum ./Snakefile
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>

<div class="output_subarea output_stream output_stdout output_text">
<pre>fcdcdbda6cc42ee8fac608ed9e2d4391  ./Snakefile
</pre>
</div>
</div>

</div>
</div>

</div><div class="fragment">
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[6]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">md5</span><span class="p">(</span><span class="n">fname</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;funzione di hash dei file appropriata anche per i big data&quot;&quot;&quot;</span>
    <span class="n">hash_md5</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">md5</span><span class="p">()</span>
    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">chunk</span> <span class="ow">in</span> <span class="nb">iter</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">4096</span><span class="p">),</span> <span class="sa">b</span><span class="s2">&quot;&quot;</span><span class="p">):</span>
            <span class="n">hash_md5</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">hash_md5</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>

<span class="n">hash_result</span> <span class="o">=</span> <span class="n">md5</span><span class="p">(</span><span class="s2">&quot;Snakefile&quot;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">hash_result</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>

<div class="output_subarea output_stream output_stdout output_text">
<pre>fcdcdbda6cc42ee8fac608ed9e2d4391
</pre>
</div>
</div>

</div>
</div>

</div></div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Data-Pipeline">Data Pipeline<a class="anchor-link" href="#Data-Pipeline">&#182;</a></h2><p>Ora che abbiamo un'idea di come siano fatti i dati, possiamo discutere di come questi dati possano venir messi insieme in una pipeline.</p>
<p>Per semplicità, li possiamo inserire in una gerarchia di rilevanza:</p>
<ol>
<li>metadati</li>
<li>raw data</li>
<li>codice sorgente</li>
<li>source data</li>
<li>usage data</li>
<li>intermediate data</li>
<li>temporary data</li>
</ol>
<p>Questi nomi non sono formali, solo un modo per discuterne fra di noi, ma rispecchiano molto bene la tipica procedura di analisi.</p>

................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="1---metadati">1 - metadati<a class="anchor-link" href="#1---metadati">&#182;</a></h3><p>Dati a proposito dei dati.</p>
<p>Tipicamente un file di testo semplice, che descrive il motivo per cui i dati sono stati presi, chi li ha raccolti, quando e con che metodi.</p>
<p>Può sembrare banale, ma a distanza di qualche anno potreste trovarvi un disco pieno di dati di cui non capite la ragione d'essere.</p>
<p>Un dato di cui non si conosce il motivo di esistere ha lo stesso valore di un dato cancellato.</p>
<p>Spesso riporta anche l'hashing dei dati RAW per garantire di poterne verificare l'integrità.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="2---Raw-data">2 - Raw data<a class="anchor-link" href="#2---Raw-data">&#182;</a></h3><p>Questi sono i dati originari dei vostri esperimenti. Non li userete direttamente nelle vostre analisi.
Potrebbero essere nei formati più strampalati, a seconda dell'output dello strumento di misura.</p>
<p>Questi dati sono <strong>SACRI</strong>.</p>
<p>Vanno conservati scrupolosamente e non modificati.</p>
<p>Se si dovessero avere nuove versioni (ad esempio una misura è stata ripetuta ed aggiornata) non sovrascriveteli, ma tenete le varie versioni.</p>
<p>Dal punto di vista di FOSSIL per il controllo di versione, questo tipo di dati può essere tenuto nel repository come <strong>unversioned</strong>, visto che non dovrebbe essere modificato.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="3---Codice-sorgente">3 - Codice sorgente<a class="anchor-link" href="#3---Codice-sorgente">&#182;</a></h3><p>Può sembrare banale, ma il vostro codice rappresenta comunque informazione a proposito del problema:</p>
<ul>
<li>come vanno letti e manipolati i dati?</li>
<li>come correggere gli errori? </li>
<li>a cosa bisogna stare attenti?</li>
<li>quali sono le analisi già fatte?</li>
</ul>
<p>Queste informazioni meritano di essere trattate come dati a tutti gli effetti, e sono quasi altrettanto importanti dei raw data.</p>
<p>È per questo che esiste il controllo di versione, usatelo!</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="4---Source-data">4 - Source data<a class="anchor-link" href="#4---Source-data">&#182;</a></h3><p>Una volta ottenuti i raw data, processateli tramite uno script in un formato decente.
Tramite questo script potrete unire eventuali file frammentati (ad esempio da un file per persona ad un dataset unico), correggere errori nei raw data (non dovete andare a modificarli alla fonte!) e mettere il tutto in una struttura che possa essere mantenuta a lungo. La mia preferenza è per formati di testo come il csv.</p>
<p>Lo script di generazione è più importante dei dati risultanti!</p>
<p>In questa fase dovete mantenere i dati il più possibile aderenti alle informazioni dei file RAW.
Non fate detrending, normalizzazioni o altre modifiche, solo trasportarli in un formato ragionevole.</p>
<p>Se i RAW fossero già ben formattati e strutturati e corretti, potete considerarli direttamente dei source.
Non capita mai, non sperateci.
Quando capita di solito vi stanno mentendo e non sono davvero i RAW ma dei dati già processati.</p>
................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="5---Usage-data">5 - Usage data<a class="anchor-link" href="#5---Usage-data">&#182;</a></h3><p>Qui iniziamo effettivamente la nostra analisi.</p>
<p>A partire dai dati source, possiamo comporre i dati nel formato più comodo per le analisi che abbiamo in mente, senza doverci preoccupare di cose come la normalizzazione delle tabelle del database e simili.</p>
<p>Tipicamente questi dati saranno generati solo una volta, a meno che non si riscontrino dei problemi nell'analisi (nel qual caso sarà necessario tornare indietro ai source data e capire cosa sia andato storto).</p>
<p>Diverse analisi potrebbero aver bisogno di diversi usage data.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="6---Intermediate-Data">6 - Intermediate Data<a class="anchor-link" href="#6---Intermediate-Data">&#182;</a></h3><p>La vostra analisi sarà tipicamente composta da diverse fasi, quali la normalizzazione dei dati, il detrending, e così via.</p>
<p>Dopo ciascuno di questi step è solitamente buona pratica tener traccia dei risultati in dei file intermedi, in modo da poter riprendere l'analisi da qualsiasi step intermedio senza dover ripartire da capo.</p>
<p>Di solito l'unico inconveniente della perdita di questi dati è il tempo necessario per ripetere l'analisi.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="7---Temporary-data">7 - Temporary data<a class="anchor-link" href="#7---Temporary-data">&#182;</a></h3><p>Questi dati sono il risultato intermedio delle analisi, ma con il preciso obiettivo di essere rimossi alla fine di ogni step.</p>
<p>Ad esempio potrebbero essere generati da un algoritmo parallelo distribuito che analizza un paziente alla volta, per poi ricomporre i risultati in un'unica tabella che li contiene tutti. Una volta generata la tabella complessiva, non c'è ragione di tenere le tabelle dei singoli pazienti in giro a consumare spazio, e vanno quindi eliminate.</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
................................................................................
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Snakamake è solo uno dei tanti sistemi di gestione delle pipeline di dati.</p>
<p>È quello che reputo più vicino ai nostri bisogni, ma vi invito a guardare anche gli altri.</p>
<p>Alcuni esempi famosi sono:</p>
<ul>
<li>Luigi</li>
<li>Apache Airflow</li>
<li>BigDataScript</li>
<li>Dask</li>
<li>Nextflow</li>
</ul>
<p>una lista molto comprensiva la trovate alla pagina <a href="https://github.com/pditommaso/awesome-pipeline">awesome-pipeline</a></p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>La struttura fondamentale di Snakemake è una <strong>regola</strong>, che rappresenta un programma (tipicamente uno script), i file che ha bisogno di avere in input e quelli che restituirà in output.</p>
<p>Ciascuna regola viene eseguita come un nuovo processo python a se stante.</p>
<p>Una regola ha delle sotto sezioni, di cui le più importanti sono:</p>
<ul>
<li>output: la lista dei file che la regola genererà in output (è una promessa, vanno poi effettivamente creati)</li>
<li>input: la lista dei file che la regola richiede</li>
<li>shell/run: esegue uno o più comandi di shell oppure esegue del codice python arbitrario</li>
</ul>
<p>Di default, se non si specifica altro, snakemake cerca di eseguire la regola <strong>all</strong></p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Se il file di output della regola esiste già, la regola non viene eseguita (a meno di non constringerlo).</p>
<p>Se il file di input della regola non esiste, snakemake cerca un'altra regola che abbia quel file come output e la esegue prima.</p>
<p>Questa è una struttura chiamata <strong>pull</strong> (in cui specifico il punto di arrivo), e richiede un po' di tempo per prenderci confidenza (lo standard della programmazione è di tipo <strong>push</strong>, in cui specifico il punto di partenza).</p>

</div>
</div>
</div></section></section><section><section>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In&nbsp;[41]:</div>
<div class="inner_cell">